diff options
-rw-r--r-- | sys/kern/vfs_syscalls.c | 577 | ||||
-rw-r--r-- | sys/sys/syscallsubr.h | 30 |
2 files changed, 482 insertions, 125 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index c20b6e6..f00563f 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -996,13 +996,37 @@ open(td, uap) } */ *uap; { - return kern_open(td, uap->path, UIO_USERSPACE, uap->flags, uap->mode); + return (kern_open(td, uap->path, UIO_USERSPACE, uap->flags, uap->mode)); +} + +#ifndef _SYS_SYSPROTO_H_ +struct openat_args { + int fd; + char *path; + int flag; + int mode; +}; +#endif +int +openat(struct thread *td, struct openat_args *uap) +{ + + return (kern_openat(td, uap->fd, uap->path, UIO_USERSPACE, uap->flag, + uap->mode)); } int kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags, int mode) { + + return (kern_openat(td, AT_FDCWD, path, pathseg, flags, mode)); +} + +int +kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg, + int flags, int mode) +{ struct proc *p = td->td_proc; struct filedesc *fdp = p->p_fd; struct file *fp; @@ -1039,9 +1063,10 @@ 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); + NDINIT_AT(&nd, LOOKUP, FOLLOW | AUDITVNODE1 | MPSAFE, pathseg, path, fd, + 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 @@ -1190,10 +1215,34 @@ mknod(td, uap) return (kern_mknod(td, uap->path, UIO_USERSPACE, uap->mode, uap->dev)); } +#ifndef _SYS_SYSPROTO_H_ +struct mknodat_args { + int fd; + char *path; + mode_t mode; + dev_t dev; +}; +#endif +int +mknodat(struct thread *td, struct mknodat_args *uap) +{ + + return (kern_mknodat(td, uap->fd, uap->path, UIO_USERSPACE, uap->mode, + uap->dev)); +} + int kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode, int dev) { + + return (kern_mknodat(td, AT_FDCWD, path, pathseg, mode, dev)); +} + +int +kern_mknodat(struct thread *td, int fd, char *path, enum uio_seg pathseg, + int mode, int dev) +{ struct vnode *vp; struct mount *mp; struct vattr vattr; @@ -1223,8 +1272,8 @@ kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode, return (error); restart: bwillwrite(); - NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, - pathseg, path, td); + NDINIT_AT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -1316,9 +1365,32 @@ mkfifo(td, uap) return (kern_mkfifo(td, uap->path, UIO_USERSPACE, uap->mode)); } +#ifndef _SYS_SYSPROTO_H_ +struct mkfifoat_args { + int fd; + char *path; + mode_t mode; +}; +#endif +int +mkfifoat(struct thread *td, struct mkfifoat_args *uap) +{ + + return (kern_mkfifoat(td, uap->fd, uap->path, UIO_USERSPACE, + uap->mode)); +} + int kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode) { + + return (kern_mkfifoat(td, AT_FDCWD, path, pathseg, mode)); +} + +int +kern_mkfifoat(struct thread *td, int fd, char *path, enum uio_seg pathseg, + int mode) +{ struct mount *mp; struct vattr vattr; int error; @@ -1328,8 +1400,8 @@ kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode) AUDIT_ARG(mode, mode); restart: bwillwrite(); - NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, - pathseg, path, td); + NDINIT_AT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -1393,10 +1465,30 @@ link(td, uap) char *link; } */ *uap; { - int error; - error = kern_link(td, uap->path, uap->link, UIO_USERSPACE); - return (error); + return (kern_link(td, uap->path, uap->link, UIO_USERSPACE)); +} + +#ifndef _SYS_SYSPROTO_H_ +struct linkat_args { + int fd1; + char *path1; + int fd2; + char *path2; + int flag; +}; +#endif +int +linkat(struct thread *td, struct linkat_args *uap) +{ + int flag; + + flag = uap->flag; + if (flag & ~AT_SYMLINK_FOLLOW) + return (EINVAL); + + return (kern_linkat(td, uap->fd1, uap->fd2, uap->path1, uap->path2, + UIO_USERSPACE, (flag & AT_SYMLINK_FOLLOW) ? FOLLOW : NOFOLLOW)); } static int hardlink_check_uid = 0; @@ -1441,6 +1533,14 @@ can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred) int kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg) { + + return (kern_linkat(td, AT_FDCWD, AT_FDCWD, path,link, segflg, FOLLOW)); +} + +int +kern_linkat(struct thread *td, int fd1, int fd2, char *path1, char *path2, + enum uio_seg segflg, int follow) +{ struct vnode *vp; struct mount *mp; struct nameidata nd; @@ -1449,7 +1549,9 @@ kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg) int error; bwillwrite(); - NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, segflg, path, td); + NDINIT_AT(&nd, LOOKUP, follow | MPSAFE | AUDITVNODE1, segflg, path1, + fd1, td); + if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -1465,8 +1567,8 @@ kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg) VFS_UNLOCK_GIANT(vfslocked); return (error); } - NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE2, - segflg, link, td); + NDINIT_AT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, + segflg, path2, fd2, td); if ((error = namei(&nd)) == 0) { lvfslocked = NDHASGIANT(&nd); if (nd.ni_vp != NULL) { @@ -1521,9 +1623,32 @@ symlink(td, uap) return (kern_symlink(td, uap->path, uap->link, UIO_USERSPACE)); } +#ifndef _SYS_SYSPROTO_H_ +struct symlinkat_args { + char *path; + int fd; + char *path2; +}; +#endif +int +symlinkat(struct thread *td, struct symlinkat_args *uap) +{ + + return (kern_symlinkat(td, uap->path1, uap->fd, uap->path2, + UIO_USERSPACE)); +} + int kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg) { + + return (kern_symlinkat(td, path, AT_FDCWD, link, segflg)); +} + +int +kern_symlinkat(struct thread *td, char *path1, int fd, char *path2, + enum uio_seg segflg) +{ struct mount *mp; struct vattr vattr; char *syspath; @@ -1532,17 +1657,17 @@ kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg) int vfslocked; if (segflg == UIO_SYSSPACE) { - syspath = path; + syspath = path1; } else { syspath = uma_zalloc(namei_zone, M_WAITOK); - if ((error = copyinstr(path, syspath, MAXPATHLEN, NULL)) != 0) + if ((error = copyinstr(path1, syspath, MAXPATHLEN, NULL)) != 0) goto out; } AUDIT_ARG(text, syspath); restart: bwillwrite(); - NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, - segflg, link, td); + NDINIT_AT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, + segflg, path2, fd, td); if ((error = namei(&nd)) != 0) goto out; vfslocked = NDHASGIANT(&nd); @@ -1660,15 +1785,43 @@ unlink(td, uap) char *path; } */ *uap; { - int error; - error = kern_unlink(td, uap->path, UIO_USERSPACE); - return (error); + return (kern_unlink(td, uap->path, UIO_USERSPACE)); +} + +#ifndef _SYS_SYSPROTO_H_ +struct unlinkat_args { + int fd; + char *path; + int flag; +}; +#endif +int +unlinkat(struct thread *td, struct unlinkat_args *uap) +{ + int flag = uap->flag; + int fd = uap->fd; + char *path = uap->path; + + if (flag & ~AT_REMOVEDIR) + return (EINVAL); + + if (flag & AT_REMOVEDIR) + return (kern_rmdirat(td, fd, path, UIO_USERSPACE)); + else + return (kern_unlinkat(td, fd, path, UIO_USERSPACE)); } int kern_unlink(struct thread *td, char *path, enum uio_seg pathseg) { + + return (kern_unlinkat(td, AT_FDCWD, path, pathseg)); +} + +int +kern_unlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg) +{ struct mount *mp; struct vnode *vp; int error; @@ -1677,8 +1830,8 @@ kern_unlink(struct thread *td, char *path, enum uio_seg pathseg) restart: bwillwrite(); - NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); + NDINIT_AT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); if ((error = namei(&nd)) != 0) return (error == EINVAL ? EPERM : error); vfslocked = NDHASGIANT(&nd); @@ -1919,11 +2072,36 @@ access(td, uap) return (kern_access(td, uap->path, UIO_USERSPACE, uap->flags)); } +#ifndef _SYS_SYSPROTO_H_ +struct faccessat_args { + int dirfd; + char *path; + int mode; + int flag; +} +#endif +int faccessat(struct thread *td, struct faccessat_args *uap) +{ + + if (uap->flag & ~AT_EACCESS) + return (EINVAL); + return (kern_accessat(td, uap->fd, uap->path, UIO_USERSPACE, uap->flag, + uap->mode)); +} + int -kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags) +kern_access(struct thread *td, char *path, enum uio_seg pathseg, int mode) +{ + + return (kern_accessat(td, AT_FDCWD, path, pathseg, 0, mode)); +} + +int +kern_accessat(struct thread *td, int fd, char *path, enum uio_seg pathseg, + int flags, int mode) { struct ucred *cred, *tmpcred; - register struct vnode *vp; + struct vnode *vp; struct nameidata nd; int vfslocked; int error; @@ -1933,25 +2111,30 @@ kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags) * is potentially shared. This could also mess up socket * buffer accounting which can run in an interrupt context. */ - cred = td->td_ucred; - tmpcred = crdup(cred); - tmpcred->cr_uid = cred->cr_ruid; - tmpcred->cr_groups[0] = cred->cr_rgid; - td->td_ucred = tmpcred; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); + if (!(flags & AT_EACCESS)) { + cred = td->td_ucred; + tmpcred = crdup(cred); + tmpcred->cr_uid = cred->cr_ruid; + tmpcred->cr_groups[0] = cred->cr_rgid; + td->td_ucred = tmpcred; + } else + cred = tmpcred = td->td_ucred; + NDINIT_AT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); if ((error = namei(&nd)) != 0) goto out1; vfslocked = NDHASGIANT(&nd); vp = nd.ni_vp; - error = vn_access(vp, flags, tmpcred, td); + error = vn_access(vp, mode, tmpcred, td); NDFREE(&nd, NDF_ONLY_PNBUF); vput(vp); VFS_UNLOCK_GIANT(vfslocked); out1: - td->td_ucred = cred; - crfree(tmpcred); + if (!(flags & AT_EACCESS)) { + td->td_ucred = cred; + crfree(tmpcred); + } return (error); } @@ -1979,22 +2162,8 @@ eaccess(td, uap) int kern_eaccess(struct thread *td, char *path, enum uio_seg pathseg, int flags) { - struct nameidata nd; - struct vnode *vp; - int vfslocked; - int error; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); - if ((error = namei(&nd)) != 0) - return (error); - vp = nd.ni_vp; - vfslocked = NDHASGIANT(&nd); - error = vn_access(vp, flags, td->td_ucred, td); - NDFREE(&nd, NDF_ONLY_PNBUF); - vput(vp); - VFS_UNLOCK_GIANT(vfslocked); - return (error); + return (kern_accessat(td, AT_FDCWD, path, pathseg, AT_EACCESS, flags)); } #if defined(COMPAT_43) @@ -2112,16 +2281,49 @@ stat(td, uap) return (error); } +#ifndef _SYS_SYSPROTO_H_ +struct fstatat_args { + int fd; + char *path; + struct stat *buf; + int flag; +} +#endif +int +fstatat(struct thread *td, struct fstatat_args *uap) +{ + struct stat sb; + int error; + + error = kern_statat(td, uap->flag, uap->fd, uap->path, + UIO_USERSPACE, &sb); + if (error == 0) + error = copyout(&sb, uap->buf, sizeof (sb)); + return (error); +} + int kern_stat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp) { + + return (kern_statat(td, 0, AT_FDCWD, path, pathseg, sbp)); +} + +int +kern_statat(struct thread *td, int flag, int fd, char *path, + enum uio_seg pathseg, struct stat *sbp) +{ struct nameidata nd; struct stat sb; int error, vfslocked; - NDINIT(&nd, LOOKUP, - FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); + if (flag & ~AT_SYMLINK_NOFOLLOW) + return (EINVAL); + + NDINIT_AT(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : + FOLLOW) | LOCKSHARED | LOCKLEAF | AUDITVNODE1 | MPSAFE, pathseg, + path, fd, td); + if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -2170,30 +2372,9 @@ lstat(td, uap) int kern_lstat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp) { - struct vnode *vp; - struct stat sb; - struct nameidata nd; - int error, vfslocked; - NDINIT(&nd, LOOKUP, - NOFOLLOW | LOCKLEAF | LOCKSHARED | MPSAFE | AUDITVNODE1, - pathseg, path, td); - if ((error = namei(&nd)) != 0) - return (error); - vfslocked = NDHASGIANT(&nd); - vp = nd.ni_vp; - error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td); - NDFREE(&nd, NDF_ONLY_PNBUF); - vput(vp); - VFS_UNLOCK_GIANT(vfslocked); - if (error) - return (error); - *sbp = sb; -#ifdef KTRACE - if (KTRPOINT(td, KTR_STRUCT)) - ktrstat(&sb); -#endif - return (0); + return (kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, path, pathseg, + sbp)); } /* @@ -2345,20 +2526,45 @@ readlink(td, uap) return (kern_readlink(td, uap->path, UIO_USERSPACE, uap->buf, UIO_USERSPACE, uap->count)); } +#ifndef _SYS_SYSPROTO_H_ +struct readlinkat_args { + int fd; + char *path; + char *buf; + size_t bufsize; +}; +#endif +int +readlinkat(struct thread *td, struct readlinkat_args *uap) +{ + + return (kern_readlinkat(td, uap->fd, uap->path, UIO_USERSPACE, + uap->buf, UIO_USERSPACE, uap->bufsize)); +} int kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf, enum uio_seg bufseg, size_t count) { - register struct vnode *vp; + + return (kern_readlinkat(td, AT_FDCWD, path, pathseg, buf, bufseg, + count)); +} + +int +kern_readlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg, + char *buf, enum uio_seg bufseg, size_t count) +{ + struct vnode *vp; struct iovec aiov; struct uio auio; int error; struct nameidata nd; int vfslocked; - NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); + NDINIT_AT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); + if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); @@ -2582,23 +2788,33 @@ chmod(td, uap) return (kern_chmod(td, uap->path, UIO_USERSPACE, uap->mode)); } +#ifndef _SYS_SYSPROTO_H_ +struct fchmodat_args { + int dirfd; + char *path; + mode_t mode; + int flag; +} +#endif +int +fchmodat(struct thread *td, struct fchmodat_args *uap) +{ + int flag = uap->flag; + int fd = uap->fd; + char *path = uap->path; + mode_t mode = uap->mode; + + if (flag & ~AT_SYMLINK_NOFOLLOW) + return (EINVAL); + + return (kern_fchmodat(td, fd, path, UIO_USERSPACE, mode, flag)); +} + int kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int mode) { - int error; - struct nameidata nd; - int vfslocked; - AUDIT_ARG(mode, mode); - NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td); - if ((error = namei(&nd)) != 0) - return (error); - vfslocked = NDHASGIANT(&nd); - NDFREE(&nd, NDF_ONLY_PNBUF); - error = setfmode(td, nd.ni_vp, mode); - vrele(nd.ni_vp); - VFS_UNLOCK_GIANT(vfslocked); - return (error); + return (kern_fchmodat(td, AT_FDCWD, path, pathseg, mode, 0)); } /* @@ -2618,18 +2834,30 @@ lchmod(td, uap) int mode; } */ *uap; { + + return (kern_fchmodat(td, AT_FDCWD, uap->path, UIO_USERSPACE, + uap->mode, AT_SYMLINK_NOFOLLOW)); +} + + +int +kern_fchmodat(struct thread *td, int fd, char *path, enum uio_seg pathseg, + mode_t mode, int flag) +{ int error; struct nameidata nd; int vfslocked; + int follow; - AUDIT_ARG(mode, (mode_t)uap->mode); - NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, UIO_USERSPACE, - uap->path, td); + AUDIT_ARG(mode, mode); + follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; + NDINIT_AT(&nd, LOOKUP, follow | MPSAFE | AUDITVNODE1, pathseg, path, + fd, td); if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); NDFREE(&nd, NDF_ONLY_PNBUF); - error = setfmode(td, nd.ni_vp, uap->mode); + error = setfmode(td, nd.ni_vp, mode); vrele(nd.ni_vp); VFS_UNLOCK_GIANT(vfslocked); return (error); @@ -2727,16 +2955,48 @@ chown(td, uap) return (kern_chown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid)); } +#ifndef _SYS_SYSPROTO_H_ +struct fchownat_args { + int fd; + const char * path; + uid_t uid; + gid_t gid; + int flag; +}; +#endif +int +fchownat(struct thread *td, struct fchownat_args *uap) +{ + int flag; + + flag = uap->flag; + if (flag & ~AT_SYMLINK_NOFOLLOW) + return (EINVAL); + + return (kern_fchownat(td, uap->fd, uap->path, UIO_USERSPACE, uap->uid, + uap->gid, uap->flag)); +} + int kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid, int gid) { - int error; + + return (kern_fchownat(td, AT_FDCWD, path, pathseg, uid, gid, 0)); +} + +int +kern_fchownat(struct thread *td, int fd, char *path, enum uio_seg pathseg, + int uid, int gid, int flag) +{ struct nameidata nd; - int vfslocked; + int error, vfslocked, follow; AUDIT_ARG(owner, uid, gid); - NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td); + follow = (flag & AT_SYMLINK_NOFOLLOW) == 0 ? NOFOLLOW : FOLLOW; + NDINIT_AT(&nd, LOOKUP, follow | MPSAFE | AUDITVNODE1, pathseg, path, + fd, td); + if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -2774,20 +3034,9 @@ int kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid, int gid) { - int error; - struct nameidata nd; - int vfslocked; - AUDIT_ARG(owner, uid, gid); - NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td); - if ((error = namei(&nd)) != 0) - return (error); - vfslocked = NDHASGIANT(&nd); - NDFREE(&nd, NDF_ONLY_PNBUF); - error = setfown(td, nd.ni_vp, uid, gid); - vrele(nd.ni_vp); - VFS_UNLOCK_GIANT(vfslocked); - return (error); + return (kern_fchownat(td, AT_FDCWD, path, pathseg, uid, gid, + AT_SYMLINK_NOFOLLOW)); } /* @@ -2929,18 +3178,42 @@ utimes(td, uap) UIO_USERSPACE)); } +#ifndef _SYS_SYSPROTO_H_ +struct futimesat_args { + int fd; + const char * path; + const struct timeval * times; +}; +#endif +int +futimesat(struct thread *td, struct futimesat_args *uap) +{ + + return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE, + uap->times, UIO_USERSPACE)); +} + int kern_utimes(struct thread *td, char *path, enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg) { - struct timespec ts[2]; - int error; + + return (kern_utimesat(td, AT_FDCWD, path, pathseg, tptr, tptrseg)); +} + +int +kern_utimesat(struct thread *td, int fd, char *path, enum uio_seg pathseg, + struct timeval *tptr, enum uio_seg tptrseg) +{ struct nameidata nd; - int vfslocked; + struct timespec ts[2]; + int error, vfslocked; if ((error = getutimes(tptr, tptrseg, ts)) != 0) return (error); - NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td); + NDINIT_AT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, + fd, td); + if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -3226,9 +3499,33 @@ rename(td, uap) return (kern_rename(td, uap->from, uap->to, UIO_USERSPACE)); } +#ifndef _SYS_SYSPROTO_H_ +struct renameat_args { + int oldfd; + char *old; + int newfd; + char *new; +}; +#endif +int +renameat(struct thread *td, struct renameat_args *uap) +{ + + return (kern_renameat(td, uap->oldfd, uap->old, uap->newfd, uap->new, + UIO_USERSPACE)); +} + int kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg) { + + return (kern_renameat(td, AT_FDCWD, from, AT_FDCWD, to, pathseg)); +} + +int +kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new, + enum uio_seg pathseg) +{ struct mount *mp = NULL; struct vnode *tvp, *fvp, *tdvp; struct nameidata fromnd, tond; @@ -3238,12 +3535,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); @@ -3264,8 +3562,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) { @@ -3361,9 +3659,31 @@ mkdir(td, uap) return (kern_mkdir(td, uap->path, UIO_USERSPACE, uap->mode)); } +#ifndef _SYS_SYSPROTO_H_ +struct mkdirat_args { + int fd; + char *path; + mode_t mode; +}; +#endif +int +mkdirat(struct thread *td, struct mkdirat_args *uap) +{ + + return (kern_mkdirat(td, uap->fd, uap->path, UIO_USERSPACE, uap->mode)); +} + int kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode) { + + return (kern_mkdirat(td, AT_FDCWD, path, segflg, mode)); +} + +int +kern_mkdirat(struct thread *td, int fd, char *path, enum uio_seg segflg, + int mode) +{ struct mount *mp; struct vnode *vp; struct vattr vattr; @@ -3374,8 +3694,8 @@ kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode) AUDIT_ARG(mode, mode); restart: bwillwrite(); - NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, - segflg, path, td); + NDINIT_AT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, + segflg, path, fd, td); nd.ni_cnd.cn_flags |= WILLBEDIR; if ((error = namei(&nd)) != 0) return (error); @@ -3451,6 +3771,13 @@ rmdir(td, uap) int kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg) { + + return (kern_rmdirat(td, AT_FDCWD, path, pathseg)); +} + +int +kern_rmdirat(struct thread *td, int fd, char *path, enum uio_seg pathseg) +{ struct mount *mp; struct vnode *vp; int error; @@ -3459,8 +3786,8 @@ kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg) restart: bwillwrite(); - NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); + NDINIT_AT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1, + pathseg, path, fd, td); if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h index 1612f87..c492ff4 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -56,6 +56,8 @@ int kern_accept(struct thread *td, int s, struct sockaddr **name, socklen_t *namelen, struct file **fp); int kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags); +int kern_accessat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, int flags, int mode); int kern_adjtime(struct thread *td, struct timeval *delta, struct timeval *olddelta); int kern_alternate_path(struct thread *td, const char *prefix, char *path, @@ -78,6 +80,10 @@ int kern_eaccess(struct thread *td, char *path, enum uio_seg pathseg, int flags); int kern_execve(struct thread *td, struct image_args *args, struct mac *mac_p); +int kern_fchmodat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, mode_t mode, int flag); +int kern_fchownat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, int uid, int gid, int flag); int kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg); int kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf); int kern_fstat(struct thread *td, int fd, struct stat *sbp); @@ -105,16 +111,24 @@ int kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid, int gid); int kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg); +int kern_linkat(struct thread *td, int fd1, int fd2, char *path1, + char *path2, enum uio_seg segflg, int follow); int kern_lstat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp); int kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg); int kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode); +int kern_mkdirat(struct thread *td, int fd, char *path, + enum uio_seg segflg, int mode); int kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode); +int kern_mkfifoat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, int mode); int kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode, int dev); +int kern_mknodat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, int mode, int dev); int kern_msgctl(struct thread *, int, int, struct msqid_ds *); int kern_msgsnd(struct thread *, int, const void *, size_t, int, long); int kern_msgrcv(struct thread *, int, void *, size_t, long, int, long *); @@ -122,6 +136,8 @@ int kern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt); int kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags, int mode); +int kern_openat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, int flags, int mode); int kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg, int name); int kern_preadv(struct thread *td, int fd, struct uio *auio, off_t offset); @@ -130,12 +146,18 @@ int kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int kern_pwritev(struct thread *td, int fd, struct uio *auio, off_t offset); int kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf, enum uio_seg bufseg, size_t count); +int kern_readlinkat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, char *buf, enum uio_seg bufseg, size_t count); int kern_readv(struct thread *td, int fd, struct uio *auio); int kern_recvit(struct thread *td, int s, struct msghdr *mp, enum uio_seg fromseg, struct mbuf **controlp); int kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg); +int kern_renameat(struct thread *td, int oldfd, char *old, int newfd, + char *new, enum uio_seg pathseg); int kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg); +int kern_rmdirat(struct thread *td, int fd, char *path, + enum uio_seg pathseg); int kern_sched_rr_get_interval(struct thread *td, pid_t pid, struct timespec *ts); int kern_semctl(struct thread *td, int semid, int semnum, int cmd, @@ -166,17 +188,25 @@ int kern_sigprocmask(struct thread *td, int how, int kern_sigsuspend(struct thread *td, sigset_t mask); int kern_stat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp); +int kern_statat(struct thread *td, int flag, int fd, char *path, + enum uio_seg pathseg, struct stat *sbp); int kern_statfs(struct thread *td, char *path, enum uio_seg pathseg, struct statfs *buf); int kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg); +int kern_symlinkat(struct thread *td, char *path1, int fd, char *path2, + enum uio_seg segflg); int kern_thr_new(struct thread *td, struct thr_param *param); int kern_thr_suspend(struct thread *td, struct timespec *tsp); int kern_truncate(struct thread *td, char *path, enum uio_seg pathseg, off_t length); int kern_unlink(struct thread *td, char *path, enum uio_seg pathseg); +int kern_unlinkat(struct thread *td, int fd, char *path, + enum uio_seg pathseg); int kern_utimes(struct thread *td, char *path, enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg); +int kern_utimesat(struct thread *td, int fd, char *path, + enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg); int kern_wait(struct thread *td, pid_t pid, int *status, int options, struct rusage *rup); int kern_writev(struct thread *td, int fd, struct uio *auio); |