diff --git a/include/dirent.h b/include/dirent.h index 0d1e0c7..cedec07 100644 --- a/include/dirent.h +++ b/include/dirent.h @@ -95,9 +95,11 @@ typedef void * DIR; __BEGIN_DECLS #if __BSD_VISIBLE DIR *__opendir2(const char *, int); +DIR *__fdopendir2(int, int); int alphasort(const void *, const void *); int getdents(int, char *, int); int getdirentries(int, char *, int, long *); +DIR *fdopendir(int); #endif DIR *opendir(const char *); struct dirent * diff --git a/include/stdio.h b/include/stdio.h index 1eef563..6b709e2 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -447,5 +447,8 @@ extern int __isthreaded; #define putchar_unlocked(x) putc_unlocked(x, stdout) #endif +#if __BSD_VISIBLE +int renameat(int, const char *, int, const char *); +#endif __END_DECLS #endif /* !_STDIO_H_ */ diff --git a/include/unistd.h b/include/unistd.h index 3f302bb..07508f3 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -559,6 +559,17 @@ void *valloc(size_t); /* obsoleted by malloc() */ extern int optreset; /* getopt(3) external variable */ #endif #endif /* __BSD_VISIBLE */ + +#if __BSD_VISIBLE +int faccessat(int, const char *, int); +int fchmodat(int, const char *, mode_t, int); +int fchownat(int, const char *, uid_t, gid_t, int); +int fexecve(int, char *const [], char *const []); +int linkat(int, const char *, int, const char *, int); +ssize_t readlinkat(int, const char *, char *, size_t); +int symlinkat(const char *, int, const char *); +int unlinkat(int, const char *, int); +#endif /* __BSD_VISIBLE */ __END_DECLS #endif /* !_UNISTD_H_ */ diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index 2079f4e..b84e49c 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -10,7 +10,7 @@ SRCS+= __getosreldate.c __xuname.c \ clock.c closedir.c confstr.c \ crypt.c ctermid.c daemon.c devname.c dirname.c disklabel.c \ dlfcn.c dlfunc.c drand48.c erand48.c err.c errlst.c errno.c \ - exec.c feature_present.c fmtcheck.c fmtmsg.c fnmatch.c \ + exec.c fdopendir.c feature_present.c fmtcheck.c fmtmsg.c fnmatch.c \ fpclassify.c frexp.c fstab.c ftok.c fts.c fts-compat.c ftw.c \ getbootfile.c getbsize.c \ getcap.c getcwd.c getdomainname.c getgrent.c getgrouplist.c \ diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map index 2bfda74..89a1320 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -329,6 +329,7 @@ FBSD_1.0 { }; FBSD_1.1 { + fdopendir; fts_open; fts_close; fts_read; diff --git a/lib/libc/gen/fdopendir.c b/lib/libc/gen/fdopendir.c new file mode 100644 index 0000000..2f23500 --- /dev/null +++ b/lib/libc/gen/fdopendir.c @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2007 + * Roman Divacky. All rights reserved. + * + * 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. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)opendir.c 8.8 (Berkeley) 5/1/95"; +#endif /* LIBC_SCCS and not lint */ +#include +__FBSDID("$FreeBSD$"); + +#include "namespace.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "un-namespace.h" + +#include "telldir.h" +/* + * Open a directory. + */ +DIR * +fdopendir(fd) + const int fd; +{ + + return (__fdopendir2(fd, DTF_HIDEW|DTF_NODUP)); +} + +DIR * +__fdopendir2(fd, flags) + const int fd; + int flags; +{ + DIR *dirp; + int incr; + int saved_errno; + int unionstack; + struct stat statb; + + dirp = NULL; + if (_fstat(fd, &statb) != 0) + goto fail; + if (!S_ISDIR(statb.st_mode)) { + errno = ENOTDIR; + goto fail; + } + if (_fcntl(fd, F_SETFD, FD_CLOEXEC) == -1 || + (dirp = malloc(sizeof(DIR) + sizeof(struct _telldir))) == NULL) + goto fail; + + dirp->dd_td = (struct _telldir *)((char *)dirp + sizeof(DIR)); + LIST_INIT(&dirp->dd_td->td_locq); + dirp->dd_td->td_loccnt = 0; + + /* + * Use the system page size if that is a multiple of DIRBLKSIZ. + * Hopefully this can be a big win someday by allowing page + * trades to user space to be done by _getdirentries(). + */ + incr = getpagesize(); + if ((incr % DIRBLKSIZ) != 0) + incr = DIRBLKSIZ; + + /* + * Determine whether this directory is the top of a union stack. + */ + if (flags & DTF_NODUP) { + struct statfs sfb; + + if (_fstatfs(fd, &sfb) < 0) + goto fail; + unionstack = !strcmp(sfb.f_fstypename, "unionfs") + || (sfb.f_flags & MNT_UNION); + } else { + unionstack = 0; + } + + if (unionstack) { + int len = 0; + int space = 0; + char *buf = 0; + char *ddptr = 0; + char *ddeptr; + int n; + struct dirent **dpv; + + /* + * The strategy here is to read all the directory + * entries into a buffer, sort the buffer, and + * remove duplicate entries by setting the inode + * number to zero. + */ + + do { + /* + * Always make at least DIRBLKSIZ bytes + * available to _getdirentries + */ + if (space < DIRBLKSIZ) { + space += incr; + len += incr; + buf = reallocf(buf, len); + if (buf == NULL) + goto fail; + ddptr = buf + (len - space); + } + + n = _getdirentries(fd, ddptr, space, &dirp->dd_seek); + if (n > 0) { + ddptr += n; + space -= n; + } + } while (n > 0); + + ddeptr = ddptr; + flags |= __DTF_READALL; + + /* + * Re-open the directory. + * This has the effect of rewinding back to the + * top of the union stack and is needed by + * programs which plan to fchdir to a descriptor + * which has also been read -- see fts.c. + */ + if (flags & DTF_REWIND) { + /* XXX: what here? */ + } + + /* + * There is now a buffer full of (possibly) duplicate + * names. + */ + dirp->dd_buf = buf; + + /* + * Go round this loop twice... + * + * Scan through the buffer, counting entries. + * On the second pass, save pointers to each one. + * Then sort the pointers and remove duplicate names. + */ + for (dpv = 0;;) { + n = 0; + ddptr = buf; + while (ddptr < ddeptr) { + struct dirent *dp; + + dp = (struct dirent *) ddptr; + if ((long)dp & 03L) + break; + if ((dp->d_reclen <= 0) || + (dp->d_reclen > (ddeptr + 1 - ddptr))) + break; + ddptr += dp->d_reclen; + if (dp->d_fileno) { + if (dpv) + dpv[n] = dp; + n++; + } + } + + if (dpv) { + struct dirent *xp; + + /* + * This sort must be stable. + */ + mergesort(dpv, n, sizeof(*dpv), alphasort); + + dpv[n] = NULL; + xp = NULL; + + /* + * Scan through the buffer in sort order, + * zapping the inode number of any + * duplicate names. + */ + for (n = 0; dpv[n]; n++) { + struct dirent *dp = dpv[n]; + + if ((xp == NULL) || + strcmp(dp->d_name, xp->d_name)) { + xp = dp; + } else { + dp->d_fileno = 0; + } + if (dp->d_type == DT_WHT && + (flags & DTF_HIDEW)) + dp->d_fileno = 0; + } + + free(dpv); + break; + } else { + dpv = malloc((n+1) * sizeof(struct dirent *)); + if (dpv == NULL) + break; + } + } + + dirp->dd_len = len; + dirp->dd_size = ddptr - dirp->dd_buf; + } else { + dirp->dd_len = incr; + dirp->dd_size = 0; + dirp->dd_buf = malloc(dirp->dd_len); + if (dirp->dd_buf == NULL) + goto fail; + dirp->dd_seek = 0; + flags &= ~DTF_REWIND; + } + + dirp->dd_loc = 0; + dirp->dd_fd = fd; + dirp->dd_flags = flags; + dirp->dd_lock = NULL; + + /* + * Set up seek point for rewinddir. + */ + dirp->dd_rewind = telldir(dirp); + + return (dirp); + +fail: + saved_errno = errno; + free(dirp); + errno = saved_errno; + return (NULL); +} diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map index 82e9bef..a80d991 100644 --- a/lib/libc/sys/Symbol.map +++ b/lib/libc/sys/Symbol.map @@ -334,6 +334,24 @@ FBSD_1.0 { truncate; }; +FBSD_1.1 { + faccessat; + fchmodat; + fchownat; + fexecve; + fstatat; + futimesat; + linkat; + mkdirat; + mkfifoat; + mknodat; + openat; + readlinkat; + renameat; + symlinkat; + unlinkat; +}; + FBSDprivate_1.0 { ___acl_aclcheck_fd; __sys___acl_aclcheck_fd; diff --git a/sys/amd64/linux32/linux.h b/sys/amd64/linux32/linux.h index 17543bd..fc7cf7c 100644 --- a/sys/amd64/linux32/linux.h +++ b/sys/amd64/linux32/linux.h @@ -579,8 +579,6 @@ int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h); #define LINUX_F_WRLCK 1 #define LINUX_F_UNLCK 2 -#define LINUX_AT_FDCWD -100 - /* * mount flags */ diff --git a/sys/amd64/linux32/linux32_dummy.c b/sys/amd64/linux32/linux32_dummy.c index 6ac97a3..82607fb 100644 --- a/sys/amd64/linux32/linux32_dummy.c +++ b/sys/amd64/linux32/linux32_dummy.c @@ -96,18 +96,6 @@ DUMMY(inotify_init); DUMMY(inotify_add_watch); DUMMY(inotify_rm_watch); DUMMY(migrate_pages); -DUMMY(mkdirat); -DUMMY(mknodat); -DUMMY(fchownat); -DUMMY(futimesat); -DUMMY(fstatat64); -DUMMY(unlinkat); -DUMMY(renameat); -DUMMY(linkat); -DUMMY(symlinkat); -DUMMY(readlinkat); -DUMMY(fchmodat); -DUMMY(faccessat); DUMMY(pselect6); DUMMY(ppoll); DUMMY(unshare); diff --git a/sys/amd64/linux32/linux32_proto.h b/sys/amd64/linux32/linux32_proto.h index c48bf74..248b8c7 100644 --- a/sys/amd64/linux32/linux32_proto.h +++ b/sys/amd64/linux32/linux32_proto.h @@ -2,7 +2,7 @@ * System call prototypes. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/amd64/linux32/linux32_proto.h,v 1.34 2008/03/16 16:29:37 rdivacky Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/amd64/linux32/syscalls.master,v 1.31 2008/03/16 16:24:20 rdivacky Exp */ @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -886,45 +887,77 @@ struct linux_migrate_pages_args { }; struct linux_openat_args { char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; - char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)]; + char filename_l_[PADL_(const char *)]; const char * filename; char filename_r_[PADR_(const char *)]; char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)]; }; struct linux_mkdirat_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char pathname_l_[PADL_(const char *)]; const char * pathname; char pathname_r_[PADR_(const char *)]; + char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)]; }; struct linux_mknodat_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char filename_l_[PADL_(const char *)]; const char * filename; char filename_r_[PADR_(const char *)]; + char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)]; + char dev_l_[PADL_(l_uint)]; l_uint dev; char dev_r_[PADR_(l_uint)]; }; struct linux_fchownat_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char filename_l_[PADL_(const char *)]; const char * filename; char filename_r_[PADR_(const char *)]; + char uid_l_[PADL_(l_uid16_t)]; l_uid16_t uid; char uid_r_[PADR_(l_uid16_t)]; + char gid_l_[PADL_(l_gid16_t)]; l_gid16_t gid; char gid_r_[PADR_(l_gid16_t)]; + char flag_l_[PADL_(l_int)]; l_int flag; char flag_r_[PADR_(l_int)]; }; struct linux_futimesat_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)]; + char utimes_l_[PADL_(struct l_timeval *)]; struct l_timeval * utimes; char utimes_r_[PADR_(struct l_timeval *)]; }; struct linux_fstatat64_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char pathname_l_[PADL_(char *)]; char * pathname; char pathname_r_[PADR_(char *)]; + char statbuf_l_[PADL_(struct l_stat64 *)]; struct l_stat64 * statbuf; char statbuf_r_[PADR_(struct l_stat64 *)]; + char flag_l_[PADL_(l_int)]; l_int flag; char flag_r_[PADR_(l_int)]; }; struct linux_unlinkat_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char pathname_l_[PADL_(const char *)]; const char * pathname; char pathname_r_[PADR_(const char *)]; + char flag_l_[PADL_(l_int)]; l_int flag; char flag_r_[PADR_(l_int)]; }; struct linux_renameat_args { - register_t dummy; + char olddfd_l_[PADL_(l_int)]; l_int olddfd; char olddfd_r_[PADR_(l_int)]; + char oldname_l_[PADL_(const char *)]; const char * oldname; char oldname_r_[PADR_(const char *)]; + char newdfd_l_[PADL_(l_int)]; l_int newdfd; char newdfd_r_[PADR_(l_int)]; + char newname_l_[PADL_(const char *)]; const char * newname; char newname_r_[PADR_(const char *)]; }; struct linux_linkat_args { - register_t dummy; + char olddfd_l_[PADL_(l_int)]; l_int olddfd; char olddfd_r_[PADR_(l_int)]; + char oldname_l_[PADL_(const char *)]; const char * oldname; char oldname_r_[PADR_(const char *)]; + char newdfd_l_[PADL_(l_int)]; l_int newdfd; char newdfd_r_[PADR_(l_int)]; + char newname_l_[PADL_(const char *)]; const char * newname; char newname_r_[PADR_(const char *)]; + char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; }; struct linux_symlinkat_args { - register_t dummy; + char oldname_l_[PADL_(const char *)]; const char * oldname; char oldname_r_[PADR_(const char *)]; + char newdfd_l_[PADL_(l_int)]; l_int newdfd; char newdfd_r_[PADR_(l_int)]; + char newname_l_[PADL_(const char *)]; const char * newname; char newname_r_[PADR_(const char *)]; }; struct linux_readlinkat_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)]; + char bufsiz_l_[PADL_(l_int)]; l_int bufsiz; char bufsiz_r_[PADR_(l_int)]; }; struct linux_fchmodat_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char filename_l_[PADL_(const char *)]; const char * filename; char filename_r_[PADR_(const char *)]; + char mode_l_[PADL_(l_mode_t)]; l_mode_t mode; char mode_r_[PADR_(l_mode_t)]; }; struct linux_faccessat_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char filename_l_[PADL_(const char *)]; const char * filename; char filename_r_[PADR_(const char *)]; + char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)]; }; struct linux_pselect6_args { register_t dummy; @@ -1412,18 +1445,18 @@ int linux_unshare(struct thread *, struct linux_unshare_args *); #define LINUX_SYS_AUE_linux_inotify_rm_watch AUE_NULL #define LINUX_SYS_AUE_linux_migrate_pages AUE_NULL #define LINUX_SYS_AUE_linux_openat AUE_OPEN_RWTC -#define LINUX_SYS_AUE_linux_mkdirat AUE_NULL -#define LINUX_SYS_AUE_linux_mknodat AUE_NULL -#define LINUX_SYS_AUE_linux_fchownat AUE_NULL -#define LINUX_SYS_AUE_linux_futimesat AUE_NULL -#define LINUX_SYS_AUE_linux_fstatat64 AUE_NULL -#define LINUX_SYS_AUE_linux_unlinkat AUE_NULL -#define LINUX_SYS_AUE_linux_renameat AUE_NULL -#define LINUX_SYS_AUE_linux_linkat AUE_NULL -#define LINUX_SYS_AUE_linux_symlinkat AUE_NULL -#define LINUX_SYS_AUE_linux_readlinkat AUE_NULL -#define LINUX_SYS_AUE_linux_fchmodat AUE_NULL -#define LINUX_SYS_AUE_linux_faccessat AUE_NULL +#define LINUX_SYS_AUE_linux_mkdirat AUE_MKDIRAT +#define LINUX_SYS_AUE_linux_mknodat AUE_MKNODAT +#define LINUX_SYS_AUE_linux_fchownat AUE_FCHOWNAT +#define LINUX_SYS_AUE_linux_futimesat AUE_FUTIMESAT +#define LINUX_SYS_AUE_linux_fstatat64 AUE_FSTATAT +#define LINUX_SYS_AUE_linux_unlinkat AUE_UNLINKAT +#define LINUX_SYS_AUE_linux_renameat AUE_RENAMEAT +#define LINUX_SYS_AUE_linux_linkat AUE_LINKAT +#define LINUX_SYS_AUE_linux_symlinkat AUE_SYMLINKAT +#define LINUX_SYS_AUE_linux_readlinkat AUE_READLINKAT +#define LINUX_SYS_AUE_linux_fchmodat AUE_FCHMODAT +#define LINUX_SYS_AUE_linux_faccessat AUE_FACCESSAT #define LINUX_SYS_AUE_linux_pselect6 AUE_NULL #define LINUX_SYS_AUE_linux_ppoll AUE_NULL #define LINUX_SYS_AUE_linux_unshare AUE_NULL diff --git a/sys/amd64/linux32/linux32_syscall.h b/sys/amd64/linux32/linux32_syscall.h index 95d5829..4dcdc94 100644 --- a/sys/amd64/linux32/linux32_syscall.h +++ b/sys/amd64/linux32/linux32_syscall.h @@ -2,7 +2,7 @@ * System call numbers. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/amd64/linux32/linux32_syscall.h,v 1.34 2008/03/16 16:29:37 rdivacky Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/amd64/linux32/syscalls.master,v 1.31 2008/03/16 16:24:20 rdivacky Exp */ diff --git a/sys/amd64/linux32/linux32_sysent.c b/sys/amd64/linux32/linux32_sysent.c index 8a7f13d..d5edda2 100644 --- a/sys/amd64/linux32/linux32_sysent.c +++ b/sys/amd64/linux32/linux32_sysent.c @@ -2,11 +2,10 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/amd64/linux32/linux32_sysent.c,v 1.34 2008/03/16 16:29:37 rdivacky Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/amd64/linux32/syscalls.master,v 1.31 2008/03/16 16:24:20 rdivacky Exp */ -#include #include "opt_compat.h" #include #include @@ -316,18 +315,18 @@ struct sysent linux_sysent[] = { { 0, (sy_call_t *)linux_inotify_rm_watch, AUE_NULL, NULL, 0, 0 }, /* 293 = linux_inotify_rm_watch */ { 0, (sy_call_t *)linux_migrate_pages, AUE_NULL, NULL, 0, 0 }, /* 294 = linux_migrate_pages */ { AS(linux_openat_args), (sy_call_t *)linux_openat, AUE_OPEN_RWTC, NULL, 0, 0 }, /* 295 = linux_openat */ - { 0, (sy_call_t *)linux_mkdirat, AUE_NULL, NULL, 0, 0 }, /* 296 = linux_mkdirat */ - { 0, (sy_call_t *)linux_mknodat, AUE_NULL, NULL, 0, 0 }, /* 297 = linux_mknodat */ - { 0, (sy_call_t *)linux_fchownat, AUE_NULL, NULL, 0, 0 }, /* 298 = linux_fchownat */ - { 0, (sy_call_t *)linux_futimesat, AUE_NULL, NULL, 0, 0 }, /* 299 = linux_futimesat */ - { 0, (sy_call_t *)linux_fstatat64, AUE_NULL, NULL, 0, 0 }, /* 300 = linux_fstatat64 */ - { 0, (sy_call_t *)linux_unlinkat, AUE_NULL, NULL, 0, 0 }, /* 301 = linux_unlinkat */ - { 0, (sy_call_t *)linux_renameat, AUE_NULL, NULL, 0, 0 }, /* 302 = linux_renameat */ - { 0, (sy_call_t *)linux_linkat, AUE_NULL, NULL, 0, 0 }, /* 303 = linux_linkat */ - { 0, (sy_call_t *)linux_symlinkat, AUE_NULL, NULL, 0, 0 }, /* 304 = linux_symlinkat */ - { 0, (sy_call_t *)linux_readlinkat, AUE_NULL, NULL, 0, 0 }, /* 305 = linux_readlinkat */ - { 0, (sy_call_t *)linux_fchmodat, AUE_NULL, NULL, 0, 0 }, /* 306 = linux_fchmodat */ - { 0, (sy_call_t *)linux_faccessat, AUE_NULL, NULL, 0, 0 }, /* 307 = linux_faccessat */ + { AS(linux_mkdirat_args), (sy_call_t *)linux_mkdirat, AUE_MKDIRAT, NULL, 0, 0 }, /* 296 = linux_mkdirat */ + { AS(linux_mknodat_args), (sy_call_t *)linux_mknodat, AUE_MKNODAT, NULL, 0, 0 }, /* 297 = linux_mknodat */ + { AS(linux_fchownat_args), (sy_call_t *)linux_fchownat, AUE_FCHOWNAT, NULL, 0, 0 }, /* 298 = linux_fchownat */ + { AS(linux_futimesat_args), (sy_call_t *)linux_futimesat, AUE_FUTIMESAT, NULL, 0, 0 }, /* 299 = linux_futimesat */ + { AS(linux_fstatat64_args), (sy_call_t *)linux_fstatat64, AUE_FSTATAT, NULL, 0, 0 }, /* 300 = linux_fstatat64 */ + { AS(linux_unlinkat_args), (sy_call_t *)linux_unlinkat, AUE_UNLINKAT, NULL, 0, 0 }, /* 301 = linux_unlinkat */ + { AS(linux_renameat_args), (sy_call_t *)linux_renameat, AUE_RENAMEAT, NULL, 0, 0 }, /* 302 = linux_renameat */ + { AS(linux_linkat_args), (sy_call_t *)linux_linkat, AUE_LINKAT, NULL, 0, 0 }, /* 303 = linux_linkat */ + { AS(linux_symlinkat_args), (sy_call_t *)linux_symlinkat, AUE_SYMLINKAT, NULL, 0, 0 }, /* 304 = linux_symlinkat */ + { AS(linux_readlinkat_args), (sy_call_t *)linux_readlinkat, AUE_READLINKAT, NULL, 0, 0 }, /* 305 = linux_readlinkat */ + { AS(linux_fchmodat_args), (sy_call_t *)linux_fchmodat, AUE_FCHMODAT, NULL, 0, 0 }, /* 306 = linux_fchmodat */ + { AS(linux_faccessat_args), (sy_call_t *)linux_faccessat, AUE_FACCESSAT, NULL, 0, 0 }, /* 307 = linux_faccessat */ { 0, (sy_call_t *)linux_pselect6, AUE_NULL, NULL, 0, 0 }, /* 308 = linux_pselect6 */ { 0, (sy_call_t *)linux_ppoll, AUE_NULL, NULL, 0, 0 }, /* 309 = linux_ppoll */ { 0, (sy_call_t *)linux_unshare, AUE_NULL, NULL, 0, 0 }, /* 310 = linux_unshare */ diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c index c70e044..ed1db1a 100644 --- a/sys/amd64/linux32/linux32_sysvec.c +++ b/sys/amd64/linux32/linux32_sysvec.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD: src/sys/amd64/linux32/linux32_sysvec.c,v 1.33 2008/03/13 10: #include #include #include +#include #include #include #include @@ -788,7 +789,7 @@ exec_linux_imgact_try(struct image_params *imgp) */ if ((error = exec_shell_imgact(imgp)) == 0) { linux_emul_convpath(FIRST_THREAD_IN_PROC(imgp->proc), - imgp->interpreter_name, UIO_SYSSPACE, &rpath, 0); + imgp->interpreter_name, UIO_SYSSPACE, &rpath, 0, AT_FDCWD); if (rpath != NULL) { len = strlen(rpath) + 1; diff --git a/sys/amd64/linux32/syscalls.master b/sys/amd64/linux32/syscalls.master index beafee6..9556b46 100644 --- a/sys/amd64/linux32/syscalls.master +++ b/sys/amd64/linux32/syscalls.master @@ -465,20 +465,31 @@ 292 AUE_NULL STD { int linux_inotify_add_watch(void); } 293 AUE_NULL STD { int linux_inotify_rm_watch(void); } 294 AUE_NULL STD { int linux_migrate_pages(void); } -295 AUE_OPEN_RWTC STD { int linux_openat(l_int dfd, char *filename, \ +295 AUE_OPEN_RWTC STD { int linux_openat(l_int dfd, const char *filename, \ l_int flags, l_int mode); } -296 AUE_NULL STD { int linux_mkdirat(void); } -297 AUE_NULL STD { int linux_mknodat(void); } -298 AUE_NULL STD { int linux_fchownat(void); } -299 AUE_NULL STD { int linux_futimesat(void); } -300 AUE_NULL STD { int linux_fstatat64(void); } -301 AUE_NULL STD { int linux_unlinkat(void); } -302 AUE_NULL STD { int linux_renameat(void); } -303 AUE_NULL STD { int linux_linkat(void); } -304 AUE_NULL STD { int linux_symlinkat(void); } -305 AUE_NULL STD { int linux_readlinkat(void); } -306 AUE_NULL STD { int linux_fchmodat(void); } -307 AUE_NULL STD { int linux_faccessat(void); } +296 AUE_MKDIRAT STD { int linux_mkdirat(l_int dfd, const char *pathname, \ + l_int mode); } +297 AUE_MKNODAT STD { int linux_mknodat(l_int dfd, const char *filename, \ + l_int mode, l_uint dev); } +298 AUE_FCHOWNAT STD { int linux_fchownat(l_int dfd, const char *filename, \ + l_uid16_t uid, l_gid16_t gid, l_int flag); } +299 AUE_FUTIMESAT STD { int linux_futimesat(l_int dfd, char *filename, \ + struct l_timeval *utimes); } +300 AUE_FSTATAT STD { int linux_fstatat64(l_int dfd, char *pathname, \ + struct l_stat64 *statbuf, l_int flag); } +301 AUE_UNLINKAT STD { int linux_unlinkat(l_int dfd, const char *pathname, \ + l_int flag); } +302 AUE_RENAMEAT STD { int linux_renameat(l_int olddfd, const char *oldname, \ + l_int newdfd, const char *newname); } +303 AUE_LINKAT STD { int linux_linkat(l_int olddfd, const char *oldname, \ + l_int newdfd, const char *newname, l_int flags); } +304 AUE_SYMLINKAT STD { int linux_symlinkat(const char *oldname, l_int newdfd, \ + const char *newname); } +305 AUE_READLINKAT STD { int linux_readlinkat(l_int dfd, const char *path, \ + char *buf, l_int bufsiz); } +306 AUE_FCHMODAT STD { int linux_fchmodat(l_int dfd, const char *filename, \ + l_mode_t mode); } +307 AUE_FACCESSAT STD { int linux_faccessat(l_int dfd, const char *filename, l_int mode); } 308 AUE_NULL STD { int linux_pselect6(void); } 309 AUE_NULL STD { int linux_ppoll(void); } 310 AUE_NULL STD { int linux_unshare(void); } diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index f455096..959cdb3 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -260,16 +260,18 @@ freebsd32_exec_copyin_args(struct image_args *args, char *fname, args->endp = args->begin_argv; args->stringspace = ARG_MAX; - args->fname = args->buf + ARG_MAX; - /* * Copy the file name. */ - error = (segflg == UIO_SYSSPACE) ? - copystr(fname, args->fname, PATH_MAX, &length) : - copyinstr(fname, args->fname, PATH_MAX, &length); - if (error != 0) - goto err_exit; + if (fname != NULL) { + args->fname = args->buf + ARG_MAX; + error = (segflg == UIO_SYSSPACE) ? + copystr(fname, args->fname, PATH_MAX, &length) : + copyinstr(fname, args->fname, PATH_MAX, &length); + if (error != 0) + goto err_exit; + } else + args->fname = NULL; /* * extract arguments first @@ -342,6 +344,21 @@ freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap) return (error); } +int +freebsd32_fexecve(struct thread *td, struct freebsd32_fexecve_args *uap) +{ + struct image_args eargs; + int error; + + error = freebsd32_exec_copyin_args(&eargs, NULL, UIO_SYSSPACE, + uap->argv, uap->envv); + if (error == 0) { + eargs.fd = uap->fd; + error = kern_execve(td, &eargs, NULL); + } + return (error); +} + #ifdef __ia64__ static int freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, @@ -1229,6 +1246,27 @@ freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap) return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE)); } +int +freebsd32_futimesat(struct thread *td, struct freebsd32_futimesat_args *uap) +{ + struct timeval32 s32[2]; + struct timeval s[2], *sp; + int error; + + if (uap->times != NULL) { + error = copyin(uap->times, s32, sizeof(s32)); + if (error) + return (error); + CP(s32[0], s[0], tv_sec); + CP(s32[0], s[0], tv_usec); + CP(s32[1], s[1], tv_sec); + CP(s32[1], s[1], tv_usec); + sp = s; + } else + sp = NULL; + return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE, + sp, UIO_SYSSPACE)); +} int freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap) @@ -1917,6 +1955,21 @@ freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap) } int +freebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap) +{ + struct stat ub; + struct stat32 ub32; + int error; + + error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE, &ub); + if (error) + return (error); + copy_stat(&ub, &ub32); + error = copyout(&ub32, uap->buf, sizeof(ub32)); + return (error); +} + +int freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap) { struct stat sb; diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h index 77c0638..4479673 100644 --- a/sys/compat/freebsd32/freebsd32_proto.h +++ b/sys/compat/freebsd32/freebsd32_proto.h @@ -2,7 +2,7 @@ * System call prototypes. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/compat/freebsd32/freebsd32_proto.h,v 1.85 2008/03/26 15:24:01 dfr Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/compat/freebsd32/syscalls.master,v 1.99 2008/03/26 15:23:07 dfr Exp */ @@ -328,6 +328,22 @@ struct freebsd32_ftruncate_args { char lengthlo_l_[PADL_(u_int32_t)]; u_int32_t lengthlo; char lengthlo_r_[PADR_(u_int32_t)]; char lengthhi_l_[PADL_(u_int32_t)]; u_int32_t lengthhi; char lengthhi_r_[PADR_(u_int32_t)]; }; +struct freebsd32_fexecve_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char argv_l_[PADL_(u_int32_t *)]; u_int32_t * argv; char argv_r_[PADR_(u_int32_t *)]; + char envv_l_[PADL_(u_int32_t *)]; u_int32_t * envv; char envv_r_[PADR_(u_int32_t *)]; +}; +struct freebsd32_fstatat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char buf_l_[PADL_(struct stat *)]; struct stat * buf; char buf_r_[PADR_(struct stat *)]; + char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)]; +}; +struct freebsd32_futimesat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char times_l_[PADL_(struct timeval *)]; struct timeval * times; char times_r_[PADR_(struct timeval *)]; +}; int freebsd32_wait4(struct thread *, struct freebsd32_wait4_args *); int freebsd32_recvmsg(struct thread *, struct freebsd32_recvmsg_args *); int freebsd32_sendmsg(struct thread *, struct freebsd32_sendmsg_args *); @@ -385,6 +401,9 @@ int freebsd32_mmap(struct thread *, struct freebsd32_mmap_args *); int freebsd32_lseek(struct thread *, struct freebsd32_lseek_args *); int freebsd32_truncate(struct thread *, struct freebsd32_truncate_args *); int freebsd32_ftruncate(struct thread *, struct freebsd32_ftruncate_args *); +int freebsd32_fexecve(struct thread *, struct freebsd32_fexecve_args *); +int freebsd32_fstatat(struct thread *, struct freebsd32_fstatat_args *); +int freebsd32_futimesat(struct thread *, struct freebsd32_futimesat_args *); #ifdef COMPAT_43 @@ -588,6 +607,9 @@ int freebsd6_freebsd32_ftruncate(struct thread *, struct freebsd6_freebsd32_ftru #define FREEBSD32_SYS_AUE_freebsd32_lseek AUE_LSEEK #define FREEBSD32_SYS_AUE_freebsd32_truncate AUE_TRUNCATE #define FREEBSD32_SYS_AUE_freebsd32_ftruncate AUE_FTRUNCATE +#define FREEBSD32_SYS_AUE_freebsd32_fexecve AUE_FEXECVE +#define FREEBSD32_SYS_AUE_freebsd32_fstatat AUE_FSTATAT +#define FREEBSD32_SYS_AUE_freebsd32_futimesat AUE_FUTIMESAT #undef PAD_ #undef PADL_ diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h index ad24afb..2a4fd24 100644 --- a/sys/compat/freebsd32/freebsd32_syscall.h +++ b/sys/compat/freebsd32/freebsd32_syscall.h @@ -2,7 +2,7 @@ * System call numbers. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/compat/freebsd32/freebsd32_syscall.h,v 1.83 2008/03/26 15:24:02 dfr Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/compat/freebsd32/syscalls.master,v 1.99 2008/03/26 15:23:07 dfr Exp */ @@ -340,4 +340,19 @@ #define FREEBSD32_SYS_cpuset_getid 486 #define FREEBSD32_SYS_cpuset_getaffinity 487 #define FREEBSD32_SYS_cpuset_setaffinity 488 -#define FREEBSD32_SYS_MAXSYSCALL 489 +#define FREEBSD32_SYS_faccessat 489 +#define FREEBSD32_SYS_fchmodat 490 +#define FREEBSD32_SYS_fchownat 491 +#define FREEBSD32_SYS_freebsd32_fexecve 492 +#define FREEBSD32_SYS_freebsd32_fstatat 493 +#define FREEBSD32_SYS_freebsd32_futimesat 494 +#define FREEBSD32_SYS_linkat 495 +#define FREEBSD32_SYS_mkdirat 496 +#define FREEBSD32_SYS_mkfifoat 497 +#define FREEBSD32_SYS_mknodat 498 +#define FREEBSD32_SYS_openat 499 +#define FREEBSD32_SYS_readlinkat 500 +#define FREEBSD32_SYS_renameat 501 +#define FREEBSD32_SYS_symlinkat 502 +#define FREEBSD32_SYS_unlinkat 503 +#define FREEBSD32_SYS_MAXSYSCALL 504 diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c index 33af79c..b25b903 100644 --- a/sys/compat/freebsd32/freebsd32_syscalls.c +++ b/sys/compat/freebsd32/freebsd32_syscalls.c @@ -2,7 +2,7 @@ * System call names. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/compat/freebsd32/freebsd32_syscalls.c,v 1.74 2008/03/26 15:24:02 dfr Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/compat/freebsd32/syscalls.master,v 1.99 2008/03/26 15:23:07 dfr Exp */ @@ -496,4 +496,19 @@ const char *freebsd32_syscallnames[] = { "cpuset_getid", /* 486 = cpuset_getid */ "cpuset_getaffinity", /* 487 = cpuset_getaffinity */ "cpuset_setaffinity", /* 488 = cpuset_setaffinity */ + "faccessat", /* 489 = faccessat */ + "fchmodat", /* 490 = fchmodat */ + "fchownat", /* 491 = fchownat */ + "freebsd32_fexecve", /* 492 = freebsd32_fexecve */ + "freebsd32_fstatat", /* 493 = freebsd32_fstatat */ + "freebsd32_futimesat", /* 494 = freebsd32_futimesat */ + "linkat", /* 495 = linkat */ + "mkdirat", /* 496 = mkdirat */ + "mkfifoat", /* 497 = mkfifoat */ + "mknodat", /* 498 = mknodat */ + "openat", /* 499 = openat */ + "readlinkat", /* 500 = readlinkat */ + "renameat", /* 501 = renameat */ + "symlinkat", /* 502 = symlinkat */ + "unlinkat", /* 503 = unlinkat */ }; diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c index 807ebdc..ca3fae2 100644 --- a/sys/compat/freebsd32/freebsd32_sysent.c +++ b/sys/compat/freebsd32/freebsd32_sysent.c @@ -2,7 +2,7 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/compat/freebsd32/freebsd32_sysent.c,v 1.84 2008/03/26 15:24:02 dfr Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/compat/freebsd32/syscalls.master,v 1.99 2008/03/26 15:23:07 dfr Exp */ @@ -527,4 +527,19 @@ struct sysent freebsd32_sysent[] = { { AS(cpuset_getid_args), (sy_call_t *)cpuset_getid, AUE_NULL, NULL, 0, 0 }, /* 486 = cpuset_getid */ { AS(cpuset_getaffinity_args), (sy_call_t *)cpuset_getaffinity, AUE_NULL, NULL, 0, 0 }, /* 487 = cpuset_getaffinity */ { AS(cpuset_setaffinity_args), (sy_call_t *)cpuset_setaffinity, AUE_NULL, NULL, 0, 0 }, /* 488 = cpuset_setaffinity */ + { AS(faccessat_args), (sy_call_t *)faccessat, AUE_FACCESSAT, NULL, 0, 0 }, /* 489 = faccessat */ + { AS(fchmodat_args), (sy_call_t *)fchmodat, AUE_FCHMODAT, NULL, 0, 0 }, /* 490 = fchmodat */ + { AS(fchownat_args), (sy_call_t *)fchownat, AUE_FCHOWNAT, NULL, 0, 0 }, /* 491 = fchownat */ + { AS(freebsd32_fexecve_args), (sy_call_t *)freebsd32_fexecve, AUE_FEXECVE, NULL, 0, 0 }, /* 492 = freebsd32_fexecve */ + { AS(freebsd32_fstatat_args), (sy_call_t *)freebsd32_fstatat, AUE_FSTATAT, NULL, 0, 0 }, /* 493 = freebsd32_fstatat */ + { AS(freebsd32_futimesat_args), (sy_call_t *)freebsd32_futimesat, AUE_FUTIMESAT, NULL, 0, 0 }, /* 494 = freebsd32_futimesat */ + { AS(linkat_args), (sy_call_t *)linkat, AUE_LINKAT, NULL, 0, 0 }, /* 495 = linkat */ + { AS(mkdirat_args), (sy_call_t *)mkdirat, AUE_MKDIRAT, NULL, 0, 0 }, /* 496 = mkdirat */ + { AS(mkfifoat_args), (sy_call_t *)mkfifoat, AUE_MKFIFOAT, NULL, 0, 0 }, /* 497 = mkfifoat */ + { AS(mknodat_args), (sy_call_t *)mknodat, AUE_MKNODAT, NULL, 0, 0 }, /* 498 = mknodat */ + { AS(openat_args), (sy_call_t *)openat, AUE_OPENAT_RWTC, NULL, 0, 0 }, /* 499 = openat */ + { AS(readlinkat_args), (sy_call_t *)readlinkat, AUE_READLINKAT, NULL, 0, 0 }, /* 500 = readlinkat */ + { AS(renameat_args), (sy_call_t *)renameat, AUE_RENAMEAT, NULL, 0, 0 }, /* 501 = renameat */ + { AS(symlinkat_args), (sy_call_t *)symlinkat, AUE_SYMLINKAT, NULL, 0, 0 }, /* 502 = symlinkat */ + { AS(unlinkat_args), (sy_call_t *)unlinkat, AUE_UNLINKAT, NULL, 0, 0 }, /* 503 = unlinkat */ }; diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index e4d88c3..e2bdcd6 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -810,3 +810,33 @@ 488 AUE_NULL NOPROTO { int cpuset_setaffinity(cpulevel_t level, \ cpuwhich_t which, id_t id, size_t cpusetsize, \ const cpuset_t *mask); } +489 AUE_FACCESSAT NOPROTO { int faccessat(int fd, char *path, int mode, \ + int flag); } +490 AUE_FCHMODAT NOPROTO { int fchmodat(int fd, const char *path, \ + mode_t mode, int flag); } +491 AUE_FCHOWNAT NOPROTO { int fchownat(int fd, char *path, uid_t uid, \ + gid_t gid, int flag); } +492 AUE_FEXECVE STD { int freebsd32_fexecve(int fd, \ + u_int32_t *argv, u_int32_t *envv); } +493 AUE_FSTATAT STD { int freebsd32_fstatat(int fd, char *path, \ + struct stat *buf, int flag); } +494 AUE_FUTIMESAT STD { int freebsd32_futimesat(int fd, char *path, \ + struct timeval *times); } +495 AUE_LINKAT NOPROTO { int linkat(int fd1, char *path1, int fd2, \ + char *path2, int flag); } +496 AUE_MKDIRAT NOPROTO { int mkdirat(int fd, char *path, \ + mode_t mode); } +497 AUE_MKFIFOAT NOPROTO { int mkfifoat(int fd, char *path, \ + mode_t mode); } +498 AUE_MKNODAT NOPROTO { int mknodat(int fd, char *path, \ + mode_t mode, dev_t dev); } +499 AUE_OPENAT_RWTC NOPROTO { int openat(int fd, char *path, int flag, \ + mode_t mode); } +500 AUE_READLINKAT NOPROTO { int readlinkat(int fd, char *path, char *buf, \ + size_t bufsize); } +501 AUE_RENAMEAT NOPROTO { int renameat(int oldfd, char *old, int newfd, \ + const char *new); } +502 AUE_SYMLINKAT NOPROTO { int symlinkat(char *path1, int fd, \ + char *path2); } +503 AUE_UNLINKAT NOPROTO { int unlinkat(int fd, char *path, \ + int flag); } diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c index 86586b2..7ae41ae 100644 --- a/sys/compat/linprocfs/linprocfs.c +++ b/sys/compat/linprocfs/linprocfs.c @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD: src/sys/compat/linprocfs/linprocfs.c,v 1.118 2008/01/10 01:1 #include #include #include +#include #include #include #include diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c index cb2f3c9..6cfe5c9 100644 --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -67,6 +67,7 @@ __FBSDID("$FreeBSD: src/sys/compat/linux/linux_file.c,v 1.110 2008/03/26 15:23:0 #include #endif #include +#include int linux_creat(struct thread *td, struct linux_creat_args *args) @@ -88,7 +89,7 @@ linux_creat(struct thread *td, struct linux_creat_args *args) static int -linux_common_open(struct thread *td, char *path, int l_flags, int mode, int openat) +linux_common_open(struct thread *td, int dirfd, char *path, int l_flags, int mode) { struct proc *p = td->td_proc; struct file *fp; @@ -130,7 +131,10 @@ linux_common_open(struct thread *td, char *path, int l_flags, int mode, int open bsd_flags |= O_NOFOLLOW; /* XXX LINUX_O_NOATIME: unable to be easily implemented. */ - error = kern_open(td, path, UIO_SYSSPACE, bsd_flags, mode); + if (dirfd != -1) + error = kern_openat(td, dirfd, path, UIO_SYSSPACE, bsd_flags, mode); + else + error = kern_open(td, path, UIO_SYSSPACE, bsd_flags, mode); if (!error) { fd = td->td_retval[0]; /* @@ -172,122 +176,27 @@ linux_common_open(struct thread *td, char *path, int l_flags, int mode, int open if (ldebug(open)) printf(LMSG("open returns error %d"), error); #endif - if (!openat) - LFREEPATH(path); - return error; -} - -/* - * common code for linux *at set of syscalls - * - * works like this: - * if filename is absolute - * ignore dirfd - * else - * if dirfd == AT_FDCWD - * return CWD/filename - * else - * return DIRFD/filename - */ -static int -linux_at(struct thread *td, int dirfd, char *filename, char **newpath, char **freebuf) -{ - struct file *fp; - int error = 0, vfslocked; - struct vnode *dvp; - struct filedesc *fdp = td->td_proc->p_fd; - char *fullpath = "unknown"; - char *freepath = NULL; - - /* don't do anything if the pathname is absolute */ - if (*filename == '/') { - *newpath= filename; - return (0); - } - - /* check for AT_FDWCD */ - if (dirfd == LINUX_AT_FDCWD) { - FILEDESC_SLOCK(fdp); - dvp = fdp->fd_cdir; - vref(dvp); - FILEDESC_SUNLOCK(fdp); - } else { - error = fget(td, dirfd, &fp); - if (error) - return (error); - dvp = fp->f_vnode; - /* only a dir can be dfd */ - if (dvp->v_type != VDIR) { - fdrop(fp, td); - return (ENOTDIR); - } - vref(dvp); - fdrop(fp, td); - } - - /* - * XXXRW: This is bogus, as vn_fullpath() returns only an advisory - * file path, and may fail in several common situations, including - * for file systmes that don't use the name cache, and if the entry - * for the file falls out of the name cache. We should implement - * openat() in the FreeBSD native system call layer properly (using a - * requested starting directory), and have Linux and other ABIs wrap - * the native implementation. - */ - error = vn_fullpath(td, dvp, &fullpath, &freepath); - if (!error) { - *newpath = malloc(strlen(fullpath) + strlen(filename) + 2, M_TEMP, M_WAITOK | M_ZERO); - *freebuf = freepath; - sprintf(*newpath, "%s/%s", fullpath, filename); - } else { - *newpath = NULL; - } - vfslocked = VFS_LOCK_GIANT(dvp->v_mount); - vrele(dvp); - VFS_UNLOCK_GIANT(vfslocked); - return (error); + LFREEPATH(path); + return (error); } int linux_openat(struct thread *td, struct linux_openat_args *args) { - char *newpath, *oldpath, *freebuf, *path; - int error; + char *path; + int dfd; - oldpath = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); - error = copyinstr(args->filename, oldpath, MAXPATHLEN, NULL); - if (error) { - free(oldpath, M_TEMP); - return (error); - } + dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; + if (args->flags & LINUX_O_CREAT) + LCONVPATH_AT(td, args->filename, &path, 1, dfd); + else + LCONVPATH_AT(td, args->filename, &path, 0, dfd); #ifdef DEBUG if (ldebug(openat)) printf(ARGS(openat, "%i, %s, 0x%x, 0x%x"), args->dfd, - oldpath, args->flags, args->mode); -#endif - newpath = freebuf = NULL; - error = linux_at(td, args->dfd, oldpath, &newpath, &freebuf); - if (error == 0) { -#ifdef DEBUG - if (ldebug(openat)) - printf(LMSG("newpath: %s"), newpath); + path, args->flags, args->mode); #endif - if (args->flags & LINUX_O_CREAT) - LCONVPATH_SEG(td, newpath, &path, 1, UIO_SYSSPACE); - else - LCONVPATH_SEG(td, newpath, &path, 0, UIO_SYSSPACE); - } - if (freebuf) - free(freebuf, M_TEMP); - if (*oldpath != '/') - free(newpath, M_TEMP); - if (error == 0) { - error = linux_common_open(td, path, args->flags, - args->mode, 1); - LFREEPATH(path); - } - free(oldpath, M_TEMP); - return (error); + return (linux_common_open(td, dfd, path, args->flags, args->mode)); } int @@ -306,7 +215,7 @@ linux_open(struct thread *td, struct linux_open_args *args) path, args->flags, args->mode); #endif - return linux_common_open(td, path, args->flags, args->mode, 0); + return (linux_common_open(td, -1, path, args->flags, args->mode)); } int @@ -656,6 +565,31 @@ linux_access(struct thread *td, struct linux_access_args *args) } int +linux_faccessat(struct thread *td, struct linux_faccessat_args *args) +{ + char *path; + int error, dfd; + + /* linux convention */ + if (args->mode & ~(F_OK | X_OK | W_OK | R_OK)) + return (EINVAL); + + dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; + LCONVPATHEXIST_AT(td, args->filename, &path, dfd); + +#ifdef DEBUG + if (ldebug(access)) + printf(ARGS(access, "%s, %d"), path, args->mode); +#endif + + error = kern_accessat(td, dfd, path, UIO_SYSSPACE, 0 /* XXX */, + args->mode); + LFREEPATH(path); + + return (error); +} + +int linux_unlink(struct thread *td, struct linux_unlink_args *args) { char *path; @@ -680,6 +614,37 @@ linux_unlink(struct thread *td, struct linux_unlink_args *args) } int +linux_unlinkat(struct thread *td, struct linux_unlinkat_args *args) +{ + char *path; + int error, dfd; + struct stat st; + + if (args->flag & ~LINUX_AT_REMOVEDIR) + return (EINVAL); + + dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; + LCONVPATHEXIST_AT(td, args->pathname, &path, dfd); + +#ifdef DEBUG + if (ldebug(unlinkat)) + printf(ARGS(unlinkat, "%s"), path); +#endif + + if (args->flag & LINUX_AT_REMOVEDIR) + error = kern_rmdirat(td, dfd, path, UIO_SYSSPACE); + else + error = kern_unlinkat(td, dfd, path, UIO_SYSSPACE); + if (error == EPERM && !(args->flag & LINUX_AT_REMOVEDIR)) { + /* Introduce POSIX noncompliant behaviour of Linux */ + if (kern_statat(td, AT_SYMLINK_NOFOLLOW, dfd, path, + UIO_SYSSPACE, &st) == 0 && S_ISDIR(st.st_mode)) + error = EISDIR; + } + LFREEPATH(path); + return (error); +} +int linux_chdir(struct thread *td, struct linux_chdir_args *args) { char *path; @@ -714,6 +679,25 @@ linux_chmod(struct thread *td, struct linux_chmod_args *args) } int +linux_fchmodat(struct thread *td, struct linux_fchmodat_args *args) +{ + char *path; + int error, dfd; + + dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; + LCONVPATHEXIST_AT(td, args->filename, &path, dfd); + +#ifdef DEBUG + if (ldebug(fchmodat)) + printf(ARGS(fchmodat, "%s, %d"), path, args->mode); +#endif + + error = kern_chmodat(td, dfd, path, UIO_SYSSPACE, args->mode); + LFREEPATH(path); + return (error); +} + +int linux_mkdir(struct thread *td, struct linux_mkdir_args *args) { char *path; @@ -731,6 +715,24 @@ linux_mkdir(struct thread *td, struct linux_mkdir_args *args) } int +linux_mkdirat(struct thread *td, struct linux_mkdirat_args *args) +{ + char *path; + int error, dfd; + + dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; + LCONVPATHCREAT_AT(td, args->pathname, &path, dfd); + +#ifdef DEBUG + if (ldebug(mkdirat)) + printf(ARGS(mkdirat, "%s, %d"), path, args->mode); +#endif + error = kern_mkdirat(td, dfd, path, UIO_SYSSPACE, args->mode); + LFREEPATH(path); + return (error); +} + +int linux_rmdir(struct thread *td, struct linux_rmdir_args *args) { char *path; @@ -755,7 +757,7 @@ linux_rename(struct thread *td, struct linux_rename_args *args) LCONVPATHEXIST(td, args->from, &from); /* Expand LCONVPATHCREATE so that `from' can be freed on errors */ - error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1); + error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD); if (to == NULL) { LFREEPATH(from); return (error); @@ -772,6 +774,32 @@ linux_rename(struct thread *td, struct linux_rename_args *args) } int +linux_renameat(struct thread *td, struct linux_renameat_args *args) +{ + char *from, *to; + int error, olddfd, newdfd; + + olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd; + newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd; + LCONVPATHEXIST_AT(td, args->oldname, &from, olddfd); + /* Expand LCONVPATHCREATE so that `from' can be freed on errors */ + error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, newdfd); + if (to == NULL) { + LFREEPATH(from); + return (error); + } + +#ifdef DEBUG + if (ldebug(renameat)) + printf(ARGS(renameat, "%s, %s"), from, to); +#endif + error = kern_renameat(td, olddfd, from, newdfd, to, UIO_SYSSPACE); + LFREEPATH(from); + LFREEPATH(to); + return (error); +} + +int linux_symlink(struct thread *td, struct linux_symlink_args *args) { char *path, *to; @@ -779,7 +807,7 @@ linux_symlink(struct thread *td, struct linux_symlink_args *args) LCONVPATHEXIST(td, args->path, &path); /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ - error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1); + error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD); if (to == NULL) { LFREEPATH(path); return (error); @@ -796,6 +824,32 @@ linux_symlink(struct thread *td, struct linux_symlink_args *args) } int +linux_symlinkat(struct thread *td, struct linux_symlinkat_args *args) +{ + char *path, *to; + int error, dfd; + + dfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd; + LCONVPATHEXIST_AT(td, args->oldname, &path, dfd); + /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ + error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, dfd); + if (to == NULL) { + LFREEPATH(path); + return (error); + } + +#ifdef DEBUG + if (ldebug(symlinkat)) + printf(ARGS(symlinkat, "%s, %s"), path, to); +#endif + + error = kern_symlinkat(td, path, dfd, to, UIO_SYSSPACE); + LFREEPATH(path); + LFREEPATH(to); + return (error); +} + +int linux_readlink(struct thread *td, struct linux_readlink_args *args) { char *name; @@ -815,6 +869,26 @@ linux_readlink(struct thread *td, struct linux_readlink_args *args) } int +linux_readlinkat(struct thread *td, struct linux_readlinkat_args *args) +{ + char *name; + int error, dfd; + + dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; + LCONVPATHEXIST_AT(td, args->path, &name, dfd); + +#ifdef DEBUG + if (ldebug(readlinkat)) + printf(ARGS(readlinkat, "%s, %p, %d"), name, (void *)args->buf, + args->bufsiz); +#endif + + error = kern_readlinkat(td, dfd, name, UIO_SYSSPACE, args->buf, + UIO_USERSPACE, args->bufsiz); + LFREEPATH(name); + return (error); +} +int linux_truncate(struct thread *td, struct linux_truncate_args *args) { char *path; @@ -854,7 +928,7 @@ linux_link(struct thread *td, struct linux_link_args *args) LCONVPATHEXIST(td, args->path, &path); /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ - error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1); + error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD); if (to == NULL) { LFREEPATH(path); return (error); @@ -871,6 +945,41 @@ linux_link(struct thread *td, struct linux_link_args *args) } int +linux_linkat(struct thread *td, struct linux_linkat_args *args) +{ + char *path, *to; + int error, olddfd, newdfd; + + /* + * They really introduced flags argument which is forbidden to + * use. + */ + if (args->flags != 0) + return (EINVAL); + + olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd; + newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd; + LCONVPATHEXIST_AT(td, args->oldname, &path, olddfd); + /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ + error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, newdfd); + if (to == NULL) { + LFREEPATH(path); + return (error); + } + +#ifdef DEBUG + if (ldebug(linkat)) + printf(ARGS(linkat, "%i, %s, %i, %s, %i"), args->olddfd, path, + args->newdfd, to, args->flags); +#endif + + error = kern_linkat(td, olddfd, newdfd, path, to, UIO_SYSSPACE, FOLLOW); + LFREEPATH(path); + LFREEPATH(to); + return (error); +} + +int linux_fdatasync(td, uap) struct thread *td; struct linux_fdatasync_args *uap; @@ -1338,6 +1447,31 @@ linux_chown(struct thread *td, struct linux_chown_args *args) } int +linux_fchownat(struct thread *td, struct linux_fchownat_args *args) +{ + char *path; + int error, dfd, follow; + + if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW) + return (EINVAL); + + dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; + LCONVPATHEXIST_AT(td, args->filename, &path, dfd); + +#ifdef DEBUG + if (ldebug(fchownat)) + printf(ARGS(fchownat, "%s, %d, %d"), path, args->uid, args->gid); +#endif + + follow = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) == 0 ? 0 : + AT_SYMLINK_NOFOLLOW; + error = kern_fchownat(td, dfd, path, UIO_SYSSPACE, args->uid, args->gid, + follow); + LFREEPATH(path); + return (error); +} + +int linux_lchown(struct thread *td, struct linux_lchown_args *args) { char *path; diff --git a/sys/compat/linux/linux_file.h b/sys/compat/linux/linux_file.h new file mode 100644 index 0000000..e229cb6 --- /dev/null +++ b/sys/compat/linux/linux_file.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2007 Roman Divacky + * All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _LINUX_FILE_H_ +#define _LINUX_FILE_H_ + +#define LINUX_AT_FDCWD -100 +#define LINUX_AT_SYMLINK_NOFOLLOW 0x100 +#define LINUX_AT_REMOVEDIR 0x200 + +#endif /* !_LINUX_FILE_H_ */ diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index dbf032d..e08646a 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -87,6 +87,7 @@ __FBSDID("$FreeBSD: src/sys/compat/linux/linux_misc.c,v 1.219 2008/03/25 13:20:5 #include #endif +#include #include #include #include @@ -836,6 +837,39 @@ linux_utimes(struct thread *td, struct linux_utimes_args *args) LFREEPATH(fname); return (error); } + +int +linux_futimesat(struct thread *td, struct linux_futimesat_args *args) +{ + l_timeval ltv[2]; + struct timeval tv[2], *tvp = NULL; + char *fname; + int error, dfd; + + dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; + LCONVPATHEXIST_AT(td, args->filename, &fname, dfd); + +#ifdef DEBUG + if (ldebug(futimesat)) + printf(ARGS(futimesat, "%s, *"), fname); +#endif + + if (args->utimes != NULL) { + if ((error = copyin(args->utimes, ltv, sizeof ltv))) { + LFREEPATH(fname); + return (error); + } + tv[0].tv_sec = ltv[0].tv_sec; + tv[0].tv_usec = ltv[0].tv_usec; + tv[1].tv_sec = ltv[1].tv_sec; + tv[1].tv_usec = ltv[1].tv_usec; + tvp = tv; + } + + error = kern_utimesat(td, dfd, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE); + LFREEPATH(fname); + return (error); +} #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ #define __WCLONE 0x80000000 @@ -963,6 +997,56 @@ linux_mknod(struct thread *td, struct linux_mknod_args *args) case S_IFREG: error = kern_open(td, path, UIO_SYSSPACE, O_WRONLY | O_CREAT | O_TRUNC, args->mode); + if (error == 0) + kern_close(td, td->td_retval[0]); + break; + + default: + error = EINVAL; + break; + } + LFREEPATH(path); + return (error); +} + +int +linux_mknodat(struct thread *td, struct linux_mknodat_args *args) +{ + char *path; + int error, dfd; + + dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; + LCONVPATHCREAT_AT(td, args->filename, &path, dfd); + +#ifdef DEBUG + if (ldebug(mknodat)) + printf(ARGS(mknodat, "%s, %d, %d"), path, args->mode, args->dev); +#endif + + switch (args->mode & S_IFMT) { + case S_IFIFO: + case S_IFSOCK: + error = kern_mkfifoat(td, dfd, path, UIO_SYSSPACE, args->mode); + break; + + case S_IFCHR: + case S_IFBLK: + error = kern_mknodat(td, dfd, path, UIO_SYSSPACE, args->mode, + args->dev); + break; + + case S_IFDIR: + error = EPERM; + break; + + case 0: + args->mode |= S_IFREG; + /* FALLTHROUGH */ + case S_IFREG: + error = kern_openat(td, dfd, path, UIO_SYSSPACE, + O_WRONLY | O_CREAT | O_TRUNC, args->mode); + if (error == 0) + kern_close(td, td->td_retval[0]); break; default: diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c index 603fea2..f0cb420 100644 --- a/sys/compat/linux/linux_stats.c +++ b/sys/compat/linux/linux_stats.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD: src/sys/compat/linux/linux_stats.c,v 1.90 2008/01/05 12:36:3 #endif #include +#include #include @@ -114,9 +115,10 @@ translate_fd_major_minor(struct thread *td, int fd, struct stat *buf) } static void -translate_path_major_minor(struct thread *td, char *path, struct stat *buf) +translate_path_major_minor_at(struct thread *td, char *path, + struct stat *buf, int dfd) { - struct proc *p = td->td_proc; + struct proc *p = td->td_proc; struct filedesc *fdp = p->p_fd; int fd; int temp; @@ -124,7 +126,7 @@ translate_path_major_minor(struct thread *td, char *path, struct stat *buf) if (!S_ISCHR(buf->st_mode) && !S_ISBLK(buf->st_mode)) return; temp = td->td_retval[0]; - if (kern_open(td, path, UIO_SYSSPACE, O_RDONLY, 0) != 0) + if (kern_openat(td, dfd, path, UIO_SYSSPACE, O_RDONLY, 0) != 0) return; fd = td->td_retval[0]; td->td_retval[0] = temp; @@ -132,6 +134,12 @@ translate_path_major_minor(struct thread *td, char *path, struct stat *buf) fdclose(fdp, fdp->fd_ofiles[fd], fd, td); } +static inline void +translate_path_major_minor(struct thread *td, char *path, struct stat *buf) +{ + translate_path_major_minor_at(td, path, buf, AT_FDCWD); +} + static int newstat_copyout(struct stat *buf, void *ubuf) { @@ -581,4 +589,33 @@ linux_fstat64(struct thread *td, struct linux_fstat64_args *args) return (error); } +int +linux_fstatat64(struct thread *td, struct linux_fstatat64_args *args) +{ + char *path; + int error, dfd, flag; + struct stat buf; + + if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW) + return (EINVAL); + flag = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) ? + AT_SYMLINK_NOFOLLOW : 0; + + dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; + LCONVPATHEXIST_AT(td, args->pathname, &path, dfd); + +#ifdef DEBUG + if (ldebug(fstatat64)) + printf(ARGS(fstatat64, "%i, %s, %i"), args->dfd, path, args->flag); +#endif + + error = kern_statat(td, flag, dfd, path, UIO_SYSSPACE, &buf); + translate_path_major_minor_at(td, args->pathname, &buf, dfd); + if (!error) + error = stat64_copyout(&buf, args->statbuf); + LFREEPATH(path); + + return (error); +} + #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ diff --git a/sys/compat/linux/linux_uid16.c b/sys/compat/linux/linux_uid16.c index 8df1439..c31da68 100644 --- a/sys/compat/linux/linux_uid16.c +++ b/sys/compat/linux/linux_uid16.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD: src/sys/compat/linux/linux_uid16.c,v 1.22 2007/06/12 00:11:5 #include "opt_compat.h" +#include #include #include #include diff --git a/sys/compat/linux/linux_util.c b/sys/compat/linux/linux_util.c index 9b779da..aaa9ef9 100644 --- a/sys/compat/linux/linux_util.c +++ b/sys/compat/linux/linux_util.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD: src/sys/compat/linux/linux_util.c,v 1.32 2007/02/24 16:49:24 #include #include +#include #include #include #include @@ -65,16 +66,17 @@ const char linux_emul_path[] = "/compat/linux"; * named file, i.e. we check if the directory it should be in exists. */ int -linux_emul_convpath(td, path, pathseg, pbuf, cflag) +linux_emul_convpath(td, path, pathseg, pbuf, cflag, dfd) struct thread *td; - char *path; + const char *path; enum uio_seg pathseg; char **pbuf; int cflag; + int dfd; { return (kern_alternate_path(td, linux_emul_path, path, pathseg, pbuf, - cflag)); + cflag, dfd)); } void diff --git a/sys/compat/linux/linux_util.h b/sys/compat/linux/linux_util.h index a9e5bca..1e4cbaf 100644 --- a/sys/compat/linux/linux_util.h +++ b/sys/compat/linux/linux_util.h @@ -51,23 +51,25 @@ extern const char linux_emul_path[]; -int linux_emul_convpath(struct thread *, char *, enum uio_seg, char **, int); +int linux_emul_convpath(struct thread *, const char *, enum uio_seg, char **, int, int); -#define LCONVPATH_SEG(td, upath, pathp, i, seg) \ +#define LCONVPATH_AT(td, upath, pathp, i, dfd) \ do { \ int _error; \ \ - _error = linux_emul_convpath(td, upath, seg, \ - pathp, i); \ + _error = linux_emul_convpath(td, upath, UIO_USERSPACE, \ + pathp, i, dfd); \ if (*(pathp) == NULL) \ return (_error); \ } while (0) #define LCONVPATH(td, upath, pathp, i) \ - LCONVPATH_SEG(td, upath, pathp, i, UIO_USERSPACE) + LCONVPATH_AT(td, upath, pathp, i, AT_FDCWD) #define LCONVPATHEXIST(td, upath, pathp) LCONVPATH(td, upath, pathp, 0) +#define LCONVPATHEXIST_AT(td, upath, pathp, dfd) LCONVPATH_AT(td, upath, pathp, 0, dfd) #define LCONVPATHCREAT(td, upath, pathp) LCONVPATH(td, upath, pathp, 1) +#define LCONVPATHCREAT_AT(td, upath, pathp, dfd) LCONVPATH_AT(td, upath, pathp, 1, dfd) #define LFREEPATH(path) free(path, M_TEMP) #define DUMMY(s) \ diff --git a/sys/compat/pecoff/imgact_pecoff.c b/sys/compat/pecoff/imgact_pecoff.c index 13f66a7..b4f557f 100644 --- a/sys/compat/pecoff/imgact_pecoff.c +++ b/sys/compat/pecoff/imgact_pecoff.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD: src/sys/compat/pecoff/imgact_pecoff.c,v 1.43 2008/01/13 14:4 #include #include +#include #include #include #include diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c index 5190a98..3036e45 100644 --- a/sys/compat/svr4/svr4_sysvec.c +++ b/sys/compat/svr4/svr4_sysvec.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD: src/sys/compat/svr4/svr4_sysvec.c,v 1.43 2008/03/12 22:17:06 #include #include #include +#include #include #include #include @@ -257,7 +258,7 @@ svr4_emul_find(struct thread *td, char *path, enum uio_seg pathseg, { return (kern_alternate_path(td, svr4_emul_path, path, pathseg, pbuf, - create)); + create, AT_FDCWD)); } static int diff --git a/sys/fs/coda/coda_vfsops.c b/sys/fs/coda/coda_vfsops.c index 45ad324..4fe36c5 100644 --- a/sys/fs/coda/coda_vfsops.c +++ b/sys/fs/coda/coda_vfsops.c @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD: src/sys/fs/coda/coda_vfsops.c,v 1.79 2008/02/10 11:18:12 rwa #include #include #include +#include #include #include #include diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c index f0e7368..798e01a 100644 --- a/sys/fs/msdosfs/msdosfs_vfsops.c +++ b/sys/fs/msdosfs/msdosfs_vfsops.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c index 338cb1e..9efee91 100644 --- a/sys/fs/nullfs/null_vfsops.c +++ b/sys/fs/nullfs/null_vfsops.c @@ -42,6 +42,7 @@ #include #include +#include #include #include #include diff --git a/sys/fs/unionfs/union_vfsops.c b/sys/fs/unionfs/union_vfsops.c index eb5a393..50fd667 100644 --- a/sys/fs/unionfs/union_vfsops.c +++ b/sys/fs/unionfs/union_vfsops.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include diff --git a/sys/i386/ibcs2/ibcs2_util.c b/sys/i386/ibcs2/ibcs2_util.c index 512c309..6e21c45 100644 --- a/sys/i386/ibcs2/ibcs2_util.c +++ b/sys/i386/ibcs2/ibcs2_util.c @@ -32,6 +32,7 @@ #include __FBSDID("$FreeBSD: src/sys/i386/ibcs2/ibcs2_util.c,v 1.19 2005/02/07 22:02:18 jhb Exp $"); +#include #include #include #include @@ -55,5 +56,5 @@ ibcs2_emul_find(struct thread *td, char *path, enum uio_seg pathseg, { return (kern_alternate_path(td, ibcs2_emul_path, path, pathseg, pbuf, - cflag)); + cflag, AT_FDCWD)); } diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h index 3e3140f..1515489 100644 --- a/sys/i386/linux/linux.h +++ b/sys/i386/linux/linux.h @@ -550,8 +550,6 @@ int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h); #define LINUX_F_WRLCK 1 #define LINUX_F_UNLCK 2 -#define LINUX_AT_FDCWD -100 - /* * mount flags */ diff --git a/sys/i386/linux/linux_dummy.c b/sys/i386/linux/linux_dummy.c index 6c105c0..55e4c7a 100644 --- a/sys/i386/linux/linux_dummy.c +++ b/sys/i386/linux/linux_dummy.c @@ -87,18 +87,6 @@ DUMMY(inotify_init); DUMMY(inotify_add_watch); DUMMY(inotify_rm_watch); DUMMY(migrate_pages); -DUMMY(mkdirat); -DUMMY(mknodat); -DUMMY(fchownat); -DUMMY(futimesat); -DUMMY(fstatat64); -DUMMY(unlinkat); -DUMMY(renameat); -DUMMY(linkat); -DUMMY(symlinkat); -DUMMY(readlinkat); -DUMMY(fchmodat); -DUMMY(faccessat); DUMMY(pselect6); DUMMY(ppoll); DUMMY(unshare); diff --git a/sys/i386/linux/linux_proto.h b/sys/i386/linux/linux_proto.h index 14c4e59..281c9ff 100644 --- a/sys/i386/linux/linux_proto.h +++ b/sys/i386/linux/linux_proto.h @@ -2,7 +2,7 @@ * System call prototypes. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/i386/linux/linux_proto.h,v 1.96 2008/03/16 16:29:37 rdivacky Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.90 2008/03/16 16:27:44 rdivacky Exp */ @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -905,45 +906,77 @@ struct linux_migrate_pages_args { }; struct linux_openat_args { char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; - char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)]; + char filename_l_[PADL_(const char *)]; const char * filename; char filename_r_[PADR_(const char *)]; char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)]; }; struct linux_mkdirat_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char pathname_l_[PADL_(const char *)]; const char * pathname; char pathname_r_[PADR_(const char *)]; + char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)]; }; struct linux_mknodat_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char filename_l_[PADL_(const char *)]; const char * filename; char filename_r_[PADR_(const char *)]; + char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)]; + char dev_l_[PADL_(l_uint)]; l_uint dev; char dev_r_[PADR_(l_uint)]; }; struct linux_fchownat_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char filename_l_[PADL_(const char *)]; const char * filename; char filename_r_[PADR_(const char *)]; + char uid_l_[PADL_(l_uid16_t)]; l_uid16_t uid; char uid_r_[PADR_(l_uid16_t)]; + char gid_l_[PADL_(l_gid16_t)]; l_gid16_t gid; char gid_r_[PADR_(l_gid16_t)]; + char flag_l_[PADL_(l_int)]; l_int flag; char flag_r_[PADR_(l_int)]; }; struct linux_futimesat_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)]; + char utimes_l_[PADL_(struct l_timeval *)]; struct l_timeval * utimes; char utimes_r_[PADR_(struct l_timeval *)]; }; struct linux_fstatat64_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char pathname_l_[PADL_(char *)]; char * pathname; char pathname_r_[PADR_(char *)]; + char statbuf_l_[PADL_(struct l_stat64 *)]; struct l_stat64 * statbuf; char statbuf_r_[PADR_(struct l_stat64 *)]; + char flag_l_[PADL_(l_int)]; l_int flag; char flag_r_[PADR_(l_int)]; }; struct linux_unlinkat_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char pathname_l_[PADL_(const char *)]; const char * pathname; char pathname_r_[PADR_(const char *)]; + char flag_l_[PADL_(l_int)]; l_int flag; char flag_r_[PADR_(l_int)]; }; struct linux_renameat_args { - register_t dummy; + char olddfd_l_[PADL_(l_int)]; l_int olddfd; char olddfd_r_[PADR_(l_int)]; + char oldname_l_[PADL_(const char *)]; const char * oldname; char oldname_r_[PADR_(const char *)]; + char newdfd_l_[PADL_(l_int)]; l_int newdfd; char newdfd_r_[PADR_(l_int)]; + char newname_l_[PADL_(const char *)]; const char * newname; char newname_r_[PADR_(const char *)]; }; struct linux_linkat_args { - register_t dummy; + char olddfd_l_[PADL_(l_int)]; l_int olddfd; char olddfd_r_[PADR_(l_int)]; + char oldname_l_[PADL_(const char *)]; const char * oldname; char oldname_r_[PADR_(const char *)]; + char newdfd_l_[PADL_(l_int)]; l_int newdfd; char newdfd_r_[PADR_(l_int)]; + char newname_l_[PADL_(const char *)]; const char * newname; char newname_r_[PADR_(const char *)]; + char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; }; struct linux_symlinkat_args { - register_t dummy; + char oldname_l_[PADL_(const char *)]; const char * oldname; char oldname_r_[PADR_(const char *)]; + char newdfd_l_[PADL_(l_int)]; l_int newdfd; char newdfd_r_[PADR_(l_int)]; + char newname_l_[PADL_(const char *)]; const char * newname; char newname_r_[PADR_(const char *)]; }; struct linux_readlinkat_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)]; + char bufsiz_l_[PADL_(l_int)]; l_int bufsiz; char bufsiz_r_[PADR_(l_int)]; }; struct linux_fchmodat_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char filename_l_[PADL_(const char *)]; const char * filename; char filename_r_[PADR_(const char *)]; + char mode_l_[PADL_(l_mode_t)]; l_mode_t mode; char mode_r_[PADR_(l_mode_t)]; }; struct linux_faccessat_args { - register_t dummy; + char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)]; + char filename_l_[PADL_(const char *)]; const char * filename; char filename_r_[PADR_(const char *)]; + char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)]; }; struct linux_pselect6_args { register_t dummy; @@ -1433,18 +1466,18 @@ int linux_unshare(struct thread *, struct linux_unshare_args *); #define LINUX_SYS_AUE_linux_inotify_rm_watch AUE_NULL #define LINUX_SYS_AUE_linux_migrate_pages AUE_NULL #define LINUX_SYS_AUE_linux_openat AUE_OPEN_RWTC -#define LINUX_SYS_AUE_linux_mkdirat AUE_NULL -#define LINUX_SYS_AUE_linux_mknodat AUE_NULL -#define LINUX_SYS_AUE_linux_fchownat AUE_NULL -#define LINUX_SYS_AUE_linux_futimesat AUE_NULL -#define LINUX_SYS_AUE_linux_fstatat64 AUE_NULL -#define LINUX_SYS_AUE_linux_unlinkat AUE_NULL -#define LINUX_SYS_AUE_linux_renameat AUE_NULL -#define LINUX_SYS_AUE_linux_linkat AUE_NULL -#define LINUX_SYS_AUE_linux_symlinkat AUE_NULL -#define LINUX_SYS_AUE_linux_readlinkat AUE_NULL -#define LINUX_SYS_AUE_linux_fchmodat AUE_NULL -#define LINUX_SYS_AUE_linux_faccessat AUE_NULL +#define LINUX_SYS_AUE_linux_mkdirat AUE_MKDIRAT +#define LINUX_SYS_AUE_linux_mknodat AUE_MKNODAT +#define LINUX_SYS_AUE_linux_fchownat AUE_FCHOWNAT +#define LINUX_SYS_AUE_linux_futimesat AUE_FUTIMESAT +#define LINUX_SYS_AUE_linux_fstatat64 AUE_FSTATAT +#define LINUX_SYS_AUE_linux_unlinkat AUE_UNLINKAT +#define LINUX_SYS_AUE_linux_renameat AUE_RENAMEAT +#define LINUX_SYS_AUE_linux_linkat AUE_LINKAT +#define LINUX_SYS_AUE_linux_symlinkat AUE_SYMLINKAT +#define LINUX_SYS_AUE_linux_readlinkat AUE_READLINKAT +#define LINUX_SYS_AUE_linux_fchmodat AUE_FCHMODAT +#define LINUX_SYS_AUE_linux_faccessat AUE_FACCESSAT #define LINUX_SYS_AUE_linux_pselect6 AUE_NULL #define LINUX_SYS_AUE_linux_ppoll AUE_NULL #define LINUX_SYS_AUE_linux_unshare AUE_NULL diff --git a/sys/i386/linux/linux_syscall.h b/sys/i386/linux/linux_syscall.h index abea8db..c789239 100644 --- a/sys/i386/linux/linux_syscall.h +++ b/sys/i386/linux/linux_syscall.h @@ -2,7 +2,7 @@ * System call numbers. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/i386/linux/linux_syscall.h,v 1.88 2008/03/16 16:29:37 rdivacky Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.90 2008/03/16 16:27:44 rdivacky Exp */ diff --git a/sys/i386/linux/linux_sysent.c b/sys/i386/linux/linux_sysent.c index 58c21d6..0e64653 100644 --- a/sys/i386/linux/linux_sysent.c +++ b/sys/i386/linux/linux_sysent.c @@ -2,11 +2,10 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/i386/linux/linux_sysent.c,v 1.95 2008/03/16 16:29:37 rdivacky Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.90 2008/03/16 16:27:44 rdivacky Exp */ -#include #include #include #include @@ -315,18 +314,18 @@ struct sysent linux_sysent[] = { { 0, (sy_call_t *)linux_inotify_rm_watch, AUE_NULL, NULL, 0, 0 }, /* 293 = linux_inotify_rm_watch */ { 0, (sy_call_t *)linux_migrate_pages, AUE_NULL, NULL, 0, 0 }, /* 294 = linux_migrate_pages */ { AS(linux_openat_args), (sy_call_t *)linux_openat, AUE_OPEN_RWTC, NULL, 0, 0 }, /* 295 = linux_openat */ - { 0, (sy_call_t *)linux_mkdirat, AUE_NULL, NULL, 0, 0 }, /* 296 = linux_mkdirat */ - { 0, (sy_call_t *)linux_mknodat, AUE_NULL, NULL, 0, 0 }, /* 297 = linux_mknodat */ - { 0, (sy_call_t *)linux_fchownat, AUE_NULL, NULL, 0, 0 }, /* 298 = linux_fchownat */ - { 0, (sy_call_t *)linux_futimesat, AUE_NULL, NULL, 0, 0 }, /* 299 = linux_futimesat */ - { 0, (sy_call_t *)linux_fstatat64, AUE_NULL, NULL, 0, 0 }, /* 300 = linux_fstatat64 */ - { 0, (sy_call_t *)linux_unlinkat, AUE_NULL, NULL, 0, 0 }, /* 301 = linux_unlinkat */ - { 0, (sy_call_t *)linux_renameat, AUE_NULL, NULL, 0, 0 }, /* 302 = linux_renameat */ - { 0, (sy_call_t *)linux_linkat, AUE_NULL, NULL, 0, 0 }, /* 303 = linux_linkat */ - { 0, (sy_call_t *)linux_symlinkat, AUE_NULL, NULL, 0, 0 }, /* 304 = linux_symlinkat */ - { 0, (sy_call_t *)linux_readlinkat, AUE_NULL, NULL, 0, 0 }, /* 305 = linux_readlinkat */ - { 0, (sy_call_t *)linux_fchmodat, AUE_NULL, NULL, 0, 0 }, /* 306 = linux_fchmodat */ - { 0, (sy_call_t *)linux_faccessat, AUE_NULL, NULL, 0, 0 }, /* 307 = linux_faccessat */ + { AS(linux_mkdirat_args), (sy_call_t *)linux_mkdirat, AUE_MKDIRAT, NULL, 0, 0 }, /* 296 = linux_mkdirat */ + { AS(linux_mknodat_args), (sy_call_t *)linux_mknodat, AUE_MKNODAT, NULL, 0, 0 }, /* 297 = linux_mknodat */ + { AS(linux_fchownat_args), (sy_call_t *)linux_fchownat, AUE_FCHOWNAT, NULL, 0, 0 }, /* 298 = linux_fchownat */ + { AS(linux_futimesat_args), (sy_call_t *)linux_futimesat, AUE_FUTIMESAT, NULL, 0, 0 }, /* 299 = linux_futimesat */ + { AS(linux_fstatat64_args), (sy_call_t *)linux_fstatat64, AUE_FSTATAT, NULL, 0, 0 }, /* 300 = linux_fstatat64 */ + { AS(linux_unlinkat_args), (sy_call_t *)linux_unlinkat, AUE_UNLINKAT, NULL, 0, 0 }, /* 301 = linux_unlinkat */ + { AS(linux_renameat_args), (sy_call_t *)linux_renameat, AUE_RENAMEAT, NULL, 0, 0 }, /* 302 = linux_renameat */ + { AS(linux_linkat_args), (sy_call_t *)linux_linkat, AUE_LINKAT, NULL, 0, 0 }, /* 303 = linux_linkat */ + { AS(linux_symlinkat_args), (sy_call_t *)linux_symlinkat, AUE_SYMLINKAT, NULL, 0, 0 }, /* 304 = linux_symlinkat */ + { AS(linux_readlinkat_args), (sy_call_t *)linux_readlinkat, AUE_READLINKAT, NULL, 0, 0 }, /* 305 = linux_readlinkat */ + { AS(linux_fchmodat_args), (sy_call_t *)linux_fchmodat, AUE_FCHMODAT, NULL, 0, 0 }, /* 306 = linux_fchmodat */ + { AS(linux_faccessat_args), (sy_call_t *)linux_faccessat, AUE_FACCESSAT, NULL, 0, 0 }, /* 307 = linux_faccessat */ { 0, (sy_call_t *)linux_pselect6, AUE_NULL, NULL, 0, 0 }, /* 308 = linux_pselect6 */ { 0, (sy_call_t *)linux_ppoll, AUE_NULL, NULL, 0, 0 }, /* 309 = linux_ppoll */ { 0, (sy_call_t *)linux_unshare, AUE_NULL, NULL, 0, 0 }, /* 310 = linux_unshare */ diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index 62c5612..93fd4fa 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD: src/sys/i386/linux/linux_sysvec.c,v 1.152 2008/03/13 10:54:3 #include #include #include +#include #include #include #include @@ -776,7 +777,7 @@ exec_linux_imgact_try(struct image_params *imgp) */ if ((error = exec_shell_imgact(imgp)) == 0) { linux_emul_convpath(FIRST_THREAD_IN_PROC(imgp->proc), - imgp->interpreter_name, UIO_SYSSPACE, &rpath, 0); + imgp->interpreter_name, UIO_SYSSPACE, &rpath, 0, AT_FDCWD); if (rpath != NULL) { len = strlen(rpath) + 1; diff --git a/sys/i386/linux/syscalls.master b/sys/i386/linux/syscalls.master index 8fd44d7..9ca33f8 100644 --- a/sys/i386/linux/syscalls.master +++ b/sys/i386/linux/syscalls.master @@ -475,20 +475,31 @@ 292 AUE_NULL STD { int linux_inotify_add_watch(void); } 293 AUE_NULL STD { int linux_inotify_rm_watch(void); } 294 AUE_NULL STD { int linux_migrate_pages(void); } -295 AUE_OPEN_RWTC STD { int linux_openat(l_int dfd, char *filename, \ +295 AUE_OPEN_RWTC STD { int linux_openat(l_int dfd, const char *filename, \ l_int flags, l_int mode); } -296 AUE_NULL STD { int linux_mkdirat(void); } -297 AUE_NULL STD { int linux_mknodat(void); } -298 AUE_NULL STD { int linux_fchownat(void); } -299 AUE_NULL STD { int linux_futimesat(void); } -300 AUE_NULL STD { int linux_fstatat64(void); } -301 AUE_NULL STD { int linux_unlinkat(void); } -302 AUE_NULL STD { int linux_renameat(void); } -303 AUE_NULL STD { int linux_linkat(void); } -304 AUE_NULL STD { int linux_symlinkat(void); } -305 AUE_NULL STD { int linux_readlinkat(void); } -306 AUE_NULL STD { int linux_fchmodat(void); } -307 AUE_NULL STD { int linux_faccessat(void); } +296 AUE_MKDIRAT STD { int linux_mkdirat(l_int dfd, const char *pathname, \ + l_int mode); } +297 AUE_MKNODAT STD { int linux_mknodat(l_int dfd, const char *filename, \ + l_int mode, l_uint dev); } +298 AUE_FCHOWNAT STD { int linux_fchownat(l_int dfd, const char *filename, \ + l_uid16_t uid, l_gid16_t gid, l_int flag); } +299 AUE_FUTIMESAT STD { int linux_futimesat(l_int dfd, char *filename, \ + struct l_timeval *utimes); } +300 AUE_FSTATAT STD { int linux_fstatat64(l_int dfd, char *pathname, \ + struct l_stat64 *statbuf, l_int flag); } +301 AUE_UNLINKAT STD { int linux_unlinkat(l_int dfd, const char *pathname, \ + l_int flag); } +302 AUE_RENAMEAT STD { int linux_renameat(l_int olddfd, const char *oldname, \ + l_int newdfd, const char *newname); } +303 AUE_LINKAT STD { int linux_linkat(l_int olddfd, const char *oldname, \ + l_int newdfd, const char *newname, l_int flags); } +304 AUE_SYMLINKAT STD { int linux_symlinkat(const char *oldname, l_int newdfd, \ + const char *newname); } +305 AUE_READLINKAT STD { int linux_readlinkat(l_int dfd, const char *path, \ + char *buf, l_int bufsiz); } +306 AUE_FCHMODAT STD { int linux_fchmodat(l_int dfd, const char *filename, \ + l_mode_t mode); } +307 AUE_FACCESSAT STD { int linux_faccessat(l_int dfd, const char *filename, l_int mode); } 308 AUE_NULL STD { int linux_pselect6(void); } 309 AUE_NULL STD { int linux_ppoll(void); } 310 AUE_NULL STD { int linux_unshare(void); } diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 98d1749..4a1ddc2 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -2,7 +2,7 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/kern/init_sysent.c,v 1.237 2008/03/26 15:24:02 dfr Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.241 2008/03/26 15:23:09 dfr Exp */ @@ -517,4 +517,19 @@ struct sysent sysent[] = { { AS(cpuset_getid_args), (sy_call_t *)cpuset_getid, AUE_NULL, NULL, 0, 0 }, /* 486 = cpuset_getid */ { AS(cpuset_getaffinity_args), (sy_call_t *)cpuset_getaffinity, AUE_NULL, NULL, 0, 0 }, /* 487 = cpuset_getaffinity */ { AS(cpuset_setaffinity_args), (sy_call_t *)cpuset_setaffinity, AUE_NULL, NULL, 0, 0 }, /* 488 = cpuset_setaffinity */ + { AS(faccessat_args), (sy_call_t *)faccessat, AUE_FACCESSAT, NULL, 0, 0 }, /* 489 = faccessat */ + { AS(fchmodat_args), (sy_call_t *)fchmodat, AUE_FCHMODAT, NULL, 0, 0 }, /* 490 = fchmodat */ + { AS(fchownat_args), (sy_call_t *)fchownat, AUE_FCHOWNAT, NULL, 0, 0 }, /* 491 = fchownat */ + { AS(fexecve_args), (sy_call_t *)fexecve, AUE_FEXECVE, NULL, 0, 0 }, /* 492 = fexecve */ + { AS(fstatat_args), (sy_call_t *)fstatat, AUE_FSTATAT, NULL, 0, 0 }, /* 493 = fstatat */ + { AS(futimesat_args), (sy_call_t *)futimesat, AUE_FUTIMESAT, NULL, 0, 0 }, /* 494 = futimesat */ + { AS(linkat_args), (sy_call_t *)linkat, AUE_LINKAT, NULL, 0, 0 }, /* 495 = linkat */ + { AS(mkdirat_args), (sy_call_t *)mkdirat, AUE_MKDIRAT, NULL, 0, 0 }, /* 496 = mkdirat */ + { AS(mkfifoat_args), (sy_call_t *)mkfifoat, AUE_MKFIFOAT, NULL, 0, 0 }, /* 497 = mkfifoat */ + { AS(mknodat_args), (sy_call_t *)mknodat, AUE_MKNODAT, NULL, 0, 0 }, /* 498 = mknodat */ + { AS(openat_args), (sy_call_t *)openat, AUE_OPENAT_RWTC, NULL, 0, 0 }, /* 499 = openat */ + { AS(readlinkat_args), (sy_call_t *)readlinkat, AUE_READLINKAT, NULL, 0, 0 }, /* 500 = readlinkat */ + { AS(renameat_args), (sy_call_t *)renameat, AUE_RENAMEAT, NULL, 0, 0 }, /* 501 = renameat */ + { AS(symlinkat_args), (sy_call_t *)symlinkat, AUE_SYMLINKAT, NULL, 0, 0 }, /* 502 = symlinkat */ + { AS(unlinkat_args), (sy_call_t *)unlinkat, AUE_UNLINKAT, NULL, 0, 0 }, /* 503 = unlinkat */ }; diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index d22842e..32f5bc9 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -2067,7 +2067,7 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags, int hold) } /* - * FREAD and FWRITE failure return EBADF as per POSIX. + * FREAD, FWRITE and FEXEC failure return EBADF as per POSIX. * * Only one flag, or 0, may be specified. */ @@ -2079,6 +2079,10 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags, int hold) FILEDESC_SUNLOCK(fdp); return (EBADF); } + if (flags == FEXEC && (fp->f_flag & FEXEC) == 0) { + FILEDESC_SUNLOCK(fdp); + return (EBADF); + } if (hold) { fhold(fp); FILEDESC_SUNLOCK(fdp); @@ -2157,6 +2161,14 @@ fgetvp_write(struct thread *td, int fd, struct vnode **vpp) } #endif + +/* Gets a vnode if file was opened with either FREAD or FEXEC flag. */ +int +fgetvp_exec(struct thread *td, int fd, struct vnode **vpp) +{ + return (_fgetvp(td, fd, vpp, VEXEC)); +} + /* * Like fget() but loads the underlying socket, or returns an error if the * descriptor does not represent a socket. diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 1c1782b..19aea16 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -189,6 +189,28 @@ execve(td, uap) } #ifndef _SYS_SYSPROTO_H_ +struct fexecve_args { + int fd; + char **argv; + char **envv; +} +#endif +int +fexecve(struct thread *td, struct fexecve_args *uap) +{ + int error; + struct image_args args; + + error = exec_copyin_args(&args, NULL, UIO_SYSSPACE, + uap->argv, uap->envv); + if (error == 0) { + args.fd = uap->fd; + error = kern_execve(td, &args, NULL); + } + return (error); +} + +#ifndef _SYS_SYSPROTO_H_ struct __mac_execve_args { char *fname; char **argv; @@ -284,7 +306,7 @@ do_execve(td, args, mac_p) struct ucred *newcred = NULL, *oldcred; struct uidinfo *euip; register_t *stack_base; - int error, len, i; + int error, len = 0, i; struct image_params image_params, *imgp; struct vattr attr; int (*img_first)(struct image_params *); @@ -294,7 +316,7 @@ do_execve(td, args, mac_p) struct vnode *tracevp = NULL; struct ucred *tracecred = NULL; #endif - struct vnode *textvp = NULL; + struct vnode *textvp = NULL, *binvp = NULL; int credential_changing; int vfslocked; int textset; @@ -305,6 +327,7 @@ do_execve(td, args, mac_p) #ifdef HWPMC_HOOKS struct pmckern_procexec pe; #endif + static const char fexecv_proc_title[] = "(fexecv)"; vfslocked = 0; imgp = &image_params; @@ -355,17 +378,29 @@ do_execve(td, args, mac_p) * XXXAUDIT: It would be desirable to also audit the name of the * interpreter if this is an interpreted binary. */ - ndp = &nd; - NDINIT(ndp, LOOKUP, ISOPEN | LOCKLEAF | FOLLOW | SAVENAME | MPSAFE | - AUDITVNODE1, UIO_SYSSPACE, args->fname, td); + if (args->fname != NULL) { + ndp = &nd; + NDINIT(ndp, LOOKUP, ISOPEN | LOCKLEAF | FOLLOW | SAVENAME + | MPSAFE | AUDITVNODE1, UIO_SYSSPACE, args->fname, td); + } interpret: - error = namei(ndp); - if (error) - goto exec_fail; + if (args->fname != NULL) { + error = namei(ndp); + if (error) + goto exec_fail; - vfslocked = NDHASGIANT(ndp); - imgp->vp = ndp->ni_vp; + vfslocked = NDHASGIANT(ndp); + binvp = ndp->ni_vp; + imgp->vp = binvp; + } else { + error = fgetvp_exec(td, args->fd, &binvp); + if (error) + goto exec_fail; + vfslocked = VFS_LOCK_GIANT(binvp->v_mount); + vn_lock(binvp, LK_EXCLUSIVE | LK_RETRY); + imgp->vp = binvp; + } /* * Check file permissions (also 'opens' file) @@ -438,12 +473,13 @@ interpret: */ imgp->vp->v_vflag &= ~VV_TEXT; /* free name buffer and old vnode */ - NDFREE(ndp, NDF_ONLY_PNBUF); + if (args->fname != NULL) + NDFREE(ndp, NDF_ONLY_PNBUF); #ifdef MAC interplabel = mac_vnode_label_alloc(); - mac_vnode_copy_label(ndp->ni_vp->v_label, interplabel); + mac_vnode_copy_label(binvp->v_label, interplabel); #endif - vput(ndp->ni_vp); + vput(binvp); vm_object_deallocate(imgp->object); imgp->object = NULL; VFS_UNLOCK_GIANT(vfslocked); @@ -451,6 +487,7 @@ interpret: /* set new name to that of the interpreter */ NDINIT(ndp, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME | MPSAFE, UIO_SYSSPACE, imgp->interpreter_name, td); + args->fname = imgp->interpreter_name; goto interpret; } @@ -496,7 +533,7 @@ interpret: vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY); /* Get a reference to the vnode prior to locking the proc */ - VREF(ndp->ni_vp); + VREF(binvp); /* * For security and other reasons, signal handlers cannot @@ -522,8 +559,18 @@ interpret: execsigs(p); /* name this process - nameiexec(p, ndp) */ - len = min(ndp->ni_cnd.cn_namelen,MAXCOMLEN); - bcopy(ndp->ni_cnd.cn_nameptr, p->p_comm, len); + if (args->fname) { + len = min(ndp->ni_cnd.cn_namelen,MAXCOMLEN); + bcopy(ndp->ni_cnd.cn_nameptr, p->p_comm, len); + } else { + len = MAXCOMLEN; + if (vn_commname(binvp, p->p_comm, MAXCOMLEN + 1) == 0) + len = MAXCOMLEN; + else { + len = sizeof(fexecv_proc_title); + bcopy(fexecv_proc_title, p->p_comm, len); + } + } p->p_comm[len] = 0; bcopy(p->p_comm, td->td_name, sizeof(td->td_name)); @@ -653,7 +700,7 @@ interpret: * to locking the proc lock. */ textvp = p->p_textvp; - p->p_textvp = ndp->ni_vp; + p->p_textvp = binvp; /* * Notify others that we exec'd, and clear the P_INEXEC flag @@ -736,8 +783,8 @@ done1: vrele(textvp); VFS_UNLOCK_GIANT(tvfslocked); } - if (ndp->ni_vp && error != 0) - vrele(ndp->ni_vp); + if (binvp && error != 0) + vrele(binvp); #ifdef KTRACE if (tracevp != NULL) { int tvfslocked; @@ -766,7 +813,8 @@ exec_fail_dealloc: exec_unmap_first_page(imgp); if (imgp->vp != NULL) { - NDFREE(ndp, NDF_ONLY_PNBUF); + if (args->fname) + NDFREE(ndp, NDF_ONLY_PNBUF); vput(imgp->vp); } @@ -991,17 +1039,18 @@ exec_copyin_args(struct image_args *args, char *fname, args->begin_argv = args->buf; args->endp = args->begin_argv; args->stringspace = ARG_MAX; - - args->fname = args->buf + ARG_MAX; - /* * Copy the file name. */ - error = (segflg == UIO_SYSSPACE) ? - copystr(fname, args->fname, PATH_MAX, &length) : - copyinstr(fname, args->fname, PATH_MAX, &length); - if (error != 0) - goto err_exit; + if (fname != NULL) { + args->fname = args->buf + ARG_MAX; + error = (segflg == UIO_SYSSPACE) ? + copystr(fname, args->fname, PATH_MAX, &length) : + copyinstr(fname, args->fname, PATH_MAX, &length); + if (error != 0) + goto err_exit; + } else + args->fname = NULL; /* * extract arguments first diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index f29b607..26f3fe0 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -22,6 +22,7 @@ __FBSDID("$FreeBSD: src/sys/kern/kern_jail.c,v 1.75 2008/01/24 08:25:58 bz Exp $ #include #include #include +#include #include #include #include diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index fe7731f..5ddcdb3 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -2,7 +2,7 @@ * System call names. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/kern/syscalls.c,v 1.221 2008/03/26 15:24:02 dfr Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.241 2008/03/26 15:23:09 dfr Exp */ @@ -496,4 +496,19 @@ const char *syscallnames[] = { "cpuset_getid", /* 486 = cpuset_getid */ "cpuset_getaffinity", /* 487 = cpuset_getaffinity */ "cpuset_setaffinity", /* 488 = cpuset_setaffinity */ + "faccessat", /* 489 = faccessat */ + "fchmodat", /* 490 = fchmodat */ + "fchownat", /* 491 = fchownat */ + "fexecve", /* 492 = fexecve */ + "fstatat", /* 493 = fstatat */ + "futimesat", /* 494 = futimesat */ + "linkat", /* 495 = linkat */ + "mkdirat", /* 496 = mkdirat */ + "mkfifoat", /* 497 = mkfifoat */ + "mknodat", /* 498 = mknodat */ + "openat", /* 499 = openat */ + "readlinkat", /* 500 = readlinkat */ + "renameat", /* 501 = renameat */ + "symlinkat", /* 502 = symlinkat */ + "unlinkat", /* 503 = unlinkat */ }; diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index b6313b6..cfc4e30 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -858,6 +858,33 @@ 488 AUE_NULL STD { int cpuset_setaffinity(cpulevel_t level, \ cpuwhich_t which, id_t id, size_t cpusetsize, \ const cpuset_t *mask); } - +489 AUE_FACCESSAT STD { int faccessat(int fd, char *path, int mode, \ + int flag); } +490 AUE_FCHMODAT STD { int fchmodat(int fd, char *path, mode_t mode, \ + int flag); } +491 AUE_FCHOWNAT STD { int fchownat(int fd, char *path, uid_t uid, \ + gid_t gid, int flag); } +492 AUE_FEXECVE STD { int fexecve(int fd, char **argv, \ + char **envv); } +493 AUE_FSTATAT STD { int fstatat(int fd, char *path, \ + struct stat *buf, int flag); } +494 AUE_FUTIMESAT STD { int futimesat(int fd, char *path, \ + struct timeval *times); } +495 AUE_LINKAT STD { int linkat(int fd1, char *path1, int fd2, \ + char *path2, int flag); } +496 AUE_MKDIRAT STD { int mkdirat(int fd, char *path, mode_t mode); } +497 AUE_MKFIFOAT STD { int mkfifoat(int fd, char *path, mode_t mode); } +498 AUE_MKNODAT STD { int mknodat(int fd, char *path, mode_t mode, \ + dev_t dev); } +; XXX: see the comment for open +499 AUE_OPENAT_RWTC STD { int openat(int fd, char *path, int flag, \ + mode_t mode); } +500 AUE_READLINKAT STD { int readlinkat(int fd, char *path, char *buf, \ + size_t bufsize); } +501 AUE_RENAMEAT STD { int renameat(int oldfd, char *old, int newfd, \ + char *new); } +502 AUE_SYMLINKAT STD { int symlinkat(char *path1, int fd, \ + char *path2); } +503 AUE_UNLINKAT STD { int unlinkat(int fd, char *path, int flag); } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c index a4758fa..d46f25e 100644 --- a/sys/kern/systrace_args.c +++ b/sys/kern/systrace_args.c @@ -2,7 +2,7 @@ * System call argument to DTrace register array converstion. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/kern/systrace_args.c,v 1.21 2008/03/26 15:24:02 dfr Exp $ + * $FreeBSD$ * This file is part of the DTrace syscall provider. */ @@ -2901,6 +2901,152 @@ systrace_args(int sysnum, void *params, u_int64_t *uarg, int *n_args) *n_args = 5; break; } + /* faccessat */ + case 489: { + struct faccessat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* char * */ + iarg[2] = p->mode; /* int */ + iarg[3] = p->flag; /* int */ + *n_args = 4; + break; + } + /* fchmodat */ + case 490: { + struct fchmodat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* char * */ + iarg[2] = p->mode; /* mode_t */ + iarg[3] = p->flag; /* int */ + *n_args = 4; + break; + } + /* fchownat */ + case 491: { + struct fchownat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* char * */ + uarg[2] = p->uid; /* uid_t */ + iarg[3] = p->gid; /* gid_t */ + iarg[4] = p->flag; /* int */ + *n_args = 5; + break; + } + /* fexecve */ + case 492: { + struct fexecve_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->argv; /* char ** */ + uarg[2] = (intptr_t) p->envv; /* char ** */ + *n_args = 3; + break; + } + /* fstatat */ + case 493: { + struct fstatat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* char * */ + uarg[2] = (intptr_t) p->buf; /* struct stat * */ + iarg[3] = p->flag; /* int */ + *n_args = 4; + break; + } + /* futimesat */ + case 494: { + struct futimesat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* char * */ + uarg[2] = (intptr_t) p->times; /* struct timeval * */ + *n_args = 3; + break; + } + /* linkat */ + case 495: { + struct linkat_args *p = params; + iarg[0] = p->fd1; /* int */ + uarg[1] = (intptr_t) p->path1; /* char * */ + iarg[2] = p->fd2; /* int */ + uarg[3] = (intptr_t) p->path2; /* char * */ + iarg[4] = p->flag; /* int */ + *n_args = 5; + break; + } + /* mkdirat */ + case 496: { + struct mkdirat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* char * */ + iarg[2] = p->mode; /* mode_t */ + *n_args = 3; + break; + } + /* mkfifoat */ + case 497: { + struct mkfifoat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* char * */ + iarg[2] = p->mode; /* mode_t */ + *n_args = 3; + break; + } + /* mknodat */ + case 498: { + struct mknodat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* char * */ + iarg[2] = p->mode; /* mode_t */ + iarg[3] = p->dev; /* dev_t */ + *n_args = 4; + break; + } + /* openat */ + case 499: { + struct openat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* char * */ + iarg[2] = p->flag; /* int */ + iarg[3] = p->mode; /* mode_t */ + *n_args = 4; + break; + } + /* readlinkat */ + case 500: { + struct readlinkat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* char * */ + uarg[2] = (intptr_t) p->buf; /* char * */ + uarg[3] = p->bufsize; /* size_t */ + *n_args = 4; + break; + } + /* renameat */ + case 501: { + struct renameat_args *p = params; + iarg[0] = p->oldfd; /* int */ + uarg[1] = (intptr_t) p->old; /* char * */ + iarg[2] = p->newfd; /* int */ + uarg[3] = (intptr_t) p->new; /* char * */ + *n_args = 4; + break; + } + /* symlinkat */ + case 502: { + struct symlinkat_args *p = params; + uarg[0] = (intptr_t) p->path1; /* char * */ + iarg[1] = p->fd; /* int */ + uarg[2] = (intptr_t) p->path2; /* char * */ + *n_args = 3; + break; + } + /* unlinkat */ + case 503: { + struct unlinkat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* char * */ + iarg[2] = p->flag; /* int */ + *n_args = 3; + break; + } default: *n_args = 0; break; diff --git a/sys/kern/vfs_acl.c b/sys/kern/vfs_acl.c index 7d6672d..762fb27 100644 --- a/sys/kern/vfs_acl.c +++ b/sys/kern/vfs_acl.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD: src/sys/kern/vfs_acl.c,v 1.57 2008/03/16 10:58:05 rwatson Ex #include #include #include +#include #include #include #include diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index 013a069..64cf265 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -838,3 +838,22 @@ vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir, *retbuf = bp; return (0); } + +int +vn_commname(struct vnode *vp, char *buf, u_int buflen) +{ + struct namecache *ncp; + int l; + + CACHE_LOCK(); + ncp = TAILQ_FIRST(&vp->v_cache_dst); + if (!ncp) { + CACHE_UNLOCK(); + return (ENOENT); + } + l = min(ncp->nc_nlen, buflen - 1); + memcpy(buf, ncp->nc_name, l); + CACHE_UNLOCK(); + buf[l] = '\0'; + return (0); +} diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index e2c9c48..9c21123 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD: src/sys/kern/vfs_extattr.c,v 1.434 2008/01/13 14:44:10 attil #include #include #include +#include #include #include #include diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 291948b..f836c33 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD: src/sys/kern/vfs_lookup.c,v 1.108 2008/03/16 10:58:05 rwatso #include #include #include +#include #include #include #include @@ -192,9 +193,28 @@ namei(struct nameidata *ndp) ndp->ni_rootdir = fdp->fd_rdir; ndp->ni_topdir = fdp->fd_jdir; - dp = fdp->fd_cdir; + if (cnp->cn_pnbuf[0] != '/' && ndp->ni_dirfd != AT_FDCWD) { + error = fgetvp(td, ndp->ni_dirfd, &dp); + if (error == 0 && dp->v_type != VDIR) { + vfslocked = VFS_LOCK_GIANT(dp->v_mount); + vrele(dp); + VFS_UNLOCK_GIANT(vfslocked); + error = ENOTDIR; + } + if (error) { + FILEDESC_SUNLOCK(fdp); + uma_zfree(namei_zone, cnp->cn_pnbuf); +#ifdef DIAGNOSTIC + cnp->cn_pnbuf = NULL; + cnp->cn_nameptr = NULL; +#endif + return (error); + } + } else { + dp = fdp->fd_cdir; + VREF(dp); + } vfslocked = VFS_LOCK_GIANT(dp->v_mount); - VREF(dp); FILEDESC_SUNLOCK(fdp); for (;;) { /* @@ -1012,8 +1032,8 @@ NDFREE(struct nameidata *ndp, const u_int flags) * the M_TEMP bucket if one is returned. */ int -kern_alternate_path(struct thread *td, const char *prefix, char *path, - enum uio_seg pathseg, char **pathbuf, int create) +kern_alternate_path(struct thread *td, const char *prefix, const char *path, + enum uio_seg pathseg, char **pathbuf, int create, int dirfd) { struct nameidata nd, ndroot; char *ptr, *buf, *cp; @@ -1051,6 +1071,15 @@ kern_alternate_path(struct thread *td, const char *prefix, char *path, goto keeporig; } + if (dirfd != AT_FDCWD) { + /* + * We want the original because the "prefix" is + * included in the already opened dirfd. + */ + bcopy(ptr, buf, len); + return (0); + } + /* * We know that there is a / somewhere in this pathname. * Search backwards for it, to find the file's parent dir diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index e702dee..c0e47b0 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD: src/sys/kern/vfs_mount.c,v 1.277 2008/03/23 13:45:23 kib Exp #include #include #include +#include #include #include #include diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index a4d6fb1..1bcb1c9 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -996,13 +996,38 @@ open(td, uap) } */ *uap; { - return kern_open(td, uap->path, UIO_USERSPACE, uap->flags, uap->mode); + return (kern_open(td, uap->path, UIO_USERSPACE, uap->flags, + uap->mode)); +} + +#ifndef _SYS_SYSPROTO_H_ +struct openat_args { + int fd; + char *path; + int flag; + int mode; +}; +#endif +int +openat(struct thread *td, struct openat_args *uap) +{ + + return (kern_openat(td, uap->fd, uap->path, UIO_USERSPACE, + uap->flag, uap->mode)); } int kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags, int mode) { + + return (kern_openat(td, AT_FDCWD, path, pathseg, flags, mode)); +} + +int +kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg, + int flags, int mode) +{ struct proc *p = td->td_proc; struct filedesc *fdp = p->p_fd; struct file *fp; @@ -1018,9 +1043,18 @@ kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags, AUDIT_ARG(fflags, flags); AUDIT_ARG(mode, mode); - if ((flags & O_ACCMODE) == O_ACCMODE) + /* XXX: audit dirfd */ + if (flags & O_EXEC) { + if (flags & O_ACCMODE) + return (EINVAL); + } else if ((flags & O_ACCMODE) == O_ACCMODE) return (EINVAL); - flags = FFLAGS(flags); + else + flags = FFLAGS(flags); + + NDINIT_AT(&nd, LOOKUP, FOLLOW | AUDITVNODE1 | MPSAFE, pathseg, path, + fd, td); + error = falloc(td, &nfp, &indx); if (error) return (error); @@ -1029,9 +1063,8 @@ kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags, /* Set the flags early so the finit in devfs can pick them up. */ fp->f_flag = flags & FMASK; cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; - NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1 | MPSAFE, pathseg, path, td); td->td_dupfd = -1; /* XXX check for fdopen */ - error = vn_open(&nd, &flags, cmode, fp); + error = vn_open(&nd, &flags, cmode, fp); if (error) { /* * If the vn_open replaced the method vector, something @@ -1180,10 +1213,34 @@ mknod(td, uap) return (kern_mknod(td, uap->path, UIO_USERSPACE, uap->mode, uap->dev)); } +#ifndef _SYS_SYSPROTO_H_ +struct mknodat_args { + int fd; + char *path; + mode_t mode; + dev_t dev; +}; +#endif +int +mknodat(struct thread *td, struct mknodat_args *uap) +{ + + return (kern_mknodat(td, uap->fd, uap->path, UIO_USERSPACE, uap->mode, + uap->dev)); +} + int kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode, int dev) { + + return (kern_mknodat(td, AT_FDCWD, path, pathseg, mode, dev)); +} + +int +kern_mknodat(struct thread *td, int fd, char *path, enum uio_seg pathseg, + int mode, int dev) +{ struct vnode *vp; struct mount *mp; struct vattr vattr; @@ -1213,8 +1270,8 @@ kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode, return (error); restart: bwillwrite(); - NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, - pathseg, path, td); + NDINIT_AT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -1306,9 +1363,32 @@ mkfifo(td, uap) return (kern_mkfifo(td, uap->path, UIO_USERSPACE, uap->mode)); } +#ifndef _SYS_SYSPROTO_H_ +struct mkfifoat_args { + int fd; + char *path; + mode_t mode; +}; +#endif +int +mkfifoat(struct thread *td, struct mkfifoat_args *uap) +{ + + return (kern_mkfifoat(td, uap->fd, uap->path, UIO_USERSPACE, + uap->mode)); +} + int kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode) { + + return (kern_mkfifoat(td, AT_FDCWD, path, pathseg, mode)); +} + +int +kern_mkfifoat(struct thread *td, int fd, char *path, enum uio_seg pathseg, + int mode) +{ struct mount *mp; struct vattr vattr; int error; @@ -1318,8 +1398,8 @@ kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode) AUDIT_ARG(mode, mode); restart: bwillwrite(); - NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, - pathseg, path, td); + NDINIT_AT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -1383,10 +1463,30 @@ link(td, uap) char *link; } */ *uap; { - int error; - error = kern_link(td, uap->path, uap->link, UIO_USERSPACE); - return (error); + return (kern_link(td, uap->path, uap->link, UIO_USERSPACE)); +} + +#ifndef _SYS_SYSPROTO_H_ +struct linkat_args { + int fd1; + char *path1; + int fd2; + char *path2; + int flag; +}; +#endif +int +linkat(struct thread *td, struct linkat_args *uap) +{ + int flag; + + flag = uap->flag; + if (flag & ~AT_SYMLINK_FOLLOW) + return (EINVAL); + + return (kern_linkat(td, uap->fd1, uap->fd2, uap->path1, uap->path2, + UIO_USERSPACE, (flag & AT_SYMLINK_FOLLOW) ? FOLLOW : 0)); } static int hardlink_check_uid = 0; @@ -1431,6 +1531,14 @@ can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred) int kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg) { + + return (kern_linkat(td, AT_FDCWD, AT_FDCWD, path,link, segflg, FOLLOW)); +} + +int +kern_linkat(struct thread *td, int fd1, int fd2, char *path1, char *path2, + enum uio_seg segflg, int follow) +{ struct vnode *vp; struct mount *mp; struct nameidata nd; @@ -1439,7 +1547,9 @@ kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg) int error; bwillwrite(); - NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, segflg, path, td); + NDINIT_AT(&nd, LOOKUP, follow | MPSAFE | AUDITVNODE1, segflg, path1, + fd1, td); + if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -1455,8 +1565,8 @@ kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg) VFS_UNLOCK_GIANT(vfslocked); return (error); } - NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE2, - segflg, link, td); + NDINIT_AT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, + segflg, path2, fd2, td); if ((error = namei(&nd)) == 0) { lvfslocked = NDHASGIANT(&nd); if (nd.ni_vp != NULL) { @@ -1511,9 +1621,32 @@ symlink(td, uap) return (kern_symlink(td, uap->path, uap->link, UIO_USERSPACE)); } +#ifndef _SYS_SYSPROTO_H_ +struct symlinkat_args { + char *path; + int fd; + char *path2; +}; +#endif +int +symlinkat(struct thread *td, struct symlinkat_args *uap) +{ + + return (kern_symlinkat(td, uap->path1, uap->fd, uap->path2, + UIO_USERSPACE)); +} + int kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg) { + + return (kern_symlinkat(td, path, AT_FDCWD, link, segflg)); +} + +int +kern_symlinkat(struct thread *td, char *path1, int fd, char *path2, + enum uio_seg segflg) +{ struct mount *mp; struct vattr vattr; char *syspath; @@ -1522,17 +1655,17 @@ kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg) int vfslocked; if (segflg == UIO_SYSSPACE) { - syspath = path; + syspath = path1; } else { syspath = uma_zalloc(namei_zone, M_WAITOK); - if ((error = copyinstr(path, syspath, MAXPATHLEN, NULL)) != 0) + if ((error = copyinstr(path1, syspath, MAXPATHLEN, NULL)) != 0) goto out; } AUDIT_ARG(text, syspath); restart: bwillwrite(); - NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, - segflg, link, td); + NDINIT_AT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, + segflg, path2, fd, td); if ((error = namei(&nd)) != 0) goto out; vfslocked = NDHASGIANT(&nd); @@ -1650,15 +1783,43 @@ unlink(td, uap) char *path; } */ *uap; { - int error; - error = kern_unlink(td, uap->path, UIO_USERSPACE); - return (error); + return (kern_unlink(td, uap->path, UIO_USERSPACE)); +} + +#ifndef _SYS_SYSPROTO_H_ +struct unlinkat_args { + int fd; + char *path; + int flag; +}; +#endif +int +unlinkat(struct thread *td, struct unlinkat_args *uap) +{ + int flag = uap->flag; + int fd = uap->fd; + char *path = uap->path; + + if (flag & ~AT_REMOVEDIR) + return (EINVAL); + + if (flag & AT_REMOVEDIR) + return (kern_rmdirat(td, fd, path, UIO_USERSPACE)); + else + return (kern_unlinkat(td, fd, path, UIO_USERSPACE)); } int kern_unlink(struct thread *td, char *path, enum uio_seg pathseg) { + + return (kern_unlinkat(td, AT_FDCWD, path, pathseg)); +} + +int +kern_unlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg) +{ struct mount *mp; struct vnode *vp; int error; @@ -1667,8 +1828,8 @@ kern_unlink(struct thread *td, char *path, enum uio_seg pathseg) restart: bwillwrite(); - NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); + NDINIT_AT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); if ((error = namei(&nd)) != 0) return (error == EINVAL ? EPERM : error); vfslocked = NDHASGIANT(&nd); @@ -1909,39 +2070,70 @@ access(td, uap) return (kern_access(td, uap->path, UIO_USERSPACE, uap->flags)); } +#ifndef _SYS_SYSPROTO_H_ +struct faccessat_args { + int dirfd; + char *path; + int mode; + int flag; +} +#endif +int faccessat(struct thread *td, struct faccessat_args *uap) +{ + + if (uap->flag & ~AT_EACCESS) + return (EINVAL); + return (kern_accessat(td, uap->fd, uap->path, UIO_USERSPACE, uap->flag, + uap->mode)); +} + +int +kern_access(struct thread *td, char *path, enum uio_seg pathseg, int mode) +{ + + return (kern_accessat(td, AT_FDCWD, path, pathseg, 0, mode)); +} + int -kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags) +kern_accessat(struct thread *td, int fd, char *path, enum uio_seg pathseg, + int flags, int mode) { struct ucred *cred, *tmpcred; - register struct vnode *vp; + struct vnode *vp; struct nameidata nd; int vfslocked; int error; + NDINIT_AT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); + /* * Create and modify a temporary credential instead of one that * is potentially shared. This could also mess up socket * buffer accounting which can run in an interrupt context. */ - cred = td->td_ucred; - tmpcred = crdup(cred); - tmpcred->cr_uid = cred->cr_ruid; - tmpcred->cr_groups[0] = cred->cr_rgid; - td->td_ucred = tmpcred; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); + if (!(flags & AT_EACCESS)) { + cred = td->td_ucred; + tmpcred = crdup(cred); + tmpcred->cr_uid = cred->cr_ruid; + tmpcred->cr_groups[0] = cred->cr_rgid; + td->td_ucred = tmpcred; + } else + cred = tmpcred = td->td_ucred; if ((error = namei(&nd)) != 0) goto out1; vfslocked = NDHASGIANT(&nd); vp = nd.ni_vp; - error = vn_access(vp, flags, tmpcred, td); + error = vn_access(vp, mode, tmpcred, td); NDFREE(&nd, NDF_ONLY_PNBUF); vput(vp); VFS_UNLOCK_GIANT(vfslocked); out1: - td->td_ucred = cred; - crfree(tmpcred); + if (!(flags & AT_EACCESS)) { + td->td_ucred = cred; + crfree(tmpcred); + } return (error); } @@ -1969,22 +2161,8 @@ eaccess(td, uap) int kern_eaccess(struct thread *td, char *path, enum uio_seg pathseg, int flags) { - struct nameidata nd; - struct vnode *vp; - int vfslocked; - int error; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); - if ((error = namei(&nd)) != 0) - return (error); - vp = nd.ni_vp; - vfslocked = NDHASGIANT(&nd); - error = vn_access(vp, flags, td->td_ucred, td); - NDFREE(&nd, NDF_ONLY_PNBUF); - vput(vp); - VFS_UNLOCK_GIANT(vfslocked); - return (error); + return (kern_accessat(td, AT_FDCWD, path, pathseg, AT_EACCESS, flags)); } #if defined(COMPAT_43) @@ -2102,16 +2280,49 @@ stat(td, uap) return (error); } +#ifndef _SYS_SYSPROTO_H_ +struct fstatat_args { + int fd; + char *path; + struct stat *buf; + int flag; +} +#endif +int +fstatat(struct thread *td, struct fstatat_args *uap) +{ + struct stat sb; + int error; + + error = kern_statat(td, uap->flag, uap->fd, uap->path, + UIO_USERSPACE, &sb); + if (error == 0) + error = copyout(&sb, uap->buf, sizeof (sb)); + return (error); +} + int kern_stat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp) { + + return (kern_statat(td, 0, AT_FDCWD, path, pathseg, sbp)); +} + +int +kern_statat(struct thread *td, int flag, int fd, char *path, + enum uio_seg pathseg, struct stat *sbp) +{ struct nameidata nd; struct stat sb; int error, vfslocked; - NDINIT(&nd, LOOKUP, - FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); + if (flag & ~AT_SYMLINK_NOFOLLOW) + return (EINVAL); + + NDINIT_AT(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : + FOLLOW) | LOCKSHARED | LOCKLEAF | AUDITVNODE1 | MPSAFE, pathseg, + path, fd, td); + if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -2160,30 +2371,9 @@ lstat(td, uap) int kern_lstat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp) { - struct vnode *vp; - struct stat sb; - struct nameidata nd; - int error, vfslocked; - NDINIT(&nd, LOOKUP, - NOFOLLOW | LOCKLEAF | LOCKSHARED | MPSAFE | AUDITVNODE1, - pathseg, path, td); - if ((error = namei(&nd)) != 0) - return (error); - vfslocked = NDHASGIANT(&nd); - vp = nd.ni_vp; - error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td); - NDFREE(&nd, NDF_ONLY_PNBUF); - vput(vp); - VFS_UNLOCK_GIANT(vfslocked); - if (error) - return (error); - *sbp = sb; -#ifdef KTRACE - if (KTRPOINT(td, KTR_STRUCT)) - ktrstat(&sb); -#endif - return (0); + return (kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, path, pathseg, + sbp)); } /* @@ -2335,20 +2525,45 @@ readlink(td, uap) return (kern_readlink(td, uap->path, UIO_USERSPACE, uap->buf, UIO_USERSPACE, uap->count)); } +#ifndef _SYS_SYSPROTO_H_ +struct readlinkat_args { + int fd; + char *path; + char *buf; + size_t bufsize; +}; +#endif +int +readlinkat(struct thread *td, struct readlinkat_args *uap) +{ + + return (kern_readlinkat(td, uap->fd, uap->path, UIO_USERSPACE, + uap->buf, UIO_USERSPACE, uap->bufsize)); +} int kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf, enum uio_seg bufseg, size_t count) { - register struct vnode *vp; + + return (kern_readlinkat(td, AT_FDCWD, path, pathseg, buf, bufseg, + count)); +} + +int +kern_readlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg, + char *buf, enum uio_seg bufseg, size_t count) +{ + struct vnode *vp; struct iovec aiov; struct uio auio; int error; struct nameidata nd; int vfslocked; - NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); + NDINIT_AT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); + if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); @@ -2572,23 +2787,33 @@ chmod(td, uap) return (kern_chmod(td, uap->path, UIO_USERSPACE, uap->mode)); } +#ifndef _SYS_SYSPROTO_H_ +struct fchmodat_args { + int dirfd; + char *path; + mode_t mode; + int flag; +} +#endif +int +fchmodat(struct thread *td, struct fchmodat_args *uap) +{ + int flag = uap->flag; + int fd = uap->fd; + char *path = uap->path; + mode_t mode = uap->mode; + + if (flag & ~AT_SYMLINK_NOFOLLOW) + return (EINVAL); + + return (kern_fchmodat(td, fd, path, UIO_USERSPACE, mode, flag)); +} + int kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int mode) { - int error; - struct nameidata nd; - int vfslocked; - AUDIT_ARG(mode, mode); - NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td); - if ((error = namei(&nd)) != 0) - return (error); - vfslocked = NDHASGIANT(&nd); - NDFREE(&nd, NDF_ONLY_PNBUF); - error = setfmode(td, nd.ni_vp, mode); - vrele(nd.ni_vp); - VFS_UNLOCK_GIANT(vfslocked); - return (error); + return (kern_fchmodat(td, AT_FDCWD, path, pathseg, mode, 0)); } /* @@ -2608,18 +2833,30 @@ lchmod(td, uap) int mode; } */ *uap; { + + return (kern_fchmodat(td, AT_FDCWD, uap->path, UIO_USERSPACE, + uap->mode, AT_SYMLINK_NOFOLLOW)); +} + + +int +kern_fchmodat(struct thread *td, int fd, char *path, enum uio_seg pathseg, + mode_t mode, int flag) +{ int error; struct nameidata nd; int vfslocked; + int follow; - AUDIT_ARG(mode, (mode_t)uap->mode); - NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, UIO_USERSPACE, - uap->path, td); + AUDIT_ARG(mode, mode); + follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; + NDINIT_AT(&nd, LOOKUP, follow | MPSAFE | AUDITVNODE1, pathseg, path, + fd, td); if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); NDFREE(&nd, NDF_ONLY_PNBUF); - error = setfmode(td, nd.ni_vp, uap->mode); + error = setfmode(td, nd.ni_vp, mode); vrele(nd.ni_vp); VFS_UNLOCK_GIANT(vfslocked); return (error); @@ -2717,16 +2954,48 @@ chown(td, uap) return (kern_chown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid)); } +#ifndef _SYS_SYSPROTO_H_ +struct fchownat_args { + int fd; + const char * path; + uid_t uid; + gid_t gid; + int flag; +}; +#endif +int +fchownat(struct thread *td, struct fchownat_args *uap) +{ + int flag; + + flag = uap->flag; + if (flag & ~AT_SYMLINK_NOFOLLOW) + return (EINVAL); + + return (kern_fchownat(td, uap->fd, uap->path, UIO_USERSPACE, uap->uid, + uap->gid, uap->flag)); +} + int kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid, int gid) { - int error; + + return (kern_fchownat(td, AT_FDCWD, path, pathseg, uid, gid, 0)); +} + +int +kern_fchownat(struct thread *td, int fd, char *path, enum uio_seg pathseg, + int uid, int gid, int flag) +{ struct nameidata nd; - int vfslocked; + int error, vfslocked, follow; AUDIT_ARG(owner, uid, gid); - NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td); + follow = (flag & AT_SYMLINK_NOFOLLOW) == 0 ? NOFOLLOW : FOLLOW; + NDINIT_AT(&nd, LOOKUP, follow | MPSAFE | AUDITVNODE1, pathseg, path, + fd, td); + if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -2764,20 +3033,9 @@ int kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid, int gid) { - int error; - struct nameidata nd; - int vfslocked; - AUDIT_ARG(owner, uid, gid); - NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td); - if ((error = namei(&nd)) != 0) - return (error); - vfslocked = NDHASGIANT(&nd); - NDFREE(&nd, NDF_ONLY_PNBUF); - error = setfown(td, nd.ni_vp, uid, gid); - vrele(nd.ni_vp); - VFS_UNLOCK_GIANT(vfslocked); - return (error); + return (kern_fchownat(td, AT_FDCWD, path, pathseg, uid, gid, + AT_SYMLINK_NOFOLLOW)); } /* @@ -2919,18 +3177,42 @@ utimes(td, uap) UIO_USERSPACE)); } +#ifndef _SYS_SYSPROTO_H_ +struct futimesat_args { + int fd; + const char * path; + const struct timeval * times; +}; +#endif +int +futimesat(struct thread *td, struct futimesat_args *uap) +{ + + return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE, + uap->times, UIO_USERSPACE)); +} + int kern_utimes(struct thread *td, char *path, enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg) { - struct timespec ts[2]; - int error; + + return (kern_utimesat(td, AT_FDCWD, path, pathseg, tptr, tptrseg)); +} + +int +kern_utimesat(struct thread *td, int fd, char *path, enum uio_seg pathseg, + struct timeval *tptr, enum uio_seg tptrseg) +{ struct nameidata nd; - int vfslocked; + struct timespec ts[2]; + int error, vfslocked; if ((error = getutimes(tptr, tptrseg, ts)) != 0) return (error); - NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td); + NDINIT_AT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, + fd, td); + if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -3216,9 +3498,33 @@ rename(td, uap) return (kern_rename(td, uap->from, uap->to, UIO_USERSPACE)); } +#ifndef _SYS_SYSPROTO_H_ +struct renameat_args { + int oldfd; + char *old; + int newfd; + char *new; +}; +#endif +int +renameat(struct thread *td, struct renameat_args *uap) +{ + + return (kern_renameat(td, uap->oldfd, uap->old, uap->newfd, uap->new, + UIO_USERSPACE)); +} + int kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg) { + + return (kern_renameat(td, AT_FDCWD, from, AT_FDCWD, to, pathseg)); +} + +int +kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new, + enum uio_seg pathseg) +{ struct mount *mp = NULL; struct vnode *tvp, *fvp, *tdvp; struct nameidata fromnd, tond; @@ -3228,12 +3534,13 @@ kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg) bwillwrite(); #ifdef MAC - NDINIT(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART | MPSAFE | - AUDITVNODE1, pathseg, from, td); + NDINIT_AT(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART | MPSAFE | + AUDITVNODE1, pathseg, old, oldfd, td); #else - NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART | MPSAFE | - AUDITVNODE1, pathseg, from, td); + NDINIT_AT(&fromnd, DELETE, WANTPARENT | SAVESTART | MPSAFE | + AUDITVNODE1, pathseg, old, oldfd, td); #endif + if ((error = namei(&fromnd)) != 0) return (error); fvfslocked = NDHASGIANT(&fromnd); @@ -3254,8 +3561,8 @@ kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg) vrele(fvp); goto out1; } - NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | - MPSAFE | AUDITVNODE2, pathseg, to, td); + NDINIT_AT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | + MPSAFE | AUDITVNODE2, pathseg, new, newfd, td); if (fromnd.ni_vp->v_type == VDIR) tond.ni_cnd.cn_flags |= WILLBEDIR; if ((error = namei(&tond)) != 0) { @@ -3325,6 +3632,7 @@ out1: vrele(fromnd.ni_startdir); VFS_UNLOCK_GIANT(fvfslocked); VFS_UNLOCK_GIANT(tvfslocked); + /* Nothing to do, return success. */ if (error == -1) return (0); return (error); @@ -3351,9 +3659,31 @@ mkdir(td, uap) return (kern_mkdir(td, uap->path, UIO_USERSPACE, uap->mode)); } +#ifndef _SYS_SYSPROTO_H_ +struct mkdirat_args { + int fd; + char *path; + mode_t mode; +}; +#endif +int +mkdirat(struct thread *td, struct mkdirat_args *uap) +{ + + return (kern_mkdirat(td, uap->fd, uap->path, UIO_USERSPACE, uap->mode)); +} + int kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode) { + + return (kern_mkdirat(td, AT_FDCWD, path, segflg, mode)); +} + +int +kern_mkdirat(struct thread *td, int fd, char *path, enum uio_seg segflg, + int mode) +{ struct mount *mp; struct vnode *vp; struct vattr vattr; @@ -3364,8 +3694,8 @@ kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode) AUDIT_ARG(mode, mode); restart: bwillwrite(); - NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, - segflg, path, td); + NDINIT_AT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, + segflg, path, fd, td); nd.ni_cnd.cn_flags |= WILLBEDIR; if ((error = namei(&nd)) != 0) return (error); @@ -3441,6 +3771,13 @@ rmdir(td, uap) int kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg) { + + return (kern_rmdirat(td, AT_FDCWD, path, pathseg)); +} + +int +kern_rmdirat(struct thread *td, int fd, char *path, enum uio_seg pathseg) +{ struct mount *mp; struct vnode *vp; int error; @@ -3449,8 +3786,8 @@ kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg) restart: bwillwrite(); - NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); + NDINIT_AT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index fd560d0..cffc27c 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -212,6 +212,8 @@ restart: } if (fmode & FREAD) mode |= VREAD; + if (fmode & FEXEC) + mode |= VEXEC; if (fmode & O_APPEND) mode |= VAPPEND; #ifdef MAC diff --git a/sys/security/mac/mac_syscalls.c b/sys/security/mac/mac_syscalls.c index cffd197..7eab519 100644 --- a/sys/security/mac/mac_syscalls.c +++ b/sys/security/mac/mac_syscalls.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD: src/sys/security/mac/mac_syscalls.c,v 1.135 2008/01/13 14:44 #include "opt_mac.h" #include +#include #include #include #include diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h index adf760d..04bd2c6 100644 --- a/sys/sys/fcntl.h +++ b/sys/sys/fcntl.h @@ -105,6 +105,23 @@ typedef __pid_t pid_t; #ifdef _KERNEL #define FHASLOCK 0x4000 /* descriptor holds advisory lock */ #endif +/* Defined by POSIX Extended API Set Part 2 */ +#if __BSD_VISIBLE +/* + * Magic value that specify the use of the current working directory + * to determine the target of relative file paths in the openat() and + * similar syscalls. + */ +#define AT_FDCWD -100 + +/* + * Miscellaneous flags for the *at() syscalls. + */ +#define AT_EACCESS 0x100 /* Check access using effective user and group ID */ +#define AT_SYMLINK_NOFOLLOW 0x200 /* Do not follow symbolic links */ +#define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic link */ +#define AT_REMOVEDIR 0x800 /* Remove directory instead of file */ +#endif /* Defined by POSIX 1003.1; BSD default, but must be distinct from O_RDONLY. */ #define O_NOCTTY 0x8000 /* don't assign controlling terminal */ @@ -114,6 +131,15 @@ typedef __pid_t pid_t; #define O_DIRECT 0x00010000 #endif +/* Defined by POSIX Extended API Set Part 2 */ +#if __BSD_VISIBLE +#define O_DIRECTORY 0x00020000 /* Fail if not directory */ +#define O_EXEC 0x00040000 /* open for execute only */ +#endif +#ifdef _KERNEL +#define FEXEC 0x00040000 +#endif + /* * XXX missing O_DSYNC, O_RSYNC. */ @@ -124,7 +150,7 @@ typedef __pid_t pid_t; #define OFLAGS(fflags) ((fflags) - 1) /* bits to save after open */ -#define FMASK (FREAD|FWRITE|FAPPEND|FASYNC|FFSYNC|FNONBLOCK|O_DIRECT) +#define FMASK (FREAD|FWRITE|FAPPEND|FASYNC|FFSYNC|FNONBLOCK|O_DIRECT|FEXEC) /* bits settable by fcntl(F_SETFL, ...) */ #define FCNTLFLAGS (FAPPEND|FASYNC|FFSYNC|FNONBLOCK|O_DIRECT) @@ -246,6 +272,7 @@ __BEGIN_DECLS int open(const char *, int, ...); int creat(const char *, mode_t); int fcntl(int, int, ...); +int openat(int, const char *, int, ...); #if __BSD_VISIBLE int flock(int, int); #endif diff --git a/sys/sys/file.h b/sys/sys/file.h index 6833445..ef4a35c 100644 --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -190,6 +190,7 @@ void finit(struct file *, u_int, short, void *, struct fileops *); int fgetvp(struct thread *td, int fd, struct vnode **vpp); int fgetvp_read(struct thread *td, int fd, struct vnode **vpp); int fgetvp_write(struct thread *td, int fd, struct vnode **vpp); +int fgetvp_exec(struct thread *td, int fd, struct vnode **vpp); int fgetsock(struct thread *td, int fd, struct socket **spp, u_int *fflagp); void fputsock(struct socket *sp); diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h index 31a6265..842c1a3 100644 --- a/sys/sys/imgact.h +++ b/sys/sys/imgact.h @@ -45,6 +45,7 @@ struct image_args { int stringspace; /* space left in arg & env buffer */ int argc; /* count of argument strings */ int envc; /* count of environment strings */ + int fd; /* file descriptor of the executable */ }; struct image_params { diff --git a/sys/sys/namei.h b/sys/sys/namei.h index e50c667..45e681b 100644 --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -69,6 +69,7 @@ struct nameidata { struct vnode *ni_startdir; /* starting directory */ struct vnode *ni_rootdir; /* logical root directory */ struct vnode *ni_topdir; /* logical top directory */ + int ni_dirfd; /* starting directory for *at functions */ /* * Results: returned from/manipulated by lookup */ @@ -148,19 +149,22 @@ struct nameidata { /* * Initialization of a nameidata structure. */ -static void NDINIT(struct nameidata *, u_long, u_long, enum uio_seg, - const char *, struct thread *); +#define NDINIT(ndp, op, flags, segflg, namep, td) \ + NDINIT_AT(ndp, op, flags, segflg, namep, AT_FDCWD, td) + static __inline void -NDINIT(struct nameidata *ndp, +NDINIT_AT(struct nameidata *ndp, u_long op, u_long flags, enum uio_seg segflg, const char *namep, + int dirfd, struct thread *td) { ndp->ni_cnd.cn_nameiop = op; ndp->ni_cnd.cn_flags = flags; ndp->ni_segflg = segflg; ndp->ni_dirp = namep; + ndp->ni_dirfd = dirfd; ndp->ni_cnd.cn_thread = td; } diff --git a/sys/sys/stat.h b/sys/sys/stat.h index afa9253..8195f80 100644 --- a/sys/sys/stat.h +++ b/sys/sys/stat.h @@ -330,6 +330,12 @@ int mknod(const char *, mode_t, dev_t); #endif int stat(const char * __restrict, struct stat * __restrict); mode_t umask(mode_t); +#if __BSD_VISIBLE +int fstatat(int, const char *, struct stat *, int); +int mkdirat(int, const char *, mode_t); +int mkfifoat(int, const char *, mode_t); +int mknodat(int, const char *, mode_t, dev_t); +#endif __END_DECLS #endif /* !_KERNEL */ diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index e2dfa8b..c916022 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -2,7 +2,7 @@ * System call numbers. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/sys/syscall.h,v 1.218 2008/03/26 15:24:02 dfr Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.241 2008/03/26 15:23:09 dfr Exp */ @@ -403,4 +403,19 @@ #define SYS_cpuset_getid 486 #define SYS_cpuset_getaffinity 487 #define SYS_cpuset_setaffinity 488 -#define SYS_MAXSYSCALL 489 +#define SYS_faccessat 489 +#define SYS_fchmodat 490 +#define SYS_fchownat 491 +#define SYS_fexecve 492 +#define SYS_fstatat 493 +#define SYS_futimesat 494 +#define SYS_linkat 495 +#define SYS_mkdirat 496 +#define SYS_mkfifoat 497 +#define SYS_mknodat 498 +#define SYS_openat 499 +#define SYS_readlinkat 500 +#define SYS_renameat 501 +#define SYS_symlinkat 502 +#define SYS_unlinkat 503 +#define SYS_MAXSYSCALL 504 diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk index b74e269..c4c5f8b 100644 --- a/sys/sys/syscall.mk +++ b/sys/sys/syscall.mk @@ -1,6 +1,6 @@ # FreeBSD system call names. # DO NOT EDIT-- this file is automatically generated. -# $FreeBSD: src/sys/sys/syscall.mk,v 1.173 2008/03/26 15:24:02 dfr Exp $ +# $FreeBSD$ # created from FreeBSD: src/sys/kern/syscalls.master,v 1.241 2008/03/26 15:23:09 dfr Exp MIASM = \ syscall.o \ @@ -351,4 +351,19 @@ MIASM = \ cpuset_setid.o \ cpuset_getid.o \ cpuset_getaffinity.o \ - cpuset_setaffinity.o + cpuset_setaffinity.o \ + faccessat.o \ + fchmodat.o \ + fchownat.o \ + fexecve.o \ + fstatat.o \ + futimesat.o \ + linkat.o \ + mkdirat.o \ + mkfifoat.o \ + mknodat.o \ + openat.o \ + readlinkat.o \ + renameat.o \ + symlinkat.o \ + unlinkat.o diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h index 5aa39fb..b4e871a 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -56,14 +56,18 @@ int kern_accept(struct thread *td, int s, struct sockaddr **name, socklen_t *namelen, struct file **fp); int kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags); +int kern_accessat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, int flags, int mode); int kern_adjtime(struct thread *td, struct timeval *delta, struct timeval *olddelta); -int kern_alternate_path(struct thread *td, const char *prefix, char *path, - enum uio_seg pathseg, char **pathbuf, int create); +int kern_alternate_path(struct thread *td, const char *prefix, const char *path, + enum uio_seg pathseg, char **pathbuf, int create, int dirfd); int kern_bind(struct thread *td, int fd, struct sockaddr *sa); int kern_chdir(struct thread *td, char *path, enum uio_seg pathseg); int kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int mode); +int kern_chmodat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, mode_t mode); int kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid, int gid); int kern_clock_getres(struct thread *td, clockid_t clock_id, @@ -78,6 +82,10 @@ int kern_eaccess(struct thread *td, char *path, enum uio_seg pathseg, int flags); int kern_execve(struct thread *td, struct image_args *args, struct mac *mac_p); +int kern_fchmodat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, mode_t mode, int flag); +int kern_fchownat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, int uid, int gid, int flag); int kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg); int kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf); int kern_fstat(struct thread *td, int fd, struct stat *sbp); @@ -105,16 +113,26 @@ int kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid, int gid); int kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg); +int kern_linkat(struct thread *td, int fd1, int fd2, char *path1, + char *path2, enum uio_seg segflg, int follow); int kern_lstat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp); +int kern_lstatat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, struct stat *sbp); int kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg); int kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode); +int kern_mkdirat(struct thread *td, int fd, char *path, + enum uio_seg segflg, int mode); int kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode); +int kern_mkfifoat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, int mode); int kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode, int dev); +int kern_mknodat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, int mode, int dev); int kern_msgctl(struct thread *, int, int, struct msqid_ds *); int kern_msgsnd(struct thread *, int, const void *, size_t, int, long); int kern_msgrcv(struct thread *, int, void *, size_t, long, int, long *); @@ -122,6 +140,8 @@ int kern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt); int kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags, int mode); +int kern_openat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, int flags, int mode); int kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg, int name); int kern_preadv(struct thread *td, int fd, struct uio *auio, off_t offset); @@ -130,12 +150,18 @@ int kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int kern_pwritev(struct thread *td, int fd, struct uio *auio, off_t offset); int kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf, enum uio_seg bufseg, size_t count); +int kern_readlinkat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, char *buf, enum uio_seg bufseg, size_t count); int kern_readv(struct thread *td, int fd, struct uio *auio); int kern_recvit(struct thread *td, int s, struct msghdr *mp, enum uio_seg fromseg, struct mbuf **controlp); int kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg); +int kern_renameat(struct thread *td, int oldfd, char *old, int newfd, + char *new, enum uio_seg pathseg); int kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg); +int kern_rmdirat(struct thread *td, int fd, char *path, + enum uio_seg pathseg); int kern_sched_rr_get_interval(struct thread *td, pid_t pid, struct timespec *ts); int kern_semctl(struct thread *td, int semid, int semnum, int cmd, @@ -166,17 +192,25 @@ int kern_sigprocmask(struct thread *td, int how, int kern_sigsuspend(struct thread *td, sigset_t mask); int kern_stat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp); +int kern_statat(struct thread *td, int flag, int fd, char *path, + enum uio_seg pathseg, struct stat *sbp); int kern_statfs(struct thread *td, char *path, enum uio_seg pathseg, struct statfs *buf); int kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg); +int kern_symlinkat(struct thread *td, char *path1, int fd, char *path2, + enum uio_seg segflg); int kern_thr_new(struct thread *td, struct thr_param *param); int kern_thr_suspend(struct thread *td, struct timespec *tsp); int kern_truncate(struct thread *td, char *path, enum uio_seg pathseg, off_t length); int kern_unlink(struct thread *td, char *path, enum uio_seg pathseg); +int kern_unlinkat(struct thread *td, int fd, char *path, + enum uio_seg pathseg); int kern_utimes(struct thread *td, char *path, enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg); +int kern_utimesat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg); int kern_wait(struct thread *td, pid_t pid, int *status, int options, struct rusage *rup); int kern_writev(struct thread *td, int fd, struct uio *auio); diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h index 3dfaf2c..828de7e 100644 --- a/sys/sys/sysproto.h +++ b/sys/sys/sysproto.h @@ -2,7 +2,7 @@ * System call prototypes. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/sys/sysproto.h,v 1.222 2008/03/26 15:24:02 dfr Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.241 2008/03/26 15:23:09 dfr Exp */ @@ -1541,6 +1541,92 @@ struct cpuset_setaffinity_args { char cpusetsize_l_[PADL_(size_t)]; size_t cpusetsize; char cpusetsize_r_[PADR_(size_t)]; char mask_l_[PADL_(const cpuset_t *)]; const cpuset_t * mask; char mask_r_[PADR_(const cpuset_t *)]; }; +struct faccessat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)]; + char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)]; +}; +struct fchmodat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char mode_l_[PADL_(mode_t)]; mode_t mode; char mode_r_[PADR_(mode_t)]; + char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)]; +}; +struct fchownat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char uid_l_[PADL_(uid_t)]; uid_t uid; char uid_r_[PADR_(uid_t)]; + char gid_l_[PADL_(gid_t)]; gid_t gid; char gid_r_[PADR_(gid_t)]; + char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)]; +}; +struct fexecve_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char argv_l_[PADL_(char **)]; char ** argv; char argv_r_[PADR_(char **)]; + char envv_l_[PADL_(char **)]; char ** envv; char envv_r_[PADR_(char **)]; +}; +struct fstatat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char buf_l_[PADL_(struct stat *)]; struct stat * buf; char buf_r_[PADR_(struct stat *)]; + char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)]; +}; +struct futimesat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char times_l_[PADL_(struct timeval *)]; struct timeval * times; char times_r_[PADR_(struct timeval *)]; +}; +struct linkat_args { + char fd1_l_[PADL_(int)]; int fd1; char fd1_r_[PADR_(int)]; + char path1_l_[PADL_(char *)]; char * path1; char path1_r_[PADR_(char *)]; + char fd2_l_[PADL_(int)]; int fd2; char fd2_r_[PADR_(int)]; + char path2_l_[PADL_(char *)]; char * path2; char path2_r_[PADR_(char *)]; + char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)]; +}; +struct mkdirat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char mode_l_[PADL_(mode_t)]; mode_t mode; char mode_r_[PADR_(mode_t)]; +}; +struct mkfifoat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char mode_l_[PADL_(mode_t)]; mode_t mode; char mode_r_[PADR_(mode_t)]; +}; +struct mknodat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char mode_l_[PADL_(mode_t)]; mode_t mode; char mode_r_[PADR_(mode_t)]; + char dev_l_[PADL_(dev_t)]; dev_t dev; char dev_r_[PADR_(dev_t)]; +}; +struct openat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)]; + char mode_l_[PADL_(mode_t)]; mode_t mode; char mode_r_[PADR_(mode_t)]; +}; +struct readlinkat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)]; + char bufsize_l_[PADL_(size_t)]; size_t bufsize; char bufsize_r_[PADR_(size_t)]; +}; +struct renameat_args { + char oldfd_l_[PADL_(int)]; int oldfd; char oldfd_r_[PADR_(int)]; + char old_l_[PADL_(char *)]; char * old; char old_r_[PADR_(char *)]; + char newfd_l_[PADL_(int)]; int newfd; char newfd_r_[PADR_(int)]; + char new_l_[PADL_(char *)]; char * new; char new_r_[PADR_(char *)]; +}; +struct symlinkat_args { + char path1_l_[PADL_(char *)]; char * path1; char path1_r_[PADR_(char *)]; + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char path2_l_[PADL_(char *)]; char * path2; char path2_r_[PADR_(char *)]; +}; +struct unlinkat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)]; +}; int nosys(struct thread *, struct nosys_args *); void sys_exit(struct thread *, struct sys_exit_args *); int fork(struct thread *, struct fork_args *); @@ -1882,6 +1968,21 @@ int cpuset_setid(struct thread *, struct cpuset_setid_args *); int cpuset_getid(struct thread *, struct cpuset_getid_args *); int cpuset_getaffinity(struct thread *, struct cpuset_getaffinity_args *); int cpuset_setaffinity(struct thread *, struct cpuset_setaffinity_args *); +int faccessat(struct thread *, struct faccessat_args *); +int fchmodat(struct thread *, struct fchmodat_args *); +int fchownat(struct thread *, struct fchownat_args *); +int fexecve(struct thread *, struct fexecve_args *); +int fstatat(struct thread *, struct fstatat_args *); +int futimesat(struct thread *, struct futimesat_args *); +int linkat(struct thread *, struct linkat_args *); +int mkdirat(struct thread *, struct mkdirat_args *); +int mkfifoat(struct thread *, struct mkfifoat_args *); +int mknodat(struct thread *, struct mknodat_args *); +int openat(struct thread *, struct openat_args *); +int readlinkat(struct thread *, struct readlinkat_args *); +int renameat(struct thread *, struct renameat_args *); +int symlinkat(struct thread *, struct symlinkat_args *); +int unlinkat(struct thread *, struct unlinkat_args *); #ifdef COMPAT_43 @@ -2448,6 +2549,21 @@ int freebsd4_sigreturn(struct thread *, struct freebsd4_sigreturn_args *); #define SYS_AUE_cpuset_getid AUE_NULL #define SYS_AUE_cpuset_getaffinity AUE_NULL #define SYS_AUE_cpuset_setaffinity AUE_NULL +#define SYS_AUE_faccessat AUE_FACCESSAT +#define SYS_AUE_fchmodat AUE_FCHMODAT +#define SYS_AUE_fchownat AUE_FCHOWNAT +#define SYS_AUE_fexecve AUE_FEXECVE +#define SYS_AUE_fstatat AUE_FSTATAT +#define SYS_AUE_futimesat AUE_FUTIMESAT +#define SYS_AUE_linkat AUE_LINKAT +#define SYS_AUE_mkdirat AUE_MKDIRAT +#define SYS_AUE_mkfifoat AUE_MKFIFOAT +#define SYS_AUE_mknodat AUE_MKNODAT +#define SYS_AUE_openat AUE_OPENAT_RWTC +#define SYS_AUE_readlinkat AUE_READLINKAT +#define SYS_AUE_renameat AUE_RENAMEAT +#define SYS_AUE_symlinkat AUE_SYMLINKAT +#define SYS_AUE_unlinkat AUE_UNLINKAT #undef PAD_ #undef PADL_ diff --git a/sys/sys/time.h b/sys/sys/time.h index dc77562..856dc3b 100644 --- a/sys/sys/time.h +++ b/sys/sys/time.h @@ -321,6 +321,7 @@ int lutimes(const char *, const struct timeval *); int setitimer(int, const struct itimerval *, struct itimerval *); int settimeofday(const struct timeval *, const struct timezone *); int utimes(const char *, const struct timeval *); +int futimesat(int, const char *, const struct timeval [2]); __END_DECLS #endif /* !_KERNEL */ diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 66dc5d4..260f6ae 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -579,6 +579,7 @@ int speedup_syncer(void); vn_fullpath(FIRST_THREAD_IN_PROC(p), (p)->p_textvp, rb, rfb) int vn_fullpath(struct thread *td, struct vnode *vn, char **retbuf, char **freebuf); +int vn_commname(struct vnode *vn, char *buf, u_int buflen); int vaccess(enum vtype type, mode_t file_mode, uid_t file_uid, gid_t file_gid, mode_t acc_mode, struct ucred *cred, int *privused); diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c index a2f26f7..a28279a 100644 --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD: src/sys/ufs/ffs/ffs_snapshot.c,v 1.141 2008/03/19 06:19:01 j #include #include #include +#include #include #include #include