vfs_syscalls.c revision 1.130 1 /* $NetBSD: vfs_syscalls.c,v 1.130 1999/03/17 15:35:03 bouyer 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. 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 *
40 * @(#)vfs_syscalls.c 8.42 (Berkeley) 7/31/95
41 */
42
43 #include "opt_uvm.h"
44 #include "opt_compat_netbsd.h"
45 #include "opt_compat_43.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
61 #include <sys/syscallargs.h>
62
63 #include <vm/vm.h>
64 #include <sys/sysctl.h>
65
66 #if defined(UVM)
67 #include <uvm/uvm_extern.h>
68 #endif
69
70 static int change_dir __P((struct nameidata *, struct proc *));
71 static int change_mode __P((struct vnode *, int, struct proc *p));
72 static int change_owner __P((struct vnode *, uid_t, gid_t, struct proc *,
73 int));
74 static int change_utimes __P((struct vnode *vp, const struct timeval *,
75 struct proc *p));
76 static int rename_files __P((const char *, const char *, struct proc *, int));
77
78 void checkdirs __P((struct vnode *));
79 int dounmount __P((struct mount *, int, struct proc *));
80
81 /*
82 * Virtual File System System Calls
83 */
84
85 /*
86 * Mount a file system.
87 */
88
89 /*
90 * This table is used to maintain compatibility with 4.3BSD
91 * and NetBSD 0.9 mount syscalls. Note, the order is important!
92 *
93 * Also note that not all of these had actual numbers in 4.3BSD
94 * or NetBSD 0.9!
95 */
96 const char *mountcompatnames[] = {
97 NULL, /* 0 = MOUNT_NONE */
98 MOUNT_FFS, /* 1 */
99 MOUNT_NFS, /* 2 */
100 MOUNT_MFS, /* 3 */
101 MOUNT_MSDOS, /* 4 */
102 MOUNT_LFS, /* 5 */
103 NULL, /* 6 = MOUNT_LOFS */
104 MOUNT_FDESC, /* 7 */
105 MOUNT_PORTAL, /* 8 */
106 MOUNT_NULL, /* 9 */
107 MOUNT_UMAP, /* 10 */
108 MOUNT_KERNFS, /* 11 */
109 MOUNT_PROCFS, /* 12 */
110 MOUNT_AFS, /* 13 */
111 MOUNT_CD9660, /* 14 = MOUNT_ISOFS */
112 MOUNT_UNION, /* 15 */
113 MOUNT_ADOSFS, /* 16 */
114 MOUNT_EXT2FS, /* 17 */
115 MOUNT_CODA, /* 18 */
116 MOUNT_FILECORE, /* 19 */
117 };
118 const int nmountcompatnames = sizeof(mountcompatnames) /
119 sizeof(mountcompatnames[0]);
120
121 /* ARGSUSED */
122 int
123 sys_mount(p, v, retval)
124 struct proc *p;
125 void *v;
126 register_t *retval;
127 {
128 register struct sys_mount_args /* {
129 syscallarg(const char *) type;
130 syscallarg(const char *) path;
131 syscallarg(int) flags;
132 syscallarg(void *) data;
133 } */ *uap = v;
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 /*
143 * Get vnode to be covered
144 */
145 NDINIT(&nd, LOOKUP, FOLLOW , UIO_USERSPACE,
146 SCARG(uap, path), p);
147 if ((error = namei(&nd)) != 0)
148 return (error);
149 vp = nd.ni_vp;
150 /*
151 * A lookup in VFS_MOUNT might result in an attempt to
152 * lock this vnode again, so make the lock resursive.
153 */
154 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_SETRECURSE);
155 if (SCARG(uap, flags) & MNT_UPDATE) {
156 if ((vp->v_flag & VROOT) == 0) {
157 vput(vp);
158 return (EINVAL);
159 }
160 mp = vp->v_mount;
161 flag = mp->mnt_flag;
162 vfs = mp->mnt_op;
163 /*
164 * We only allow the filesystem to be reloaded if it
165 * is currently mounted read-only.
166 */
167 if ((SCARG(uap, flags) & MNT_RELOAD) &&
168 ((mp->mnt_flag & MNT_RDONLY) == 0)) {
169 vput(vp);
170 return (EOPNOTSUPP); /* Needs translation */
171 }
172 /*
173 * In "highly secure" mode, don't let the caller do anything
174 * but downgrade a filesystem from read-write to read-only.
175 * (see also below; MNT_UPDATE is required.)
176 */
177 if (securelevel >= 2 &&
178 (SCARG(uap, flags) !=
179 (mp->mnt_flag | MNT_RDONLY |
180 MNT_RELOAD | MNT_FORCE | MNT_UPDATE))) {
181 vput(vp);
182 return (EPERM);
183 }
184 mp->mnt_flag |=
185 SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
186 /*
187 * Only root, or the user that did the original mount is
188 * permitted to update it.
189 */
190 if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
191 (error = suser(p->p_ucred, &p->p_acflag)) != 0) {
192 vput(vp);
193 return (error);
194 }
195 /*
196 * Do not allow NFS export by non-root users. For non-root
197 * users, silently enforce MNT_NOSUID and MNT_NODEV, and
198 * MNT_NOEXEC if mount point is already MNT_NOEXEC.
199 */
200 if (p->p_ucred->cr_uid != 0) {
201 if (SCARG(uap, flags) & MNT_EXPORTED) {
202 vput(vp);
203 return (EPERM);
204 }
205 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
206 if (flag & MNT_NOEXEC)
207 SCARG(uap, flags) |= MNT_NOEXEC;
208 }
209 if (vfs_busy(mp, LK_NOWAIT, 0)) {
210 vput(vp);
211 return (EPERM);
212 }
213 VOP_UNLOCK(vp, 0);
214 goto update;
215 } else {
216 if (securelevel >= 2)
217 return (EPERM);
218 }
219 /*
220 * If the user is not root, ensure that they own the directory
221 * onto which we are attempting to mount.
222 */
223 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) != 0 ||
224 (va.va_uid != p->p_ucred->cr_uid &&
225 (error = suser(p->p_ucred, &p->p_acflag)) != 0)) {
226 vput(vp);
227 return (error);
228 }
229 /*
230 * Do not allow NFS export by non-root users. For non-root users,
231 * silently enforce MNT_NOSUID and MNT_NODEV, and MNT_NOEXEC if the
232 * mount point is already MNT_NOEXEC.
233 */
234 if (p->p_ucred->cr_uid != 0) {
235 if (SCARG(uap, flags) & MNT_EXPORTED) {
236 vput(vp);
237 return (EPERM);
238 }
239 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
240 if (vp->v_mount->mnt_flag & MNT_NOEXEC)
241 SCARG(uap, flags) |= MNT_NOEXEC;
242 }
243 if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
244 return (error);
245 if (vp->v_type != VDIR) {
246 vput(vp);
247 return (ENOTDIR);
248 }
249 error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL);
250 if (error) {
251 #if defined(COMPAT_09) || defined(COMPAT_43)
252 /*
253 * Historically filesystem types were identified by number.
254 * If we get an integer for the filesystem type instead of a
255 * string, we check to see if it matches one of the historic
256 * filesystem types.
257 */
258 u_long fsindex = (u_long)SCARG(uap, type);
259 if (fsindex >= nmountcompatnames ||
260 mountcompatnames[fsindex] == NULL) {
261 vput(vp);
262 return (ENODEV);
263 }
264 strncpy(fstypename, mountcompatnames[fsindex], MFSNAMELEN);
265 #else
266 vput(vp);
267 return (error);
268 #endif
269 }
270 #ifdef COMPAT_10
271 /* Accept `ufs' as an alias for `ffs'. */
272 if (!strncmp(fstypename, "ufs", MFSNAMELEN))
273 strncpy(fstypename, "ffs", MFSNAMELEN);
274 #endif
275 if ((vfs = vfs_getopsbyname(fstypename)) == NULL) {
276 vput(vp);
277 return (ENODEV);
278 }
279 if (vp->v_mountedhere != NULL) {
280 vput(vp);
281 return (EBUSY);
282 }
283
284 /*
285 * Allocate and initialize the file system.
286 */
287 mp = (struct mount *)malloc((u_long)sizeof(struct mount),
288 M_MOUNT, M_WAITOK);
289 memset((char *)mp, 0, (u_long)sizeof(struct mount));
290 lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);
291 (void)vfs_busy(mp, LK_NOWAIT, 0);
292 mp->mnt_op = vfs;
293 vfs->vfs_refcount++;
294 mp->mnt_vnodecovered = vp;
295 mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
296 update:
297 /*
298 * Set the mount level flags.
299 */
300 if (SCARG(uap, flags) & MNT_RDONLY)
301 mp->mnt_flag |= MNT_RDONLY;
302 else if (mp->mnt_flag & MNT_RDONLY)
303 mp->mnt_flag |= MNT_WANTRDWR;
304 mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
305 MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOCOREDUMP |
306 MNT_NOATIME | MNT_NODEVMTIME | MNT_SYMPERM);
307 mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
308 MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC |
309 MNT_NOCOREDUMP | MNT_NOATIME | MNT_NODEVMTIME | MNT_SYMPERM);
310 /*
311 * Mount the filesystem.
312 */
313 error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
314 if (mp->mnt_flag & MNT_UPDATE) {
315 vrele(vp);
316 if (mp->mnt_flag & MNT_WANTRDWR)
317 mp->mnt_flag &= ~MNT_RDONLY;
318 mp->mnt_flag &=~
319 (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
320 if (error)
321 mp->mnt_flag = flag;
322 vfs_unbusy(mp);
323 return (error);
324 }
325 /*
326 * Put the new filesystem on the mount list after root.
327 */
328 cache_purge(vp);
329 if (!error) {
330 vp->v_mountedhere = mp;
331 simple_lock(&mountlist_slock);
332 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
333 simple_unlock(&mountlist_slock);
334 checkdirs(vp);
335 VOP_UNLOCK(vp, 0);
336 vfs_unbusy(mp);
337 (void) VFS_STATFS(mp, &mp->mnt_stat, p);
338 if ((error = VFS_START(mp, 0, p)))
339 vrele(vp);
340 } else {
341 vp->v_mountedhere = (struct mount *)0;
342 vfs->vfs_refcount--;
343 vfs_unbusy(mp);
344 free((caddr_t)mp, M_MOUNT);
345 vput(vp);
346 }
347 return (error);
348 }
349
350 /*
351 * Scan all active processes to see if any of them have a current
352 * or root directory onto which the new filesystem has just been
353 * mounted. If so, replace them with the new mount point.
354 */
355 void
356 checkdirs(olddp)
357 struct vnode *olddp;
358 {
359 struct filedesc *fdp;
360 struct vnode *newdp;
361 struct proc *p;
362
363 if (olddp->v_usecount == 1)
364 return;
365 if (VFS_ROOT(olddp->v_mountedhere, &newdp))
366 panic("mount: lost mount");
367 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
368 fdp = p->p_fd;
369 if (fdp->fd_cdir == olddp) {
370 vrele(fdp->fd_cdir);
371 VREF(newdp);
372 fdp->fd_cdir = newdp;
373 }
374 if (fdp->fd_rdir == olddp) {
375 vrele(fdp->fd_rdir);
376 VREF(newdp);
377 fdp->fd_rdir = newdp;
378 }
379 }
380 if (rootvnode == olddp) {
381 vrele(rootvnode);
382 VREF(newdp);
383 rootvnode = newdp;
384 }
385 vput(newdp);
386 }
387
388 /*
389 * Unmount a file system.
390 *
391 * Note: unmount takes a path to the vnode mounted on as argument,
392 * not special file (as before).
393 */
394 /* ARGSUSED */
395 int
396 sys_unmount(p, v, retval)
397 struct proc *p;
398 void *v;
399 register_t *retval;
400 {
401 register struct sys_unmount_args /* {
402 syscallarg(const char *) path;
403 syscallarg(int) flags;
404 } */ *uap = v;
405 register struct vnode *vp;
406 struct mount *mp;
407 int error;
408 struct nameidata nd;
409
410 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
411 SCARG(uap, path), p);
412 if ((error = namei(&nd)) != 0)
413 return (error);
414 vp = nd.ni_vp;
415 mp = vp->v_mount;
416
417 /*
418 * Only root, or the user that did the original mount is
419 * permitted to unmount this filesystem.
420 */
421 if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
422 (error = suser(p->p_ucred, &p->p_acflag)) != 0) {
423 vput(vp);
424 return (error);
425 }
426
427 /*
428 * Don't allow unmounting the root file system.
429 */
430 if (mp->mnt_flag & MNT_ROOTFS) {
431 vput(vp);
432 return (EINVAL);
433 }
434
435 /*
436 * Must be the root of the filesystem
437 */
438 if ((vp->v_flag & VROOT) == 0) {
439 vput(vp);
440 return (EINVAL);
441 }
442 vput(vp);
443
444 if (vfs_busy(mp, 0, 0))
445 return (EBUSY);
446
447 return (dounmount(mp, SCARG(uap, flags), p));
448 }
449
450 /*
451 * Do the actual file system unmount. File system is assumed to have been
452 * marked busy by the caller.
453 */
454 int
455 dounmount(mp, flags, p)
456 register struct mount *mp;
457 int flags;
458 struct proc *p;
459 {
460 struct vnode *coveredvp;
461 int error;
462
463 simple_lock(&mountlist_slock);
464 mp->mnt_flag |= MNT_UNMOUNT;
465 vfs_unbusy(mp);
466 lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock);
467 if (mp->mnt_flag & MNT_EXPUBLIC)
468 vfs_setpublicfs(NULL, NULL, NULL);
469 mp->mnt_flag &=~ MNT_ASYNC;
470 #if !defined(UVM)
471 vnode_pager_umount(mp); /* release cached vnodes */
472 #endif
473 cache_purgevfs(mp); /* remove cache entries for this file sys */
474 if (((mp->mnt_flag & MNT_RDONLY) ||
475 (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
476 (flags & MNT_FORCE))
477 error = VFS_UNMOUNT(mp, flags, p);
478 simple_lock(&mountlist_slock);
479 if (error) {
480 mp->mnt_flag &= ~MNT_UNMOUNT;
481 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
482 &mountlist_slock);
483 if (mp->mnt_flag & MNT_MWAIT)
484 wakeup((caddr_t)mp);
485 return (error);
486 }
487 CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
488 if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
489 coveredvp->v_mountedhere = NULL;
490 vrele(coveredvp);
491 }
492 mp->mnt_op->vfs_refcount--;
493 if (mp->mnt_vnodelist.lh_first != NULL)
494 panic("unmount: dangling vnode");
495 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock);
496 if (mp->mnt_flag & MNT_MWAIT)
497 wakeup((caddr_t)mp);
498 free((caddr_t)mp, M_MOUNT);
499 return (0);
500 }
501
502 /*
503 * Sync each mounted filesystem.
504 */
505 #ifdef DEBUG
506 int syncprt = 0;
507 struct ctldebug debug0 = { "syncprt", &syncprt };
508 #endif
509
510 /* ARGSUSED */
511 int
512 sys_sync(p, v, retval)
513 struct proc *p;
514 void *v;
515 register_t *retval;
516 {
517 register struct mount *mp, *nmp;
518 int asyncflag;
519
520 simple_lock(&mountlist_slock);
521 for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) {
522 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock)) {
523 nmp = mp->mnt_list.cqe_prev;
524 continue;
525 }
526 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
527 asyncflag = mp->mnt_flag & MNT_ASYNC;
528 mp->mnt_flag &= ~MNT_ASYNC;
529 #if defined(UVM)
530 uvm_vnp_sync(mp);
531 #else
532 vnode_pager_sync(mp);
533 #endif
534 VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
535 if (asyncflag)
536 mp->mnt_flag |= MNT_ASYNC;
537 }
538 simple_lock(&mountlist_slock);
539 nmp = mp->mnt_list.cqe_prev;
540 vfs_unbusy(mp);
541
542 }
543 simple_unlock(&mountlist_slock);
544 #ifdef DEBUG
545 if (syncprt)
546 vfs_bufstats();
547 #endif /* DEBUG */
548 return (0);
549 }
550
551 /*
552 * Change filesystem quotas.
553 */
554 /* ARGSUSED */
555 int
556 sys_quotactl(p, v, retval)
557 struct proc *p;
558 void *v;
559 register_t *retval;
560 {
561 register struct sys_quotactl_args /* {
562 syscallarg(const char *) path;
563 syscallarg(int) cmd;
564 syscallarg(int) uid;
565 syscallarg(caddr_t) arg;
566 } */ *uap = v;
567 register struct mount *mp;
568 int error;
569 struct nameidata nd;
570
571 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
572 if ((error = namei(&nd)) != 0)
573 return (error);
574 mp = nd.ni_vp->v_mount;
575 vrele(nd.ni_vp);
576 return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
577 SCARG(uap, arg), p));
578 }
579
580 /*
581 * Get filesystem statistics.
582 */
583 /* ARGSUSED */
584 int
585 sys_statfs(p, v, retval)
586 struct proc *p;
587 void *v;
588 register_t *retval;
589 {
590 register struct sys_statfs_args /* {
591 syscallarg(const char *) path;
592 syscallarg(struct statfs *) buf;
593 } */ *uap = v;
594 register struct mount *mp;
595 register struct statfs *sp;
596 int error;
597 struct nameidata nd;
598
599 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
600 if ((error = namei(&nd)) != 0)
601 return (error);
602 mp = nd.ni_vp->v_mount;
603 sp = &mp->mnt_stat;
604 vrele(nd.ni_vp);
605 if ((error = VFS_STATFS(mp, sp, p)) != 0)
606 return (error);
607 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
608 return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
609 }
610
611 /*
612 * Get filesystem statistics.
613 */
614 /* ARGSUSED */
615 int
616 sys_fstatfs(p, v, retval)
617 struct proc *p;
618 void *v;
619 register_t *retval;
620 {
621 register struct sys_fstatfs_args /* {
622 syscallarg(int) fd;
623 syscallarg(struct statfs *) buf;
624 } */ *uap = v;
625 struct file *fp;
626 struct mount *mp;
627 register struct statfs *sp;
628 int error;
629
630 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
631 return (error);
632 mp = ((struct vnode *)fp->f_data)->v_mount;
633 sp = &mp->mnt_stat;
634 if ((error = VFS_STATFS(mp, sp, p)) != 0)
635 return (error);
636 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
637 return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
638 }
639
640 /*
641 * Get statistics on all filesystems.
642 */
643 int
644 sys_getfsstat(p, v, retval)
645 struct proc *p;
646 void *v;
647 register_t *retval;
648 {
649 register struct sys_getfsstat_args /* {
650 syscallarg(struct statfs *) buf;
651 syscallarg(long) bufsize;
652 syscallarg(int) flags;
653 } */ *uap = v;
654 register struct mount *mp, *nmp;
655 register struct statfs *sp;
656 caddr_t sfsp;
657 long count, maxcount, error;
658
659 maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
660 sfsp = (caddr_t)SCARG(uap, buf);
661 simple_lock(&mountlist_slock);
662 count = 0;
663 for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
664 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock)) {
665 nmp = mp->mnt_list.cqe_next;
666 continue;
667 }
668 if (sfsp && count < maxcount) {
669 sp = &mp->mnt_stat;
670 /*
671 * If MNT_NOWAIT is specified, do not refresh the
672 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
673 */
674 if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 ||
675 (SCARG(uap, flags) & MNT_WAIT)) &&
676 (error = VFS_STATFS(mp, sp, p)) != 0) {
677 simple_lock(&mountlist_slock);
678 nmp = mp->mnt_list.cqe_next;
679 vfs_unbusy(mp);
680 continue;
681 }
682 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
683 error = copyout(sp, sfsp, sizeof(*sp));
684 if (error)
685 return (error);
686 sfsp += sizeof(*sp);
687 }
688 count++;
689 simple_lock(&mountlist_slock);
690 nmp = mp->mnt_list.cqe_next;
691 vfs_unbusy(mp);
692 }
693 simple_unlock(&mountlist_slock);
694 if (sfsp && count > maxcount)
695 *retval = maxcount;
696 else
697 *retval = count;
698 return (0);
699 }
700
701 /*
702 * Change current working directory to a given file descriptor.
703 */
704 /* ARGSUSED */
705 int
706 sys_fchdir(p, v, retval)
707 struct proc *p;
708 void *v;
709 register_t *retval;
710 {
711 struct sys_fchdir_args /* {
712 syscallarg(int) fd;
713 } */ *uap = v;
714 register struct filedesc *fdp = p->p_fd;
715 struct vnode *vp, *tdp;
716 struct mount *mp;
717 struct file *fp;
718 int error;
719
720 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
721 return (error);
722 vp = (struct vnode *)fp->f_data;
723 VREF(vp);
724 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
725 if (vp->v_type != VDIR)
726 error = ENOTDIR;
727 else
728 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
729 while (!error && (mp = vp->v_mountedhere) != NULL) {
730 if (vfs_busy(mp, 0, 0))
731 continue;
732 error = VFS_ROOT(mp, &tdp);
733 vfs_unbusy(mp);
734 if (error)
735 break;
736 vput(vp);
737 vp = tdp;
738 }
739 if (error) {
740 vput(vp);
741 return (error);
742 }
743 VOP_UNLOCK(vp, 0);
744 vrele(fdp->fd_cdir);
745 fdp->fd_cdir = vp;
746 return (0);
747 }
748
749 /*
750 * Change current working directory (``.'').
751 */
752 /* ARGSUSED */
753 int
754 sys_chdir(p, v, retval)
755 struct proc *p;
756 void *v;
757 register_t *retval;
758 {
759 struct sys_chdir_args /* {
760 syscallarg(const char *) path;
761 } */ *uap = v;
762 register struct filedesc *fdp = p->p_fd;
763 int error;
764 struct nameidata nd;
765
766 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
767 SCARG(uap, path), p);
768 if ((error = change_dir(&nd, p)) != 0)
769 return (error);
770 vrele(fdp->fd_cdir);
771 fdp->fd_cdir = nd.ni_vp;
772 return (0);
773 }
774
775 /*
776 * Change notion of root (``/'') directory.
777 */
778 /* ARGSUSED */
779 int
780 sys_chroot(p, v, retval)
781 struct proc *p;
782 void *v;
783 register_t *retval;
784 {
785 struct sys_chroot_args /* {
786 syscallarg(const char *) path;
787 } */ *uap = v;
788 register struct filedesc *fdp = p->p_fd;
789 int error;
790 struct nameidata nd;
791
792 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
793 return (error);
794 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
795 SCARG(uap, path), p);
796 if ((error = change_dir(&nd, p)) != 0)
797 return (error);
798 if (fdp->fd_rdir != NULL)
799 vrele(fdp->fd_rdir);
800 fdp->fd_rdir = nd.ni_vp;
801 return (0);
802 }
803
804 /*
805 * Common routine for chroot and chdir.
806 */
807 static int
808 change_dir(ndp, p)
809 register struct nameidata *ndp;
810 struct proc *p;
811 {
812 struct vnode *vp;
813 int error;
814
815 if ((error = namei(ndp)) != 0)
816 return (error);
817 vp = ndp->ni_vp;
818 if (vp->v_type != VDIR)
819 error = ENOTDIR;
820 else
821 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
822
823 if (error)
824 vput(vp);
825 else
826 VOP_UNLOCK(vp, 0);
827 return (error);
828 }
829
830 /*
831 * Check permissions, allocate an open file structure,
832 * and call the device open routine if any.
833 */
834 int
835 sys_open(p, v, retval)
836 struct proc *p;
837 void *v;
838 register_t *retval;
839 {
840 register struct sys_open_args /* {
841 syscallarg(const char *) path;
842 syscallarg(int) flags;
843 syscallarg(int) mode;
844 } */ *uap = v;
845 register struct filedesc *fdp = p->p_fd;
846 register struct file *fp;
847 register struct vnode *vp;
848 int flags, cmode;
849 struct file *nfp;
850 int type, indx, error;
851 struct flock lf;
852 struct nameidata nd;
853 extern struct fileops vnops;
854
855 flags = FFLAGS(SCARG(uap, flags));
856 if ((flags & (FREAD | FWRITE)) == 0)
857 return (EINVAL);
858 if ((error = falloc(p, &nfp, &indx)) != 0)
859 return (error);
860 fp = nfp;
861 cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
862 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
863 p->p_dupfd = -indx - 1; /* XXX check for fdopen */
864 if ((error = vn_open(&nd, flags, cmode)) != 0) {
865 ffree(fp);
866 if ((error == ENODEV || error == ENXIO) &&
867 p->p_dupfd >= 0 && /* XXX from fdopen */
868 (error =
869 dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
870 *retval = indx;
871 return (0);
872 }
873 if (error == ERESTART)
874 error = EINTR;
875 fdp->fd_ofiles[indx] = NULL;
876 return (error);
877 }
878 p->p_dupfd = 0;
879 vp = nd.ni_vp;
880 fp->f_flag = flags & FMASK;
881 fp->f_type = DTYPE_VNODE;
882 fp->f_ops = &vnops;
883 fp->f_data = (caddr_t)vp;
884 if (flags & (O_EXLOCK | O_SHLOCK)) {
885 lf.l_whence = SEEK_SET;
886 lf.l_start = 0;
887 lf.l_len = 0;
888 if (flags & O_EXLOCK)
889 lf.l_type = F_WRLCK;
890 else
891 lf.l_type = F_RDLCK;
892 type = F_FLOCK;
893 if ((flags & FNONBLOCK) == 0)
894 type |= F_WAIT;
895 VOP_UNLOCK(vp, 0);
896 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
897 if (error) {
898 (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
899 ffree(fp);
900 fdp->fd_ofiles[indx] = NULL;
901 return (error);
902 }
903 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
904 fp->f_flag |= FHASLOCK;
905 }
906 VOP_UNLOCK(vp, 0);
907 *retval = indx;
908 return (0);
909 }
910
911 /*
912 * Create a special file.
913 */
914 /* ARGSUSED */
915 int
916 sys_mknod(p, v, retval)
917 struct proc *p;
918 void *v;
919 register_t *retval;
920 {
921 register struct sys_mknod_args /* {
922 syscallarg(const char *) path;
923 syscallarg(int) mode;
924 syscallarg(int) dev;
925 } */ *uap = v;
926 register struct vnode *vp;
927 struct vattr vattr;
928 int error;
929 int whiteout = 0;
930 struct nameidata nd;
931
932 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
933 return (error);
934 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
935 if ((error = namei(&nd)) != 0)
936 return (error);
937 vp = nd.ni_vp;
938 if (vp != NULL)
939 error = EEXIST;
940 else {
941 VATTR_NULL(&vattr);
942 vattr.va_mode =
943 (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
944 vattr.va_rdev = SCARG(uap, dev);
945 whiteout = 0;
946
947 switch (SCARG(uap, mode) & S_IFMT) {
948 case S_IFMT: /* used by badsect to flag bad sectors */
949 vattr.va_type = VBAD;
950 break;
951 case S_IFCHR:
952 vattr.va_type = VCHR;
953 break;
954 case S_IFBLK:
955 vattr.va_type = VBLK;
956 break;
957 case S_IFWHT:
958 whiteout = 1;
959 break;
960 default:
961 error = EINVAL;
962 break;
963 }
964 }
965 if (!error) {
966 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
967 if (whiteout) {
968 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
969 if (error)
970 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
971 vput(nd.ni_dvp);
972 } else {
973 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
974 &nd.ni_cnd, &vattr);
975 }
976 } else {
977 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
978 if (nd.ni_dvp == vp)
979 vrele(nd.ni_dvp);
980 else
981 vput(nd.ni_dvp);
982 if (vp)
983 vrele(vp);
984 }
985 return (error);
986 }
987
988 /*
989 * Create a named pipe.
990 */
991 /* ARGSUSED */
992 int
993 sys_mkfifo(p, v, retval)
994 struct proc *p;
995 void *v;
996 register_t *retval;
997 {
998 register struct sys_mkfifo_args /* {
999 syscallarg(const char *) path;
1000 syscallarg(int) mode;
1001 } */ *uap = v;
1002 struct vattr vattr;
1003 int error;
1004 struct nameidata nd;
1005
1006 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1007 if ((error = namei(&nd)) != 0)
1008 return (error);
1009 if (nd.ni_vp != NULL) {
1010 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1011 if (nd.ni_dvp == nd.ni_vp)
1012 vrele(nd.ni_dvp);
1013 else
1014 vput(nd.ni_dvp);
1015 vrele(nd.ni_vp);
1016 return (EEXIST);
1017 }
1018 VATTR_NULL(&vattr);
1019 vattr.va_type = VFIFO;
1020 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1021 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1022 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
1023 }
1024
1025 /*
1026 * Make a hard file link.
1027 */
1028 /* ARGSUSED */
1029 int
1030 sys_link(p, v, retval)
1031 struct proc *p;
1032 void *v;
1033 register_t *retval;
1034 {
1035 register struct sys_link_args /* {
1036 syscallarg(const char *) path;
1037 syscallarg(const char *) link;
1038 } */ *uap = v;
1039 register struct vnode *vp;
1040 struct nameidata nd;
1041 int error;
1042
1043 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1044 if ((error = namei(&nd)) != 0)
1045 return (error);
1046 vp = nd.ni_vp;
1047 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
1048 if ((error = namei(&nd)) != 0)
1049 goto out;
1050 if (nd.ni_vp) {
1051 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1052 if (nd.ni_dvp == nd.ni_vp)
1053 vrele(nd.ni_dvp);
1054 else
1055 vput(nd.ni_dvp);
1056 vrele(nd.ni_vp);
1057 error = EEXIST;
1058 goto out;
1059 }
1060 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1061 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1062 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1063 out:
1064 vrele(vp);
1065 return (error);
1066 }
1067
1068 /*
1069 * Make a symbolic link.
1070 */
1071 /* ARGSUSED */
1072 int
1073 sys_symlink(p, v, retval)
1074 struct proc *p;
1075 void *v;
1076 register_t *retval;
1077 {
1078 register struct sys_symlink_args /* {
1079 syscallarg(const char *) path;
1080 syscallarg(const char *) link;
1081 } */ *uap = v;
1082 struct vattr vattr;
1083 char *path;
1084 int error;
1085 struct nameidata nd;
1086
1087 MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
1088 error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL);
1089 if (error)
1090 goto out;
1091 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
1092 if ((error = namei(&nd)) != 0)
1093 goto out;
1094 if (nd.ni_vp) {
1095 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1096 if (nd.ni_dvp == nd.ni_vp)
1097 vrele(nd.ni_dvp);
1098 else
1099 vput(nd.ni_dvp);
1100 vrele(nd.ni_vp);
1101 error = EEXIST;
1102 goto out;
1103 }
1104 VATTR_NULL(&vattr);
1105 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
1106 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1107 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
1108 out:
1109 FREE(path, M_NAMEI);
1110 return (error);
1111 }
1112
1113 /*
1114 * Delete a whiteout from the filesystem.
1115 */
1116 /* ARGSUSED */
1117 int
1118 sys_undelete(p, v, retval)
1119 struct proc *p;
1120 void *v;
1121 register_t *retval;
1122 {
1123 register struct sys_undelete_args /* {
1124 syscallarg(const char *) path;
1125 } */ *uap = v;
1126 int error;
1127 struct nameidata nd;
1128
1129 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
1130 SCARG(uap, path), p);
1131 error = namei(&nd);
1132 if (error)
1133 return (error);
1134
1135 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1136 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1137 if (nd.ni_dvp == nd.ni_vp)
1138 vrele(nd.ni_dvp);
1139 else
1140 vput(nd.ni_dvp);
1141 if (nd.ni_vp)
1142 vrele(nd.ni_vp);
1143 return (EEXIST);
1144 }
1145
1146 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1147 if ((error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) != 0)
1148 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1149 vput(nd.ni_dvp);
1150 return (error);
1151 }
1152
1153 /*
1154 * Delete a name from the filesystem.
1155 */
1156 /* ARGSUSED */
1157 int
1158 sys_unlink(p, v, retval)
1159 struct proc *p;
1160 void *v;
1161 register_t *retval;
1162 {
1163 struct sys_unlink_args /* {
1164 syscallarg(const char *) path;
1165 } */ *uap = v;
1166 register struct vnode *vp;
1167 int error;
1168 struct nameidata nd;
1169
1170 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
1171 SCARG(uap, path), p);
1172 if ((error = namei(&nd)) != 0)
1173 return (error);
1174 vp = nd.ni_vp;
1175
1176 /*
1177 * The root of a mounted filesystem cannot be deleted.
1178 */
1179 if (vp->v_flag & VROOT) {
1180 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1181 if (nd.ni_dvp == vp)
1182 vrele(nd.ni_dvp);
1183 else
1184 vput(nd.ni_dvp);
1185 vput(vp);
1186 error = EBUSY;
1187 goto out;
1188 }
1189
1190 #if defined(UVM)
1191 (void)uvm_vnp_uncache(vp);
1192 #else
1193 (void)vnode_pager_uncache(vp);
1194 #endif
1195
1196 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1197 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1198 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1199 out:
1200 return (error);
1201 }
1202
1203 /*
1204 * Reposition read/write file offset.
1205 */
1206 int
1207 sys_lseek(p, v, retval)
1208 struct proc *p;
1209 void *v;
1210 register_t *retval;
1211 {
1212 register struct sys_lseek_args /* {
1213 syscallarg(int) fd;
1214 syscallarg(int) pad;
1215 syscallarg(off_t) offset;
1216 syscallarg(int) whence;
1217 } */ *uap = v;
1218 struct ucred *cred = p->p_ucred;
1219 register struct filedesc *fdp = p->p_fd;
1220 register struct file *fp;
1221 struct vnode *vp;
1222 struct vattr vattr;
1223 register off_t newoff;
1224 int error;
1225
1226 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
1227 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
1228 return (EBADF);
1229
1230 vp = (struct vnode *)fp->f_data;
1231 if (fp->f_type != DTYPE_VNODE
1232 || vp->v_type == VFIFO)
1233 return (ESPIPE);
1234
1235 switch (SCARG(uap, whence)) {
1236 case SEEK_CUR:
1237 newoff = fp->f_offset + SCARG(uap, offset);
1238 break;
1239 case SEEK_END:
1240 error = VOP_GETATTR(vp, &vattr, cred, p);
1241 if (error)
1242 return (error);
1243 newoff = SCARG(uap, offset) + vattr.va_size;
1244 break;
1245 case SEEK_SET:
1246 newoff = SCARG(uap, offset);
1247 break;
1248 default:
1249 return (EINVAL);
1250 }
1251 if ((error = VOP_SEEK(vp, fp->f_offset, newoff, cred)) != 0)
1252 return (error);
1253
1254 *(off_t *)retval = fp->f_offset = newoff;
1255 return (0);
1256 }
1257
1258 /*
1259 * Positional read system call.
1260 */
1261 int
1262 sys_pread(p, v, retval)
1263 struct proc *p;
1264 void *v;
1265 register_t *retval;
1266 {
1267 struct sys_pread_args /* {
1268 syscallarg(int) fd;
1269 syscallarg(void *) buf;
1270 syscallarg(size_t) nbyte;
1271 syscallarg(off_t) offset;
1272 } */ *uap = v;
1273 struct filedesc *fdp = p->p_fd;
1274 struct file *fp;
1275 struct vnode *vp;
1276 off_t offset;
1277 int error, fd = SCARG(uap, fd);
1278
1279 if ((u_int)fd >= fdp->fd_nfiles ||
1280 (fp = fdp->fd_ofiles[fd]) == NULL ||
1281 (fp->f_flag & FREAD) == 0)
1282 return (EBADF);
1283
1284 vp = (struct vnode *)fp->f_data;
1285 if (fp->f_type != DTYPE_VNODE
1286 || vp->v_type == VFIFO)
1287 return (ESPIPE);
1288
1289 offset = SCARG(uap, offset);
1290
1291 /*
1292 * XXX This works because no file systems actually
1293 * XXX take any action on the seek operation.
1294 */
1295 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1296 return (error);
1297
1298 return (dofileread(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
1299 &offset, 0, retval));
1300 }
1301
1302 /*
1303 * Positional scatter read system call.
1304 */
1305 int
1306 sys_preadv(p, v, retval)
1307 struct proc *p;
1308 void *v;
1309 register_t *retval;
1310 {
1311 struct sys_preadv_args /* {
1312 syscallarg(int) fd;
1313 syscallarg(const struct iovec *) iovp;
1314 syscallarg(int) iovcnt;
1315 syscallarg(off_t) offset;
1316 } */ *uap = v;
1317 struct filedesc *fdp = p->p_fd;
1318 struct file *fp;
1319 struct vnode *vp;
1320 off_t offset;
1321 int error, fd = SCARG(uap, fd);
1322
1323 if ((u_int)fd >= fdp->fd_nfiles ||
1324 (fp = fdp->fd_ofiles[fd]) == NULL ||
1325 (fp->f_flag & FREAD) == 0)
1326 return (EBADF);
1327
1328 vp = (struct vnode *)fp->f_data;
1329 if (fp->f_type != DTYPE_VNODE
1330 || vp->v_type == VFIFO)
1331 return (ESPIPE);
1332
1333 offset = SCARG(uap, offset);
1334
1335 /*
1336 * XXX This works because no file systems actually
1337 * XXX take any action on the seek operation.
1338 */
1339 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1340 return (error);
1341
1342 return (dofilereadv(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
1343 &offset, 0, retval));
1344 }
1345
1346 /*
1347 * Positional write system call.
1348 */
1349 int
1350 sys_pwrite(p, v, retval)
1351 struct proc *p;
1352 void *v;
1353 register_t *retval;
1354 {
1355 struct sys_pwrite_args /* {
1356 syscallarg(int) fd;
1357 syscallarg(const void *) buf;
1358 syscallarg(size_t) nbyte;
1359 syscallarg(off_t) offset;
1360 } */ *uap = v;
1361 struct filedesc *fdp = p->p_fd;
1362 struct file *fp;
1363 struct vnode *vp;
1364 off_t offset;
1365 int error, fd = SCARG(uap, fd);
1366
1367 if ((u_int)fd >= fdp->fd_nfiles ||
1368 (fp = fdp->fd_ofiles[fd]) == NULL ||
1369 (fp->f_flag & FWRITE) == 0)
1370 return (EBADF);
1371
1372 vp = (struct vnode *)fp->f_data;
1373 if (fp->f_type != DTYPE_VNODE
1374 || vp->v_type == VFIFO)
1375 return (ESPIPE);
1376
1377 offset = SCARG(uap, offset);
1378
1379 /*
1380 * XXX This works because no file systems actually
1381 * XXX take any action on the seek operation.
1382 */
1383 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1384 return (error);
1385
1386 return (dofilewrite(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
1387 &offset, 0, retval));
1388 }
1389
1390 /*
1391 * Positional gather write system call.
1392 */
1393 int
1394 sys_pwritev(p, v, retval)
1395 struct proc *p;
1396 void *v;
1397 register_t *retval;
1398 {
1399 struct sys_pwritev_args /* {
1400 syscallarg(int) fd;
1401 syscallarg(const struct iovec *) iovp;
1402 syscallarg(int) iovcnt;
1403 syscallarg(off_t) offset;
1404 } */ *uap = v;
1405 struct filedesc *fdp = p->p_fd;
1406 struct file *fp;
1407 struct vnode *vp;
1408 off_t offset;
1409 int error, fd = SCARG(uap, fd);
1410
1411 if ((u_int)fd >= fdp->fd_nfiles ||
1412 (fp = fdp->fd_ofiles[fd]) == NULL ||
1413 (fp->f_flag & FWRITE) == 0)
1414 return (EBADF);
1415
1416 vp = (struct vnode *)fp->f_data;
1417 if (fp->f_type != DTYPE_VNODE
1418 || vp->v_type == VFIFO)
1419 return (ESPIPE);
1420
1421 offset = SCARG(uap, offset);
1422
1423 /*
1424 * XXX This works because no file systems actually
1425 * XXX take any action on the seek operation.
1426 */
1427 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1428 return (error);
1429
1430 return (dofilewritev(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
1431 &offset, 0, retval));
1432 }
1433
1434 /*
1435 * Check access permissions.
1436 */
1437 int
1438 sys_access(p, v, retval)
1439 struct proc *p;
1440 void *v;
1441 register_t *retval;
1442 {
1443 register struct sys_access_args /* {
1444 syscallarg(const char *) path;
1445 syscallarg(int) flags;
1446 } */ *uap = v;
1447 register struct ucred *cred = p->p_ucred;
1448 register struct vnode *vp;
1449 int error, flags, t_gid, t_uid;
1450 struct nameidata nd;
1451
1452 t_uid = cred->cr_uid;
1453 t_gid = cred->cr_gid;
1454 cred->cr_uid = p->p_cred->p_ruid;
1455 cred->cr_gid = p->p_cred->p_rgid;
1456 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1457 SCARG(uap, path), p);
1458 if ((error = namei(&nd)) != 0)
1459 goto out1;
1460 vp = nd.ni_vp;
1461
1462 /* Flags == 0 means only check for existence. */
1463 if (SCARG(uap, flags)) {
1464 flags = 0;
1465 if (SCARG(uap, flags) & R_OK)
1466 flags |= VREAD;
1467 if (SCARG(uap, flags) & W_OK)
1468 flags |= VWRITE;
1469 if (SCARG(uap, flags) & X_OK)
1470 flags |= VEXEC;
1471 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1472 error = VOP_ACCESS(vp, flags, cred, p);
1473 }
1474 vput(vp);
1475 out1:
1476 cred->cr_uid = t_uid;
1477 cred->cr_gid = t_gid;
1478 return (error);
1479 }
1480
1481 /*
1482 * Get file status; this version follows links.
1483 */
1484 /* ARGSUSED */
1485 int
1486 sys___stat13(p, v, retval)
1487 struct proc *p;
1488 void *v;
1489 register_t *retval;
1490 {
1491 register struct sys___stat13_args /* {
1492 syscallarg(const char *) path;
1493 syscallarg(struct stat *) ub;
1494 } */ *uap = v;
1495 struct stat sb;
1496 int error;
1497 struct nameidata nd;
1498
1499 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1500 SCARG(uap, path), p);
1501 if ((error = namei(&nd)) != 0)
1502 return (error);
1503 error = vn_stat(nd.ni_vp, &sb, p);
1504 vput(nd.ni_vp);
1505 if (error)
1506 return (error);
1507 error = copyout(&sb, SCARG(uap, ub), sizeof(sb));
1508 return (error);
1509 }
1510
1511 /*
1512 * Get file status; this version does not follow links.
1513 */
1514 /* ARGSUSED */
1515 int
1516 sys___lstat13(p, v, retval)
1517 struct proc *p;
1518 void *v;
1519 register_t *retval;
1520 {
1521 register struct sys___lstat13_args /* {
1522 syscallarg(const char *) path;
1523 syscallarg(struct stat *) ub;
1524 } */ *uap = v;
1525 struct stat sb;
1526 int error;
1527 struct nameidata nd;
1528
1529 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
1530 SCARG(uap, path), p);
1531 if ((error = namei(&nd)) != 0)
1532 return (error);
1533 error = vn_stat(nd.ni_vp, &sb, p);
1534 vput(nd.ni_vp);
1535 if (error)
1536 return (error);
1537 error = copyout(&sb, SCARG(uap, ub), sizeof(sb));
1538 return (error);
1539 }
1540
1541 /*
1542 * Get configurable pathname variables.
1543 */
1544 /* ARGSUSED */
1545 int
1546 sys_pathconf(p, v, retval)
1547 struct proc *p;
1548 void *v;
1549 register_t *retval;
1550 {
1551 register struct sys_pathconf_args /* {
1552 syscallarg(const char *) path;
1553 syscallarg(int) name;
1554 } */ *uap = v;
1555 int error;
1556 struct nameidata nd;
1557
1558 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1559 SCARG(uap, path), p);
1560 if ((error = namei(&nd)) != 0)
1561 return (error);
1562 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
1563 vput(nd.ni_vp);
1564 return (error);
1565 }
1566
1567 /*
1568 * Return target name of a symbolic link.
1569 */
1570 /* ARGSUSED */
1571 int
1572 sys_readlink(p, v, retval)
1573 struct proc *p;
1574 void *v;
1575 register_t *retval;
1576 {
1577 register struct sys_readlink_args /* {
1578 syscallarg(const char *) path;
1579 syscallarg(char *) buf;
1580 syscallarg(size_t) count;
1581 } */ *uap = v;
1582 register struct vnode *vp;
1583 struct iovec aiov;
1584 struct uio auio;
1585 int error;
1586 struct nameidata nd;
1587
1588 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
1589 SCARG(uap, path), p);
1590 if ((error = namei(&nd)) != 0)
1591 return (error);
1592 vp = nd.ni_vp;
1593 if (vp->v_type != VLNK)
1594 error = EINVAL;
1595 else if (!(vp->v_mount->mnt_flag & MNT_SYMPERM) ||
1596 (error = VOP_ACCESS(vp, VREAD, p->p_ucred, p)) == 0) {
1597 aiov.iov_base = SCARG(uap, buf);
1598 aiov.iov_len = SCARG(uap, count);
1599 auio.uio_iov = &aiov;
1600 auio.uio_iovcnt = 1;
1601 auio.uio_offset = 0;
1602 auio.uio_rw = UIO_READ;
1603 auio.uio_segflg = UIO_USERSPACE;
1604 auio.uio_procp = p;
1605 auio.uio_resid = SCARG(uap, count);
1606 error = VOP_READLINK(vp, &auio, p->p_ucred);
1607 }
1608 vput(vp);
1609 *retval = SCARG(uap, count) - auio.uio_resid;
1610 return (error);
1611 }
1612
1613 /*
1614 * Change flags of a file given a path name.
1615 */
1616 /* ARGSUSED */
1617 int
1618 sys_chflags(p, v, retval)
1619 struct proc *p;
1620 void *v;
1621 register_t *retval;
1622 {
1623 register struct sys_chflags_args /* {
1624 syscallarg(const char *) path;
1625 syscallarg(u_long) flags;
1626 } */ *uap = v;
1627 register struct vnode *vp;
1628 struct vattr vattr;
1629 int error;
1630 struct nameidata nd;
1631
1632 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1633 if ((error = namei(&nd)) != 0)
1634 return (error);
1635 vp = nd.ni_vp;
1636 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1637 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1638 VATTR_NULL(&vattr);
1639 vattr.va_flags = SCARG(uap, flags);
1640 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1641 vput(vp);
1642 return (error);
1643 }
1644
1645 /*
1646 * Change flags of a file given a file descriptor.
1647 */
1648 /* ARGSUSED */
1649 int
1650 sys_fchflags(p, v, retval)
1651 struct proc *p;
1652 void *v;
1653 register_t *retval;
1654 {
1655 register struct sys_fchflags_args /* {
1656 syscallarg(int) fd;
1657 syscallarg(u_long) flags;
1658 } */ *uap = v;
1659 struct vattr vattr;
1660 struct vnode *vp;
1661 struct file *fp;
1662 int error;
1663
1664 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1665 return (error);
1666 vp = (struct vnode *)fp->f_data;
1667 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1668 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1669 VATTR_NULL(&vattr);
1670 vattr.va_flags = SCARG(uap, flags);
1671 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1672 VOP_UNLOCK(vp, 0);
1673 return (error);
1674 }
1675
1676 /*
1677 * Change mode of a file given path name; this version follows links.
1678 */
1679 /* ARGSUSED */
1680 int
1681 sys_chmod(p, v, retval)
1682 struct proc *p;
1683 void *v;
1684 register_t *retval;
1685 {
1686 register struct sys_chmod_args /* {
1687 syscallarg(const char *) path;
1688 syscallarg(int) mode;
1689 } */ *uap = v;
1690 int error;
1691 struct nameidata nd;
1692
1693 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1694 if ((error = namei(&nd)) != 0)
1695 return (error);
1696
1697 error = change_mode(nd.ni_vp, SCARG(uap, mode), p);
1698
1699 vrele(nd.ni_vp);
1700 return (error);
1701 }
1702
1703 /*
1704 * Change mode of a file given a file descriptor.
1705 */
1706 /* ARGSUSED */
1707 int
1708 sys_fchmod(p, v, retval)
1709 struct proc *p;
1710 void *v;
1711 register_t *retval;
1712 {
1713 register struct sys_fchmod_args /* {
1714 syscallarg(int) fd;
1715 syscallarg(int) mode;
1716 } */ *uap = v;
1717 struct file *fp;
1718 int error;
1719
1720 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1721 return (error);
1722
1723 return (change_mode((struct vnode *)fp->f_data, SCARG(uap, mode), p));
1724 }
1725
1726 /*
1727 * Change mode of a file given path name; this version does not follow links.
1728 */
1729 /* ARGSUSED */
1730 int
1731 sys_lchmod(p, v, retval)
1732 struct proc *p;
1733 void *v;
1734 register_t *retval;
1735 {
1736 register struct sys_lchmod_args /* {
1737 syscallarg(const char *) path;
1738 syscallarg(int) mode;
1739 } */ *uap = v;
1740 int error;
1741 struct nameidata nd;
1742
1743 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1744 if ((error = namei(&nd)) != 0)
1745 return (error);
1746
1747 error = change_mode(nd.ni_vp, SCARG(uap, mode), p);
1748
1749 vrele(nd.ni_vp);
1750 return (error);
1751 }
1752
1753 /*
1754 * Common routine to set mode given a vnode.
1755 */
1756 static int
1757 change_mode(vp, mode, p)
1758 struct vnode *vp;
1759 int mode;
1760 struct proc *p;
1761 {
1762 struct vattr vattr;
1763 int error;
1764
1765 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1766 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1767 VATTR_NULL(&vattr);
1768 vattr.va_mode = mode & ALLPERMS;
1769 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1770 VOP_UNLOCK(vp, 0);
1771 return (error);
1772 }
1773
1774 /*
1775 * Set ownership given a path name; this version follows links.
1776 */
1777 /* ARGSUSED */
1778 int
1779 sys_chown(p, v, retval)
1780 struct proc *p;
1781 void *v;
1782 register_t *retval;
1783 {
1784 register struct sys_chown_args /* {
1785 syscallarg(const char *) path;
1786 syscallarg(uid_t) uid;
1787 syscallarg(gid_t) gid;
1788 } */ *uap = v;
1789 int error;
1790 struct nameidata nd;
1791
1792 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1793 if ((error = namei(&nd)) != 0)
1794 return (error);
1795
1796 error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 0);
1797
1798 vrele(nd.ni_vp);
1799 return (error);
1800 }
1801
1802 /*
1803 * Set ownership given a path name; this version follows links.
1804 * Provides POSIX semantics.
1805 */
1806 /* ARGSUSED */
1807 int
1808 sys___posix_chown(p, v, retval)
1809 struct proc *p;
1810 void *v;
1811 register_t *retval;
1812 {
1813 register struct sys_chown_args /* {
1814 syscallarg(const char *) path;
1815 syscallarg(uid_t) uid;
1816 syscallarg(gid_t) gid;
1817 } */ *uap = v;
1818 int error;
1819 struct nameidata nd;
1820
1821 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1822 if ((error = namei(&nd)) != 0)
1823 return (error);
1824
1825 error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 1);
1826
1827 vrele(nd.ni_vp);
1828 return (error);
1829 }
1830
1831 /*
1832 * Set ownership given a file descriptor.
1833 */
1834 /* ARGSUSED */
1835 int
1836 sys_fchown(p, v, retval)
1837 struct proc *p;
1838 void *v;
1839 register_t *retval;
1840 {
1841 register struct sys_fchown_args /* {
1842 syscallarg(int) fd;
1843 syscallarg(uid_t) uid;
1844 syscallarg(gid_t) gid;
1845 } */ *uap = v;
1846 int error;
1847 struct file *fp;
1848
1849 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1850 return (error);
1851
1852 return (change_owner((struct vnode *)fp->f_data, SCARG(uap, uid),
1853 SCARG(uap, gid), p, 0));
1854 }
1855
1856 /*
1857 * Set ownership given a file descriptor, providing POSIX/XPG semantics.
1858 */
1859 /* ARGSUSED */
1860 int
1861 sys___posix_fchown(p, v, retval)
1862 struct proc *p;
1863 void *v;
1864 register_t *retval;
1865 {
1866 register struct sys_fchown_args /* {
1867 syscallarg(int) fd;
1868 syscallarg(uid_t) uid;
1869 syscallarg(gid_t) gid;
1870 } */ *uap = v;
1871 int error;
1872 struct file *fp;
1873
1874 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1875 return (error);
1876
1877 return (change_owner((struct vnode *)fp->f_data, SCARG(uap, uid),
1878 SCARG(uap, gid), p, 1));
1879 }
1880
1881 /*
1882 * Set ownership given a path name; this version does not follow links.
1883 */
1884 /* ARGSUSED */
1885 int
1886 sys_lchown(p, v, retval)
1887 struct proc *p;
1888 void *v;
1889 register_t *retval;
1890 {
1891 register struct sys_lchown_args /* {
1892 syscallarg(const char *) path;
1893 syscallarg(uid_t) uid;
1894 syscallarg(gid_t) gid;
1895 } */ *uap = v;
1896 int error;
1897 struct nameidata nd;
1898
1899 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1900 if ((error = namei(&nd)) != 0)
1901 return (error);
1902
1903 error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 0);
1904
1905 vrele(nd.ni_vp);
1906 return (error);
1907 }
1908
1909 /*
1910 * Set ownership given a path name; this version does not follow links.
1911 * Provides POSIX/XPG semantics.
1912 */
1913 /* ARGSUSED */
1914 int
1915 sys___posix_lchown(p, v, retval)
1916 struct proc *p;
1917 void *v;
1918 register_t *retval;
1919 {
1920 register struct sys_lchown_args /* {
1921 syscallarg(const char *) path;
1922 syscallarg(uid_t) uid;
1923 syscallarg(gid_t) gid;
1924 } */ *uap = v;
1925 int error;
1926 struct nameidata nd;
1927
1928 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1929 if ((error = namei(&nd)) != 0)
1930 return (error);
1931
1932 error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 1);
1933
1934 vrele(nd.ni_vp);
1935 return (error);
1936 }
1937
1938 /*
1939 * Common routine to set ownership given a vnode.
1940 */
1941 static int
1942 change_owner(vp, uid, gid, p, posix_semantics)
1943 register struct vnode *vp;
1944 uid_t uid;
1945 gid_t gid;
1946 struct proc *p;
1947 int posix_semantics;
1948 {
1949 struct vattr vattr;
1950 mode_t newmode;
1951 int error;
1952
1953 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1954 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1955 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
1956 goto out;
1957
1958 #define CHANGED(x) ((x) != -1)
1959 newmode = vattr.va_mode;
1960 if (posix_semantics) {
1961 /*
1962 * POSIX/XPG semantics: if the caller is not the super-user,
1963 * clear set-user-id and set-group-id bits. Both POSIX and
1964 * the XPG consider the behaviour for calls by the super-user
1965 * implementation-defined; we leave the set-user-id and set-
1966 * group-id settings intact in that case.
1967 */
1968 if (suser(p->p_ucred, NULL) != 0)
1969 newmode &= ~(S_ISUID | S_ISGID);
1970 } else {
1971 /*
1972 * NetBSD semantics: when changing owner and/or group,
1973 * clear the respective bit(s).
1974 */
1975 if (CHANGED(uid))
1976 newmode &= ~S_ISUID;
1977 if (CHANGED(gid))
1978 newmode &= ~S_ISGID;
1979 }
1980 /* Update va_mode iff altered. */
1981 if (vattr.va_mode == newmode)
1982 newmode = VNOVAL;
1983
1984 VATTR_NULL(&vattr);
1985 vattr.va_uid = CHANGED(uid) ? uid : VNOVAL;
1986 vattr.va_gid = CHANGED(gid) ? gid : VNOVAL;
1987 vattr.va_mode = newmode;
1988 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1989 #undef CHANGED
1990
1991 out:
1992 VOP_UNLOCK(vp, 0);
1993 return (error);
1994 }
1995
1996 /*
1997 * Set the access and modification times given a path name; this
1998 * version follows links.
1999 */
2000 /* ARGSUSED */
2001 int
2002 sys_utimes(p, v, retval)
2003 struct proc *p;
2004 void *v;
2005 register_t *retval;
2006 {
2007 register struct sys_utimes_args /* {
2008 syscallarg(const char *) path;
2009 syscallarg(const struct timeval *) tptr;
2010 } */ *uap = v;
2011 int error;
2012 struct nameidata nd;
2013
2014 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2015 if ((error = namei(&nd)) != 0)
2016 return (error);
2017
2018 error = change_utimes(nd.ni_vp, SCARG(uap, tptr), p);
2019
2020 vrele(nd.ni_vp);
2021 return (error);
2022 }
2023
2024 /*
2025 * Set the access and modification times given a file descriptor.
2026 */
2027 /* ARGSUSED */
2028 int
2029 sys_futimes(p, v, retval)
2030 struct proc *p;
2031 void *v;
2032 register_t *retval;
2033 {
2034 register struct sys_futimes_args /* {
2035 syscallarg(int) fd;
2036 syscallarg(const struct timeval *) tptr;
2037 } */ *uap = v;
2038 int error;
2039 struct file *fp;
2040
2041 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2042 return (error);
2043
2044 return (change_utimes((struct vnode *)fp->f_data, SCARG(uap, tptr),
2045 p));
2046 }
2047
2048 /*
2049 * Set the access and modification times given a path name; this
2050 * version does not follow links.
2051 */
2052 /* ARGSUSED */
2053 int
2054 sys_lutimes(p, v, retval)
2055 struct proc *p;
2056 void *v;
2057 register_t *retval;
2058 {
2059 register struct sys_lutimes_args /* {
2060 syscallarg(const char *) path;
2061 syscallarg(const struct timeval *) tptr;
2062 } */ *uap = v;
2063 int error;
2064 struct nameidata nd;
2065
2066 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2067 if ((error = namei(&nd)) != 0)
2068 return (error);
2069
2070 error = change_utimes(nd.ni_vp, SCARG(uap, tptr), p);
2071
2072 vrele(nd.ni_vp);
2073 return (error);
2074 }
2075
2076 /*
2077 * Common routine to set access and modification times given a vnode.
2078 */
2079 static int
2080 change_utimes(vp, tptr, p)
2081 struct vnode *vp;
2082 const struct timeval *tptr;
2083 struct proc *p;
2084 {
2085 struct timeval tv[2];
2086 struct vattr vattr;
2087 int error;
2088
2089 VATTR_NULL(&vattr);
2090 if (tptr == NULL) {
2091 microtime(&tv[0]);
2092 tv[1] = tv[0];
2093 vattr.va_vaflags |= VA_UTIMES_NULL;
2094 } else {
2095 error = copyin(tptr, tv, sizeof(tv));
2096 if (error)
2097 return (error);
2098 }
2099 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2100 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2101 vattr.va_atime.tv_sec = tv[0].tv_sec;
2102 vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
2103 vattr.va_mtime.tv_sec = tv[1].tv_sec;
2104 vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
2105 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2106 VOP_UNLOCK(vp, 0);
2107 return (error);
2108 }
2109
2110 /*
2111 * Truncate a file given its path name.
2112 */
2113 /* ARGSUSED */
2114 int
2115 sys_truncate(p, v, retval)
2116 struct proc *p;
2117 void *v;
2118 register_t *retval;
2119 {
2120 register struct sys_truncate_args /* {
2121 syscallarg(const char *) path;
2122 syscallarg(int) pad;
2123 syscallarg(off_t) length;
2124 } */ *uap = v;
2125 register struct vnode *vp;
2126 struct vattr vattr;
2127 int error;
2128 struct nameidata nd;
2129
2130 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2131 if ((error = namei(&nd)) != 0)
2132 return (error);
2133 vp = nd.ni_vp;
2134 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2135 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2136 if (vp->v_type == VDIR)
2137 error = EISDIR;
2138 else if ((error = vn_writechk(vp)) == 0 &&
2139 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
2140 VATTR_NULL(&vattr);
2141 vattr.va_size = SCARG(uap, length);
2142 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2143 }
2144 vput(vp);
2145 return (error);
2146 }
2147
2148 /*
2149 * Truncate a file given a file descriptor.
2150 */
2151 /* ARGSUSED */
2152 int
2153 sys_ftruncate(p, v, retval)
2154 struct proc *p;
2155 void *v;
2156 register_t *retval;
2157 {
2158 register struct sys_ftruncate_args /* {
2159 syscallarg(int) fd;
2160 syscallarg(int) pad;
2161 syscallarg(off_t) length;
2162 } */ *uap = v;
2163 struct vattr vattr;
2164 struct vnode *vp;
2165 struct file *fp;
2166 int error;
2167
2168 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2169 return (error);
2170 if ((fp->f_flag & FWRITE) == 0)
2171 return (EINVAL);
2172 vp = (struct vnode *)fp->f_data;
2173 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2174 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2175 if (vp->v_type == VDIR)
2176 error = EISDIR;
2177 else if ((error = vn_writechk(vp)) == 0) {
2178 VATTR_NULL(&vattr);
2179 vattr.va_size = SCARG(uap, length);
2180 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
2181 }
2182 VOP_UNLOCK(vp, 0);
2183 return (error);
2184 }
2185
2186 /*
2187 * Sync an open file.
2188 */
2189 /* ARGSUSED */
2190 int
2191 sys_fsync(p, v, retval)
2192 struct proc *p;
2193 void *v;
2194 register_t *retval;
2195 {
2196 struct sys_fsync_args /* {
2197 syscallarg(int) fd;
2198 } */ *uap = v;
2199 register struct vnode *vp;
2200 struct file *fp;
2201 int error;
2202
2203 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2204 return (error);
2205 vp = (struct vnode *)fp->f_data;
2206 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2207 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT, p);
2208 VOP_UNLOCK(vp, 0);
2209 return (error);
2210 }
2211
2212 /*
2213 * Sync the data of an open file.
2214 */
2215 /* ARGSUSED */
2216 int
2217 sys_fdatasync(p, v, retval)
2218 struct proc *p;
2219 void *v;
2220 register_t *retval;
2221 {
2222 struct sys_fdatasync_args /* {
2223 syscallarg(int) fd;
2224 } */ *uap = v;
2225 struct vnode *vp;
2226 struct file *fp;
2227 int error;
2228
2229 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2230 return (error);
2231 vp = (struct vnode *)fp->f_data;
2232 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2233 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT|FSYNC_DATAONLY, p);
2234 VOP_UNLOCK(vp, 0);
2235 return (error);
2236 }
2237
2238 /*
2239 * Rename files, (standard) BSD semantics frontend.
2240 */
2241 /* ARGSUSED */
2242 int
2243 sys_rename(p, v, retval)
2244 struct proc *p;
2245 void *v;
2246 register_t *retval;
2247 {
2248 register struct sys_rename_args /* {
2249 syscallarg(const char *) from;
2250 syscallarg(const char *) to;
2251 } */ *uap = v;
2252
2253 return (rename_files(SCARG(uap, from), SCARG(uap, to), p, 0));
2254 }
2255
2256 /*
2257 * Rename files, POSIX semantics frontend.
2258 */
2259 /* ARGSUSED */
2260 int
2261 sys___posix_rename(p, v, retval)
2262 struct proc *p;
2263 void *v;
2264 register_t *retval;
2265 {
2266 register struct sys___posix_rename_args /* {
2267 syscallarg(const char *) from;
2268 syscallarg(const char *) to;
2269 } */ *uap = v;
2270
2271 return (rename_files(SCARG(uap, from), SCARG(uap, to), p, 1));
2272 }
2273
2274 /*
2275 * Rename files. Source and destination must either both be directories,
2276 * or both not be directories. If target is a directory, it must be empty.
2277 * If `from' and `to' refer to the same object, the value of the `retain'
2278 * argument is used to determine whether `from' will be
2279 *
2280 * (retain == 0) deleted unless `from' and `to' refer to the same
2281 * object in the file system's name space (BSD).
2282 * (retain == 1) always retained (POSIX).
2283 */
2284 static int
2285 rename_files(from, to, p, retain)
2286 const char *from, *to;
2287 struct proc *p;
2288 int retain;
2289 {
2290 register struct vnode *tvp, *fvp, *tdvp;
2291 struct nameidata fromnd, tond;
2292 int error;
2293
2294 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
2295 from, p);
2296 if ((error = namei(&fromnd)) != 0)
2297 return (error);
2298 fvp = fromnd.ni_vp;
2299 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
2300 UIO_USERSPACE, to, p);
2301 if ((error = namei(&tond)) != 0) {
2302 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2303 vrele(fromnd.ni_dvp);
2304 vrele(fvp);
2305 goto out1;
2306 }
2307 tdvp = tond.ni_dvp;
2308 tvp = tond.ni_vp;
2309
2310 if (tvp != NULL) {
2311 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2312 error = ENOTDIR;
2313 goto out;
2314 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2315 error = EISDIR;
2316 goto out;
2317 }
2318 }
2319
2320 if (fvp == tdvp)
2321 error = EINVAL;
2322
2323 /*
2324 * Source and destination refer to the same object.
2325 */
2326 if (fvp == tvp) {
2327 if (retain)
2328 error = -1;
2329 else if (fromnd.ni_dvp == tdvp &&
2330 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
2331 !memcmp(fromnd.ni_cnd.cn_nameptr,
2332 tond.ni_cnd.cn_nameptr,
2333 fromnd.ni_cnd.cn_namelen))
2334 error = -1;
2335 }
2336
2337 out:
2338 if (!error) {
2339 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
2340 if (fromnd.ni_dvp != tdvp)
2341 VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2342 if (tvp) {
2343 #if defined(UVM)
2344 (void)uvm_vnp_uncache(tvp);
2345 #else
2346 (void)vnode_pager_uncache(tvp);
2347 #endif
2348 VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
2349 }
2350 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2351 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2352 } else {
2353 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
2354 if (tdvp == tvp)
2355 vrele(tdvp);
2356 else
2357 vput(tdvp);
2358 if (tvp)
2359 vput(tvp);
2360 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2361 vrele(fromnd.ni_dvp);
2362 vrele(fvp);
2363 }
2364 vrele(tond.ni_startdir);
2365 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
2366 out1:
2367 if (fromnd.ni_startdir)
2368 vrele(fromnd.ni_startdir);
2369 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
2370 return (error == -1 ? 0 : error);
2371 }
2372
2373 /*
2374 * Make a directory file.
2375 */
2376 /* ARGSUSED */
2377 int
2378 sys_mkdir(p, v, retval)
2379 struct proc *p;
2380 void *v;
2381 register_t *retval;
2382 {
2383 register struct sys_mkdir_args /* {
2384 syscallarg(const char *) path;
2385 syscallarg(int) mode;
2386 } */ *uap = v;
2387 register struct vnode *vp;
2388 struct vattr vattr;
2389 int error;
2390 struct nameidata nd;
2391
2392 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
2393 if ((error = namei(&nd)) != 0)
2394 return (error);
2395 vp = nd.ni_vp;
2396 if (vp != NULL) {
2397 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2398 if (nd.ni_dvp == vp)
2399 vrele(nd.ni_dvp);
2400 else
2401 vput(nd.ni_dvp);
2402 vrele(vp);
2403 return (EEXIST);
2404 }
2405 VATTR_NULL(&vattr);
2406 vattr.va_type = VDIR;
2407 vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
2408 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2409 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
2410 if (!error)
2411 vput(nd.ni_vp);
2412 return (error);
2413 }
2414
2415 /*
2416 * Remove a directory file.
2417 */
2418 /* ARGSUSED */
2419 int
2420 sys_rmdir(p, v, retval)
2421 struct proc *p;
2422 void *v;
2423 register_t *retval;
2424 {
2425 struct sys_rmdir_args /* {
2426 syscallarg(const char *) path;
2427 } */ *uap = v;
2428 register struct vnode *vp;
2429 int error;
2430 struct nameidata nd;
2431
2432 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
2433 SCARG(uap, path), p);
2434 if ((error = namei(&nd)) != 0)
2435 return (error);
2436 vp = nd.ni_vp;
2437 if (vp->v_type != VDIR) {
2438 error = ENOTDIR;
2439 goto out;
2440 }
2441 /*
2442 * No rmdir "." please.
2443 */
2444 if (nd.ni_dvp == vp) {
2445 error = EINVAL;
2446 goto out;
2447 }
2448 /*
2449 * The root of a mounted filesystem cannot be deleted.
2450 */
2451 if (vp->v_flag & VROOT)
2452 error = EBUSY;
2453 out:
2454 if (!error) {
2455 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2456 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2457 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2458 } else {
2459 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2460 if (nd.ni_dvp == vp)
2461 vrele(nd.ni_dvp);
2462 else
2463 vput(nd.ni_dvp);
2464 vput(vp);
2465 }
2466 return (error);
2467 }
2468
2469 /*
2470 * Read a block of directory entries in a file system independent format.
2471 */
2472 int
2473 sys_getdents(p, v, retval)
2474 struct proc *p;
2475 void *v;
2476 register_t *retval;
2477 {
2478 register struct sys_getdents_args /* {
2479 syscallarg(int) fd;
2480 syscallarg(char *) buf;
2481 syscallarg(size_t) count;
2482 } */ *uap = v;
2483 struct file *fp;
2484 int error, done;
2485
2486 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2487 return (error);
2488 if ((fp->f_flag & FREAD) == 0)
2489 return (EBADF);
2490 error = vn_readdir(fp, SCARG(uap, buf), UIO_USERSPACE,
2491 SCARG(uap, count), &done, p, 0, 0);
2492 *retval = done;
2493 return (error);
2494 }
2495
2496 /*
2497 * Set the mode mask for creation of filesystem nodes.
2498 */
2499 int
2500 sys_umask(p, v, retval)
2501 struct proc *p;
2502 void *v;
2503 register_t *retval;
2504 {
2505 struct sys_umask_args /* {
2506 syscallarg(mode_t) newmask;
2507 } */ *uap = v;
2508 register struct filedesc *fdp;
2509
2510 fdp = p->p_fd;
2511 *retval = fdp->fd_cmask;
2512 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
2513 return (0);
2514 }
2515
2516 /*
2517 * Void all references to file by ripping underlying filesystem
2518 * away from vnode.
2519 */
2520 /* ARGSUSED */
2521 int
2522 sys_revoke(p, v, retval)
2523 struct proc *p;
2524 void *v;
2525 register_t *retval;
2526 {
2527 register struct sys_revoke_args /* {
2528 syscallarg(const char *) path;
2529 } */ *uap = v;
2530 register struct vnode *vp;
2531 struct vattr vattr;
2532 int error;
2533 struct nameidata nd;
2534
2535 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2536 if ((error = namei(&nd)) != 0)
2537 return (error);
2538 vp = nd.ni_vp;
2539 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
2540 goto out;
2541 if (p->p_ucred->cr_uid != vattr.va_uid &&
2542 (error = suser(p->p_ucred, &p->p_acflag)) != 0)
2543 goto out;
2544 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
2545 VOP_REVOKE(vp, REVOKEALL);
2546 out:
2547 vrele(vp);
2548 return (error);
2549 }
2550
2551 /*
2552 * Convert a user file descriptor to a kernel file entry.
2553 */
2554 int
2555 getvnode(fdp, fd, fpp)
2556 struct filedesc *fdp;
2557 int fd;
2558 struct file **fpp;
2559 {
2560 struct vnode *vp;
2561 struct file *fp;
2562
2563 if ((u_int)fd >= fdp->fd_nfiles ||
2564 (fp = fdp->fd_ofiles[fd]) == NULL)
2565 return (EBADF);
2566 if (fp->f_type != DTYPE_VNODE)
2567 return (EINVAL);
2568 vp = (struct vnode *)fp->f_data;
2569 if (vp->v_type == VBAD)
2570 return (EBADF);
2571 *fpp = fp;
2572 return (0);
2573 }
2574