diff --git a/libc/Makefile b/libc/Makefile index 53ce1d93..ff29daca 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -481,6 +481,8 @@ unistd/setpgid.o \ unistd/setuid.o \ unistd/sfork.o \ unistd/sleep.o \ +unistd/symlinkat.o \ +unistd/symlink.o \ unistd/sysconf.o \ unistd/tcgetpgrp.o \ unistd/tcsetpgrp.o \ diff --git a/libc/include/unistd.h b/libc/include/unistd.h index 7c56dae3..bf33a367 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -285,8 +285,6 @@ int setregid(gid_t, gid_t); int setreuid(uid_t, uid_t); pid_t setsid(void); void swab(const void* __restrict, void* __restrict, ssize_t); -int symlink(const char*, const char*); -int symlinkat(const char*, int, const char*); void sync(void); int ttyname_r(int, char*, size_t); #endif @@ -349,6 +347,8 @@ int setgid(gid_t); int setpgid(pid_t, pid_t); int setuid(uid_t); unsigned sleep(unsigned); +int symlink(const char*, const char*); +int symlinkat(const char*, int, const char*); long sysconf(int); pid_t tcgetpgrp(int); int tcsetpgrp(int, pid_t); diff --git a/libc/unistd/symlink.cpp b/libc/unistd/symlink.cpp new file mode 100644 index 00000000..e5becae6 --- /dev/null +++ b/libc/unistd/symlink.cpp @@ -0,0 +1,31 @@ +/******************************************************************************* + + 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 . + + unistd/symlink.cpp + Create a symbolic link. + +*******************************************************************************/ + +#include +#include + +extern "C" int symlink(const char* oldpath, const char* newpath) +{ + return symlinkat(oldpath, AT_FDCWD, newpath); +} diff --git a/libc/unistd/symlinkat.cpp b/libc/unistd/symlinkat.cpp new file mode 100644 index 00000000..dc4e698b --- /dev/null +++ b/libc/unistd/symlinkat.cpp @@ -0,0 +1,35 @@ +/******************************************************************************* + + 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 . + + unistd/symlinkat.cpp + Create a symbolic link. + +*******************************************************************************/ + +#include + +#include +#include + +DEFN_SYSCALL3(int, sys_symlinkat, SYSCALL_LINKAT, const char*, int, const char*); + +extern "C" int symlinkat(const char* oldpath, int newdirfd, const char* newpath) +{ + return sys_symlinkat(oldpath, newdirfd, newpath); +} diff --git a/sortix/include/sortix/syscallnum.h b/sortix/include/sortix/syscallnum.h index 6c8cc0cf..62968034 100644 --- a/sortix/include/sortix/syscallnum.h +++ b/sortix/include/sortix/syscallnum.h @@ -144,6 +144,7 @@ #define SYSCALL_SETPRIORITY 120 #define SYSCALL_PRLIMIT 121 #define SYSCALL_DUP3 122 -#define SYSCALL_MAX_NUM 123 /* index of highest constant + 1 */ +#define SYSCALL_SYMLINKAT 123 +#define SYSCALL_MAX_NUM 124 /* index of highest constant + 1 */ #endif diff --git a/sortix/io.cpp b/sortix/io.cpp index 5eb947f7..07e0e052 100644 --- a/sortix/io.cpp +++ b/sortix/io.cpp @@ -595,6 +595,36 @@ static int sys_link(const char* oldpath, const char* newpath) return sys_linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0); } +static int sys_symlinkat(const char* oldpath, int newdirfd, const char* newpath) +{ + ioctx_t ctx; SetupUserIOCtx(&ctx); + + char* newpathcopy = GetStringFromUser(newpath); + if ( !newpathcopy ) + return -1; + const char* newrelpath = newpathcopy; + Ref newfrom(PrepareLookup(&newrelpath, newdirfd)); + if ( !newfrom ) { delete[] newpathcopy; return -1; } + + char* final_elem; + Ref dir = OpenDirContainingPath(&ctx, newfrom, newpathcopy, + &final_elem); + delete[] newpathcopy; + if ( !dir ) + return -1; + + char* oldpathcopy = GetStringFromUser(oldpath); + if ( !oldpathcopy ) { delete[] final_elem; return -1; } + + int ret = (errno = EPERM, -1); + + delete[] oldpathcopy; + delete[] final_elem; + + return ret; +} + + static int sys_settermmode(int fd, unsigned mode) { Ref desc = CurrentProcess()->GetDescriptor(fd); @@ -1019,6 +1049,7 @@ void Init() Syscall::Register(SYSCALL_SEND, (void*) sys_send); Syscall::Register(SYSCALL_SETTERMMODE, (void*) sys_settermmode); Syscall::Register(SYSCALL_STAT, (void*) sys_stat); + Syscall::Register(SYSCALL_SYMLINKAT, (void*) sys_symlinkat); Syscall::Register(SYSCALL_TCGETPGRP, (void*) sys_tcgetpgrp); Syscall::Register(SYSCALL_TCGETWINSIZE, (void*) sys_tcgetwinsize); Syscall::Register(SYSCALL_TCSETPGRP, (void*) sys_tcsetpgrp);