1/* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94
| 1/* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94
|
39 * $Id: vfs_syscalls.c,v 1.95 1998/03/08 09:57:21 julian Exp $
| 39 * $Id: vfs_syscalls.c,v 1.96 1998/03/29 18:23:44 dyson Exp $
|
40 */ 41 42/* For 4.3 integer FS ID compatibility */ 43#include "opt_compat.h" 44 45/* 46 * XXX - The following is required because of some magic done 47 * in getdirentries() below which is only done if the translucent 48 * filesystem `UNION' is compiled into the kernel. This is broken, 49 * but I don't have time to study the code deeply enough to understand 50 * what's going on and determine an appropriate fix. -GAW 51 */ 52#include "opt_union.h" 53 54#include <sys/param.h> 55#include <sys/systm.h> 56#include <sys/sysent.h> 57#include <sys/sysproto.h> 58#include <sys/namei.h> 59#include <sys/filedesc.h> 60#include <sys/kernel.h> 61#include <sys/fcntl.h> 62#include <sys/file.h> 63#include <sys/stat.h> 64#include <sys/unistd.h> 65#include <sys/vnode.h> 66#include <sys/malloc.h> 67#include <sys/mount.h> 68#include <sys/proc.h> 69#include <sys/dirent.h> 70 71#ifdef UNION 72#include <miscfs/union/union.h> 73#endif 74 75#include <vm/vm.h> 76#include <vm/vm_object.h> 77#include <vm/vm_extern.h> 78#include <vm/vm_zone.h> 79#include <sys/sysctl.h> 80 81static int change_dir __P((struct nameidata *ndp, struct proc *p)); 82static void checkdirs __P((struct vnode *olddp)); 83 84static int usermount = 0; /* if 1, non-root can mount fs. */ 85 86SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, ""); 87 88/* 89 * Virtual File System System Calls 90 */ 91 92/* 93 * Mount a file system. 94 */ 95#ifndef _SYS_SYSPROTO_H_ 96struct mount_args { 97 char *type; 98 char *path; 99 int flags; 100 caddr_t data; 101}; 102#endif 103/* ARGSUSED */ 104int 105mount(p, uap) 106 struct proc *p; 107 register struct mount_args /* { 108 syscallarg(char *) type; 109 syscallarg(char *) path; 110 syscallarg(int) flags; 111 syscallarg(caddr_t) data; 112 } */ *uap; 113{ 114 struct vnode *vp; 115 struct mount *mp; 116 struct vfsconf *vfsp; 117 int error, flag = 0, flag2 = 0; 118 struct vattr va; 119 u_long fstypenum; 120 struct nameidata nd; 121 char fstypename[MFSNAMELEN]; 122 123 if (usermount == 0 && (error = suser(p->p_ucred, &p->p_acflag))) 124 return (error); 125 126 /* 127 * Get vnode to be covered 128 */ 129 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 130 SCARG(uap, path), p); 131 if (error = namei(&nd)) 132 return (error); 133 vp = nd.ni_vp; 134 if (SCARG(uap, flags) & MNT_UPDATE) { 135 if ((vp->v_flag & VROOT) == 0) { 136 vput(vp); 137 return (EINVAL); 138 } 139 mp = vp->v_mount; 140 flag = mp->mnt_flag; 141 flag2 = mp->mnt_kern_flag; 142 /* 143 * We only allow the filesystem to be reloaded if it 144 * is currently mounted read-only. 145 */ 146 if ((SCARG(uap, flags) & MNT_RELOAD) && 147 ((mp->mnt_flag & MNT_RDONLY) == 0)) { 148 vput(vp); 149 return (EOPNOTSUPP); /* Needs translation */ 150 } 151 mp->mnt_flag |= 152 SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE); 153 /* 154 * Only root, or the user that did the original mount is 155 * permitted to update it. 156 */ 157 if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid && 158 (error = suser(p->p_ucred, &p->p_acflag))) { 159 vput(vp); 160 return (error); 161 } 162 /* 163 * Do not allow NFS export by non-root users. Silently 164 * enforce MNT_NOSUID and MNT_NODEV for non-root users. 165 */ 166 if (p->p_ucred->cr_uid != 0) { 167 if (SCARG(uap, flags) & MNT_EXPORTED) { 168 vput(vp); 169 return (EPERM); 170 } 171 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; 172 } 173 if (vfs_busy(mp, LK_NOWAIT, 0, p)) { 174 vput(vp); 175 return (EBUSY); 176 } 177 VOP_UNLOCK(vp, 0, p); 178 goto update; 179 } 180 /* 181 * If the user is not root, ensure that they own the directory 182 * onto which we are attempting to mount. 183 */ 184 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) || 185 (va.va_uid != p->p_ucred->cr_uid && 186 (error = suser(p->p_ucred, &p->p_acflag)))) { 187 vput(vp); 188 return (error); 189 } 190 /* 191 * Do not allow NFS export by non-root users. Silently 192 * enforce MNT_NOSUID and MNT_NODEV for non-root users. 193 */ 194 if (p->p_ucred->cr_uid != 0) { 195 if (SCARG(uap, flags) & MNT_EXPORTED) { 196 vput(vp); 197 return (EPERM); 198 } 199 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; 200 } 201 if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) 202 return (error); 203 if (vp->v_type != VDIR) { 204 vput(vp); 205 return (ENOTDIR); 206 } 207#ifdef COMPAT_43 208 /* 209 * Historically filesystem types were identified by number. If we 210 * get an integer for the filesystem type instead of a string, we 211 * check to see if it matches one of the historic filesystem types. 212 */ 213 fstypenum = (u_long)SCARG(uap, type); 214 if (fstypenum < maxvfsconf) { 215 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) 216 if (vfsp->vfc_typenum == fstypenum) 217 break; 218 if (vfsp == NULL) { 219 vput(vp); 220 return (ENODEV); 221 } 222 strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN); 223 } else 224#endif /* COMPAT_43 */ 225 if (error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) { 226 vput(vp); 227 return (error); 228 } 229 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) 230 if (!strcmp(vfsp->vfc_name, fstypename)) 231 break; 232 if (vfsp == NULL) { 233 vput(vp); 234 return (ENODEV); 235 } 236 if (vp->v_mountedhere != NULL) { 237 vput(vp); 238 return (EBUSY); 239 } 240 241 /* 242 * Allocate and initialize the filesystem. 243 */ 244 mp = (struct mount *)malloc((u_long)sizeof(struct mount), 245 M_MOUNT, M_WAITOK); 246 bzero((char *)mp, (u_long)sizeof(struct mount)); 247 lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, LK_NOPAUSE); 248 (void)vfs_busy(mp, LK_NOWAIT, 0, p); 249 mp->mnt_op = vfsp->vfc_vfsops; 250 mp->mnt_vfc = vfsp; 251 vfsp->vfc_refcount++; 252 mp->mnt_stat.f_type = vfsp->vfc_typenum; 253 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; 254 strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); 255 vp->v_mountedhere = mp; 256 mp->mnt_vnodecovered = vp; 257 mp->mnt_stat.f_owner = p->p_ucred->cr_uid; 258update: 259 /* 260 * Set the mount level flags. 261 */ 262 if (SCARG(uap, flags) & MNT_RDONLY) 263 mp->mnt_flag |= MNT_RDONLY; 264 else if (mp->mnt_flag & MNT_RDONLY) 265 mp->mnt_kern_flag |= MNTK_WANTRDWR; 266 mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | 267 MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME |
| 40 */ 41 42/* For 4.3 integer FS ID compatibility */ 43#include "opt_compat.h" 44 45/* 46 * XXX - The following is required because of some magic done 47 * in getdirentries() below which is only done if the translucent 48 * filesystem `UNION' is compiled into the kernel. This is broken, 49 * but I don't have time to study the code deeply enough to understand 50 * what's going on and determine an appropriate fix. -GAW 51 */ 52#include "opt_union.h" 53 54#include <sys/param.h> 55#include <sys/systm.h> 56#include <sys/sysent.h> 57#include <sys/sysproto.h> 58#include <sys/namei.h> 59#include <sys/filedesc.h> 60#include <sys/kernel.h> 61#include <sys/fcntl.h> 62#include <sys/file.h> 63#include <sys/stat.h> 64#include <sys/unistd.h> 65#include <sys/vnode.h> 66#include <sys/malloc.h> 67#include <sys/mount.h> 68#include <sys/proc.h> 69#include <sys/dirent.h> 70 71#ifdef UNION 72#include <miscfs/union/union.h> 73#endif 74 75#include <vm/vm.h> 76#include <vm/vm_object.h> 77#include <vm/vm_extern.h> 78#include <vm/vm_zone.h> 79#include <sys/sysctl.h> 80 81static int change_dir __P((struct nameidata *ndp, struct proc *p)); 82static void checkdirs __P((struct vnode *olddp)); 83 84static int usermount = 0; /* if 1, non-root can mount fs. */ 85 86SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, ""); 87 88/* 89 * Virtual File System System Calls 90 */ 91 92/* 93 * Mount a file system. 94 */ 95#ifndef _SYS_SYSPROTO_H_ 96struct mount_args { 97 char *type; 98 char *path; 99 int flags; 100 caddr_t data; 101}; 102#endif 103/* ARGSUSED */ 104int 105mount(p, uap) 106 struct proc *p; 107 register struct mount_args /* { 108 syscallarg(char *) type; 109 syscallarg(char *) path; 110 syscallarg(int) flags; 111 syscallarg(caddr_t) data; 112 } */ *uap; 113{ 114 struct vnode *vp; 115 struct mount *mp; 116 struct vfsconf *vfsp; 117 int error, flag = 0, flag2 = 0; 118 struct vattr va; 119 u_long fstypenum; 120 struct nameidata nd; 121 char fstypename[MFSNAMELEN]; 122 123 if (usermount == 0 && (error = suser(p->p_ucred, &p->p_acflag))) 124 return (error); 125 126 /* 127 * Get vnode to be covered 128 */ 129 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 130 SCARG(uap, path), p); 131 if (error = namei(&nd)) 132 return (error); 133 vp = nd.ni_vp; 134 if (SCARG(uap, flags) & MNT_UPDATE) { 135 if ((vp->v_flag & VROOT) == 0) { 136 vput(vp); 137 return (EINVAL); 138 } 139 mp = vp->v_mount; 140 flag = mp->mnt_flag; 141 flag2 = mp->mnt_kern_flag; 142 /* 143 * We only allow the filesystem to be reloaded if it 144 * is currently mounted read-only. 145 */ 146 if ((SCARG(uap, flags) & MNT_RELOAD) && 147 ((mp->mnt_flag & MNT_RDONLY) == 0)) { 148 vput(vp); 149 return (EOPNOTSUPP); /* Needs translation */ 150 } 151 mp->mnt_flag |= 152 SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE); 153 /* 154 * Only root, or the user that did the original mount is 155 * permitted to update it. 156 */ 157 if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid && 158 (error = suser(p->p_ucred, &p->p_acflag))) { 159 vput(vp); 160 return (error); 161 } 162 /* 163 * Do not allow NFS export by non-root users. Silently 164 * enforce MNT_NOSUID and MNT_NODEV for non-root users. 165 */ 166 if (p->p_ucred->cr_uid != 0) { 167 if (SCARG(uap, flags) & MNT_EXPORTED) { 168 vput(vp); 169 return (EPERM); 170 } 171 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; 172 } 173 if (vfs_busy(mp, LK_NOWAIT, 0, p)) { 174 vput(vp); 175 return (EBUSY); 176 } 177 VOP_UNLOCK(vp, 0, p); 178 goto update; 179 } 180 /* 181 * If the user is not root, ensure that they own the directory 182 * onto which we are attempting to mount. 183 */ 184 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) || 185 (va.va_uid != p->p_ucred->cr_uid && 186 (error = suser(p->p_ucred, &p->p_acflag)))) { 187 vput(vp); 188 return (error); 189 } 190 /* 191 * Do not allow NFS export by non-root users. Silently 192 * enforce MNT_NOSUID and MNT_NODEV for non-root users. 193 */ 194 if (p->p_ucred->cr_uid != 0) { 195 if (SCARG(uap, flags) & MNT_EXPORTED) { 196 vput(vp); 197 return (EPERM); 198 } 199 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; 200 } 201 if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) 202 return (error); 203 if (vp->v_type != VDIR) { 204 vput(vp); 205 return (ENOTDIR); 206 } 207#ifdef COMPAT_43 208 /* 209 * Historically filesystem types were identified by number. If we 210 * get an integer for the filesystem type instead of a string, we 211 * check to see if it matches one of the historic filesystem types. 212 */ 213 fstypenum = (u_long)SCARG(uap, type); 214 if (fstypenum < maxvfsconf) { 215 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) 216 if (vfsp->vfc_typenum == fstypenum) 217 break; 218 if (vfsp == NULL) { 219 vput(vp); 220 return (ENODEV); 221 } 222 strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN); 223 } else 224#endif /* COMPAT_43 */ 225 if (error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) { 226 vput(vp); 227 return (error); 228 } 229 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) 230 if (!strcmp(vfsp->vfc_name, fstypename)) 231 break; 232 if (vfsp == NULL) { 233 vput(vp); 234 return (ENODEV); 235 } 236 if (vp->v_mountedhere != NULL) { 237 vput(vp); 238 return (EBUSY); 239 } 240 241 /* 242 * Allocate and initialize the filesystem. 243 */ 244 mp = (struct mount *)malloc((u_long)sizeof(struct mount), 245 M_MOUNT, M_WAITOK); 246 bzero((char *)mp, (u_long)sizeof(struct mount)); 247 lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, LK_NOPAUSE); 248 (void)vfs_busy(mp, LK_NOWAIT, 0, p); 249 mp->mnt_op = vfsp->vfc_vfsops; 250 mp->mnt_vfc = vfsp; 251 vfsp->vfc_refcount++; 252 mp->mnt_stat.f_type = vfsp->vfc_typenum; 253 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; 254 strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); 255 vp->v_mountedhere = mp; 256 mp->mnt_vnodecovered = vp; 257 mp->mnt_stat.f_owner = p->p_ucred->cr_uid; 258update: 259 /* 260 * Set the mount level flags. 261 */ 262 if (SCARG(uap, flags) & MNT_RDONLY) 263 mp->mnt_flag |= MNT_RDONLY; 264 else if (mp->mnt_flag & MNT_RDONLY) 265 mp->mnt_kern_flag |= MNTK_WANTRDWR; 266 mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | 267 MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME |
|
| 268 MNT_NOSYMFOLLOW |
|
268 MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR); 269 mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC | 270 MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE |
| 269 MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR); 270 mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC | 271 MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE |
|
| 272 MNT_NOSYMFOLLOW |
|
271 MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR); 272 /* 273 * Mount the filesystem. 274 */ 275 error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p); 276 if (mp->mnt_flag & MNT_UPDATE) { 277 vrele(vp); 278 if (mp->mnt_kern_flag & MNTK_WANTRDWR) 279 mp->mnt_flag &= ~MNT_RDONLY; 280 mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE); 281 mp->mnt_kern_flag &=~ MNTK_WANTRDWR; 282 if (error) { 283 mp->mnt_flag = flag; 284 mp->mnt_kern_flag = flag2; 285 } 286 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 287 if (mp->mnt_syncer == NULL) 288 error = vfs_allocate_syncvnode(mp); 289 } else { 290 if (mp->mnt_syncer != NULL) 291 vrele(mp->mnt_syncer); 292 mp->mnt_syncer = NULL; 293 } 294 vfs_unbusy(mp, p); 295 return (error); 296 } 297 /* 298 * Put the new filesystem on the mount list after root. 299 */ 300 cache_purge(vp); 301 if (!error) { 302 simple_lock(&mountlist_slock); 303 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); 304 simple_unlock(&mountlist_slock); 305 checkdirs(vp); 306 VOP_UNLOCK(vp, 0, p); 307 if ((mp->mnt_flag & MNT_RDONLY) == 0) 308 error = vfs_allocate_syncvnode(mp); 309 vfs_unbusy(mp, p); 310 if (error = VFS_START(mp, 0, p)) 311 vrele(vp); 312 } else { 313 mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0; 314 mp->mnt_vfc->vfc_refcount--; 315 vfs_unbusy(mp, p); 316 free((caddr_t)mp, M_MOUNT); 317 vput(vp); 318 } 319 return (error); 320} 321 322/* 323 * Scan all active processes to see if any of them have a current 324 * or root directory onto which the new filesystem has just been 325 * mounted. If so, replace them with the new mount point. 326 */ 327static void 328checkdirs(olddp) 329 struct vnode *olddp; 330{ 331 struct filedesc *fdp; 332 struct vnode *newdp; 333 struct proc *p; 334 335 if (olddp->v_usecount == 1) 336 return; 337 if (VFS_ROOT(olddp->v_mountedhere, &newdp)) 338 panic("mount: lost mount"); 339 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 340 fdp = p->p_fd; 341 if (fdp->fd_cdir == olddp) { 342 vrele(fdp->fd_cdir); 343 VREF(newdp); 344 fdp->fd_cdir = newdp; 345 } 346 if (fdp->fd_rdir == olddp) { 347 vrele(fdp->fd_rdir); 348 VREF(newdp); 349 fdp->fd_rdir = newdp; 350 } 351 } 352 if (rootvnode == olddp) { 353 vrele(rootvnode); 354 VREF(newdp); 355 rootvnode = newdp; 356 } 357 vput(newdp); 358} 359 360/* 361 * Unmount a file system. 362 * 363 * Note: unmount takes a path to the vnode mounted on as argument, 364 * not special file (as before). 365 */ 366#ifndef _SYS_SYSPROTO_H_ 367struct unmount_args { 368 char *path; 369 int flags; 370}; 371#endif 372/* ARGSUSED */ 373int 374unmount(p, uap) 375 struct proc *p; 376 register struct unmount_args /* { 377 syscallarg(char *) path; 378 syscallarg(int) flags; 379 } */ *uap; 380{ 381 register struct vnode *vp; 382 struct mount *mp; 383 int error; 384 struct nameidata nd; 385 386 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 387 SCARG(uap, path), p); 388 if (error = namei(&nd)) 389 return (error); 390 vp = nd.ni_vp; 391 mp = vp->v_mount; 392 393 /* 394 * Only root, or the user that did the original mount is 395 * permitted to unmount this filesystem. 396 */ 397 if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) && 398 (error = suser(p->p_ucred, &p->p_acflag))) { 399 vput(vp); 400 return (error); 401 } 402 403 /* 404 * Don't allow unmounting the root file system. 405 */ 406 if (mp->mnt_flag & MNT_ROOTFS) { 407 vput(vp); 408 return (EINVAL); 409 } 410 411 /* 412 * Must be the root of the filesystem 413 */ 414 if ((vp->v_flag & VROOT) == 0) { 415 vput(vp); 416 return (EINVAL); 417 } 418 vput(vp); 419 return (dounmount(mp, SCARG(uap, flags), p)); 420} 421 422/* 423 * Do the actual file system unmount. 424 */ 425int 426dounmount(mp, flags, p) 427 register struct mount *mp; 428 int flags; 429 struct proc *p; 430{ 431 struct vnode *coveredvp; 432 int error; 433 434 simple_lock(&mountlist_slock); 435 mp->mnt_kern_flag |= MNTK_UNMOUNT; 436 lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p); 437 438 if (mp->mnt_flag & MNT_EXPUBLIC) 439 vfs_setpublicfs(NULL, NULL, NULL); 440 441 vfs_msync(mp, MNT_WAIT); 442 mp->mnt_flag &=~ MNT_ASYNC; 443 cache_purgevfs(mp); /* remove cache entries for this file sys */ 444 if (mp->mnt_syncer != NULL) 445 vrele(mp->mnt_syncer); 446 if (((mp->mnt_flag & MNT_RDONLY) || 447 (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) || 448 (flags & MNT_FORCE)) 449 error = VFS_UNMOUNT(mp, flags, p); 450 simple_lock(&mountlist_slock); 451 if (error) { 452 if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL) 453 (void) vfs_allocate_syncvnode(mp); 454 mp->mnt_kern_flag &= ~MNTK_UNMOUNT; 455 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE, 456 &mountlist_slock, p); 457 return (error); 458 } 459 CIRCLEQ_REMOVE(&mountlist, mp, mnt_list); 460 if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) { 461 coveredvp->v_mountedhere = (struct mount *)0; 462 vrele(coveredvp); 463 } 464 mp->mnt_vfc->vfc_refcount--; 465 if (mp->mnt_vnodelist.lh_first != NULL) 466 panic("unmount: dangling vnode"); 467 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p); 468 if (mp->mnt_kern_flag & MNTK_MWAIT) 469 wakeup((caddr_t)mp); 470 free((caddr_t)mp, M_MOUNT); 471 return (0); 472} 473 474/* 475 * Sync each mounted filesystem. 476 */ 477#ifndef _SYS_SYSPROTO_H_ 478struct sync_args { 479 int dummy; 480}; 481#endif 482 483#ifdef DEBUG 484static int syncprt = 0; 485SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, ""); 486#endif 487 488/* ARGSUSED */ 489int 490sync(p, uap) 491 struct proc *p; 492 struct sync_args *uap; 493{ 494 register struct mount *mp, *nmp; 495 int asyncflag; 496 497 simple_lock(&mountlist_slock); 498 for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { 499 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { 500 nmp = mp->mnt_list.cqe_next; 501 continue; 502 } 503 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 504 asyncflag = mp->mnt_flag & MNT_ASYNC; 505 mp->mnt_flag &= ~MNT_ASYNC; 506 vfs_msync(mp, MNT_NOWAIT); 507 VFS_SYNC(mp, MNT_NOWAIT, 508 ((p != NULL) ? p->p_ucred : NOCRED), p); 509 mp->mnt_flag |= asyncflag; 510 } 511 simple_lock(&mountlist_slock); 512 nmp = mp->mnt_list.cqe_next; 513 vfs_unbusy(mp, p); 514 } 515 simple_unlock(&mountlist_slock); 516#if 0 517/* 518 * XXX don't call vfs_bufstats() yet because that routine 519 * was not imported in the Lite2 merge. 520 */ 521#ifdef DIAGNOSTIC 522 if (syncprt) 523 vfs_bufstats(); 524#endif /* DIAGNOSTIC */ 525#endif 526 return (0); 527} 528 529/* 530 * Change filesystem quotas. 531 */ 532#ifndef _SYS_SYSPROTO_H_ 533struct quotactl_args { 534 char *path; 535 int cmd; 536 int uid; 537 caddr_t arg; 538}; 539#endif 540/* ARGSUSED */ 541int 542quotactl(p, uap) 543 struct proc *p; 544 register struct quotactl_args /* { 545 syscallarg(char *) path; 546 syscallarg(int) cmd; 547 syscallarg(int) uid; 548 syscallarg(caddr_t) arg; 549 } */ *uap; 550{ 551 register struct mount *mp; 552 int error; 553 struct nameidata nd; 554 555 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 556 if (error = namei(&nd)) 557 return (error); 558 mp = nd.ni_vp->v_mount; 559 vrele(nd.ni_vp); 560 return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid), 561 SCARG(uap, arg), p)); 562} 563 564/* 565 * Get filesystem statistics. 566 */ 567#ifndef _SYS_SYSPROTO_H_ 568struct statfs_args { 569 char *path; 570 struct statfs *buf; 571}; 572#endif 573/* ARGSUSED */ 574int 575statfs(p, uap) 576 struct proc *p; 577 register struct statfs_args /* { 578 syscallarg(char *) path; 579 syscallarg(struct statfs *) buf; 580 } */ *uap; 581{ 582 register struct mount *mp; 583 register struct statfs *sp; 584 int error; 585 struct nameidata nd; 586 struct statfs sb; 587 588 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 589 if (error = namei(&nd)) 590 return (error); 591 mp = nd.ni_vp->v_mount; 592 sp = &mp->mnt_stat; 593 vrele(nd.ni_vp); 594 error = VFS_STATFS(mp, sp, p); 595 if (error) 596 return (error); 597 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 598 if (p->p_ucred->cr_uid != 0) { 599 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 600 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 601 sp = &sb; 602 } 603 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 604} 605 606/* 607 * Get filesystem statistics. 608 */ 609#ifndef _SYS_SYSPROTO_H_ 610struct fstatfs_args { 611 int fd; 612 struct statfs *buf; 613}; 614#endif 615/* ARGSUSED */ 616int 617fstatfs(p, uap) 618 struct proc *p; 619 register struct fstatfs_args /* { 620 syscallarg(int) fd; 621 syscallarg(struct statfs *) buf; 622 } */ *uap; 623{ 624 struct file *fp; 625 struct mount *mp; 626 register struct statfs *sp; 627 int error; 628 struct statfs sb; 629 630 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 631 return (error); 632 mp = ((struct vnode *)fp->f_data)->v_mount; 633 sp = &mp->mnt_stat; 634 error = VFS_STATFS(mp, sp, p); 635 if (error) 636 return (error); 637 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 638 if (p->p_ucred->cr_uid != 0) { 639 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 640 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 641 sp = &sb; 642 } 643 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 644} 645 646/* 647 * Get statistics on all filesystems. 648 */ 649#ifndef _SYS_SYSPROTO_H_ 650struct getfsstat_args { 651 struct statfs *buf; 652 long bufsize; 653 int flags; 654}; 655#endif 656int 657getfsstat(p, uap) 658 struct proc *p; 659 register struct getfsstat_args /* { 660 syscallarg(struct statfs *) buf; 661 syscallarg(long) bufsize; 662 syscallarg(int) flags; 663 } */ *uap; 664{ 665 register struct mount *mp, *nmp; 666 register struct statfs *sp; 667 caddr_t sfsp; 668 long count, maxcount, error; 669 670 maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); 671 sfsp = (caddr_t)SCARG(uap, buf); 672 count = 0; 673 simple_lock(&mountlist_slock); 674 for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { 675 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { 676 nmp = mp->mnt_list.cqe_next; 677 continue; 678 } 679 if (sfsp && count < maxcount) { 680 sp = &mp->mnt_stat; 681 /* 682 * If MNT_NOWAIT or MNT_LAZY is specified, do not 683 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY 684 * overrides MNT_WAIT. 685 */ 686 if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 || 687 (SCARG(uap, flags) & MNT_WAIT)) && 688 (error = VFS_STATFS(mp, sp, p))) { 689 simple_lock(&mountlist_slock); 690 nmp = mp->mnt_list.cqe_next; 691 vfs_unbusy(mp, p); 692 continue; 693 } 694 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 695 error = copyout((caddr_t)sp, sfsp, sizeof(*sp)); 696 if (error) { 697 vfs_unbusy(mp, p); 698 return (error); 699 } 700 sfsp += sizeof(*sp); 701 } 702 count++; 703 simple_lock(&mountlist_slock); 704 nmp = mp->mnt_list.cqe_next; 705 vfs_unbusy(mp, p); 706 } 707 simple_unlock(&mountlist_slock); 708 if (sfsp && count > maxcount) 709 p->p_retval[0] = maxcount; 710 else 711 p->p_retval[0] = count; 712 return (0); 713} 714 715/* 716 * Change current working directory to a given file descriptor. 717 */ 718#ifndef _SYS_SYSPROTO_H_ 719struct fchdir_args { 720 int fd; 721}; 722#endif 723/* ARGSUSED */ 724int 725fchdir(p, uap) 726 struct proc *p; 727 struct fchdir_args /* { 728 syscallarg(int) fd; 729 } */ *uap; 730{ 731 register struct filedesc *fdp = p->p_fd; 732 struct vnode *vp, *tdp; 733 struct mount *mp; 734 struct file *fp; 735 int error; 736 737 if (error = getvnode(fdp, SCARG(uap, fd), &fp)) 738 return (error); 739 vp = (struct vnode *)fp->f_data; 740 VREF(vp); 741 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 742 if (vp->v_type != VDIR) 743 error = ENOTDIR; 744 else 745 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 746 while (!error && (mp = vp->v_mountedhere) != NULL) { 747 if (vfs_busy(mp, 0, 0, p)) 748 continue; 749 error = VFS_ROOT(mp, &tdp); 750 vfs_unbusy(mp, p); 751 if (error) 752 break; 753 vput(vp); 754 vp = tdp; 755 } 756 if (error) { 757 vput(vp); 758 return (error); 759 } 760 VOP_UNLOCK(vp, 0, p); 761 vrele(fdp->fd_cdir); 762 fdp->fd_cdir = vp; 763 return (0); 764} 765 766/* 767 * Change current working directory (``.''). 768 */ 769#ifndef _SYS_SYSPROTO_H_ 770struct chdir_args { 771 char *path; 772}; 773#endif 774/* ARGSUSED */ 775int 776chdir(p, uap) 777 struct proc *p; 778 struct chdir_args /* { 779 syscallarg(char *) path; 780 } */ *uap; 781{ 782 register struct filedesc *fdp = p->p_fd; 783 int error; 784 struct nameidata nd; 785 786 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 787 SCARG(uap, path), p); 788 if (error = change_dir(&nd, p)) 789 return (error); 790 vrele(fdp->fd_cdir); 791 fdp->fd_cdir = nd.ni_vp; 792 return (0); 793} 794 795/* 796 * Change notion of root (``/'') directory. 797 */ 798#ifndef _SYS_SYSPROTO_H_ 799struct chroot_args { 800 char *path; 801}; 802#endif 803/* ARGSUSED */ 804int 805chroot(p, uap) 806 struct proc *p; 807 struct chroot_args /* { 808 syscallarg(char *) path; 809 } */ *uap; 810{ 811 register struct filedesc *fdp = p->p_fd; 812 int error; 813 struct nameidata nd; 814 815 error = suser(p->p_ucred, &p->p_acflag); 816 if (error) 817 return (error); 818 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 819 SCARG(uap, path), p); 820 if (error = change_dir(&nd, p)) 821 return (error); 822 vrele(fdp->fd_rdir); 823 fdp->fd_rdir = nd.ni_vp; 824 return (0); 825} 826 827/* 828 * Common routine for chroot and chdir. 829 */ 830static int 831change_dir(ndp, p) 832 register struct nameidata *ndp; 833 struct proc *p; 834{ 835 struct vnode *vp; 836 int error; 837 838 error = namei(ndp); 839 if (error) 840 return (error); 841 vp = ndp->ni_vp; 842 if (vp->v_type != VDIR) 843 error = ENOTDIR; 844 else 845 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 846 if (error) 847 vput(vp); 848 else 849 VOP_UNLOCK(vp, 0, p); 850 return (error); 851} 852 853/* 854 * Check permissions, allocate an open file structure, 855 * and call the device open routine if any. 856 */ 857#ifndef _SYS_SYSPROTO_H_ 858struct open_args { 859 char *path; 860 int flags; 861 int mode; 862}; 863#endif 864int 865open(p, uap) 866 struct proc *p; 867 register struct open_args /* { 868 syscallarg(char *) path; 869 syscallarg(int) flags; 870 syscallarg(int) mode; 871 } */ *uap; 872{ 873 register struct filedesc *fdp = p->p_fd; 874 register struct file *fp; 875 register struct vnode *vp; 876 int cmode, flags, oflags; 877 struct file *nfp; 878 int type, indx, error; 879 struct flock lf; 880 struct nameidata nd; 881 882 oflags = SCARG(uap, flags); 883 if ((oflags & O_ACCMODE) == O_ACCMODE) 884 return (EINVAL); 885 flags = FFLAGS(oflags); 886 error = falloc(p, &nfp, &indx); 887 if (error) 888 return (error); 889 fp = nfp; 890 cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; 891 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 892 p->p_dupfd = -indx - 1; /* XXX check for fdopen */ 893 error = vn_open(&nd, flags, cmode); 894 if (error) { 895 ffree(fp); 896 if ((error == ENODEV || error == ENXIO) && 897 p->p_dupfd >= 0 && /* XXX from fdopen */ 898 (error = 899 dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) { 900 p->p_retval[0] = indx; 901 return (0); 902 } 903 if (error == ERESTART) 904 error = EINTR; 905 fdp->fd_ofiles[indx] = NULL; 906 return (error); 907 } 908 p->p_dupfd = 0; 909 vp = nd.ni_vp; 910 911 fp->f_flag = flags & FMASK; 912 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE); 913 fp->f_ops = &vnops; 914 fp->f_data = (caddr_t)vp; 915 if (flags & (O_EXLOCK | O_SHLOCK)) { 916 lf.l_whence = SEEK_SET; 917 lf.l_start = 0; 918 lf.l_len = 0; 919 if (flags & O_EXLOCK) 920 lf.l_type = F_WRLCK; 921 else 922 lf.l_type = F_RDLCK; 923 type = F_FLOCK; 924 if ((flags & FNONBLOCK) == 0) 925 type |= F_WAIT; 926 VOP_UNLOCK(vp, 0, p); 927 if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) { 928 (void) vn_close(vp, fp->f_flag, fp->f_cred, p); 929 ffree(fp); 930 fdp->fd_ofiles[indx] = NULL; 931 return (error); 932 } 933 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 934 fp->f_flag |= FHASLOCK; 935 } 936 if ((vp->v_type == VREG) && (vp->v_object == NULL)) 937 vfs_object_create(vp, p, p->p_ucred, TRUE); 938 VOP_UNLOCK(vp, 0, p); 939 p->p_retval[0] = indx; 940 return (0); 941} 942 943#ifdef COMPAT_43 944/* 945 * Create a file. 946 */ 947#ifndef _SYS_SYSPROTO_H_ 948struct ocreat_args { 949 char *path; 950 int mode; 951}; 952#endif 953int 954ocreat(p, uap) 955 struct proc *p; 956 register struct ocreat_args /* { 957 syscallarg(char *) path; 958 syscallarg(int) mode; 959 } */ *uap; 960{ 961 struct open_args /* { 962 syscallarg(char *) path; 963 syscallarg(int) flags; 964 syscallarg(int) mode; 965 } */ nuap; 966 967 SCARG(&nuap, path) = SCARG(uap, path); 968 SCARG(&nuap, mode) = SCARG(uap, mode); 969 SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC; 970 return (open(p, &nuap)); 971} 972#endif /* COMPAT_43 */ 973 974/* 975 * Create a special file. 976 */ 977#ifndef _SYS_SYSPROTO_H_ 978struct mknod_args { 979 char *path; 980 int mode; 981 int dev; 982}; 983#endif 984/* ARGSUSED */ 985int 986mknod(p, uap) 987 struct proc *p; 988 register struct mknod_args /* { 989 syscallarg(char *) path; 990 syscallarg(int) mode; 991 syscallarg(int) dev; 992 } */ *uap; 993{ 994 register struct vnode *vp; 995 struct vattr vattr; 996 int error; 997 int whiteout; 998 struct nameidata nd; 999 1000 error = suser(p->p_ucred, &p->p_acflag); 1001 if (error) 1002 return (error); 1003 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1004 if (error = namei(&nd)) 1005 return (error); 1006 vp = nd.ni_vp; 1007 if (vp != NULL) 1008 error = EEXIST; 1009 else { 1010 VATTR_NULL(&vattr); 1011 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; 1012 vattr.va_rdev = SCARG(uap, dev); 1013 whiteout = 0; 1014 1015 switch (SCARG(uap, mode) & S_IFMT) { 1016 case S_IFMT: /* used by badsect to flag bad sectors */ 1017 vattr.va_type = VBAD; 1018 break; 1019 case S_IFCHR: 1020 vattr.va_type = VCHR; 1021 break; 1022 case S_IFBLK: 1023 vattr.va_type = VBLK; 1024 break; 1025 case S_IFWHT: 1026 whiteout = 1; 1027 break; 1028 default: 1029 error = EINVAL; 1030 break; 1031 } 1032 } 1033 if (!error) { 1034 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1035 if (whiteout) { 1036 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); 1037 if (error) 1038 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1039 vput(nd.ni_dvp); 1040 } else { 1041 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, 1042 &nd.ni_cnd, &vattr); 1043 } 1044 } else { 1045 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1046 if (nd.ni_dvp == vp) 1047 vrele(nd.ni_dvp); 1048 else 1049 vput(nd.ni_dvp); 1050 if (vp) 1051 vrele(vp); 1052 } 1053 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod"); 1054 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod"); 1055 return (error); 1056} 1057 1058/* 1059 * Create a named pipe. 1060 */ 1061#ifndef _SYS_SYSPROTO_H_ 1062struct mkfifo_args { 1063 char *path; 1064 int mode; 1065}; 1066#endif 1067/* ARGSUSED */ 1068int 1069mkfifo(p, uap) 1070 struct proc *p; 1071 register struct mkfifo_args /* { 1072 syscallarg(char *) path; 1073 syscallarg(int) mode; 1074 } */ *uap; 1075{ 1076 struct vattr vattr; 1077 int error; 1078 struct nameidata nd; 1079 1080 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1081 if (error = namei(&nd)) 1082 return (error); 1083 if (nd.ni_vp != NULL) { 1084 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1085 if (nd.ni_dvp == nd.ni_vp) 1086 vrele(nd.ni_dvp); 1087 else 1088 vput(nd.ni_dvp); 1089 vrele(nd.ni_vp); 1090 return (EEXIST); 1091 } 1092 VATTR_NULL(&vattr); 1093 vattr.va_type = VFIFO; 1094 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; 1095 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1096 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr)); 1097} 1098 1099/* 1100 * Make a hard file link. 1101 */ 1102#ifndef _SYS_SYSPROTO_H_ 1103struct link_args { 1104 char *path; 1105 char *link; 1106}; 1107#endif 1108/* ARGSUSED */ 1109int 1110link(p, uap) 1111 struct proc *p; 1112 register struct link_args /* { 1113 syscallarg(char *) path; 1114 syscallarg(char *) link; 1115 } */ *uap; 1116{ 1117 register struct vnode *vp; 1118 struct nameidata nd; 1119 int error; 1120 1121 NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), p); 1122 if (error = namei(&nd)) 1123 return (error); 1124 vp = nd.ni_vp; 1125 if (vp->v_type == VDIR) 1126 error = EPERM; /* POSIX */ 1127 else { 1128 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p); 1129 error = namei(&nd); 1130 if (!error) { 1131 if (nd.ni_vp != NULL) { 1132 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1133 if (nd.ni_dvp == nd.ni_vp) 1134 vrele(nd.ni_dvp); 1135 else 1136 vput(nd.ni_dvp); 1137 if (nd.ni_vp) 1138 vrele(nd.ni_vp); 1139 error = EEXIST; 1140 } else { 1141 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, 1142 LEASE_WRITE); 1143 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1144 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 1145 } 1146 } 1147 } 1148 vrele(vp); 1149 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link"); 1150 ASSERT_VOP_UNLOCKED(nd.ni_vp, "link"); 1151 return (error); 1152} 1153 1154/* 1155 * Make a symbolic link. 1156 */ 1157#ifndef _SYS_SYSPROTO_H_ 1158struct symlink_args { 1159 char *path; 1160 char *link; 1161}; 1162#endif 1163/* ARGSUSED */ 1164int 1165symlink(p, uap) 1166 struct proc *p; 1167 register struct symlink_args /* { 1168 syscallarg(char *) path; 1169 syscallarg(char *) link; 1170 } */ *uap; 1171{ 1172 struct vattr vattr; 1173 char *path; 1174 int error; 1175 struct nameidata nd; 1176 1177 path = zalloc(namei_zone); 1178 if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) 1179 goto out; 1180 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p); 1181 if (error = namei(&nd)) 1182 goto out; 1183 if (nd.ni_vp) { 1184 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1185 if (nd.ni_dvp == nd.ni_vp) 1186 vrele(nd.ni_dvp); 1187 else 1188 vput(nd.ni_dvp); 1189 vrele(nd.ni_vp); 1190 error = EEXIST; 1191 goto out; 1192 } 1193 VATTR_NULL(&vattr); 1194 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; 1195 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1196 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 1197 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink"); 1198 ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink"); 1199out: 1200 zfree(namei_zone, path); 1201 return (error); 1202} 1203 1204/* 1205 * Delete a whiteout from the filesystem. 1206 */ 1207/* ARGSUSED */ 1208int 1209undelete(p, uap) 1210 struct proc *p; 1211 register struct undelete_args /* { 1212 syscallarg(char *) path; 1213 } */ *uap; 1214{ 1215 int error; 1216 struct nameidata nd; 1217 1218 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, 1219 SCARG(uap, path), p); 1220 error = namei(&nd); 1221 if (error) 1222 return (error); 1223 1224 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 1225 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1226 if (nd.ni_dvp == nd.ni_vp) 1227 vrele(nd.ni_dvp); 1228 else 1229 vput(nd.ni_dvp); 1230 if (nd.ni_vp) 1231 vrele(nd.ni_vp); 1232 return (EEXIST); 1233 } 1234 1235 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1236 if (error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) 1237 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1238 vput(nd.ni_dvp); 1239 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete"); 1240 ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete"); 1241 return (error); 1242} 1243 1244/* 1245 * Delete a name from the filesystem. 1246 */ 1247#ifndef _SYS_SYSPROTO_H_ 1248struct unlink_args { 1249 char *path; 1250}; 1251#endif 1252/* ARGSUSED */ 1253int 1254unlink(p, uap) 1255 struct proc *p; 1256 struct unlink_args /* { 1257 syscallarg(char *) path; 1258 } */ *uap; 1259{ 1260 register struct vnode *vp; 1261 int error; 1262 struct nameidata nd; 1263 1264 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1265 if (error = namei(&nd)) 1266 return (error); 1267 vp = nd.ni_vp; 1268 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1269 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1270 1271 if (vp->v_type == VDIR) 1272 error = EPERM; /* POSIX */ 1273 else { 1274 /* 1275 * The root of a mounted filesystem cannot be deleted. 1276 * 1277 * XXX: can this only be a VDIR case? 1278 */ 1279 if (vp->v_flag & VROOT) 1280 error = EBUSY; 1281 } 1282 1283 if (!error) { 1284 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1285 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd); 1286 } else { 1287 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1288 if (nd.ni_dvp == vp) 1289 vrele(nd.ni_dvp); 1290 else 1291 vput(nd.ni_dvp); 1292 if (vp != NULLVP) 1293 vput(vp); 1294 } 1295 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink"); 1296 ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink"); 1297 return (error); 1298} 1299 1300/* 1301 * Reposition read/write file offset. 1302 */ 1303#ifndef _SYS_SYSPROTO_H_ 1304struct lseek_args { 1305 int fd; 1306 int pad; 1307 off_t offset; 1308 int whence; 1309}; 1310#endif 1311int 1312lseek(p, uap) 1313 struct proc *p; 1314 register struct lseek_args /* { 1315 syscallarg(int) fd; 1316 syscallarg(int) pad; 1317 syscallarg(off_t) offset; 1318 syscallarg(int) whence; 1319 } */ *uap; 1320{ 1321 struct ucred *cred = p->p_ucred; 1322 register struct filedesc *fdp = p->p_fd; 1323 register struct file *fp; 1324 struct vattr vattr; 1325 int error; 1326 1327 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || 1328 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) 1329 return (EBADF); 1330 if (fp->f_type != DTYPE_VNODE) 1331 return (ESPIPE); 1332 switch (SCARG(uap, whence)) { 1333 case L_INCR: 1334 fp->f_offset += SCARG(uap, offset); 1335 break; 1336 case L_XTND: 1337 error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p); 1338 if (error) 1339 return (error); 1340 fp->f_offset = SCARG(uap, offset) + vattr.va_size; 1341 break; 1342 case L_SET: 1343 fp->f_offset = SCARG(uap, offset); 1344 break; 1345 default: 1346 return (EINVAL); 1347 } 1348 *(off_t *)(p->p_retval) = fp->f_offset; 1349 return (0); 1350} 1351 1352#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1353/* 1354 * Reposition read/write file offset. 1355 */ 1356#ifndef _SYS_SYSPROTO_H_ 1357struct olseek_args { 1358 int fd; 1359 long offset; 1360 int whence; 1361}; 1362#endif 1363int 1364olseek(p, uap) 1365 struct proc *p; 1366 register struct olseek_args /* { 1367 syscallarg(int) fd; 1368 syscallarg(long) offset; 1369 syscallarg(int) whence; 1370 } */ *uap; 1371{ 1372 struct lseek_args /* { 1373 syscallarg(int) fd; 1374 syscallarg(int) pad; 1375 syscallarg(off_t) offset; 1376 syscallarg(int) whence; 1377 } */ nuap; 1378 int error; 1379 1380 SCARG(&nuap, fd) = SCARG(uap, fd); 1381 SCARG(&nuap, offset) = SCARG(uap, offset); 1382 SCARG(&nuap, whence) = SCARG(uap, whence); 1383 error = lseek(p, &nuap); 1384 return (error); 1385} 1386#endif /* COMPAT_43 */ 1387 1388/* 1389 * Check access permissions. 1390 */ 1391#ifndef _SYS_SYSPROTO_H_ 1392struct access_args { 1393 char *path; 1394 int flags; 1395}; 1396#endif 1397int 1398access(p, uap) 1399 struct proc *p; 1400 register struct access_args /* { 1401 syscallarg(char *) path; 1402 syscallarg(int) flags; 1403 } */ *uap; 1404{ 1405 register struct ucred *cred = p->p_ucred; 1406 register struct vnode *vp; 1407 int error, flags, t_gid, t_uid; 1408 struct nameidata nd; 1409 1410 t_uid = cred->cr_uid; 1411 t_gid = cred->cr_groups[0]; 1412 cred->cr_uid = p->p_cred->p_ruid; 1413 cred->cr_groups[0] = p->p_cred->p_rgid; 1414 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1415 SCARG(uap, path), p); 1416 if (error = namei(&nd)) 1417 goto out1; 1418 vp = nd.ni_vp; 1419 1420 /* Flags == 0 means only check for existence. */ 1421 if (SCARG(uap, flags)) { 1422 flags = 0; 1423 if (SCARG(uap, flags) & R_OK) 1424 flags |= VREAD; 1425 if (SCARG(uap, flags) & W_OK) 1426 flags |= VWRITE; 1427 if (SCARG(uap, flags) & X_OK) 1428 flags |= VEXEC; 1429 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1430 error = VOP_ACCESS(vp, flags, cred, p); 1431 } 1432 vput(vp); 1433out1: 1434 cred->cr_uid = t_uid; 1435 cred->cr_groups[0] = t_gid; 1436 return (error); 1437} 1438 1439#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1440/* 1441 * Get file status; this version follows links. 1442 */ 1443#ifndef _SYS_SYSPROTO_H_ 1444struct ostat_args { 1445 char *path; 1446 struct ostat *ub; 1447}; 1448#endif 1449/* ARGSUSED */ 1450int 1451ostat(p, uap) 1452 struct proc *p; 1453 register struct ostat_args /* { 1454 syscallarg(char *) path; 1455 syscallarg(struct ostat *) ub; 1456 } */ *uap; 1457{ 1458 struct stat sb; 1459 struct ostat osb; 1460 int error; 1461 struct nameidata nd; 1462 1463 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1464 SCARG(uap, path), p); 1465 if (error = namei(&nd)) 1466 return (error); 1467 error = vn_stat(nd.ni_vp, &sb, p); 1468 vput(nd.ni_vp); 1469 if (error) 1470 return (error); 1471 cvtstat(&sb, &osb); 1472 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1473 return (error); 1474} 1475 1476/* 1477 * Get file status; this version does not follow links. 1478 */ 1479#ifndef _SYS_SYSPROTO_H_ 1480struct olstat_args { 1481 char *path; 1482 struct ostat *ub; 1483}; 1484#endif 1485/* ARGSUSED */ 1486int 1487olstat(p, uap) 1488 struct proc *p; 1489 register struct olstat_args /* { 1490 syscallarg(char *) path; 1491 syscallarg(struct ostat *) ub; 1492 } */ *uap; 1493{ 1494 struct vnode *vp; 1495 struct stat sb; 1496 struct ostat osb; 1497 int error; 1498 struct nameidata nd; 1499 1500 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1501 SCARG(uap, path), p); 1502 if (error = namei(&nd)) 1503 return (error); 1504 vp = nd.ni_vp; 1505 error = vn_stat(vp, &sb, p);
| 273 MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR); 274 /* 275 * Mount the filesystem. 276 */ 277 error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p); 278 if (mp->mnt_flag & MNT_UPDATE) { 279 vrele(vp); 280 if (mp->mnt_kern_flag & MNTK_WANTRDWR) 281 mp->mnt_flag &= ~MNT_RDONLY; 282 mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE); 283 mp->mnt_kern_flag &=~ MNTK_WANTRDWR; 284 if (error) { 285 mp->mnt_flag = flag; 286 mp->mnt_kern_flag = flag2; 287 } 288 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 289 if (mp->mnt_syncer == NULL) 290 error = vfs_allocate_syncvnode(mp); 291 } else { 292 if (mp->mnt_syncer != NULL) 293 vrele(mp->mnt_syncer); 294 mp->mnt_syncer = NULL; 295 } 296 vfs_unbusy(mp, p); 297 return (error); 298 } 299 /* 300 * Put the new filesystem on the mount list after root. 301 */ 302 cache_purge(vp); 303 if (!error) { 304 simple_lock(&mountlist_slock); 305 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); 306 simple_unlock(&mountlist_slock); 307 checkdirs(vp); 308 VOP_UNLOCK(vp, 0, p); 309 if ((mp->mnt_flag & MNT_RDONLY) == 0) 310 error = vfs_allocate_syncvnode(mp); 311 vfs_unbusy(mp, p); 312 if (error = VFS_START(mp, 0, p)) 313 vrele(vp); 314 } else { 315 mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0; 316 mp->mnt_vfc->vfc_refcount--; 317 vfs_unbusy(mp, p); 318 free((caddr_t)mp, M_MOUNT); 319 vput(vp); 320 } 321 return (error); 322} 323 324/* 325 * Scan all active processes to see if any of them have a current 326 * or root directory onto which the new filesystem has just been 327 * mounted. If so, replace them with the new mount point. 328 */ 329static void 330checkdirs(olddp) 331 struct vnode *olddp; 332{ 333 struct filedesc *fdp; 334 struct vnode *newdp; 335 struct proc *p; 336 337 if (olddp->v_usecount == 1) 338 return; 339 if (VFS_ROOT(olddp->v_mountedhere, &newdp)) 340 panic("mount: lost mount"); 341 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 342 fdp = p->p_fd; 343 if (fdp->fd_cdir == olddp) { 344 vrele(fdp->fd_cdir); 345 VREF(newdp); 346 fdp->fd_cdir = newdp; 347 } 348 if (fdp->fd_rdir == olddp) { 349 vrele(fdp->fd_rdir); 350 VREF(newdp); 351 fdp->fd_rdir = newdp; 352 } 353 } 354 if (rootvnode == olddp) { 355 vrele(rootvnode); 356 VREF(newdp); 357 rootvnode = newdp; 358 } 359 vput(newdp); 360} 361 362/* 363 * Unmount a file system. 364 * 365 * Note: unmount takes a path to the vnode mounted on as argument, 366 * not special file (as before). 367 */ 368#ifndef _SYS_SYSPROTO_H_ 369struct unmount_args { 370 char *path; 371 int flags; 372}; 373#endif 374/* ARGSUSED */ 375int 376unmount(p, uap) 377 struct proc *p; 378 register struct unmount_args /* { 379 syscallarg(char *) path; 380 syscallarg(int) flags; 381 } */ *uap; 382{ 383 register struct vnode *vp; 384 struct mount *mp; 385 int error; 386 struct nameidata nd; 387 388 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 389 SCARG(uap, path), p); 390 if (error = namei(&nd)) 391 return (error); 392 vp = nd.ni_vp; 393 mp = vp->v_mount; 394 395 /* 396 * Only root, or the user that did the original mount is 397 * permitted to unmount this filesystem. 398 */ 399 if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) && 400 (error = suser(p->p_ucred, &p->p_acflag))) { 401 vput(vp); 402 return (error); 403 } 404 405 /* 406 * Don't allow unmounting the root file system. 407 */ 408 if (mp->mnt_flag & MNT_ROOTFS) { 409 vput(vp); 410 return (EINVAL); 411 } 412 413 /* 414 * Must be the root of the filesystem 415 */ 416 if ((vp->v_flag & VROOT) == 0) { 417 vput(vp); 418 return (EINVAL); 419 } 420 vput(vp); 421 return (dounmount(mp, SCARG(uap, flags), p)); 422} 423 424/* 425 * Do the actual file system unmount. 426 */ 427int 428dounmount(mp, flags, p) 429 register struct mount *mp; 430 int flags; 431 struct proc *p; 432{ 433 struct vnode *coveredvp; 434 int error; 435 436 simple_lock(&mountlist_slock); 437 mp->mnt_kern_flag |= MNTK_UNMOUNT; 438 lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p); 439 440 if (mp->mnt_flag & MNT_EXPUBLIC) 441 vfs_setpublicfs(NULL, NULL, NULL); 442 443 vfs_msync(mp, MNT_WAIT); 444 mp->mnt_flag &=~ MNT_ASYNC; 445 cache_purgevfs(mp); /* remove cache entries for this file sys */ 446 if (mp->mnt_syncer != NULL) 447 vrele(mp->mnt_syncer); 448 if (((mp->mnt_flag & MNT_RDONLY) || 449 (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) || 450 (flags & MNT_FORCE)) 451 error = VFS_UNMOUNT(mp, flags, p); 452 simple_lock(&mountlist_slock); 453 if (error) { 454 if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL) 455 (void) vfs_allocate_syncvnode(mp); 456 mp->mnt_kern_flag &= ~MNTK_UNMOUNT; 457 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE, 458 &mountlist_slock, p); 459 return (error); 460 } 461 CIRCLEQ_REMOVE(&mountlist, mp, mnt_list); 462 if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) { 463 coveredvp->v_mountedhere = (struct mount *)0; 464 vrele(coveredvp); 465 } 466 mp->mnt_vfc->vfc_refcount--; 467 if (mp->mnt_vnodelist.lh_first != NULL) 468 panic("unmount: dangling vnode"); 469 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p); 470 if (mp->mnt_kern_flag & MNTK_MWAIT) 471 wakeup((caddr_t)mp); 472 free((caddr_t)mp, M_MOUNT); 473 return (0); 474} 475 476/* 477 * Sync each mounted filesystem. 478 */ 479#ifndef _SYS_SYSPROTO_H_ 480struct sync_args { 481 int dummy; 482}; 483#endif 484 485#ifdef DEBUG 486static int syncprt = 0; 487SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, ""); 488#endif 489 490/* ARGSUSED */ 491int 492sync(p, uap) 493 struct proc *p; 494 struct sync_args *uap; 495{ 496 register struct mount *mp, *nmp; 497 int asyncflag; 498 499 simple_lock(&mountlist_slock); 500 for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { 501 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { 502 nmp = mp->mnt_list.cqe_next; 503 continue; 504 } 505 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 506 asyncflag = mp->mnt_flag & MNT_ASYNC; 507 mp->mnt_flag &= ~MNT_ASYNC; 508 vfs_msync(mp, MNT_NOWAIT); 509 VFS_SYNC(mp, MNT_NOWAIT, 510 ((p != NULL) ? p->p_ucred : NOCRED), p); 511 mp->mnt_flag |= asyncflag; 512 } 513 simple_lock(&mountlist_slock); 514 nmp = mp->mnt_list.cqe_next; 515 vfs_unbusy(mp, p); 516 } 517 simple_unlock(&mountlist_slock); 518#if 0 519/* 520 * XXX don't call vfs_bufstats() yet because that routine 521 * was not imported in the Lite2 merge. 522 */ 523#ifdef DIAGNOSTIC 524 if (syncprt) 525 vfs_bufstats(); 526#endif /* DIAGNOSTIC */ 527#endif 528 return (0); 529} 530 531/* 532 * Change filesystem quotas. 533 */ 534#ifndef _SYS_SYSPROTO_H_ 535struct quotactl_args { 536 char *path; 537 int cmd; 538 int uid; 539 caddr_t arg; 540}; 541#endif 542/* ARGSUSED */ 543int 544quotactl(p, uap) 545 struct proc *p; 546 register struct quotactl_args /* { 547 syscallarg(char *) path; 548 syscallarg(int) cmd; 549 syscallarg(int) uid; 550 syscallarg(caddr_t) arg; 551 } */ *uap; 552{ 553 register struct mount *mp; 554 int error; 555 struct nameidata nd; 556 557 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 558 if (error = namei(&nd)) 559 return (error); 560 mp = nd.ni_vp->v_mount; 561 vrele(nd.ni_vp); 562 return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid), 563 SCARG(uap, arg), p)); 564} 565 566/* 567 * Get filesystem statistics. 568 */ 569#ifndef _SYS_SYSPROTO_H_ 570struct statfs_args { 571 char *path; 572 struct statfs *buf; 573}; 574#endif 575/* ARGSUSED */ 576int 577statfs(p, uap) 578 struct proc *p; 579 register struct statfs_args /* { 580 syscallarg(char *) path; 581 syscallarg(struct statfs *) buf; 582 } */ *uap; 583{ 584 register struct mount *mp; 585 register struct statfs *sp; 586 int error; 587 struct nameidata nd; 588 struct statfs sb; 589 590 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 591 if (error = namei(&nd)) 592 return (error); 593 mp = nd.ni_vp->v_mount; 594 sp = &mp->mnt_stat; 595 vrele(nd.ni_vp); 596 error = VFS_STATFS(mp, sp, p); 597 if (error) 598 return (error); 599 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 600 if (p->p_ucred->cr_uid != 0) { 601 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 602 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 603 sp = &sb; 604 } 605 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 606} 607 608/* 609 * Get filesystem statistics. 610 */ 611#ifndef _SYS_SYSPROTO_H_ 612struct fstatfs_args { 613 int fd; 614 struct statfs *buf; 615}; 616#endif 617/* ARGSUSED */ 618int 619fstatfs(p, uap) 620 struct proc *p; 621 register struct fstatfs_args /* { 622 syscallarg(int) fd; 623 syscallarg(struct statfs *) buf; 624 } */ *uap; 625{ 626 struct file *fp; 627 struct mount *mp; 628 register struct statfs *sp; 629 int error; 630 struct statfs sb; 631 632 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 633 return (error); 634 mp = ((struct vnode *)fp->f_data)->v_mount; 635 sp = &mp->mnt_stat; 636 error = VFS_STATFS(mp, sp, p); 637 if (error) 638 return (error); 639 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 640 if (p->p_ucred->cr_uid != 0) { 641 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 642 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 643 sp = &sb; 644 } 645 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 646} 647 648/* 649 * Get statistics on all filesystems. 650 */ 651#ifndef _SYS_SYSPROTO_H_ 652struct getfsstat_args { 653 struct statfs *buf; 654 long bufsize; 655 int flags; 656}; 657#endif 658int 659getfsstat(p, uap) 660 struct proc *p; 661 register struct getfsstat_args /* { 662 syscallarg(struct statfs *) buf; 663 syscallarg(long) bufsize; 664 syscallarg(int) flags; 665 } */ *uap; 666{ 667 register struct mount *mp, *nmp; 668 register struct statfs *sp; 669 caddr_t sfsp; 670 long count, maxcount, error; 671 672 maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); 673 sfsp = (caddr_t)SCARG(uap, buf); 674 count = 0; 675 simple_lock(&mountlist_slock); 676 for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { 677 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { 678 nmp = mp->mnt_list.cqe_next; 679 continue; 680 } 681 if (sfsp && count < maxcount) { 682 sp = &mp->mnt_stat; 683 /* 684 * If MNT_NOWAIT or MNT_LAZY is specified, do not 685 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY 686 * overrides MNT_WAIT. 687 */ 688 if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 || 689 (SCARG(uap, flags) & MNT_WAIT)) && 690 (error = VFS_STATFS(mp, sp, p))) { 691 simple_lock(&mountlist_slock); 692 nmp = mp->mnt_list.cqe_next; 693 vfs_unbusy(mp, p); 694 continue; 695 } 696 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 697 error = copyout((caddr_t)sp, sfsp, sizeof(*sp)); 698 if (error) { 699 vfs_unbusy(mp, p); 700 return (error); 701 } 702 sfsp += sizeof(*sp); 703 } 704 count++; 705 simple_lock(&mountlist_slock); 706 nmp = mp->mnt_list.cqe_next; 707 vfs_unbusy(mp, p); 708 } 709 simple_unlock(&mountlist_slock); 710 if (sfsp && count > maxcount) 711 p->p_retval[0] = maxcount; 712 else 713 p->p_retval[0] = count; 714 return (0); 715} 716 717/* 718 * Change current working directory to a given file descriptor. 719 */ 720#ifndef _SYS_SYSPROTO_H_ 721struct fchdir_args { 722 int fd; 723}; 724#endif 725/* ARGSUSED */ 726int 727fchdir(p, uap) 728 struct proc *p; 729 struct fchdir_args /* { 730 syscallarg(int) fd; 731 } */ *uap; 732{ 733 register struct filedesc *fdp = p->p_fd; 734 struct vnode *vp, *tdp; 735 struct mount *mp; 736 struct file *fp; 737 int error; 738 739 if (error = getvnode(fdp, SCARG(uap, fd), &fp)) 740 return (error); 741 vp = (struct vnode *)fp->f_data; 742 VREF(vp); 743 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 744 if (vp->v_type != VDIR) 745 error = ENOTDIR; 746 else 747 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 748 while (!error && (mp = vp->v_mountedhere) != NULL) { 749 if (vfs_busy(mp, 0, 0, p)) 750 continue; 751 error = VFS_ROOT(mp, &tdp); 752 vfs_unbusy(mp, p); 753 if (error) 754 break; 755 vput(vp); 756 vp = tdp; 757 } 758 if (error) { 759 vput(vp); 760 return (error); 761 } 762 VOP_UNLOCK(vp, 0, p); 763 vrele(fdp->fd_cdir); 764 fdp->fd_cdir = vp; 765 return (0); 766} 767 768/* 769 * Change current working directory (``.''). 770 */ 771#ifndef _SYS_SYSPROTO_H_ 772struct chdir_args { 773 char *path; 774}; 775#endif 776/* ARGSUSED */ 777int 778chdir(p, uap) 779 struct proc *p; 780 struct chdir_args /* { 781 syscallarg(char *) path; 782 } */ *uap; 783{ 784 register struct filedesc *fdp = p->p_fd; 785 int error; 786 struct nameidata nd; 787 788 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 789 SCARG(uap, path), p); 790 if (error = change_dir(&nd, p)) 791 return (error); 792 vrele(fdp->fd_cdir); 793 fdp->fd_cdir = nd.ni_vp; 794 return (0); 795} 796 797/* 798 * Change notion of root (``/'') directory. 799 */ 800#ifndef _SYS_SYSPROTO_H_ 801struct chroot_args { 802 char *path; 803}; 804#endif 805/* ARGSUSED */ 806int 807chroot(p, uap) 808 struct proc *p; 809 struct chroot_args /* { 810 syscallarg(char *) path; 811 } */ *uap; 812{ 813 register struct filedesc *fdp = p->p_fd; 814 int error; 815 struct nameidata nd; 816 817 error = suser(p->p_ucred, &p->p_acflag); 818 if (error) 819 return (error); 820 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 821 SCARG(uap, path), p); 822 if (error = change_dir(&nd, p)) 823 return (error); 824 vrele(fdp->fd_rdir); 825 fdp->fd_rdir = nd.ni_vp; 826 return (0); 827} 828 829/* 830 * Common routine for chroot and chdir. 831 */ 832static int 833change_dir(ndp, p) 834 register struct nameidata *ndp; 835 struct proc *p; 836{ 837 struct vnode *vp; 838 int error; 839 840 error = namei(ndp); 841 if (error) 842 return (error); 843 vp = ndp->ni_vp; 844 if (vp->v_type != VDIR) 845 error = ENOTDIR; 846 else 847 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 848 if (error) 849 vput(vp); 850 else 851 VOP_UNLOCK(vp, 0, p); 852 return (error); 853} 854 855/* 856 * Check permissions, allocate an open file structure, 857 * and call the device open routine if any. 858 */ 859#ifndef _SYS_SYSPROTO_H_ 860struct open_args { 861 char *path; 862 int flags; 863 int mode; 864}; 865#endif 866int 867open(p, uap) 868 struct proc *p; 869 register struct open_args /* { 870 syscallarg(char *) path; 871 syscallarg(int) flags; 872 syscallarg(int) mode; 873 } */ *uap; 874{ 875 register struct filedesc *fdp = p->p_fd; 876 register struct file *fp; 877 register struct vnode *vp; 878 int cmode, flags, oflags; 879 struct file *nfp; 880 int type, indx, error; 881 struct flock lf; 882 struct nameidata nd; 883 884 oflags = SCARG(uap, flags); 885 if ((oflags & O_ACCMODE) == O_ACCMODE) 886 return (EINVAL); 887 flags = FFLAGS(oflags); 888 error = falloc(p, &nfp, &indx); 889 if (error) 890 return (error); 891 fp = nfp; 892 cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; 893 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 894 p->p_dupfd = -indx - 1; /* XXX check for fdopen */ 895 error = vn_open(&nd, flags, cmode); 896 if (error) { 897 ffree(fp); 898 if ((error == ENODEV || error == ENXIO) && 899 p->p_dupfd >= 0 && /* XXX from fdopen */ 900 (error = 901 dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) { 902 p->p_retval[0] = indx; 903 return (0); 904 } 905 if (error == ERESTART) 906 error = EINTR; 907 fdp->fd_ofiles[indx] = NULL; 908 return (error); 909 } 910 p->p_dupfd = 0; 911 vp = nd.ni_vp; 912 913 fp->f_flag = flags & FMASK; 914 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE); 915 fp->f_ops = &vnops; 916 fp->f_data = (caddr_t)vp; 917 if (flags & (O_EXLOCK | O_SHLOCK)) { 918 lf.l_whence = SEEK_SET; 919 lf.l_start = 0; 920 lf.l_len = 0; 921 if (flags & O_EXLOCK) 922 lf.l_type = F_WRLCK; 923 else 924 lf.l_type = F_RDLCK; 925 type = F_FLOCK; 926 if ((flags & FNONBLOCK) == 0) 927 type |= F_WAIT; 928 VOP_UNLOCK(vp, 0, p); 929 if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) { 930 (void) vn_close(vp, fp->f_flag, fp->f_cred, p); 931 ffree(fp); 932 fdp->fd_ofiles[indx] = NULL; 933 return (error); 934 } 935 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 936 fp->f_flag |= FHASLOCK; 937 } 938 if ((vp->v_type == VREG) && (vp->v_object == NULL)) 939 vfs_object_create(vp, p, p->p_ucred, TRUE); 940 VOP_UNLOCK(vp, 0, p); 941 p->p_retval[0] = indx; 942 return (0); 943} 944 945#ifdef COMPAT_43 946/* 947 * Create a file. 948 */ 949#ifndef _SYS_SYSPROTO_H_ 950struct ocreat_args { 951 char *path; 952 int mode; 953}; 954#endif 955int 956ocreat(p, uap) 957 struct proc *p; 958 register struct ocreat_args /* { 959 syscallarg(char *) path; 960 syscallarg(int) mode; 961 } */ *uap; 962{ 963 struct open_args /* { 964 syscallarg(char *) path; 965 syscallarg(int) flags; 966 syscallarg(int) mode; 967 } */ nuap; 968 969 SCARG(&nuap, path) = SCARG(uap, path); 970 SCARG(&nuap, mode) = SCARG(uap, mode); 971 SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC; 972 return (open(p, &nuap)); 973} 974#endif /* COMPAT_43 */ 975 976/* 977 * Create a special file. 978 */ 979#ifndef _SYS_SYSPROTO_H_ 980struct mknod_args { 981 char *path; 982 int mode; 983 int dev; 984}; 985#endif 986/* ARGSUSED */ 987int 988mknod(p, uap) 989 struct proc *p; 990 register struct mknod_args /* { 991 syscallarg(char *) path; 992 syscallarg(int) mode; 993 syscallarg(int) dev; 994 } */ *uap; 995{ 996 register struct vnode *vp; 997 struct vattr vattr; 998 int error; 999 int whiteout; 1000 struct nameidata nd; 1001 1002 error = suser(p->p_ucred, &p->p_acflag); 1003 if (error) 1004 return (error); 1005 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1006 if (error = namei(&nd)) 1007 return (error); 1008 vp = nd.ni_vp; 1009 if (vp != NULL) 1010 error = EEXIST; 1011 else { 1012 VATTR_NULL(&vattr); 1013 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; 1014 vattr.va_rdev = SCARG(uap, dev); 1015 whiteout = 0; 1016 1017 switch (SCARG(uap, mode) & S_IFMT) { 1018 case S_IFMT: /* used by badsect to flag bad sectors */ 1019 vattr.va_type = VBAD; 1020 break; 1021 case S_IFCHR: 1022 vattr.va_type = VCHR; 1023 break; 1024 case S_IFBLK: 1025 vattr.va_type = VBLK; 1026 break; 1027 case S_IFWHT: 1028 whiteout = 1; 1029 break; 1030 default: 1031 error = EINVAL; 1032 break; 1033 } 1034 } 1035 if (!error) { 1036 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1037 if (whiteout) { 1038 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); 1039 if (error) 1040 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1041 vput(nd.ni_dvp); 1042 } else { 1043 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, 1044 &nd.ni_cnd, &vattr); 1045 } 1046 } else { 1047 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1048 if (nd.ni_dvp == vp) 1049 vrele(nd.ni_dvp); 1050 else 1051 vput(nd.ni_dvp); 1052 if (vp) 1053 vrele(vp); 1054 } 1055 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod"); 1056 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod"); 1057 return (error); 1058} 1059 1060/* 1061 * Create a named pipe. 1062 */ 1063#ifndef _SYS_SYSPROTO_H_ 1064struct mkfifo_args { 1065 char *path; 1066 int mode; 1067}; 1068#endif 1069/* ARGSUSED */ 1070int 1071mkfifo(p, uap) 1072 struct proc *p; 1073 register struct mkfifo_args /* { 1074 syscallarg(char *) path; 1075 syscallarg(int) mode; 1076 } */ *uap; 1077{ 1078 struct vattr vattr; 1079 int error; 1080 struct nameidata nd; 1081 1082 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1083 if (error = namei(&nd)) 1084 return (error); 1085 if (nd.ni_vp != NULL) { 1086 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1087 if (nd.ni_dvp == nd.ni_vp) 1088 vrele(nd.ni_dvp); 1089 else 1090 vput(nd.ni_dvp); 1091 vrele(nd.ni_vp); 1092 return (EEXIST); 1093 } 1094 VATTR_NULL(&vattr); 1095 vattr.va_type = VFIFO; 1096 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; 1097 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1098 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr)); 1099} 1100 1101/* 1102 * Make a hard file link. 1103 */ 1104#ifndef _SYS_SYSPROTO_H_ 1105struct link_args { 1106 char *path; 1107 char *link; 1108}; 1109#endif 1110/* ARGSUSED */ 1111int 1112link(p, uap) 1113 struct proc *p; 1114 register struct link_args /* { 1115 syscallarg(char *) path; 1116 syscallarg(char *) link; 1117 } */ *uap; 1118{ 1119 register struct vnode *vp; 1120 struct nameidata nd; 1121 int error; 1122 1123 NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), p); 1124 if (error = namei(&nd)) 1125 return (error); 1126 vp = nd.ni_vp; 1127 if (vp->v_type == VDIR) 1128 error = EPERM; /* POSIX */ 1129 else { 1130 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p); 1131 error = namei(&nd); 1132 if (!error) { 1133 if (nd.ni_vp != NULL) { 1134 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1135 if (nd.ni_dvp == nd.ni_vp) 1136 vrele(nd.ni_dvp); 1137 else 1138 vput(nd.ni_dvp); 1139 if (nd.ni_vp) 1140 vrele(nd.ni_vp); 1141 error = EEXIST; 1142 } else { 1143 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, 1144 LEASE_WRITE); 1145 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1146 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 1147 } 1148 } 1149 } 1150 vrele(vp); 1151 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link"); 1152 ASSERT_VOP_UNLOCKED(nd.ni_vp, "link"); 1153 return (error); 1154} 1155 1156/* 1157 * Make a symbolic link. 1158 */ 1159#ifndef _SYS_SYSPROTO_H_ 1160struct symlink_args { 1161 char *path; 1162 char *link; 1163}; 1164#endif 1165/* ARGSUSED */ 1166int 1167symlink(p, uap) 1168 struct proc *p; 1169 register struct symlink_args /* { 1170 syscallarg(char *) path; 1171 syscallarg(char *) link; 1172 } */ *uap; 1173{ 1174 struct vattr vattr; 1175 char *path; 1176 int error; 1177 struct nameidata nd; 1178 1179 path = zalloc(namei_zone); 1180 if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) 1181 goto out; 1182 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p); 1183 if (error = namei(&nd)) 1184 goto out; 1185 if (nd.ni_vp) { 1186 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1187 if (nd.ni_dvp == nd.ni_vp) 1188 vrele(nd.ni_dvp); 1189 else 1190 vput(nd.ni_dvp); 1191 vrele(nd.ni_vp); 1192 error = EEXIST; 1193 goto out; 1194 } 1195 VATTR_NULL(&vattr); 1196 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; 1197 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1198 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 1199 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink"); 1200 ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink"); 1201out: 1202 zfree(namei_zone, path); 1203 return (error); 1204} 1205 1206/* 1207 * Delete a whiteout from the filesystem. 1208 */ 1209/* ARGSUSED */ 1210int 1211undelete(p, uap) 1212 struct proc *p; 1213 register struct undelete_args /* { 1214 syscallarg(char *) path; 1215 } */ *uap; 1216{ 1217 int error; 1218 struct nameidata nd; 1219 1220 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, 1221 SCARG(uap, path), p); 1222 error = namei(&nd); 1223 if (error) 1224 return (error); 1225 1226 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 1227 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1228 if (nd.ni_dvp == nd.ni_vp) 1229 vrele(nd.ni_dvp); 1230 else 1231 vput(nd.ni_dvp); 1232 if (nd.ni_vp) 1233 vrele(nd.ni_vp); 1234 return (EEXIST); 1235 } 1236 1237 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1238 if (error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) 1239 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1240 vput(nd.ni_dvp); 1241 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete"); 1242 ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete"); 1243 return (error); 1244} 1245 1246/* 1247 * Delete a name from the filesystem. 1248 */ 1249#ifndef _SYS_SYSPROTO_H_ 1250struct unlink_args { 1251 char *path; 1252}; 1253#endif 1254/* ARGSUSED */ 1255int 1256unlink(p, uap) 1257 struct proc *p; 1258 struct unlink_args /* { 1259 syscallarg(char *) path; 1260 } */ *uap; 1261{ 1262 register struct vnode *vp; 1263 int error; 1264 struct nameidata nd; 1265 1266 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1267 if (error = namei(&nd)) 1268 return (error); 1269 vp = nd.ni_vp; 1270 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1271 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1272 1273 if (vp->v_type == VDIR) 1274 error = EPERM; /* POSIX */ 1275 else { 1276 /* 1277 * The root of a mounted filesystem cannot be deleted. 1278 * 1279 * XXX: can this only be a VDIR case? 1280 */ 1281 if (vp->v_flag & VROOT) 1282 error = EBUSY; 1283 } 1284 1285 if (!error) { 1286 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1287 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd); 1288 } else { 1289 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1290 if (nd.ni_dvp == vp) 1291 vrele(nd.ni_dvp); 1292 else 1293 vput(nd.ni_dvp); 1294 if (vp != NULLVP) 1295 vput(vp); 1296 } 1297 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink"); 1298 ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink"); 1299 return (error); 1300} 1301 1302/* 1303 * Reposition read/write file offset. 1304 */ 1305#ifndef _SYS_SYSPROTO_H_ 1306struct lseek_args { 1307 int fd; 1308 int pad; 1309 off_t offset; 1310 int whence; 1311}; 1312#endif 1313int 1314lseek(p, uap) 1315 struct proc *p; 1316 register struct lseek_args /* { 1317 syscallarg(int) fd; 1318 syscallarg(int) pad; 1319 syscallarg(off_t) offset; 1320 syscallarg(int) whence; 1321 } */ *uap; 1322{ 1323 struct ucred *cred = p->p_ucred; 1324 register struct filedesc *fdp = p->p_fd; 1325 register struct file *fp; 1326 struct vattr vattr; 1327 int error; 1328 1329 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || 1330 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) 1331 return (EBADF); 1332 if (fp->f_type != DTYPE_VNODE) 1333 return (ESPIPE); 1334 switch (SCARG(uap, whence)) { 1335 case L_INCR: 1336 fp->f_offset += SCARG(uap, offset); 1337 break; 1338 case L_XTND: 1339 error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p); 1340 if (error) 1341 return (error); 1342 fp->f_offset = SCARG(uap, offset) + vattr.va_size; 1343 break; 1344 case L_SET: 1345 fp->f_offset = SCARG(uap, offset); 1346 break; 1347 default: 1348 return (EINVAL); 1349 } 1350 *(off_t *)(p->p_retval) = fp->f_offset; 1351 return (0); 1352} 1353 1354#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1355/* 1356 * Reposition read/write file offset. 1357 */ 1358#ifndef _SYS_SYSPROTO_H_ 1359struct olseek_args { 1360 int fd; 1361 long offset; 1362 int whence; 1363}; 1364#endif 1365int 1366olseek(p, uap) 1367 struct proc *p; 1368 register struct olseek_args /* { 1369 syscallarg(int) fd; 1370 syscallarg(long) offset; 1371 syscallarg(int) whence; 1372 } */ *uap; 1373{ 1374 struct lseek_args /* { 1375 syscallarg(int) fd; 1376 syscallarg(int) pad; 1377 syscallarg(off_t) offset; 1378 syscallarg(int) whence; 1379 } */ nuap; 1380 int error; 1381 1382 SCARG(&nuap, fd) = SCARG(uap, fd); 1383 SCARG(&nuap, offset) = SCARG(uap, offset); 1384 SCARG(&nuap, whence) = SCARG(uap, whence); 1385 error = lseek(p, &nuap); 1386 return (error); 1387} 1388#endif /* COMPAT_43 */ 1389 1390/* 1391 * Check access permissions. 1392 */ 1393#ifndef _SYS_SYSPROTO_H_ 1394struct access_args { 1395 char *path; 1396 int flags; 1397}; 1398#endif 1399int 1400access(p, uap) 1401 struct proc *p; 1402 register struct access_args /* { 1403 syscallarg(char *) path; 1404 syscallarg(int) flags; 1405 } */ *uap; 1406{ 1407 register struct ucred *cred = p->p_ucred; 1408 register struct vnode *vp; 1409 int error, flags, t_gid, t_uid; 1410 struct nameidata nd; 1411 1412 t_uid = cred->cr_uid; 1413 t_gid = cred->cr_groups[0]; 1414 cred->cr_uid = p->p_cred->p_ruid; 1415 cred->cr_groups[0] = p->p_cred->p_rgid; 1416 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1417 SCARG(uap, path), p); 1418 if (error = namei(&nd)) 1419 goto out1; 1420 vp = nd.ni_vp; 1421 1422 /* Flags == 0 means only check for existence. */ 1423 if (SCARG(uap, flags)) { 1424 flags = 0; 1425 if (SCARG(uap, flags) & R_OK) 1426 flags |= VREAD; 1427 if (SCARG(uap, flags) & W_OK) 1428 flags |= VWRITE; 1429 if (SCARG(uap, flags) & X_OK) 1430 flags |= VEXEC; 1431 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1432 error = VOP_ACCESS(vp, flags, cred, p); 1433 } 1434 vput(vp); 1435out1: 1436 cred->cr_uid = t_uid; 1437 cred->cr_groups[0] = t_gid; 1438 return (error); 1439} 1440 1441#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1442/* 1443 * Get file status; this version follows links. 1444 */ 1445#ifndef _SYS_SYSPROTO_H_ 1446struct ostat_args { 1447 char *path; 1448 struct ostat *ub; 1449}; 1450#endif 1451/* ARGSUSED */ 1452int 1453ostat(p, uap) 1454 struct proc *p; 1455 register struct ostat_args /* { 1456 syscallarg(char *) path; 1457 syscallarg(struct ostat *) ub; 1458 } */ *uap; 1459{ 1460 struct stat sb; 1461 struct ostat osb; 1462 int error; 1463 struct nameidata nd; 1464 1465 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1466 SCARG(uap, path), p); 1467 if (error = namei(&nd)) 1468 return (error); 1469 error = vn_stat(nd.ni_vp, &sb, p); 1470 vput(nd.ni_vp); 1471 if (error) 1472 return (error); 1473 cvtstat(&sb, &osb); 1474 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1475 return (error); 1476} 1477 1478/* 1479 * Get file status; this version does not follow links. 1480 */ 1481#ifndef _SYS_SYSPROTO_H_ 1482struct olstat_args { 1483 char *path; 1484 struct ostat *ub; 1485}; 1486#endif 1487/* ARGSUSED */ 1488int 1489olstat(p, uap) 1490 struct proc *p; 1491 register struct olstat_args /* { 1492 syscallarg(char *) path; 1493 syscallarg(struct ostat *) ub; 1494 } */ *uap; 1495{ 1496 struct vnode *vp; 1497 struct stat sb; 1498 struct ostat osb; 1499 int error; 1500 struct nameidata nd; 1501 1502 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1503 SCARG(uap, path), p); 1504 if (error = namei(&nd)) 1505 return (error); 1506 vp = nd.ni_vp; 1507 error = vn_stat(vp, &sb, p);
|
1506 if (vp->v_type == VLNK) 1507 sb.st_mode |= S_IFLNK | ACCESSPERMS; /* 0777 */
| |
1508 vput(vp); 1509 if (error) 1510 return (error); 1511 cvtstat(&sb, &osb); 1512 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1513 return (error); 1514} 1515 1516/* 1517 * Convert from an old to a new stat structure. 1518 */ 1519void 1520cvtstat(st, ost) 1521 struct stat *st; 1522 struct ostat *ost; 1523{ 1524 1525 ost->st_dev = st->st_dev; 1526 ost->st_ino = st->st_ino; 1527 ost->st_mode = st->st_mode; 1528 ost->st_nlink = st->st_nlink; 1529 ost->st_uid = st->st_uid; 1530 ost->st_gid = st->st_gid; 1531 ost->st_rdev = st->st_rdev; 1532 if (st->st_size < (quad_t)1 << 32) 1533 ost->st_size = st->st_size; 1534 else 1535 ost->st_size = -2; 1536 ost->st_atime = st->st_atime; 1537 ost->st_mtime = st->st_mtime; 1538 ost->st_ctime = st->st_ctime; 1539 ost->st_blksize = st->st_blksize; 1540 ost->st_blocks = st->st_blocks; 1541 ost->st_flags = st->st_flags; 1542 ost->st_gen = st->st_gen; 1543} 1544#endif /* COMPAT_43 || COMPAT_SUNOS */ 1545 1546/* 1547 * Get file status; this version follows links. 1548 */ 1549#ifndef _SYS_SYSPROTO_H_ 1550struct stat_args { 1551 char *path; 1552 struct stat *ub; 1553}; 1554#endif 1555/* ARGSUSED */ 1556int 1557stat(p, uap) 1558 struct proc *p; 1559 register struct stat_args /* { 1560 syscallarg(char *) path; 1561 syscallarg(struct stat *) ub; 1562 } */ *uap; 1563{ 1564 struct stat sb; 1565 int error; 1566 struct nameidata nd; 1567 1568 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1569 SCARG(uap, path), p); 1570 if (error = namei(&nd)) 1571 return (error); 1572 error = vn_stat(nd.ni_vp, &sb, p); 1573 vput(nd.ni_vp); 1574 if (error) 1575 return (error); 1576 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 1577 return (error); 1578} 1579 1580/* 1581 * Get file status; this version does not follow links. 1582 */ 1583#ifndef _SYS_SYSPROTO_H_ 1584struct lstat_args { 1585 char *path; 1586 struct stat *ub; 1587}; 1588#endif 1589/* ARGSUSED */ 1590int 1591lstat(p, uap) 1592 struct proc *p; 1593 register struct lstat_args /* { 1594 syscallarg(char *) path; 1595 syscallarg(struct stat *) ub; 1596 } */ *uap; 1597{ 1598 int error; 1599 struct vnode *vp; 1600 struct stat sb; 1601 struct nameidata nd; 1602 1603 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1604 SCARG(uap, path), p); 1605 if (error = namei(&nd)) 1606 return (error); 1607 vp = nd.ni_vp; 1608 error = vn_stat(vp, &sb, p);
| 1508 vput(vp); 1509 if (error) 1510 return (error); 1511 cvtstat(&sb, &osb); 1512 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1513 return (error); 1514} 1515 1516/* 1517 * Convert from an old to a new stat structure. 1518 */ 1519void 1520cvtstat(st, ost) 1521 struct stat *st; 1522 struct ostat *ost; 1523{ 1524 1525 ost->st_dev = st->st_dev; 1526 ost->st_ino = st->st_ino; 1527 ost->st_mode = st->st_mode; 1528 ost->st_nlink = st->st_nlink; 1529 ost->st_uid = st->st_uid; 1530 ost->st_gid = st->st_gid; 1531 ost->st_rdev = st->st_rdev; 1532 if (st->st_size < (quad_t)1 << 32) 1533 ost->st_size = st->st_size; 1534 else 1535 ost->st_size = -2; 1536 ost->st_atime = st->st_atime; 1537 ost->st_mtime = st->st_mtime; 1538 ost->st_ctime = st->st_ctime; 1539 ost->st_blksize = st->st_blksize; 1540 ost->st_blocks = st->st_blocks; 1541 ost->st_flags = st->st_flags; 1542 ost->st_gen = st->st_gen; 1543} 1544#endif /* COMPAT_43 || COMPAT_SUNOS */ 1545 1546/* 1547 * Get file status; this version follows links. 1548 */ 1549#ifndef _SYS_SYSPROTO_H_ 1550struct stat_args { 1551 char *path; 1552 struct stat *ub; 1553}; 1554#endif 1555/* ARGSUSED */ 1556int 1557stat(p, uap) 1558 struct proc *p; 1559 register struct stat_args /* { 1560 syscallarg(char *) path; 1561 syscallarg(struct stat *) ub; 1562 } */ *uap; 1563{ 1564 struct stat sb; 1565 int error; 1566 struct nameidata nd; 1567 1568 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1569 SCARG(uap, path), p); 1570 if (error = namei(&nd)) 1571 return (error); 1572 error = vn_stat(nd.ni_vp, &sb, p); 1573 vput(nd.ni_vp); 1574 if (error) 1575 return (error); 1576 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 1577 return (error); 1578} 1579 1580/* 1581 * Get file status; this version does not follow links. 1582 */ 1583#ifndef _SYS_SYSPROTO_H_ 1584struct lstat_args { 1585 char *path; 1586 struct stat *ub; 1587}; 1588#endif 1589/* ARGSUSED */ 1590int 1591lstat(p, uap) 1592 struct proc *p; 1593 register struct lstat_args /* { 1594 syscallarg(char *) path; 1595 syscallarg(struct stat *) ub; 1596 } */ *uap; 1597{ 1598 int error; 1599 struct vnode *vp; 1600 struct stat sb; 1601 struct nameidata nd; 1602 1603 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1604 SCARG(uap, path), p); 1605 if (error = namei(&nd)) 1606 return (error); 1607 vp = nd.ni_vp; 1608 error = vn_stat(vp, &sb, p);
|
1609 if (vp->v_type == VLNK) 1610 sb.st_mode |= S_IFLNK | ACCESSPERMS; /* 0777 */
| |
1611 vput(vp); 1612 if (error) 1613 return (error); 1614 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 1615 return (error); 1616} 1617 1618/* 1619 * Get configurable pathname variables. 1620 */ 1621#ifndef _SYS_SYSPROTO_H_ 1622struct pathconf_args { 1623 char *path; 1624 int name; 1625}; 1626#endif 1627/* ARGSUSED */ 1628int 1629pathconf(p, uap) 1630 struct proc *p; 1631 register struct pathconf_args /* { 1632 syscallarg(char *) path; 1633 syscallarg(int) name; 1634 } */ *uap; 1635{ 1636 int error; 1637 struct nameidata nd; 1638 1639 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1640 SCARG(uap, path), p); 1641 if (error = namei(&nd)) 1642 return (error); 1643 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), p->p_retval); 1644 vput(nd.ni_vp); 1645 return (error); 1646} 1647 1648/* 1649 * Return target name of a symbolic link. 1650 */ 1651#ifndef _SYS_SYSPROTO_H_ 1652struct readlink_args { 1653 char *path; 1654 char *buf; 1655 int count; 1656}; 1657#endif 1658/* ARGSUSED */ 1659int 1660readlink(p, uap) 1661 struct proc *p; 1662 register struct readlink_args /* { 1663 syscallarg(char *) path; 1664 syscallarg(char *) buf; 1665 syscallarg(int) count; 1666 } */ *uap; 1667{ 1668 register struct vnode *vp; 1669 struct iovec aiov; 1670 struct uio auio; 1671 int error; 1672 struct nameidata nd; 1673 1674 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1675 SCARG(uap, path), p); 1676 if (error = namei(&nd)) 1677 return (error); 1678 vp = nd.ni_vp; 1679 if (vp->v_type != VLNK) 1680 error = EINVAL; 1681 else { 1682 aiov.iov_base = SCARG(uap, buf); 1683 aiov.iov_len = SCARG(uap, count); 1684 auio.uio_iov = &aiov; 1685 auio.uio_iovcnt = 1; 1686 auio.uio_offset = 0; 1687 auio.uio_rw = UIO_READ; 1688 auio.uio_segflg = UIO_USERSPACE; 1689 auio.uio_procp = p; 1690 auio.uio_resid = SCARG(uap, count); 1691 error = VOP_READLINK(vp, &auio, p->p_ucred); 1692 } 1693 vput(vp); 1694 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid; 1695 return (error); 1696} 1697 1698/* 1699 * Change flags of a file given a path name. 1700 */ 1701#ifndef _SYS_SYSPROTO_H_ 1702struct chflags_args { 1703 char *path; 1704 int flags; 1705}; 1706#endif 1707/* ARGSUSED */ 1708int 1709chflags(p, uap) 1710 struct proc *p; 1711 register struct chflags_args /* { 1712 syscallarg(char *) path; 1713 syscallarg(int) flags; 1714 } */ *uap; 1715{ 1716 register struct vnode *vp; 1717 struct vattr vattr; 1718 int error; 1719 struct nameidata nd; 1720 1721 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1722 if (error = namei(&nd)) 1723 return (error); 1724 vp = nd.ni_vp; 1725 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1726 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1727 VATTR_NULL(&vattr); 1728 vattr.va_flags = SCARG(uap, flags); 1729 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1730 vput(vp); 1731 return (error); 1732} 1733 1734/* 1735 * Change flags of a file given a file descriptor. 1736 */ 1737#ifndef _SYS_SYSPROTO_H_ 1738struct fchflags_args { 1739 int fd; 1740 int flags; 1741}; 1742#endif 1743/* ARGSUSED */ 1744int 1745fchflags(p, uap) 1746 struct proc *p; 1747 register struct fchflags_args /* { 1748 syscallarg(int) fd; 1749 syscallarg(int) flags; 1750 } */ *uap; 1751{ 1752 struct vattr vattr; 1753 struct vnode *vp; 1754 struct file *fp; 1755 int error; 1756 1757 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1758 return (error); 1759 vp = (struct vnode *)fp->f_data; 1760 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1761 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1762 VATTR_NULL(&vattr); 1763 vattr.va_flags = SCARG(uap, flags); 1764 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1765 VOP_UNLOCK(vp, 0, p); 1766 return (error); 1767} 1768 1769/* 1770 * Change mode of a file given path name. 1771 */ 1772#ifndef _SYS_SYSPROTO_H_ 1773struct chmod_args { 1774 char *path; 1775 int mode; 1776}; 1777#endif 1778/* ARGSUSED */ 1779int 1780chmod(p, uap) 1781 struct proc *p; 1782 register struct chmod_args /* { 1783 syscallarg(char *) path; 1784 syscallarg(int) mode; 1785 } */ *uap; 1786{ 1787 register struct vnode *vp; 1788 struct vattr vattr; 1789 int error; 1790 struct nameidata nd; 1791 1792 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1793 if (error = namei(&nd)) 1794 return (error); 1795 vp = nd.ni_vp; 1796 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1797 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1798 VATTR_NULL(&vattr); 1799 vattr.va_mode = SCARG(uap, mode) & ALLPERMS; 1800 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1801 vput(vp); 1802 return (error); 1803} 1804 1805/* 1806 * Change mode of a file given a file descriptor. 1807 */ 1808#ifndef _SYS_SYSPROTO_H_ 1809struct fchmod_args { 1810 int fd; 1811 int mode; 1812}; 1813#endif 1814/* ARGSUSED */ 1815int 1816fchmod(p, uap) 1817 struct proc *p; 1818 register struct fchmod_args /* { 1819 syscallarg(int) fd; 1820 syscallarg(int) mode; 1821 } */ *uap; 1822{ 1823 struct vattr vattr; 1824 struct vnode *vp; 1825 struct file *fp; 1826 int error; 1827 1828 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1829 return (error); 1830 vp = (struct vnode *)fp->f_data; 1831 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1832 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1833 VATTR_NULL(&vattr); 1834 vattr.va_mode = SCARG(uap, mode) & ALLPERMS; 1835 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1836 VOP_UNLOCK(vp, 0, p); 1837 return (error); 1838} 1839 1840/* 1841 * Set ownership given a path name. 1842 */ 1843#ifndef _SYS_SYSPROTO_H_ 1844struct chown_args { 1845 char *path; 1846 int uid; 1847 int gid; 1848}; 1849#endif 1850/* ARGSUSED */ 1851int 1852chown(p, uap) 1853 struct proc *p; 1854 register struct chown_args /* { 1855 syscallarg(char *) path; 1856 syscallarg(int) uid; 1857 syscallarg(int) gid; 1858 } */ *uap; 1859{ 1860 register struct vnode *vp; 1861 struct vattr vattr; 1862 int error; 1863 struct nameidata nd; 1864 1865 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1866 if (error = namei(&nd)) 1867 return (error); 1868 vp = nd.ni_vp; 1869 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1870 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1871 VATTR_NULL(&vattr); 1872 vattr.va_uid = SCARG(uap, uid); 1873 vattr.va_gid = SCARG(uap, gid); 1874 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1875 vput(vp); 1876 return (error); 1877} 1878 1879/* 1880 * Set ownership given a path name, do not cross symlinks. 1881 */ 1882#ifndef _SYS_SYSPROTO_H_ 1883struct lchown_args { 1884 char *path; 1885 int uid; 1886 int gid; 1887}; 1888#endif 1889/* ARGSUSED */ 1890int 1891lchown(p, uap) 1892 struct proc *p; 1893 register struct lchown_args /* { 1894 syscallarg(char *) path; 1895 syscallarg(int) uid; 1896 syscallarg(int) gid; 1897 } */ *uap; 1898{ 1899 register struct vnode *vp; 1900 struct vattr vattr; 1901 int error; 1902 struct nameidata nd; 1903 1904 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1905 if (error = namei(&nd)) 1906 return (error); 1907 vp = nd.ni_vp; 1908 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1909 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1910 VATTR_NULL(&vattr); 1911 vattr.va_uid = SCARG(uap, uid); 1912 vattr.va_gid = SCARG(uap, gid); 1913 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1914 vput(vp); 1915 return (error); 1916} 1917 1918/* 1919 * Set ownership given a file descriptor. 1920 */ 1921#ifndef _SYS_SYSPROTO_H_ 1922struct fchown_args { 1923 int fd; 1924 int uid; 1925 int gid; 1926}; 1927#endif 1928/* ARGSUSED */ 1929int 1930fchown(p, uap) 1931 struct proc *p; 1932 register struct fchown_args /* { 1933 syscallarg(int) fd; 1934 syscallarg(int) uid; 1935 syscallarg(int) gid; 1936 } */ *uap; 1937{ 1938 struct vattr vattr; 1939 struct vnode *vp; 1940 struct file *fp; 1941 int error; 1942 1943 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1944 return (error); 1945 vp = (struct vnode *)fp->f_data; 1946 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1947 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1948 VATTR_NULL(&vattr); 1949 vattr.va_uid = SCARG(uap, uid); 1950 vattr.va_gid = SCARG(uap, gid); 1951 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1952 VOP_UNLOCK(vp, 0, p); 1953 return (error); 1954} 1955 1956/* 1957 * Set the access and modification times of a file. 1958 */ 1959#ifndef _SYS_SYSPROTO_H_ 1960struct utimes_args { 1961 char *path; 1962 struct timeval *tptr; 1963}; 1964#endif 1965/* ARGSUSED */ 1966int 1967utimes(p, uap) 1968 struct proc *p; 1969 register struct utimes_args /* { 1970 syscallarg(char *) path; 1971 syscallarg(struct timeval *) tptr; 1972 } */ *uap; 1973{ 1974 register struct vnode *vp; 1975 struct timeval tv[2]; 1976 struct vattr vattr; 1977 int error; 1978 struct nameidata nd; 1979 1980 VATTR_NULL(&vattr); 1981 if (SCARG(uap, tptr) == NULL) { 1982 microtime(&tv[0]); 1983 tv[1] = tv[0]; 1984 vattr.va_vaflags |= VA_UTIMES_NULL; 1985 } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv, 1986 sizeof (tv))) 1987 return (error); 1988 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1989 if (error = namei(&nd)) 1990 return (error); 1991 vp = nd.ni_vp; 1992 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1993 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1994 vattr.va_atime.tv_sec = tv[0].tv_sec; 1995 vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000; 1996 vattr.va_mtime.tv_sec = tv[1].tv_sec; 1997 vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000; 1998 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1999 vput(vp); 2000 return (error); 2001} 2002 2003/* 2004 * Truncate a file given its path name. 2005 */ 2006#ifndef _SYS_SYSPROTO_H_ 2007struct truncate_args { 2008 char *path; 2009 int pad; 2010 off_t length; 2011}; 2012#endif 2013/* ARGSUSED */ 2014int 2015truncate(p, uap) 2016 struct proc *p; 2017 register struct truncate_args /* { 2018 syscallarg(char *) path; 2019 syscallarg(int) pad; 2020 syscallarg(off_t) length; 2021 } */ *uap; 2022{ 2023 register struct vnode *vp; 2024 struct vattr vattr; 2025 int error; 2026 struct nameidata nd; 2027 2028 if (uap->length < 0) 2029 return(EINVAL); 2030 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2031 if (error = namei(&nd)) 2032 return (error); 2033 vp = nd.ni_vp; 2034 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2035 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2036 if (vp->v_type == VDIR) 2037 error = EISDIR; 2038 else if ((error = vn_writechk(vp)) == 0 && 2039 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) { 2040 VATTR_NULL(&vattr); 2041 vattr.va_size = SCARG(uap, length); 2042 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2043 } 2044 vput(vp); 2045 return (error); 2046} 2047 2048/* 2049 * Truncate a file given a file descriptor. 2050 */ 2051#ifndef _SYS_SYSPROTO_H_ 2052struct ftruncate_args { 2053 int fd; 2054 int pad; 2055 off_t length; 2056}; 2057#endif 2058/* ARGSUSED */ 2059int 2060ftruncate(p, uap) 2061 struct proc *p; 2062 register struct ftruncate_args /* { 2063 syscallarg(int) fd; 2064 syscallarg(int) pad; 2065 syscallarg(off_t) length; 2066 } */ *uap; 2067{ 2068 struct vattr vattr; 2069 struct vnode *vp; 2070 struct file *fp; 2071 int error; 2072 2073 if (uap->length < 0) 2074 return(EINVAL); 2075 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2076 return (error); 2077 if ((fp->f_flag & FWRITE) == 0) 2078 return (EINVAL); 2079 vp = (struct vnode *)fp->f_data; 2080 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2081 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2082 if (vp->v_type == VDIR) 2083 error = EISDIR; 2084 else if ((error = vn_writechk(vp)) == 0) { 2085 VATTR_NULL(&vattr); 2086 vattr.va_size = SCARG(uap, length); 2087 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 2088 } 2089 VOP_UNLOCK(vp, 0, p); 2090 return (error); 2091} 2092 2093#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2094/* 2095 * Truncate a file given its path name. 2096 */ 2097#ifndef _SYS_SYSPROTO_H_ 2098struct otruncate_args { 2099 char *path; 2100 long length; 2101}; 2102#endif 2103/* ARGSUSED */ 2104int 2105otruncate(p, uap) 2106 struct proc *p; 2107 register struct otruncate_args /* { 2108 syscallarg(char *) path; 2109 syscallarg(long) length; 2110 } */ *uap; 2111{ 2112 struct truncate_args /* { 2113 syscallarg(char *) path; 2114 syscallarg(int) pad; 2115 syscallarg(off_t) length; 2116 } */ nuap; 2117 2118 SCARG(&nuap, path) = SCARG(uap, path); 2119 SCARG(&nuap, length) = SCARG(uap, length); 2120 return (truncate(p, &nuap)); 2121} 2122 2123/* 2124 * Truncate a file given a file descriptor. 2125 */ 2126#ifndef _SYS_SYSPROTO_H_ 2127struct oftruncate_args { 2128 int fd; 2129 long length; 2130}; 2131#endif 2132/* ARGSUSED */ 2133int 2134oftruncate(p, uap) 2135 struct proc *p; 2136 register struct oftruncate_args /* { 2137 syscallarg(int) fd; 2138 syscallarg(long) length; 2139 } */ *uap; 2140{ 2141 struct ftruncate_args /* { 2142 syscallarg(int) fd; 2143 syscallarg(int) pad; 2144 syscallarg(off_t) length; 2145 } */ nuap; 2146 2147 SCARG(&nuap, fd) = SCARG(uap, fd); 2148 SCARG(&nuap, length) = SCARG(uap, length); 2149 return (ftruncate(p, &nuap)); 2150} 2151#endif /* COMPAT_43 || COMPAT_SUNOS */ 2152 2153/* 2154 * Sync an open file. 2155 */ 2156#ifndef _SYS_SYSPROTO_H_ 2157struct fsync_args { 2158 int fd; 2159}; 2160#endif 2161/* ARGSUSED */ 2162int 2163fsync(p, uap) 2164 struct proc *p; 2165 struct fsync_args /* { 2166 syscallarg(int) fd; 2167 } */ *uap; 2168{ 2169 register struct vnode *vp; 2170 struct file *fp; 2171 int error; 2172 2173 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2174 return (error); 2175 vp = (struct vnode *)fp->f_data; 2176 if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p)) == NULL) { 2177 if (vp->v_object) { 2178 vm_object_page_clean(vp->v_object, 0, 0, FALSE); 2179 } 2180 if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP)) { 2181 error = VOP_FSYNC(vp, fp->f_cred, MNT_LAZY, p); 2182 } else { 2183 error = VOP_FSYNC(vp, fp->f_cred, 2184 (vp->v_mount && (vp->v_mount->mnt_flag & MNT_ASYNC)) ? 2185 MNT_NOWAIT : MNT_WAIT, p); 2186 } 2187 VOP_UNLOCK(vp, 0, p); 2188 2189 if ((vp->v_mount->mnt_flag & MNT_SOFTDEP) && bioops.io_sync) 2190 (*bioops.io_sync)(NULL); 2191 } 2192 return (error); 2193} 2194 2195/* 2196 * Rename files. Source and destination must either both be directories, 2197 * or both not be directories. If target is a directory, it must be empty. 2198 */ 2199#ifndef _SYS_SYSPROTO_H_ 2200struct rename_args { 2201 char *from; 2202 char *to; 2203}; 2204#endif 2205/* ARGSUSED */ 2206int 2207rename(p, uap) 2208 struct proc *p; 2209 register struct rename_args /* { 2210 syscallarg(char *) from; 2211 syscallarg(char *) to; 2212 } */ *uap; 2213{ 2214 register struct vnode *tvp, *fvp, *tdvp; 2215 struct nameidata fromnd, tond; 2216 int error; 2217 2218 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 2219 SCARG(uap, from), p); 2220 if (error = namei(&fromnd)) 2221 return (error); 2222 fvp = fromnd.ni_vp; 2223 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ, 2224 UIO_USERSPACE, SCARG(uap, to), p); 2225 if (fromnd.ni_vp->v_type == VDIR) 2226 tond.ni_cnd.cn_flags |= WILLBEDIR; 2227 if (error = namei(&tond)) { 2228 /* Translate error code for rename("dir1", "dir2/."). */ 2229 if (error == EISDIR && fvp->v_type == VDIR) 2230 error = EINVAL; 2231 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 2232 vrele(fromnd.ni_dvp); 2233 vrele(fvp); 2234 goto out1; 2235 } 2236 tdvp = tond.ni_dvp; 2237 tvp = tond.ni_vp; 2238 if (tvp != NULL) { 2239 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 2240 error = ENOTDIR; 2241 goto out; 2242 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 2243 error = EISDIR; 2244 goto out; 2245 } 2246 } 2247 if (fvp == tdvp) 2248 error = EINVAL; 2249 /* 2250 * If source is the same as the destination (that is the 2251 * same inode number with the same name in the same directory), 2252 * then there is nothing to do. 2253 */ 2254 if (fvp == tvp && fromnd.ni_dvp == tdvp && 2255 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 2256 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 2257 fromnd.ni_cnd.cn_namelen)) 2258 error = -1; 2259out: 2260 if (!error) { 2261 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE); 2262 if (fromnd.ni_dvp != tdvp) { 2263 VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2264 } 2265 if (tvp) { 2266 VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE); 2267 } 2268 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 2269 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 2270 } else { 2271 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 2272 if (tdvp == tvp) 2273 vrele(tdvp); 2274 else 2275 vput(tdvp); 2276 if (tvp) 2277 vput(tvp); 2278 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 2279 vrele(fromnd.ni_dvp); 2280 vrele(fvp); 2281 } 2282 vrele(tond.ni_startdir); 2283 ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename"); 2284 ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename"); 2285 ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename"); 2286 ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename"); 2287 zfree(namei_zone, tond.ni_cnd.cn_pnbuf); 2288out1: 2289 if (fromnd.ni_startdir) 2290 vrele(fromnd.ni_startdir); 2291 zfree(namei_zone, fromnd.ni_cnd.cn_pnbuf); 2292 if (error == -1) 2293 return (0); 2294 return (error); 2295} 2296 2297/* 2298 * Make a directory file. 2299 */ 2300#ifndef _SYS_SYSPROTO_H_ 2301struct mkdir_args { 2302 char *path; 2303 int mode; 2304}; 2305#endif 2306/* ARGSUSED */ 2307int 2308mkdir(p, uap) 2309 struct proc *p; 2310 register struct mkdir_args /* { 2311 syscallarg(char *) path; 2312 syscallarg(int) mode; 2313 } */ *uap; 2314{ 2315 register struct vnode *vp; 2316 struct vattr vattr; 2317 int error; 2318 struct nameidata nd; 2319 2320 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 2321 nd.ni_cnd.cn_flags |= WILLBEDIR; 2322 if (error = namei(&nd)) 2323 return (error); 2324 vp = nd.ni_vp; 2325 if (vp != NULL) { 2326 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2327 if (nd.ni_dvp == vp) 2328 vrele(nd.ni_dvp); 2329 else 2330 vput(nd.ni_dvp); 2331 vrele(vp); 2332 return (EEXIST); 2333 } 2334 VATTR_NULL(&vattr); 2335 vattr.va_type = VDIR; 2336 vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask; 2337 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2338 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 2339 if (!error) 2340 vput(nd.ni_vp); 2341 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir"); 2342 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir"); 2343 return (error); 2344} 2345 2346/* 2347 * Remove a directory file. 2348 */ 2349#ifndef _SYS_SYSPROTO_H_ 2350struct rmdir_args { 2351 char *path; 2352}; 2353#endif 2354/* ARGSUSED */ 2355int 2356rmdir(p, uap) 2357 struct proc *p; 2358 struct rmdir_args /* { 2359 syscallarg(char *) path; 2360 } */ *uap; 2361{ 2362 register struct vnode *vp; 2363 int error; 2364 struct nameidata nd; 2365 2366 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 2367 SCARG(uap, path), p); 2368 if (error = namei(&nd)) 2369 return (error); 2370 vp = nd.ni_vp; 2371 if (vp->v_type != VDIR) { 2372 error = ENOTDIR; 2373 goto out; 2374 } 2375 /* 2376 * No rmdir "." please. 2377 */ 2378 if (nd.ni_dvp == vp) { 2379 error = EINVAL; 2380 goto out; 2381 } 2382 /* 2383 * The root of a mounted filesystem cannot be deleted. 2384 */ 2385 if (vp->v_flag & VROOT) 2386 error = EBUSY; 2387out: 2388 if (!error) { 2389 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2390 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2391 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 2392 } else { 2393 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2394 if (nd.ni_dvp == vp) 2395 vrele(nd.ni_dvp); 2396 else 2397 vput(nd.ni_dvp); 2398 vput(vp); 2399 } 2400 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir"); 2401 ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir"); 2402 return (error); 2403} 2404 2405#ifdef COMPAT_43 2406/* 2407 * Read a block of directory entries in a file system independent format. 2408 */ 2409#ifndef _SYS_SYSPROTO_H_ 2410struct ogetdirentries_args { 2411 int fd; 2412 char *buf; 2413 u_int count; 2414 long *basep; 2415}; 2416#endif 2417int 2418ogetdirentries(p, uap) 2419 struct proc *p; 2420 register struct ogetdirentries_args /* { 2421 syscallarg(int) fd; 2422 syscallarg(char *) buf; 2423 syscallarg(u_int) count; 2424 syscallarg(long *) basep; 2425 } */ *uap; 2426{ 2427 register struct vnode *vp; 2428 struct file *fp; 2429 struct uio auio, kuio; 2430 struct iovec aiov, kiov; 2431 struct dirent *dp, *edp; 2432 caddr_t dirbuf; 2433 int error, eofflag, readcnt; 2434 long loff; 2435 2436 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2437 return (error); 2438 if ((fp->f_flag & FREAD) == 0) 2439 return (EBADF); 2440 vp = (struct vnode *)fp->f_data; 2441unionread: 2442 if (vp->v_type != VDIR) 2443 return (EINVAL); 2444 aiov.iov_base = SCARG(uap, buf); 2445 aiov.iov_len = SCARG(uap, count); 2446 auio.uio_iov = &aiov; 2447 auio.uio_iovcnt = 1; 2448 auio.uio_rw = UIO_READ; 2449 auio.uio_segflg = UIO_USERSPACE; 2450 auio.uio_procp = p; 2451 auio.uio_resid = SCARG(uap, count); 2452 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2453 loff = auio.uio_offset = fp->f_offset; 2454# if (BYTE_ORDER != LITTLE_ENDIAN) 2455 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 2456 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 2457 NULL, NULL); 2458 fp->f_offset = auio.uio_offset; 2459 } else 2460# endif 2461 { 2462 kuio = auio; 2463 kuio.uio_iov = &kiov; 2464 kuio.uio_segflg = UIO_SYSSPACE; 2465 kiov.iov_len = SCARG(uap, count); 2466 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK); 2467 kiov.iov_base = dirbuf; 2468 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, 2469 NULL, NULL); 2470 fp->f_offset = kuio.uio_offset; 2471 if (error == 0) { 2472 readcnt = SCARG(uap, count) - kuio.uio_resid; 2473 edp = (struct dirent *)&dirbuf[readcnt]; 2474 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 2475# if (BYTE_ORDER == LITTLE_ENDIAN) 2476 /* 2477 * The expected low byte of 2478 * dp->d_namlen is our dp->d_type. 2479 * The high MBZ byte of dp->d_namlen 2480 * is our dp->d_namlen. 2481 */ 2482 dp->d_type = dp->d_namlen; 2483 dp->d_namlen = 0; 2484# else 2485 /* 2486 * The dp->d_type is the high byte 2487 * of the expected dp->d_namlen, 2488 * so must be zero'ed. 2489 */ 2490 dp->d_type = 0; 2491# endif 2492 if (dp->d_reclen > 0) { 2493 dp = (struct dirent *) 2494 ((char *)dp + dp->d_reclen); 2495 } else { 2496 error = EIO; 2497 break; 2498 } 2499 } 2500 if (dp >= edp) 2501 error = uiomove(dirbuf, readcnt, &auio); 2502 } 2503 FREE(dirbuf, M_TEMP); 2504 } 2505 VOP_UNLOCK(vp, 0, p); 2506 if (error) 2507 return (error); 2508 2509#ifdef UNION 2510{ 2511 if ((SCARG(uap, count) == auio.uio_resid) && 2512 (vp->v_op == union_vnodeop_p)) { 2513 struct vnode *lvp; 2514 2515 lvp = union_dircache(vp, p); 2516 if (lvp != NULLVP) { 2517 struct vattr va; 2518 2519 /* 2520 * If the directory is opaque, 2521 * then don't show lower entries 2522 */ 2523 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2524 if (va.va_flags & OPAQUE) { 2525 vput(lvp); 2526 lvp = NULL; 2527 } 2528 } 2529 2530 if (lvp != NULLVP) { 2531 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2532 if (error) { 2533 vput(lvp); 2534 return (error); 2535 } 2536 VOP_UNLOCK(lvp, 0, p); 2537 fp->f_data = (caddr_t) lvp; 2538 fp->f_offset = 0; 2539 error = vn_close(vp, FREAD, fp->f_cred, p); 2540 if (error) 2541 return (error); 2542 vp = lvp; 2543 goto unionread; 2544 } 2545 } 2546} 2547#endif /* UNION */ 2548 2549 if ((SCARG(uap, count) == auio.uio_resid) && 2550 (vp->v_flag & VROOT) && 2551 (vp->v_mount->mnt_flag & MNT_UNION)) { 2552 struct vnode *tvp = vp; 2553 vp = vp->v_mount->mnt_vnodecovered; 2554 VREF(vp); 2555 fp->f_data = (caddr_t) vp; 2556 fp->f_offset = 0; 2557 vrele(tvp); 2558 goto unionread; 2559 } 2560 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2561 sizeof(long)); 2562 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid; 2563 return (error); 2564} 2565#endif /* COMPAT_43 */ 2566 2567/* 2568 * Read a block of directory entries in a file system independent format. 2569 */ 2570#ifndef _SYS_SYSPROTO_H_ 2571struct getdirentries_args { 2572 int fd; 2573 char *buf; 2574 u_int count; 2575 long *basep; 2576}; 2577#endif 2578int 2579getdirentries(p, uap) 2580 struct proc *p; 2581 register struct getdirentries_args /* { 2582 syscallarg(int) fd; 2583 syscallarg(char *) buf; 2584 syscallarg(u_int) count; 2585 syscallarg(long *) basep; 2586 } */ *uap; 2587{ 2588 register struct vnode *vp; 2589 struct file *fp; 2590 struct uio auio; 2591 struct iovec aiov; 2592 long loff; 2593 int error, eofflag; 2594 2595 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2596 return (error); 2597 if ((fp->f_flag & FREAD) == 0) 2598 return (EBADF); 2599 vp = (struct vnode *)fp->f_data; 2600unionread: 2601 if (vp->v_type != VDIR) 2602 return (EINVAL); 2603 aiov.iov_base = SCARG(uap, buf); 2604 aiov.iov_len = SCARG(uap, count); 2605 auio.uio_iov = &aiov; 2606 auio.uio_iovcnt = 1; 2607 auio.uio_rw = UIO_READ; 2608 auio.uio_segflg = UIO_USERSPACE; 2609 auio.uio_procp = p; 2610 auio.uio_resid = SCARG(uap, count); 2611 /* vn_lock(vp, LK_SHARED | LK_RETRY, p); */ 2612 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2613 loff = auio.uio_offset = fp->f_offset; 2614 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL); 2615 fp->f_offset = auio.uio_offset; 2616 VOP_UNLOCK(vp, 0, p); 2617 if (error) 2618 return (error); 2619 2620#ifdef UNION 2621{ 2622 if ((SCARG(uap, count) == auio.uio_resid) && 2623 (vp->v_op == union_vnodeop_p)) { 2624 struct vnode *lvp; 2625 2626 lvp = union_dircache(vp, p); 2627 if (lvp != NULLVP) { 2628 struct vattr va; 2629 2630 /* 2631 * If the directory is opaque, 2632 * then don't show lower entries 2633 */ 2634 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2635 if (va.va_flags & OPAQUE) { 2636 vput(lvp); 2637 lvp = NULL; 2638 } 2639 } 2640 2641 if (lvp != NULLVP) { 2642 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2643 if (error) { 2644 vput(lvp); 2645 return (error); 2646 } 2647 VOP_UNLOCK(lvp, 0, p); 2648 fp->f_data = (caddr_t) lvp; 2649 fp->f_offset = 0; 2650 error = vn_close(vp, FREAD, fp->f_cred, p); 2651 if (error) 2652 return (error); 2653 vp = lvp; 2654 goto unionread; 2655 } 2656 } 2657} 2658#endif /* UNION */ 2659 2660 if ((SCARG(uap, count) == auio.uio_resid) && 2661 (vp->v_flag & VROOT) && 2662 (vp->v_mount->mnt_flag & MNT_UNION)) { 2663 struct vnode *tvp = vp; 2664 vp = vp->v_mount->mnt_vnodecovered; 2665 VREF(vp); 2666 fp->f_data = (caddr_t) vp; 2667 fp->f_offset = 0; 2668 vrele(tvp); 2669 goto unionread; 2670 } 2671 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2672 sizeof(long)); 2673 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid; 2674 return (error); 2675} 2676 2677/* 2678 * Set the mode mask for creation of filesystem nodes. 2679 */ 2680#ifndef _SYS_SYSPROTO_H_ 2681struct umask_args { 2682 int newmask; 2683}; 2684#endif 2685int 2686umask(p, uap) 2687 struct proc *p; 2688 struct umask_args /* { 2689 syscallarg(int) newmask; 2690 } */ *uap; 2691{ 2692 register struct filedesc *fdp; 2693 2694 fdp = p->p_fd; 2695 p->p_retval[0] = fdp->fd_cmask; 2696 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS; 2697 return (0); 2698} 2699 2700/* 2701 * Void all references to file by ripping underlying filesystem 2702 * away from vnode. 2703 */ 2704#ifndef _SYS_SYSPROTO_H_ 2705struct revoke_args { 2706 char *path; 2707}; 2708#endif 2709/* ARGSUSED */ 2710int 2711revoke(p, uap) 2712 struct proc *p; 2713 register struct revoke_args /* { 2714 syscallarg(char *) path; 2715 } */ *uap; 2716{ 2717 register struct vnode *vp; 2718 struct vattr vattr; 2719 int error; 2720 struct nameidata nd; 2721 2722 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2723 if (error = namei(&nd)) 2724 return (error); 2725 vp = nd.ni_vp; 2726 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 2727 goto out; 2728 if (p->p_ucred->cr_uid != vattr.va_uid && 2729 (error = suser(p->p_ucred, &p->p_acflag))) 2730 goto out; 2731 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 2732 VOP_REVOKE(vp, REVOKEALL); 2733out: 2734 vrele(vp); 2735 return (error); 2736} 2737 2738/* 2739 * Convert a user file descriptor to a kernel file entry. 2740 */ 2741int 2742getvnode(fdp, fd, fpp) 2743 struct filedesc *fdp; 2744 int fd; 2745 struct file **fpp; 2746{ 2747 struct file *fp; 2748 2749 if ((u_int)fd >= fdp->fd_nfiles || 2750 (fp = fdp->fd_ofiles[fd]) == NULL) 2751 return (EBADF); 2752 if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) 2753 return (EINVAL); 2754 *fpp = fp; 2755 return (0); 2756} 2757#ifndef _SYS_SYSPROTO_H_ 2758struct __getcwd_args { 2759 u_char *buf; 2760 u_int buflen; 2761}; 2762#endif 2763#define STATNODE(mode, name, var) \ 2764 SYSCTL_INT(_vfs_cache, OID_AUTO, name, mode, var, 0, ""); 2765 2766static int disablecwd; 2767SYSCTL_INT(_debug, OID_AUTO, disablecwd, CTLFLAG_RW, &disablecwd, 0, ""); 2768 2769static u_long numcwdcalls; STATNODE(CTLFLAG_RD, numcwdcalls, &numcwdcalls); 2770static u_long numcwdfail1; STATNODE(CTLFLAG_RD, numcwdfail1, &numcwdfail1); 2771static u_long numcwdfail2; STATNODE(CTLFLAG_RD, numcwdfail2, &numcwdfail2); 2772static u_long numcwdfail3; STATNODE(CTLFLAG_RD, numcwdfail3, &numcwdfail3); 2773static u_long numcwdfail4; STATNODE(CTLFLAG_RD, numcwdfail4, &numcwdfail4); 2774static u_long numcwdfound; STATNODE(CTLFLAG_RD, numcwdfound, &numcwdfound); 2775int 2776__getcwd(p, uap) 2777 struct proc *p; 2778 struct __getcwd_args *uap; 2779{ 2780 char *bp, *buf; 2781 int error, i, slash_prefixed; 2782 struct filedesc *fdp; 2783 struct namecache *ncp; 2784 struct vnode *vp; 2785 2786 numcwdcalls++; 2787 if (disablecwd) 2788 return (ENODEV); 2789 if (uap->buflen < 2) 2790 return (EINVAL); 2791 if (uap->buflen > MAXPATHLEN) 2792 uap->buflen = MAXPATHLEN; 2793 buf = bp = malloc(uap->buflen, M_TEMP, M_WAITOK); 2794 bp += uap->buflen - 1; 2795 *bp = '\0'; 2796 fdp = p->p_fd; 2797 slash_prefixed = 0; 2798 for (vp = fdp->fd_cdir; vp != fdp->fd_rdir && vp != rootvnode;) { 2799 if (vp->v_flag & VROOT) { 2800 vp = vp->v_mount->mnt_vnodecovered; 2801 continue; 2802 } 2803 if (vp->v_dd->v_id != vp->v_ddid) { 2804 numcwdfail1++; 2805 free(buf, M_TEMP); 2806 return (ENOTDIR); 2807 } 2808 ncp = TAILQ_FIRST(&vp->v_cache_dst); 2809 if (!ncp) { 2810 numcwdfail2++; 2811 free(buf, M_TEMP); 2812 return (ENOENT); 2813 } 2814 if (ncp->nc_dvp != vp->v_dd) { 2815 numcwdfail3++; 2816 free(buf, M_TEMP); 2817 return (EBADF); 2818 } 2819 for (i = ncp->nc_nlen - 1; i >= 0; i--) { 2820 if (bp == buf) { 2821 numcwdfail4++; 2822 free(buf, M_TEMP); 2823 return (ENOMEM); 2824 } 2825 *--bp = ncp->nc_name[i]; 2826 } 2827 if (bp == buf) { 2828 numcwdfail4++; 2829 free(buf, M_TEMP); 2830 return (ENOMEM); 2831 } 2832 *--bp = '/'; 2833 slash_prefixed = 1; 2834 vp = vp->v_dd; 2835 } 2836 if (!slash_prefixed) { 2837 if (bp == buf) { 2838 numcwdfail4++; 2839 free(buf, M_TEMP); 2840 return (ENOMEM); 2841 } 2842 *--bp = '/'; 2843 } 2844 numcwdfound++; 2845 error = copyout(bp, uap->buf, strlen(bp) + 1); 2846 free(buf, M_TEMP); 2847 return (error); 2848}
| 1609 vput(vp); 1610 if (error) 1611 return (error); 1612 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 1613 return (error); 1614} 1615 1616/* 1617 * Get configurable pathname variables. 1618 */ 1619#ifndef _SYS_SYSPROTO_H_ 1620struct pathconf_args { 1621 char *path; 1622 int name; 1623}; 1624#endif 1625/* ARGSUSED */ 1626int 1627pathconf(p, uap) 1628 struct proc *p; 1629 register struct pathconf_args /* { 1630 syscallarg(char *) path; 1631 syscallarg(int) name; 1632 } */ *uap; 1633{ 1634 int error; 1635 struct nameidata nd; 1636 1637 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1638 SCARG(uap, path), p); 1639 if (error = namei(&nd)) 1640 return (error); 1641 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), p->p_retval); 1642 vput(nd.ni_vp); 1643 return (error); 1644} 1645 1646/* 1647 * Return target name of a symbolic link. 1648 */ 1649#ifndef _SYS_SYSPROTO_H_ 1650struct readlink_args { 1651 char *path; 1652 char *buf; 1653 int count; 1654}; 1655#endif 1656/* ARGSUSED */ 1657int 1658readlink(p, uap) 1659 struct proc *p; 1660 register struct readlink_args /* { 1661 syscallarg(char *) path; 1662 syscallarg(char *) buf; 1663 syscallarg(int) count; 1664 } */ *uap; 1665{ 1666 register struct vnode *vp; 1667 struct iovec aiov; 1668 struct uio auio; 1669 int error; 1670 struct nameidata nd; 1671 1672 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1673 SCARG(uap, path), p); 1674 if (error = namei(&nd)) 1675 return (error); 1676 vp = nd.ni_vp; 1677 if (vp->v_type != VLNK) 1678 error = EINVAL; 1679 else { 1680 aiov.iov_base = SCARG(uap, buf); 1681 aiov.iov_len = SCARG(uap, count); 1682 auio.uio_iov = &aiov; 1683 auio.uio_iovcnt = 1; 1684 auio.uio_offset = 0; 1685 auio.uio_rw = UIO_READ; 1686 auio.uio_segflg = UIO_USERSPACE; 1687 auio.uio_procp = p; 1688 auio.uio_resid = SCARG(uap, count); 1689 error = VOP_READLINK(vp, &auio, p->p_ucred); 1690 } 1691 vput(vp); 1692 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid; 1693 return (error); 1694} 1695 1696/* 1697 * Change flags of a file given a path name. 1698 */ 1699#ifndef _SYS_SYSPROTO_H_ 1700struct chflags_args { 1701 char *path; 1702 int flags; 1703}; 1704#endif 1705/* ARGSUSED */ 1706int 1707chflags(p, uap) 1708 struct proc *p; 1709 register struct chflags_args /* { 1710 syscallarg(char *) path; 1711 syscallarg(int) flags; 1712 } */ *uap; 1713{ 1714 register struct vnode *vp; 1715 struct vattr vattr; 1716 int error; 1717 struct nameidata nd; 1718 1719 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1720 if (error = namei(&nd)) 1721 return (error); 1722 vp = nd.ni_vp; 1723 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1724 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1725 VATTR_NULL(&vattr); 1726 vattr.va_flags = SCARG(uap, flags); 1727 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1728 vput(vp); 1729 return (error); 1730} 1731 1732/* 1733 * Change flags of a file given a file descriptor. 1734 */ 1735#ifndef _SYS_SYSPROTO_H_ 1736struct fchflags_args { 1737 int fd; 1738 int flags; 1739}; 1740#endif 1741/* ARGSUSED */ 1742int 1743fchflags(p, uap) 1744 struct proc *p; 1745 register struct fchflags_args /* { 1746 syscallarg(int) fd; 1747 syscallarg(int) flags; 1748 } */ *uap; 1749{ 1750 struct vattr vattr; 1751 struct vnode *vp; 1752 struct file *fp; 1753 int error; 1754 1755 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1756 return (error); 1757 vp = (struct vnode *)fp->f_data; 1758 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1759 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1760 VATTR_NULL(&vattr); 1761 vattr.va_flags = SCARG(uap, flags); 1762 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1763 VOP_UNLOCK(vp, 0, p); 1764 return (error); 1765} 1766 1767/* 1768 * Change mode of a file given path name. 1769 */ 1770#ifndef _SYS_SYSPROTO_H_ 1771struct chmod_args { 1772 char *path; 1773 int mode; 1774}; 1775#endif 1776/* ARGSUSED */ 1777int 1778chmod(p, uap) 1779 struct proc *p; 1780 register struct chmod_args /* { 1781 syscallarg(char *) path; 1782 syscallarg(int) mode; 1783 } */ *uap; 1784{ 1785 register struct vnode *vp; 1786 struct vattr vattr; 1787 int error; 1788 struct nameidata nd; 1789 1790 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1791 if (error = namei(&nd)) 1792 return (error); 1793 vp = nd.ni_vp; 1794 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1795 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1796 VATTR_NULL(&vattr); 1797 vattr.va_mode = SCARG(uap, mode) & ALLPERMS; 1798 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1799 vput(vp); 1800 return (error); 1801} 1802 1803/* 1804 * Change mode of a file given a file descriptor. 1805 */ 1806#ifndef _SYS_SYSPROTO_H_ 1807struct fchmod_args { 1808 int fd; 1809 int mode; 1810}; 1811#endif 1812/* ARGSUSED */ 1813int 1814fchmod(p, uap) 1815 struct proc *p; 1816 register struct fchmod_args /* { 1817 syscallarg(int) fd; 1818 syscallarg(int) mode; 1819 } */ *uap; 1820{ 1821 struct vattr vattr; 1822 struct vnode *vp; 1823 struct file *fp; 1824 int error; 1825 1826 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1827 return (error); 1828 vp = (struct vnode *)fp->f_data; 1829 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1830 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1831 VATTR_NULL(&vattr); 1832 vattr.va_mode = SCARG(uap, mode) & ALLPERMS; 1833 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1834 VOP_UNLOCK(vp, 0, p); 1835 return (error); 1836} 1837 1838/* 1839 * Set ownership given a path name. 1840 */ 1841#ifndef _SYS_SYSPROTO_H_ 1842struct chown_args { 1843 char *path; 1844 int uid; 1845 int gid; 1846}; 1847#endif 1848/* ARGSUSED */ 1849int 1850chown(p, uap) 1851 struct proc *p; 1852 register struct chown_args /* { 1853 syscallarg(char *) path; 1854 syscallarg(int) uid; 1855 syscallarg(int) gid; 1856 } */ *uap; 1857{ 1858 register struct vnode *vp; 1859 struct vattr vattr; 1860 int error; 1861 struct nameidata nd; 1862 1863 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1864 if (error = namei(&nd)) 1865 return (error); 1866 vp = nd.ni_vp; 1867 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1868 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1869 VATTR_NULL(&vattr); 1870 vattr.va_uid = SCARG(uap, uid); 1871 vattr.va_gid = SCARG(uap, gid); 1872 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1873 vput(vp); 1874 return (error); 1875} 1876 1877/* 1878 * Set ownership given a path name, do not cross symlinks. 1879 */ 1880#ifndef _SYS_SYSPROTO_H_ 1881struct lchown_args { 1882 char *path; 1883 int uid; 1884 int gid; 1885}; 1886#endif 1887/* ARGSUSED */ 1888int 1889lchown(p, uap) 1890 struct proc *p; 1891 register struct lchown_args /* { 1892 syscallarg(char *) path; 1893 syscallarg(int) uid; 1894 syscallarg(int) gid; 1895 } */ *uap; 1896{ 1897 register struct vnode *vp; 1898 struct vattr vattr; 1899 int error; 1900 struct nameidata nd; 1901 1902 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1903 if (error = namei(&nd)) 1904 return (error); 1905 vp = nd.ni_vp; 1906 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1907 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1908 VATTR_NULL(&vattr); 1909 vattr.va_uid = SCARG(uap, uid); 1910 vattr.va_gid = SCARG(uap, gid); 1911 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1912 vput(vp); 1913 return (error); 1914} 1915 1916/* 1917 * Set ownership given a file descriptor. 1918 */ 1919#ifndef _SYS_SYSPROTO_H_ 1920struct fchown_args { 1921 int fd; 1922 int uid; 1923 int gid; 1924}; 1925#endif 1926/* ARGSUSED */ 1927int 1928fchown(p, uap) 1929 struct proc *p; 1930 register struct fchown_args /* { 1931 syscallarg(int) fd; 1932 syscallarg(int) uid; 1933 syscallarg(int) gid; 1934 } */ *uap; 1935{ 1936 struct vattr vattr; 1937 struct vnode *vp; 1938 struct file *fp; 1939 int error; 1940 1941 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1942 return (error); 1943 vp = (struct vnode *)fp->f_data; 1944 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1945 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1946 VATTR_NULL(&vattr); 1947 vattr.va_uid = SCARG(uap, uid); 1948 vattr.va_gid = SCARG(uap, gid); 1949 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1950 VOP_UNLOCK(vp, 0, p); 1951 return (error); 1952} 1953 1954/* 1955 * Set the access and modification times of a file. 1956 */ 1957#ifndef _SYS_SYSPROTO_H_ 1958struct utimes_args { 1959 char *path; 1960 struct timeval *tptr; 1961}; 1962#endif 1963/* ARGSUSED */ 1964int 1965utimes(p, uap) 1966 struct proc *p; 1967 register struct utimes_args /* { 1968 syscallarg(char *) path; 1969 syscallarg(struct timeval *) tptr; 1970 } */ *uap; 1971{ 1972 register struct vnode *vp; 1973 struct timeval tv[2]; 1974 struct vattr vattr; 1975 int error; 1976 struct nameidata nd; 1977 1978 VATTR_NULL(&vattr); 1979 if (SCARG(uap, tptr) == NULL) { 1980 microtime(&tv[0]); 1981 tv[1] = tv[0]; 1982 vattr.va_vaflags |= VA_UTIMES_NULL; 1983 } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv, 1984 sizeof (tv))) 1985 return (error); 1986 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1987 if (error = namei(&nd)) 1988 return (error); 1989 vp = nd.ni_vp; 1990 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1991 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1992 vattr.va_atime.tv_sec = tv[0].tv_sec; 1993 vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000; 1994 vattr.va_mtime.tv_sec = tv[1].tv_sec; 1995 vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000; 1996 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1997 vput(vp); 1998 return (error); 1999} 2000 2001/* 2002 * Truncate a file given its path name. 2003 */ 2004#ifndef _SYS_SYSPROTO_H_ 2005struct truncate_args { 2006 char *path; 2007 int pad; 2008 off_t length; 2009}; 2010#endif 2011/* ARGSUSED */ 2012int 2013truncate(p, uap) 2014 struct proc *p; 2015 register struct truncate_args /* { 2016 syscallarg(char *) path; 2017 syscallarg(int) pad; 2018 syscallarg(off_t) length; 2019 } */ *uap; 2020{ 2021 register struct vnode *vp; 2022 struct vattr vattr; 2023 int error; 2024 struct nameidata nd; 2025 2026 if (uap->length < 0) 2027 return(EINVAL); 2028 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2029 if (error = namei(&nd)) 2030 return (error); 2031 vp = nd.ni_vp; 2032 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2033 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2034 if (vp->v_type == VDIR) 2035 error = EISDIR; 2036 else if ((error = vn_writechk(vp)) == 0 && 2037 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) { 2038 VATTR_NULL(&vattr); 2039 vattr.va_size = SCARG(uap, length); 2040 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2041 } 2042 vput(vp); 2043 return (error); 2044} 2045 2046/* 2047 * Truncate a file given a file descriptor. 2048 */ 2049#ifndef _SYS_SYSPROTO_H_ 2050struct ftruncate_args { 2051 int fd; 2052 int pad; 2053 off_t length; 2054}; 2055#endif 2056/* ARGSUSED */ 2057int 2058ftruncate(p, uap) 2059 struct proc *p; 2060 register struct ftruncate_args /* { 2061 syscallarg(int) fd; 2062 syscallarg(int) pad; 2063 syscallarg(off_t) length; 2064 } */ *uap; 2065{ 2066 struct vattr vattr; 2067 struct vnode *vp; 2068 struct file *fp; 2069 int error; 2070 2071 if (uap->length < 0) 2072 return(EINVAL); 2073 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2074 return (error); 2075 if ((fp->f_flag & FWRITE) == 0) 2076 return (EINVAL); 2077 vp = (struct vnode *)fp->f_data; 2078 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2079 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2080 if (vp->v_type == VDIR) 2081 error = EISDIR; 2082 else if ((error = vn_writechk(vp)) == 0) { 2083 VATTR_NULL(&vattr); 2084 vattr.va_size = SCARG(uap, length); 2085 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 2086 } 2087 VOP_UNLOCK(vp, 0, p); 2088 return (error); 2089} 2090 2091#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2092/* 2093 * Truncate a file given its path name. 2094 */ 2095#ifndef _SYS_SYSPROTO_H_ 2096struct otruncate_args { 2097 char *path; 2098 long length; 2099}; 2100#endif 2101/* ARGSUSED */ 2102int 2103otruncate(p, uap) 2104 struct proc *p; 2105 register struct otruncate_args /* { 2106 syscallarg(char *) path; 2107 syscallarg(long) length; 2108 } */ *uap; 2109{ 2110 struct truncate_args /* { 2111 syscallarg(char *) path; 2112 syscallarg(int) pad; 2113 syscallarg(off_t) length; 2114 } */ nuap; 2115 2116 SCARG(&nuap, path) = SCARG(uap, path); 2117 SCARG(&nuap, length) = SCARG(uap, length); 2118 return (truncate(p, &nuap)); 2119} 2120 2121/* 2122 * Truncate a file given a file descriptor. 2123 */ 2124#ifndef _SYS_SYSPROTO_H_ 2125struct oftruncate_args { 2126 int fd; 2127 long length; 2128}; 2129#endif 2130/* ARGSUSED */ 2131int 2132oftruncate(p, uap) 2133 struct proc *p; 2134 register struct oftruncate_args /* { 2135 syscallarg(int) fd; 2136 syscallarg(long) length; 2137 } */ *uap; 2138{ 2139 struct ftruncate_args /* { 2140 syscallarg(int) fd; 2141 syscallarg(int) pad; 2142 syscallarg(off_t) length; 2143 } */ nuap; 2144 2145 SCARG(&nuap, fd) = SCARG(uap, fd); 2146 SCARG(&nuap, length) = SCARG(uap, length); 2147 return (ftruncate(p, &nuap)); 2148} 2149#endif /* COMPAT_43 || COMPAT_SUNOS */ 2150 2151/* 2152 * Sync an open file. 2153 */ 2154#ifndef _SYS_SYSPROTO_H_ 2155struct fsync_args { 2156 int fd; 2157}; 2158#endif 2159/* ARGSUSED */ 2160int 2161fsync(p, uap) 2162 struct proc *p; 2163 struct fsync_args /* { 2164 syscallarg(int) fd; 2165 } */ *uap; 2166{ 2167 register struct vnode *vp; 2168 struct file *fp; 2169 int error; 2170 2171 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2172 return (error); 2173 vp = (struct vnode *)fp->f_data; 2174 if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p)) == NULL) { 2175 if (vp->v_object) { 2176 vm_object_page_clean(vp->v_object, 0, 0, FALSE); 2177 } 2178 if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP)) { 2179 error = VOP_FSYNC(vp, fp->f_cred, MNT_LAZY, p); 2180 } else { 2181 error = VOP_FSYNC(vp, fp->f_cred, 2182 (vp->v_mount && (vp->v_mount->mnt_flag & MNT_ASYNC)) ? 2183 MNT_NOWAIT : MNT_WAIT, p); 2184 } 2185 VOP_UNLOCK(vp, 0, p); 2186 2187 if ((vp->v_mount->mnt_flag & MNT_SOFTDEP) && bioops.io_sync) 2188 (*bioops.io_sync)(NULL); 2189 } 2190 return (error); 2191} 2192 2193/* 2194 * Rename files. Source and destination must either both be directories, 2195 * or both not be directories. If target is a directory, it must be empty. 2196 */ 2197#ifndef _SYS_SYSPROTO_H_ 2198struct rename_args { 2199 char *from; 2200 char *to; 2201}; 2202#endif 2203/* ARGSUSED */ 2204int 2205rename(p, uap) 2206 struct proc *p; 2207 register struct rename_args /* { 2208 syscallarg(char *) from; 2209 syscallarg(char *) to; 2210 } */ *uap; 2211{ 2212 register struct vnode *tvp, *fvp, *tdvp; 2213 struct nameidata fromnd, tond; 2214 int error; 2215 2216 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 2217 SCARG(uap, from), p); 2218 if (error = namei(&fromnd)) 2219 return (error); 2220 fvp = fromnd.ni_vp; 2221 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ, 2222 UIO_USERSPACE, SCARG(uap, to), p); 2223 if (fromnd.ni_vp->v_type == VDIR) 2224 tond.ni_cnd.cn_flags |= WILLBEDIR; 2225 if (error = namei(&tond)) { 2226 /* Translate error code for rename("dir1", "dir2/."). */ 2227 if (error == EISDIR && fvp->v_type == VDIR) 2228 error = EINVAL; 2229 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 2230 vrele(fromnd.ni_dvp); 2231 vrele(fvp); 2232 goto out1; 2233 } 2234 tdvp = tond.ni_dvp; 2235 tvp = tond.ni_vp; 2236 if (tvp != NULL) { 2237 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 2238 error = ENOTDIR; 2239 goto out; 2240 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 2241 error = EISDIR; 2242 goto out; 2243 } 2244 } 2245 if (fvp == tdvp) 2246 error = EINVAL; 2247 /* 2248 * If source is the same as the destination (that is the 2249 * same inode number with the same name in the same directory), 2250 * then there is nothing to do. 2251 */ 2252 if (fvp == tvp && fromnd.ni_dvp == tdvp && 2253 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 2254 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 2255 fromnd.ni_cnd.cn_namelen)) 2256 error = -1; 2257out: 2258 if (!error) { 2259 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE); 2260 if (fromnd.ni_dvp != tdvp) { 2261 VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2262 } 2263 if (tvp) { 2264 VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE); 2265 } 2266 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 2267 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 2268 } else { 2269 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 2270 if (tdvp == tvp) 2271 vrele(tdvp); 2272 else 2273 vput(tdvp); 2274 if (tvp) 2275 vput(tvp); 2276 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 2277 vrele(fromnd.ni_dvp); 2278 vrele(fvp); 2279 } 2280 vrele(tond.ni_startdir); 2281 ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename"); 2282 ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename"); 2283 ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename"); 2284 ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename"); 2285 zfree(namei_zone, tond.ni_cnd.cn_pnbuf); 2286out1: 2287 if (fromnd.ni_startdir) 2288 vrele(fromnd.ni_startdir); 2289 zfree(namei_zone, fromnd.ni_cnd.cn_pnbuf); 2290 if (error == -1) 2291 return (0); 2292 return (error); 2293} 2294 2295/* 2296 * Make a directory file. 2297 */ 2298#ifndef _SYS_SYSPROTO_H_ 2299struct mkdir_args { 2300 char *path; 2301 int mode; 2302}; 2303#endif 2304/* ARGSUSED */ 2305int 2306mkdir(p, uap) 2307 struct proc *p; 2308 register struct mkdir_args /* { 2309 syscallarg(char *) path; 2310 syscallarg(int) mode; 2311 } */ *uap; 2312{ 2313 register struct vnode *vp; 2314 struct vattr vattr; 2315 int error; 2316 struct nameidata nd; 2317 2318 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 2319 nd.ni_cnd.cn_flags |= WILLBEDIR; 2320 if (error = namei(&nd)) 2321 return (error); 2322 vp = nd.ni_vp; 2323 if (vp != NULL) { 2324 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2325 if (nd.ni_dvp == vp) 2326 vrele(nd.ni_dvp); 2327 else 2328 vput(nd.ni_dvp); 2329 vrele(vp); 2330 return (EEXIST); 2331 } 2332 VATTR_NULL(&vattr); 2333 vattr.va_type = VDIR; 2334 vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask; 2335 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2336 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 2337 if (!error) 2338 vput(nd.ni_vp); 2339 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir"); 2340 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir"); 2341 return (error); 2342} 2343 2344/* 2345 * Remove a directory file. 2346 */ 2347#ifndef _SYS_SYSPROTO_H_ 2348struct rmdir_args { 2349 char *path; 2350}; 2351#endif 2352/* ARGSUSED */ 2353int 2354rmdir(p, uap) 2355 struct proc *p; 2356 struct rmdir_args /* { 2357 syscallarg(char *) path; 2358 } */ *uap; 2359{ 2360 register struct vnode *vp; 2361 int error; 2362 struct nameidata nd; 2363 2364 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 2365 SCARG(uap, path), p); 2366 if (error = namei(&nd)) 2367 return (error); 2368 vp = nd.ni_vp; 2369 if (vp->v_type != VDIR) { 2370 error = ENOTDIR; 2371 goto out; 2372 } 2373 /* 2374 * No rmdir "." please. 2375 */ 2376 if (nd.ni_dvp == vp) { 2377 error = EINVAL; 2378 goto out; 2379 } 2380 /* 2381 * The root of a mounted filesystem cannot be deleted. 2382 */ 2383 if (vp->v_flag & VROOT) 2384 error = EBUSY; 2385out: 2386 if (!error) { 2387 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2388 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2389 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 2390 } else { 2391 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2392 if (nd.ni_dvp == vp) 2393 vrele(nd.ni_dvp); 2394 else 2395 vput(nd.ni_dvp); 2396 vput(vp); 2397 } 2398 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir"); 2399 ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir"); 2400 return (error); 2401} 2402 2403#ifdef COMPAT_43 2404/* 2405 * Read a block of directory entries in a file system independent format. 2406 */ 2407#ifndef _SYS_SYSPROTO_H_ 2408struct ogetdirentries_args { 2409 int fd; 2410 char *buf; 2411 u_int count; 2412 long *basep; 2413}; 2414#endif 2415int 2416ogetdirentries(p, uap) 2417 struct proc *p; 2418 register struct ogetdirentries_args /* { 2419 syscallarg(int) fd; 2420 syscallarg(char *) buf; 2421 syscallarg(u_int) count; 2422 syscallarg(long *) basep; 2423 } */ *uap; 2424{ 2425 register struct vnode *vp; 2426 struct file *fp; 2427 struct uio auio, kuio; 2428 struct iovec aiov, kiov; 2429 struct dirent *dp, *edp; 2430 caddr_t dirbuf; 2431 int error, eofflag, readcnt; 2432 long loff; 2433 2434 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2435 return (error); 2436 if ((fp->f_flag & FREAD) == 0) 2437 return (EBADF); 2438 vp = (struct vnode *)fp->f_data; 2439unionread: 2440 if (vp->v_type != VDIR) 2441 return (EINVAL); 2442 aiov.iov_base = SCARG(uap, buf); 2443 aiov.iov_len = SCARG(uap, count); 2444 auio.uio_iov = &aiov; 2445 auio.uio_iovcnt = 1; 2446 auio.uio_rw = UIO_READ; 2447 auio.uio_segflg = UIO_USERSPACE; 2448 auio.uio_procp = p; 2449 auio.uio_resid = SCARG(uap, count); 2450 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2451 loff = auio.uio_offset = fp->f_offset; 2452# if (BYTE_ORDER != LITTLE_ENDIAN) 2453 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 2454 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 2455 NULL, NULL); 2456 fp->f_offset = auio.uio_offset; 2457 } else 2458# endif 2459 { 2460 kuio = auio; 2461 kuio.uio_iov = &kiov; 2462 kuio.uio_segflg = UIO_SYSSPACE; 2463 kiov.iov_len = SCARG(uap, count); 2464 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK); 2465 kiov.iov_base = dirbuf; 2466 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, 2467 NULL, NULL); 2468 fp->f_offset = kuio.uio_offset; 2469 if (error == 0) { 2470 readcnt = SCARG(uap, count) - kuio.uio_resid; 2471 edp = (struct dirent *)&dirbuf[readcnt]; 2472 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 2473# if (BYTE_ORDER == LITTLE_ENDIAN) 2474 /* 2475 * The expected low byte of 2476 * dp->d_namlen is our dp->d_type. 2477 * The high MBZ byte of dp->d_namlen 2478 * is our dp->d_namlen. 2479 */ 2480 dp->d_type = dp->d_namlen; 2481 dp->d_namlen = 0; 2482# else 2483 /* 2484 * The dp->d_type is the high byte 2485 * of the expected dp->d_namlen, 2486 * so must be zero'ed. 2487 */ 2488 dp->d_type = 0; 2489# endif 2490 if (dp->d_reclen > 0) { 2491 dp = (struct dirent *) 2492 ((char *)dp + dp->d_reclen); 2493 } else { 2494 error = EIO; 2495 break; 2496 } 2497 } 2498 if (dp >= edp) 2499 error = uiomove(dirbuf, readcnt, &auio); 2500 } 2501 FREE(dirbuf, M_TEMP); 2502 } 2503 VOP_UNLOCK(vp, 0, p); 2504 if (error) 2505 return (error); 2506 2507#ifdef UNION 2508{ 2509 if ((SCARG(uap, count) == auio.uio_resid) && 2510 (vp->v_op == union_vnodeop_p)) { 2511 struct vnode *lvp; 2512 2513 lvp = union_dircache(vp, p); 2514 if (lvp != NULLVP) { 2515 struct vattr va; 2516 2517 /* 2518 * If the directory is opaque, 2519 * then don't show lower entries 2520 */ 2521 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2522 if (va.va_flags & OPAQUE) { 2523 vput(lvp); 2524 lvp = NULL; 2525 } 2526 } 2527 2528 if (lvp != NULLVP) { 2529 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2530 if (error) { 2531 vput(lvp); 2532 return (error); 2533 } 2534 VOP_UNLOCK(lvp, 0, p); 2535 fp->f_data = (caddr_t) lvp; 2536 fp->f_offset = 0; 2537 error = vn_close(vp, FREAD, fp->f_cred, p); 2538 if (error) 2539 return (error); 2540 vp = lvp; 2541 goto unionread; 2542 } 2543 } 2544} 2545#endif /* UNION */ 2546 2547 if ((SCARG(uap, count) == auio.uio_resid) && 2548 (vp->v_flag & VROOT) && 2549 (vp->v_mount->mnt_flag & MNT_UNION)) { 2550 struct vnode *tvp = vp; 2551 vp = vp->v_mount->mnt_vnodecovered; 2552 VREF(vp); 2553 fp->f_data = (caddr_t) vp; 2554 fp->f_offset = 0; 2555 vrele(tvp); 2556 goto unionread; 2557 } 2558 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2559 sizeof(long)); 2560 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid; 2561 return (error); 2562} 2563#endif /* COMPAT_43 */ 2564 2565/* 2566 * Read a block of directory entries in a file system independent format. 2567 */ 2568#ifndef _SYS_SYSPROTO_H_ 2569struct getdirentries_args { 2570 int fd; 2571 char *buf; 2572 u_int count; 2573 long *basep; 2574}; 2575#endif 2576int 2577getdirentries(p, uap) 2578 struct proc *p; 2579 register struct getdirentries_args /* { 2580 syscallarg(int) fd; 2581 syscallarg(char *) buf; 2582 syscallarg(u_int) count; 2583 syscallarg(long *) basep; 2584 } */ *uap; 2585{ 2586 register struct vnode *vp; 2587 struct file *fp; 2588 struct uio auio; 2589 struct iovec aiov; 2590 long loff; 2591 int error, eofflag; 2592 2593 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2594 return (error); 2595 if ((fp->f_flag & FREAD) == 0) 2596 return (EBADF); 2597 vp = (struct vnode *)fp->f_data; 2598unionread: 2599 if (vp->v_type != VDIR) 2600 return (EINVAL); 2601 aiov.iov_base = SCARG(uap, buf); 2602 aiov.iov_len = SCARG(uap, count); 2603 auio.uio_iov = &aiov; 2604 auio.uio_iovcnt = 1; 2605 auio.uio_rw = UIO_READ; 2606 auio.uio_segflg = UIO_USERSPACE; 2607 auio.uio_procp = p; 2608 auio.uio_resid = SCARG(uap, count); 2609 /* vn_lock(vp, LK_SHARED | LK_RETRY, p); */ 2610 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2611 loff = auio.uio_offset = fp->f_offset; 2612 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL); 2613 fp->f_offset = auio.uio_offset; 2614 VOP_UNLOCK(vp, 0, p); 2615 if (error) 2616 return (error); 2617 2618#ifdef UNION 2619{ 2620 if ((SCARG(uap, count) == auio.uio_resid) && 2621 (vp->v_op == union_vnodeop_p)) { 2622 struct vnode *lvp; 2623 2624 lvp = union_dircache(vp, p); 2625 if (lvp != NULLVP) { 2626 struct vattr va; 2627 2628 /* 2629 * If the directory is opaque, 2630 * then don't show lower entries 2631 */ 2632 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2633 if (va.va_flags & OPAQUE) { 2634 vput(lvp); 2635 lvp = NULL; 2636 } 2637 } 2638 2639 if (lvp != NULLVP) { 2640 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2641 if (error) { 2642 vput(lvp); 2643 return (error); 2644 } 2645 VOP_UNLOCK(lvp, 0, p); 2646 fp->f_data = (caddr_t) lvp; 2647 fp->f_offset = 0; 2648 error = vn_close(vp, FREAD, fp->f_cred, p); 2649 if (error) 2650 return (error); 2651 vp = lvp; 2652 goto unionread; 2653 } 2654 } 2655} 2656#endif /* UNION */ 2657 2658 if ((SCARG(uap, count) == auio.uio_resid) && 2659 (vp->v_flag & VROOT) && 2660 (vp->v_mount->mnt_flag & MNT_UNION)) { 2661 struct vnode *tvp = vp; 2662 vp = vp->v_mount->mnt_vnodecovered; 2663 VREF(vp); 2664 fp->f_data = (caddr_t) vp; 2665 fp->f_offset = 0; 2666 vrele(tvp); 2667 goto unionread; 2668 } 2669 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2670 sizeof(long)); 2671 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid; 2672 return (error); 2673} 2674 2675/* 2676 * Set the mode mask for creation of filesystem nodes. 2677 */ 2678#ifndef _SYS_SYSPROTO_H_ 2679struct umask_args { 2680 int newmask; 2681}; 2682#endif 2683int 2684umask(p, uap) 2685 struct proc *p; 2686 struct umask_args /* { 2687 syscallarg(int) newmask; 2688 } */ *uap; 2689{ 2690 register struct filedesc *fdp; 2691 2692 fdp = p->p_fd; 2693 p->p_retval[0] = fdp->fd_cmask; 2694 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS; 2695 return (0); 2696} 2697 2698/* 2699 * Void all references to file by ripping underlying filesystem 2700 * away from vnode. 2701 */ 2702#ifndef _SYS_SYSPROTO_H_ 2703struct revoke_args { 2704 char *path; 2705}; 2706#endif 2707/* ARGSUSED */ 2708int 2709revoke(p, uap) 2710 struct proc *p; 2711 register struct revoke_args /* { 2712 syscallarg(char *) path; 2713 } */ *uap; 2714{ 2715 register struct vnode *vp; 2716 struct vattr vattr; 2717 int error; 2718 struct nameidata nd; 2719 2720 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2721 if (error = namei(&nd)) 2722 return (error); 2723 vp = nd.ni_vp; 2724 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 2725 goto out; 2726 if (p->p_ucred->cr_uid != vattr.va_uid && 2727 (error = suser(p->p_ucred, &p->p_acflag))) 2728 goto out; 2729 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 2730 VOP_REVOKE(vp, REVOKEALL); 2731out: 2732 vrele(vp); 2733 return (error); 2734} 2735 2736/* 2737 * Convert a user file descriptor to a kernel file entry. 2738 */ 2739int 2740getvnode(fdp, fd, fpp) 2741 struct filedesc *fdp; 2742 int fd; 2743 struct file **fpp; 2744{ 2745 struct file *fp; 2746 2747 if ((u_int)fd >= fdp->fd_nfiles || 2748 (fp = fdp->fd_ofiles[fd]) == NULL) 2749 return (EBADF); 2750 if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) 2751 return (EINVAL); 2752 *fpp = fp; 2753 return (0); 2754} 2755#ifndef _SYS_SYSPROTO_H_ 2756struct __getcwd_args { 2757 u_char *buf; 2758 u_int buflen; 2759}; 2760#endif 2761#define STATNODE(mode, name, var) \ 2762 SYSCTL_INT(_vfs_cache, OID_AUTO, name, mode, var, 0, ""); 2763 2764static int disablecwd; 2765SYSCTL_INT(_debug, OID_AUTO, disablecwd, CTLFLAG_RW, &disablecwd, 0, ""); 2766 2767static u_long numcwdcalls; STATNODE(CTLFLAG_RD, numcwdcalls, &numcwdcalls); 2768static u_long numcwdfail1; STATNODE(CTLFLAG_RD, numcwdfail1, &numcwdfail1); 2769static u_long numcwdfail2; STATNODE(CTLFLAG_RD, numcwdfail2, &numcwdfail2); 2770static u_long numcwdfail3; STATNODE(CTLFLAG_RD, numcwdfail3, &numcwdfail3); 2771static u_long numcwdfail4; STATNODE(CTLFLAG_RD, numcwdfail4, &numcwdfail4); 2772static u_long numcwdfound; STATNODE(CTLFLAG_RD, numcwdfound, &numcwdfound); 2773int 2774__getcwd(p, uap) 2775 struct proc *p; 2776 struct __getcwd_args *uap; 2777{ 2778 char *bp, *buf; 2779 int error, i, slash_prefixed; 2780 struct filedesc *fdp; 2781 struct namecache *ncp; 2782 struct vnode *vp; 2783 2784 numcwdcalls++; 2785 if (disablecwd) 2786 return (ENODEV); 2787 if (uap->buflen < 2) 2788 return (EINVAL); 2789 if (uap->buflen > MAXPATHLEN) 2790 uap->buflen = MAXPATHLEN; 2791 buf = bp = malloc(uap->buflen, M_TEMP, M_WAITOK); 2792 bp += uap->buflen - 1; 2793 *bp = '\0'; 2794 fdp = p->p_fd; 2795 slash_prefixed = 0; 2796 for (vp = fdp->fd_cdir; vp != fdp->fd_rdir && vp != rootvnode;) { 2797 if (vp->v_flag & VROOT) { 2798 vp = vp->v_mount->mnt_vnodecovered; 2799 continue; 2800 } 2801 if (vp->v_dd->v_id != vp->v_ddid) { 2802 numcwdfail1++; 2803 free(buf, M_TEMP); 2804 return (ENOTDIR); 2805 } 2806 ncp = TAILQ_FIRST(&vp->v_cache_dst); 2807 if (!ncp) { 2808 numcwdfail2++; 2809 free(buf, M_TEMP); 2810 return (ENOENT); 2811 } 2812 if (ncp->nc_dvp != vp->v_dd) { 2813 numcwdfail3++; 2814 free(buf, M_TEMP); 2815 return (EBADF); 2816 } 2817 for (i = ncp->nc_nlen - 1; i >= 0; i--) { 2818 if (bp == buf) { 2819 numcwdfail4++; 2820 free(buf, M_TEMP); 2821 return (ENOMEM); 2822 } 2823 *--bp = ncp->nc_name[i]; 2824 } 2825 if (bp == buf) { 2826 numcwdfail4++; 2827 free(buf, M_TEMP); 2828 return (ENOMEM); 2829 } 2830 *--bp = '/'; 2831 slash_prefixed = 1; 2832 vp = vp->v_dd; 2833 } 2834 if (!slash_prefixed) { 2835 if (bp == buf) { 2836 numcwdfail4++; 2837 free(buf, M_TEMP); 2838 return (ENOMEM); 2839 } 2840 *--bp = '/'; 2841 } 2842 numcwdfound++; 2843 error = copyout(bp, uap->buf, strlen(bp) + 1); 2844 free(buf, M_TEMP); 2845 return (error); 2846}
|