--- //depot/vendor/freebsd/src/sys/bsm/audit_kevents.h 2009/03/03 17:20:16 +++ //depot/user/jhb/acpipci/bsm/audit_kevents.h 2009/03/25 15:31:06 @@ -677,6 +677,8 @@ #define AUE_FFSCTL AUE_NULL #define AUE_FGETATTRLIST AUE_NULL #define AUE_FGETXATTR AUE_NULL +#define AUE_FLINK AUE_NULL +#define AUE_FLINKAT AUE_NULL #define AUE_FLISTXATTR AUE_NULL #define AUE_FREMOVEXATTR AUE_NULL #define AUE_FSCTL AUE_NULL --- //depot/vendor/freebsd/src/sys/compat/freebsd32/syscalls.master 2008/12/10 21:00:18 +++ //depot/user/jhb/acpipci/compat/freebsd32/syscalls.master 2009/03/25 15:33:04 @@ -870,3 +870,5 @@ 504 AUE_POSIX_OPENPT NOPROTO { int posix_openpt(int flags); } ; 505 is initialised by the kgssapi code, if present. 505 AUE_NULL UNIMPL gssd_syscall +506 AUE_FLINK NOPROTO { int flink(int fd, char *link); } +507 AUE_FLINKAT NOPROTO { int flinkat(int fd, int fdlink, char *link); } --- //depot/vendor/freebsd/src/sys/kern/syscalls.master 2008/11/09 10:50:13 +++ //depot/user/jhb/acpipci/kern/syscalls.master 2009/03/25 15:33:04 @@ -897,5 +897,7 @@ 504 AUE_POSIX_OPENPT STD { int posix_openpt(int flags); } ; 505 is initialised by the kgssapi code, if present. 505 AUE_NULL NOSTD { int gssd_syscall(char *path); } +506 AUE_FLINK STD { int flink(int fd, char *link); } +507 AUE_FLINKAT STD { int flinkat(int fd, int fdlink, char *link); } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master --- //depot/vendor/freebsd/src/sys/kern/vfs_syscalls.c 2009/02/20 13:10:13 +++ //depot/user/jhb/acpipci/kern/vfs_syscalls.c 2009/03/25 15:38:08 @@ -1556,45 +1556,20 @@ return (0); } -int -kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg) +static int +make_link(struct thread *td, struct vnode *vp, int fd, char *path, + 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 nameidata nd; struct mount *mp; - struct nameidata nd; - int vfslocked; - int lvfslocked; - int error; + int error, lvfslocked; - bwillwrite(); - NDINIT_AT(&nd, LOOKUP, follow | MPSAFE | AUDITVNODE1, segflg, path1, - fd1, td); - - if ((error = namei(&nd)) != 0) - return (error); - vfslocked = NDHASGIANT(&nd); - NDFREE(&nd, NDF_ONLY_PNBUF); - vp = nd.ni_vp; - if (vp->v_type == VDIR) { - vrele(vp); - VFS_UNLOCK_GIANT(vfslocked); + if (vp->v_type == VDIR) return (EPERM); /* POSIX */ - } - if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { - vrele(vp); - VFS_UNLOCK_GIANT(vfslocked); + if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) return (error); - } NDINIT_AT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, - segflg, path2, fd2, td); + segflg, path, fd, td); if ((error = namei(&nd)) == 0) { lvfslocked = NDHASGIANT(&nd); if (nd.ni_vp != NULL) { @@ -1622,8 +1597,108 @@ NDFREE(&nd, NDF_ONLY_PNBUF); VFS_UNLOCK_GIANT(lvfslocked); } + vn_finished_write(mp); + return (error); +} + +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 nameidata nd; + int vfslocked; + int error; + + bwillwrite(); + NDINIT_AT(&nd, LOOKUP, follow | MPSAFE | AUDITVNODE1, segflg, path1, + fd1, td); + + if ((error = namei(&nd)) != 0) + return (error); + vfslocked = NDHASGIANT(&nd); + NDFREE(&nd, NDF_ONLY_PNBUF); + vp = nd.ni_vp; + error = make_link(td, vp, fd2, path2, segflg); vrele(vp); - vn_finished_write(mp); + VFS_UNLOCK_GIANT(vfslocked); + return (error); +} + +#ifndef _SYS_SYSPROTO_H_ +struct flink_args { + int fd; + char *link; +}; +#endif +int +flink(td, uap) + struct thread *td; + struct flink_args /* { + int fd; + char *link; + } */ *uap; +{ + + return (kern_flink(td, uap->fd, uap->link, UIO_USERSPACE)); +} + +#ifndef _SYS_SYSPROTO_H_ +struct flinkat_args { + int fd; + int fdlink; + char *link; +}; +#endif +int +flinkat(td, uap) + struct thread *td; + struct flinkat_args /* { + int fd; + int fdlink; + char *link; + } */ *uap; +{ + + return (kern_flinkat(td, uap->fd, uap->fdlink, uap->link, UIO_USERSPACE)); +} + +int +kern_flink(struct thread *td, int fd, char *link, enum uio_seg segflg) +{ + + return (kern_flinkat(td, fd, AT_FDCWD, link, segflg)); +} + +int +kern_flinkat(struct thread *td, int fd, int fdlink, char *link, + enum uio_seg segflg) +{ + struct vnode *vp; + struct file *fp; + int error, vfslocked; + + bwillwrite(); + AUDIT_ARG(fd, fd); + error = getvnode(td->td_proc->p_fd, fd, &fp); + if (error) + return (error); + vp = fp->f_vnode; + VREF(vp); + fdrop(fp, td); + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + vn_lock(vp, LK_SHARED | LK_RETRY); + AUDIT_ARG(vnode, vp, ARG_VNODE1); + VOP_UNLOCK(vp, 0); + error = make_link(td, vp, fdlink, link, segflg); + vrele(vp); VFS_UNLOCK_GIANT(vfslocked); return (error); } --- //depot/vendor/freebsd/src/sys/sys/syscallsubr.h 2009/02/20 13:10:13 +++ //depot/user/jhb/acpipci/sys/syscallsubr.h 2009/03/25 15:31:06 @@ -86,6 +86,9 @@ 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_flink(struct thread *td, int fd, char *link, enum uio_seg segflg); +int kern_flinkat(struct thread *td, int fd, int fdlink, char *link, + enum uio_seg segflg); int kern_fstat(struct thread *td, int fd, struct stat *sbp); int kern_fstatfs(struct thread *td, int fd, struct statfs *buf); int kern_ftruncate(struct thread *td, int fd, off_t length);