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