diff --git a/include/dirent.h b/include/dirent.h index 0d1e0c7..3ac8533 100644 --- a/include/dirent.h +++ b/include/dirent.h @@ -95,11 +95,15 @@ 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 *); #endif DIR *opendir(const char *); +#if __BSD_VISIBLE +DIR *fdopendir(int); +#endif struct dirent * readdir(DIR *); #if __POSIX_VISIBLE >= 199506 || __XSI_VISIBLE >= 500 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 2bfa0de..bb5389e 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 d5efad5..050efa7 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 f5e2dec..67f9302 100644 --- a/lib/libc/sys/Symbol.map +++ b/lib/libc/sys/Symbol.map @@ -335,6 +335,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 a71f7bc..0712b9b 100644 --- a/sys/amd64/linux32/linux32_proto.h +++ b/sys/amd64/linux32/linux32_proto.h @@ -881,45 +881,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; diff --git a/sys/amd64/linux32/linux32_sysent.c b/sys/amd64/linux32/linux32_sysent.c index 99372d0..3a1d26f 100644 --- a/sys/amd64/linux32/linux32_sysent.c +++ b/sys/amd64/linux32/linux32_sysent.c @@ -316,18 +316,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_NULL, NULL, 0, 0 }, /* 296 = linux_mkdirat */ + { AS(linux_mknodat_args), (sy_call_t *)linux_mknodat, AUE_NULL, NULL, 0, 0 }, /* 297 = linux_mknodat */ + { AS(linux_fchownat_args), (sy_call_t *)linux_fchownat, AUE_NULL, NULL, 0, 0 }, /* 298 = linux_fchownat */ + { AS(linux_futimesat_args), (sy_call_t *)linux_futimesat, AUE_NULL, NULL, 0, 0 }, /* 299 = linux_futimesat */ + { AS(linux_fstatat64_args), (sy_call_t *)linux_fstatat64, AUE_NULL, NULL, 0, 0 }, /* 300 = linux_fstatat64 */ + { AS(linux_unlinkat_args), (sy_call_t *)linux_unlinkat, AUE_NULL, NULL, 0, 0 }, /* 301 = linux_unlinkat */ + { AS(linux_renameat_args), (sy_call_t *)linux_renameat, AUE_NULL, NULL, 0, 0 }, /* 302 = linux_renameat */ + { AS(linux_linkat_args), (sy_call_t *)linux_linkat, AUE_NULL, NULL, 0, 0 }, /* 303 = linux_linkat */ + { AS(linux_symlinkat_args), (sy_call_t *)linux_symlinkat, AUE_NULL, NULL, 0, 0 }, /* 304 = linux_symlinkat */ + { AS(linux_readlinkat_args), (sy_call_t *)linux_readlinkat, AUE_NULL, NULL, 0, 0 }, /* 305 = linux_readlinkat */ + { AS(linux_fchmodat_args), (sy_call_t *)linux_fchmodat, AUE_NULL, NULL, 0, 0 }, /* 306 = linux_fchmodat */ + { AS(linux_faccessat_args), (sy_call_t *)linux_faccessat, AUE_NULL, 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 2473d9c..c150722 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.31 2007/09/20 13: #include #include #include +#include #include #include #include @@ -789,7 +790,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 eab7db1..646d1ff 100644 --- a/sys/amd64/linux32/syscalls.master +++ b/sys/amd64/linux32/syscalls.master @@ -464,20 +464,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_NULL STD { int linux_mkdirat(l_int dfd, const char *pathname, \ + l_int mode); } +297 AUE_NULL STD { int linux_mknodat(l_int dfd, const char *filename, \ + l_int mode, l_uint dev); } +298 AUE_NULL STD { int linux_fchownat(l_int dfd, const char *filename, \ + l_uid16_t uid, l_gid16_t gid, l_int flag); } +299 AUE_NULL STD { int linux_futimesat(l_int dfd, char *filename, \ + struct l_timeval *utimes); } +300 AUE_NULL STD { int linux_fstatat64(l_int dfd, char *pathname, \ + struct l_stat64 *statbuf, l_int flag); } +301 AUE_NULL STD { int linux_unlinkat(l_int dfd, const char *pathname, \ + l_int flag); } +302 AUE_NULL STD { int linux_renameat(l_int olddfd, const char *oldname, \ + l_int newdfd, const char *newname); } +303 AUE_NULL STD { int linux_linkat(l_int olddfd, const char *oldname, \ + l_int newdfd, const char *newname, l_int flags); } +304 AUE_NULL STD { int linux_symlinkat(const char *oldname, l_int newdfd, \ + const char *newname); } +305 AUE_NULL STD { int linux_readlinkat(l_int dfd, const char *path, \ + char *buf, l_int bufsiz); } +306 AUE_NULL STD { int linux_fchmodat(l_int dfd, const char *filename, \ + l_mode_t mode); } +307 AUE_NULL 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 941a312..5aca052 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.82 2008/02/12 20:11:54 ru Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/compat/freebsd32/syscalls.master,v 1.96 2008/02/12 20:09:03 ru Exp */ @@ -327,6 +327,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_(const char *)]; const char * path; char path_r_[PADR_(const 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_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char times_l_[PADL_(const struct timeval *)]; const struct timeval * times; char times_r_[PADR_(const 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 *); @@ -384,6 +400,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 @@ -587,6 +606,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 49f9bfd..f8b2d80 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.80 2008/02/12 20:11:54 ru Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/compat/freebsd32/syscalls.master,v 1.96 2008/02/12 20:09:03 ru Exp */ @@ -340,4 +340,19 @@ #define FREEBSD32_SYS_thr_kill2 481 #define FREEBSD32_SYS_shm_open 482 #define FREEBSD32_SYS_shm_unlink 483 -#define FREEBSD32_SYS_MAXSYSCALL 484 +#define FREEBSD32_SYS_faccessat 484 +#define FREEBSD32_SYS_fchmodat 485 +#define FREEBSD32_SYS_fchownat 486 +#define FREEBSD32_SYS_freebsd32_fexecve 487 +#define FREEBSD32_SYS_freebsd32_fstatat 488 +#define FREEBSD32_SYS_freebsd32_futimesat 489 +#define FREEBSD32_SYS_linkat 490 +#define FREEBSD32_SYS_mkdirat 491 +#define FREEBSD32_SYS_mkfifoat 492 +#define FREEBSD32_SYS_mknodat 493 +#define FREEBSD32_SYS_openat 494 +#define FREEBSD32_SYS_readlinkat 495 +#define FREEBSD32_SYS_renameat 496 +#define FREEBSD32_SYS_symlinkat 497 +#define FREEBSD32_SYS_unlinkat 498 +#define FREEBSD32_SYS_MAXSYSCALL 499 diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c index e223e74..bbf5fa5 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.71 2008/02/12 20:11:54 ru Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/compat/freebsd32/syscalls.master,v 1.96 2008/02/12 20:09:03 ru Exp */ @@ -491,4 +491,19 @@ const char *freebsd32_syscallnames[] = { "thr_kill2", /* 481 = thr_kill2 */ "shm_open", /* 482 = shm_open */ "shm_unlink", /* 483 = shm_unlink */ + "faccessat", /* 484 = faccessat */ + "fchmodat", /* 485 = fchmodat */ + "fchownat", /* 486 = fchownat */ + "freebsd32_fexecve", /* 487 = freebsd32_fexecve */ + "freebsd32_fstatat", /* 488 = freebsd32_fstatat */ + "freebsd32_futimesat", /* 489 = freebsd32_futimesat */ + "linkat", /* 490 = linkat */ + "mkdirat", /* 491 = mkdirat */ + "mkfifoat", /* 492 = mkfifoat */ + "mknodat", /* 493 = mknodat */ + "openat", /* 494 = openat */ + "readlinkat", /* 495 = readlinkat */ + "renameat", /* 496 = renameat */ + "symlinkat", /* 497 = symlinkat */ + "unlinkat", /* 498 = unlinkat */ }; diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c index 65a4192..d62a5d5 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.81 2008/02/12 20:11:54 ru Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/compat/freebsd32/syscalls.master,v 1.96 2008/02/12 20:09:03 ru Exp */ @@ -523,4 +523,19 @@ struct sysent freebsd32_sysent[] = { { AS(thr_kill2_args), (sy_call_t *)thr_kill2, AUE_KILL, NULL, 0, 0 }, /* 481 = thr_kill2 */ { AS(shm_open_args), (sy_call_t *)shm_open, AUE_SHMOPEN, NULL, 0, 0 }, /* 482 = shm_open */ { AS(shm_unlink_args), (sy_call_t *)shm_unlink, AUE_SHMUNLINK, NULL, 0, 0 }, /* 483 = shm_unlink */ + { AS(faccessat_args), (sy_call_t *)faccessat, AUE_FACCESSAT, NULL, 0, 0 }, /* 484 = faccessat */ + { AS(fchmodat_args), (sy_call_t *)fchmodat, AUE_FCHMODAT, NULL, 0, 0 }, /* 485 = fchmodat */ + { AS(fchownat_args), (sy_call_t *)fchownat, AUE_FCHOWNAT, NULL, 0, 0 }, /* 486 = fchownat */ + { AS(freebsd32_fexecve_args), (sy_call_t *)freebsd32_fexecve, AUE_FEXECVE, NULL, 0, 0 }, /* 487 = freebsd32_fexecve */ + { AS(freebsd32_fstatat_args), (sy_call_t *)freebsd32_fstatat, AUE_FSTATAT, NULL, 0, 0 }, /* 488 = freebsd32_fstatat */ + { AS(freebsd32_futimesat_args), (sy_call_t *)freebsd32_futimesat, AUE_FUTIMESAT, NULL, 0, 0 }, /* 489 = freebsd32_futimesat */ + { AS(linkat_args), (sy_call_t *)linkat, AUE_LINKAT, NULL, 0, 0 }, /* 490 = linkat */ + { AS(mkdirat_args), (sy_call_t *)mkdirat, AUE_MKDIRAT, NULL, 0, 0 }, /* 491 = mkdirat */ + { AS(mkfifoat_args), (sy_call_t *)mkfifoat, AUE_MKFIFOAT, NULL, 0, 0 }, /* 492 = mkfifoat */ + { AS(mknodat_args), (sy_call_t *)mknodat, AUE_MKNODAT, NULL, 0, 0 }, /* 493 = mknodat */ + { AS(openat_args), (sy_call_t *)openat, AUE_OPENAT_RWTC, NULL, 0, 0 }, /* 494 = openat */ + { AS(readlinkat_args), (sy_call_t *)readlinkat, AUE_READLINKAT, NULL, 0, 0 }, /* 495 = readlinkat */ + { AS(renameat_args), (sy_call_t *)renameat, AUE_RENAMEAT, NULL, 0, 0 }, /* 496 = renameat */ + { AS(symlinkat_args), (sy_call_t *)symlinkat, AUE_SYMLINKAT, NULL, 0, 0 }, /* 497 = symlinkat */ + { AS(unlinkat_args), (sy_call_t *)unlinkat, AUE_UNLINKAT, NULL, 0, 0 }, /* 498 = unlinkat */ }; diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 3cce7a5..194e453 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -799,3 +799,35 @@ 482 AUE_SHMOPEN NOPROTO { int shm_open(const char *path, int flags, \ mode_t mode); } 483 AUE_SHMUNLINK NOPROTO { int shm_unlink(const char *path); } +484 AUE_FACCESSAT NOPROTO { int faccessat(int fd, const char *path, \ + int mode, int flag); } +485 AUE_FCHMODAT NOPROTO { int fchmodat(int fd, const char *path, \ + mode_t mode, int flag); } +486 AUE_FCHOWNAT NOPROTO { int fchownat(int fd, const char *path, \ + uid_t uid, gid_t gid, int flag); } +487 AUE_FEXECVE STD { int freebsd32_fexecve(int fd, \ + u_int32_t *argv, u_int32_t *envv); } +488 AUE_FSTATAT STD { int freebsd32_fstatat(int fd, \ + const char *path, \ + struct stat *buf, int flag); } +489 AUE_FUTIMESAT STD { int freebsd32_futimesat(int fd, \ + const char *path, \ + const struct timeval *times); } +490 AUE_LINKAT NOPROTO { int linkat(int fd1, const char *path1, \ + int fd2, const char *path2, int flag); } +491 AUE_MKDIRAT NOPROTO { int mkdirat(int fd, const char *path, \ + mode_t mode); } +492 AUE_MKFIFOAT NOPROTO { int mkfifoat(int fd, const char *path, \ + mode_t mode); } +493 AUE_MKNODAT NOPROTO { int mknodat(int fd, const char *path, \ + mode_t mode, dev_t dev); } +494 AUE_OPENAT_RWTC NOPROTO { int openat(int fd, const char *path, \ + int flag, mode_t mode); } +495 AUE_READLINKAT NOPROTO { int readlinkat(int fd, const char *path, \ + char *buf, size_t bufsize); } +496 AUE_RENAMEAT NOPROTO { int renameat(int oldfd, const char *old, \ + int newfd, const char *new); } +497 AUE_SYMLINKAT NOPROTO { int symlinkat(const char *path1, int fd, \ + const char *path2); } +498 AUE_UNLINKAT NOPROTO { int unlinkat(int fd, const 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 2b1d2b0..f569c9c 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.109 2008/01/13 14:43:5 #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,30 @@ 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; - - oldpath = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); - error = copyinstr(args->filename, oldpath, MAXPATHLEN, NULL); - if (error) { - free(oldpath, M_TEMP); - return (error); - } + char *path; + int dfd; + + if (args->dfd == LINUX_AT_FDCWD) + dfd = AT_FDCWD; + else + dfd = 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 +218,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 +568,34 @@ 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); + + if (args->dfd == LINUX_AT_FDCWD) + dfd = -1; + else + dfd = 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, args->mode); + LFREEPATH(path); + + return (error); +} + +int linux_unlink(struct thread *td, struct linux_unlink_args *args) { char *path; @@ -680,6 +620,41 @@ 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); + + if (args->dfd == LINUX_AT_FDCWD) + dfd = AT_FDCWD; + else + dfd = 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 +689,29 @@ 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; + + if (args->dfd == LINUX_AT_FDCWD) + dfd = AT_FDCWD; + else + dfd = 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 +729,28 @@ 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; + + if (args->dfd == LINUX_AT_FDCWD) + dfd = AT_FDCWD; + else + dfd = 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 +775,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 +792,40 @@ 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; + + if (args->olddfd == LINUX_AT_FDCWD) + olddfd = AT_FDCWD; + else + olddfd = args->olddfd; + + if (args->newdfd == LINUX_AT_FDCWD) + newdfd = AT_FDCWD; + else + newdfd = 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 +833,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 +850,36 @@ 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; + + if (args->newdfd == LINUX_AT_FDCWD) + dfd = AT_FDCWD; + else + dfd = 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 +899,30 @@ 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; + + if (args->dfd == LINUX_AT_FDCWD) + dfd = AT_FDCWD; + else + dfd = 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 +962,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 +979,49 @@ 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); + + if (args->olddfd == LINUX_AT_FDCWD) + olddfd = AT_FDCWD; + else + olddfd = args->olddfd; + + if (args->newdfd == LINUX_AT_FDCWD) + newdfd = AT_FDCWD; + else + newdfd = 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; @@ -1336,6 +1487,35 @@ 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; + + if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW) + return (EINVAL); + + if (args->dfd == LINUX_AT_FDCWD) + dfd = AT_FDCWD; + else + dfd = 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 + + if (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) + error = kern_lchownat(td, dfd, path, UIO_SYSSPACE, args->uid, args->gid); + else + error = kern_chownat(td, dfd, path, UIO_SYSSPACE, args->uid, args->gid); + 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 e8c72f5..89429ce 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -86,6 +86,7 @@ __FBSDID("$FreeBSD: src/sys/compat/linux/linux_misc.c,v 1.216 2008/01/13 14:43:5 #include #endif +#include #include #include #include @@ -820,6 +821,43 @@ 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; + + if (args->dfd == LINUX_AT_FDCWD) + dfd = AT_FDCWD; + else + dfd = 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 @@ -947,6 +985,60 @@ 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; + + if (args->dfd == LINUX_AT_FDCWD) + dfd = AT_FDCWD; + else + dfd = 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..c54710d 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,37 @@ 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; + + if (args->dfd == LINUX_AT_FDCWD) + dfd = AT_FDCWD; + else + dfd = 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 83220e0..9a7b611 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.42 2006/07/21 20:40:13 #include #include #include +#include #include #include #include @@ -258,7 +259,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 48138a5..6d89717 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 df4aca5..e7d8d3f 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 39abce4..f773834 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 a55ba68..939937c 100644 --- a/sys/i386/linux/linux_proto.h +++ b/sys/i386/linux/linux_proto.h @@ -900,45 +900,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; diff --git a/sys/i386/linux/linux_sysent.c b/sys/i386/linux/linux_sysent.c index 46adc59..c9160d3 100644 --- a/sys/i386/linux/linux_sysent.c +++ b/sys/i386/linux/linux_sysent.c @@ -315,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_NULL, NULL, 0, 0 }, /* 296 = linux_mkdirat */ + { AS(linux_mknodat_args), (sy_call_t *)linux_mknodat, AUE_NULL, NULL, 0, 0 }, /* 297 = linux_mknodat */ + { AS(linux_fchownat_args), (sy_call_t *)linux_fchownat, AUE_NULL, NULL, 0, 0 }, /* 298 = linux_fchownat */ + { AS(linux_futimesat_args), (sy_call_t *)linux_futimesat, AUE_NULL, NULL, 0, 0 }, /* 299 = linux_futimesat */ + { AS(linux_fstatat64_args), (sy_call_t *)linux_fstatat64, AUE_NULL, NULL, 0, 0 }, /* 300 = linux_fstatat64 */ + { AS(linux_unlinkat_args), (sy_call_t *)linux_unlinkat, AUE_NULL, NULL, 0, 0 }, /* 301 = linux_unlinkat */ + { AS(linux_renameat_args), (sy_call_t *)linux_renameat, AUE_NULL, NULL, 0, 0 }, /* 302 = linux_renameat */ + { AS(linux_linkat_args), (sy_call_t *)linux_linkat, AUE_NULL, NULL, 0, 0 }, /* 303 = linux_linkat */ + { AS(linux_symlinkat_args), (sy_call_t *)linux_symlinkat, AUE_NULL, NULL, 0, 0 }, /* 304 = linux_symlinkat */ + { AS(linux_readlinkat_args), (sy_call_t *)linux_readlinkat, AUE_NULL, NULL, 0, 0 }, /* 305 = linux_readlinkat */ + { AS(linux_fchmodat_args), (sy_call_t *)linux_fchmodat, AUE_NULL, NULL, 0, 0 }, /* 306 = linux_fchmodat */ + { AS(linux_faccessat_args), (sy_call_t *)linux_faccessat, AUE_NULL, 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 59e1eac..d271ae8 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.150 2007/09/20 13:46:2 #include #include #include +#include #include #include #include @@ -777,7 +778,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 cb35fcf..7109211 100644 --- a/sys/i386/linux/syscalls.master +++ b/sys/i386/linux/syscalls.master @@ -474,20 +474,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_NULL STD { int linux_mkdirat(l_int dfd, const char *pathname, \ + l_int mode); } +297 AUE_NULL STD { int linux_mknodat(l_int dfd, const char *filename, \ + l_int mode, l_uint dev); } +298 AUE_NULL STD { int linux_fchownat(l_int dfd, const char *filename, \ + l_uid16_t uid, l_gid16_t gid, l_int flag); } +299 AUE_NULL STD { int linux_futimesat(l_int dfd, char *filename, \ + struct l_timeval *utimes); } +300 AUE_NULL STD { int linux_fstatat64(l_int dfd, char *pathname, \ + struct l_stat64 *statbuf, l_int flag); } +301 AUE_NULL STD { int linux_unlinkat(l_int dfd, const char *pathname, \ + l_int flag); } +302 AUE_NULL STD { int linux_renameat(l_int olddfd, const char *oldname, \ + l_int newdfd, const char *newname); } +303 AUE_NULL STD { int linux_linkat(l_int olddfd, const char *oldname, \ + l_int newdfd, const char *newname, l_int flags); } +304 AUE_NULL STD { int linux_symlinkat(const char *oldname, l_int newdfd, \ + const char *newname); } +305 AUE_NULL STD { int linux_readlinkat(l_int dfd, const char *path, \ + char *buf, l_int bufsiz); } +306 AUE_NULL STD { int linux_fchmodat(l_int dfd, const char *filename, \ + l_mode_t mode); } +307 AUE_NULL 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 8a43640..45fc6ec 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.233 2008/02/12 20:11:54 ru Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.237 2008/02/12 20:09:04 ru Exp */ @@ -513,4 +513,19 @@ struct sysent sysent[] = { { AS(thr_kill2_args), (sy_call_t *)thr_kill2, AUE_KILL, NULL, 0, 0 }, /* 481 = thr_kill2 */ { AS(shm_open_args), (sy_call_t *)shm_open, AUE_SHMOPEN, NULL, 0, 0 }, /* 482 = shm_open */ { AS(shm_unlink_args), (sy_call_t *)shm_unlink, AUE_SHMUNLINK, NULL, 0, 0 }, /* 483 = shm_unlink */ + { AS(faccessat_args), (sy_call_t *)faccessat, AUE_FACCESSAT, NULL, 0, 0 }, /* 484 = faccessat */ + { AS(fchmodat_args), (sy_call_t *)fchmodat, AUE_FCHMODAT, NULL, 0, 0 }, /* 485 = fchmodat */ + { AS(fchownat_args), (sy_call_t *)fchownat, AUE_FCHOWNAT, NULL, 0, 0 }, /* 486 = fchownat */ + { AS(fexecve_args), (sy_call_t *)fexecve, AUE_FEXECVE, NULL, 0, 0 }, /* 487 = fexecve */ + { AS(fstatat_args), (sy_call_t *)fstatat, AUE_FSTATAT, NULL, 0, 0 }, /* 488 = fstatat */ + { AS(futimesat_args), (sy_call_t *)futimesat, AUE_FUTIMESAT, NULL, 0, 0 }, /* 489 = futimesat */ + { AS(linkat_args), (sy_call_t *)linkat, AUE_LINKAT, NULL, 0, 0 }, /* 490 = linkat */ + { AS(mkdirat_args), (sy_call_t *)mkdirat, AUE_MKDIRAT, NULL, 0, 0 }, /* 491 = mkdirat */ + { AS(mkfifoat_args), (sy_call_t *)mkfifoat, AUE_MKFIFOAT, NULL, 0, 0 }, /* 492 = mkfifoat */ + { AS(mknodat_args), (sy_call_t *)mknodat, AUE_MKNODAT, NULL, 0, 0 }, /* 493 = mknodat */ + { AS(openat_args), (sy_call_t *)openat, AUE_OPENAT_RWTC, NULL, 0, 0 }, /* 494 = openat */ + { AS(readlinkat_args), (sy_call_t *)readlinkat, AUE_READLINKAT, NULL, 0, 0 }, /* 495 = readlinkat */ + { AS(renameat_args), (sy_call_t *)renameat, AUE_RENAMEAT, NULL, 0, 0 }, /* 496 = renameat */ + { AS(symlinkat_args), (sy_call_t *)symlinkat, AUE_SYMLINKAT, NULL, 0, 0 }, /* 497 = symlinkat */ + { AS(unlinkat_args), (sy_call_t *)unlinkat, AUE_UNLINKAT, NULL, 0, 0 }, /* 498 = unlinkat */ }; diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 270056a..6aaa909 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1995,7 +1995,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. */ @@ -2007,6 +2007,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); @@ -2085,6 +2089,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 c46842b..0a1d32c 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/kern_kse.c b/sys/kern/kern_kse.c index 4be5c05..9f22eaf 100644 --- a/sys/kern/kern_kse.c +++ b/sys/kern/kern_kse.c @@ -69,7 +69,6 @@ static int thread_alloc_spare(struct thread *td); static struct thread *thread_schedule_upcall(struct thread *td, struct kse_upcall *ku); static struct kse_upcall *upcall_alloc(void); - struct mtx kse_lock; MTX_SYSINIT(kse_lock, &kse_lock, "kse lock", MTX_SPIN); diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 169c946..0de73ea 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.217 2008/02/12 20:11:54 ru Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.237 2008/02/12 20:09:04 ru Exp */ @@ -491,4 +491,19 @@ const char *syscallnames[] = { "thr_kill2", /* 481 = thr_kill2 */ "shm_open", /* 482 = shm_open */ "shm_unlink", /* 483 = shm_unlink */ + "faccessat", /* 484 = faccessat */ + "fchmodat", /* 485 = fchmodat */ + "fchownat", /* 486 = fchownat */ + "fexecve", /* 487 = fexecve */ + "fstatat", /* 488 = fstatat */ + "futimesat", /* 489 = futimesat */ + "linkat", /* 490 = linkat */ + "mkdirat", /* 491 = mkdirat */ + "mkfifoat", /* 492 = mkfifoat */ + "mknodat", /* 493 = mknodat */ + "openat", /* 494 = openat */ + "readlinkat", /* 495 = readlinkat */ + "renameat", /* 496 = renameat */ + "symlinkat", /* 497 = symlinkat */ + "unlinkat", /* 498 = unlinkat */ }; diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 62df157..5771f33 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -850,5 +850,36 @@ 482 AUE_SHMOPEN STD { int shm_open(const char *path, int flags, \ mode_t mode); } 483 AUE_SHMUNLINK STD { int shm_unlink(const char *path); } +484 AUE_FACCESSAT STD { int faccessat(int fd, const char *path, \ + int mode, int flag); } +485 AUE_FCHMODAT STD { int fchmodat(int fd, const char *path, \ + mode_t mode, int flag); } +486 AUE_FCHOWNAT STD { int fchownat(int fd, const char *path, \ + uid_t uid, gid_t gid, int flag); } +487 AUE_FEXECVE STD { int fexecve(int fd, char **argv, \ + char **envv); } +488 AUE_FSTATAT STD { int fstatat(int fd, const char *path, \ + struct stat *buf, int flag); } +489 AUE_FUTIMESAT STD { int futimesat(int fd, const char *path, \ + const struct timeval *times); } +490 AUE_LINKAT STD { int linkat(int fd1, const char *path1, \ + int fd2, const char *path2, int flag); } +491 AUE_MKDIRAT STD { int mkdirat(int fd, const char *path, \ + mode_t mode); } +492 AUE_MKFIFOAT STD { int mkfifoat(int fd, const char *path, \ + mode_t mode); } +493 AUE_MKNODAT STD { int mknodat(int fd, const char *path, \ + mode_t mode, dev_t dev); } +; XXX: see the comment for open +494 AUE_OPENAT_RWTC STD { int openat(int fd, const char *path, \ + int flag, mode_t mode); } +495 AUE_READLINKAT STD { int readlinkat(int fd, const char *path, \ + char *buf, size_t bufsize); } +496 AUE_RENAMEAT STD { int renameat(int oldfd, const char *old, \ + int newfd, const char *new); } +497 AUE_SYMLINKAT STD { int symlinkat(const char *path1, int fd, \ + const char *path2); } +498 AUE_UNLINKAT STD { int unlinkat(int fd, const 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 84838f8..67d2d5e 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.17 2008/02/12 20:11:54 ru Exp $ + * $FreeBSD$ * This file is part of the DTrace syscall provider. */ @@ -2887,6 +2887,152 @@ systrace_args(int sysnum, void *params, u_int64_t *uarg, int *n_args) *n_args = 1; break; } + /* faccessat */ + case 484: { + struct faccessat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* const char * */ + iarg[2] = p->mode; /* int */ + iarg[3] = p->flag; /* int */ + *n_args = 4; + break; + } + /* fchmodat */ + case 485: { + struct fchmodat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* const char * */ + iarg[2] = p->mode; /* mode_t */ + iarg[3] = p->flag; /* int */ + *n_args = 4; + break; + } + /* fchownat */ + case 486: { + struct fchownat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* const char * */ + uarg[2] = p->uid; /* uid_t */ + iarg[3] = p->gid; /* gid_t */ + iarg[4] = p->flag; /* int */ + *n_args = 5; + break; + } + /* fexecve */ + case 487: { + 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 488: { + struct fstatat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* const char * */ + uarg[2] = (intptr_t) p->buf; /* struct stat * */ + iarg[3] = p->flag; /* int */ + *n_args = 4; + break; + } + /* futimesat */ + case 489: { + struct futimesat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* const char * */ + uarg[2] = (intptr_t) p->times; /* const struct timeval * */ + *n_args = 3; + break; + } + /* linkat */ + case 490: { + struct linkat_args *p = params; + iarg[0] = p->fd1; /* int */ + uarg[1] = (intptr_t) p->path1; /* const char * */ + iarg[2] = p->fd2; /* int */ + uarg[3] = (intptr_t) p->path2; /* const char * */ + iarg[4] = p->flag; /* int */ + *n_args = 5; + break; + } + /* mkdirat */ + case 491: { + struct mkdirat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* const char * */ + iarg[2] = p->mode; /* mode_t */ + *n_args = 3; + break; + } + /* mkfifoat */ + case 492: { + struct mkfifoat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* const char * */ + iarg[2] = p->mode; /* mode_t */ + *n_args = 3; + break; + } + /* mknodat */ + case 493: { + struct mknodat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* const char * */ + iarg[2] = p->mode; /* mode_t */ + iarg[3] = p->dev; /* dev_t */ + *n_args = 4; + break; + } + /* openat */ + case 494: { + struct openat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* const char * */ + iarg[2] = p->flag; /* int */ + iarg[3] = p->mode; /* mode_t */ + *n_args = 4; + break; + } + /* readlinkat */ + case 495: { + struct readlinkat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* const char * */ + uarg[2] = (intptr_t) p->buf; /* char * */ + uarg[3] = p->bufsize; /* size_t */ + *n_args = 4; + break; + } + /* renameat */ + case 496: { + struct renameat_args *p = params; + iarg[0] = p->oldfd; /* int */ + uarg[1] = (intptr_t) p->old; /* const char * */ + iarg[2] = p->newfd; /* int */ + uarg[3] = (intptr_t) p->new; /* const char * */ + *n_args = 4; + break; + } + /* symlinkat */ + case 497: { + struct symlinkat_args *p = params; + uarg[0] = (intptr_t) p->path1; /* const char * */ + iarg[1] = p->fd; /* int */ + uarg[2] = (intptr_t) p->path2; /* const char * */ + *n_args = 3; + break; + } + /* unlinkat */ + case 498: { + struct unlinkat_args *p = params; + iarg[0] = p->fd; /* int */ + uarg[1] = (intptr_t) p->path; /* const 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 f42c188..a3b3fcc 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.56 2008/01/13 14:44:09 attilio Ex #include #include #include +#include #include #include #include diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index 3fb3ef8..827bc61 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -840,3 +840,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 i; + + CACHE_LOCK(); + ncp = TAILQ_FIRST(&vp->v_cache_dst); + if (!ncp) { + CACHE_UNLOCK(); + return (ENOENT); + } + for (i = 0; i < ncp->nc_nlen && i < buflen - 1; i++) + buf[i] = ncp->nc_name[i]; + buf[i] = '\0'; + CACHE_UNLOCK(); + 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 e73c9fa..c3c6c13 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.105 2008/01/13 14:44:10 attili #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 abdfa64..1c05c13 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.274 2008/02/14 17:04:31 yar Exp #include #include #include +#include #include #include #include diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 7888de0..fbc7b73 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -991,14 +991,35 @@ open(td, uap) int mode; } */ *uap; { - 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, (const char *)path, pathseg, flags, mode)); +} + +int +kern_openat(struct thread *td, int fd, const 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; @@ -1014,9 +1035,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, 0 | FOLLOW | AUDITVNODE1 | + MPSAFE, pathseg, path, fd, td); + error = falloc(td, &nfp, &indx); if (error) return (error); @@ -1025,9 +1055,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 @@ -1176,10 +1205,32 @@ 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, (const char *)path, pathseg, mode, dev)); +} + +int +kern_mknodat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, + int mode, int dev) +{ struct vnode *vp; struct mount *mp; struct vattr vattr; @@ -1209,8 +1260,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, 0 | LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -1302,9 +1353,29 @@ 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, (const char *)path, pathseg, mode)); +} + +int +kern_mkfifoat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, + int mode) +{ struct mount *mp; struct vattr vattr; int error; @@ -1314,8 +1385,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, 0 | LOCKPARENT | + SAVENAME | MPSAFE | AUDITVNODE1, pathseg, path, fd, td); if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -1385,6 +1456,29 @@ link(td, uap) return (error); } +#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 = uap->flag; + int fd1 = uap->fd1, fd2 = uap->fd2; + const char *path1 = uap->path1, *path2 = uap->path2; + + if (flag & ~AT_SYMLINK_FOLLOW) + return (EINVAL); + + return (kern_linkat(td, fd1, fd2, path1, path2, UIO_USERSPACE, + (flag & AT_SYMLINK_FOLLOW) ? FOLLOW : 0)); +} + static int hardlink_check_uid = 0; SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_uid, CTLFLAG_RW, &hardlink_check_uid, 0, @@ -1427,6 +1521,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, (const char *)path, + (const char *)link, segflg, FOLLOW)); +} + +int +kern_linkat(struct thread *td, int fd1, int fd2, const char *path1, + const char *path2, enum uio_seg segflg, int follow) +{ struct vnode *vp; struct mount *mp; struct nameidata nd; @@ -1435,7 +1537,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, 0 | follow | MPSAFE | AUDITVNODE1, + segflg, path1, fd1, td); + if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -1451,8 +1555,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, 0 | LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, + segflg, path2, fd2, td); if ((error = namei(&nd)) == 0) { lvfslocked = NDHASGIANT(&nd); if (nd.ni_vp != NULL) { @@ -1507,9 +1611,30 @@ 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, (const char *)path, AT_FDCWD, (const char *)link, + segflg)); +} + +int +kern_symlinkat(struct thread *td, const char *path1, int fd, const char *path2, + enum uio_seg segflg) +{ struct mount *mp; struct vattr vattr; char *syspath; @@ -1518,17 +1643,17 @@ kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg) int vfslocked; if (segflg == UIO_SYSSPACE) { - syspath = path; + syspath = __DECONST(char *, 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, 0 | LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, + segflg, path2, fd, td); if ((error = namei(&nd)) != 0) goto out; vfslocked = NDHASGIANT(&nd); @@ -1652,9 +1777,38 @@ unlink(td, uap) return (error); } +#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; + const 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, (const char *)path, pathseg)); +} + +int +kern_unlinkat(struct thread *td, int fd, const char *path, enum uio_seg pathseg) +{ struct mount *mp; struct vnode *vp; int error; @@ -1663,8 +1817,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, 0 | LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); if ((error = namei(&nd)) != 0) return (error == EINVAL ? EPERM : error); vfslocked = NDHASGIANT(&nd); @@ -1905,15 +2059,43 @@ 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); + /* XXX: what about mode? */ + return (kern_accessat(td, uap->fd, uap->path, UIO_USERSPACE, + uap->flag)); +} + int kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags) { + return (kern_accessat(td, AT_FDCWD, (const char *)path, pathseg, + flags)); +} + +int +kern_accessat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, + int flags) +{ struct ucred *cred, *tmpcred; - register struct vnode *vp; + struct vnode *vp; struct nameidata nd; int vfslocked; int error; + NDINIT_AT(&nd, LOOKUP, 0 | 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 @@ -1921,11 +2103,14 @@ kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags) */ cred = td->td_ucred; tmpcred = crdup(cred); - tmpcred->cr_uid = cred->cr_ruid; - tmpcred->cr_groups[0] = cred->cr_rgid; + if (flags & AT_EACCESS) { + tmpcred->cr_uid = cred->cr_uid; + tmpcred->cr_groups[0] = cred->cr_groups[0]; + } else { + 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 ((error = namei(&nd)) != 0) goto out1; vfslocked = NDHASGIANT(&nd); @@ -2098,16 +2283,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, (const char *)path, pathseg, sbp)); +} + +int +kern_statat(struct thread *td, int flag, int fd, const 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, 0 | + ((flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW) | + LOCKSHARED | LOCKLEAF | AUDITVNODE1 | MPSAFE, + pathseg, path, fd, td); + if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -2117,10 +2335,9 @@ kern_stat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp) VFS_UNLOCK_GIANT(vfslocked); if (mtx_owned(&Giant)) printf("stat(%d): %s\n", vfslocked, path); - if (error) - return (error); - *sbp = sb; - return (0); + if (error == 0) + *sbp = sb; + return (error); } /* @@ -2152,26 +2369,8 @@ 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; - return (0); + return (kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, + (const char *)path, pathseg, sbp)); } /* @@ -2323,20 +2522,43 @@ 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, (const char *)path, pathseg, buf, + bufseg, count)); +} + +int +kern_readlinkat(struct thread *td, int fd, const 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, 0 | NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); + if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); @@ -2560,15 +2782,48 @@ 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; + const char *path = uap->path; + mode_t mode = uap->mode; + + if (flag & ~AT_SYMLINK_NOFOLLOW) + return (EINVAL); + + if (flag & AT_SYMLINK_NOFOLLOW) + return (kern_lchmodat(td, fd, path, UIO_USERSPACE, mode)); + else + return (kern_chmodat(td, fd, path, UIO_USERSPACE, mode)); +} + int kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int mode) { - int error; + return (kern_chmodat(td, AT_FDCWD, (const char *)path, pathseg, mode)); +} + +int +kern_chmodat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, + mode_t mode) +{ struct nameidata nd; - int vfslocked; + int error, vfslocked; AUDIT_ARG(mode, mode); - NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td); + NDINIT_AT(&nd, LOOKUP, 0 | FOLLOW | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); + if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -2596,18 +2851,26 @@ lchmod(td, uap) int mode; } */ *uap; { + return (kern_lchmodat(td, AT_FDCWD, uap->path, UIO_USERSPACE, uap->mode)); +} + + +int +kern_lchmodat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, + mode_t mode) +{ int error; struct nameidata nd; int vfslocked; - AUDIT_ARG(mode, (mode_t)uap->mode); - NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, UIO_USERSPACE, - uap->path, td); + AUDIT_ARG(mode, mode); + NDINIT_AT(&nd, LOOKUP, NOFOLLOW | 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); @@ -2705,16 +2968,44 @@ chown(td, uap) return (kern_chown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid)); } +#ifndef _SYS_SYSPROTO_H_ +#endif +int +fchownat(struct thread *td, struct fchownat_args *uap) +{ + int flag = uap->flag; + int fd = uap->fd; + const char *path = uap->path; + uid_t uid = uap->uid; + uid_t gid = uap->gid; + + if (flag & ~AT_SYMLINK_NOFOLLOW) + return (EINVAL); + + if (flag & AT_SYMLINK_NOFOLLOW) + return (kern_lchownat(td, fd, path, UIO_USERSPACE, uid, gid)); + else + return (kern_chownat(td, fd, path, UIO_USERSPACE, uid, gid)); +} + int kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid, int gid) { - int error; + return (kern_chownat(td, AT_FDCWD, (const char *)path, pathseg, uid, gid)); +} + +int +kern_chownat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, + int uid, int gid) +{ struct nameidata nd; - int vfslocked; + int error, vfslocked; AUDIT_ARG(owner, uid, gid); - NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td); + NDINIT_AT(&nd, LOOKUP, 0 | FOLLOW | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); + if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -2752,12 +3043,20 @@ int kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid, int gid) { - int error; + return (kern_lchownat(td, AT_FDCWD, (const char *)path, pathseg, uid, gid)); +} + +int +kern_lchownat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, + int uid, int gid) +{ struct nameidata nd; - int vfslocked; + int error, vfslocked; AUDIT_ARG(owner, uid, gid); - NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td); + NDINIT_AT(&nd, LOOKUP, 0 | NOFOLLOW | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); + if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -2907,18 +3206,36 @@ utimes(td, uap) UIO_USERSPACE)); } +#ifndef _SYS_SYSPROTO_H_ +#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, (const char *)path, pathseg, + (const struct timeval *)tptr, tptrseg)); +} + +int +kern_utimesat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, + const 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, 0 | FOLLOW | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); + if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -3204,9 +3521,32 @@ 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, (const char *)from, AT_FDCWD, + (const char *)to, pathseg)); +} + +int +kern_renameat(struct thread *td, int oldfd, const char *old, int newfd, + const char *new, enum uio_seg pathseg) +{ struct mount *mp = NULL; struct vnode *tvp, *fvp, *tdvp; struct nameidata fromnd, tond; @@ -3216,12 +3556,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); @@ -3242,8 +3583,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) { @@ -3313,6 +3654,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); @@ -3339,9 +3681,29 @@ 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, (const char *)path, segflg, mode)); +} + +int +kern_mkdirat(struct thread *td, int fd, const char *path, enum uio_seg segflg, + int mode) +{ struct mount *mp; struct vnode *vp; struct vattr vattr; @@ -3352,8 +3714,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); @@ -3429,6 +3791,12 @@ rmdir(td, uap) int kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg) { + return (kern_rmdirat(td, AT_FDCWD, (const char *)path, pathseg)); +} + +int +kern_rmdirat(struct thread *td, int fd, const char *path, enum uio_seg pathseg) +{ struct mount *mp; struct vnode *vp; int error; @@ -3437,8 +3805,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 5ea420f..36825a4 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 380acd7..9079f39 100644 --- a/sys/sys/fcntl.h +++ b/sys/sys/fcntl.h @@ -105,6 +105,17 @@ 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 +#define AT_FDCWD -100 /* Use the current working directory + * to determine the target of relative + * file paths. + */ +#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 +125,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 +144,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) @@ -225,6 +245,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 461be13..e65cdcb 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.214 2008/02/12 20:11:53 ru Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.237 2008/02/12 20:09:04 ru Exp */ @@ -403,4 +403,19 @@ #define SYS_thr_kill2 481 #define SYS_shm_open 482 #define SYS_shm_unlink 483 -#define SYS_MAXSYSCALL 484 +#define SYS_faccessat 484 +#define SYS_fchmodat 485 +#define SYS_fchownat 486 +#define SYS_fexecve 487 +#define SYS_fstatat 488 +#define SYS_futimesat 489 +#define SYS_linkat 490 +#define SYS_mkdirat 491 +#define SYS_mkfifoat 492 +#define SYS_mknodat 493 +#define SYS_openat 494 +#define SYS_readlinkat 495 +#define SYS_renameat 496 +#define SYS_symlinkat 497 +#define SYS_unlinkat 498 +#define SYS_MAXSYSCALL 499 diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk index 3a97c25..812b7de 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.169 2008/02/12 20:11:53 ru Exp $ +# $FreeBSD$ # created from FreeBSD: src/sys/kern/syscalls.master,v 1.237 2008/02/12 20:09:04 ru Exp MIASM = \ syscall.o \ @@ -351,4 +351,19 @@ MIASM = \ ftruncate.o \ thr_kill2.o \ shm_open.o \ - shm_unlink.o + shm_unlink.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..6d8139c 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -56,16 +56,24 @@ 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, const char *path, + enum uio_seg pathseg, int flags); 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, const 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_chownat(struct thread *td, int fd, const char *path, + enum uio_seg pathseg, int uid, int gid); +int kern_lchmodat(struct thread *td, int fd, const char *path, + enum uio_seg pathseg, mode_t mode); int kern_clock_getres(struct thread *td, clockid_t clock_id, struct timespec *ts); int kern_clock_gettime(struct thread *td, clockid_t clock_id, @@ -103,18 +111,30 @@ int kern_kldload(struct thread *td, const char *file, int *fileid); int kern_kldunload(struct thread *td, int fileid, int flags); int kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid, int gid); +int kern_lchownat(struct thread *td, int fd, const 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, const char *path1, + const 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, const 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, const 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, const 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, const 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 +142,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, const 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 +152,17 @@ 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, const 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, const char *old, int newfd, + const 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, const 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 +193,24 @@ 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, const 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, const char *path1, int fd, + const 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, const 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, const char *path, enum uio_seg pathseg, + const 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 29e5603..11365c1 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.218 2008/02/12 20:11:54 ru Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.237 2008/02/12 20:09:04 ru Exp */ @@ -1528,6 +1528,92 @@ struct shm_open_args { struct shm_unlink_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; }; +struct faccessat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const 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_(const char *)]; const char * path; char path_r_[PADR_(const 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_(const char *)]; const char * path; char path_r_[PADR_(const 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_(const char *)]; const char * path; char path_r_[PADR_(const 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_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char times_l_[PADL_(const struct timeval *)]; const struct timeval * times; char times_r_[PADR_(const struct timeval *)]; +}; +struct linkat_args { + char fd1_l_[PADL_(int)]; int fd1; char fd1_r_[PADR_(int)]; + char path1_l_[PADL_(const char *)]; const char * path1; char path1_r_[PADR_(const char *)]; + char fd2_l_[PADL_(int)]; int fd2; char fd2_r_[PADR_(int)]; + char path2_l_[PADL_(const char *)]; const char * path2; char path2_r_[PADR_(const 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_(const char *)]; const char * path; char path_r_[PADR_(const 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_(const char *)]; const char * path; char path_r_[PADR_(const 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_(const char *)]; const char * path; char path_r_[PADR_(const 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_(const char *)]; const char * path; char path_r_[PADR_(const 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_(const char *)]; const char * path; char path_r_[PADR_(const 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_(const char *)]; const char * old; char old_r_[PADR_(const char *)]; + char newfd_l_[PADL_(int)]; int newfd; char newfd_r_[PADR_(int)]; + char new_l_[PADL_(const char *)]; const char * new; char new_r_[PADR_(const char *)]; +}; +struct symlinkat_args { + char path1_l_[PADL_(const char *)]; const char * path1; char path1_r_[PADR_(const char *)]; + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char path2_l_[PADL_(const char *)]; const char * path2; char path2_r_[PADR_(const char *)]; +}; +struct unlinkat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const 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 *); @@ -1869,6 +1955,21 @@ int ftruncate(struct thread *, struct ftruncate_args *); int thr_kill2(struct thread *, struct thr_kill2_args *); int shm_open(struct thread *, struct shm_open_args *); int shm_unlink(struct thread *, struct shm_unlink_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 @@ -2435,6 +2536,21 @@ int freebsd4_sigreturn(struct thread *, struct freebsd4_sigreturn_args *); #define SYS_AUE_thr_kill2 AUE_KILL #define SYS_AUE_shm_open AUE_SHMOPEN #define SYS_AUE_shm_unlink AUE_SHMUNLINK +#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 1bbe8b8..d9ae827 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -581,6 +581,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 156f93e..b0da1de 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.140 2008/01/24 12:34:29 a #include #include #include +#include #include #include #include