From c7238745be689761f482abf8114cdf2c17eedfe6 Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Sat, 31 Jul 2010 22:46:31 +0200 Subject: [PATCH] Add a renameat(2) system call. Based-on: FreeBSD --- bin/ln/symlink.7 | 4 +- include/stdio.h | 3 +- lib/libc/sys/Makefile.inc | 2 +- lib/libc/sys/rename.2 | 82 +++++++++++++++++++++++++++++++++++++-- sys/kern/init_sysent.c | 1 + sys/kern/syscalls.c | 1 + sys/kern/syscalls.master | 2 + sys/kern/vfs_syscalls.c | 32 ++++++++++++++- sys/sys/syscall-hide.h | 1 + sys/sys/syscall.h | 3 +- sys/sys/syscall.mk | 3 +- sys/sys/sysproto.h | 10 +++++ sys/sys/sysunion.h | 1 + 13 files changed, 134 insertions(+), 11 deletions(-) diff --git a/bin/ln/symlink.7 b/bin/ln/symlink.7 index e2c8aebd43..c4f345aa73 100644 --- a/bin/ln/symlink.7 +++ b/bin/ln/symlink.7 @@ -31,9 +31,8 @@ .\" .\" @(#)symlink.7 8.3 (Berkeley) 3/31/94 .\" $FreeBSD: src/bin/ln/symlink.7,v 1.13.2.7 2003/03/03 19:04:46 trhodes Exp $ -.\" $DragonFly: src/bin/ln/symlink.7,v 1.2 2003/06/17 04:22:50 dillon Exp $ .\" -.Dd March 31, 1994 +.Dd July 31, 2010 .Dt SYMLINK 7 .Os .Sh NAME @@ -446,6 +445,7 @@ whether specified on the command line or encountered in the tree walk. .Xr lstat 2 , .Xr readlink 2 , .Xr rename 2 , +.Xr renameat 2 , .Xr symlink 2 , .Xr unlink 2 , .Xr fts 3 , diff --git a/include/stdio.h b/include/stdio.h index 473e91a591..2f241adc94 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -35,7 +35,6 @@ * * @(#)stdio.h 8.5 (Berkeley) 4/29/95 * $FreeBSD: src/include/stdio.h,v 1.78 2009/03/25 08:07:52 das Exp $ - * $DragonFly: src/include/stdio.h,v 1.14 2008/06/05 17:53:10 swildner Exp $ */ #ifndef _STDIO_H_ @@ -298,7 +297,7 @@ char *tempnam(const char *, const char *); #if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 ssize_t getdelim(char ** __restrict, size_t * __restrict, int, FILE * __restrict); -/* int renameat(int, const char *, int, const char *); */ +int renameat(int, const char *, int, const char *); int vdprintf(int, const char * __restrict, __va_list); /* diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index b50849ff07..7bd1592af0 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -1,6 +1,5 @@ # @(#)Makefile.inc 8.3 (Berkeley) 10/24/94 # $FreeBSD: src/lib/libc/sys/Makefile.inc,v 1.75.2.7 2003/04/22 17:31:18 trhodes Exp $ -# $DragonFly: src/lib/libc/sys/Makefile.inc,v 1.39 2008/11/11 00:55:49 pavalos Exp $ # sys sources .PATH: ${.CURDIR}/../libc/${MACHINE_ARCH}/sys ${.CURDIR}/../libc/sys @@ -141,6 +140,7 @@ MLINKS+=open.2 openat.2 MLINKS+=pathconf.2 fpathconf.2 MLINKS+=read.2 pread.2 read.2 preadv.2 read.2 readv.2 MLINKS+=recv.2 recvfrom.2 recv.2 recvmsg.2 +MLINKS+=rename.2 renameat.2 MLINKS+=rtprio.2 lwp_rtprio.2 .if !defined(NO_P1003_1B) MLINKS+=sched_get_priority_max.2 sched_get_priority_min.2 \ diff --git a/lib/libc/sys/rename.2 b/lib/libc/sys/rename.2 index f06d3584b2..a133a62ecc 100644 --- a/lib/libc/sys/rename.2 +++ b/lib/libc/sys/rename.2 @@ -31,9 +31,8 @@ .\" .\" @(#)rename.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD: src/lib/libc/sys/rename.2,v 1.8.2.7 2001/12/14 18:34:01 ru Exp $ -.\" $DragonFly: src/lib/libc/sys/rename.2,v 1.2 2003/06/17 04:26:47 dillon Exp $ .\" -.Dd June 4, 1993 +.Dd July 31, 2010 .Dt RENAME 2 .Os .Sh NAME @@ -45,6 +44,8 @@ .In stdio.h .Ft int .Fn rename "const char *from" "const char *to" +.Ft int +.Fn renameat "int fromfd" "const char *from" "int tofd" "const char *to" .Sh DESCRIPTION .Fn Rename causes the link named @@ -74,6 +75,37 @@ If the final component of is a symbolic link, the symbolic link is renamed, not the file or directory to which it points. +.Pp +The +.Fn renameat +system call is equivalent to +.Fn rename +except in the case where either +.Fa from +or +.Fa to +specifies a relative path. +If +.Fa from +is a relative path, the file to be renamed is located +relative to the directory associated with the file descriptor +.Fa fromfd +instead of the current working directory. +If the +.Fa to +is a relative path, the same happens only relative to the directory associated +with +.Fa tofd . +If the +.Fn renameat +is passed the special value +.Dv AT_FDCWD +in the +.Fa fromfd +or +.Fa tofd +parameter, the current working directory is used in the determination +of the file for the respective path parameter. .\".Sh CAVEAT .\"The system can deadlock if a loop in the file system graph is present. .\"This loop takes the form of an entry in directory @@ -190,11 +222,55 @@ or .Fa To is a directory and is not empty. .El +.Pp +In addition to the errors returned by the +.Fn rename , +the +.Fn renameat +may fail if: +.Bl -tag -width Er +.It Bq Er EBADF +The +.Fa from +argument does not specify an absolute path and the +.Fa fromfd +argument is neither +.Dv AT_FDCWD +nor a valid file descriptor open for searching, or the +.Fa to +argument does not specify an absolute path and the +.Fa tofd +argument is neither +.Dv AT_FDCWD +nor a valid file descriptor open for searching. +.It Bq Er ENOTDIR +The +.Fa from +argument is not an absolute path and +.Fa fromfd +is neither +.Dv AT_FDCWD +nor a file descriptor associated with a directory, or the +.Fa to +argument is not an absolute path and +.Fa tofd +is neither +.Dv AT_FDCWD +nor a file descriptor associated with a directory. +.El .Sh SEE ALSO .Xr open 2 , .Xr symlink 7 .Sh STANDARDS The .Fn rename -function call is expected to conform to +system call is expected to conform to .St -p1003.1-96 . +The +.Fn renameat +system call follows The Open Group Extended API Set 2 specification. +.Sh HISTORY +The +.Fn renameat +system call appeared in +.Dx 2.7 . diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index f186de105b..71b3d7bcd6 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -556,4 +556,5 @@ struct sysent sysent[] = { { AS(ioprio_set_args), (sy_call_t *)sys_ioprio_set }, /* 520 = ioprio_set */ { AS(ioprio_get_args), (sy_call_t *)sys_ioprio_get }, /* 521 = ioprio_get */ { AS(chroot_kernel_args), (sy_call_t *)sys_chroot_kernel }, /* 522 = chroot_kernel */ + { AS(renameat_args), (sy_call_t *)sys_renameat }, /* 523 = renameat */ }; diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 42d6c83c36..22eddadd9a 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -530,4 +530,5 @@ const char *syscallnames[] = { "ioprio_set", /* 520 = ioprio_set */ "ioprio_get", /* 521 = ioprio_get */ "chroot_kernel", /* 522 = chroot_kernel */ + "renameat", /* 523 = renameat */ }; diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 591bcef77e..1c2fca57ce 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -732,3 +732,5 @@ 520 STD BSD { int ioprio_set(int which, int who, int prio); } 521 STD BSD { int ioprio_get(int which, int who); } 522 STD BSD { int chroot_kernel(char *path); } +523 STD POSIX { int renameat(int oldfd, char *old, int newfd, \ + char *new); } diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 3ab94e2112..eed35431a0 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -37,7 +37,6 @@ * * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 * $FreeBSD: src/sys/kern/vfs_syscalls.c,v 1.151.2.18 2003/04/04 20:35:58 tegge Exp $ - * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.135 2008/11/11 00:55:49 pavalos Exp $ */ #include @@ -3800,6 +3799,37 @@ sys_rename(struct rename_args *uap) return (error); } +/* + * renameat_args(int oldfd, char *old, int newfd, char *new) + * + * Rename files using paths relative to the directories associated with + * oldfd and newfd. Source and destination must either both be directories, + * or both not be directories. If target is a directory, it must be empty. + * + * MPALMOSTSAFE + */ +int +sys_renameat(struct renameat_args *uap) +{ + struct nlookupdata oldnd, newnd; + struct file *oldfp, *newfp; + int error; + + get_mplock(); + error = nlookup_init_at(&oldnd, &oldfp, uap->oldfd, uap->old, + UIO_USERSPACE, 0); + if (error == 0) { + error = nlookup_init_at(&newnd, &newfp, uap->newfd, uap->new, + UIO_USERSPACE, 0); + if (error == 0) + error = kern_rename(&oldnd, &newnd); + nlookup_done(&newnd); + } + nlookup_done(&oldnd); + rel_mplock(); + return (error); +} + int kern_mkdir(struct nlookupdata *nd, int mode) { diff --git a/sys/sys/syscall-hide.h b/sys/sys/syscall-hide.h index 06071954b6..0d7d32d468 100644 --- a/sys/sys/syscall-hide.h +++ b/sys/sys/syscall-hide.h @@ -353,3 +353,4 @@ HIDE_POSIX(mq_timedreceive) HIDE_BSD(ioprio_set) HIDE_BSD(ioprio_get) HIDE_BSD(chroot_kernel) +HIDE_POSIX(renameat) diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index b121f6e227..35531273d2 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -362,4 +362,5 @@ #define SYS_ioprio_set 520 #define SYS_ioprio_get 521 #define SYS_chroot_kernel 522 -#define SYS_MAXSYSCALL 523 +#define SYS_renameat 523 +#define SYS_MAXSYSCALL 524 diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk index 4103f665da..892e5e8045 100644 --- a/sys/sys/syscall.mk +++ b/sys/sys/syscall.mk @@ -301,4 +301,5 @@ MIASM = \ mq_timedreceive.o \ ioprio_set.o \ ioprio_get.o \ - chroot_kernel.o + chroot_kernel.o \ + renameat.o diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h index 6b365aff83..de8594e347 100644 --- a/sys/sys/sysproto.h +++ b/sys/sys/sysproto.h @@ -2301,6 +2301,15 @@ struct chroot_kernel_args { #endif char * path; char path_[PAD_(char *)]; }; +struct renameat_args { +#ifdef _KERNEL + struct sysmsg sysmsg; +#endif + int oldfd; char oldfd_[PAD_(int)]; + char * old; char old_[PAD_(char *)]; + int newfd; char newfd_[PAD_(int)]; + char * new; char new_[PAD_(char *)]; +}; #ifdef COMPAT_43 @@ -2910,6 +2919,7 @@ int sys_mq_timedreceive (struct mq_timedreceive_args *); int sys_ioprio_set (struct ioprio_set_args *); int sys_ioprio_get (struct ioprio_get_args *); int sys_chroot_kernel (struct chroot_kernel_args *); +int sys_renameat (struct renameat_args *); #endif /* !_SYS_SYSPROTO_H_ */ #undef PAD_ diff --git a/sys/sys/sysunion.h b/sys/sys/sysunion.h index 374ee3c482..62aef5d900 100644 --- a/sys/sys/sysunion.h +++ b/sys/sys/sysunion.h @@ -409,4 +409,5 @@ union sysunion { struct ioprio_set_args ioprio_set; struct ioprio_get_args ioprio_get; struct chroot_kernel_args chroot_kernel; + struct renameat_args renameat; }; -- 2.41.0