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