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