From: Nicolas Thery Date: Sun, 9 Aug 2009 17:33:23 +0000 (+0200) Subject: add fchownat(2) system call X-Git-Tag: v2.4.0~292^2~1 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/32013176c8992dafb4587c2a186d4aca1227756a add fchownat(2) system call Add also libc_r wrapper and man page. --- diff --git a/include/unistd.h b/include/unistd.h index 83139db302..1735b98599 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -318,6 +318,7 @@ int access(const char *, int); unsigned int alarm(unsigned int); int chdir(const char *); int chown(const char *, uid_t, gid_t); +int fchownat(int, const char *, uid_t, gid_t, int); int close(int); int dup(int); int dup2(int, int); diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index dd847f8341..01f76999ed 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -103,7 +103,7 @@ MLINKS+=caps_sys_get.2 caps_sys_wait.2 MLINKS+=chdir.2 fchdir.2 MLINKS+=chflags.2 fchflags.2 chflags.2 lchflags.2 MLINKS+=chmod.2 fchmod.2 chmod.2 lchmod.2 chmod.2 fchmodat.2 -MLINKS+=chown.2 fchown.2 chown.2 lchown.2 +MLINKS+=chown.2 fchown.2 chown.2 lchown.2 chown.2 fchownat.2 MLINKS+=clock_gettime.2 clock_getres.2 clock_gettime.2 clock_settime.2 MLINKS+=dup.2 dup2.2 MLINKS+=fhopen.2 fhstat.2 fhopen.2 fhstatfs.2 fhopen.2 fhstatvfs.2 diff --git a/lib/libc/sys/chown.2 b/lib/libc/sys/chown.2 index 96b1b35ffc..7326161be8 100644 --- a/lib/libc/sys/chown.2 +++ b/lib/libc/sys/chown.2 @@ -33,13 +33,14 @@ .\" $FreeBSD: src/lib/libc/sys/chown.2,v 1.12.2.6 2001/12/14 18:34:00 ru Exp $ .\" $DragonFly: src/lib/libc/sys/chown.2,v 1.2 2003/06/17 04:26:47 dillon Exp $ .\" -.Dd April 19, 1994 +.Dd August 9, 2009 .Dt CHOWN 2 .Os .Sh NAME .Nm chown , .Nm fchown , -.Nm lchown +.Nm lchown , +.Nm fchownat .Nd change owner and group of a file .Sh LIBRARY .Lb libc @@ -51,6 +52,8 @@ .Fn fchown "int fd" "uid_t owner" "gid_t group" .Ft int .Fn lchown "const char *path" "uid_t owner" "gid_t group" +.Ft int +.Fn fchownat "int dirfd" "const char *path" "uid_t owner" "gid_t group" "int flags" .Sh DESCRIPTION The owner ID and group ID of the file named by @@ -91,16 +94,56 @@ but does not follow symbolic links. .Pp One of the owner or group id's may be left unchanged by specifying it as -1. +.Pp +The +.Fn fchownat +function is equivalent to the +.Fn chown +or +.Fn lchown +functions except in the case where the +.Fa path +specifies a relative path. +In this case the file to be opened is determined relative to the directory +associated with the file descriptor +.Fa dirfd +instead of the current working directory. +If +.Fn fchownat +is passed the special value +.Dv AT_FDCWD +in the +.Fa dirfd +parameter, the current working directory is used +and the behavior is identical to a call to +.Fn chown +or +.Fn lchown . +.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_SYMLINK_NOFOLLOW +If +.Fa path +names a symbolic link, the mode of the symbolic link is changed. +.El .Sh RETURN VALUES .Rv -std .Sh ERRORS -.Fn Chown -and +.Fn Chown , .Fn lchown +and +.Fn fchownat will fail and the file will be unchanged if: .Bl -tag -width Er .It Bq Er ENOTDIR -A component of the path prefix is not a directory. +A component of the path prefix or +.Fa dirfd +is not a directory. .It Bq Er ENAMETOOLONG A component of a pathname exceeded 255 characters, or an entire path name exceeded 1023 characters. @@ -167,3 +210,8 @@ The function was added in .Fx 3.0 to compensate for the loss of functionality. +.Pp +The +.Fn fchownat +system call appeared in +.Dx 2.3 . diff --git a/lib/libc_r/uthread/Makefile.inc b/lib/libc_r/uthread/Makefile.inc index 67298faee5..eebb17751a 100644 --- a/lib/libc_r/uthread/Makefile.inc +++ b/lib/libc_r/uthread/Makefile.inc @@ -50,6 +50,7 @@ SRCS+= \ uthread_fchmod.c \ uthread_fchmodat.c \ uthread_fchown.c \ + uthread_fchownat.c \ uthread_fcntl.c \ uthread_fd.c \ uthread_find_thread.c \ diff --git a/lib/libc_r/uthread/uthread_fchownat.c b/lib/libc_r/uthread/uthread_fchownat.c new file mode 100644 index 0000000000..6a5ff7dcae --- /dev/null +++ b/lib/libc_r/uthread/uthread_fchownat.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 +_fchownat(int fd, const char *path, uid_t owner, gid_t group, int flags) +{ + int ret; + + if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) { + ret = __sys_fchownat(fd, path, owner, group, flags); + _FD_UNLOCK(fd, FD_READ); + } + return (ret); +} + +__strong_reference(_fchownat, fchownat); diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 6d69ef665f..65bfd122b2 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -540,4 +540,5 @@ struct sysent sysent[] = { { AS(openat_args), (sy_call_t *)sys_openat }, /* 504 = openat */ { 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 */ }; diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 007e6a967d..e1fa42216e 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -514,4 +514,5 @@ const char *syscallnames[] = { "openat", /* 504 = openat */ "fstatat", /* 505 = fstatat */ "fchmodat", /* 506 = fchmodat */ + "fchownat", /* 507 = fchownat */ }; diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 83fe3f1e0f..628a1387b9 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -696,3 +696,5 @@ struct stat *sb, int flags); } 506 STD POSIX { int fchmodat(int fd, char *path, int mode, \ int flags); } +507 STD POSIX { int fchownat(int fd, char *path, int uid, int gid, \ + int flags); } diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 83bf5cf478..0c723e4194 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -2906,6 +2906,32 @@ sys_fchown(struct fchown_args *uap) return (error); } +/* + * fchownat(int fd, char *path, int uid, int gid, int flags) + * + * Set ownership of file pointed to by fd/path. + */ +int +sys_fchownat(struct fchownat_args *uap) +{ + struct nlookupdata nd; + struct file *fp; + int error; + int flags; + + if (uap->flags & ~_AT_SYMLINK_MASK) + return (EINVAL); + flags = (uap->flags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW; + + error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, + UIO_USERSPACE, flags); + if (error == 0) + error = kern_chown(&nd, uap->uid, uap->gid); + nlookup_done_at(&nd, fp); + return (error); +} + + static int getutimes(const struct timeval *tvp, struct timespec *tsp) { diff --git a/sys/sys/syscall-hide.h b/sys/sys/syscall-hide.h index cb22bbddbb..6e83a94418 100644 --- a/sys/sys/syscall-hide.h +++ b/sys/sys/syscall-hide.h @@ -337,3 +337,4 @@ HIDE_BSD(getvfsstat) HIDE_POSIX(openat) HIDE_POSIX(fstatat) HIDE_POSIX(fchmodat) +HIDE_POSIX(fchownat) diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index ff73c93fd3..e64115148e 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -348,4 +348,5 @@ #define SYS_openat 504 #define SYS_fstatat 505 #define SYS_fchmodat 506 -#define SYS_MAXSYSCALL 507 +#define SYS_fchownat 507 +#define SYS_MAXSYSCALL 508 diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk index e027afdc3d..aee75a187b 100644 --- a/sys/sys/syscall.mk +++ b/sys/sys/syscall.mk @@ -288,4 +288,5 @@ MIASM = \ getvfsstat.o \ openat.o \ fstatat.o \ - fchmodat.o + fchmodat.o \ + fchownat.o diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h index 05db2a2f5b..6f80bc70be 100644 --- a/sys/sys/sysproto.h +++ b/sys/sys/sysproto.h @@ -2186,6 +2186,16 @@ struct fchmodat_args { int mode; char mode_[PAD_(int)]; int flags; char flags_[PAD_(int)]; }; +struct fchownat_args { +#ifdef _KERNEL + struct sysmsg sysmsg; +#endif + int fd; char fd_[PAD_(int)]; + char * path; char path_[PAD_(char *)]; + int uid; char uid_[PAD_(int)]; + int gid; char gid_[PAD_(int)]; + int flags; char flags_[PAD_(int)]; +}; #ifdef COMPAT_43 @@ -2775,6 +2785,7 @@ int sys_getvfsstat (struct getvfsstat_args *); int sys_openat (struct openat_args *); int sys_fstatat (struct fstatat_args *); int sys_fchmodat (struct fchmodat_args *); +int sys_fchownat (struct fchownat_args *); #endif /* !_SYS_SYSPROTO_H_ */ #undef PAD_ diff --git a/sys/sys/sysunion.h b/sys/sys/sysunion.h index f2bc2fe56a..4d70eec7d1 100644 --- a/sys/sys/sysunion.h +++ b/sys/sys/sysunion.h @@ -393,4 +393,5 @@ union sysunion { struct openat_args openat; struct fstatat_args fstatat; struct fchmodat_args fchmodat; + struct fchownat_args fchownat; };