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