vfs_syscalls.c revision 1.133.2.1 1 /* $NetBSD: vfs_syscalls.c,v 1.133.2.1 2000/02/01 23:10:54 he 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 filedesc *fdp;
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 fdp = p->p_fd;
366 if (fdp->fd_cdir == olddp) {
367 vrele(fdp->fd_cdir);
368 VREF(newdp);
369 fdp->fd_cdir = newdp;
370 }
371 if (fdp->fd_rdir == olddp) {
372 vrele(fdp->fd_rdir);
373 VREF(newdp);
374 fdp->fd_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 register struct filedesc *fdp = p->p_fd;
707 struct vnode *vp, *tdp;
708 struct mount *mp;
709 struct file *fp;
710 int error;
711
712 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
713 return (error);
714 vp = (struct vnode *)fp->f_data;
715
716 VREF(vp);
717 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
718 if (vp->v_type != VDIR)
719 error = ENOTDIR;
720 else
721 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
722 while (!error && (mp = vp->v_mountedhere) != NULL) {
723 if (vfs_busy(mp, 0, 0))
724 continue;
725 error = VFS_ROOT(mp, &tdp);
726 vfs_unbusy(mp);
727 if (error)
728 break;
729 vput(vp);
730 vp = tdp;
731 }
732 if (error) {
733 vput(vp);
734 return (error);
735 }
736 VOP_UNLOCK(vp, 0);
737
738 /*
739 * Disallow changing to a directory not under the process's
740 * current root directory (if there is one).
741 */
742 if (fdp->fd_rdir &&
743 !vn_isunder(vp, NULL, p)) {
744 vrele(vp);
745 return EPERM; /* operation not permitted */
746 }
747
748 vrele(fdp->fd_cdir);
749 fdp->fd_cdir = vp;
750 return (0);
751 }
752
753 /*
754 * Change this process's notion of the root directory to a given file descriptor.
755 */
756
757 int
758 sys_fchroot(p, v, retval)
759 struct proc *p;
760 void *v;
761 register_t *retval;
762 {
763 struct sys_fchroot_args *uap = v;
764 struct filedesc *fdp = p->p_fd;
765 struct vnode *vp;
766 struct file *fp;
767 int error;
768
769 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
770 return error;
771 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
772 return error;
773 vp = (struct vnode *) fp->f_data;
774 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
775 if (vp->v_type != VDIR)
776 error = ENOTDIR;
777 else
778 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
779 VOP_UNLOCK(vp, 0);
780 if (error)
781 return error;
782 VREF(vp);
783
784 /*
785 * Prevent escaping from chroot by putting the root under
786 * the working directory. Silently chdir to / if we aren't
787 * already there.
788 */
789 if (!vn_isunder(fdp->fd_cdir, vp, p)) {
790 /*
791 * XXX would be more failsafe to change directory to a
792 * deadfs node here instead
793 */
794 vrele(fdp->fd_cdir);
795 VREF(vp);
796 fdp->fd_cdir = vp;
797 }
798
799 if (fdp->fd_rdir != NULL)
800 vrele(fdp->fd_rdir);
801 fdp->fd_rdir = vp;
802 return 0;
803 }
804
805
806
807 /*
808 * Change current working directory (``.'').
809 */
810 /* ARGSUSED */
811 int
812 sys_chdir(p, v, retval)
813 struct proc *p;
814 void *v;
815 register_t *retval;
816 {
817 struct sys_chdir_args /* {
818 syscallarg(const char *) path;
819 } */ *uap = v;
820 register struct filedesc *fdp = p->p_fd;
821 int error;
822 struct nameidata nd;
823
824 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
825 SCARG(uap, path), p);
826 if ((error = change_dir(&nd, p)) != 0)
827 return (error);
828 vrele(fdp->fd_cdir);
829 fdp->fd_cdir = nd.ni_vp;
830 return (0);
831 }
832
833 /*
834 * Change notion of root (``/'') directory.
835 */
836 /* ARGSUSED */
837 int
838 sys_chroot(p, v, retval)
839 struct proc *p;
840 void *v;
841 register_t *retval;
842 {
843 struct sys_chroot_args /* {
844 syscallarg(const char *) path;
845 } */ *uap = v;
846 register struct filedesc *fdp = p->p_fd;
847 struct vnode *vp;
848 int error;
849 struct nameidata nd;
850
851 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
852 return (error);
853 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
854 SCARG(uap, path), p);
855 if ((error = change_dir(&nd, p)) != 0)
856 return (error);
857 if (fdp->fd_rdir != NULL)
858 vrele(fdp->fd_rdir);
859 vp = nd.ni_vp;
860 fdp->fd_rdir = vp;
861
862 /*
863 * Prevent escaping from chroot by putting the root under
864 * the working directory. Silently chdir to / if we aren't
865 * already there.
866 */
867 if (!vn_isunder(fdp->fd_cdir, vp, p)) {
868 /*
869 * XXX would be more failsafe to change directory to a
870 * deadfs node here instead
871 */
872 vrele(fdp->fd_cdir);
873 VREF(vp);
874 fdp->fd_cdir = vp;
875 }
876
877 return (0);
878 }
879
880 /*
881 * Common routine for chroot and chdir.
882 */
883 static int
884 change_dir(ndp, p)
885 register struct nameidata *ndp;
886 struct proc *p;
887 {
888 struct vnode *vp;
889 int error;
890
891 if ((error = namei(ndp)) != 0)
892 return (error);
893 vp = ndp->ni_vp;
894 if (vp->v_type != VDIR)
895 error = ENOTDIR;
896 else
897 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
898
899 if (error)
900 vput(vp);
901 else
902 VOP_UNLOCK(vp, 0);
903 return (error);
904 }
905
906 /*
907 * Check permissions, allocate an open file structure,
908 * and call the device open routine if any.
909 */
910 int
911 sys_open(p, v, retval)
912 struct proc *p;
913 void *v;
914 register_t *retval;
915 {
916 register struct sys_open_args /* {
917 syscallarg(const char *) path;
918 syscallarg(int) flags;
919 syscallarg(int) mode;
920 } */ *uap = v;
921 register struct filedesc *fdp = p->p_fd;
922 register struct file *fp;
923 register struct vnode *vp;
924 int flags, cmode;
925 struct file *nfp;
926 int type, indx, error;
927 struct flock lf;
928 struct nameidata nd;
929
930 flags = FFLAGS(SCARG(uap, flags));
931 if ((flags & (FREAD | FWRITE)) == 0)
932 return (EINVAL);
933 if ((error = falloc(p, &nfp, &indx)) != 0)
934 return (error);
935 fp = nfp;
936 cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
937 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
938 p->p_dupfd = -indx - 1; /* XXX check for fdopen */
939 if ((error = vn_open(&nd, flags, cmode)) != 0) {
940 ffree(fp);
941 if ((error == ENODEV || error == ENXIO) &&
942 p->p_dupfd >= 0 && /* XXX from fdopen */
943 (error =
944 dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
945 *retval = indx;
946 return (0);
947 }
948 if (error == ERESTART)
949 error = EINTR;
950 fdp->fd_ofiles[indx] = NULL;
951 return (error);
952 }
953 p->p_dupfd = 0;
954 vp = nd.ni_vp;
955 fp->f_flag = flags & FMASK;
956 fp->f_type = DTYPE_VNODE;
957 fp->f_ops = &vnops;
958 fp->f_data = (caddr_t)vp;
959 if (flags & (O_EXLOCK | O_SHLOCK)) {
960 lf.l_whence = SEEK_SET;
961 lf.l_start = 0;
962 lf.l_len = 0;
963 if (flags & O_EXLOCK)
964 lf.l_type = F_WRLCK;
965 else
966 lf.l_type = F_RDLCK;
967 type = F_FLOCK;
968 if ((flags & FNONBLOCK) == 0)
969 type |= F_WAIT;
970 VOP_UNLOCK(vp, 0);
971 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
972 if (error) {
973 (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
974 ffree(fp);
975 fdp->fd_ofiles[indx] = NULL;
976 return (error);
977 }
978 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
979 fp->f_flag |= FHASLOCK;
980 }
981 VOP_UNLOCK(vp, 0);
982 *retval = indx;
983 return (0);
984 }
985
986 /*
987 * Create a special file.
988 */
989 /* ARGSUSED */
990 int
991 sys_mknod(p, v, retval)
992 struct proc *p;
993 void *v;
994 register_t *retval;
995 {
996 register struct sys_mknod_args /* {
997 syscallarg(const char *) path;
998 syscallarg(int) mode;
999 syscallarg(int) dev;
1000 } */ *uap = v;
1001 register struct vnode *vp;
1002 struct vattr vattr;
1003 int error;
1004 int whiteout = 0;
1005 struct nameidata nd;
1006
1007 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
1008 return (error);
1009 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1010 if ((error = namei(&nd)) != 0)
1011 return (error);
1012 vp = nd.ni_vp;
1013 if (vp != NULL)
1014 error = EEXIST;
1015 else {
1016 VATTR_NULL(&vattr);
1017 vattr.va_mode =
1018 (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1019 vattr.va_rdev = SCARG(uap, dev);
1020 whiteout = 0;
1021
1022 switch (SCARG(uap, mode) & S_IFMT) {
1023 case S_IFMT: /* used by badsect to flag bad sectors */
1024 vattr.va_type = VBAD;
1025 break;
1026 case S_IFCHR:
1027 vattr.va_type = VCHR;
1028 break;
1029 case S_IFBLK:
1030 vattr.va_type = VBLK;
1031 break;
1032 case S_IFWHT:
1033 whiteout = 1;
1034 break;
1035 default:
1036 error = EINVAL;
1037 break;
1038 }
1039 }
1040 if (!error) {
1041 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1042 if (whiteout) {
1043 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
1044 if (error)
1045 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1046 vput(nd.ni_dvp);
1047 } else {
1048 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1049 &nd.ni_cnd, &vattr);
1050 }
1051 } else {
1052 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1053 if (nd.ni_dvp == vp)
1054 vrele(nd.ni_dvp);
1055 else
1056 vput(nd.ni_dvp);
1057 if (vp)
1058 vrele(vp);
1059 }
1060 return (error);
1061 }
1062
1063 /*
1064 * Create a named pipe.
1065 */
1066 /* ARGSUSED */
1067 int
1068 sys_mkfifo(p, v, retval)
1069 struct proc *p;
1070 void *v;
1071 register_t *retval;
1072 {
1073 register struct sys_mkfifo_args /* {
1074 syscallarg(const char *) path;
1075 syscallarg(int) mode;
1076 } */ *uap = v;
1077 struct vattr vattr;
1078 int error;
1079 struct nameidata nd;
1080
1081 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1082 if ((error = namei(&nd)) != 0)
1083 return (error);
1084 if (nd.ni_vp != NULL) {
1085 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1086 if (nd.ni_dvp == nd.ni_vp)
1087 vrele(nd.ni_dvp);
1088 else
1089 vput(nd.ni_dvp);
1090 vrele(nd.ni_vp);
1091 return (EEXIST);
1092 }
1093 VATTR_NULL(&vattr);
1094 vattr.va_type = VFIFO;
1095 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1096 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1097 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
1098 }
1099
1100 /*
1101 * Make a hard file link.
1102 */
1103 /* ARGSUSED */
1104 int
1105 sys_link(p, v, retval)
1106 struct proc *p;
1107 void *v;
1108 register_t *retval;
1109 {
1110 register struct sys_link_args /* {
1111 syscallarg(const char *) path;
1112 syscallarg(const char *) link;
1113 } */ *uap = v;
1114 register struct vnode *vp;
1115 struct nameidata nd;
1116 int error;
1117
1118 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1119 if ((error = namei(&nd)) != 0)
1120 return (error);
1121 vp = nd.ni_vp;
1122 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
1123 if ((error = namei(&nd)) != 0)
1124 goto out;
1125 if (nd.ni_vp) {
1126 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1127 if (nd.ni_dvp == nd.ni_vp)
1128 vrele(nd.ni_dvp);
1129 else
1130 vput(nd.ni_dvp);
1131 vrele(nd.ni_vp);
1132 error = EEXIST;
1133 goto out;
1134 }
1135 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1136 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1137 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1138 out:
1139 vrele(vp);
1140 return (error);
1141 }
1142
1143 /*
1144 * Make a symbolic link.
1145 */
1146 /* ARGSUSED */
1147 int
1148 sys_symlink(p, v, retval)
1149 struct proc *p;
1150 void *v;
1151 register_t *retval;
1152 {
1153 register struct sys_symlink_args /* {
1154 syscallarg(const char *) path;
1155 syscallarg(const char *) link;
1156 } */ *uap = v;
1157 struct vattr vattr;
1158 char *path;
1159 int error;
1160 struct nameidata nd;
1161
1162 MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
1163 error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL);
1164 if (error)
1165 goto out;
1166 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
1167 if ((error = namei(&nd)) != 0)
1168 goto out;
1169 if (nd.ni_vp) {
1170 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1171 if (nd.ni_dvp == nd.ni_vp)
1172 vrele(nd.ni_dvp);
1173 else
1174 vput(nd.ni_dvp);
1175 vrele(nd.ni_vp);
1176 error = EEXIST;
1177 goto out;
1178 }
1179 VATTR_NULL(&vattr);
1180 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
1181 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1182 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
1183 out:
1184 FREE(path, M_NAMEI);
1185 return (error);
1186 }
1187
1188 /*
1189 * Delete a whiteout from the filesystem.
1190 */
1191 /* ARGSUSED */
1192 int
1193 sys_undelete(p, v, retval)
1194 struct proc *p;
1195 void *v;
1196 register_t *retval;
1197 {
1198 register struct sys_undelete_args /* {
1199 syscallarg(const char *) path;
1200 } */ *uap = v;
1201 int error;
1202 struct nameidata nd;
1203
1204 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
1205 SCARG(uap, path), p);
1206 error = namei(&nd);
1207 if (error)
1208 return (error);
1209
1210 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1211 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1212 if (nd.ni_dvp == nd.ni_vp)
1213 vrele(nd.ni_dvp);
1214 else
1215 vput(nd.ni_dvp);
1216 if (nd.ni_vp)
1217 vrele(nd.ni_vp);
1218 return (EEXIST);
1219 }
1220
1221 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1222 if ((error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) != 0)
1223 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1224 vput(nd.ni_dvp);
1225 return (error);
1226 }
1227
1228 /*
1229 * Delete a name from the filesystem.
1230 */
1231 /* ARGSUSED */
1232 int
1233 sys_unlink(p, v, retval)
1234 struct proc *p;
1235 void *v;
1236 register_t *retval;
1237 {
1238 struct sys_unlink_args /* {
1239 syscallarg(const char *) path;
1240 } */ *uap = v;
1241 register struct vnode *vp;
1242 int error;
1243 struct nameidata nd;
1244
1245 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
1246 SCARG(uap, path), p);
1247 if ((error = namei(&nd)) != 0)
1248 return (error);
1249 vp = nd.ni_vp;
1250
1251 /*
1252 * The root of a mounted filesystem cannot be deleted.
1253 */
1254 if (vp->v_flag & VROOT) {
1255 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1256 if (nd.ni_dvp == vp)
1257 vrele(nd.ni_dvp);
1258 else
1259 vput(nd.ni_dvp);
1260 vput(vp);
1261 error = EBUSY;
1262 goto out;
1263 }
1264
1265 (void)uvm_vnp_uncache(vp);
1266
1267 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1268 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1269 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1270 out:
1271 return (error);
1272 }
1273
1274 /*
1275 * Reposition read/write file offset.
1276 */
1277 int
1278 sys_lseek(p, v, retval)
1279 struct proc *p;
1280 void *v;
1281 register_t *retval;
1282 {
1283 register struct sys_lseek_args /* {
1284 syscallarg(int) fd;
1285 syscallarg(int) pad;
1286 syscallarg(off_t) offset;
1287 syscallarg(int) whence;
1288 } */ *uap = v;
1289 struct ucred *cred = p->p_ucred;
1290 register struct filedesc *fdp = p->p_fd;
1291 register struct file *fp;
1292 struct vnode *vp;
1293 struct vattr vattr;
1294 register off_t newoff;
1295 int error;
1296
1297 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
1298 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
1299 return (EBADF);
1300
1301 vp = (struct vnode *)fp->f_data;
1302 if (fp->f_type != DTYPE_VNODE
1303 || vp->v_type == VFIFO)
1304 return (ESPIPE);
1305
1306 switch (SCARG(uap, whence)) {
1307 case SEEK_CUR:
1308 newoff = fp->f_offset + SCARG(uap, offset);
1309 break;
1310 case SEEK_END:
1311 error = VOP_GETATTR(vp, &vattr, cred, p);
1312 if (error)
1313 return (error);
1314 newoff = SCARG(uap, offset) + vattr.va_size;
1315 break;
1316 case SEEK_SET:
1317 newoff = SCARG(uap, offset);
1318 break;
1319 default:
1320 return (EINVAL);
1321 }
1322 if ((error = VOP_SEEK(vp, fp->f_offset, newoff, cred)) != 0)
1323 return (error);
1324
1325 *(off_t *)retval = fp->f_offset = newoff;
1326 return (0);
1327 }
1328
1329 /*
1330 * Positional read system call.
1331 */
1332 int
1333 sys_pread(p, v, retval)
1334 struct proc *p;
1335 void *v;
1336 register_t *retval;
1337 {
1338 struct sys_pread_args /* {
1339 syscallarg(int) fd;
1340 syscallarg(void *) buf;
1341 syscallarg(size_t) nbyte;
1342 syscallarg(off_t) offset;
1343 } */ *uap = v;
1344 struct filedesc *fdp = p->p_fd;
1345 struct file *fp;
1346 struct vnode *vp;
1347 off_t offset;
1348 int error, fd = SCARG(uap, fd);
1349
1350 if ((u_int)fd >= fdp->fd_nfiles ||
1351 (fp = fdp->fd_ofiles[fd]) == NULL ||
1352 (fp->f_flag & FREAD) == 0)
1353 return (EBADF);
1354
1355 vp = (struct vnode *)fp->f_data;
1356 if (fp->f_type != DTYPE_VNODE
1357 || vp->v_type == VFIFO)
1358 return (ESPIPE);
1359
1360 offset = SCARG(uap, offset);
1361
1362 /*
1363 * XXX This works because no file systems actually
1364 * XXX take any action on the seek operation.
1365 */
1366 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1367 return (error);
1368
1369 return (dofileread(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
1370 &offset, 0, retval));
1371 }
1372
1373 /*
1374 * Positional scatter read system call.
1375 */
1376 int
1377 sys_preadv(p, v, retval)
1378 struct proc *p;
1379 void *v;
1380 register_t *retval;
1381 {
1382 struct sys_preadv_args /* {
1383 syscallarg(int) fd;
1384 syscallarg(const struct iovec *) iovp;
1385 syscallarg(int) iovcnt;
1386 syscallarg(off_t) offset;
1387 } */ *uap = v;
1388 struct filedesc *fdp = p->p_fd;
1389 struct file *fp;
1390 struct vnode *vp;
1391 off_t offset;
1392 int error, fd = SCARG(uap, fd);
1393
1394 if ((u_int)fd >= fdp->fd_nfiles ||
1395 (fp = fdp->fd_ofiles[fd]) == NULL ||
1396 (fp->f_flag & FREAD) == 0)
1397 return (EBADF);
1398
1399 vp = (struct vnode *)fp->f_data;
1400 if (fp->f_type != DTYPE_VNODE
1401 || vp->v_type == VFIFO)
1402 return (ESPIPE);
1403
1404 offset = SCARG(uap, offset);
1405
1406 /*
1407 * XXX This works because no file systems actually
1408 * XXX take any action on the seek operation.
1409 */
1410 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1411 return (error);
1412
1413 return (dofilereadv(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
1414 &offset, 0, retval));
1415 }
1416
1417 /*
1418 * Positional write system call.
1419 */
1420 int
1421 sys_pwrite(p, v, retval)
1422 struct proc *p;
1423 void *v;
1424 register_t *retval;
1425 {
1426 struct sys_pwrite_args /* {
1427 syscallarg(int) fd;
1428 syscallarg(const void *) buf;
1429 syscallarg(size_t) nbyte;
1430 syscallarg(off_t) offset;
1431 } */ *uap = v;
1432 struct filedesc *fdp = p->p_fd;
1433 struct file *fp;
1434 struct vnode *vp;
1435 off_t offset;
1436 int error, fd = SCARG(uap, fd);
1437
1438 if ((u_int)fd >= fdp->fd_nfiles ||
1439 (fp = fdp->fd_ofiles[fd]) == NULL ||
1440 (fp->f_flag & FWRITE) == 0)
1441 return (EBADF);
1442
1443 vp = (struct vnode *)fp->f_data;
1444 if (fp->f_type != DTYPE_VNODE
1445 || vp->v_type == VFIFO)
1446 return (ESPIPE);
1447
1448 offset = SCARG(uap, offset);
1449
1450 /*
1451 * XXX This works because no file systems actually
1452 * XXX take any action on the seek operation.
1453 */
1454 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1455 return (error);
1456
1457 return (dofilewrite(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
1458 &offset, 0, retval));
1459 }
1460
1461 /*
1462 * Positional gather write system call.
1463 */
1464 int
1465 sys_pwritev(p, v, retval)
1466 struct proc *p;
1467 void *v;
1468 register_t *retval;
1469 {
1470 struct sys_pwritev_args /* {
1471 syscallarg(int) fd;
1472 syscallarg(const struct iovec *) iovp;
1473 syscallarg(int) iovcnt;
1474 syscallarg(off_t) offset;
1475 } */ *uap = v;
1476 struct filedesc *fdp = p->p_fd;
1477 struct file *fp;
1478 struct vnode *vp;
1479 off_t offset;
1480 int error, fd = SCARG(uap, fd);
1481
1482 if ((u_int)fd >= fdp->fd_nfiles ||
1483 (fp = fdp->fd_ofiles[fd]) == NULL ||
1484 (fp->f_flag & FWRITE) == 0)
1485 return (EBADF);
1486
1487 vp = (struct vnode *)fp->f_data;
1488 if (fp->f_type != DTYPE_VNODE
1489 || vp->v_type == VFIFO)
1490 return (ESPIPE);
1491
1492 offset = SCARG(uap, offset);
1493
1494 /*
1495 * XXX This works because no file systems actually
1496 * XXX take any action on the seek operation.
1497 */
1498 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1499 return (error);
1500
1501 return (dofilewritev(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
1502 &offset, 0, retval));
1503 }
1504
1505 /*
1506 * Check access permissions.
1507 */
1508 int
1509 sys_access(p, v, retval)
1510 struct proc *p;
1511 void *v;
1512 register_t *retval;
1513 {
1514 register struct sys_access_args /* {
1515 syscallarg(const char *) path;
1516 syscallarg(int) flags;
1517 } */ *uap = v;
1518 register struct ucred *cred = p->p_ucred;
1519 register struct vnode *vp;
1520 int error, flags, t_gid, t_uid;
1521 struct nameidata nd;
1522
1523 t_uid = cred->cr_uid;
1524 t_gid = cred->cr_gid;
1525 cred->cr_uid = p->p_cred->p_ruid;
1526 cred->cr_gid = p->p_cred->p_rgid;
1527 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1528 SCARG(uap, path), p);
1529 if ((error = namei(&nd)) != 0)
1530 goto out1;
1531 vp = nd.ni_vp;
1532
1533 /* Flags == 0 means only check for existence. */
1534 if (SCARG(uap, flags)) {
1535 flags = 0;
1536 if (SCARG(uap, flags) & R_OK)
1537 flags |= VREAD;
1538 if (SCARG(uap, flags) & W_OK)
1539 flags |= VWRITE;
1540 if (SCARG(uap, flags) & X_OK)
1541 flags |= VEXEC;
1542 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1543 error = VOP_ACCESS(vp, flags, cred, p);
1544 }
1545 vput(vp);
1546 out1:
1547 cred->cr_uid = t_uid;
1548 cred->cr_gid = t_gid;
1549 return (error);
1550 }
1551
1552 /*
1553 * Get file status; this version follows links.
1554 */
1555 /* ARGSUSED */
1556 int
1557 sys___stat13(p, v, retval)
1558 struct proc *p;
1559 void *v;
1560 register_t *retval;
1561 {
1562 register struct sys___stat13_args /* {
1563 syscallarg(const char *) path;
1564 syscallarg(struct stat *) ub;
1565 } */ *uap = v;
1566 struct stat sb;
1567 int error;
1568 struct nameidata nd;
1569
1570 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1571 SCARG(uap, path), p);
1572 if ((error = namei(&nd)) != 0)
1573 return (error);
1574 error = vn_stat(nd.ni_vp, &sb, p);
1575 vput(nd.ni_vp);
1576 if (error)
1577 return (error);
1578 error = copyout(&sb, SCARG(uap, ub), sizeof(sb));
1579 return (error);
1580 }
1581
1582 /*
1583 * Get file status; this version does not follow links.
1584 */
1585 /* ARGSUSED */
1586 int
1587 sys___lstat13(p, v, retval)
1588 struct proc *p;
1589 void *v;
1590 register_t *retval;
1591 {
1592 register struct sys___lstat13_args /* {
1593 syscallarg(const char *) path;
1594 syscallarg(struct stat *) ub;
1595 } */ *uap = v;
1596 struct stat sb;
1597 int error;
1598 struct nameidata nd;
1599
1600 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
1601 SCARG(uap, path), p);
1602 if ((error = namei(&nd)) != 0)
1603 return (error);
1604 error = vn_stat(nd.ni_vp, &sb, p);
1605 vput(nd.ni_vp);
1606 if (error)
1607 return (error);
1608 error = copyout(&sb, SCARG(uap, ub), sizeof(sb));
1609 return (error);
1610 }
1611
1612 /*
1613 * Get configurable pathname variables.
1614 */
1615 /* ARGSUSED */
1616 int
1617 sys_pathconf(p, v, retval)
1618 struct proc *p;
1619 void *v;
1620 register_t *retval;
1621 {
1622 register struct sys_pathconf_args /* {
1623 syscallarg(const char *) path;
1624 syscallarg(int) name;
1625 } */ *uap = v;
1626 int error;
1627 struct nameidata nd;
1628
1629 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1630 SCARG(uap, path), p);
1631 if ((error = namei(&nd)) != 0)
1632 return (error);
1633 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
1634 vput(nd.ni_vp);
1635 return (error);
1636 }
1637
1638 /*
1639 * Return target name of a symbolic link.
1640 */
1641 /* ARGSUSED */
1642 int
1643 sys_readlink(p, v, retval)
1644 struct proc *p;
1645 void *v;
1646 register_t *retval;
1647 {
1648 register struct sys_readlink_args /* {
1649 syscallarg(const char *) path;
1650 syscallarg(char *) buf;
1651 syscallarg(size_t) count;
1652 } */ *uap = v;
1653 register struct vnode *vp;
1654 struct iovec aiov;
1655 struct uio auio;
1656 int error;
1657 struct nameidata nd;
1658
1659 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
1660 SCARG(uap, path), p);
1661 if ((error = namei(&nd)) != 0)
1662 return (error);
1663 vp = nd.ni_vp;
1664 if (vp->v_type != VLNK)
1665 error = EINVAL;
1666 else if (!(vp->v_mount->mnt_flag & MNT_SYMPERM) ||
1667 (error = VOP_ACCESS(vp, VREAD, p->p_ucred, p)) == 0) {
1668 aiov.iov_base = SCARG(uap, buf);
1669 aiov.iov_len = SCARG(uap, count);
1670 auio.uio_iov = &aiov;
1671 auio.uio_iovcnt = 1;
1672 auio.uio_offset = 0;
1673 auio.uio_rw = UIO_READ;
1674 auio.uio_segflg = UIO_USERSPACE;
1675 auio.uio_procp = p;
1676 auio.uio_resid = SCARG(uap, count);
1677 error = VOP_READLINK(vp, &auio, p->p_ucred);
1678 }
1679 vput(vp);
1680 *retval = SCARG(uap, count) - auio.uio_resid;
1681 return (error);
1682 }
1683
1684 /*
1685 * Change flags of a file given a path name.
1686 */
1687 /* ARGSUSED */
1688 int
1689 sys_chflags(p, v, retval)
1690 struct proc *p;
1691 void *v;
1692 register_t *retval;
1693 {
1694 register struct sys_chflags_args /* {
1695 syscallarg(const char *) path;
1696 syscallarg(u_long) flags;
1697 } */ *uap = v;
1698 register struct vnode *vp;
1699 struct vattr vattr;
1700 int error;
1701 struct nameidata nd;
1702
1703 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1704 if ((error = namei(&nd)) != 0)
1705 return (error);
1706 vp = nd.ni_vp;
1707 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1708 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1709 VATTR_NULL(&vattr);
1710 vattr.va_flags = SCARG(uap, flags);
1711 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1712 vput(vp);
1713 return (error);
1714 }
1715
1716 /*
1717 * Change flags of a file given a file descriptor.
1718 */
1719 /* ARGSUSED */
1720 int
1721 sys_fchflags(p, v, retval)
1722 struct proc *p;
1723 void *v;
1724 register_t *retval;
1725 {
1726 register struct sys_fchflags_args /* {
1727 syscallarg(int) fd;
1728 syscallarg(u_long) flags;
1729 } */ *uap = v;
1730 struct vattr vattr;
1731 struct vnode *vp;
1732 struct file *fp;
1733 int error;
1734
1735 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1736 return (error);
1737 vp = (struct vnode *)fp->f_data;
1738 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1739 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1740 VATTR_NULL(&vattr);
1741 vattr.va_flags = SCARG(uap, flags);
1742 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1743 VOP_UNLOCK(vp, 0);
1744 return (error);
1745 }
1746
1747 /*
1748 * Change mode of a file given path name; this version follows links.
1749 */
1750 /* ARGSUSED */
1751 int
1752 sys_chmod(p, v, retval)
1753 struct proc *p;
1754 void *v;
1755 register_t *retval;
1756 {
1757 register struct sys_chmod_args /* {
1758 syscallarg(const char *) path;
1759 syscallarg(int) mode;
1760 } */ *uap = v;
1761 int error;
1762 struct nameidata nd;
1763
1764 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1765 if ((error = namei(&nd)) != 0)
1766 return (error);
1767
1768 error = change_mode(nd.ni_vp, SCARG(uap, mode), p);
1769
1770 vrele(nd.ni_vp);
1771 return (error);
1772 }
1773
1774 /*
1775 * Change mode of a file given a file descriptor.
1776 */
1777 /* ARGSUSED */
1778 int
1779 sys_fchmod(p, v, retval)
1780 struct proc *p;
1781 void *v;
1782 register_t *retval;
1783 {
1784 register struct sys_fchmod_args /* {
1785 syscallarg(int) fd;
1786 syscallarg(int) mode;
1787 } */ *uap = v;
1788 struct file *fp;
1789 int error;
1790
1791 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1792 return (error);
1793
1794 return (change_mode((struct vnode *)fp->f_data, SCARG(uap, mode), p));
1795 }
1796
1797 /*
1798 * Change mode of a file given path name; this version does not follow links.
1799 */
1800 /* ARGSUSED */
1801 int
1802 sys_lchmod(p, v, retval)
1803 struct proc *p;
1804 void *v;
1805 register_t *retval;
1806 {
1807 register struct sys_lchmod_args /* {
1808 syscallarg(const char *) path;
1809 syscallarg(int) mode;
1810 } */ *uap = v;
1811 int error;
1812 struct nameidata nd;
1813
1814 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1815 if ((error = namei(&nd)) != 0)
1816 return (error);
1817
1818 error = change_mode(nd.ni_vp, SCARG(uap, mode), p);
1819
1820 vrele(nd.ni_vp);
1821 return (error);
1822 }
1823
1824 /*
1825 * Common routine to set mode given a vnode.
1826 */
1827 static int
1828 change_mode(vp, mode, p)
1829 struct vnode *vp;
1830 int mode;
1831 struct proc *p;
1832 {
1833 struct vattr vattr;
1834 int error;
1835
1836 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1837 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1838 VATTR_NULL(&vattr);
1839 vattr.va_mode = mode & ALLPERMS;
1840 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1841 VOP_UNLOCK(vp, 0);
1842 return (error);
1843 }
1844
1845 /*
1846 * Set ownership given a path name; this version follows links.
1847 */
1848 /* ARGSUSED */
1849 int
1850 sys_chown(p, v, retval)
1851 struct proc *p;
1852 void *v;
1853 register_t *retval;
1854 {
1855 register struct sys_chown_args /* {
1856 syscallarg(const char *) path;
1857 syscallarg(uid_t) uid;
1858 syscallarg(gid_t) gid;
1859 } */ *uap = v;
1860 int error;
1861 struct nameidata nd;
1862
1863 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1864 if ((error = namei(&nd)) != 0)
1865 return (error);
1866
1867 error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 0);
1868
1869 vrele(nd.ni_vp);
1870 return (error);
1871 }
1872
1873 /*
1874 * Set ownership given a path name; this version follows links.
1875 * Provides POSIX semantics.
1876 */
1877 /* ARGSUSED */
1878 int
1879 sys___posix_chown(p, v, retval)
1880 struct proc *p;
1881 void *v;
1882 register_t *retval;
1883 {
1884 register struct sys_chown_args /* {
1885 syscallarg(const char *) path;
1886 syscallarg(uid_t) uid;
1887 syscallarg(gid_t) gid;
1888 } */ *uap = v;
1889 int error;
1890 struct nameidata nd;
1891
1892 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1893 if ((error = namei(&nd)) != 0)
1894 return (error);
1895
1896 error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 1);
1897
1898 vrele(nd.ni_vp);
1899 return (error);
1900 }
1901
1902 /*
1903 * Set ownership given a file descriptor.
1904 */
1905 /* ARGSUSED */
1906 int
1907 sys_fchown(p, v, retval)
1908 struct proc *p;
1909 void *v;
1910 register_t *retval;
1911 {
1912 register struct sys_fchown_args /* {
1913 syscallarg(int) fd;
1914 syscallarg(uid_t) uid;
1915 syscallarg(gid_t) gid;
1916 } */ *uap = v;
1917 int error;
1918 struct file *fp;
1919
1920 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1921 return (error);
1922
1923 return (change_owner((struct vnode *)fp->f_data, SCARG(uap, uid),
1924 SCARG(uap, gid), p, 0));
1925 }
1926
1927 /*
1928 * Set ownership given a file descriptor, providing POSIX/XPG semantics.
1929 */
1930 /* ARGSUSED */
1931 int
1932 sys___posix_fchown(p, v, retval)
1933 struct proc *p;
1934 void *v;
1935 register_t *retval;
1936 {
1937 register struct sys_fchown_args /* {
1938 syscallarg(int) fd;
1939 syscallarg(uid_t) uid;
1940 syscallarg(gid_t) gid;
1941 } */ *uap = v;
1942 int error;
1943 struct file *fp;
1944
1945 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1946 return (error);
1947
1948 return (change_owner((struct vnode *)fp->f_data, SCARG(uap, uid),
1949 SCARG(uap, gid), p, 1));
1950 }
1951
1952 /*
1953 * Set ownership given a path name; this version does not follow links.
1954 */
1955 /* ARGSUSED */
1956 int
1957 sys_lchown(p, v, retval)
1958 struct proc *p;
1959 void *v;
1960 register_t *retval;
1961 {
1962 register struct sys_lchown_args /* {
1963 syscallarg(const char *) path;
1964 syscallarg(uid_t) uid;
1965 syscallarg(gid_t) gid;
1966 } */ *uap = v;
1967 int error;
1968 struct nameidata nd;
1969
1970 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1971 if ((error = namei(&nd)) != 0)
1972 return (error);
1973
1974 error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 0);
1975
1976 vrele(nd.ni_vp);
1977 return (error);
1978 }
1979
1980 /*
1981 * Set ownership given a path name; this version does not follow links.
1982 * Provides POSIX/XPG semantics.
1983 */
1984 /* ARGSUSED */
1985 int
1986 sys___posix_lchown(p, v, retval)
1987 struct proc *p;
1988 void *v;
1989 register_t *retval;
1990 {
1991 register struct sys_lchown_args /* {
1992 syscallarg(const char *) path;
1993 syscallarg(uid_t) uid;
1994 syscallarg(gid_t) gid;
1995 } */ *uap = v;
1996 int error;
1997 struct nameidata nd;
1998
1999 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2000 if ((error = namei(&nd)) != 0)
2001 return (error);
2002
2003 error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 1);
2004
2005 vrele(nd.ni_vp);
2006 return (error);
2007 }
2008
2009 /*
2010 * Common routine to set ownership given a vnode.
2011 */
2012 static int
2013 change_owner(vp, uid, gid, p, posix_semantics)
2014 register struct vnode *vp;
2015 uid_t uid;
2016 gid_t gid;
2017 struct proc *p;
2018 int posix_semantics;
2019 {
2020 struct vattr vattr;
2021 mode_t newmode;
2022 int error;
2023
2024 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2025 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2026 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
2027 goto out;
2028
2029 #define CHANGED(x) ((x) != -1)
2030 newmode = vattr.va_mode;
2031 if (posix_semantics) {
2032 /*
2033 * POSIX/XPG semantics: if the caller is not the super-user,
2034 * clear set-user-id and set-group-id bits. Both POSIX and
2035 * the XPG consider the behaviour for calls by the super-user
2036 * implementation-defined; we leave the set-user-id and set-
2037 * group-id settings intact in that case.
2038 */
2039 if (suser(p->p_ucred, NULL) != 0)
2040 newmode &= ~(S_ISUID | S_ISGID);
2041 } else {
2042 /*
2043 * NetBSD semantics: when changing owner and/or group,
2044 * clear the respective bit(s).
2045 */
2046 if (CHANGED(uid))
2047 newmode &= ~S_ISUID;
2048 if (CHANGED(gid))
2049 newmode &= ~S_ISGID;
2050 }
2051 /* Update va_mode iff altered. */
2052 if (vattr.va_mode == newmode)
2053 newmode = VNOVAL;
2054
2055 VATTR_NULL(&vattr);
2056 vattr.va_uid = CHANGED(uid) ? uid : VNOVAL;
2057 vattr.va_gid = CHANGED(gid) ? gid : VNOVAL;
2058 vattr.va_mode = newmode;
2059 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2060 #undef CHANGED
2061
2062 out:
2063 VOP_UNLOCK(vp, 0);
2064 return (error);
2065 }
2066
2067 /*
2068 * Set the access and modification times given a path name; this
2069 * version follows links.
2070 */
2071 /* ARGSUSED */
2072 int
2073 sys_utimes(p, v, retval)
2074 struct proc *p;
2075 void *v;
2076 register_t *retval;
2077 {
2078 register struct sys_utimes_args /* {
2079 syscallarg(const char *) path;
2080 syscallarg(const struct timeval *) tptr;
2081 } */ *uap = v;
2082 int error;
2083 struct nameidata nd;
2084
2085 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2086 if ((error = namei(&nd)) != 0)
2087 return (error);
2088
2089 error = change_utimes(nd.ni_vp, SCARG(uap, tptr), p);
2090
2091 vrele(nd.ni_vp);
2092 return (error);
2093 }
2094
2095 /*
2096 * Set the access and modification times given a file descriptor.
2097 */
2098 /* ARGSUSED */
2099 int
2100 sys_futimes(p, v, retval)
2101 struct proc *p;
2102 void *v;
2103 register_t *retval;
2104 {
2105 register struct sys_futimes_args /* {
2106 syscallarg(int) fd;
2107 syscallarg(const struct timeval *) tptr;
2108 } */ *uap = v;
2109 int error;
2110 struct file *fp;
2111
2112 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2113 return (error);
2114
2115 return (change_utimes((struct vnode *)fp->f_data, SCARG(uap, tptr),
2116 p));
2117 }
2118
2119 /*
2120 * Set the access and modification times given a path name; this
2121 * version does not follow links.
2122 */
2123 /* ARGSUSED */
2124 int
2125 sys_lutimes(p, v, retval)
2126 struct proc *p;
2127 void *v;
2128 register_t *retval;
2129 {
2130 register struct sys_lutimes_args /* {
2131 syscallarg(const char *) path;
2132 syscallarg(const struct timeval *) tptr;
2133 } */ *uap = v;
2134 int error;
2135 struct nameidata nd;
2136
2137 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2138 if ((error = namei(&nd)) != 0)
2139 return (error);
2140
2141 error = change_utimes(nd.ni_vp, SCARG(uap, tptr), p);
2142
2143 vrele(nd.ni_vp);
2144 return (error);
2145 }
2146
2147 /*
2148 * Common routine to set access and modification times given a vnode.
2149 */
2150 static int
2151 change_utimes(vp, tptr, p)
2152 struct vnode *vp;
2153 const struct timeval *tptr;
2154 struct proc *p;
2155 {
2156 struct timeval tv[2];
2157 struct vattr vattr;
2158 int error;
2159
2160 VATTR_NULL(&vattr);
2161 if (tptr == NULL) {
2162 microtime(&tv[0]);
2163 tv[1] = tv[0];
2164 vattr.va_vaflags |= VA_UTIMES_NULL;
2165 } else {
2166 error = copyin(tptr, tv, sizeof(tv));
2167 if (error)
2168 return (error);
2169 }
2170 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2171 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2172 vattr.va_atime.tv_sec = tv[0].tv_sec;
2173 vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
2174 vattr.va_mtime.tv_sec = tv[1].tv_sec;
2175 vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
2176 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2177 VOP_UNLOCK(vp, 0);
2178 return (error);
2179 }
2180
2181 /*
2182 * Truncate a file given its path name.
2183 */
2184 /* ARGSUSED */
2185 int
2186 sys_truncate(p, v, retval)
2187 struct proc *p;
2188 void *v;
2189 register_t *retval;
2190 {
2191 register struct sys_truncate_args /* {
2192 syscallarg(const char *) path;
2193 syscallarg(int) pad;
2194 syscallarg(off_t) length;
2195 } */ *uap = v;
2196 register struct vnode *vp;
2197 struct vattr vattr;
2198 int error;
2199 struct nameidata nd;
2200
2201 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2202 if ((error = namei(&nd)) != 0)
2203 return (error);
2204 vp = nd.ni_vp;
2205 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2206 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2207 if (vp->v_type == VDIR)
2208 error = EISDIR;
2209 else if ((error = vn_writechk(vp)) == 0 &&
2210 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
2211 VATTR_NULL(&vattr);
2212 vattr.va_size = SCARG(uap, length);
2213 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2214 }
2215 vput(vp);
2216 return (error);
2217 }
2218
2219 /*
2220 * Truncate a file given a file descriptor.
2221 */
2222 /* ARGSUSED */
2223 int
2224 sys_ftruncate(p, v, retval)
2225 struct proc *p;
2226 void *v;
2227 register_t *retval;
2228 {
2229 register struct sys_ftruncate_args /* {
2230 syscallarg(int) fd;
2231 syscallarg(int) pad;
2232 syscallarg(off_t) length;
2233 } */ *uap = v;
2234 struct vattr vattr;
2235 struct vnode *vp;
2236 struct file *fp;
2237 int error;
2238
2239 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2240 return (error);
2241 if ((fp->f_flag & FWRITE) == 0)
2242 return (EINVAL);
2243 vp = (struct vnode *)fp->f_data;
2244 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2245 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2246 if (vp->v_type == VDIR)
2247 error = EISDIR;
2248 else if ((error = vn_writechk(vp)) == 0) {
2249 VATTR_NULL(&vattr);
2250 vattr.va_size = SCARG(uap, length);
2251 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
2252 }
2253 VOP_UNLOCK(vp, 0);
2254 return (error);
2255 }
2256
2257 /*
2258 * Sync an open file.
2259 */
2260 /* ARGSUSED */
2261 int
2262 sys_fsync(p, v, retval)
2263 struct proc *p;
2264 void *v;
2265 register_t *retval;
2266 {
2267 struct sys_fsync_args /* {
2268 syscallarg(int) fd;
2269 } */ *uap = v;
2270 register struct vnode *vp;
2271 struct file *fp;
2272 int error;
2273
2274 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2275 return (error);
2276 vp = (struct vnode *)fp->f_data;
2277 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2278 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT, p);
2279 VOP_UNLOCK(vp, 0);
2280 return (error);
2281 }
2282
2283 /*
2284 * Sync the data of an open file.
2285 */
2286 /* ARGSUSED */
2287 int
2288 sys_fdatasync(p, v, retval)
2289 struct proc *p;
2290 void *v;
2291 register_t *retval;
2292 {
2293 struct sys_fdatasync_args /* {
2294 syscallarg(int) fd;
2295 } */ *uap = v;
2296 struct vnode *vp;
2297 struct file *fp;
2298 int error;
2299
2300 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2301 return (error);
2302 vp = (struct vnode *)fp->f_data;
2303 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2304 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT|FSYNC_DATAONLY, p);
2305 VOP_UNLOCK(vp, 0);
2306 return (error);
2307 }
2308
2309 /*
2310 * Rename files, (standard) BSD semantics frontend.
2311 */
2312 /* ARGSUSED */
2313 int
2314 sys_rename(p, v, retval)
2315 struct proc *p;
2316 void *v;
2317 register_t *retval;
2318 {
2319 register struct sys_rename_args /* {
2320 syscallarg(const char *) from;
2321 syscallarg(const char *) to;
2322 } */ *uap = v;
2323
2324 return (rename_files(SCARG(uap, from), SCARG(uap, to), p, 0));
2325 }
2326
2327 /*
2328 * Rename files, POSIX semantics frontend.
2329 */
2330 /* ARGSUSED */
2331 int
2332 sys___posix_rename(p, v, retval)
2333 struct proc *p;
2334 void *v;
2335 register_t *retval;
2336 {
2337 register struct sys___posix_rename_args /* {
2338 syscallarg(const char *) from;
2339 syscallarg(const char *) to;
2340 } */ *uap = v;
2341
2342 return (rename_files(SCARG(uap, from), SCARG(uap, to), p, 1));
2343 }
2344
2345 /*
2346 * Rename files. Source and destination must either both be directories,
2347 * or both not be directories. If target is a directory, it must be empty.
2348 * If `from' and `to' refer to the same object, the value of the `retain'
2349 * argument is used to determine whether `from' will be
2350 *
2351 * (retain == 0) deleted unless `from' and `to' refer to the same
2352 * object in the file system's name space (BSD).
2353 * (retain == 1) always retained (POSIX).
2354 */
2355 static int
2356 rename_files(from, to, p, retain)
2357 const char *from, *to;
2358 struct proc *p;
2359 int retain;
2360 {
2361 register struct vnode *tvp, *fvp, *tdvp;
2362 struct nameidata fromnd, tond;
2363 int error;
2364
2365 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
2366 from, p);
2367 if ((error = namei(&fromnd)) != 0)
2368 return (error);
2369 fvp = fromnd.ni_vp;
2370 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
2371 UIO_USERSPACE, to, p);
2372 if ((error = namei(&tond)) != 0) {
2373 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2374 vrele(fromnd.ni_dvp);
2375 vrele(fvp);
2376 goto out1;
2377 }
2378 tdvp = tond.ni_dvp;
2379 tvp = tond.ni_vp;
2380
2381 if (tvp != NULL) {
2382 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2383 error = ENOTDIR;
2384 goto out;
2385 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2386 error = EISDIR;
2387 goto out;
2388 }
2389 }
2390
2391 if (fvp == tdvp)
2392 error = EINVAL;
2393
2394 /*
2395 * Source and destination refer to the same object.
2396 */
2397 if (fvp == tvp) {
2398 if (retain)
2399 error = -1;
2400 else if (fromnd.ni_dvp == tdvp &&
2401 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
2402 !memcmp(fromnd.ni_cnd.cn_nameptr,
2403 tond.ni_cnd.cn_nameptr,
2404 fromnd.ni_cnd.cn_namelen))
2405 error = -1;
2406 }
2407
2408 out:
2409 if (!error) {
2410 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
2411 if (fromnd.ni_dvp != tdvp)
2412 VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2413 if (tvp) {
2414 (void)uvm_vnp_uncache(tvp);
2415 VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
2416 }
2417 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2418 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2419 } else {
2420 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
2421 if (tdvp == tvp)
2422 vrele(tdvp);
2423 else
2424 vput(tdvp);
2425 if (tvp)
2426 vput(tvp);
2427 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2428 vrele(fromnd.ni_dvp);
2429 vrele(fvp);
2430 }
2431 vrele(tond.ni_startdir);
2432 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
2433 out1:
2434 if (fromnd.ni_startdir)
2435 vrele(fromnd.ni_startdir);
2436 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
2437 return (error == -1 ? 0 : error);
2438 }
2439
2440 /*
2441 * Make a directory file.
2442 */
2443 /* ARGSUSED */
2444 int
2445 sys_mkdir(p, v, retval)
2446 struct proc *p;
2447 void *v;
2448 register_t *retval;
2449 {
2450 register struct sys_mkdir_args /* {
2451 syscallarg(const char *) path;
2452 syscallarg(int) mode;
2453 } */ *uap = v;
2454 register struct vnode *vp;
2455 struct vattr vattr;
2456 int error;
2457 struct nameidata nd;
2458
2459 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
2460 if ((error = namei(&nd)) != 0)
2461 return (error);
2462 vp = nd.ni_vp;
2463 if (vp != NULL) {
2464 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2465 if (nd.ni_dvp == vp)
2466 vrele(nd.ni_dvp);
2467 else
2468 vput(nd.ni_dvp);
2469 vrele(vp);
2470 return (EEXIST);
2471 }
2472 VATTR_NULL(&vattr);
2473 vattr.va_type = VDIR;
2474 vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
2475 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2476 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
2477 if (!error)
2478 vput(nd.ni_vp);
2479 return (error);
2480 }
2481
2482 /*
2483 * Remove a directory file.
2484 */
2485 /* ARGSUSED */
2486 int
2487 sys_rmdir(p, v, retval)
2488 struct proc *p;
2489 void *v;
2490 register_t *retval;
2491 {
2492 struct sys_rmdir_args /* {
2493 syscallarg(const char *) path;
2494 } */ *uap = v;
2495 register struct vnode *vp;
2496 int error;
2497 struct nameidata nd;
2498
2499 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
2500 SCARG(uap, path), p);
2501 if ((error = namei(&nd)) != 0)
2502 return (error);
2503 vp = nd.ni_vp;
2504 if (vp->v_type != VDIR) {
2505 error = ENOTDIR;
2506 goto out;
2507 }
2508 /*
2509 * No rmdir "." please.
2510 */
2511 if (nd.ni_dvp == vp) {
2512 error = EINVAL;
2513 goto out;
2514 }
2515 /*
2516 * The root of a mounted filesystem cannot be deleted.
2517 */
2518 if (vp->v_flag & VROOT)
2519 error = EBUSY;
2520 out:
2521 if (!error) {
2522 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2523 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2524 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2525 } else {
2526 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2527 if (nd.ni_dvp == vp)
2528 vrele(nd.ni_dvp);
2529 else
2530 vput(nd.ni_dvp);
2531 vput(vp);
2532 }
2533 return (error);
2534 }
2535
2536 /*
2537 * Read a block of directory entries in a file system independent format.
2538 */
2539 int
2540 sys_getdents(p, v, retval)
2541 struct proc *p;
2542 void *v;
2543 register_t *retval;
2544 {
2545 register struct sys_getdents_args /* {
2546 syscallarg(int) fd;
2547 syscallarg(char *) buf;
2548 syscallarg(size_t) count;
2549 } */ *uap = v;
2550 struct file *fp;
2551 int error, done;
2552
2553 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2554 return (error);
2555 if ((fp->f_flag & FREAD) == 0)
2556 return (EBADF);
2557 error = vn_readdir(fp, SCARG(uap, buf), UIO_USERSPACE,
2558 SCARG(uap, count), &done, p, 0, 0);
2559 *retval = done;
2560 return (error);
2561 }
2562
2563 /*
2564 * Set the mode mask for creation of filesystem nodes.
2565 */
2566 int
2567 sys_umask(p, v, retval)
2568 struct proc *p;
2569 void *v;
2570 register_t *retval;
2571 {
2572 struct sys_umask_args /* {
2573 syscallarg(mode_t) newmask;
2574 } */ *uap = v;
2575 register struct filedesc *fdp;
2576
2577 fdp = p->p_fd;
2578 *retval = fdp->fd_cmask;
2579 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
2580 return (0);
2581 }
2582
2583 /*
2584 * Void all references to file by ripping underlying filesystem
2585 * away from vnode.
2586 */
2587 /* ARGSUSED */
2588 int
2589 sys_revoke(p, v, retval)
2590 struct proc *p;
2591 void *v;
2592 register_t *retval;
2593 {
2594 register struct sys_revoke_args /* {
2595 syscallarg(const char *) path;
2596 } */ *uap = v;
2597 register struct vnode *vp;
2598 struct vattr vattr;
2599 int error;
2600 struct nameidata nd;
2601
2602 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2603 if ((error = namei(&nd)) != 0)
2604 return (error);
2605 vp = nd.ni_vp;
2606 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
2607 goto out;
2608 if (p->p_ucred->cr_uid != vattr.va_uid &&
2609 (error = suser(p->p_ucred, &p->p_acflag)) != 0)
2610 goto out;
2611 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
2612 VOP_REVOKE(vp, REVOKEALL);
2613 out:
2614 vrele(vp);
2615 return (error);
2616 }
2617
2618 /*
2619 * Convert a user file descriptor to a kernel file entry.
2620 */
2621 int
2622 getvnode(fdp, fd, fpp)
2623 struct filedesc *fdp;
2624 int fd;
2625 struct file **fpp;
2626 {
2627 struct vnode *vp;
2628 struct file *fp;
2629
2630 if ((u_int)fd >= fdp->fd_nfiles ||
2631 (fp = fdp->fd_ofiles[fd]) == NULL)
2632 return (EBADF);
2633 if (fp->f_type != DTYPE_VNODE)
2634 return (EINVAL);
2635 vp = (struct vnode *)fp->f_data;
2636 if (vp->v_type == VBAD)
2637 return (EBADF);
2638 *fpp = fp;
2639 return (0);
2640 }
2641