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