diff --git a/libc/Makefile b/libc/Makefile index 684fc0f8..0f2dc966 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -212,6 +212,8 @@ putc.o \ raise.o \ rand.o \ readdirents.o \ +readlinkat.o \ +readlink.o \ read.o \ realpath.o \ removeat.o \ diff --git a/libc/include/unistd.h b/libc/include/unistd.h index fc789ae5..8a9d2715 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -111,8 +111,6 @@ int lockf(int, int, off_t); int nice(int); long pathconf(const char*, int); int pause(void); -ssize_t readlink(const char* restrict, char* restrict, size_t); -ssize_t readlinkat(int, const char* restrict, char* restrict, size_t); int setegid(gid_t); int seteuid(uid_t); int setgid(gid_t); @@ -170,6 +168,8 @@ off_t lseek(int, off_t, int); int pipe(int [2]); ssize_t pread(int, void*, size_t, off_t); ssize_t pwrite(int, const void*, size_t, off_t); +ssize_t readlink(const char* restrict, char* restrict, size_t); +ssize_t readlinkat(int, const char* restrict, char* restrict, size_t); ssize_t read(int, void*, size_t); int rmdir(const char*); unsigned sleep(unsigned); diff --git a/libc/readlink.cpp b/libc/readlink.cpp new file mode 100644 index 00000000..da193b25 --- /dev/null +++ b/libc/readlink.cpp @@ -0,0 +1,32 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + readlink.cpp + Read contents of symbolic link. + +*******************************************************************************/ + +#include +#include + +extern "C" ssize_t readlink(const char* restrict path, char* restrict buf, + size_t size) +{ + return readlinkat(AT_FDCWD, path, buf, size); +} diff --git a/libc/readlinkat.cpp b/libc/readlinkat.cpp new file mode 100644 index 00000000..b7ecdcab --- /dev/null +++ b/libc/readlinkat.cpp @@ -0,0 +1,37 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + readlinkat.cpp + Read contents of symbolic link. + +*******************************************************************************/ + +#include + +#include +#include + +DEFN_SYSCALL4(ssize_t, sys_readlinkat, SYSCALL_READLINKAT, int, + const char* restrict, char* restrict, size_t); + +extern "C" ssize_t readlinkat(int dirfd, const char* restrict path, + char* restrict buf, size_t size) +{ + return sys_readlinkat(dirfd, path, buf, size); +} diff --git a/sortix/descriptor.cpp b/sortix/descriptor.cpp index f83b5b6a..2c56c51d 100644 --- a/sortix/descriptor.cpp +++ b/sortix/descriptor.cpp @@ -420,6 +420,8 @@ int Descriptor::rename_here(ioctx_t* ctx, Ref from, ssize_t Descriptor::readlink(ioctx_t* ctx, char* buf, size_t bufsize) { + if ( (size_t) SSIZE_MAX < bufsize ) + bufsize = (size_t) SSIZE_MAX; return vnode->readlink(ctx, buf, bufsize); } diff --git a/sortix/include/sortix/syscallnum.h b/sortix/include/sortix/syscallnum.h index 67ceee96..3f18848c 100644 --- a/sortix/include/sortix/syscallnum.h +++ b/sortix/include/sortix/syscallnum.h @@ -95,6 +95,7 @@ #define SYSCALL_FSM_FSBIND 71 #define SYSCALL_PPOLL 72 #define SYSCALL_RENAMEAT 73 -#define SYSCALL_MAX_NUM 74 /* index of highest constant + 1 */ +#define SYSCALL_READLINKAT 74 +#define SYSCALL_MAX_NUM 75 /* index of highest constant + 1 */ #endif diff --git a/sortix/io.cpp b/sortix/io.cpp index b4460700..58f6270d 100644 --- a/sortix/io.cpp +++ b/sortix/io.cpp @@ -540,6 +540,25 @@ static int sys_renameat(int olddirfd, const char* oldpath, return ret; } +// TODO: This should probably be moved into user-space. It'd be nice if +// user-space could just open the symlink and read/write it like a regular file. +static ssize_t sys_readlinkat(int dirfd, const char* path, char* buf, size_t size) +{ + char* pathcopy = GetStringFromUser(path); + if ( !pathcopy ) + return -1; + ioctx_t ctx; SetupUserIOCtx(&ctx); + const char* relpath = pathcopy; + Ref from = PrepareLookup(&relpath, dirfd); + if ( !from ) { delete[] pathcopy; return -1; } + // TODO: Open the symbolic link, instead of what it points to! + Ref desc = from->open(&ctx, relpath, O_RDONLY); + delete[] pathcopy; + if ( !desc ) + return -1; + return (int) desc->readlink(&ctx, buf, size); +} + void Init() { Syscall::Register(SYSCALL_ACCESS, (void*) sys_access); @@ -570,6 +589,7 @@ void Init() Syscall::Register(SYSCALL_PREAD, (void*) sys_pread); Syscall::Register(SYSCALL_PWRITE, (void*) sys_pwrite); Syscall::Register(SYSCALL_READDIRENTS, (void*) sys_readdirents); + Syscall::Register(SYSCALL_READLINKAT, (void*) sys_readlinkat); Syscall::Register(SYSCALL_READ, (void*) sys_read); Syscall::Register(SYSCALL_RENAMEAT, (void*) sys_renameat); Syscall::Register(SYSCALL_RMDIR, (void*) sys_rmdir);