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