diff --git a/libc/Makefile b/libc/Makefile index fb1616a5..d48c6904 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -161,6 +161,7 @@ ioleast.o \ isatty.o \ kernelinfo.o \ kill.o \ +link.o \ localeconv.o \ lseek.o \ memstat.o \ diff --git a/libc/include/unistd.h b/libc/include/unistd.h index 3fdb5765..b1936082 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -115,7 +115,6 @@ pid_t getpgrp(void); pid_t getsid(pid_t); uid_t getuid(void); int lchown(const char*, uid_t, gid_t); -int link(const char*, const char*); int linkat(int, const char*, int, const char*, int); int lockf(int, int, off_t); int nice(int); @@ -169,6 +168,7 @@ char* get_current_dir_name(void); pid_t getpid(void); pid_t getppid(void); int isatty(int); +int link(const char*, const char*); off_t lseek(int, off_t, int); int pipe(int [2]); ssize_t pread(int, void*, size_t, off_t); diff --git a/libc/link.cpp b/libc/link.cpp new file mode 100644 index 00000000..b1826542 --- /dev/null +++ b/libc/link.cpp @@ -0,0 +1,33 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2012. + + 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 . + + link.cpp + Give a new name to a file. + +*******************************************************************************/ + +#include +#include + +DEFN_SYSCALL2(int, sys_link, SYSCALL_LINK, const char*, const char*); + +extern "C" int link(const char* oldpath, const char* newpath) +{ + return sys_link(oldpath, newpath); +} diff --git a/sortix/include/sortix/syscallnum.h b/sortix/include/sortix/syscallnum.h index c6310f05..6a19dd6a 100644 --- a/sortix/include/sortix/syscallnum.h +++ b/sortix/include/sortix/syscallnum.h @@ -80,6 +80,7 @@ #define SYSCALL_FSTATAT 56 #define SYSCALL_CHMOD 57 #define SYSCALL_CHOWN 58 -#define SYSCALL_MAX_NUM 59 /* index of highest constant + 1 */ +#define SYSCALL_LINK 59 +#define SYSCALL_MAX_NUM 60 /* index of highest constant + 1 */ #endif diff --git a/sortix/io.cpp b/sortix/io.cpp index 0fd4e277..081c2c7e 100644 --- a/sortix/io.cpp +++ b/sortix/io.cpp @@ -349,6 +349,37 @@ static int sys_chmod(const char* path, mode_t mode) return desc->chmod(&ctx, mode); } +static int sys_link(const char* oldpath, const char* newpath) +{ + ioctx_t ctx; SetupUserIOCtx(&ctx); + + char* newpathcopy = GetStringFromUser(newpath); + if ( !newpathcopy ) + return -1; + const char* newrelpath = newpathcopy; + Ref newfrom(PrepareLookup(&newrelpath)); + + 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; } + const char* oldrelpath = oldpathcopy; + Ref oldfrom(PrepareLookup(&oldrelpath)); + + Ref file = oldfrom->open(&ctx, oldrelpath, O_RDONLY); + delete[] oldpathcopy; + if ( !file ) { delete[] final_elem; return -1; } + + int ret = dir->link(&ctx, final_elem, file); + delete[] final_elem; + return ret; +} + static int sys_settermmode(int fd, unsigned mode) { Ref desc = CurrentProcess()->GetDescriptor(fd); @@ -399,6 +430,7 @@ void Init() Syscall::Register(SYSCALL_FTRUNCATE, (void*) sys_ftruncate); Syscall::Register(SYSCALL_GETTERMMODE, (void*) sys_gettermmode); Syscall::Register(SYSCALL_ISATTY, (void*) sys_isatty); + Syscall::Register(SYSCALL_LINK, (void*) sys_link); Syscall::Register(SYSCALL_MKDIR, (void*) sys_mkdir); Syscall::Register(SYSCALL_OPENAT, (void*) sys_openat); Syscall::Register(SYSCALL_OPEN, (void*) sys_open);