From 3a6d8629056d17a471930c8e729995714d62cf80 Mon Sep 17 00:00:00 2001 From: Nicolas Thery Date: Tue, 18 Aug 2009 21:27:32 +0200 Subject: [PATCH] add unlinkat(2) system call Also add libc_r wrapper and man page. --- include/unistd.h | 1 + lib/libc/sys/Makefile.inc | 3 +- lib/libc/sys/rmdir.2 | 5 +- lib/libc/sys/unlink.2 | 5 +- lib/libc/sys/unlinkat.2 | 113 ++++++++++++++++++++++++++ lib/libc_r/uthread/Makefile.inc | 1 + lib/libc_r/uthread/uthread_unlinkat.c | 51 ++++++++++++ sys/kern/init_sysent.c | 1 + sys/kern/syscalls.c | 1 + sys/kern/syscalls.master | 1 + sys/kern/vfs_syscalls.c | 27 ++++++ sys/sys/fcntl.h | 1 + sys/sys/syscall-hide.h | 1 + sys/sys/syscall.h | 3 +- sys/sys/syscall.mk | 3 +- sys/sys/sysproto.h | 9 ++ sys/sys/sysunion.h | 1 + 17 files changed, 220 insertions(+), 7 deletions(-) create mode 100644 lib/libc/sys/unlinkat.2 create mode 100644 lib/libc_r/uthread/uthread_unlinkat.c diff --git a/include/unistd.h b/include/unistd.h index 1735b98599..8aa10bde46 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -362,6 +362,7 @@ int tcsetpgrp(int, pid_t); char *ttyname(int); int ttyname_r(int, char *, size_t); int unlink(const char *); +int unlinkat(int, const char *, int); ssize_t write(int, const void *, size_t); /* 1003.2-1992 */ diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index 01f76999ed..5cafb365f2 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -90,7 +90,8 @@ MAN+= _exit.2 accept.2 access.2 acct.2 adjtime.2 \ sigstack.2 sigsuspend.2 socket.2 socketpair.2 stat.2 statfs.2 \ statvfs.2 swapon.2 symlink.2 sync.2 sysarch.2 syscall.2 syslink.2 \ truncate.2 tls.2 umask.2 umtx.2 undelete.2 \ - unlink.2 utimes.2 utrace.2 upc_register.2 usched_set.2 uuidgen.2 \ + unlink.2 unlinkat.2 utimes.2 utrace.2 upc_register.2 usched_set.2 \ + uuidgen.2 \ varsym.2 vfork.2 wait.2 write.2 .if !defined(NO_P1003_1B) diff --git a/lib/libc/sys/rmdir.2 b/lib/libc/sys/rmdir.2 index ce36cfc5ed..ce6cafc8df 100644 --- a/lib/libc/sys/rmdir.2 +++ b/lib/libc/sys/rmdir.2 @@ -33,7 +33,7 @@ .\" $FreeBSD: src/lib/libc/sys/rmdir.2,v 1.5.2.5 2001/12/14 18:34:01 ru Exp $ .\" $DragonFly: src/lib/libc/sys/rmdir.2,v 1.2 2003/06/17 04:26:47 dillon Exp $ .\" -.Dd June 4, 1993 +.Dd August 18, 2009 .Dt RMDIR 2 .Os .Sh NAME @@ -98,7 +98,8 @@ points outside the process's allocated address space. .El .Sh SEE ALSO .Xr mkdir 2 , -.Xr unlink 2 +.Xr unlink 2 , +.Xr unlinkat 2 .Sh HISTORY The .Fn rmdir diff --git a/lib/libc/sys/unlink.2 b/lib/libc/sys/unlink.2 index 5cec372eab..9c4eb34f80 100644 --- a/lib/libc/sys/unlink.2 +++ b/lib/libc/sys/unlink.2 @@ -33,7 +33,7 @@ .\" $FreeBSD: src/lib/libc/sys/unlink.2,v 1.8.2.4 2001/12/14 18:34:02 ru Exp $ .\" $DragonFly: src/lib/libc/sys/unlink.2,v 1.4 2007/04/26 17:35:03 swildner Exp $ .\" -.Dd June 4, 1993 +.Dd August 18, 2009 .Dt UNLINK 2 .Os .Sh NAME @@ -108,7 +108,8 @@ points outside the process's allocated address space. .Xr close 2 , .Xr link 2 , .Xr rmdir 2 , -.Xr symlink 7 +.Xr symlink 7 , +.Xr unlinkat 2 .Sh HISTORY An .Fn unlink diff --git a/lib/libc/sys/unlinkat.2 b/lib/libc/sys/unlinkat.2 new file mode 100644 index 0000000000..960b762033 --- /dev/null +++ b/lib/libc/sys/unlinkat.2 @@ -0,0 +1,113 @@ +.\" Copyright (c) 2009 The DragonFly Project. All rights reserved. +.\" +.\" This code is derived from software contributed to The DragonFly Project +.\" by Nicolas Thery +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" 3. Neither the name of The DragonFly Project nor the names of its +.\" contributors may be used to endorse or promote products derived +.\" from this software without specific, prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, +.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd August 18, 2009 +.Dt UNLINKAT 2 +.Os +.Sh NAME +.Nm unlinkat +.Nd remove directory entry or directory file +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In fcntl.h +.In unistd.h +.Ft int +.Fn unlinkat "int fd" "const char *path" "int flags" +.Sh DESCRIPTION +The +.Fn unlinkat +function +operates as the +.Fn unlink +or +.Fn rmdir +functions depending on the value of +.Fa flags . +.Pp +The values for the +.Fa flags +are constructed by a bitwise-inclusive OR of flags from the following list, +defined in +.In fcntl.h : +.Bl -tag -width indent +.It Dv AT_REMOVEDIR +Remove a directory file instead of a directory entry. +.El +.Pp +If +.Fa path +specifies a relative path the directory entry or directory file to delete is +determined relative to the directory associated with the file descriptor +.Fa fd +instead of the current working directory. +If +.Fa fd +is the special value +.Dv AT_FDCWD +the current working directory is used and the behavior is identical to a call to +.Fn rmdir +or +.Fn unlink . +.Sh RETURN VALUES +.Rv -std unlinkat +.Sh ERRORS +The +.Fn unlinkat +function can fail with the same error codes as +.Fn unlink +and +.Fn rmdir . +In addition, +.Fn unlinkat +can fail with: +.Bl -tag -width Er +.It Bq Er EBADF +.Fa fd +is not a valid file descriptor. +.It Bq Er ENOTDIR +.Fa path +is relative and +.Fa fd +does not point to a directory. +.It Bq Er EINVAL +.Fa flags +contains unsupported flags. +.El +.Sh SEE ALSO +.Xr rmdir 2 , +.Xr unlink 2 +.Sh HISTORY +The +.Fn unlinkat +system call appeared in +.Dx 2.3 . diff --git a/lib/libc_r/uthread/Makefile.inc b/lib/libc_r/uthread/Makefile.inc index eebb17751a..f267fbf0c7 100644 --- a/lib/libc_r/uthread/Makefile.inc +++ b/lib/libc_r/uthread/Makefile.inc @@ -129,6 +129,7 @@ SRCS+= \ uthread_switch_np.c \ uthread_system.c \ uthread_tcdrain.c \ + uthread_unlinkat.c \ uthread_vfork.c \ uthread_wait.c \ uthread_wait4.c \ diff --git a/lib/libc_r/uthread/uthread_unlinkat.c b/lib/libc_r/uthread/uthread_unlinkat.c new file mode 100644 index 0000000000..75f84db67b --- /dev/null +++ b/lib/libc_r/uthread/uthread_unlinkat.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2009 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Nicolas Thery + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include "pthread_private.h" + +int +_unlinkat(int fd, const char *path, int flags) +{ + int ret; + + if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) { + ret = __sys_unlinkat(fd, path, flags); + _FD_UNLOCK(fd, FD_READ); + } + return (ret); +} + +__strong_reference(_unlinkat, unlinkat); diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 65bfd122b2..8cba3a2b75 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -541,4 +541,5 @@ struct sysent sysent[] = { { AS(fstatat_args), (sy_call_t *)sys_fstatat }, /* 505 = fstatat */ { AS(fchmodat_args), (sy_call_t *)sys_fchmodat }, /* 506 = fchmodat */ { AS(fchownat_args), (sy_call_t *)sys_fchownat }, /* 507 = fchownat */ + { AS(unlinkat_args), (sy_call_t *)sys_unlinkat }, /* 508 = unlinkat */ }; diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index e1fa42216e..2caa347042 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -515,4 +515,5 @@ const char *syscallnames[] = { "fstatat", /* 505 = fstatat */ "fchmodat", /* 506 = fchmodat */ "fchownat", /* 507 = fchownat */ + "unlinkat", /* 508 = unlinkat */ }; diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 628a1387b9..607ac4b9b7 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -698,3 +698,4 @@ int flags); } 507 STD POSIX { int fchownat(int fd, char *path, int uid, int gid, \ int flags); } +508 STD POSIX { int unlinkat(int fd, char *path, int flags); } diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 5b6e0ef807..da1e2b6d57 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -2237,6 +2237,33 @@ sys_unlink(struct unlink_args *uap) return (error); } + +/* + * unlinkat_args(int fd, char *path, int flags) + * + * Delete the file or directory entry pointed to by fd/path. + */ +int +sys_unlinkat(struct unlinkat_args *uap) +{ + struct nlookupdata nd; + struct file *fp; + int error; + + if (uap->flags & ~AT_REMOVEDIR) + return (EINVAL); + + error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0); + if (error == 0) { + if (uap->flags & AT_REMOVEDIR) + error = kern_rmdir(&nd); + else + error = kern_unlink(&nd); + } + nlookup_done_at(&nd, fp); + return (error); +} + int kern_lseek(int fd, off_t offset, int whence, off_t *res) { diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h index a8919d87a9..05130206a2 100644 --- a/sys/sys/fcntl.h +++ b/sys/sys/fcntl.h @@ -171,6 +171,7 @@ #define AT_FDCWD 0xFFFAFDCD /* invalid file descriptor */ #define AT_SYMLINK_NOFOLLOW 1 #define _AT_SYMLINK_MASK 1 +#define AT_REMOVEDIR 2 /* * Constants used for fcntl(2) diff --git a/sys/sys/syscall-hide.h b/sys/sys/syscall-hide.h index 6e83a94418..dd87f6a44c 100644 --- a/sys/sys/syscall-hide.h +++ b/sys/sys/syscall-hide.h @@ -338,3 +338,4 @@ HIDE_POSIX(openat) HIDE_POSIX(fstatat) HIDE_POSIX(fchmodat) HIDE_POSIX(fchownat) +HIDE_POSIX(unlinkat) diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index e64115148e..aee1f3190b 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -349,4 +349,5 @@ #define SYS_fstatat 505 #define SYS_fchmodat 506 #define SYS_fchownat 507 -#define SYS_MAXSYSCALL 508 +#define SYS_unlinkat 508 +#define SYS_MAXSYSCALL 509 diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk index aee75a187b..b87f94f08f 100644 --- a/sys/sys/syscall.mk +++ b/sys/sys/syscall.mk @@ -289,4 +289,5 @@ MIASM = \ openat.o \ fstatat.o \ fchmodat.o \ - fchownat.o + fchownat.o \ + unlinkat.o diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h index 6f80bc70be..4fc4cb6758 100644 --- a/sys/sys/sysproto.h +++ b/sys/sys/sysproto.h @@ -2196,6 +2196,14 @@ struct fchownat_args { int gid; char gid_[PAD_(int)]; int flags; char flags_[PAD_(int)]; }; +struct unlinkat_args { +#ifdef _KERNEL + struct sysmsg sysmsg; +#endif + int fd; char fd_[PAD_(int)]; + char * path; char path_[PAD_(char *)]; + int flags; char flags_[PAD_(int)]; +}; #ifdef COMPAT_43 @@ -2786,6 +2794,7 @@ int sys_openat (struct openat_args *); int sys_fstatat (struct fstatat_args *); int sys_fchmodat (struct fchmodat_args *); int sys_fchownat (struct fchownat_args *); +int sys_unlinkat (struct unlinkat_args *); #endif /* !_SYS_SYSPROTO_H_ */ #undef PAD_ diff --git a/sys/sys/sysunion.h b/sys/sys/sysunion.h index 4d70eec7d1..20baf78c25 100644 --- a/sys/sys/sysunion.h +++ b/sys/sys/sysunion.h @@ -394,4 +394,5 @@ union sysunion { struct fstatat_args fstatat; struct fchmodat_args fchmodat; struct fchownat_args fchownat; + struct unlinkat_args unlinkat; }; -- 2.41.0