Annotation of src/sys/kern/vfs_syscalls.c, Revision 1.159
1.159 ! mrg 1: /* $NetBSD: vfs_syscalls.c,v 1.158 2000/06/19 18:53:55 pooka Exp $ */
1.31 cgd 2:
3: /*
4: * Copyright (c) 1989, 1993
5: * The Regents of the University of California. All rights reserved.
6: * (c) UNIX System Laboratories, Inc.
7: * All or some portions of this file are derived from material licensed
8: * to the University of California by American Telephone and Telegraph
9: * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10: * the permission of UNIX System Laboratories, Inc.
11: *
12: * Redistribution and use in source and binary forms, with or without
13: * modification, are permitted provided that the following conditions
14: * are met:
15: * 1. Redistributions of source code must retain the above copyright
16: * notice, this list of conditions and the following disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
20: * 3. All advertising materials mentioning features or use of this software
21: * must display the following acknowledgement:
22: * This product includes software developed by the University of
23: * California, Berkeley and its contributors.
24: * 4. Neither the name of the University nor the names of its contributors
25: * may be used to endorse or promote products derived from this software
26: * without specific prior written permission.
27: *
28: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38: * SUCH DAMAGE.
39: *
1.113 fvdl 40: * @(#)vfs_syscalls.c 8.42 (Berkeley) 7/31/95
1.31 cgd 41: */
1.111 mrg 42:
1.121 jonathan 43: #include "opt_compat_netbsd.h"
1.127 christos 44: #include "opt_compat_43.h"
1.31 cgd 45:
46: #include <sys/param.h>
47: #include <sys/systm.h>
48: #include <sys/namei.h>
49: #include <sys/filedesc.h>
50: #include <sys/kernel.h>
51: #include <sys/file.h>
52: #include <sys/stat.h>
53: #include <sys/vnode.h>
54: #include <sys/mount.h>
55: #include <sys/proc.h>
56: #include <sys/uio.h>
57: #include <sys/malloc.h>
58: #include <sys/dirent.h>
1.35 cgd 59: #include <sys/syscallargs.h>
60:
1.148 fvdl 61: #include <miscfs/genfs/genfs.h>
62: #include <miscfs/syncfs/syncfs.h>
63:
1.110 mrg 64: #include <uvm/uvm_extern.h>
1.159 ! mrg 65:
! 66: #include <sys/sysctl.h>
1.110 mrg 67:
1.63 christos 68: static int change_dir __P((struct nameidata *, struct proc *));
1.97 enami 69: static int change_mode __P((struct vnode *, int, struct proc *p));
1.112 kleink 70: static int change_owner __P((struct vnode *, uid_t, gid_t, struct proc *,
71: int));
1.97 enami 72: static int change_utimes __P((struct vnode *vp, const struct timeval *,
73: struct proc *p));
1.90 kleink 74: static int rename_files __P((const char *, const char *, struct proc *, int));
1.63 christos 75:
76: void checkdirs __P((struct vnode *));
1.31 cgd 77:
1.150 fvdl 78: int dovfsusermount = 0;
79:
1.31 cgd 80: /*
81: * Virtual File System System Calls
82: */
83:
84: /*
85: * Mount a file system.
86: */
1.99 thorpej 87:
88: /*
89: * This table is used to maintain compatibility with 4.3BSD
90: * and NetBSD 0.9 mount syscalls. Note, the order is important!
1.124 thorpej 91: *
92: * Also note that not all of these had actual numbers in 4.3BSD
93: * or NetBSD 0.9!
1.99 thorpej 94: */
1.113 fvdl 95: const char *mountcompatnames[] = {
1.99 thorpej 96: NULL, /* 0 = MOUNT_NONE */
97: MOUNT_FFS, /* 1 */
98: MOUNT_NFS, /* 2 */
99: MOUNT_MFS, /* 3 */
100: MOUNT_MSDOS, /* 4 */
101: MOUNT_LFS, /* 5 */
102: NULL, /* 6 = MOUNT_LOFS */
103: MOUNT_FDESC, /* 7 */
104: MOUNT_PORTAL, /* 8 */
105: MOUNT_NULL, /* 9 */
106: MOUNT_UMAP, /* 10 */
107: MOUNT_KERNFS, /* 11 */
108: MOUNT_PROCFS, /* 12 */
109: MOUNT_AFS, /* 13 */
110: MOUNT_CD9660, /* 14 = MOUNT_ISOFS */
111: MOUNT_UNION, /* 15 */
112: MOUNT_ADOSFS, /* 16 */
113: MOUNT_EXT2FS, /* 17 */
1.124 thorpej 114: MOUNT_CODA, /* 18 */
115: MOUNT_FILECORE, /* 19 */
1.136 christos 116: MOUNT_NTFS, /* 20 */
1.99 thorpej 117: };
1.113 fvdl 118: const int nmountcompatnames = sizeof(mountcompatnames) /
1.99 thorpej 119: sizeof(mountcompatnames[0]);
120:
1.31 cgd 121: /* ARGSUSED */
1.63 christos 122: int
1.57 mycroft 123: sys_mount(p, v, retval)
1.31 cgd 124: struct proc *p;
1.56 thorpej 125: void *v;
126: register_t *retval;
127: {
1.155 augustss 128: struct sys_mount_args /* {
1.74 cgd 129: syscallarg(const char *) type;
130: syscallarg(const char *) path;
1.35 cgd 131: syscallarg(int) flags;
1.74 cgd 132: syscallarg(void *) data;
1.56 thorpej 133: } */ *uap = v;
1.113 fvdl 134: struct vnode *vp;
135: struct mount *mp;
1.63 christos 136: int error, flag = 0;
1.31 cgd 137: char fstypename[MFSNAMELEN];
1.43 mycroft 138: struct vattr va;
1.31 cgd 139: struct nameidata nd;
1.109 thorpej 140: struct vfsops *vfs;
1.31 cgd 141:
1.150 fvdl 142: if (dovfsusermount == 0 && (error = suser(p->p_ucred, &p->p_acflag)))
143: return (error);
1.31 cgd 144: /*
145: * Get vnode to be covered
146: */
1.113 fvdl 147: NDINIT(&nd, LOOKUP, FOLLOW , UIO_USERSPACE,
1.35 cgd 148: SCARG(uap, path), p);
1.63 christos 149: if ((error = namei(&nd)) != 0)
1.31 cgd 150: return (error);
151: vp = nd.ni_vp;
1.113 fvdl 152: /*
153: * A lookup in VFS_MOUNT might result in an attempt to
154: * lock this vnode again, so make the lock resursive.
155: */
1.128 fvdl 156: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_SETRECURSE);
1.35 cgd 157: if (SCARG(uap, flags) & MNT_UPDATE) {
1.31 cgd 158: if ((vp->v_flag & VROOT) == 0) {
159: vput(vp);
160: return (EINVAL);
161: }
162: mp = vp->v_mount;
163: flag = mp->mnt_flag;
1.109 thorpej 164: vfs = mp->mnt_op;
1.31 cgd 165: /*
166: * We only allow the filesystem to be reloaded if it
167: * is currently mounted read-only.
168: */
1.35 cgd 169: if ((SCARG(uap, flags) & MNT_RELOAD) &&
1.31 cgd 170: ((mp->mnt_flag & MNT_RDONLY) == 0)) {
171: vput(vp);
172: return (EOPNOTSUPP); /* Needs translation */
173: }
1.125 tls 174: /*
175: * In "highly secure" mode, don't let the caller do anything
176: * but downgrade a filesystem from read-write to read-only.
177: * (see also below; MNT_UPDATE is required.)
178: */
179: if (securelevel >= 2 &&
180: (SCARG(uap, flags) !=
181: (mp->mnt_flag | MNT_RDONLY |
182: MNT_RELOAD | MNT_FORCE | MNT_UPDATE))) {
183: vput(vp);
184: return (EPERM);
185: }
1.31 cgd 186: mp->mnt_flag |=
1.35 cgd 187: SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
1.43 mycroft 188: /*
189: * Only root, or the user that did the original mount is
190: * permitted to update it.
191: */
192: if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
1.93 enami 193: (error = suser(p->p_ucred, &p->p_acflag)) != 0) {
1.43 mycroft 194: vput(vp);
195: return (error);
196: }
197: /*
1.130 bouyer 198: * Do not allow NFS export by non-root users. For non-root
199: * users, silently enforce MNT_NOSUID and MNT_NODEV, and
200: * MNT_NOEXEC if mount point is already MNT_NOEXEC.
1.43 mycroft 201: */
202: if (p->p_ucred->cr_uid != 0) {
203: if (SCARG(uap, flags) & MNT_EXPORTED) {
204: vput(vp);
205: return (EPERM);
206: }
207: SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
1.130 bouyer 208: if (flag & MNT_NOEXEC)
209: SCARG(uap, flags) |= MNT_NOEXEC;
1.43 mycroft 210: }
1.113 fvdl 211: if (vfs_busy(mp, LK_NOWAIT, 0)) {
212: vput(vp);
213: return (EPERM);
214: }
215: VOP_UNLOCK(vp, 0);
1.31 cgd 216: goto update;
1.125 tls 217: } else {
1.158 pooka 218: if (securelevel >= 2) {
219: vput(vp);
1.125 tls 220: return (EPERM);
1.158 pooka 221: }
1.31 cgd 222: }
1.43 mycroft 223: /*
224: * If the user is not root, ensure that they own the directory
225: * onto which we are attempting to mount.
226: */
1.93 enami 227: if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) != 0 ||
1.43 mycroft 228: (va.va_uid != p->p_ucred->cr_uid &&
1.93 enami 229: (error = suser(p->p_ucred, &p->p_acflag)) != 0)) {
1.43 mycroft 230: vput(vp);
231: return (error);
232: }
233: /*
1.130 bouyer 234: * Do not allow NFS export by non-root users. For non-root users,
235: * silently enforce MNT_NOSUID and MNT_NODEV, and MNT_NOEXEC if the
236: * mount point is already MNT_NOEXEC.
1.43 mycroft 237: */
238: if (p->p_ucred->cr_uid != 0) {
239: if (SCARG(uap, flags) & MNT_EXPORTED) {
240: vput(vp);
241: return (EPERM);
242: }
243: SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
1.130 bouyer 244: if (vp->v_mount->mnt_flag & MNT_NOEXEC)
245: SCARG(uap, flags) |= MNT_NOEXEC;
1.43 mycroft 246: }
1.63 christos 247: if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
1.31 cgd 248: return (error);
249: if (vp->v_type != VDIR) {
250: vput(vp);
251: return (ENOTDIR);
252: }
1.63 christos 253: error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL);
254: if (error) {
1.54 cgd 255: #if defined(COMPAT_09) || defined(COMPAT_43)
256: /*
257: * Historically filesystem types were identified by number.
258: * If we get an integer for the filesystem type instead of a
259: * string, we check to see if it matches one of the historic
260: * filesystem types.
261: */
1.109 thorpej 262: u_long fsindex = (u_long)SCARG(uap, type);
1.99 thorpej 263: if (fsindex >= nmountcompatnames ||
264: mountcompatnames[fsindex] == NULL) {
1.54 cgd 265: vput(vp);
266: return (ENODEV);
267: }
1.99 thorpej 268: strncpy(fstypename, mountcompatnames[fsindex], MFSNAMELEN);
1.31 cgd 269: #else
270: vput(vp);
271: return (error);
272: #endif
273: }
1.58 gwr 274: #ifdef COMPAT_10
1.59 mycroft 275: /* Accept `ufs' as an alias for `ffs'. */
276: if (!strncmp(fstypename, "ufs", MFSNAMELEN))
277: strncpy(fstypename, "ffs", MFSNAMELEN);
1.58 gwr 278: #endif
1.109 thorpej 279: if ((vfs = vfs_getopsbyname(fstypename)) == NULL) {
1.31 cgd 280: vput(vp);
281: return (ENODEV);
282: }
1.43 mycroft 283: if (vp->v_mountedhere != NULL) {
284: vput(vp);
285: return (EBUSY);
286: }
1.31 cgd 287:
288: /*
289: * Allocate and initialize the file system.
290: */
291: mp = (struct mount *)malloc((u_long)sizeof(struct mount),
292: M_MOUNT, M_WAITOK);
1.123 perry 293: memset((char *)mp, 0, (u_long)sizeof(struct mount));
1.113 fvdl 294: lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);
295: (void)vfs_busy(mp, LK_NOWAIT, 0);
1.109 thorpej 296: mp->mnt_op = vfs;
297: vfs->vfs_refcount++;
1.129 fvdl 298: mp->mnt_vnodecovered = vp;
1.43 mycroft 299: mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
1.148 fvdl 300: mp->mnt_unmounter = NULL;
1.31 cgd 301: update:
302: /*
303: * Set the mount level flags.
304: */
1.35 cgd 305: if (SCARG(uap, flags) & MNT_RDONLY)
1.31 cgd 306: mp->mnt_flag |= MNT_RDONLY;
307: else if (mp->mnt_flag & MNT_RDONLY)
308: mp->mnt_flag |= MNT_WANTRDWR;
309: mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
1.79 fvdl 310: MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOCOREDUMP |
1.157 fvdl 311: MNT_NOATIME | MNT_NODEVMTIME | MNT_SYMPERM | MNT_SOFTDEP);
1.35 cgd 312: mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
1.73 cgd 313: MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC |
1.157 fvdl 314: MNT_NOCOREDUMP | MNT_NOATIME | MNT_NODEVMTIME | MNT_SYMPERM |
315: MNT_SOFTDEP);
1.31 cgd 316: /*
317: * Mount the filesystem.
318: */
1.35 cgd 319: error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
1.31 cgd 320: if (mp->mnt_flag & MNT_UPDATE) {
321: vrele(vp);
322: if (mp->mnt_flag & MNT_WANTRDWR)
323: mp->mnt_flag &= ~MNT_RDONLY;
324: mp->mnt_flag &=~
325: (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
326: if (error)
327: mp->mnt_flag = flag;
1.151 mycroft 328: if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0) {
1.148 fvdl 329: if (mp->mnt_syncer == NULL)
330: error = vfs_allocate_syncvnode(mp);
331: } else {
1.151 mycroft 332: if (mp->mnt_syncer != NULL) {
1.148 fvdl 333: vgone(mp->mnt_syncer);
1.151 mycroft 334: mp->mnt_syncer = NULL;
335: }
1.148 fvdl 336: }
1.113 fvdl 337: vfs_unbusy(mp);
1.31 cgd 338: return (error);
339: }
340: /*
341: * Put the new filesystem on the mount list after root.
342: */
343: cache_purge(vp);
344: if (!error) {
1.128 fvdl 345: vp->v_mountedhere = mp;
1.113 fvdl 346: simple_lock(&mountlist_slock);
1.47 mycroft 347: CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
1.113 fvdl 348: simple_unlock(&mountlist_slock);
1.43 mycroft 349: checkdirs(vp);
1.113 fvdl 350: VOP_UNLOCK(vp, 0);
1.151 mycroft 351: if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0)
1.148 fvdl 352: error = vfs_allocate_syncvnode(mp);
1.113 fvdl 353: vfs_unbusy(mp);
1.46 mycroft 354: (void) VFS_STATFS(mp, &mp->mnt_stat, p);
1.113 fvdl 355: if ((error = VFS_START(mp, 0, p)))
356: vrele(vp);
1.31 cgd 357: } else {
1.128 fvdl 358: vp->v_mountedhere = (struct mount *)0;
1.109 thorpej 359: vfs->vfs_refcount--;
1.113 fvdl 360: vfs_unbusy(mp);
1.31 cgd 361: free((caddr_t)mp, M_MOUNT);
362: vput(vp);
363: }
364: return (error);
365: }
366:
367: /*
1.43 mycroft 368: * Scan all active processes to see if any of them have a current
369: * or root directory onto which the new filesystem has just been
370: * mounted. If so, replace them with the new mount point.
371: */
1.63 christos 372: void
1.43 mycroft 373: checkdirs(olddp)
374: struct vnode *olddp;
375: {
1.134 thorpej 376: struct cwdinfo *cwdi;
1.43 mycroft 377: struct vnode *newdp;
378: struct proc *p;
379:
380: if (olddp->v_usecount == 1)
381: return;
382: if (VFS_ROOT(olddp->v_mountedhere, &newdp))
383: panic("mount: lost mount");
1.144 thorpej 384: proclist_lock_read();
1.43 mycroft 385: for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
1.134 thorpej 386: cwdi = p->p_cwdi;
387: if (cwdi->cwdi_cdir == olddp) {
388: vrele(cwdi->cwdi_cdir);
1.43 mycroft 389: VREF(newdp);
1.134 thorpej 390: cwdi->cwdi_cdir = newdp;
1.43 mycroft 391: }
1.134 thorpej 392: if (cwdi->cwdi_rdir == olddp) {
393: vrele(cwdi->cwdi_rdir);
1.43 mycroft 394: VREF(newdp);
1.134 thorpej 395: cwdi->cwdi_rdir = newdp;
1.43 mycroft 396: }
397: }
1.143 thorpej 398: proclist_unlock_read();
1.43 mycroft 399: if (rootvnode == olddp) {
400: vrele(rootvnode);
401: VREF(newdp);
402: rootvnode = newdp;
403: }
404: vput(newdp);
405: }
406:
407: /*
1.31 cgd 408: * Unmount a file system.
409: *
410: * Note: unmount takes a path to the vnode mounted on as argument,
411: * not special file (as before).
412: */
413: /* ARGSUSED */
1.63 christos 414: int
1.57 mycroft 415: sys_unmount(p, v, retval)
1.31 cgd 416: struct proc *p;
1.56 thorpej 417: void *v;
418: register_t *retval;
419: {
1.155 augustss 420: struct sys_unmount_args /* {
1.74 cgd 421: syscallarg(const char *) path;
1.35 cgd 422: syscallarg(int) flags;
1.56 thorpej 423: } */ *uap = v;
1.155 augustss 424: struct vnode *vp;
1.31 cgd 425: struct mount *mp;
426: int error;
427: struct nameidata nd;
428:
1.35 cgd 429: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
430: SCARG(uap, path), p);
1.63 christos 431: if ((error = namei(&nd)) != 0)
1.31 cgd 432: return (error);
433: vp = nd.ni_vp;
1.43 mycroft 434: mp = vp->v_mount;
1.31 cgd 435:
436: /*
1.43 mycroft 437: * Only root, or the user that did the original mount is
438: * permitted to unmount this filesystem.
1.31 cgd 439: */
1.43 mycroft 440: if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
1.93 enami 441: (error = suser(p->p_ucred, &p->p_acflag)) != 0) {
1.31 cgd 442: vput(vp);
443: return (error);
444: }
445:
446: /*
1.47 mycroft 447: * Don't allow unmounting the root file system.
448: */
449: if (mp->mnt_flag & MNT_ROOTFS) {
450: vput(vp);
451: return (EINVAL);
452: }
453:
454: /*
1.31 cgd 455: * Must be the root of the filesystem
456: */
457: if ((vp->v_flag & VROOT) == 0) {
458: vput(vp);
459: return (EINVAL);
460: }
461: vput(vp);
1.78 fvdl 462:
1.113 fvdl 463: if (vfs_busy(mp, 0, 0))
1.78 fvdl 464: return (EBUSY);
465:
1.35 cgd 466: return (dounmount(mp, SCARG(uap, flags), p));
1.31 cgd 467: }
468:
469: /*
1.78 fvdl 470: * Do the actual file system unmount. File system is assumed to have been
471: * marked busy by the caller.
1.31 cgd 472: */
1.63 christos 473: int
1.31 cgd 474: dounmount(mp, flags, p)
1.155 augustss 475: struct mount *mp;
1.31 cgd 476: int flags;
477: struct proc *p;
478: {
479: struct vnode *coveredvp;
480: int error;
1.140 sommerfe 481: int async;
1.31 cgd 482:
1.113 fvdl 483: simple_lock(&mountlist_slock);
1.148 fvdl 484: vfs_unbusy(mp);
485: /*
486: * XXX Freeze syncer. This should really be done on a mountpoint
487: * basis, but especially the softdep code possibly called from
488: * the syncer doesn't exactly work on a per-mountpoint basis,
489: * so the softdep code would become a maze of vfs_busy calls.
490: */
491: lockmgr(&syncer_lock, LK_EXCLUSIVE, NULL);
492:
1.31 cgd 493: mp->mnt_flag |= MNT_UNMOUNT;
1.148 fvdl 494: mp->mnt_unmounter = p;
1.113 fvdl 495: lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock);
1.91 fvdl 496: if (mp->mnt_flag & MNT_EXPUBLIC)
497: vfs_setpublicfs(NULL, NULL, NULL);
1.141 sommerfe 498: async = mp->mnt_flag & MNT_ASYNC;
1.151 mycroft 499: mp->mnt_flag &= ~MNT_ASYNC;
1.31 cgd 500: cache_purgevfs(mp); /* remove cache entries for this file sys */
1.151 mycroft 501: if (mp->mnt_syncer != NULL) {
1.148 fvdl 502: vgone(mp->mnt_syncer);
1.151 mycroft 503: mp->mnt_syncer = NULL;
504: }
1.113 fvdl 505: if (((mp->mnt_flag & MNT_RDONLY) ||
506: (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
1.31 cgd 507: (flags & MNT_FORCE))
508: error = VFS_UNMOUNT(mp, flags, p);
1.113 fvdl 509: simple_lock(&mountlist_slock);
1.31 cgd 510: if (error) {
1.151 mycroft 511: if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0)
1.148 fvdl 512: (void) vfs_allocate_syncvnode(mp);
1.113 fvdl 513: mp->mnt_flag &= ~MNT_UNMOUNT;
1.148 fvdl 514: mp->mnt_unmounter = NULL;
1.140 sommerfe 515: mp->mnt_flag |= async;
1.113 fvdl 516: lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
517: &mountlist_slock);
1.148 fvdl 518: lockmgr(&syncer_lock, LK_RELEASE, NULL);
1.151 mycroft 519: while (mp->mnt_wcnt > 0) {
1.113 fvdl 520: wakeup((caddr_t)mp);
1.148 fvdl 521: tsleep(&mp->mnt_wcnt, PVFS, "mntwcnt1", 0);
1.142 sommerfe 522: }
523: return (error);
1.113 fvdl 524: }
525: CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
526: if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
527: coveredvp->v_mountedhere = NULL;
528: vrele(coveredvp);
529: }
530: mp->mnt_op->vfs_refcount--;
531: if (mp->mnt_vnodelist.lh_first != NULL)
532: panic("unmount: dangling vnode");
1.142 sommerfe 533: mp->mnt_flag |= MNT_GONE;
1.113 fvdl 534: lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock);
1.148 fvdl 535: lockmgr(&syncer_lock, LK_RELEASE, NULL);
1.142 sommerfe 536: while(mp->mnt_wcnt > 0) {
1.113 fvdl 537: wakeup((caddr_t)mp);
1.148 fvdl 538: tsleep(&mp->mnt_wcnt, PVFS, "mntwcnt2", 0);
1.142 sommerfe 539: }
1.113 fvdl 540: free((caddr_t)mp, M_MOUNT);
541: return (0);
1.31 cgd 542: }
543:
544: /*
545: * Sync each mounted filesystem.
546: */
547: #ifdef DEBUG
548: int syncprt = 0;
549: struct ctldebug debug0 = { "syncprt", &syncprt };
550: #endif
551:
552: /* ARGSUSED */
1.63 christos 553: int
1.57 mycroft 554: sys_sync(p, v, retval)
1.31 cgd 555: struct proc *p;
1.57 mycroft 556: void *v;
1.35 cgd 557: register_t *retval;
1.31 cgd 558: {
1.155 augustss 559: struct mount *mp, *nmp;
1.31 cgd 560: int asyncflag;
561:
1.113 fvdl 562: simple_lock(&mountlist_slock);
1.77 mikel 563: for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) {
1.113 fvdl 564: if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock)) {
565: nmp = mp->mnt_list.cqe_prev;
566: continue;
567: }
568: if ((mp->mnt_flag & MNT_RDONLY) == 0) {
1.31 cgd 569: asyncflag = mp->mnt_flag & MNT_ASYNC;
570: mp->mnt_flag &= ~MNT_ASYNC;
1.110 mrg 571: uvm_vnp_sync(mp);
1.31 cgd 572: VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
573: if (asyncflag)
1.113 fvdl 574: mp->mnt_flag |= MNT_ASYNC;
1.31 cgd 575: }
1.113 fvdl 576: simple_lock(&mountlist_slock);
577: nmp = mp->mnt_list.cqe_prev;
578: vfs_unbusy(mp);
579:
1.31 cgd 580: }
1.113 fvdl 581: simple_unlock(&mountlist_slock);
1.31 cgd 582: #ifdef DEBUG
583: if (syncprt)
584: vfs_bufstats();
585: #endif /* DEBUG */
586: return (0);
587: }
588:
589: /*
590: * Change filesystem quotas.
591: */
592: /* ARGSUSED */
1.63 christos 593: int
1.57 mycroft 594: sys_quotactl(p, v, retval)
1.31 cgd 595: struct proc *p;
1.56 thorpej 596: void *v;
597: register_t *retval;
598: {
1.155 augustss 599: struct sys_quotactl_args /* {
1.74 cgd 600: syscallarg(const char *) path;
1.35 cgd 601: syscallarg(int) cmd;
602: syscallarg(int) uid;
603: syscallarg(caddr_t) arg;
1.56 thorpej 604: } */ *uap = v;
1.155 augustss 605: struct mount *mp;
1.31 cgd 606: int error;
607: struct nameidata nd;
608:
1.35 cgd 609: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.63 christos 610: if ((error = namei(&nd)) != 0)
1.31 cgd 611: return (error);
612: mp = nd.ni_vp->v_mount;
613: vrele(nd.ni_vp);
1.35 cgd 614: return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
615: SCARG(uap, arg), p));
1.31 cgd 616: }
617:
618: /*
619: * Get filesystem statistics.
620: */
621: /* ARGSUSED */
1.63 christos 622: int
1.57 mycroft 623: sys_statfs(p, v, retval)
1.31 cgd 624: struct proc *p;
1.56 thorpej 625: void *v;
626: register_t *retval;
627: {
1.155 augustss 628: struct sys_statfs_args /* {
1.74 cgd 629: syscallarg(const char *) path;
1.35 cgd 630: syscallarg(struct statfs *) buf;
1.56 thorpej 631: } */ *uap = v;
1.155 augustss 632: struct mount *mp;
633: struct statfs *sp;
1.31 cgd 634: int error;
635: struct nameidata nd;
636:
1.35 cgd 637: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.63 christos 638: if ((error = namei(&nd)) != 0)
1.31 cgd 639: return (error);
640: mp = nd.ni_vp->v_mount;
641: sp = &mp->mnt_stat;
642: vrele(nd.ni_vp);
1.63 christos 643: if ((error = VFS_STATFS(mp, sp, p)) != 0)
1.31 cgd 644: return (error);
645: sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1.148 fvdl 646: sp->f_oflags = sp->f_flags & 0xffff;
1.74 cgd 647: return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
1.31 cgd 648: }
649:
650: /*
651: * Get filesystem statistics.
652: */
653: /* ARGSUSED */
1.63 christos 654: int
1.57 mycroft 655: sys_fstatfs(p, v, retval)
1.31 cgd 656: struct proc *p;
1.56 thorpej 657: void *v;
658: register_t *retval;
659: {
1.155 augustss 660: struct sys_fstatfs_args /* {
1.35 cgd 661: syscallarg(int) fd;
662: syscallarg(struct statfs *) buf;
1.56 thorpej 663: } */ *uap = v;
1.31 cgd 664: struct file *fp;
665: struct mount *mp;
1.155 augustss 666: struct statfs *sp;
1.31 cgd 667: int error;
668:
1.135 thorpej 669: /* getvnode() will use the descriptor for us */
1.63 christos 670: if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1.31 cgd 671: return (error);
1.62 mycroft 672: mp = ((struct vnode *)fp->f_data)->v_mount;
1.31 cgd 673: sp = &mp->mnt_stat;
1.63 christos 674: if ((error = VFS_STATFS(mp, sp, p)) != 0)
1.135 thorpej 675: goto out;
1.31 cgd 676: sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1.148 fvdl 677: sp->f_oflags = sp->f_flags & 0xffff;
1.135 thorpej 678: error = copyout(sp, SCARG(uap, buf), sizeof(*sp));
679: out:
680: FILE_UNUSE(fp, p);
681: return (error);
1.31 cgd 682: }
683:
684: /*
685: * Get statistics on all filesystems.
686: */
1.63 christos 687: int
1.57 mycroft 688: sys_getfsstat(p, v, retval)
1.31 cgd 689: struct proc *p;
1.56 thorpej 690: void *v;
691: register_t *retval;
692: {
1.155 augustss 693: struct sys_getfsstat_args /* {
1.35 cgd 694: syscallarg(struct statfs *) buf;
695: syscallarg(long) bufsize;
696: syscallarg(int) flags;
1.56 thorpej 697: } */ *uap = v;
1.155 augustss 698: struct mount *mp, *nmp;
699: struct statfs *sp;
1.31 cgd 700: caddr_t sfsp;
701: long count, maxcount, error;
702:
1.35 cgd 703: maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
704: sfsp = (caddr_t)SCARG(uap, buf);
1.113 fvdl 705: simple_lock(&mountlist_slock);
706: count = 0;
707: for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
708: if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock)) {
709: nmp = mp->mnt_list.cqe_next;
710: continue;
711: }
712: if (sfsp && count < maxcount) {
1.31 cgd 713: sp = &mp->mnt_stat;
714: /*
1.148 fvdl 715: * If MNT_NOWAIT or MNT_LAZY is specified, do not
716: * refresh the fsstat cache. MNT_WAIT or MNT_LAXY
717: * overrides MNT_NOWAIT.
1.31 cgd 718: */
1.148 fvdl 719: if (SCARG(uap, flags) != MNT_NOWAIT &&
720: SCARG(uap, flags) != MNT_LAZY &&
721: (SCARG(uap, flags) == MNT_WAIT ||
722: SCARG(uap, flags) == 0) &&
1.113 fvdl 723: (error = VFS_STATFS(mp, sp, p)) != 0) {
724: simple_lock(&mountlist_slock);
725: nmp = mp->mnt_list.cqe_next;
726: vfs_unbusy(mp);
1.31 cgd 727: continue;
1.113 fvdl 728: }
1.31 cgd 729: sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1.148 fvdl 730: sp->f_oflags = sp->f_flags & 0xffff;
1.74 cgd 731: error = copyout(sp, sfsp, sizeof(*sp));
1.133 mycroft 732: if (error) {
733: vfs_unbusy(mp);
1.31 cgd 734: return (error);
1.133 mycroft 735: }
1.31 cgd 736: sfsp += sizeof(*sp);
737: }
738: count++;
1.113 fvdl 739: simple_lock(&mountlist_slock);
740: nmp = mp->mnt_list.cqe_next;
741: vfs_unbusy(mp);
1.31 cgd 742: }
1.113 fvdl 743: simple_unlock(&mountlist_slock);
1.31 cgd 744: if (sfsp && count > maxcount)
745: *retval = maxcount;
746: else
747: *retval = count;
748: return (0);
749: }
750:
751: /*
752: * Change current working directory to a given file descriptor.
753: */
754: /* ARGSUSED */
1.63 christos 755: int
1.57 mycroft 756: sys_fchdir(p, v, retval)
1.31 cgd 757: struct proc *p;
1.56 thorpej 758: void *v;
759: register_t *retval;
760: {
1.57 mycroft 761: struct sys_fchdir_args /* {
1.35 cgd 762: syscallarg(int) fd;
1.56 thorpej 763: } */ *uap = v;
1.134 thorpej 764: struct filedesc *fdp = p->p_fd;
765: struct cwdinfo *cwdi = p->p_cwdi;
1.43 mycroft 766: struct vnode *vp, *tdp;
767: struct mount *mp;
1.31 cgd 768: struct file *fp;
769: int error;
770:
1.135 thorpej 771: /* getvnode() will use the descriptor for us */
1.63 christos 772: if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
1.31 cgd 773: return (error);
1.62 mycroft 774: vp = (struct vnode *)fp->f_data;
1.131 sommerfe 775:
1.43 mycroft 776: VREF(vp);
1.113 fvdl 777: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.31 cgd 778: if (vp->v_type != VDIR)
779: error = ENOTDIR;
780: else
1.89 mycroft 781: error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
1.43 mycroft 782: while (!error && (mp = vp->v_mountedhere) != NULL) {
1.113 fvdl 783: if (vfs_busy(mp, 0, 0))
1.43 mycroft 784: continue;
1.113 fvdl 785: error = VFS_ROOT(mp, &tdp);
786: vfs_unbusy(mp);
787: if (error)
1.43 mycroft 788: break;
789: vput(vp);
790: vp = tdp;
791: }
792: if (error) {
1.113 fvdl 793: vput(vp);
1.135 thorpej 794: goto out;
1.43 mycroft 795: }
1.113 fvdl 796: VOP_UNLOCK(vp, 0);
1.131 sommerfe 797:
798: /*
799: * Disallow changing to a directory not under the process's
800: * current root directory (if there is one).
801: */
1.135 thorpej 802: if (cwdi->cwdi_rdir && !vn_isunder(vp, NULL, p)) {
1.131 sommerfe 803: vrele(vp);
1.135 thorpej 804: error = EPERM; /* operation not permitted */
805: goto out;
1.131 sommerfe 806: }
807:
1.134 thorpej 808: vrele(cwdi->cwdi_cdir);
809: cwdi->cwdi_cdir = vp;
1.135 thorpej 810: out:
811: FILE_UNUSE(fp, p);
812: return (error);
1.31 cgd 813: }
814:
815: /*
1.131 sommerfe 816: * Change this process's notion of the root directory to a given file descriptor.
817: */
818:
819: int
820: sys_fchroot(p, v, retval)
821: struct proc *p;
822: void *v;
823: register_t *retval;
824: {
825: struct sys_fchroot_args *uap = v;
1.134 thorpej 826: struct filedesc *fdp = p->p_fd;
827: struct cwdinfo *cwdi = p->p_cwdi;
1.131 sommerfe 828: struct vnode *vp;
829: struct file *fp;
830: int error;
831:
832: if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
833: return error;
1.135 thorpej 834: /* getvnode() will use the descriptor for us */
1.131 sommerfe 835: if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
836: return error;
837: vp = (struct vnode *) fp->f_data;
838: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
839: if (vp->v_type != VDIR)
840: error = ENOTDIR;
841: else
842: error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
843: VOP_UNLOCK(vp, 0);
844: if (error)
1.135 thorpej 845: goto out;
1.131 sommerfe 846: VREF(vp);
847:
848: /*
849: * Prevent escaping from chroot by putting the root under
850: * the working directory. Silently chdir to / if we aren't
851: * already there.
852: */
1.134 thorpej 853: if (!vn_isunder(cwdi->cwdi_cdir, vp, p)) {
1.131 sommerfe 854: /*
855: * XXX would be more failsafe to change directory to a
856: * deadfs node here instead
857: */
1.134 thorpej 858: vrele(cwdi->cwdi_cdir);
1.131 sommerfe 859: VREF(vp);
1.134 thorpej 860: cwdi->cwdi_cdir = vp;
1.131 sommerfe 861: }
862:
1.134 thorpej 863: if (cwdi->cwdi_rdir != NULL)
864: vrele(cwdi->cwdi_rdir);
865: cwdi->cwdi_rdir = vp;
1.135 thorpej 866: out:
867: FILE_UNUSE(fp, p);
868: return (error);
1.131 sommerfe 869: }
870:
871:
872:
873: /*
1.31 cgd 874: * Change current working directory (``.'').
875: */
876: /* ARGSUSED */
1.63 christos 877: int
1.57 mycroft 878: sys_chdir(p, v, retval)
1.31 cgd 879: struct proc *p;
1.56 thorpej 880: void *v;
881: register_t *retval;
882: {
1.57 mycroft 883: struct sys_chdir_args /* {
1.74 cgd 884: syscallarg(const char *) path;
1.56 thorpej 885: } */ *uap = v;
1.134 thorpej 886: struct cwdinfo *cwdi = p->p_cwdi;
1.31 cgd 887: int error;
888: struct nameidata nd;
889:
1.35 cgd 890: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
891: SCARG(uap, path), p);
1.63 christos 892: if ((error = change_dir(&nd, p)) != 0)
1.31 cgd 893: return (error);
1.134 thorpej 894: vrele(cwdi->cwdi_cdir);
895: cwdi->cwdi_cdir = nd.ni_vp;
1.31 cgd 896: return (0);
897: }
898:
899: /*
900: * Change notion of root (``/'') directory.
901: */
902: /* ARGSUSED */
1.63 christos 903: int
1.57 mycroft 904: sys_chroot(p, v, retval)
1.31 cgd 905: struct proc *p;
1.56 thorpej 906: void *v;
907: register_t *retval;
908: {
1.57 mycroft 909: struct sys_chroot_args /* {
1.74 cgd 910: syscallarg(const char *) path;
1.56 thorpej 911: } */ *uap = v;
1.134 thorpej 912: struct cwdinfo *cwdi = p->p_cwdi;
1.131 sommerfe 913: struct vnode *vp;
1.31 cgd 914: int error;
915: struct nameidata nd;
916:
1.63 christos 917: if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
1.31 cgd 918: return (error);
1.35 cgd 919: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
920: SCARG(uap, path), p);
1.63 christos 921: if ((error = change_dir(&nd, p)) != 0)
1.31 cgd 922: return (error);
1.134 thorpej 923: if (cwdi->cwdi_rdir != NULL)
924: vrele(cwdi->cwdi_rdir);
1.131 sommerfe 925: vp = nd.ni_vp;
1.134 thorpej 926: cwdi->cwdi_rdir = vp;
1.131 sommerfe 927:
928: /*
929: * Prevent escaping from chroot by putting the root under
930: * the working directory. Silently chdir to / if we aren't
931: * already there.
932: */
1.134 thorpej 933: if (!vn_isunder(cwdi->cwdi_cdir, vp, p)) {
1.131 sommerfe 934: /*
935: * XXX would be more failsafe to change directory to a
936: * deadfs node here instead
937: */
1.134 thorpej 938: vrele(cwdi->cwdi_cdir);
1.131 sommerfe 939: VREF(vp);
1.134 thorpej 940: cwdi->cwdi_cdir = vp;
1.131 sommerfe 941: }
942:
1.31 cgd 943: return (0);
944: }
945:
946: /*
947: * Common routine for chroot and chdir.
948: */
949: static int
950: change_dir(ndp, p)
1.155 augustss 951: struct nameidata *ndp;
1.31 cgd 952: struct proc *p;
953: {
954: struct vnode *vp;
955: int error;
956:
1.63 christos 957: if ((error = namei(ndp)) != 0)
1.31 cgd 958: return (error);
959: vp = ndp->ni_vp;
960: if (vp->v_type != VDIR)
961: error = ENOTDIR;
962: else
1.89 mycroft 963: error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
1.113 fvdl 964:
1.31 cgd 965: if (error)
1.113 fvdl 966: vput(vp);
967: else
968: VOP_UNLOCK(vp, 0);
1.31 cgd 969: return (error);
970: }
971:
972: /*
973: * Check permissions, allocate an open file structure,
974: * and call the device open routine if any.
975: */
1.63 christos 976: int
1.57 mycroft 977: sys_open(p, v, retval)
1.31 cgd 978: struct proc *p;
1.56 thorpej 979: void *v;
980: register_t *retval;
981: {
1.155 augustss 982: struct sys_open_args /* {
1.74 cgd 983: syscallarg(const char *) path;
1.35 cgd 984: syscallarg(int) flags;
985: syscallarg(int) mode;
1.56 thorpej 986: } */ *uap = v;
1.134 thorpej 987: struct cwdinfo *cwdi = p->p_cwdi;
1.135 thorpej 988: struct filedesc *fdp = p->p_fd;
989: struct file *fp;
990: struct vnode *vp;
1.31 cgd 991: int flags, cmode;
992: int type, indx, error;
993: struct flock lf;
994: struct nameidata nd;
995:
1.104 mycroft 996: flags = FFLAGS(SCARG(uap, flags));
997: if ((flags & (FREAD | FWRITE)) == 0)
998: return (EINVAL);
1.135 thorpej 999: /* falloc() will use the file descriptor for us */
1000: if ((error = falloc(p, &fp, &indx)) != 0)
1.31 cgd 1001: return (error);
1.134 thorpej 1002: cmode = ((SCARG(uap, mode) &~ cwdi->cwdi_cmask) & ALLPERMS) &~ S_ISTXT;
1.35 cgd 1003: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.31 cgd 1004: p->p_dupfd = -indx - 1; /* XXX check for fdopen */
1.63 christos 1005: if ((error = vn_open(&nd, flags, cmode)) != 0) {
1.135 thorpej 1006: FILE_UNUSE(fp, p);
1.31 cgd 1007: ffree(fp);
1.45 mycroft 1008: if ((error == ENODEV || error == ENXIO) &&
1009: p->p_dupfd >= 0 && /* XXX from fdopen */
1010: (error =
1.135 thorpej 1011: dupfdopen(p, indx, p->p_dupfd, flags, error)) == 0) {
1.45 mycroft 1012: *retval = indx;
1013: return (0);
1014: }
1015: if (error == ERESTART)
1.44 mycroft 1016: error = EINTR;
1.153 thorpej 1017: fdremove(fdp, indx);
1.31 cgd 1018: return (error);
1019: }
1020: p->p_dupfd = 0;
1021: vp = nd.ni_vp;
1022: fp->f_flag = flags & FMASK;
1023: fp->f_type = DTYPE_VNODE;
1024: fp->f_ops = &vnops;
1025: fp->f_data = (caddr_t)vp;
1026: if (flags & (O_EXLOCK | O_SHLOCK)) {
1027: lf.l_whence = SEEK_SET;
1028: lf.l_start = 0;
1029: lf.l_len = 0;
1030: if (flags & O_EXLOCK)
1031: lf.l_type = F_WRLCK;
1032: else
1033: lf.l_type = F_RDLCK;
1034: type = F_FLOCK;
1035: if ((flags & FNONBLOCK) == 0)
1036: type |= F_WAIT;
1.113 fvdl 1037: VOP_UNLOCK(vp, 0);
1.63 christos 1038: error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
1039: if (error) {
1.31 cgd 1040: (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
1.135 thorpej 1041: FILE_UNUSE(fp, p);
1.31 cgd 1042: ffree(fp);
1.153 thorpej 1043: fdremove(fdp, indx);
1.31 cgd 1044: return (error);
1045: }
1.113 fvdl 1046: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.31 cgd 1047: fp->f_flag |= FHASLOCK;
1048: }
1.113 fvdl 1049: VOP_UNLOCK(vp, 0);
1.31 cgd 1050: *retval = indx;
1.135 thorpej 1051: FILE_UNUSE(fp, p);
1.31 cgd 1052: return (0);
1.137 wrstuden 1053: }
1054:
1055: /*
1056: * Get file handle system call
1057: */
1058: int
1059: sys_getfh(p, v, retval)
1060: struct proc *p;
1.155 augustss 1061: void *v;
1.137 wrstuden 1062: register_t *retval;
1063: {
1.155 augustss 1064: struct sys_getfh_args /* {
1.137 wrstuden 1065: syscallarg(char *) fname;
1066: syscallarg(fhandle_t *) fhp;
1067: } */ *uap = v;
1.155 augustss 1068: struct vnode *vp;
1.137 wrstuden 1069: fhandle_t fh;
1070: int error;
1071: struct nameidata nd;
1072:
1073: /*
1074: * Must be super user
1075: */
1076: error = suser(p->p_ucred, &p->p_acflag);
1077: if (error)
1078: return (error);
1079: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1080: SCARG(uap, fname), p);
1081: error = namei(&nd);
1082: if (error)
1083: return (error);
1084: vp = nd.ni_vp;
1085: memset((caddr_t)&fh, 0, sizeof(fh));
1086: fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1087: error = VFS_VPTOFH(vp, &fh.fh_fid);
1088: vput(vp);
1089: if (error)
1090: return (error);
1091: error = copyout((caddr_t)&fh, (caddr_t)SCARG(uap, fhp), sizeof (fh));
1092: return (error);
1093: }
1094:
1095: /*
1096: * Open a file given a file handle.
1097: *
1098: * Check permissions, allocate an open file structure,
1099: * and call the device open routine if any.
1100: */
1101: int
1102: sys_fhopen(p, v, retval)
1103: struct proc *p;
1104: void *v;
1105: register_t *retval;
1106: {
1.155 augustss 1107: struct sys_fhopen_args /* {
1.137 wrstuden 1108: syscallarg(const fhandle_t *) fhp;
1109: syscallarg(int) flags;
1110: } */ *uap = v;
1111: struct filedesc *fdp = p->p_fd;
1112: struct file *fp;
1.139 wrstuden 1113: struct vnode *vp = NULL;
1.137 wrstuden 1114: struct mount *mp;
1115: struct ucred *cred = p->p_ucred;
1116: int flags;
1117: struct file *nfp;
1118: int type, indx, error=0;
1119: struct flock lf;
1120: struct vattr va;
1121: fhandle_t fh;
1122:
1123: /*
1124: * Must be super user
1125: */
1126: if ((error = suser(p->p_ucred, &p->p_acflag)))
1127: return (error);
1128:
1129: flags = FFLAGS(SCARG(uap, flags));
1130: if ((flags & (FREAD | FWRITE)) == 0)
1131: return (EINVAL);
1132: if ((flags & O_CREAT))
1133: return (EINVAL);
1.139 wrstuden 1134: /* falloc() will use the file descriptor for us */
1.137 wrstuden 1135: if ((error = falloc(p, &nfp, &indx)) != 0)
1136: return (error);
1137: fp = nfp;
1138: if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
1.139 wrstuden 1139: goto bad;
1140:
1141: if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
1142: error = ESTALE;
1143: goto bad;
1144: }
1.137 wrstuden 1145:
1.139 wrstuden 1146: if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)) != 0) {
1147: vp = NULL; /* most likely unnecessary sanity for bad: */
1148: goto bad;
1149: }
1.137 wrstuden 1150:
1151: /* Now do an effective vn_open */
1152:
1153: if (vp->v_type == VSOCK) {
1154: error = EOPNOTSUPP;
1155: goto bad;
1156: }
1157: if (flags & FREAD) {
1158: if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0)
1159: goto bad;
1160: }
1161: if (flags & (FWRITE | O_TRUNC)) {
1162: if (vp->v_type == VDIR) {
1163: error = EISDIR;
1164: goto bad;
1165: }
1166: if ((error = vn_writechk(vp)) != 0 ||
1167: (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0)
1168: goto bad;
1169: }
1170: if (flags & O_TRUNC) {
1171: VOP_UNLOCK(vp, 0); /* XXX */
1172: VOP_LEASE(vp, p, cred, LEASE_WRITE);
1173: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); /* XXX */
1174: VATTR_NULL(&va);
1175: va.va_size = 0;
1176: if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0)
1177: goto bad;
1178: }
1179: if ((error = VOP_OPEN(vp, flags, cred, p)) != 0)
1180: goto bad;
1181: if (flags & FWRITE)
1182: vp->v_writecount++;
1183:
1184: /* done with modified vn_open, now finish what sys_open does. */
1185:
1186: fp->f_flag = flags & FMASK;
1187: fp->f_type = DTYPE_VNODE;
1188: fp->f_ops = &vnops;
1189: fp->f_data = (caddr_t)vp;
1190: if (flags & (O_EXLOCK | O_SHLOCK)) {
1191: lf.l_whence = SEEK_SET;
1192: lf.l_start = 0;
1193: lf.l_len = 0;
1194: if (flags & O_EXLOCK)
1195: lf.l_type = F_WRLCK;
1196: else
1197: lf.l_type = F_RDLCK;
1198: type = F_FLOCK;
1199: if ((flags & FNONBLOCK) == 0)
1200: type |= F_WAIT;
1201: VOP_UNLOCK(vp, 0);
1202: error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
1203: if (error) {
1204: (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
1.139 wrstuden 1205: FILE_UNUSE(fp, p);
1.137 wrstuden 1206: ffree(fp);
1.153 thorpej 1207: fdremove(fdp, indx);
1.137 wrstuden 1208: return (error);
1209: }
1210: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1211: fp->f_flag |= FHASLOCK;
1212: }
1213: VOP_UNLOCK(vp, 0);
1214: *retval = indx;
1.139 wrstuden 1215: FILE_UNUSE(fp, p);
1.137 wrstuden 1216: return (0);
1.139 wrstuden 1217:
1.137 wrstuden 1218: bad:
1.139 wrstuden 1219: FILE_UNUSE(fp, p);
1220: ffree(fp);
1.153 thorpej 1221: fdremove(fdp, indx);
1.139 wrstuden 1222: if (vp != NULL)
1223: vput(vp);
1.137 wrstuden 1224: return (error);
1225: }
1226:
1227: /* ARGSUSED */
1228: int
1229: sys_fhstat(p, v, retval)
1230: struct proc *p;
1231: void *v;
1232: register_t *retval;
1233: {
1.155 augustss 1234: struct sys_fhstat_args /* {
1.137 wrstuden 1235: syscallarg(const fhandle_t *) fhp;
1236: syscallarg(struct stat *) sb;
1237: } */ *uap = v;
1238: struct stat sb;
1239: int error;
1240: fhandle_t fh;
1241: struct mount *mp;
1242: struct vnode *vp;
1243:
1244: /*
1245: * Must be super user
1246: */
1247: if ((error = suser(p->p_ucred, &p->p_acflag)))
1248: return (error);
1249:
1250: if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
1251: return (error);
1252:
1253: if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
1254: return (ESTALE);
1255: if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
1256: return (error);
1257: error = vn_stat(vp, &sb, p);
1258: vput(vp);
1259: if (error)
1260: return (error);
1261: error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
1262: return (error);
1263: }
1264:
1265: /* ARGSUSED */
1266: int
1267: sys_fhstatfs(p, v, retval)
1268: struct proc *p;
1269: void *v;
1270: register_t *retval;
1271: {
1.155 augustss 1272: struct sys_fhstatfs_args /*
1.137 wrstuden 1273: syscallarg(const fhandle_t *) fhp;
1274: syscallarg(struct statfs *) buf;
1275: } */ *uap = v;
1276: struct statfs sp;
1277: fhandle_t fh;
1278: struct mount *mp;
1279: struct vnode *vp;
1280: int error;
1281:
1282: /*
1283: * Must be super user
1284: */
1285: if ((error = suser(p->p_ucred, &p->p_acflag)))
1286: return (error);
1287:
1288: if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
1289: return (error);
1290:
1291: if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
1292: return (ESTALE);
1293: if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
1294: return (error);
1295: mp = vp->v_mount;
1296: vput(vp);
1297: if ((error = VFS_STATFS(mp, &sp, p)) != 0)
1298: return (error);
1299: sp.f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1.148 fvdl 1300: sp.f_oflags = sp.f_flags & 0xffff;
1.137 wrstuden 1301: return (copyout(&sp, SCARG(uap, buf), sizeof(sp)));
1.31 cgd 1302: }
1303:
1304: /*
1305: * Create a special file.
1306: */
1307: /* ARGSUSED */
1.63 christos 1308: int
1.57 mycroft 1309: sys_mknod(p, v, retval)
1.31 cgd 1310: struct proc *p;
1.56 thorpej 1311: void *v;
1312: register_t *retval;
1313: {
1.155 augustss 1314: struct sys_mknod_args /* {
1.74 cgd 1315: syscallarg(const char *) path;
1.35 cgd 1316: syscallarg(int) mode;
1317: syscallarg(int) dev;
1.56 thorpej 1318: } */ *uap = v;
1.155 augustss 1319: struct vnode *vp;
1.31 cgd 1320: struct vattr vattr;
1321: int error;
1.63 christos 1322: int whiteout = 0;
1.31 cgd 1323: struct nameidata nd;
1324:
1.63 christos 1325: if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
1.31 cgd 1326: return (error);
1.35 cgd 1327: NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1.63 christos 1328: if ((error = namei(&nd)) != 0)
1.31 cgd 1329: return (error);
1330: vp = nd.ni_vp;
1.43 mycroft 1331: if (vp != NULL)
1.31 cgd 1332: error = EEXIST;
1.43 mycroft 1333: else {
1334: VATTR_NULL(&vattr);
1.94 enami 1335: vattr.va_mode =
1.134 thorpej 1336: (SCARG(uap, mode) & ALLPERMS) &~ p->p_cwdi->cwdi_cmask;
1.43 mycroft 1337: vattr.va_rdev = SCARG(uap, dev);
1338: whiteout = 0;
1339:
1340: switch (SCARG(uap, mode) & S_IFMT) {
1341: case S_IFMT: /* used by badsect to flag bad sectors */
1342: vattr.va_type = VBAD;
1343: break;
1344: case S_IFCHR:
1345: vattr.va_type = VCHR;
1346: break;
1347: case S_IFBLK:
1348: vattr.va_type = VBLK;
1349: break;
1350: case S_IFWHT:
1351: whiteout = 1;
1352: break;
1353: default:
1354: error = EINVAL;
1355: break;
1356: }
1.31 cgd 1357: }
1.43 mycroft 1358: if (!error) {
1359: VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1360: if (whiteout) {
1361: error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
1362: if (error)
1363: VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1364: vput(nd.ni_dvp);
1365: } else {
1366: error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1367: &nd.ni_cnd, &vattr);
1368: }
1369: } else {
1370: VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1371: if (nd.ni_dvp == vp)
1372: vrele(nd.ni_dvp);
1373: else
1374: vput(nd.ni_dvp);
1375: if (vp)
1376: vrele(vp);
1.31 cgd 1377: }
1378: return (error);
1379: }
1380:
1381: /*
1382: * Create a named pipe.
1383: */
1384: /* ARGSUSED */
1.63 christos 1385: int
1.57 mycroft 1386: sys_mkfifo(p, v, retval)
1.31 cgd 1387: struct proc *p;
1.56 thorpej 1388: void *v;
1389: register_t *retval;
1390: {
1.155 augustss 1391: struct sys_mkfifo_args /* {
1.74 cgd 1392: syscallarg(const char *) path;
1.35 cgd 1393: syscallarg(int) mode;
1.56 thorpej 1394: } */ *uap = v;
1.31 cgd 1395: struct vattr vattr;
1396: int error;
1397: struct nameidata nd;
1398:
1.35 cgd 1399: NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1.63 christos 1400: if ((error = namei(&nd)) != 0)
1.31 cgd 1401: return (error);
1402: if (nd.ni_vp != NULL) {
1403: VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1404: if (nd.ni_dvp == nd.ni_vp)
1405: vrele(nd.ni_dvp);
1406: else
1407: vput(nd.ni_dvp);
1408: vrele(nd.ni_vp);
1409: return (EEXIST);
1410: }
1411: VATTR_NULL(&vattr);
1412: vattr.va_type = VFIFO;
1.134 thorpej 1413: vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_cwdi->cwdi_cmask;
1.42 mycroft 1414: VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1.31 cgd 1415: return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
1416: }
1417:
1418: /*
1419: * Make a hard file link.
1420: */
1421: /* ARGSUSED */
1.63 christos 1422: int
1.57 mycroft 1423: sys_link(p, v, retval)
1.31 cgd 1424: struct proc *p;
1.56 thorpej 1425: void *v;
1426: register_t *retval;
1427: {
1.155 augustss 1428: struct sys_link_args /* {
1.74 cgd 1429: syscallarg(const char *) path;
1430: syscallarg(const char *) link;
1.56 thorpej 1431: } */ *uap = v;
1.155 augustss 1432: struct vnode *vp;
1.31 cgd 1433: struct nameidata nd;
1434: int error;
1435:
1.147 hubertf 1436: NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.63 christos 1437: if ((error = namei(&nd)) != 0)
1.31 cgd 1438: return (error);
1439: vp = nd.ni_vp;
1.66 mycroft 1440: NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
1441: if ((error = namei(&nd)) != 0)
1442: goto out;
1443: if (nd.ni_vp) {
1444: VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1445: if (nd.ni_dvp == nd.ni_vp)
1446: vrele(nd.ni_dvp);
1447: else
1448: vput(nd.ni_dvp);
1449: vrele(nd.ni_vp);
1450: error = EEXIST;
1451: goto out;
1.31 cgd 1452: }
1.66 mycroft 1453: VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1454: VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1455: error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1456: out:
1.31 cgd 1457: vrele(vp);
1458: return (error);
1459: }
1460:
1461: /*
1462: * Make a symbolic link.
1463: */
1464: /* ARGSUSED */
1.63 christos 1465: int
1.57 mycroft 1466: sys_symlink(p, v, retval)
1.31 cgd 1467: struct proc *p;
1.56 thorpej 1468: void *v;
1469: register_t *retval;
1470: {
1.155 augustss 1471: struct sys_symlink_args /* {
1.74 cgd 1472: syscallarg(const char *) path;
1473: syscallarg(const char *) link;
1.56 thorpej 1474: } */ *uap = v;
1.31 cgd 1475: struct vattr vattr;
1476: char *path;
1477: int error;
1478: struct nameidata nd;
1479:
1480: MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
1.63 christos 1481: error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL);
1482: if (error)
1.43 mycroft 1483: goto out;
1.35 cgd 1484: NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
1.63 christos 1485: if ((error = namei(&nd)) != 0)
1.43 mycroft 1486: goto out;
1.31 cgd 1487: if (nd.ni_vp) {
1488: VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1489: if (nd.ni_dvp == nd.ni_vp)
1490: vrele(nd.ni_dvp);
1491: else
1492: vput(nd.ni_dvp);
1493: vrele(nd.ni_vp);
1494: error = EEXIST;
1.43 mycroft 1495: goto out;
1.31 cgd 1496: }
1497: VATTR_NULL(&vattr);
1.134 thorpej 1498: vattr.va_mode = ACCESSPERMS &~ p->p_cwdi->cwdi_cmask;
1.42 mycroft 1499: VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1.31 cgd 1500: error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
1.43 mycroft 1501: out:
1.31 cgd 1502: FREE(path, M_NAMEI);
1503: return (error);
1504: }
1505:
1506: /*
1.43 mycroft 1507: * Delete a whiteout from the filesystem.
1508: */
1509: /* ARGSUSED */
1.63 christos 1510: int
1.57 mycroft 1511: sys_undelete(p, v, retval)
1.43 mycroft 1512: struct proc *p;
1.56 thorpej 1513: void *v;
1514: register_t *retval;
1515: {
1.155 augustss 1516: struct sys_undelete_args /* {
1.74 cgd 1517: syscallarg(const char *) path;
1.56 thorpej 1518: } */ *uap = v;
1.43 mycroft 1519: int error;
1520: struct nameidata nd;
1521:
1522: NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
1523: SCARG(uap, path), p);
1524: error = namei(&nd);
1525: if (error)
1526: return (error);
1527:
1528: if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1529: VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1530: if (nd.ni_dvp == nd.ni_vp)
1531: vrele(nd.ni_dvp);
1532: else
1533: vput(nd.ni_dvp);
1534: if (nd.ni_vp)
1535: vrele(nd.ni_vp);
1536: return (EEXIST);
1537: }
1538:
1539: VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1.63 christos 1540: if ((error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) != 0)
1.43 mycroft 1541: VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1542: vput(nd.ni_dvp);
1543: return (error);
1544: }
1545:
1546: /*
1.31 cgd 1547: * Delete a name from the filesystem.
1548: */
1549: /* ARGSUSED */
1.63 christos 1550: int
1.57 mycroft 1551: sys_unlink(p, v, retval)
1.31 cgd 1552: struct proc *p;
1.56 thorpej 1553: void *v;
1554: register_t *retval;
1555: {
1.57 mycroft 1556: struct sys_unlink_args /* {
1.74 cgd 1557: syscallarg(const char *) path;
1.56 thorpej 1558: } */ *uap = v;
1.155 augustss 1559: struct vnode *vp;
1.31 cgd 1560: int error;
1561: struct nameidata nd;
1562:
1.67 mycroft 1563: NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
1564: SCARG(uap, path), p);
1.63 christos 1565: if ((error = namei(&nd)) != 0)
1.31 cgd 1566: return (error);
1567: vp = nd.ni_vp;
1568:
1.66 mycroft 1569: /*
1570: * The root of a mounted filesystem cannot be deleted.
1571: */
1572: if (vp->v_flag & VROOT) {
1.43 mycroft 1573: VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1574: if (nd.ni_dvp == vp)
1575: vrele(nd.ni_dvp);
1576: else
1577: vput(nd.ni_dvp);
1.66 mycroft 1578: vput(vp);
1579: error = EBUSY;
1580: goto out;
1.31 cgd 1581: }
1.66 mycroft 1582:
1.110 mrg 1583: (void)uvm_vnp_uncache(vp);
1.69 fvdl 1584:
1.66 mycroft 1585: VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1.67 mycroft 1586: VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.66 mycroft 1587: error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1588: out:
1.31 cgd 1589: return (error);
1590: }
1591:
1592: /*
1593: * Reposition read/write file offset.
1594: */
1.63 christos 1595: int
1.57 mycroft 1596: sys_lseek(p, v, retval)
1.31 cgd 1597: struct proc *p;
1.56 thorpej 1598: void *v;
1599: register_t *retval;
1600: {
1.155 augustss 1601: struct sys_lseek_args /* {
1.35 cgd 1602: syscallarg(int) fd;
1603: syscallarg(int) pad;
1604: syscallarg(off_t) offset;
1605: syscallarg(int) whence;
1.56 thorpej 1606: } */ *uap = v;
1.31 cgd 1607: struct ucred *cred = p->p_ucred;
1.155 augustss 1608: struct filedesc *fdp = p->p_fd;
1609: struct file *fp;
1.84 kleink 1610: struct vnode *vp;
1.31 cgd 1611: struct vattr vattr;
1.155 augustss 1612: off_t newoff;
1.31 cgd 1613: int error;
1614:
1.35 cgd 1615: if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
1.135 thorpej 1616: (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
1617: (fp->f_iflags & FIF_WANTCLOSE) != 0)
1.31 cgd 1618: return (EBADF);
1.84 kleink 1619:
1.135 thorpej 1620: FILE_USE(fp);
1621:
1.84 kleink 1622: vp = (struct vnode *)fp->f_data;
1.135 thorpej 1623: if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
1624: error = ESPIPE;
1625: goto out;
1626: }
1.84 kleink 1627:
1.35 cgd 1628: switch (SCARG(uap, whence)) {
1.92 kleink 1629: case SEEK_CUR:
1.84 kleink 1630: newoff = fp->f_offset + SCARG(uap, offset);
1.31 cgd 1631: break;
1.92 kleink 1632: case SEEK_END:
1.85 kleink 1633: error = VOP_GETATTR(vp, &vattr, cred, p);
1.63 christos 1634: if (error)
1.135 thorpej 1635: goto out;
1.84 kleink 1636: newoff = SCARG(uap, offset) + vattr.va_size;
1.31 cgd 1637: break;
1.92 kleink 1638: case SEEK_SET:
1.84 kleink 1639: newoff = SCARG(uap, offset);
1.31 cgd 1640: break;
1641: default:
1.135 thorpej 1642: error = EINVAL;
1643: goto out;
1.31 cgd 1644: }
1.84 kleink 1645: if ((error = VOP_SEEK(vp, fp->f_offset, newoff, cred)) != 0)
1.135 thorpej 1646: goto out;
1.84 kleink 1647:
1648: *(off_t *)retval = fp->f_offset = newoff;
1.135 thorpej 1649: out:
1650: FILE_UNUSE(fp, p);
1651: return (error);
1.120 thorpej 1652: }
1653:
1654: /*
1655: * Positional read system call.
1656: */
1657: int
1658: sys_pread(p, v, retval)
1659: struct proc *p;
1660: void *v;
1661: register_t *retval;
1662: {
1663: struct sys_pread_args /* {
1664: syscallarg(int) fd;
1665: syscallarg(void *) buf;
1666: syscallarg(size_t) nbyte;
1667: syscallarg(off_t) offset;
1668: } */ *uap = v;
1669: struct filedesc *fdp = p->p_fd;
1670: struct file *fp;
1671: struct vnode *vp;
1672: off_t offset;
1673: int error, fd = SCARG(uap, fd);
1674:
1675: if ((u_int)fd >= fdp->fd_nfiles ||
1676: (fp = fdp->fd_ofiles[fd]) == NULL ||
1.135 thorpej 1677: (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
1.120 thorpej 1678: (fp->f_flag & FREAD) == 0)
1679: return (EBADF);
1680:
1.135 thorpej 1681: FILE_USE(fp);
1682:
1.120 thorpej 1683: vp = (struct vnode *)fp->f_data;
1.135 thorpej 1684: if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
1685: error = ESPIPE;
1686: goto out;
1687: }
1.120 thorpej 1688:
1689: offset = SCARG(uap, offset);
1690:
1691: /*
1692: * XXX This works because no file systems actually
1693: * XXX take any action on the seek operation.
1694: */
1695: if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1.135 thorpej 1696: goto out;
1.120 thorpej 1697:
1.135 thorpej 1698: /* dofileread() will unuse the descriptor for us */
1.120 thorpej 1699: return (dofileread(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
1700: &offset, 0, retval));
1.135 thorpej 1701:
1702: out:
1703: FILE_UNUSE(fp, p);
1704: return (error);
1.120 thorpej 1705: }
1706:
1707: /*
1708: * Positional scatter read system call.
1709: */
1710: int
1711: sys_preadv(p, v, retval)
1712: struct proc *p;
1713: void *v;
1714: register_t *retval;
1715: {
1716: struct sys_preadv_args /* {
1717: syscallarg(int) fd;
1718: syscallarg(const struct iovec *) iovp;
1719: syscallarg(int) iovcnt;
1720: syscallarg(off_t) offset;
1721: } */ *uap = v;
1722: struct filedesc *fdp = p->p_fd;
1723: struct file *fp;
1724: struct vnode *vp;
1725: off_t offset;
1726: int error, fd = SCARG(uap, fd);
1727:
1728: if ((u_int)fd >= fdp->fd_nfiles ||
1729: (fp = fdp->fd_ofiles[fd]) == NULL ||
1.135 thorpej 1730: (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
1.120 thorpej 1731: (fp->f_flag & FREAD) == 0)
1732: return (EBADF);
1733:
1.135 thorpej 1734: FILE_USE(fp);
1735:
1.120 thorpej 1736: vp = (struct vnode *)fp->f_data;
1.135 thorpej 1737: if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
1738: error = ESPIPE;
1739: goto out;
1740: }
1.120 thorpej 1741:
1742: offset = SCARG(uap, offset);
1743:
1744: /*
1745: * XXX This works because no file systems actually
1746: * XXX take any action on the seek operation.
1747: */
1748: if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1.135 thorpej 1749: goto out;
1.120 thorpej 1750:
1.135 thorpej 1751: /* dofilereadv() will unuse the descriptor for us */
1.120 thorpej 1752: return (dofilereadv(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
1753: &offset, 0, retval));
1.135 thorpej 1754:
1755: out:
1756: FILE_UNUSE(fp, p);
1757: return (error);
1.120 thorpej 1758: }
1759:
1760: /*
1761: * Positional write system call.
1762: */
1763: int
1764: sys_pwrite(p, v, retval)
1765: struct proc *p;
1766: void *v;
1767: register_t *retval;
1768: {
1769: struct sys_pwrite_args /* {
1770: syscallarg(int) fd;
1771: syscallarg(const void *) buf;
1772: syscallarg(size_t) nbyte;
1773: syscallarg(off_t) offset;
1774: } */ *uap = v;
1775: struct filedesc *fdp = p->p_fd;
1776: struct file *fp;
1777: struct vnode *vp;
1778: off_t offset;
1779: int error, fd = SCARG(uap, fd);
1780:
1781: if ((u_int)fd >= fdp->fd_nfiles ||
1782: (fp = fdp->fd_ofiles[fd]) == NULL ||
1.135 thorpej 1783: (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
1.120 thorpej 1784: (fp->f_flag & FWRITE) == 0)
1785: return (EBADF);
1786:
1.135 thorpej 1787: FILE_USE(fp);
1788:
1.120 thorpej 1789: vp = (struct vnode *)fp->f_data;
1.135 thorpej 1790: if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
1791: error = ESPIPE;
1792: goto out;
1793: }
1.120 thorpej 1794:
1795: offset = SCARG(uap, offset);
1796:
1797: /*
1798: * XXX This works because no file systems actually
1799: * XXX take any action on the seek operation.
1800: */
1801: if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1.135 thorpej 1802: goto out;
1.120 thorpej 1803:
1.135 thorpej 1804: /* dofilewrite() will unuse the descriptor for us */
1.120 thorpej 1805: return (dofilewrite(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
1806: &offset, 0, retval));
1.135 thorpej 1807:
1808: out:
1809: FILE_UNUSE(fp, p);
1810: return (error);
1.120 thorpej 1811: }
1812:
1813: /*
1814: * Positional gather write system call.
1815: */
1816: int
1817: sys_pwritev(p, v, retval)
1818: struct proc *p;
1819: void *v;
1820: register_t *retval;
1821: {
1822: struct sys_pwritev_args /* {
1823: syscallarg(int) fd;
1824: syscallarg(const struct iovec *) iovp;
1825: syscallarg(int) iovcnt;
1826: syscallarg(off_t) offset;
1827: } */ *uap = v;
1828: struct filedesc *fdp = p->p_fd;
1829: struct file *fp;
1830: struct vnode *vp;
1831: off_t offset;
1832: int error, fd = SCARG(uap, fd);
1833:
1834: if ((u_int)fd >= fdp->fd_nfiles ||
1835: (fp = fdp->fd_ofiles[fd]) == NULL ||
1.135 thorpej 1836: (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
1.120 thorpej 1837: (fp->f_flag & FWRITE) == 0)
1838: return (EBADF);
1839:
1.135 thorpej 1840: FILE_USE(fp);
1841:
1.120 thorpej 1842: vp = (struct vnode *)fp->f_data;
1.135 thorpej 1843: if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
1844: error = ESPIPE;
1845: goto out;
1846: }
1.120 thorpej 1847:
1848: offset = SCARG(uap, offset);
1849:
1850: /*
1851: * XXX This works because no file systems actually
1852: * XXX take any action on the seek operation.
1853: */
1854: if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1.135 thorpej 1855: goto out;
1.120 thorpej 1856:
1.135 thorpej 1857: /* dofilewritev() will unuse the descriptor for us */
1.120 thorpej 1858: return (dofilewritev(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
1859: &offset, 0, retval));
1.135 thorpej 1860:
1861: out:
1862: FILE_UNUSE(fp, p);
1863: return (error);
1.31 cgd 1864: }
1865:
1866: /*
1867: * Check access permissions.
1868: */
1.63 christos 1869: int
1.57 mycroft 1870: sys_access(p, v, retval)
1.31 cgd 1871: struct proc *p;
1.56 thorpej 1872: void *v;
1873: register_t *retval;
1874: {
1.155 augustss 1875: struct sys_access_args /* {
1.74 cgd 1876: syscallarg(const char *) path;
1.35 cgd 1877: syscallarg(int) flags;
1.56 thorpej 1878: } */ *uap = v;
1.155 augustss 1879: struct ucred *cred = p->p_ucred;
1880: struct vnode *vp;
1.31 cgd 1881: int error, flags, t_gid, t_uid;
1882: struct nameidata nd;
1883:
1884: t_uid = cred->cr_uid;
1.53 jtc 1885: t_gid = cred->cr_gid;
1.31 cgd 1886: cred->cr_uid = p->p_cred->p_ruid;
1.53 jtc 1887: cred->cr_gid = p->p_cred->p_rgid;
1.35 cgd 1888: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1889: SCARG(uap, path), p);
1.63 christos 1890: if ((error = namei(&nd)) != 0)
1.31 cgd 1891: goto out1;
1892: vp = nd.ni_vp;
1893:
1894: /* Flags == 0 means only check for existence. */
1.35 cgd 1895: if (SCARG(uap, flags)) {
1.31 cgd 1896: flags = 0;
1.35 cgd 1897: if (SCARG(uap, flags) & R_OK)
1.31 cgd 1898: flags |= VREAD;
1.35 cgd 1899: if (SCARG(uap, flags) & W_OK)
1.31 cgd 1900: flags |= VWRITE;
1.89 mycroft 1901: if (SCARG(uap, flags) & X_OK)
1902: flags |= VEXEC;
1.138 is 1903:
1904: error = VOP_ACCESS(vp, flags, cred, p);
1905: if (!error && (flags & VWRITE))
1906: error = vn_writechk(vp);
1.31 cgd 1907: }
1908: vput(vp);
1909: out1:
1910: cred->cr_uid = t_uid;
1.53 jtc 1911: cred->cr_gid = t_gid;
1.31 cgd 1912: return (error);
1913: }
1914:
1915: /*
1916: * Get file status; this version follows links.
1917: */
1918: /* ARGSUSED */
1.63 christos 1919: int
1.105 thorpej 1920: sys___stat13(p, v, retval)
1.31 cgd 1921: struct proc *p;
1.56 thorpej 1922: void *v;
1923: register_t *retval;
1924: {
1.155 augustss 1925: struct sys___stat13_args /* {
1.74 cgd 1926: syscallarg(const char *) path;
1.35 cgd 1927: syscallarg(struct stat *) ub;
1.56 thorpej 1928: } */ *uap = v;
1.31 cgd 1929: struct stat sb;
1930: int error;
1931: struct nameidata nd;
1932:
1.35 cgd 1933: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1934: SCARG(uap, path), p);
1.63 christos 1935: if ((error = namei(&nd)) != 0)
1.31 cgd 1936: return (error);
1937: error = vn_stat(nd.ni_vp, &sb, p);
1938: vput(nd.ni_vp);
1939: if (error)
1940: return (error);
1.122 perry 1941: error = copyout(&sb, SCARG(uap, ub), sizeof(sb));
1.31 cgd 1942: return (error);
1943: }
1944:
1945: /*
1946: * Get file status; this version does not follow links.
1947: */
1948: /* ARGSUSED */
1.63 christos 1949: int
1.105 thorpej 1950: sys___lstat13(p, v, retval)
1.31 cgd 1951: struct proc *p;
1.56 thorpej 1952: void *v;
1953: register_t *retval;
1954: {
1.155 augustss 1955: struct sys___lstat13_args /* {
1.74 cgd 1956: syscallarg(const char *) path;
1.35 cgd 1957: syscallarg(struct stat *) ub;
1.56 thorpej 1958: } */ *uap = v;
1.65 mycroft 1959: struct stat sb;
1.31 cgd 1960: int error;
1961: struct nameidata nd;
1962:
1.65 mycroft 1963: NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
1.35 cgd 1964: SCARG(uap, path), p);
1.63 christos 1965: if ((error = namei(&nd)) != 0)
1.31 cgd 1966: return (error);
1.65 mycroft 1967: error = vn_stat(nd.ni_vp, &sb, p);
1968: vput(nd.ni_vp);
1.64 jtc 1969: if (error)
1970: return (error);
1.122 perry 1971: error = copyout(&sb, SCARG(uap, ub), sizeof(sb));
1.31 cgd 1972: return (error);
1973: }
1974:
1975: /*
1976: * Get configurable pathname variables.
1977: */
1978: /* ARGSUSED */
1.63 christos 1979: int
1.57 mycroft 1980: sys_pathconf(p, v, retval)
1.31 cgd 1981: struct proc *p;
1.56 thorpej 1982: void *v;
1983: register_t *retval;
1984: {
1.155 augustss 1985: struct sys_pathconf_args /* {
1.74 cgd 1986: syscallarg(const char *) path;
1.35 cgd 1987: syscallarg(int) name;
1.56 thorpej 1988: } */ *uap = v;
1.31 cgd 1989: int error;
1990: struct nameidata nd;
1991:
1.35 cgd 1992: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1993: SCARG(uap, path), p);
1.63 christos 1994: if ((error = namei(&nd)) != 0)
1.31 cgd 1995: return (error);
1.35 cgd 1996: error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
1.31 cgd 1997: vput(nd.ni_vp);
1998: return (error);
1999: }
2000:
2001: /*
2002: * Return target name of a symbolic link.
2003: */
2004: /* ARGSUSED */
1.63 christos 2005: int
1.57 mycroft 2006: sys_readlink(p, v, retval)
1.31 cgd 2007: struct proc *p;
1.56 thorpej 2008: void *v;
2009: register_t *retval;
2010: {
1.155 augustss 2011: struct sys_readlink_args /* {
1.74 cgd 2012: syscallarg(const char *) path;
1.35 cgd 2013: syscallarg(char *) buf;
1.115 kleink 2014: syscallarg(size_t) count;
1.56 thorpej 2015: } */ *uap = v;
1.155 augustss 2016: struct vnode *vp;
1.31 cgd 2017: struct iovec aiov;
2018: struct uio auio;
2019: int error;
2020: struct nameidata nd;
2021:
1.35 cgd 2022: NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
2023: SCARG(uap, path), p);
1.63 christos 2024: if ((error = namei(&nd)) != 0)
1.31 cgd 2025: return (error);
2026: vp = nd.ni_vp;
2027: if (vp->v_type != VLNK)
2028: error = EINVAL;
1.106 enami 2029: else if (!(vp->v_mount->mnt_flag & MNT_SYMPERM) ||
2030: (error = VOP_ACCESS(vp, VREAD, p->p_ucred, p)) == 0) {
1.35 cgd 2031: aiov.iov_base = SCARG(uap, buf);
2032: aiov.iov_len = SCARG(uap, count);
1.31 cgd 2033: auio.uio_iov = &aiov;
2034: auio.uio_iovcnt = 1;
2035: auio.uio_offset = 0;
2036: auio.uio_rw = UIO_READ;
2037: auio.uio_segflg = UIO_USERSPACE;
2038: auio.uio_procp = p;
1.35 cgd 2039: auio.uio_resid = SCARG(uap, count);
1.31 cgd 2040: error = VOP_READLINK(vp, &auio, p->p_ucred);
2041: }
2042: vput(vp);
1.35 cgd 2043: *retval = SCARG(uap, count) - auio.uio_resid;
1.31 cgd 2044: return (error);
2045: }
2046:
2047: /*
2048: * Change flags of a file given a path name.
2049: */
2050: /* ARGSUSED */
1.63 christos 2051: int
1.57 mycroft 2052: sys_chflags(p, v, retval)
1.31 cgd 2053: struct proc *p;
1.56 thorpej 2054: void *v;
2055: register_t *retval;
2056: {
1.155 augustss 2057: struct sys_chflags_args /* {
1.74 cgd 2058: syscallarg(const char *) path;
2059: syscallarg(u_long) flags;
1.56 thorpej 2060: } */ *uap = v;
1.155 augustss 2061: struct vnode *vp;
1.31 cgd 2062: struct vattr vattr;
2063: int error;
2064: struct nameidata nd;
2065:
1.35 cgd 2066: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.63 christos 2067: if ((error = namei(&nd)) != 0)
1.31 cgd 2068: return (error);
2069: vp = nd.ni_vp;
1.42 mycroft 2070: VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.113 fvdl 2071: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.146 christos 2072: /* Non-superusers cannot change the flags on devices, even if they
2073: own them. */
2074: if (suser(p->p_ucred, &p->p_acflag)) {
2075: if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
2076: goto out;
2077: if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
2078: error = EINVAL;
2079: goto out;
2080: }
2081: }
1.113 fvdl 2082: VATTR_NULL(&vattr);
2083: vattr.va_flags = SCARG(uap, flags);
2084: error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1.146 christos 2085: out:
1.31 cgd 2086: vput(vp);
2087: return (error);
2088: }
2089:
2090: /*
2091: * Change flags of a file given a file descriptor.
2092: */
2093: /* ARGSUSED */
1.63 christos 2094: int
1.57 mycroft 2095: sys_fchflags(p, v, retval)
1.31 cgd 2096: struct proc *p;
1.56 thorpej 2097: void *v;
2098: register_t *retval;
2099: {
1.155 augustss 2100: struct sys_fchflags_args /* {
1.35 cgd 2101: syscallarg(int) fd;
1.74 cgd 2102: syscallarg(u_long) flags;
1.56 thorpej 2103: } */ *uap = v;
1.31 cgd 2104: struct vattr vattr;
2105: struct vnode *vp;
2106: struct file *fp;
2107: int error;
2108:
1.135 thorpej 2109: /* getvnode() will use the descriptor for us */
1.63 christos 2110: if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1.31 cgd 2111: return (error);
1.62 mycroft 2112: vp = (struct vnode *)fp->f_data;
1.42 mycroft 2113: VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.113 fvdl 2114: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.146 christos 2115: /* Non-superusers cannot change the flags on devices, even if they
2116: own them. */
2117: if (suser(p->p_ucred, &p->p_acflag)) {
2118: if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
2119: != 0)
2120: goto out;
2121: if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
2122: error = EINVAL;
2123: goto out;
2124: }
2125: }
1.113 fvdl 2126: VATTR_NULL(&vattr);
2127: vattr.va_flags = SCARG(uap, flags);
2128: error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1.146 christos 2129: out:
1.113 fvdl 2130: VOP_UNLOCK(vp, 0);
1.135 thorpej 2131: FILE_UNUSE(fp, p);
1.156 mrg 2132: return (error);
2133: }
2134:
2135: /*
2136: * Change flags of a file given a file descriptor; this version does
2137: * not follow links.
2138: */
2139: int
2140: sys_lchflags(p, v, retval)
2141: struct proc *p;
2142: void *v;
2143: register_t *retval;
2144: {
2145: register struct sys_chflags_args /* {
2146: syscallarg(const char *) path;
2147: syscallarg(u_long) flags;
2148: } */ *uap = v;
2149: register struct vnode *vp;
2150: struct vattr vattr;
2151: int error;
2152: struct nameidata nd;
2153:
2154: NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2155: if ((error = namei(&nd)) != 0)
2156: return (error);
2157: vp = nd.ni_vp;
2158: VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2159: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2160: /* Non-superusers cannot change the flags on devices, even if they
2161: own them. */
2162: if (suser(p->p_ucred, &p->p_acflag)) {
2163: if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
2164: goto out;
2165: if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
2166: error = EINVAL;
2167: goto out;
2168: }
2169: }
2170: VATTR_NULL(&vattr);
2171: vattr.va_flags = SCARG(uap, flags);
2172: error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2173: out:
2174: vput(vp);
1.31 cgd 2175: return (error);
2176: }
2177:
2178: /*
1.98 enami 2179: * Change mode of a file given path name; this version follows links.
1.31 cgd 2180: */
2181: /* ARGSUSED */
1.63 christos 2182: int
1.57 mycroft 2183: sys_chmod(p, v, retval)
1.31 cgd 2184: struct proc *p;
1.56 thorpej 2185: void *v;
2186: register_t *retval;
2187: {
1.155 augustss 2188: struct sys_chmod_args /* {
1.74 cgd 2189: syscallarg(const char *) path;
1.35 cgd 2190: syscallarg(int) mode;
1.56 thorpej 2191: } */ *uap = v;
1.31 cgd 2192: int error;
2193: struct nameidata nd;
2194:
1.35 cgd 2195: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.63 christos 2196: if ((error = namei(&nd)) != 0)
1.31 cgd 2197: return (error);
1.97 enami 2198:
2199: error = change_mode(nd.ni_vp, SCARG(uap, mode), p);
2200:
2201: vrele(nd.ni_vp);
1.31 cgd 2202: return (error);
2203: }
2204:
2205: /*
2206: * Change mode of a file given a file descriptor.
2207: */
2208: /* ARGSUSED */
1.63 christos 2209: int
1.57 mycroft 2210: sys_fchmod(p, v, retval)
1.31 cgd 2211: struct proc *p;
1.56 thorpej 2212: void *v;
2213: register_t *retval;
2214: {
1.155 augustss 2215: struct sys_fchmod_args /* {
1.35 cgd 2216: syscallarg(int) fd;
2217: syscallarg(int) mode;
1.56 thorpej 2218: } */ *uap = v;
1.31 cgd 2219: struct file *fp;
2220: int error;
2221:
1.135 thorpej 2222: /* getvnode() will use the descriptor for us */
1.63 christos 2223: if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1.31 cgd 2224: return (error);
1.97 enami 2225:
1.135 thorpej 2226: error = change_mode((struct vnode *)fp->f_data, SCARG(uap, mode), p);
2227: FILE_UNUSE(fp, p);
2228: return (error);
1.97 enami 2229: }
2230:
2231: /*
1.98 enami 2232: * Change mode of a file given path name; this version does not follow links.
2233: */
2234: /* ARGSUSED */
2235: int
2236: sys_lchmod(p, v, retval)
2237: struct proc *p;
2238: void *v;
2239: register_t *retval;
2240: {
1.155 augustss 2241: struct sys_lchmod_args /* {
1.98 enami 2242: syscallarg(const char *) path;
2243: syscallarg(int) mode;
2244: } */ *uap = v;
2245: int error;
2246: struct nameidata nd;
2247:
2248: NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2249: if ((error = namei(&nd)) != 0)
2250: return (error);
2251:
2252: error = change_mode(nd.ni_vp, SCARG(uap, mode), p);
2253:
2254: vrele(nd.ni_vp);
2255: return (error);
2256: }
2257:
2258: /*
1.97 enami 2259: * Common routine to set mode given a vnode.
2260: */
2261: static int
2262: change_mode(vp, mode, p)
2263: struct vnode *vp;
2264: int mode;
2265: struct proc *p;
2266: {
2267: struct vattr vattr;
2268: int error;
2269:
1.42 mycroft 2270: VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.113 fvdl 2271: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2272: VATTR_NULL(&vattr);
2273: vattr.va_mode = mode & ALLPERMS;
2274: error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2275: VOP_UNLOCK(vp, 0);
1.31 cgd 2276: return (error);
2277: }
2278:
2279: /*
1.98 enami 2280: * Set ownership given a path name; this version follows links.
1.31 cgd 2281: */
2282: /* ARGSUSED */
1.63 christos 2283: int
1.57 mycroft 2284: sys_chown(p, v, retval)
1.31 cgd 2285: struct proc *p;
1.56 thorpej 2286: void *v;
2287: register_t *retval;
2288: {
1.155 augustss 2289: struct sys_chown_args /* {
1.74 cgd 2290: syscallarg(const char *) path;
2291: syscallarg(uid_t) uid;
2292: syscallarg(gid_t) gid;
1.56 thorpej 2293: } */ *uap = v;
1.31 cgd 2294: int error;
2295: struct nameidata nd;
2296:
1.35 cgd 2297: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.63 christos 2298: if ((error = namei(&nd)) != 0)
1.31 cgd 2299: return (error);
1.86 kleink 2300:
1.112 kleink 2301: error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 0);
2302:
2303: vrele(nd.ni_vp);
2304: return (error);
2305: }
2306:
2307: /*
2308: * Set ownership given a path name; this version follows links.
2309: * Provides POSIX semantics.
2310: */
2311: /* ARGSUSED */
2312: int
2313: sys___posix_chown(p, v, retval)
2314: struct proc *p;
2315: void *v;
2316: register_t *retval;
2317: {
1.155 augustss 2318: struct sys_chown_args /* {
1.112 kleink 2319: syscallarg(const char *) path;
2320: syscallarg(uid_t) uid;
2321: syscallarg(gid_t) gid;
2322: } */ *uap = v;
2323: int error;
2324: struct nameidata nd;
2325:
2326: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2327: if ((error = namei(&nd)) != 0)
2328: return (error);
2329:
2330: error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 1);
1.86 kleink 2331:
2332: vrele(nd.ni_vp);
1.31 cgd 2333: return (error);
2334: }
2335:
2336: /*
2337: * Set ownership given a file descriptor.
2338: */
2339: /* ARGSUSED */
1.63 christos 2340: int
1.57 mycroft 2341: sys_fchown(p, v, retval)
1.31 cgd 2342: struct proc *p;
1.56 thorpej 2343: void *v;
2344: register_t *retval;
2345: {
1.155 augustss 2346: struct sys_fchown_args /* {
1.35 cgd 2347: syscallarg(int) fd;
1.74 cgd 2348: syscallarg(uid_t) uid;
2349: syscallarg(gid_t) gid;
1.56 thorpej 2350: } */ *uap = v;
1.71 mycroft 2351: int error;
1.31 cgd 2352: struct file *fp;
2353:
1.135 thorpej 2354: /* getvnode() will use the descriptor for us */
1.63 christos 2355: if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1.31 cgd 2356: return (error);
1.86 kleink 2357:
1.135 thorpej 2358: error = change_owner((struct vnode *)fp->f_data, SCARG(uap, uid),
2359: SCARG(uap, gid), p, 0);
2360: FILE_UNUSE(fp, p);
2361: return (error);
1.112 kleink 2362: }
2363:
2364: /*
2365: * Set ownership given a file descriptor, providing POSIX/XPG semantics.
2366: */
2367: /* ARGSUSED */
2368: int
2369: sys___posix_fchown(p, v, retval)
2370: struct proc *p;
2371: void *v;
2372: register_t *retval;
2373: {
1.155 augustss 2374: struct sys_fchown_args /* {
1.112 kleink 2375: syscallarg(int) fd;
2376: syscallarg(uid_t) uid;
2377: syscallarg(gid_t) gid;
2378: } */ *uap = v;
2379: int error;
2380: struct file *fp;
2381:
1.135 thorpej 2382: /* getvnode() will use the descriptor for us */
1.112 kleink 2383: if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2384: return (error);
2385:
1.135 thorpej 2386: error = change_owner((struct vnode *)fp->f_data, SCARG(uap, uid),
2387: SCARG(uap, gid), p, 1);
2388: FILE_UNUSE(fp, p);
2389: return (error);
1.86 kleink 2390: }
2391:
2392: /*
1.98 enami 2393: * Set ownership given a path name; this version does not follow links.
2394: */
2395: /* ARGSUSED */
2396: int
2397: sys_lchown(p, v, retval)
2398: struct proc *p;
2399: void *v;
2400: register_t *retval;
2401: {
1.155 augustss 2402: struct sys_lchown_args /* {
1.98 enami 2403: syscallarg(const char *) path;
2404: syscallarg(uid_t) uid;
2405: syscallarg(gid_t) gid;
2406: } */ *uap = v;
2407: int error;
2408: struct nameidata nd;
2409:
2410: NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2411: if ((error = namei(&nd)) != 0)
2412: return (error);
2413:
1.112 kleink 2414: error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 0);
2415:
2416: vrele(nd.ni_vp);
2417: return (error);
2418: }
2419:
2420: /*
2421: * Set ownership given a path name; this version does not follow links.
2422: * Provides POSIX/XPG semantics.
2423: */
2424: /* ARGSUSED */
2425: int
2426: sys___posix_lchown(p, v, retval)
2427: struct proc *p;
2428: void *v;
2429: register_t *retval;
2430: {
1.155 augustss 2431: struct sys_lchown_args /* {
1.112 kleink 2432: syscallarg(const char *) path;
2433: syscallarg(uid_t) uid;
2434: syscallarg(gid_t) gid;
2435: } */ *uap = v;
2436: int error;
2437: struct nameidata nd;
2438:
2439: NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2440: if ((error = namei(&nd)) != 0)
2441: return (error);
2442:
2443: error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 1);
1.98 enami 2444:
2445: vrele(nd.ni_vp);
2446: return (error);
2447: }
2448:
2449: /*
1.112 kleink 2450: * Common routine to set ownership given a vnode.
1.86 kleink 2451: */
2452: static int
1.112 kleink 2453: change_owner(vp, uid, gid, p, posix_semantics)
1.155 augustss 2454: struct vnode *vp;
1.86 kleink 2455: uid_t uid;
2456: gid_t gid;
2457: struct proc *p;
1.112 kleink 2458: int posix_semantics;
1.86 kleink 2459: {
2460: struct vattr vattr;
1.112 kleink 2461: mode_t newmode;
1.86 kleink 2462: int error;
2463:
1.42 mycroft 2464: VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.113 fvdl 2465: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.93 enami 2466: if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
1.86 kleink 2467: goto out;
2468:
1.112 kleink 2469: #define CHANGED(x) ((x) != -1)
2470: newmode = vattr.va_mode;
2471: if (posix_semantics) {
2472: /*
1.114 kleink 2473: * POSIX/XPG semantics: if the caller is not the super-user,
2474: * clear set-user-id and set-group-id bits. Both POSIX and
2475: * the XPG consider the behaviour for calls by the super-user
2476: * implementation-defined; we leave the set-user-id and set-
2477: * group-id settings intact in that case.
1.112 kleink 2478: */
2479: if (suser(p->p_ucred, NULL) != 0)
2480: newmode &= ~(S_ISUID | S_ISGID);
2481: } else {
2482: /*
2483: * NetBSD semantics: when changing owner and/or group,
2484: * clear the respective bit(s).
2485: */
2486: if (CHANGED(uid))
2487: newmode &= ~S_ISUID;
2488: if (CHANGED(gid))
2489: newmode &= ~S_ISGID;
2490: }
2491: /* Update va_mode iff altered. */
2492: if (vattr.va_mode == newmode)
2493: newmode = VNOVAL;
2494:
1.86 kleink 2495: VATTR_NULL(&vattr);
1.112 kleink 2496: vattr.va_uid = CHANGED(uid) ? uid : VNOVAL;
2497: vattr.va_gid = CHANGED(gid) ? gid : VNOVAL;
1.86 kleink 2498: vattr.va_mode = newmode;
2499: error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1.112 kleink 2500: #undef CHANGED
2501:
1.86 kleink 2502: out:
1.113 fvdl 2503: VOP_UNLOCK(vp, 0);
1.31 cgd 2504: return (error);
2505: }
2506:
2507: /*
1.98 enami 2508: * Set the access and modification times given a path name; this
2509: * version follows links.
1.31 cgd 2510: */
2511: /* ARGSUSED */
1.63 christos 2512: int
1.57 mycroft 2513: sys_utimes(p, v, retval)
1.31 cgd 2514: struct proc *p;
1.56 thorpej 2515: void *v;
2516: register_t *retval;
2517: {
1.155 augustss 2518: struct sys_utimes_args /* {
1.74 cgd 2519: syscallarg(const char *) path;
2520: syscallarg(const struct timeval *) tptr;
1.56 thorpej 2521: } */ *uap = v;
1.31 cgd 2522: int error;
2523: struct nameidata nd;
2524:
1.96 enami 2525: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2526: if ((error = namei(&nd)) != 0)
2527: return (error);
1.97 enami 2528:
2529: error = change_utimes(nd.ni_vp, SCARG(uap, tptr), p);
2530:
2531: vrele(nd.ni_vp);
1.71 mycroft 2532: return (error);
2533: }
2534:
2535: /*
2536: * Set the access and modification times given a file descriptor.
2537: */
2538: /* ARGSUSED */
2539: int
2540: sys_futimes(p, v, retval)
2541: struct proc *p;
2542: void *v;
2543: register_t *retval;
2544: {
1.155 augustss 2545: struct sys_futimes_args /* {
1.71 mycroft 2546: syscallarg(int) fd;
1.74 cgd 2547: syscallarg(const struct timeval *) tptr;
1.71 mycroft 2548: } */ *uap = v;
2549: int error;
2550: struct file *fp;
2551:
1.135 thorpej 2552: /* getvnode() will use the descriptor for us */
1.96 enami 2553: if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2554: return (error);
1.97 enami 2555:
1.135 thorpej 2556: error = change_utimes((struct vnode *)fp->f_data, SCARG(uap, tptr), p);
2557: FILE_UNUSE(fp, p);
2558: return (error);
1.98 enami 2559: }
2560:
2561: /*
2562: * Set the access and modification times given a path name; this
2563: * version does not follow links.
2564: */
2565: /* ARGSUSED */
2566: int
2567: sys_lutimes(p, v, retval)
2568: struct proc *p;
2569: void *v;
2570: register_t *retval;
2571: {
1.155 augustss 2572: struct sys_lutimes_args /* {
1.98 enami 2573: syscallarg(const char *) path;
2574: syscallarg(const struct timeval *) tptr;
2575: } */ *uap = v;
2576: int error;
2577: struct nameidata nd;
2578:
2579: NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2580: if ((error = namei(&nd)) != 0)
2581: return (error);
2582:
2583: error = change_utimes(nd.ni_vp, SCARG(uap, tptr), p);
2584:
2585: vrele(nd.ni_vp);
2586: return (error);
1.97 enami 2587: }
2588:
2589: /*
2590: * Common routine to set access and modification times given a vnode.
2591: */
2592: static int
2593: change_utimes(vp, tptr, p)
2594: struct vnode *vp;
2595: const struct timeval *tptr;
2596: struct proc *p;
2597: {
2598: struct timeval tv[2];
2599: struct vattr vattr;
2600: int error;
2601:
1.71 mycroft 2602: VATTR_NULL(&vattr);
1.97 enami 2603: if (tptr == NULL) {
1.71 mycroft 2604: microtime(&tv[0]);
2605: tv[1] = tv[0];
2606: vattr.va_vaflags |= VA_UTIMES_NULL;
2607: } else {
1.122 perry 2608: error = copyin(tptr, tv, sizeof(tv));
1.71 mycroft 2609: if (error)
2610: return (error);
2611: }
2612: VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.113 fvdl 2613: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2614: vattr.va_atime.tv_sec = tv[0].tv_sec;
2615: vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
2616: vattr.va_mtime.tv_sec = tv[1].tv_sec;
2617: vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
2618: error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2619: VOP_UNLOCK(vp, 0);
1.31 cgd 2620: return (error);
2621: }
2622:
2623: /*
2624: * Truncate a file given its path name.
2625: */
2626: /* ARGSUSED */
1.63 christos 2627: int
1.57 mycroft 2628: sys_truncate(p, v, retval)
1.31 cgd 2629: struct proc *p;
1.56 thorpej 2630: void *v;
2631: register_t *retval;
2632: {
1.155 augustss 2633: struct sys_truncate_args /* {
1.74 cgd 2634: syscallarg(const char *) path;
1.35 cgd 2635: syscallarg(int) pad;
2636: syscallarg(off_t) length;
1.56 thorpej 2637: } */ *uap = v;
1.155 augustss 2638: struct vnode *vp;
1.31 cgd 2639: struct vattr vattr;
2640: int error;
2641: struct nameidata nd;
2642:
1.35 cgd 2643: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.63 christos 2644: if ((error = namei(&nd)) != 0)
1.31 cgd 2645: return (error);
2646: vp = nd.ni_vp;
1.42 mycroft 2647: VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.113 fvdl 2648: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.31 cgd 2649: if (vp->v_type == VDIR)
2650: error = EISDIR;
2651: else if ((error = vn_writechk(vp)) == 0 &&
2652: (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
2653: VATTR_NULL(&vattr);
1.35 cgd 2654: vattr.va_size = SCARG(uap, length);
1.31 cgd 2655: error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2656: }
2657: vput(vp);
2658: return (error);
2659: }
2660:
2661: /*
2662: * Truncate a file given a file descriptor.
2663: */
2664: /* ARGSUSED */
1.63 christos 2665: int
1.57 mycroft 2666: sys_ftruncate(p, v, retval)
1.31 cgd 2667: struct proc *p;
1.56 thorpej 2668: void *v;
2669: register_t *retval;
2670: {
1.155 augustss 2671: struct sys_ftruncate_args /* {
1.35 cgd 2672: syscallarg(int) fd;
2673: syscallarg(int) pad;
2674: syscallarg(off_t) length;
1.56 thorpej 2675: } */ *uap = v;
1.31 cgd 2676: struct vattr vattr;
2677: struct vnode *vp;
2678: struct file *fp;
2679: int error;
2680:
1.135 thorpej 2681: /* getvnode() will use the descriptor for us */
1.63 christos 2682: if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1.31 cgd 2683: return (error);
1.135 thorpej 2684: if ((fp->f_flag & FWRITE) == 0) {
2685: error = EINVAL;
2686: goto out;
2687: }
1.62 mycroft 2688: vp = (struct vnode *)fp->f_data;
1.42 mycroft 2689: VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.113 fvdl 2690: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.31 cgd 2691: if (vp->v_type == VDIR)
2692: error = EISDIR;
2693: else if ((error = vn_writechk(vp)) == 0) {
2694: VATTR_NULL(&vattr);
1.35 cgd 2695: vattr.va_size = SCARG(uap, length);
1.31 cgd 2696: error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
2697: }
1.113 fvdl 2698: VOP_UNLOCK(vp, 0);
1.135 thorpej 2699: out:
2700: FILE_UNUSE(fp, p);
1.31 cgd 2701: return (error);
2702: }
2703:
2704: /*
2705: * Sync an open file.
2706: */
2707: /* ARGSUSED */
1.63 christos 2708: int
1.57 mycroft 2709: sys_fsync(p, v, retval)
1.31 cgd 2710: struct proc *p;
1.56 thorpej 2711: void *v;
2712: register_t *retval;
2713: {
1.57 mycroft 2714: struct sys_fsync_args /* {
1.35 cgd 2715: syscallarg(int) fd;
1.56 thorpej 2716: } */ *uap = v;
1.155 augustss 2717: struct vnode *vp;
1.31 cgd 2718: struct file *fp;
2719: int error;
2720:
1.135 thorpej 2721: /* getvnode() will use the descriptor for us */
1.63 christos 2722: if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1.31 cgd 2723: return (error);
1.62 mycroft 2724: vp = (struct vnode *)fp->f_data;
1.113 fvdl 2725: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.116 kleink 2726: error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT, p);
1.148 fvdl 2727: if (error == 0 && bioops.io_fsync != NULL &&
2728: vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP))
2729: (*bioops.io_fsync)(vp);
1.113 fvdl 2730: VOP_UNLOCK(vp, 0);
1.135 thorpej 2731: FILE_UNUSE(fp, p);
1.31 cgd 2732: return (error);
2733: }
2734:
2735: /*
1.117 kleink 2736: * Sync the data of an open file.
2737: */
2738: /* ARGSUSED */
2739: int
2740: sys_fdatasync(p, v, retval)
2741: struct proc *p;
2742: void *v;
2743: register_t *retval;
2744: {
2745: struct sys_fdatasync_args /* {
2746: syscallarg(int) fd;
2747: } */ *uap = v;
2748: struct vnode *vp;
2749: struct file *fp;
2750: int error;
2751:
1.135 thorpej 2752: /* getvnode() will use the descriptor for us */
1.117 kleink 2753: if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2754: return (error);
2755: vp = (struct vnode *)fp->f_data;
2756: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2757: error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT|FSYNC_DATAONLY, p);
2758: VOP_UNLOCK(vp, 0);
1.135 thorpej 2759: FILE_UNUSE(fp, p);
1.117 kleink 2760: return (error);
2761: }
2762:
2763: /*
1.90 kleink 2764: * Rename files, (standard) BSD semantics frontend.
1.31 cgd 2765: */
2766: /* ARGSUSED */
1.63 christos 2767: int
1.57 mycroft 2768: sys_rename(p, v, retval)
1.31 cgd 2769: struct proc *p;
1.56 thorpej 2770: void *v;
2771: register_t *retval;
2772: {
1.155 augustss 2773: struct sys_rename_args /* {
1.74 cgd 2774: syscallarg(const char *) from;
2775: syscallarg(const char *) to;
1.56 thorpej 2776: } */ *uap = v;
1.90 kleink 2777:
2778: return (rename_files(SCARG(uap, from), SCARG(uap, to), p, 0));
2779: }
2780:
2781: /*
2782: * Rename files, POSIX semantics frontend.
2783: */
2784: /* ARGSUSED */
2785: int
1.112 kleink 2786: sys___posix_rename(p, v, retval)
1.90 kleink 2787: struct proc *p;
2788: void *v;
2789: register_t *retval;
2790: {
1.155 augustss 2791: struct sys___posix_rename_args /* {
1.90 kleink 2792: syscallarg(const char *) from;
2793: syscallarg(const char *) to;
2794: } */ *uap = v;
2795:
2796: return (rename_files(SCARG(uap, from), SCARG(uap, to), p, 1));
2797: }
2798:
2799: /*
2800: * Rename files. Source and destination must either both be directories,
2801: * or both not be directories. If target is a directory, it must be empty.
2802: * If `from' and `to' refer to the same object, the value of the `retain'
2803: * argument is used to determine whether `from' will be
2804: *
2805: * (retain == 0) deleted unless `from' and `to' refer to the same
2806: * object in the file system's name space (BSD).
2807: * (retain == 1) always retained (POSIX).
2808: */
2809: static int
2810: rename_files(from, to, p, retain)
2811: const char *from, *to;
2812: struct proc *p;
2813: int retain;
2814: {
1.155 augustss 2815: struct vnode *tvp, *fvp, *tdvp;
1.31 cgd 2816: struct nameidata fromnd, tond;
2817: int error;
2818:
2819: NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
1.90 kleink 2820: from, p);
1.63 christos 2821: if ((error = namei(&fromnd)) != 0)
1.31 cgd 2822: return (error);
2823: fvp = fromnd.ni_vp;
2824: NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
1.90 kleink 2825: UIO_USERSPACE, to, p);
1.63 christos 2826: if ((error = namei(&tond)) != 0) {
1.31 cgd 2827: VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2828: vrele(fromnd.ni_dvp);
2829: vrele(fvp);
2830: goto out1;
2831: }
2832: tdvp = tond.ni_dvp;
2833: tvp = tond.ni_vp;
1.90 kleink 2834:
1.31 cgd 2835: if (tvp != NULL) {
2836: if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2837: error = ENOTDIR;
2838: goto out;
2839: } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2840: error = EISDIR;
2841: goto out;
2842: }
2843: }
1.90 kleink 2844:
1.31 cgd 2845: if (fvp == tdvp)
2846: error = EINVAL;
1.90 kleink 2847:
1.82 kleink 2848: /*
1.90 kleink 2849: * Source and destination refer to the same object.
1.82 kleink 2850: */
1.90 kleink 2851: if (fvp == tvp) {
2852: if (retain)
2853: error = -1;
2854: else if (fromnd.ni_dvp == tdvp &&
2855: fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1.123 perry 2856: !memcmp(fromnd.ni_cnd.cn_nameptr,
1.90 kleink 2857: tond.ni_cnd.cn_nameptr,
2858: fromnd.ni_cnd.cn_namelen))
1.82 kleink 2859: error = -1;
1.90 kleink 2860: }
2861:
1.31 cgd 2862: out:
2863: if (!error) {
1.42 mycroft 2864: VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
1.31 cgd 2865: if (fromnd.ni_dvp != tdvp)
1.42 mycroft 2866: VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1.75 fvdl 2867: if (tvp) {
1.110 mrg 2868: (void)uvm_vnp_uncache(tvp);
1.42 mycroft 2869: VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
1.75 fvdl 2870: }
1.31 cgd 2871: error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2872: tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2873: } else {
2874: VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
2875: if (tdvp == tvp)
2876: vrele(tdvp);
2877: else
2878: vput(tdvp);
2879: if (tvp)
2880: vput(tvp);
2881: VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2882: vrele(fromnd.ni_dvp);
2883: vrele(fvp);
2884: }
2885: vrele(tond.ni_startdir);
2886: FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
2887: out1:
2888: if (fromnd.ni_startdir)
2889: vrele(fromnd.ni_startdir);
2890: FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
1.80 kleink 2891: return (error == -1 ? 0 : error);
1.31 cgd 2892: }
2893:
2894: /*
2895: * Make a directory file.
2896: */
2897: /* ARGSUSED */
1.63 christos 2898: int
1.57 mycroft 2899: sys_mkdir(p, v, retval)
1.31 cgd 2900: struct proc *p;
1.56 thorpej 2901: void *v;
2902: register_t *retval;
2903: {
1.155 augustss 2904: struct sys_mkdir_args /* {
1.74 cgd 2905: syscallarg(const char *) path;
1.35 cgd 2906: syscallarg(int) mode;
1.56 thorpej 2907: } */ *uap = v;
1.155 augustss 2908: struct vnode *vp;
1.31 cgd 2909: struct vattr vattr;
2910: int error;
2911: struct nameidata nd;
2912:
1.35 cgd 2913: NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1.63 christos 2914: if ((error = namei(&nd)) != 0)
1.31 cgd 2915: return (error);
2916: vp = nd.ni_vp;
2917: if (vp != NULL) {
2918: VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2919: if (nd.ni_dvp == vp)
2920: vrele(nd.ni_dvp);
2921: else
2922: vput(nd.ni_dvp);
2923: vrele(vp);
2924: return (EEXIST);
2925: }
2926: VATTR_NULL(&vattr);
2927: vattr.va_type = VDIR;
1.134 thorpej 2928: vattr.va_mode =
2929: (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_cwdi->cwdi_cmask;
1.42 mycroft 2930: VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1.31 cgd 2931: error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
2932: if (!error)
2933: vput(nd.ni_vp);
2934: return (error);
2935: }
2936:
2937: /*
2938: * Remove a directory file.
2939: */
2940: /* ARGSUSED */
1.63 christos 2941: int
1.57 mycroft 2942: sys_rmdir(p, v, retval)
1.31 cgd 2943: struct proc *p;
1.56 thorpej 2944: void *v;
2945: register_t *retval;
2946: {
1.57 mycroft 2947: struct sys_rmdir_args /* {
1.74 cgd 2948: syscallarg(const char *) path;
1.56 thorpej 2949: } */ *uap = v;
1.155 augustss 2950: struct vnode *vp;
1.31 cgd 2951: int error;
2952: struct nameidata nd;
2953:
1.35 cgd 2954: NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
2955: SCARG(uap, path), p);
1.63 christos 2956: if ((error = namei(&nd)) != 0)
1.31 cgd 2957: return (error);
2958: vp = nd.ni_vp;
2959: if (vp->v_type != VDIR) {
2960: error = ENOTDIR;
2961: goto out;
2962: }
2963: /*
2964: * No rmdir "." please.
2965: */
2966: if (nd.ni_dvp == vp) {
2967: error = EINVAL;
2968: goto out;
2969: }
2970: /*
2971: * The root of a mounted filesystem cannot be deleted.
2972: */
2973: if (vp->v_flag & VROOT)
2974: error = EBUSY;
2975: out:
2976: if (!error) {
1.42 mycroft 2977: VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2978: VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.31 cgd 2979: error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2980: } else {
2981: VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2982: if (nd.ni_dvp == vp)
2983: vrele(nd.ni_dvp);
2984: else
2985: vput(nd.ni_dvp);
2986: vput(vp);
2987: }
2988: return (error);
2989: }
2990:
2991: /*
2992: * Read a block of directory entries in a file system independent format.
2993: */
1.63 christos 2994: int
1.101 fvdl 2995: sys_getdents(p, v, retval)
1.31 cgd 2996: struct proc *p;
1.56 thorpej 2997: void *v;
2998: register_t *retval;
2999: {
1.155 augustss 3000: struct sys_getdents_args /* {
1.35 cgd 3001: syscallarg(int) fd;
3002: syscallarg(char *) buf;
1.101 fvdl 3003: syscallarg(size_t) count;
1.56 thorpej 3004: } */ *uap = v;
1.31 cgd 3005: struct file *fp;
1.101 fvdl 3006: int error, done;
1.31 cgd 3007:
1.135 thorpej 3008: /* getvnode() will use the descriptor for us */
1.63 christos 3009: if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1.31 cgd 3010: return (error);
1.135 thorpej 3011: if ((fp->f_flag & FREAD) == 0) {
3012: error = EBADF;
3013: goto out;
3014: }
1.101 fvdl 3015: error = vn_readdir(fp, SCARG(uap, buf), UIO_USERSPACE,
3016: SCARG(uap, count), &done, p, 0, 0);
3017: *retval = done;
1.135 thorpej 3018: out:
3019: FILE_UNUSE(fp, p);
1.31 cgd 3020: return (error);
3021: }
3022:
3023: /*
3024: * Set the mode mask for creation of filesystem nodes.
3025: */
1.56 thorpej 3026: int
1.57 mycroft 3027: sys_umask(p, v, retval)
1.31 cgd 3028: struct proc *p;
1.56 thorpej 3029: void *v;
3030: register_t *retval;
3031: {
1.57 mycroft 3032: struct sys_umask_args /* {
1.103 mycroft 3033: syscallarg(mode_t) newmask;
1.56 thorpej 3034: } */ *uap = v;
1.134 thorpej 3035: struct cwdinfo *cwdi;
1.31 cgd 3036:
1.134 thorpej 3037: cwdi = p->p_cwdi;
3038: *retval = cwdi->cwdi_cmask;
3039: cwdi->cwdi_cmask = SCARG(uap, newmask) & ALLPERMS;
1.31 cgd 3040: return (0);
3041: }
3042:
3043: /*
3044: * Void all references to file by ripping underlying filesystem
3045: * away from vnode.
3046: */
3047: /* ARGSUSED */
1.63 christos 3048: int
1.57 mycroft 3049: sys_revoke(p, v, retval)
1.31 cgd 3050: struct proc *p;
1.56 thorpej 3051: void *v;
3052: register_t *retval;
3053: {
1.155 augustss 3054: struct sys_revoke_args /* {
1.74 cgd 3055: syscallarg(const char *) path;
1.56 thorpej 3056: } */ *uap = v;
1.155 augustss 3057: struct vnode *vp;
1.31 cgd 3058: struct vattr vattr;
3059: int error;
3060: struct nameidata nd;
3061:
1.35 cgd 3062: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.63 christos 3063: if ((error = namei(&nd)) != 0)
1.31 cgd 3064: return (error);
3065: vp = nd.ni_vp;
1.63 christos 3066: if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
1.31 cgd 3067: goto out;
3068: if (p->p_ucred->cr_uid != vattr.va_uid &&
1.93 enami 3069: (error = suser(p->p_ucred, &p->p_acflag)) != 0)
1.31 cgd 3070: goto out;
1.145 wrstuden 3071: if (vp->v_usecount > 1 || (vp->v_flag & (VALIASED | VLAYER)))
1.113 fvdl 3072: VOP_REVOKE(vp, REVOKEALL);
1.31 cgd 3073: out:
3074: vrele(vp);
3075: return (error);
3076: }
3077:
3078: /*
3079: * Convert a user file descriptor to a kernel file entry.
3080: */
1.60 mycroft 3081: int
1.62 mycroft 3082: getvnode(fdp, fd, fpp)
1.31 cgd 3083: struct filedesc *fdp;
1.60 mycroft 3084: int fd;
1.31 cgd 3085: struct file **fpp;
3086: {
1.60 mycroft 3087: struct vnode *vp;
1.31 cgd 3088: struct file *fp;
3089:
3090: if ((u_int)fd >= fdp->fd_nfiles ||
1.135 thorpej 3091: (fp = fdp->fd_ofiles[fd]) == NULL ||
3092: (fp->f_iflags & FIF_WANTCLOSE) != 0)
1.31 cgd 3093: return (EBADF);
1.135 thorpej 3094:
3095: FILE_USE(fp);
3096:
3097: if (fp->f_type != DTYPE_VNODE) {
3098: FILE_UNUSE(fp, NULL);
1.31 cgd 3099: return (EINVAL);
1.135 thorpej 3100: }
3101:
1.60 mycroft 3102: vp = (struct vnode *)fp->f_data;
1.135 thorpej 3103: if (vp->v_type == VBAD) {
3104: FILE_UNUSE(fp, NULL);
1.60 mycroft 3105: return (EBADF);
1.135 thorpej 3106: }
3107:
1.31 cgd 3108: *fpp = fp;
3109: return (0);
3110: }
CVSweb <webmaster@jp.NetBSD.org>