1 /*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94
39 * $FreeBSD$
40 */
41
42 /* For 4.3 integer FS ID compatibility */
43 #include "opt_compat.h"
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/buf.h>
48 #include <sys/sysent.h>
49 #include <sys/malloc.h>
50 #include <sys/mount.h>
51 #include <sys/sysproto.h>
52 #include <sys/namei.h>
53 #include <sys/filedesc.h>
54 #include <sys/kernel.h>
55 #include <sys/fcntl.h>
56 #include <sys/file.h>
57 #include <sys/linker.h>
58 #include <sys/stat.h>
59 #include <sys/unistd.h>
60 #include <sys/vnode.h>
61 #include <sys/proc.h>
62 #include <sys/dirent.h>
63 #include <sys/extattr.h>
64
65 #include <machine/limits.h>
66 #include <miscfs/union/union.h>
67 #include <sys/sysctl.h>
68 #include <vm/vm.h>
69 #include <vm/vm_object.h>
70 #include <vm/vm_zone.h>
71 #include <vm/vm_page.h>
72
73 static int change_dir __P((struct nameidata *ndp, struct proc *p));
74 static void checkdirs __P((struct vnode *olddp));
75 static int chroot_refuse_vdir_fds __P((struct filedesc *fdp));
76 static int getutimes __P((const struct timeval *, struct timespec *));
77 static int setfown __P((struct proc *, struct vnode *, uid_t, gid_t));
78 static int setfmode __P((struct proc *, struct vnode *, int));
79 static int setfflags __P((struct proc *, struct vnode *, int));
80 static int setutimes __P((struct proc *, struct vnode *,
81 const struct timespec *, int));
82 static int usermount = 0; /* if 1, non-root can mount fs. */
83
84 int (*union_dircheckp) __P((struct proc *, struct vnode **, struct file *));
85
86 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, "");
87
88 /*
89 * Virtual File System System Calls
90 */
91
92 /*
93 * Mount a file system.
94 */
95 #ifndef _SYS_SYSPROTO_H_
96 struct mount_args {
97 char *type;
98 char *path;
99 int flags;
100 caddr_t data;
101 };
102 #endif
103 /* ARGSUSED */
104 int
105 mount(p, uap)
106 struct proc *p;
107 register struct mount_args /* {
108 syscallarg(char *) type;
109 syscallarg(char *) path;
110 syscallarg(int) flags;
111 syscallarg(caddr_t) data;
112 } */ *uap;
113 {
114 struct vnode *vp;
115 struct mount *mp;
116 struct vfsconf *vfsp;
117 int error, flag = 0, flag2 = 0;
118 struct vattr va;
119 #ifdef COMPAT_43
120 u_long fstypenum;
121 #endif
122 struct nameidata nd;
123 char fstypename[MFSNAMELEN];
124
125 if (p->p_prison != NULL)
126 return (EPERM);
127 if (usermount == 0 && (error = suser(p)))
128 return (error);
129 /*
130 * Do not allow NFS export by non-root users.
131 */
132 if (SCARG(uap, flags) & MNT_EXPORTED) {
133 error = suser(p);
134 if (error)
135 return (error);
136 }
137 /*
138 * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users
139 */
140 if (suser_xxx(p->p_ucred, 0, 0))
141 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
142 /*
143 * Get vnode to be covered
144 */
145 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
146 SCARG(uap, path), p);
147 if ((error = namei(&nd)) != 0)
148 return (error);
149 NDFREE(&nd, NDF_ONLY_PNBUF);
150 vp = nd.ni_vp;
151 if (SCARG(uap, flags) & MNT_UPDATE) {
152 if ((vp->v_flag & VROOT) == 0) {
153 vput(vp);
154 return (EINVAL);
155 }
156 mp = vp->v_mount;
157 flag = mp->mnt_flag;
158 flag2 = mp->mnt_kern_flag;
159 /*
160 * We only allow the filesystem to be reloaded if it
161 * is currently mounted read-only.
162 */
163 if ((SCARG(uap, flags) & MNT_RELOAD) &&
164 ((mp->mnt_flag & MNT_RDONLY) == 0)) {
165 vput(vp);
166 return (EOPNOTSUPP); /* Needs translation */
167 }
168 /*
169 * Only root, or the user that did the original mount is
170 * permitted to update it.
171 */
172 if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
173 (error = suser(p))) {
174 vput(vp);
175 return (error);
176 }
177 if (vfs_busy(mp, LK_NOWAIT, 0, p)) {
178 vput(vp);
179 return (EBUSY);
180 }
181 simple_lock(&vp->v_interlock);
182 if ((vp->v_flag & VMOUNT) != 0 ||
183 vp->v_mountedhere != NULL) {
184 simple_unlock(&vp->v_interlock);
185 vfs_unbusy(mp, p);
186 vput(vp);
187 return (EBUSY);
188 }
189 vp->v_flag |= VMOUNT;
190 simple_unlock(&vp->v_interlock);
191 mp->mnt_flag |=
192 SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
193 VOP_UNLOCK(vp, 0, p);
194 goto update;
195 }
196 /*
197 * If the user is not root, ensure that they own the directory
198 * onto which we are attempting to mount.
199 */
200 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
201 (va.va_uid != p->p_ucred->cr_uid &&
202 (error = suser(p)))) {
203 vput(vp);
204 return (error);
205 }
206 if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0) {
207 vput(vp);
208 return (error);
209 }
210 if (vp->v_type != VDIR) {
211 vput(vp);
212 return (ENOTDIR);
213 }
214 #ifdef COMPAT_43
215 /*
216 * Historically filesystem types were identified by number. If we
217 * get an integer for the filesystem type instead of a string, we
218 * check to see if it matches one of the historic filesystem types.
219 */
220 fstypenum = (uintptr_t)SCARG(uap, type);
221 if (fstypenum < maxvfsconf) {
222 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
223 if (vfsp->vfc_typenum == fstypenum)
224 break;
225 if (vfsp == NULL) {
226 vput(vp);
227 return (ENODEV);
228 }
229 strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN);
230 } else
231 #endif /* COMPAT_43 */
232 if ((error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) != 0) {
233 vput(vp);
234 return (error);
235 }
236 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
237 if (!strcmp(vfsp->vfc_name, fstypename))
238 break;
239 if (vfsp == NULL) {
240 linker_file_t lf;
241
242 /* Only load modules for root (very important!) */
243 if ((error = suser(p)) != 0) {
244 vput(vp);
245 return error;
246 }
247 error = linker_load_file(fstypename, &lf);
248 if (error || lf == NULL) {
249 vput(vp);
250 if (lf == NULL)
251 error = ENODEV;
252 return error;
253 }
254 lf->userrefs++;
255 /* lookup again, see if the VFS was loaded */
256 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
257 if (!strcmp(vfsp->vfc_name, fstypename))
258 break;
259 if (vfsp == NULL) {
260 lf->userrefs--;
261 linker_file_unload(lf);
262 vput(vp);
263 return (ENODEV);
264 }
265 }
266 simple_lock(&vp->v_interlock);
267 if ((vp->v_flag & VMOUNT) != 0 ||
268 vp->v_mountedhere != NULL) {
269 simple_unlock(&vp->v_interlock);
270 vput(vp);
271 return (EBUSY);
272 }
273 vp->v_flag |= VMOUNT;
274 simple_unlock(&vp->v_interlock);
275
276 /*
277 * Allocate and initialize the filesystem.
278 */
279 mp = malloc(sizeof(struct mount), M_MOUNT, M_WAITOK);
280 bzero((char *)mp, (u_long)sizeof(struct mount));
281 TAILQ_INIT(&mp->mnt_nvnodelist);
282 TAILQ_INIT(&mp->mnt_reservedvnlist);
283 mp->mnt_nvnodelistsize = 0;
284 lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, LK_NOPAUSE);
285 (void)vfs_busy(mp, LK_NOWAIT, 0, p);
286 mp->mnt_op = vfsp->vfc_vfsops;
287 mp->mnt_vfc = vfsp;
288 vfsp->vfc_refcount++;
289 mp->mnt_stat.f_type = vfsp->vfc_typenum;
290 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
291 strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
292 mp->mnt_vnodecovered = vp;
293 mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
294 mp->mnt_iosize_max = DFLTPHYS;
295 VOP_UNLOCK(vp, 0, p);
296 update:
297 /*
298 * Set the mount level flags.
299 */
300 if (SCARG(uap, flags) & MNT_RDONLY)
301 mp->mnt_flag |= MNT_RDONLY;
302 else if (mp->mnt_flag & MNT_RDONLY)
303 mp->mnt_kern_flag |= MNTK_WANTRDWR;
304 mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
305 MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME |
306 MNT_NOSYMFOLLOW | MNT_IGNORE |
307 MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
308 mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
309 MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE |
310 MNT_NOSYMFOLLOW | MNT_IGNORE |
311 MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
312 /*
313 * Mount the filesystem.
314 * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
315 * get. No freeing of cn_pnbuf.
316 */
317 error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
318 if (mp->mnt_flag & MNT_UPDATE) {
319 if (mp->mnt_kern_flag & MNTK_WANTRDWR)
320 mp->mnt_flag &= ~MNT_RDONLY;
321 mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE);
322 mp->mnt_kern_flag &=~ MNTK_WANTRDWR;
323 if (error) {
324 mp->mnt_flag = flag;
325 mp->mnt_kern_flag = flag2;
326 }
327 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
328 if (mp->mnt_syncer == NULL)
329 error = vfs_allocate_syncvnode(mp);
330 } else {
331 if (mp->mnt_syncer != NULL)
332 vrele(mp->mnt_syncer);
333 mp->mnt_syncer = NULL;
334 }
335 vfs_unbusy(mp, p);
336 simple_lock(&vp->v_interlock);
337 vp->v_flag &= ~VMOUNT;
338 simple_unlock(&vp->v_interlock);
339 vrele(vp);
340 return (error);
341 }
342 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
343 /*
344 * Put the new filesystem on the mount list after root.
345 */
346 cache_purge(vp);
347 if (!error) {
348 simple_lock(&vp->v_interlock);
349 vp->v_flag &= ~VMOUNT;
350 vp->v_mountedhere = mp;
351 simple_unlock(&vp->v_interlock);
352 simple_lock(&mountlist_slock);
353 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
354 simple_unlock(&mountlist_slock);
355 checkdirs(vp);
356 VOP_UNLOCK(vp, 0, p);
357 if ((mp->mnt_flag & MNT_RDONLY) == 0)
358 error = vfs_allocate_syncvnode(mp);
359 vfs_unbusy(mp, p);
360 if ((error = VFS_START(mp, 0, p)) != 0)
361 vrele(vp);
362 } else {
363 simple_lock(&vp->v_interlock);
364 vp->v_flag &= ~VMOUNT;
365 simple_unlock(&vp->v_interlock);
366 mp->mnt_vfc->vfc_refcount--;
367 vfs_unbusy(mp, p);
368 free((caddr_t)mp, M_MOUNT);
369 vput(vp);
370 }
371 return (error);
372 }
373
374 /*
375 * Scan all active processes to see if any of them have a current
376 * or root directory onto which the new filesystem has just been
377 * mounted. If so, replace them with the new mount point.
378 */
379 static void
380 checkdirs(olddp)
381 struct vnode *olddp;
382 {
383 struct filedesc *fdp;
384 struct vnode *newdp;
385 struct proc *p;
386
387 if (olddp->v_usecount == 1)
388 return;
389 if (VFS_ROOT(olddp->v_mountedhere, &newdp))
390 panic("mount: lost mount");
391 LIST_FOREACH(p, &allproc, p_list) {
392 fdp = p->p_fd;
393 if (fdp->fd_cdir == olddp) {
394 vrele(fdp->fd_cdir);
395 VREF(newdp);
396 fdp->fd_cdir = newdp;
397 }
398 if (fdp->fd_rdir == olddp) {
399 vrele(fdp->fd_rdir);
400 VREF(newdp);
401 fdp->fd_rdir = newdp;
402 }
403 }
404 if (rootvnode == olddp) {
405 vrele(rootvnode);
406 VREF(newdp);
407 rootvnode = newdp;
408 }
409 vput(newdp);
410 }
411
412 /*
413 * Unmount a file system.
414 *
415 * Note: unmount takes a path to the vnode mounted on as argument,
416 * not special file (as before).
417 */
418 #ifndef _SYS_SYSPROTO_H_
419 struct unmount_args {
420 char *path;
421 int flags;
422 };
423 #endif
424 /* ARGSUSED */
425 int
426 unmount(p, uap)
427 struct proc *p;
428 register struct unmount_args /* {
429 syscallarg(char *) path;
430 syscallarg(int) flags;
431 } */ *uap;
432 {
433 register struct vnode *vp;
434 struct mount *mp;
435 int error;
436 struct nameidata nd;
437
438 if (p->p_prison != NULL)
439 return (EPERM);
440 if (usermount == 0 && (error = suser(p)))
441 return (error);
442 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
443 SCARG(uap, path), p);
444 if ((error = namei(&nd)) != 0)
445 return (error);
446 vp = nd.ni_vp;
447 NDFREE(&nd, NDF_ONLY_PNBUF);
448 mp = vp->v_mount;
449
450 /*
451 * Only root, or the user that did the original mount is
452 * permitted to unmount this filesystem.
453 */
454 if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
455 (error = suser(p))) {
456 vput(vp);
457 return (error);
458 }
459
460 /*
461 * Don't allow unmounting the root file system.
462 */
463 if (mp->mnt_flag & MNT_ROOTFS) {
464 vput(vp);
465 return (EINVAL);
466 }
467
468 /*
469 * Must be the root of the filesystem
470 */
471 if ((vp->v_flag & VROOT) == 0) {
472 vput(vp);
473 return (EINVAL);
474 }
475 vput(vp);
476 return (dounmount(mp, SCARG(uap, flags), p));
477 }
478
479 /*
480 * Do the actual file system unmount.
481 */
482 int
483 dounmount(mp, flags, p)
484 register struct mount *mp;
485 int flags;
486 struct proc *p;
487 {
488 struct vnode *coveredvp;
489 int error;
490 int async_flag;
491
492 simple_lock(&mountlist_slock);
493 if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
494 simple_unlock(&mountlist_slock);
495 return (EBUSY);
496 }
497 mp->mnt_kern_flag |= MNTK_UNMOUNT;
498 /* Allow filesystems to detect that a forced unmount is in progress. */
499 if (flags & MNT_FORCE)
500 mp->mnt_kern_flag |= MNTK_UNMOUNTF;
501 error = lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK |
502 ((flags & MNT_FORCE) ? 0 : LK_NOWAIT), &mountlist_slock, p);
503 if (error) {
504 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
505 if (mp->mnt_kern_flag & MNTK_MWAIT)
506 wakeup((caddr_t)mp);
507 return (error);
508 }
509
510 if (mp->mnt_flag & MNT_EXPUBLIC)
511 vfs_setpublicfs(NULL, NULL, NULL);
512
513 vfs_msync(mp, MNT_WAIT);
514 async_flag = mp->mnt_flag & MNT_ASYNC;
515 mp->mnt_flag &=~ MNT_ASYNC;
516 cache_purgevfs(mp); /* remove cache entries for this file sys */
517 if (mp->mnt_syncer != NULL)
518 vrele(mp->mnt_syncer);
519 if (((mp->mnt_flag & MNT_RDONLY) ||
520 (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
521 (flags & MNT_FORCE))
522 error = VFS_UNMOUNT(mp, flags, p);
523 simple_lock(&mountlist_slock);
524 if (error) {
525 if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
526 (void) vfs_allocate_syncvnode(mp);
527 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
528 mp->mnt_flag |= async_flag;
529 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
530 &mountlist_slock, p);
531 if (mp->mnt_kern_flag & MNTK_MWAIT)
532 wakeup((caddr_t)mp);
533 return (error);
534 }
535 TAILQ_REMOVE(&mountlist, mp, mnt_list);
536 if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
537 coveredvp->v_mountedhere = (struct mount *)0;
538 vrele(coveredvp);
539 }
540 mp->mnt_vfc->vfc_refcount--;
541 if (!TAILQ_EMPTY(&mp->mnt_nvnodelist))
542 panic("unmount: dangling vnode");
543 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p);
544 if (mp->mnt_kern_flag & MNTK_MWAIT)
545 wakeup((caddr_t)mp);
546 free((caddr_t)mp, M_MOUNT);
547 return (0);
548 }
549
550 /*
551 * Sync each mounted filesystem.
552 */
553 #ifndef _SYS_SYSPROTO_H_
554 struct sync_args {
555 int dummy;
556 };
557 #endif
558
559 #ifdef DEBUG
560 static int syncprt = 0;
561 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
562 #endif
563
564 /* ARGSUSED */
565 int
566 sync(p, uap)
567 struct proc *p;
568 struct sync_args *uap;
569 {
570 register struct mount *mp, *nmp;
571 int asyncflag;
572
573 simple_lock(&mountlist_slock);
574 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
575 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
576 nmp = TAILQ_NEXT(mp, mnt_list);
577 continue;
578 }
579 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
580 asyncflag = mp->mnt_flag & MNT_ASYNC;
581 mp->mnt_flag &= ~MNT_ASYNC;
582 vfs_msync(mp, MNT_NOWAIT);
583 VFS_SYNC(mp, MNT_NOWAIT,
584 ((p != NULL) ? p->p_ucred : NOCRED), p);
585 mp->mnt_flag |= asyncflag;
586 }
587 simple_lock(&mountlist_slock);
588 nmp = TAILQ_NEXT(mp, mnt_list);
589 vfs_unbusy(mp, p);
590 }
591 simple_unlock(&mountlist_slock);
592 #if 0
593 /*
594 * XXX don't call vfs_bufstats() yet because that routine
595 * was not imported in the Lite2 merge.
596 */
597 #ifdef DIAGNOSTIC
598 if (syncprt)
599 vfs_bufstats();
600 #endif /* DIAGNOSTIC */
601 #endif
602 return (0);
603 }
604
605 /* XXX PRISON: could be per prison flag */
606 static int prison_quotas;
607 #if 0
608 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
609 #endif
610
611 /*
612 * Change filesystem quotas.
613 */
614 #ifndef _SYS_SYSPROTO_H_
615 struct quotactl_args {
616 char *path;
617 int cmd;
618 int uid;
619 caddr_t arg;
620 };
621 #endif
622 /* ARGSUSED */
623 int
624 quotactl(p, uap)
625 struct proc *p;
626 register struct quotactl_args /* {
627 syscallarg(char *) path;
628 syscallarg(int) cmd;
629 syscallarg(int) uid;
630 syscallarg(caddr_t) arg;
631 } */ *uap;
632 {
633 register struct mount *mp;
634 int error;
635 struct nameidata nd;
636
637 if (p->p_prison && !prison_quotas)
638 return (EPERM);
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 NDFREE(&nd, NDF_ONLY_PNBUF);
644 vrele(nd.ni_vp);
645 return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
646 SCARG(uap, arg), p));
647 }
648
649 /*
650 * Get filesystem statistics.
651 */
652 #ifndef _SYS_SYSPROTO_H_
653 struct statfs_args {
654 char *path;
655 struct statfs *buf;
656 };
657 #endif
658 /* ARGSUSED */
659 int
660 statfs(p, uap)
661 struct proc *p;
662 register struct statfs_args /* {
663 syscallarg(char *) path;
664 syscallarg(struct statfs *) buf;
665 } */ *uap;
666 {
667 register struct mount *mp;
668 register struct statfs *sp;
669 int error;
670 struct nameidata nd;
671 struct statfs sb;
672
673 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
674 if ((error = namei(&nd)) != 0)
675 return (error);
676 mp = nd.ni_vp->v_mount;
677 sp = &mp->mnt_stat;
678 NDFREE(&nd, NDF_ONLY_PNBUF);
679 vrele(nd.ni_vp);
680 error = VFS_STATFS(mp, sp, p);
681 if (error)
682 return (error);
683 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
684 if (suser_xxx(p->p_ucred, 0, 0)) {
685 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
686 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
687 sp = &sb;
688 }
689 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
690 }
691
692 /*
693 * Get filesystem statistics.
694 */
695 #ifndef _SYS_SYSPROTO_H_
696 struct fstatfs_args {
697 int fd;
698 struct statfs *buf;
699 };
700 #endif
701 /* ARGSUSED */
702 int
703 fstatfs(p, uap)
704 struct proc *p;
705 register struct fstatfs_args /* {
706 syscallarg(int) fd;
707 syscallarg(struct statfs *) buf;
708 } */ *uap;
709 {
710 struct file *fp;
711 struct mount *mp;
712 register struct statfs *sp;
713 int error;
714 struct statfs sb;
715
716 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
717 return (error);
718 mp = ((struct vnode *)fp->f_data)->v_mount;
719 if (mp == NULL)
720 return (EBADF);
721 sp = &mp->mnt_stat;
722 error = VFS_STATFS(mp, sp, p);
723 if (error)
724 return (error);
725 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
726 if (suser_xxx(p->p_ucred, 0, 0)) {
727 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
728 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
729 sp = &sb;
730 }
731 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
732 }
733
734 /*
735 * Get statistics on all filesystems.
736 */
737 #ifndef _SYS_SYSPROTO_H_
738 struct getfsstat_args {
739 struct statfs *buf;
740 long bufsize;
741 int flags;
742 };
743 #endif
744 int
745 getfsstat(p, uap)
746 struct proc *p;
747 register struct getfsstat_args /* {
748 syscallarg(struct statfs *) buf;
749 syscallarg(long) bufsize;
750 syscallarg(int) flags;
751 } */ *uap;
752 {
753 register struct mount *mp, *nmp;
754 register struct statfs *sp;
755 caddr_t sfsp;
756 long count, maxcount, error;
757
758 maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
759 sfsp = (caddr_t)SCARG(uap, buf);
760 count = 0;
761 simple_lock(&mountlist_slock);
762 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
763 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
764 nmp = TAILQ_NEXT(mp, mnt_list);
765 continue;
766 }
767 if (sfsp && count < maxcount) {
768 sp = &mp->mnt_stat;
769 /*
770 * If MNT_NOWAIT or MNT_LAZY is specified, do not
771 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
772 * overrides MNT_WAIT.
773 */
774 if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
775 (SCARG(uap, flags) & MNT_WAIT)) &&
776 (error = VFS_STATFS(mp, sp, p))) {
777 simple_lock(&mountlist_slock);
778 nmp = TAILQ_NEXT(mp, mnt_list);
779 vfs_unbusy(mp, p);
780 continue;
781 }
782 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
783 error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
784 if (error) {
785 vfs_unbusy(mp, p);
786 return (error);
787 }
788 sfsp += sizeof(*sp);
789 }
790 count++;
791 simple_lock(&mountlist_slock);
792 nmp = TAILQ_NEXT(mp, mnt_list);
793 vfs_unbusy(mp, p);
794 }
795 simple_unlock(&mountlist_slock);
796 if (sfsp && count > maxcount)
797 p->p_retval[0] = maxcount;
798 else
799 p->p_retval[0] = count;
800 return (0);
801 }
802
803 /*
804 * Change current working directory to a given file descriptor.
805 */
806 #ifndef _SYS_SYSPROTO_H_
807 struct fchdir_args {
808 int fd;
809 };
810 #endif
811 /* ARGSUSED */
812 int
813 fchdir(p, uap)
814 struct proc *p;
815 struct fchdir_args /* {
816 syscallarg(int) fd;
817 } */ *uap;
818 {
819 register struct filedesc *fdp = p->p_fd;
820 struct vnode *vp, *tdp;
821 struct mount *mp;
822 struct file *fp;
823 int error;
824
825 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
826 return (error);
827 vp = (struct vnode *)fp->f_data;
828 VREF(vp);
829 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
830 if (vp->v_type != VDIR)
831 error = ENOTDIR;
832 else
833 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
834 while (!error && (mp = vp->v_mountedhere) != NULL) {
835 if (vfs_busy(mp, 0, 0, p))
836 continue;
837 error = VFS_ROOT(mp, &tdp);
838 vfs_unbusy(mp, p);
839 if (error)
840 break;
841 vput(vp);
842 vp = tdp;
843 }
844 if (error) {
845 vput(vp);
846 return (error);
847 }
848 VOP_UNLOCK(vp, 0, p);
849 vrele(fdp->fd_cdir);
850 fdp->fd_cdir = vp;
851 return (0);
852 }
853
854 /*
855 * Change current working directory (``.'').
856 */
857 #ifndef _SYS_SYSPROTO_H_
858 struct chdir_args {
859 char *path;
860 };
861 #endif
862 /* ARGSUSED */
863 int
864 chdir(p, uap)
865 struct proc *p;
866 struct chdir_args /* {
867 syscallarg(char *) path;
868 } */ *uap;
869 {
870 register struct filedesc *fdp = p->p_fd;
871 int error;
872 struct nameidata nd;
873
874 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
875 SCARG(uap, path), p);
876 if ((error = change_dir(&nd, p)) != 0)
877 return (error);
878 NDFREE(&nd, NDF_ONLY_PNBUF);
879 vrele(fdp->fd_cdir);
880 fdp->fd_cdir = nd.ni_vp;
881 return (0);
882 }
883
884 /*
885 * Helper function for raised chroot(2) security function: Refuse if
886 * any filedescriptors are open directories.
887 */
888 static int
889 chroot_refuse_vdir_fds(fdp)
890 struct filedesc *fdp;
891 {
892 struct vnode *vp;
893 struct file *fp;
894 int error;
895 int fd;
896
897 for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
898 error = getvnode(fdp, fd, &fp);
899 if (error)
900 continue;
901 vp = (struct vnode *)fp->f_data;
902 if (vp->v_type != VDIR)
903 continue;
904 return(EPERM);
905 }
906 return (0);
907 }
908
909 /*
910 * This sysctl determines if we will allow a process to chroot(2) if it
911 * has a directory open:
912 * 0: disallowed for all processes.
913 * 1: allowed for processes that were not already chroot(2)'ed.
914 * 2: allowed for all processes.
915 */
916
917 static int chroot_allow_open_directories = 1;
918
919 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
920 &chroot_allow_open_directories, 0, "");
921
922 /*
923 * Change notion of root (``/'') directory.
924 */
925 #ifndef _SYS_SYSPROTO_H_
926 struct chroot_args {
927 char *path;
928 };
929 #endif
930 /* ARGSUSED */
931 int
932 chroot(p, uap)
933 struct proc *p;
934 struct chroot_args /* {
935 syscallarg(char *) path;
936 } */ *uap;
937 {
938 register struct filedesc *fdp = p->p_fd;
939 int error;
940 struct nameidata nd;
941
942 error = suser_xxx(0, p, PRISON_ROOT);
943 if (error)
944 return (error);
945 if (chroot_allow_open_directories == 0 ||
946 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode))
947 error = chroot_refuse_vdir_fds(fdp);
948 if (error)
949 return (error);
950 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
951 SCARG(uap, path), p);
952 if ((error = change_dir(&nd, p)) != 0)
953 return (error);
954 NDFREE(&nd, NDF_ONLY_PNBUF);
955 vrele(fdp->fd_rdir);
956 fdp->fd_rdir = nd.ni_vp;
957 if (!fdp->fd_jdir) {
958 fdp->fd_jdir = nd.ni_vp;
959 VREF(fdp->fd_jdir);
960 }
961 return (0);
962 }
963
964 /*
965 * Common routine for chroot and chdir.
966 */
967 static int
968 change_dir(ndp, p)
969 register struct nameidata *ndp;
970 struct proc *p;
971 {
972 struct vnode *vp;
973 int error;
974
975 error = namei(ndp);
976 if (error)
977 return (error);
978 vp = ndp->ni_vp;
979 if (vp->v_type != VDIR)
980 error = ENOTDIR;
981 else
982 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
983 if (error)
984 vput(vp);
985 else
986 VOP_UNLOCK(vp, 0, p);
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 #ifndef _SYS_SYSPROTO_H_
995 struct open_args {
996 char *path;
997 int flags;
998 int mode;
999 };
1000 #endif
1001 int
1002 open(p, uap)
1003 struct proc *p;
1004 register struct open_args /* {
1005 syscallarg(char *) path;
1006 syscallarg(int) flags;
1007 syscallarg(int) mode;
1008 } */ *uap;
1009 {
1010 register struct filedesc *fdp = p->p_fd;
1011 register struct file *fp;
1012 register struct vnode *vp;
1013 int cmode, flags, oflags;
1014 struct file *nfp;
1015 int type, indx, error;
1016 struct flock lf;
1017 struct nameidata nd;
1018
1019 oflags = SCARG(uap, flags);
1020 if ((oflags & O_ACCMODE) == O_ACCMODE)
1021 return (EINVAL);
1022 flags = FFLAGS(oflags);
1023 error = falloc(p, &nfp, &indx);
1024 if (error)
1025 return (error);
1026 fp = nfp;
1027 cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
1028 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1029 p->p_dupfd = -indx - 1; /* XXX check for fdopen */
1030 /*
1031 * Bump the ref count to prevent another process from closing
1032 * the descriptor while we are blocked in vn_open()
1033 */
1034 fhold(fp);
1035 error = vn_open(&nd, flags, cmode);
1036 if (error) {
1037 /*
1038 * release our own reference
1039 */
1040 fdrop(fp, p);
1041
1042 /*
1043 * handle special fdopen() case. bleh. dupfdopen() is
1044 * responsible for dropping the old contents of ofiles[indx]
1045 * if it succeeds.
1046 */
1047 if ((error == ENODEV || error == ENXIO) &&
1048 p->p_dupfd >= 0 && /* XXX from fdopen */
1049 (error =
1050 dupfdopen(p, fdp, indx, p->p_dupfd, flags, error)) == 0) {
1051 p->p_retval[0] = indx;
1052 return (0);
1053 }
1054 /*
1055 * Clean up the descriptor, but only if another thread hadn't
1056 * replaced or closed it.
1057 */
1058 if (fdp->fd_ofiles[indx] == fp) {
1059 fdp->fd_ofiles[indx] = NULL;
1060 fdrop(fp, p);
1061 }
1062
1063 if (error == ERESTART)
1064 error = EINTR;
1065 return (error);
1066 }
1067 p->p_dupfd = 0;
1068 NDFREE(&nd, NDF_ONLY_PNBUF);
1069 vp = nd.ni_vp;
1070
1071 /*
1072 * There should be 2 references on the file, one from the descriptor
1073 * table, and one for us.
1074 *
1075 * Handle the case where someone closed the file (via its file
1076 * descriptor) while we were blocked. The end result should look
1077 * like opening the file succeeded but it was immediately closed.
1078 */
1079 if (fp->f_count == 1) {
1080 KASSERT(fdp->fd_ofiles[indx] != fp,
1081 ("Open file descriptor lost all refs"));
1082 VOP_UNLOCK(vp, 0, p);
1083 vn_close(vp, flags & FMASK, fp->f_cred, p);
1084 fdrop(fp, p);
1085 p->p_retval[0] = indx;
1086 return 0;
1087 }
1088
1089 fp->f_data = (caddr_t)vp;
1090 fp->f_flag = flags & FMASK;
1091 fp->f_ops = &vnops;
1092 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
1093 if (flags & (O_EXLOCK | O_SHLOCK)) {
1094 lf.l_whence = SEEK_SET;
1095 lf.l_start = 0;
1096 lf.l_len = 0;
1097 if (flags & O_EXLOCK)
1098 lf.l_type = F_WRLCK;
1099 else
1100 lf.l_type = F_RDLCK;
1101 type = F_FLOCK;
1102 if ((flags & FNONBLOCK) == 0)
1103 type |= F_WAIT;
1104 VOP_UNLOCK(vp, 0, p);
1105 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
1106 /*
1107 * lock request failed. Normally close the descriptor
1108 * but handle the case where someone might have dup()d
1109 * it when we weren't looking. One reference is
1110 * owned by the descriptor array, the other by us.
1111 */
1112 if (fdp->fd_ofiles[indx] == fp) {
1113 fdp->fd_ofiles[indx] = NULL;
1114 fdrop(fp, p);
1115 }
1116 fdrop(fp, p);
1117 return (error);
1118 }
1119 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1120 fp->f_flag |= FHASLOCK;
1121 }
1122 /* assert that vn_open created a backing object if one is needed */
1123 KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0,
1124 ("open: vmio vnode has no backing object after vn_open"));
1125 VOP_UNLOCK(vp, 0, p);
1126
1127 /*
1128 * release our private reference, leaving the one associated with the
1129 * descriptor table intact.
1130 */
1131 fdrop(fp, p);
1132 p->p_retval[0] = indx;
1133 return (0);
1134 }
1135
1136 #ifdef COMPAT_43
1137 /*
1138 * Create a file.
1139 */
1140 #ifndef _SYS_SYSPROTO_H_
1141 struct ocreat_args {
1142 char *path;
1143 int mode;
1144 };
1145 #endif
1146 int
1147 ocreat(p, uap)
1148 struct proc *p;
1149 register struct ocreat_args /* {
1150 syscallarg(char *) path;
1151 syscallarg(int) mode;
1152 } */ *uap;
1153 {
1154 struct open_args /* {
1155 syscallarg(char *) path;
1156 syscallarg(int) flags;
1157 syscallarg(int) mode;
1158 } */ nuap;
1159
1160 SCARG(&nuap, path) = SCARG(uap, path);
1161 SCARG(&nuap, mode) = SCARG(uap, mode);
1162 SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
1163 return (open(p, &nuap));
1164 }
1165 #endif /* COMPAT_43 */
1166
1167 /*
1168 * Create a special file.
1169 */
1170 #ifndef _SYS_SYSPROTO_H_
1171 struct mknod_args {
1172 char *path;
1173 int mode;
1174 int dev;
1175 };
1176 #endif
1177 /* ARGSUSED */
1178 int
1179 mknod(p, uap)
1180 struct proc *p;
1181 register struct mknod_args /* {
1182 syscallarg(char *) path;
1183 syscallarg(int) mode;
1184 syscallarg(int) dev;
1185 } */ *uap;
1186 {
1187 register struct vnode *vp;
1188 struct vattr vattr;
1189 int error;
1190 int whiteout = 0;
1191 struct nameidata nd;
1192
1193 switch (SCARG(uap, mode) & S_IFMT) {
1194 case S_IFCHR:
1195 case S_IFBLK:
1196 error = suser(p);
1197 break;
1198 default:
1199 error = suser_xxx(0, p, PRISON_ROOT);
1200 break;
1201 }
1202 if (error)
1203 return (error);
1204 bwillwrite();
1205 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1206 if ((error = namei(&nd)) != 0)
1207 return (error);
1208 vp = nd.ni_vp;
1209 if (vp != NULL)
1210 error = EEXIST;
1211 else {
1212 VATTR_NULL(&vattr);
1213 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1214 vattr.va_rdev = SCARG(uap, dev);
1215 whiteout = 0;
1216
1217 switch (SCARG(uap, mode) & S_IFMT) {
1218 case S_IFMT: /* used by badsect to flag bad sectors */
1219 vattr.va_type = VBAD;
1220 break;
1221 case S_IFCHR:
1222 vattr.va_type = VCHR;
1223 break;
1224 case S_IFBLK:
1225 vattr.va_type = VBLK;
1226 break;
1227 case S_IFWHT:
1228 whiteout = 1;
1229 break;
1230 default:
1231 error = EINVAL;
1232 break;
1233 }
1234 }
1235 if (!error) {
1236 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1237 if (whiteout)
1238 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
1239 else {
1240 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1241 &nd.ni_cnd, &vattr);
1242 if (error == 0)
1243 vput(nd.ni_vp);
1244 }
1245 NDFREE(&nd, NDF_ONLY_PNBUF);
1246 vput(nd.ni_dvp);
1247 } else {
1248 NDFREE(&nd, NDF_ONLY_PNBUF);
1249 if (nd.ni_dvp == vp)
1250 vrele(nd.ni_dvp);
1251 else
1252 vput(nd.ni_dvp);
1253 if (vp)
1254 vrele(vp);
1255 }
1256 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod");
1257 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod");
1258 return (error);
1259 }
1260
1261 /*
1262 * Create a named pipe.
1263 */
1264 #ifndef _SYS_SYSPROTO_H_
1265 struct mkfifo_args {
1266 char *path;
1267 int mode;
1268 };
1269 #endif
1270 /* ARGSUSED */
1271 int
1272 mkfifo(p, uap)
1273 struct proc *p;
1274 register struct mkfifo_args /* {
1275 syscallarg(char *) path;
1276 syscallarg(int) mode;
1277 } */ *uap;
1278 {
1279 struct vattr vattr;
1280 int error;
1281 struct nameidata nd;
1282
1283 bwillwrite();
1284 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1285 if ((error = namei(&nd)) != 0)
1286 return (error);
1287 if (nd.ni_vp != NULL) {
1288 NDFREE(&nd, NDF_ONLY_PNBUF);
1289 if (nd.ni_dvp == nd.ni_vp)
1290 vrele(nd.ni_dvp);
1291 else
1292 vput(nd.ni_dvp);
1293 vrele(nd.ni_vp);
1294 return (EEXIST);
1295 }
1296 VATTR_NULL(&vattr);
1297 vattr.va_type = VFIFO;
1298 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1299 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1300 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1301 if (error == 0)
1302 vput(nd.ni_vp);
1303 NDFREE(&nd, NDF_ONLY_PNBUF);
1304 vput(nd.ni_dvp);
1305 return (error);
1306 }
1307
1308 /*
1309 * Make a hard file link.
1310 */
1311 #ifndef _SYS_SYSPROTO_H_
1312 struct link_args {
1313 char *path;
1314 char *link;
1315 };
1316 #endif
1317 /* ARGSUSED */
1318 int
1319 link(p, uap)
1320 struct proc *p;
1321 register struct link_args /* {
1322 syscallarg(char *) path;
1323 syscallarg(char *) link;
1324 } */ *uap;
1325 {
1326 register struct vnode *vp;
1327 struct nameidata nd;
1328 int error;
1329
1330 bwillwrite();
1331 NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), p);
1332 if ((error = namei(&nd)) != 0)
1333 return (error);
1334 NDFREE(&nd, NDF_ONLY_PNBUF);
1335 vp = nd.ni_vp;
1336 if (vp->v_type == VDIR)
1337 error = EPERM; /* POSIX */
1338 else {
1339 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
1340 error = namei(&nd);
1341 if (!error) {
1342 if (nd.ni_vp != NULL) {
1343 if (nd.ni_vp)
1344 vrele(nd.ni_vp);
1345 error = EEXIST;
1346 } else {
1347 VOP_LEASE(nd.ni_dvp, p, p->p_ucred,
1348 LEASE_WRITE);
1349 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1350 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1351 }
1352 NDFREE(&nd, NDF_ONLY_PNBUF);
1353 if (nd.ni_dvp == nd.ni_vp)
1354 vrele(nd.ni_dvp);
1355 else
1356 vput(nd.ni_dvp);
1357 }
1358 }
1359 vrele(vp);
1360 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link");
1361 ASSERT_VOP_UNLOCKED(nd.ni_vp, "link");
1362 return (error);
1363 }
1364
1365 /*
1366 * Make a symbolic link.
1367 */
1368 #ifndef _SYS_SYSPROTO_H_
1369 struct symlink_args {
1370 char *path;
1371 char *link;
1372 };
1373 #endif
1374 /* ARGSUSED */
1375 int
1376 symlink(p, uap)
1377 struct proc *p;
1378 register struct symlink_args /* {
1379 syscallarg(char *) path;
1380 syscallarg(char *) link;
1381 } */ *uap;
1382 {
1383 struct vattr vattr;
1384 char *path;
1385 int error;
1386 struct nameidata nd;
1387
1388 path = zalloc(namei_zone);
1389 if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0)
1390 goto out;
1391 bwillwrite();
1392 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
1393 if ((error = namei(&nd)) != 0)
1394 goto out;
1395 if (nd.ni_vp) {
1396 NDFREE(&nd, NDF_ONLY_PNBUF);
1397 if (nd.ni_dvp == nd.ni_vp)
1398 vrele(nd.ni_dvp);
1399 else
1400 vput(nd.ni_dvp);
1401 vrele(nd.ni_vp);
1402 error = EEXIST;
1403 goto out;
1404 }
1405 VATTR_NULL(&vattr);
1406 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
1407 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1408 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
1409 NDFREE(&nd, NDF_ONLY_PNBUF);
1410 if (error == 0)
1411 vput(nd.ni_vp);
1412 vput(nd.ni_dvp);
1413 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink");
1414 ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink");
1415 out:
1416 zfree(namei_zone, path);
1417 return (error);
1418 }
1419
1420 /*
1421 * Delete a whiteout from the filesystem.
1422 */
1423 /* ARGSUSED */
1424 int
1425 undelete(p, uap)
1426 struct proc *p;
1427 register struct undelete_args /* {
1428 syscallarg(char *) path;
1429 } */ *uap;
1430 {
1431 int error;
1432 struct nameidata nd;
1433
1434 bwillwrite();
1435 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
1436 SCARG(uap, path), p);
1437 error = namei(&nd);
1438 if (error)
1439 return (error);
1440
1441 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1442 NDFREE(&nd, NDF_ONLY_PNBUF);
1443 if (nd.ni_dvp == nd.ni_vp)
1444 vrele(nd.ni_dvp);
1445 else
1446 vput(nd.ni_dvp);
1447 if (nd.ni_vp)
1448 vrele(nd.ni_vp);
1449 return (EEXIST);
1450 }
1451
1452 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1453 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
1454 NDFREE(&nd, NDF_ONLY_PNBUF);
1455 vput(nd.ni_dvp);
1456 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete");
1457 ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete");
1458 return (error);
1459 }
1460
1461 /*
1462 * Delete a name from the filesystem.
1463 */
1464 #ifndef _SYS_SYSPROTO_H_
1465 struct unlink_args {
1466 char *path;
1467 };
1468 #endif
1469 /* ARGSUSED */
1470 int
1471 unlink(p, uap)
1472 struct proc *p;
1473 struct unlink_args /* {
1474 syscallarg(char *) path;
1475 } */ *uap;
1476 {
1477 register struct vnode *vp;
1478 int error;
1479 struct nameidata nd;
1480
1481 bwillwrite();
1482 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1483 if ((error = namei(&nd)) != 0)
1484 return (error);
1485 vp = nd.ni_vp;
1486 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1487 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1488
1489 if (vp->v_type == VDIR)
1490 error = EPERM; /* POSIX */
1491 else {
1492 /*
1493 * The root of a mounted filesystem cannot be deleted.
1494 *
1495 * XXX: can this only be a VDIR case?
1496 */
1497 if (vp->v_flag & VROOT)
1498 error = EBUSY;
1499 }
1500
1501 if (!error) {
1502 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1503 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
1504 }
1505 NDFREE(&nd, NDF_ONLY_PNBUF);
1506 if (nd.ni_dvp == vp)
1507 vrele(nd.ni_dvp);
1508 else
1509 vput(nd.ni_dvp);
1510 if (vp != NULLVP)
1511 vput(vp);
1512 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
1513 ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
1514 return (error);
1515 }
1516
1517 /*
1518 * Reposition read/write file offset.
1519 */
1520 #ifndef _SYS_SYSPROTO_H_
1521 struct lseek_args {
1522 int fd;
1523 int pad;
1524 off_t offset;
1525 int whence;
1526 };
1527 #endif
1528 int
1529 lseek(p, uap)
1530 struct proc *p;
1531 register struct lseek_args /* {
1532 syscallarg(int) fd;
1533 syscallarg(int) pad;
1534 syscallarg(off_t) offset;
1535 syscallarg(int) whence;
1536 } */ *uap;
1537 {
1538 struct ucred *cred = p->p_ucred;
1539 register struct filedesc *fdp = p->p_fd;
1540 register struct file *fp;
1541 struct vattr vattr;
1542 int error;
1543
1544 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
1545 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
1546 return (EBADF);
1547 if (fp->f_type != DTYPE_VNODE)
1548 return (ESPIPE);
1549 switch (SCARG(uap, whence)) {
1550 case L_INCR:
1551 fp->f_offset += SCARG(uap, offset);
1552 break;
1553 case L_XTND:
1554 error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p);
1555 if (error)
1556 return (error);
1557 fp->f_offset = SCARG(uap, offset) + vattr.va_size;
1558 break;
1559 case L_SET:
1560 fp->f_offset = SCARG(uap, offset);
1561 break;
1562 default:
1563 return (EINVAL);
1564 }
1565 *(off_t *)(p->p_retval) = fp->f_offset;
1566 return (0);
1567 }
1568
1569 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1570 /*
1571 * Reposition read/write file offset.
1572 */
1573 #ifndef _SYS_SYSPROTO_H_
1574 struct olseek_args {
1575 int fd;
1576 long offset;
1577 int whence;
1578 };
1579 #endif
1580 int
1581 olseek(p, uap)
1582 struct proc *p;
1583 register struct olseek_args /* {
1584 syscallarg(int) fd;
1585 syscallarg(long) offset;
1586 syscallarg(int) whence;
1587 } */ *uap;
1588 {
1589 struct lseek_args /* {
1590 syscallarg(int) fd;
1591 syscallarg(int) pad;
1592 syscallarg(off_t) offset;
1593 syscallarg(int) whence;
1594 } */ nuap;
1595 int error;
1596
1597 SCARG(&nuap, fd) = SCARG(uap, fd);
1598 SCARG(&nuap, offset) = SCARG(uap, offset);
1599 SCARG(&nuap, whence) = SCARG(uap, whence);
1600 error = lseek(p, &nuap);
1601 return (error);
1602 }
1603 #endif /* COMPAT_43 */
1604
1605 /*
1606 * Check access permissions.
1607 */
1608 #ifndef _SYS_SYSPROTO_H_
1609 struct access_args {
1610 char *path;
1611 int flags;
1612 };
1613 #endif
1614 int
1615 access(p, uap)
1616 struct proc *p;
1617 register struct access_args /* {
1618 syscallarg(char *) path;
1619 syscallarg(int) flags;
1620 } */ *uap;
1621 {
1622 struct ucred *cred, *tmpcred;
1623 register struct vnode *vp;
1624 int error, flags;
1625 struct nameidata nd;
1626
1627 cred = p->p_ucred;
1628 /*
1629 * Create and modify a temporary credential instead of one that
1630 * is potentially shared. This could also mess up socket
1631 * buffer accounting which can run in an interrupt context.
1632 */
1633 tmpcred = crdup(cred);
1634 tmpcred->cr_uid = p->p_cred->p_ruid;
1635 tmpcred->cr_groups[0] = p->p_cred->p_rgid;
1636 p->p_ucred = tmpcred;
1637 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1638 SCARG(uap, path), p);
1639 if ((error = namei(&nd)) != 0)
1640 goto out1;
1641 vp = nd.ni_vp;
1642
1643 /* Flags == 0 means only check for existence. */
1644 if (SCARG(uap, flags)) {
1645 flags = 0;
1646 if (SCARG(uap, flags) & R_OK)
1647 flags |= VREAD;
1648 if (SCARG(uap, flags) & W_OK)
1649 flags |= VWRITE;
1650 if (SCARG(uap, flags) & X_OK)
1651 flags |= VEXEC;
1652 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1653 error = VOP_ACCESS(vp, flags, tmpcred, p);
1654 }
1655 NDFREE(&nd, NDF_ONLY_PNBUF);
1656 vput(vp);
1657 out1:
1658 p->p_ucred = cred;
1659 crfree(tmpcred);
1660 return (error);
1661 }
1662
1663 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1664 /*
1665 * Get file status; this version follows links.
1666 */
1667 #ifndef _SYS_SYSPROTO_H_
1668 struct ostat_args {
1669 char *path;
1670 struct ostat *ub;
1671 };
1672 #endif
1673 /* ARGSUSED */
1674 int
1675 ostat(p, uap)
1676 struct proc *p;
1677 register struct ostat_args /* {
1678 syscallarg(char *) path;
1679 syscallarg(struct ostat *) ub;
1680 } */ *uap;
1681 {
1682 struct stat sb;
1683 struct ostat osb;
1684 int error;
1685 struct nameidata nd;
1686
1687 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1688 SCARG(uap, path), p);
1689 if ((error = namei(&nd)) != 0)
1690 return (error);
1691 NDFREE(&nd, NDF_ONLY_PNBUF);
1692 error = vn_stat(nd.ni_vp, &sb, p);
1693 vput(nd.ni_vp);
1694 if (error)
1695 return (error);
1696 cvtstat(&sb, &osb);
1697 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1698 return (error);
1699 }
1700
1701 /*
1702 * Get file status; this version does not follow links.
1703 */
1704 #ifndef _SYS_SYSPROTO_H_
1705 struct olstat_args {
1706 char *path;
1707 struct ostat *ub;
1708 };
1709 #endif
1710 /* ARGSUSED */
1711 int
1712 olstat(p, uap)
1713 struct proc *p;
1714 register struct olstat_args /* {
1715 syscallarg(char *) path;
1716 syscallarg(struct ostat *) ub;
1717 } */ *uap;
1718 {
1719 struct vnode *vp;
1720 struct stat sb;
1721 struct ostat osb;
1722 int error;
1723 struct nameidata nd;
1724
1725 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1726 SCARG(uap, path), p);
1727 if ((error = namei(&nd)) != 0)
1728 return (error);
1729 vp = nd.ni_vp;
1730 error = vn_stat(vp, &sb, p);
1731 NDFREE(&nd, NDF_ONLY_PNBUF);
1732 vput(vp);
1733 if (error)
1734 return (error);
1735 cvtstat(&sb, &osb);
1736 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1737 return (error);
1738 }
1739
1740 /*
1741 * Convert from an old to a new stat structure.
1742 */
1743 void
1744 cvtstat(st, ost)
1745 struct stat *st;
1746 struct ostat *ost;
1747 {
1748
1749 ost->st_dev = st->st_dev;
1750 ost->st_ino = st->st_ino;
1751 ost->st_mode = st->st_mode;
1752 ost->st_nlink = st->st_nlink;
1753 ost->st_uid = st->st_uid;
1754 ost->st_gid = st->st_gid;
1755 ost->st_rdev = st->st_rdev;
1756 if (st->st_size < (quad_t)1 << 32)
1757 ost->st_size = st->st_size;
1758 else
1759 ost->st_size = -2;
1760 ost->st_atime = st->st_atime;
1761 ost->st_mtime = st->st_mtime;
1762 ost->st_ctime = st->st_ctime;
1763 ost->st_blksize = st->st_blksize;
1764 ost->st_blocks = st->st_blocks;
1765 ost->st_flags = st->st_flags;
1766 ost->st_gen = st->st_gen;
1767 }
1768 #endif /* COMPAT_43 || COMPAT_SUNOS */
1769
1770 /*
1771 * Get file status; this version follows links.
1772 */
1773 #ifndef _SYS_SYSPROTO_H_
1774 struct stat_args {
1775 char *path;
1776 struct stat *ub;
1777 };
1778 #endif
1779 /* ARGSUSED */
1780 int
1781 stat(p, uap)
1782 struct proc *p;
1783 register struct stat_args /* {
1784 syscallarg(char *) path;
1785 syscallarg(struct stat *) ub;
1786 } */ *uap;
1787 {
1788 struct stat sb;
1789 int error;
1790 struct nameidata nd;
1791
1792 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1793 SCARG(uap, path), p);
1794 if ((error = namei(&nd)) != 0)
1795 return (error);
1796 error = vn_stat(nd.ni_vp, &sb, p);
1797 NDFREE(&nd, NDF_ONLY_PNBUF);
1798 vput(nd.ni_vp);
1799 if (error)
1800 return (error);
1801 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1802 return (error);
1803 }
1804
1805 /*
1806 * Get file status; this version does not follow links.
1807 */
1808 #ifndef _SYS_SYSPROTO_H_
1809 struct lstat_args {
1810 char *path;
1811 struct stat *ub;
1812 };
1813 #endif
1814 /* ARGSUSED */
1815 int
1816 lstat(p, uap)
1817 struct proc *p;
1818 register struct lstat_args /* {
1819 syscallarg(char *) path;
1820 syscallarg(struct stat *) ub;
1821 } */ *uap;
1822 {
1823 int error;
1824 struct vnode *vp;
1825 struct stat sb;
1826 struct nameidata nd;
1827
1828 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1829 SCARG(uap, path), p);
1830 if ((error = namei(&nd)) != 0)
1831 return (error);
1832 vp = nd.ni_vp;
1833 error = vn_stat(vp, &sb, p);
1834 NDFREE(&nd, NDF_ONLY_PNBUF);
1835 vput(vp);
1836 if (error)
1837 return (error);
1838 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1839 return (error);
1840 }
1841
1842 void
1843 cvtnstat(sb, nsb)
1844 struct stat *sb;
1845 struct nstat *nsb;
1846 {
1847 nsb->st_dev = sb->st_dev;
1848 nsb->st_ino = sb->st_ino;
1849 nsb->st_mode = sb->st_mode;
1850 nsb->st_nlink = sb->st_nlink;
1851 nsb->st_uid = sb->st_uid;
1852 nsb->st_gid = sb->st_gid;
1853 nsb->st_rdev = sb->st_rdev;
1854 nsb->st_atimespec = sb->st_atimespec;
1855 nsb->st_mtimespec = sb->st_mtimespec;
1856 nsb->st_ctimespec = sb->st_ctimespec;
1857 nsb->st_size = sb->st_size;
1858 nsb->st_blocks = sb->st_blocks;
1859 nsb->st_blksize = sb->st_blksize;
1860 nsb->st_flags = sb->st_flags;
1861 nsb->st_gen = sb->st_gen;
1862 nsb->st_qspare[0] = sb->st_qspare[0];
1863 nsb->st_qspare[1] = sb->st_qspare[1];
1864 }
1865
1866 #ifndef _SYS_SYSPROTO_H_
1867 struct nstat_args {
1868 char *path;
1869 struct nstat *ub;
1870 };
1871 #endif
1872 /* ARGSUSED */
1873 int
1874 nstat(p, uap)
1875 struct proc *p;
1876 register struct nstat_args /* {
1877 syscallarg(char *) path;
1878 syscallarg(struct nstat *) ub;
1879 } */ *uap;
1880 {
1881 struct stat sb;
1882 struct nstat nsb;
1883 int error;
1884 struct nameidata nd;
1885
1886 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1887 SCARG(uap, path), p);
1888 if ((error = namei(&nd)) != 0)
1889 return (error);
1890 NDFREE(&nd, NDF_ONLY_PNBUF);
1891 error = vn_stat(nd.ni_vp, &sb, p);
1892 vput(nd.ni_vp);
1893 if (error)
1894 return (error);
1895 cvtnstat(&sb, &nsb);
1896 error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
1897 return (error);
1898 }
1899
1900 /*
1901 * Get file status; this version does not follow links.
1902 */
1903 #ifndef _SYS_SYSPROTO_H_
1904 struct lstat_args {
1905 char *path;
1906 struct stat *ub;
1907 };
1908 #endif
1909 /* ARGSUSED */
1910 int
1911 nlstat(p, uap)
1912 struct proc *p;
1913 register struct nlstat_args /* {
1914 syscallarg(char *) path;
1915 syscallarg(struct nstat *) ub;
1916 } */ *uap;
1917 {
1918 int error;
1919 struct vnode *vp;
1920 struct stat sb;
1921 struct nstat nsb;
1922 struct nameidata nd;
1923
1924 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1925 SCARG(uap, path), p);
1926 if ((error = namei(&nd)) != 0)
1927 return (error);
1928 vp = nd.ni_vp;
1929 NDFREE(&nd, NDF_ONLY_PNBUF);
1930 error = vn_stat(vp, &sb, p);
1931 vput(vp);
1932 if (error)
1933 return (error);
1934 cvtnstat(&sb, &nsb);
1935 error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
1936 return (error);
1937 }
1938
1939 /*
1940 * Get configurable pathname variables.
1941 */
1942 #ifndef _SYS_SYSPROTO_H_
1943 struct pathconf_args {
1944 char *path;
1945 int name;
1946 };
1947 #endif
1948 /* ARGSUSED */
1949 int
1950 pathconf(p, uap)
1951 struct proc *p;
1952 register struct pathconf_args /* {
1953 syscallarg(char *) path;
1954 syscallarg(int) name;
1955 } */ *uap;
1956 {
1957 int error;
1958 struct nameidata nd;
1959
1960 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1961 SCARG(uap, path), p);
1962 if ((error = namei(&nd)) != 0)
1963 return (error);
1964 NDFREE(&nd, NDF_ONLY_PNBUF);
1965 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), p->p_retval);
1966 vput(nd.ni_vp);
1967 return (error);
1968 }
1969
1970 /*
1971 * Return target name of a symbolic link.
1972 */
1973 #ifndef _SYS_SYSPROTO_H_
1974 struct readlink_args {
1975 char *path;
1976 char *buf;
1977 int count;
1978 };
1979 #endif
1980 /* ARGSUSED */
1981 int
1982 readlink(p, uap)
1983 struct proc *p;
1984 register struct readlink_args /* {
1985 syscallarg(char *) path;
1986 syscallarg(char *) buf;
1987 syscallarg(int) count;
1988 } */ *uap;
1989 {
1990 register struct vnode *vp;
1991 struct iovec aiov;
1992 struct uio auio;
1993 int error;
1994 struct nameidata nd;
1995
1996 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1997 SCARG(uap, path), p);
1998 if ((error = namei(&nd)) != 0)
1999 return (error);
2000 NDFREE(&nd, NDF_ONLY_PNBUF);
2001 vp = nd.ni_vp;
2002 if (vp->v_type != VLNK)
2003 error = EINVAL;
2004 else {
2005 aiov.iov_base = SCARG(uap, buf);
2006 aiov.iov_len = SCARG(uap, count);
2007 auio.uio_iov = &aiov;
2008 auio.uio_iovcnt = 1;
2009 auio.uio_offset = 0;
2010 auio.uio_rw = UIO_READ;
2011 auio.uio_segflg = UIO_USERSPACE;
2012 auio.uio_procp = p;
2013 auio.uio_resid = SCARG(uap, count);
2014 error = VOP_READLINK(vp, &auio, p->p_ucred);
2015 }
2016 vput(vp);
2017 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
2018 return (error);
2019 }
2020
2021 static int
2022 setfflags(p, vp, flags)
2023 struct proc *p;
2024 struct vnode *vp;
2025 int flags;
2026 {
2027 int error;
2028 struct vattr vattr;
2029
2030 /*
2031 * Prevent non-root users from setting flags on devices. When
2032 * a device is reused, users can retain ownership of the device
2033 * if they are allowed to set flags and programs assume that
2034 * chown can't fail when done as root.
2035 */
2036 if ((vp->v_type == VCHR || vp->v_type == VBLK) &&
2037 ((error = suser_xxx(p->p_ucred, p, PRISON_ROOT)) != 0))
2038 return (error);
2039
2040 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2041 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2042 VATTR_NULL(&vattr);
2043 vattr.va_flags = flags;
2044 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2045 VOP_UNLOCK(vp, 0, p);
2046 return (error);
2047 }
2048
2049 /*
2050 * Change flags of a file given a path name.
2051 */
2052 #ifndef _SYS_SYSPROTO_H_
2053 struct chflags_args {
2054 char *path;
2055 int flags;
2056 };
2057 #endif
2058 /* ARGSUSED */
2059 int
2060 chflags(p, uap)
2061 struct proc *p;
2062 register struct chflags_args /* {
2063 syscallarg(char *) path;
2064 syscallarg(int) flags;
2065 } */ *uap;
2066 {
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 NDFREE(&nd, NDF_ONLY_PNBUF);
2074 error = setfflags(p, nd.ni_vp, SCARG(uap, flags));
2075 vrele(nd.ni_vp);
2076 return error;
2077 }
2078
2079 /*
2080 * Change flags of a file given a file descriptor.
2081 */
2082 #ifndef _SYS_SYSPROTO_H_
2083 struct fchflags_args {
2084 int fd;
2085 int flags;
2086 };
2087 #endif
2088 /* ARGSUSED */
2089 int
2090 fchflags(p, uap)
2091 struct proc *p;
2092 register struct fchflags_args /* {
2093 syscallarg(int) fd;
2094 syscallarg(int) flags;
2095 } */ *uap;
2096 {
2097 struct file *fp;
2098 int error;
2099
2100 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2101 return (error);
2102 return setfflags(p, (struct vnode *) fp->f_data, SCARG(uap, flags));
2103 }
2104
2105 static int
2106 setfmode(p, vp, mode)
2107 struct proc *p;
2108 struct vnode *vp;
2109 int mode;
2110 {
2111 int error;
2112 struct vattr vattr;
2113
2114 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2115 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2116 VATTR_NULL(&vattr);
2117 vattr.va_mode = mode & ALLPERMS;
2118 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2119 VOP_UNLOCK(vp, 0, p);
2120 return error;
2121 }
2122
2123 /*
2124 * Change mode of a file given path name.
2125 */
2126 #ifndef _SYS_SYSPROTO_H_
2127 struct chmod_args {
2128 char *path;
2129 int mode;
2130 };
2131 #endif
2132 /* ARGSUSED */
2133 int
2134 chmod(p, uap)
2135 struct proc *p;
2136 register struct chmod_args /* {
2137 syscallarg(char *) path;
2138 syscallarg(int) mode;
2139 } */ *uap;
2140 {
2141 int error;
2142 struct nameidata nd;
2143
2144 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2145 if ((error = namei(&nd)) != 0)
2146 return (error);
2147 NDFREE(&nd, NDF_ONLY_PNBUF);
2148 error = setfmode(p, nd.ni_vp, SCARG(uap, mode));
2149 vrele(nd.ni_vp);
2150 return error;
2151 }
2152
2153 /*
2154 * Change mode of a file given path name (don't follow links.)
2155 */
2156 #ifndef _SYS_SYSPROTO_H_
2157 struct lchmod_args {
2158 char *path;
2159 int mode;
2160 };
2161 #endif
2162 /* ARGSUSED */
2163 int
2164 lchmod(p, uap)
2165 struct proc *p;
2166 register struct lchmod_args /* {
2167 syscallarg(char *) path;
2168 syscallarg(int) mode;
2169 } */ *uap;
2170 {
2171 int error;
2172 struct nameidata nd;
2173
2174 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2175 if ((error = namei(&nd)) != 0)
2176 return (error);
2177 NDFREE(&nd, NDF_ONLY_PNBUF);
2178 error = setfmode(p, nd.ni_vp, SCARG(uap, mode));
2179 vrele(nd.ni_vp);
2180 return error;
2181 }
2182
2183 /*
2184 * Change mode of a file given a file descriptor.
2185 */
2186 #ifndef _SYS_SYSPROTO_H_
2187 struct fchmod_args {
2188 int fd;
2189 int mode;
2190 };
2191 #endif
2192 /* ARGSUSED */
2193 int
2194 fchmod(p, uap)
2195 struct proc *p;
2196 register struct fchmod_args /* {
2197 syscallarg(int) fd;
2198 syscallarg(int) mode;
2199 } */ *uap;
2200 {
2201 struct file *fp;
2202 int error;
2203
2204 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2205 return (error);
2206 return setfmode(p, (struct vnode *)fp->f_data, SCARG(uap, mode));
2207 }
2208
2209 static int
2210 setfown(p, vp, uid, gid)
2211 struct proc *p;
2212 struct vnode *vp;
2213 uid_t uid;
2214 gid_t gid;
2215 {
2216 int error;
2217 struct vattr vattr;
2218
2219 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2220 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2221 VATTR_NULL(&vattr);
2222 vattr.va_uid = uid;
2223 vattr.va_gid = gid;
2224 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2225 VOP_UNLOCK(vp, 0, p);
2226 return error;
2227 }
2228
2229 /*
2230 * Set ownership given a path name.
2231 */
2232 #ifndef _SYS_SYSPROTO_H_
2233 struct chown_args {
2234 char *path;
2235 int uid;
2236 int gid;
2237 };
2238 #endif
2239 /* ARGSUSED */
2240 int
2241 chown(p, uap)
2242 struct proc *p;
2243 register struct chown_args /* {
2244 syscallarg(char *) path;
2245 syscallarg(int) uid;
2246 syscallarg(int) gid;
2247 } */ *uap;
2248 {
2249 int error;
2250 struct nameidata nd;
2251
2252 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2253 if ((error = namei(&nd)) != 0)
2254 return (error);
2255 NDFREE(&nd, NDF_ONLY_PNBUF);
2256 error = setfown(p, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2257 vrele(nd.ni_vp);
2258 return (error);
2259 }
2260
2261 /*
2262 * Set ownership given a path name, do not cross symlinks.
2263 */
2264 #ifndef _SYS_SYSPROTO_H_
2265 struct lchown_args {
2266 char *path;
2267 int uid;
2268 int gid;
2269 };
2270 #endif
2271 /* ARGSUSED */
2272 int
2273 lchown(p, uap)
2274 struct proc *p;
2275 register struct lchown_args /* {
2276 syscallarg(char *) path;
2277 syscallarg(int) uid;
2278 syscallarg(int) gid;
2279 } */ *uap;
2280 {
2281 int error;
2282 struct nameidata nd;
2283
2284 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2285 if ((error = namei(&nd)) != 0)
2286 return (error);
2287 NDFREE(&nd, NDF_ONLY_PNBUF);
2288 error = setfown(p, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2289 vrele(nd.ni_vp);
2290 return (error);
2291 }
2292
2293 /*
2294 * Set ownership given a file descriptor.
2295 */
2296 #ifndef _SYS_SYSPROTO_H_
2297 struct fchown_args {
2298 int fd;
2299 int uid;
2300 int gid;
2301 };
2302 #endif
2303 /* ARGSUSED */
2304 int
2305 fchown(p, uap)
2306 struct proc *p;
2307 register struct fchown_args /* {
2308 syscallarg(int) fd;
2309 syscallarg(int) uid;
2310 syscallarg(int) gid;
2311 } */ *uap;
2312 {
2313 struct file *fp;
2314 int error;
2315
2316 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2317 return (error);
2318 return setfown(p, (struct vnode *)fp->f_data,
2319 SCARG(uap, uid), SCARG(uap, gid));
2320 }
2321
2322 static int
2323 getutimes(usrtvp, tsp)
2324 const struct timeval *usrtvp;
2325 struct timespec *tsp;
2326 {
2327 struct timeval tv[2];
2328 int error;
2329
2330 if (usrtvp == NULL) {
2331 microtime(&tv[0]);
2332 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2333 tsp[1] = tsp[0];
2334 } else {
2335 if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0)
2336 return (error);
2337 if (tv[0].tv_usec < 0 || tv[0].tv_usec >= 1000000 ||
2338 tv[1].tv_usec < 0 || tv[1].tv_usec >= 1000000)
2339 return (EINVAL);
2340 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2341 TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]);
2342 }
2343 return 0;
2344 }
2345
2346 static int
2347 setutimes(p, vp, ts, nullflag)
2348 struct proc *p;
2349 struct vnode *vp;
2350 const struct timespec *ts;
2351 int nullflag;
2352 {
2353 int error;
2354 struct vattr vattr;
2355
2356 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2357 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2358 VATTR_NULL(&vattr);
2359 vattr.va_atime = ts[0];
2360 vattr.va_mtime = ts[1];
2361 if (nullflag)
2362 vattr.va_vaflags |= VA_UTIMES_NULL;
2363 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2364 VOP_UNLOCK(vp, 0, p);
2365 return error;
2366 }
2367
2368 /*
2369 * Set the access and modification times of a file.
2370 */
2371 #ifndef _SYS_SYSPROTO_H_
2372 struct utimes_args {
2373 char *path;
2374 struct timeval *tptr;
2375 };
2376 #endif
2377 /* ARGSUSED */
2378 int
2379 utimes(p, uap)
2380 struct proc *p;
2381 register struct utimes_args /* {
2382 syscallarg(char *) path;
2383 syscallarg(struct timeval *) tptr;
2384 } */ *uap;
2385 {
2386 struct timespec ts[2];
2387 struct timeval *usrtvp;
2388 int error;
2389 struct nameidata nd;
2390
2391 usrtvp = SCARG(uap, tptr);
2392 if ((error = getutimes(usrtvp, ts)) != 0)
2393 return (error);
2394 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2395 if ((error = namei(&nd)) != 0)
2396 return (error);
2397 NDFREE(&nd, NDF_ONLY_PNBUF);
2398 error = setutimes(p, nd.ni_vp, ts, usrtvp == NULL);
2399 vrele(nd.ni_vp);
2400 return (error);
2401 }
2402
2403 /*
2404 * Set the access and modification times of a file.
2405 */
2406 #ifndef _SYS_SYSPROTO_H_
2407 struct lutimes_args {
2408 char *path;
2409 struct timeval *tptr;
2410 };
2411 #endif
2412 /* ARGSUSED */
2413 int
2414 lutimes(p, uap)
2415 struct proc *p;
2416 register struct lutimes_args /* {
2417 syscallarg(char *) path;
2418 syscallarg(struct timeval *) tptr;
2419 } */ *uap;
2420 {
2421 struct timespec ts[2];
2422 struct timeval *usrtvp;
2423 int error;
2424 struct nameidata nd;
2425
2426 usrtvp = SCARG(uap, tptr);
2427 if ((error = getutimes(usrtvp, ts)) != 0)
2428 return (error);
2429 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2430 if ((error = namei(&nd)) != 0)
2431 return (error);
2432 NDFREE(&nd, NDF_ONLY_PNBUF);
2433 error = setutimes(p, nd.ni_vp, ts, usrtvp == NULL);
2434 vrele(nd.ni_vp);
2435 return (error);
2436 }
2437
2438 /*
2439 * Set the access and modification times of a file.
2440 */
2441 #ifndef _SYS_SYSPROTO_H_
2442 struct futimes_args {
2443 int fd;
2444 struct timeval *tptr;
2445 };
2446 #endif
2447 /* ARGSUSED */
2448 int
2449 futimes(p, uap)
2450 struct proc *p;
2451 register struct futimes_args /* {
2452 syscallarg(int ) fd;
2453 syscallarg(struct timeval *) tptr;
2454 } */ *uap;
2455 {
2456 struct timespec ts[2];
2457 struct file *fp;
2458 struct timeval *usrtvp;
2459 int error;
2460
2461 usrtvp = SCARG(uap, tptr);
2462 if ((error = getutimes(usrtvp, ts)) != 0)
2463 return (error);
2464 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2465 return (error);
2466 return setutimes(p, (struct vnode *)fp->f_data, ts, usrtvp == NULL);
2467 }
2468
2469 /*
2470 * Truncate a file given its path name.
2471 */
2472 #ifndef _SYS_SYSPROTO_H_
2473 struct truncate_args {
2474 char *path;
2475 int pad;
2476 off_t length;
2477 };
2478 #endif
2479 /* ARGSUSED */
2480 int
2481 truncate(p, uap)
2482 struct proc *p;
2483 register struct truncate_args /* {
2484 syscallarg(char *) path;
2485 syscallarg(int) pad;
2486 syscallarg(off_t) length;
2487 } */ *uap;
2488 {
2489 register struct vnode *vp;
2490 struct vattr vattr;
2491 int error;
2492 struct nameidata nd;
2493
2494 if (uap->length < 0)
2495 return(EINVAL);
2496 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2497 if ((error = namei(&nd)) != 0)
2498 return (error);
2499 vp = nd.ni_vp;
2500 NDFREE(&nd, NDF_ONLY_PNBUF);
2501 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2502 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2503 if (vp->v_type == VDIR)
2504 error = EISDIR;
2505 else if ((error = vn_writechk(vp)) == 0 &&
2506 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
2507 VATTR_NULL(&vattr);
2508 vattr.va_size = SCARG(uap, length);
2509 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2510 }
2511 vput(vp);
2512 return (error);
2513 }
2514
2515 /*
2516 * Truncate a file given a file descriptor.
2517 */
2518 #ifndef _SYS_SYSPROTO_H_
2519 struct ftruncate_args {
2520 int fd;
2521 int pad;
2522 off_t length;
2523 };
2524 #endif
2525 /* ARGSUSED */
2526 int
2527 ftruncate(p, uap)
2528 struct proc *p;
2529 register struct ftruncate_args /* {
2530 syscallarg(int) fd;
2531 syscallarg(int) pad;
2532 syscallarg(off_t) length;
2533 } */ *uap;
2534 {
2535 struct vattr vattr;
2536 struct vnode *vp;
2537 struct file *fp;
2538 int error;
2539
2540 if (uap->length < 0)
2541 return(EINVAL);
2542 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2543 return (error);
2544 if ((fp->f_flag & FWRITE) == 0)
2545 return (EINVAL);
2546 vp = (struct vnode *)fp->f_data;
2547 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2548 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2549 if (vp->v_type == VDIR)
2550 error = EISDIR;
2551 else if ((error = vn_writechk(vp)) == 0) {
2552 VATTR_NULL(&vattr);
2553 vattr.va_size = SCARG(uap, length);
2554 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
2555 }
2556 VOP_UNLOCK(vp, 0, p);
2557 return (error);
2558 }
2559
2560 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2561 /*
2562 * Truncate a file given its path name.
2563 */
2564 #ifndef _SYS_SYSPROTO_H_
2565 struct otruncate_args {
2566 char *path;
2567 long length;
2568 };
2569 #endif
2570 /* ARGSUSED */
2571 int
2572 otruncate(p, uap)
2573 struct proc *p;
2574 register struct otruncate_args /* {
2575 syscallarg(char *) path;
2576 syscallarg(long) length;
2577 } */ *uap;
2578 {
2579 struct truncate_args /* {
2580 syscallarg(char *) path;
2581 syscallarg(int) pad;
2582 syscallarg(off_t) length;
2583 } */ nuap;
2584
2585 SCARG(&nuap, path) = SCARG(uap, path);
2586 SCARG(&nuap, length) = SCARG(uap, length);
2587 return (truncate(p, &nuap));
2588 }
2589
2590 /*
2591 * Truncate a file given a file descriptor.
2592 */
2593 #ifndef _SYS_SYSPROTO_H_
2594 struct oftruncate_args {
2595 int fd;
2596 long length;
2597 };
2598 #endif
2599 /* ARGSUSED */
2600 int
2601 oftruncate(p, uap)
2602 struct proc *p;
2603 register struct oftruncate_args /* {
2604 syscallarg(int) fd;
2605 syscallarg(long) length;
2606 } */ *uap;
2607 {
2608 struct ftruncate_args /* {
2609 syscallarg(int) fd;
2610 syscallarg(int) pad;
2611 syscallarg(off_t) length;
2612 } */ nuap;
2613
2614 SCARG(&nuap, fd) = SCARG(uap, fd);
2615 SCARG(&nuap, length) = SCARG(uap, length);
2616 return (ftruncate(p, &nuap));
2617 }
2618 #endif /* COMPAT_43 || COMPAT_SUNOS */
2619
2620 /*
2621 * Sync an open file.
2622 */
2623 #ifndef _SYS_SYSPROTO_H_
2624 struct fsync_args {
2625 int fd;
2626 };
2627 #endif
2628 /* ARGSUSED */
2629 int
2630 fsync(p, uap)
2631 struct proc *p;
2632 struct fsync_args /* {
2633 syscallarg(int) fd;
2634 } */ *uap;
2635 {
2636 register struct vnode *vp;
2637 struct file *fp;
2638 vm_object_t obj;
2639 int error;
2640
2641 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2642 return (error);
2643 vp = (struct vnode *)fp->f_data;
2644 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2645 if (VOP_GETVOBJECT(vp, &obj) == 0)
2646 vm_object_page_clean(obj, 0, 0, 0);
2647 if ((error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p)) == 0 &&
2648 vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP) &&
2649 bioops.io_fsync)
2650 error = (*bioops.io_fsync)(vp);
2651 VOP_UNLOCK(vp, 0, p);
2652 return (error);
2653 }
2654
2655 /*
2656 * Rename files. Source and destination must either both be directories,
2657 * or both not be directories. If target is a directory, it must be empty.
2658 */
2659 #ifndef _SYS_SYSPROTO_H_
2660 struct rename_args {
2661 char *from;
2662 char *to;
2663 };
2664 #endif
2665 /* ARGSUSED */
2666 int
2667 rename(p, uap)
2668 struct proc *p;
2669 register struct rename_args /* {
2670 syscallarg(char *) from;
2671 syscallarg(char *) to;
2672 } */ *uap;
2673 {
2674 register struct vnode *tvp, *fvp, *tdvp;
2675 struct nameidata fromnd, tond;
2676 int error;
2677
2678 bwillwrite();
2679 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
2680 SCARG(uap, from), p);
2681 if ((error = namei(&fromnd)) != 0)
2682 return (error);
2683 fvp = fromnd.ni_vp;
2684 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ,
2685 UIO_USERSPACE, SCARG(uap, to), p);
2686 if (fromnd.ni_vp->v_type == VDIR)
2687 tond.ni_cnd.cn_flags |= WILLBEDIR;
2688 if ((error = namei(&tond)) != 0) {
2689 /* Translate error code for rename("dir1", "dir2/."). */
2690 if (error == EISDIR && fvp->v_type == VDIR)
2691 error = EINVAL;
2692 NDFREE(&fromnd, NDF_ONLY_PNBUF);
2693 vrele(fromnd.ni_dvp);
2694 vrele(fvp);
2695 goto out1;
2696 }
2697 tdvp = tond.ni_dvp;
2698 tvp = tond.ni_vp;
2699 if (tvp != NULL) {
2700 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2701 error = ENOTDIR;
2702 goto out;
2703 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2704 error = EISDIR;
2705 goto out;
2706 }
2707 }
2708 if (fvp == tdvp)
2709 error = EINVAL;
2710 /*
2711 * If the source is the same as the destination (that is, if they
2712 * are links to the same vnode), then there is nothing to do.
2713 */
2714 if (fvp == tvp)
2715 error = -1;
2716 out:
2717 if (!error) {
2718 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
2719 if (fromnd.ni_dvp != tdvp) {
2720 VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2721 }
2722 if (tvp) {
2723 VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
2724 }
2725 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2726 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2727 NDFREE(&fromnd, NDF_ONLY_PNBUF);
2728 NDFREE(&tond, NDF_ONLY_PNBUF);
2729 } else {
2730 NDFREE(&fromnd, NDF_ONLY_PNBUF);
2731 NDFREE(&tond, NDF_ONLY_PNBUF);
2732 if (tdvp == tvp)
2733 vrele(tdvp);
2734 else
2735 vput(tdvp);
2736 if (tvp)
2737 vput(tvp);
2738 vrele(fromnd.ni_dvp);
2739 vrele(fvp);
2740 }
2741 vrele(tond.ni_startdir);
2742 ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename");
2743 ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename");
2744 ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename");
2745 ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename");
2746 out1:
2747 if (fromnd.ni_startdir)
2748 vrele(fromnd.ni_startdir);
2749 if (error == -1)
2750 return (0);
2751 return (error);
2752 }
2753
2754 /*
2755 * Make a directory file.
2756 */
2757 #ifndef _SYS_SYSPROTO_H_
2758 struct mkdir_args {
2759 char *path;
2760 int mode;
2761 };
2762 #endif
2763 /* ARGSUSED */
2764 int
2765 mkdir(p, uap)
2766 struct proc *p;
2767 register struct mkdir_args /* {
2768 syscallarg(char *) path;
2769 syscallarg(int) mode;
2770 } */ *uap;
2771 {
2772 register struct vnode *vp;
2773 struct vattr vattr;
2774 int error;
2775 struct nameidata nd;
2776
2777 bwillwrite();
2778 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
2779 nd.ni_cnd.cn_flags |= WILLBEDIR;
2780 if ((error = namei(&nd)) != 0)
2781 return (error);
2782 vp = nd.ni_vp;
2783 if (vp != NULL) {
2784 NDFREE(&nd, NDF_ONLY_PNBUF);
2785 if (nd.ni_dvp == vp)
2786 vrele(nd.ni_dvp);
2787 else
2788 vput(nd.ni_dvp);
2789 vrele(vp);
2790 return (EEXIST);
2791 }
2792 VATTR_NULL(&vattr);
2793 vattr.va_type = VDIR;
2794 vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
2795 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2796 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
2797 NDFREE(&nd, NDF_ONLY_PNBUF);
2798 vput(nd.ni_dvp);
2799 if (!error)
2800 vput(nd.ni_vp);
2801 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir");
2802 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir");
2803 return (error);
2804 }
2805
2806 /*
2807 * Remove a directory file.
2808 */
2809 #ifndef _SYS_SYSPROTO_H_
2810 struct rmdir_args {
2811 char *path;
2812 };
2813 #endif
2814 /* ARGSUSED */
2815 int
2816 rmdir(p, uap)
2817 struct proc *p;
2818 struct rmdir_args /* {
2819 syscallarg(char *) path;
2820 } */ *uap;
2821 {
2822 register struct vnode *vp;
2823 int error;
2824 struct nameidata nd;
2825
2826 bwillwrite();
2827 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
2828 SCARG(uap, path), p);
2829 if ((error = namei(&nd)) != 0)
2830 return (error);
2831 vp = nd.ni_vp;
2832 if (vp->v_type != VDIR) {
2833 error = ENOTDIR;
2834 goto out;
2835 }
2836 /*
2837 * No rmdir "." please.
2838 */
2839 if (nd.ni_dvp == vp) {
2840 error = EINVAL;
2841 goto out;
2842 }
2843 /*
2844 * The root of a mounted filesystem cannot be deleted.
2845 */
2846 if (vp->v_flag & VROOT)
2847 error = EBUSY;
2848 else {
2849 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2850 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2851 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2852 }
2853 out:
2854 NDFREE(&nd, NDF_ONLY_PNBUF);
2855 if (nd.ni_dvp == vp)
2856 vrele(nd.ni_dvp);
2857 else
2858 vput(nd.ni_dvp);
2859 if (vp != NULLVP)
2860 vput(vp);
2861 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir");
2862 ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir");
2863 return (error);
2864 }
2865
2866 #ifdef COMPAT_43
2867 /*
2868 * Read a block of directory entries in a file system independent format.
2869 */
2870 #ifndef _SYS_SYSPROTO_H_
2871 struct ogetdirentries_args {
2872 int fd;
2873 char *buf;
2874 u_int count;
2875 long *basep;
2876 };
2877 #endif
2878 int
2879 ogetdirentries(p, uap)
2880 struct proc *p;
2881 register struct ogetdirentries_args /* {
2882 syscallarg(int) fd;
2883 syscallarg(char *) buf;
2884 syscallarg(u_int) count;
2885 syscallarg(long *) basep;
2886 } */ *uap;
2887 {
2888 struct vnode *vp;
2889 struct file *fp;
2890 struct uio auio, kuio;
2891 struct iovec aiov, kiov;
2892 struct dirent *dp, *edp;
2893 caddr_t dirbuf;
2894 int error, eofflag, readcnt;
2895 long loff;
2896
2897 /* XXX arbitrary sanity limit on `count'. */
2898 if (SCARG(uap, count) > 64 * 1024)
2899 return (EINVAL);
2900 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2901 return (error);
2902 if ((fp->f_flag & FREAD) == 0)
2903 return (EBADF);
2904 vp = (struct vnode *)fp->f_data;
2905 unionread:
2906 if (vp->v_type != VDIR)
2907 return (EINVAL);
2908 aiov.iov_base = SCARG(uap, buf);
2909 aiov.iov_len = SCARG(uap, count);
2910 auio.uio_iov = &aiov;
2911 auio.uio_iovcnt = 1;
2912 auio.uio_rw = UIO_READ;
2913 auio.uio_segflg = UIO_USERSPACE;
2914 auio.uio_procp = p;
2915 auio.uio_resid = SCARG(uap, count);
2916 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2917 loff = auio.uio_offset = fp->f_offset;
2918 # if (BYTE_ORDER != LITTLE_ENDIAN)
2919 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
2920 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
2921 NULL, NULL);
2922 fp->f_offset = auio.uio_offset;
2923 } else
2924 # endif
2925 {
2926 kuio = auio;
2927 kuio.uio_iov = &kiov;
2928 kuio.uio_segflg = UIO_SYSSPACE;
2929 kiov.iov_len = SCARG(uap, count);
2930 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
2931 kiov.iov_base = dirbuf;
2932 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
2933 NULL, NULL);
2934 fp->f_offset = kuio.uio_offset;
2935 if (error == 0) {
2936 readcnt = SCARG(uap, count) - kuio.uio_resid;
2937 edp = (struct dirent *)&dirbuf[readcnt];
2938 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
2939 # if (BYTE_ORDER == LITTLE_ENDIAN)
2940 /*
2941 * The expected low byte of
2942 * dp->d_namlen is our dp->d_type.
2943 * The high MBZ byte of dp->d_namlen
2944 * is our dp->d_namlen.
2945 */
2946 dp->d_type = dp->d_namlen;
2947 dp->d_namlen = 0;
2948 # else
2949 /*
2950 * The dp->d_type is the high byte
2951 * of the expected dp->d_namlen,
2952 * so must be zero'ed.
2953 */
2954 dp->d_type = 0;
2955 # endif
2956 if (dp->d_reclen > 0) {
2957 dp = (struct dirent *)
2958 ((char *)dp + dp->d_reclen);
2959 } else {
2960 error = EIO;
2961 break;
2962 }
2963 }
2964 if (dp >= edp)
2965 error = uiomove(dirbuf, readcnt, &auio);
2966 }
2967 FREE(dirbuf, M_TEMP);
2968 }
2969 VOP_UNLOCK(vp, 0, p);
2970 if (error)
2971 return (error);
2972 if (SCARG(uap, count) == auio.uio_resid) {
2973 if (union_dircheckp) {
2974 error = union_dircheckp(p, &vp, fp);
2975 if (error == -1)
2976 goto unionread;
2977 if (error)
2978 return (error);
2979 }
2980 if ((vp->v_flag & VROOT) &&
2981 (vp->v_mount->mnt_flag & MNT_UNION)) {
2982 struct vnode *tvp = vp;
2983 vp = vp->v_mount->mnt_vnodecovered;
2984 VREF(vp);
2985 fp->f_data = (caddr_t) vp;
2986 fp->f_offset = 0;
2987 vrele(tvp);
2988 goto unionread;
2989 }
2990 }
2991 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2992 sizeof(long));
2993 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
2994 return (error);
2995 }
2996 #endif /* COMPAT_43 */
2997
2998 /*
2999 * Read a block of directory entries in a file system independent format.
3000 */
3001 #ifndef _SYS_SYSPROTO_H_
3002 struct getdirentries_args {
3003 int fd;
3004 char *buf;
3005 u_int count;
3006 long *basep;
3007 };
3008 #endif
3009 int
3010 getdirentries(p, uap)
3011 struct proc *p;
3012 register struct getdirentries_args /* {
3013 syscallarg(int) fd;
3014 syscallarg(char *) buf;
3015 syscallarg(u_int) count;
3016 syscallarg(long *) basep;
3017 } */ *uap;
3018 {
3019 struct vnode *vp;
3020 struct file *fp;
3021 struct uio auio;
3022 struct iovec aiov;
3023 long loff;
3024 int error, eofflag;
3025
3026 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
3027 return (error);
3028 if ((fp->f_flag & FREAD) == 0)
3029 return (EBADF);
3030 vp = (struct vnode *)fp->f_data;
3031 unionread:
3032 if (vp->v_type != VDIR)
3033 return (EINVAL);
3034 aiov.iov_base = SCARG(uap, buf);
3035 aiov.iov_len = SCARG(uap, count);
3036 auio.uio_iov = &aiov;
3037 auio.uio_iovcnt = 1;
3038 auio.uio_rw = UIO_READ;
3039 auio.uio_segflg = UIO_USERSPACE;
3040 auio.uio_procp = p;
3041 auio.uio_resid = SCARG(uap, count);
3042 /* vn_lock(vp, LK_SHARED | LK_RETRY, p); */
3043 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
3044 loff = auio.uio_offset = fp->f_offset;
3045 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
3046 fp->f_offset = auio.uio_offset;
3047 VOP_UNLOCK(vp, 0, p);
3048 if (error)
3049 return (error);
3050 if (SCARG(uap, count) == auio.uio_resid) {
3051 if (union_dircheckp) {
3052 error = union_dircheckp(p, &vp, fp);
3053 if (error == -1)
3054 goto unionread;
3055 if (error)
3056 return (error);
3057 }
3058 if ((vp->v_flag & VROOT) &&
3059 (vp->v_mount->mnt_flag & MNT_UNION)) {
3060 struct vnode *tvp = vp;
3061 vp = vp->v_mount->mnt_vnodecovered;
3062 VREF(vp);
3063 fp->f_data = (caddr_t) vp;
3064 fp->f_offset = 0;
3065 vrele(tvp);
3066 goto unionread;
3067 }
3068 }
3069 if (SCARG(uap, basep) != NULL) {
3070 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
3071 sizeof(long));
3072 }
3073 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
3074 return (error);
3075 }
3076 #ifndef _SYS_SYSPROTO_H_
3077 struct getdents_args {
3078 int fd;
3079 char *buf;
3080 size_t count;
3081 };
3082 #endif
3083 int
3084 getdents(p, uap)
3085 struct proc *p;
3086 register struct getdents_args /* {
3087 syscallarg(int) fd;
3088 syscallarg(char *) buf;
3089 syscallarg(u_int) count;
3090 } */ *uap;
3091 {
3092 struct getdirentries_args ap;
3093 ap.fd = uap->fd;
3094 ap.buf = uap->buf;
3095 ap.count = uap->count;
3096 ap.basep = NULL;
3097 return getdirentries(p, &ap);
3098 }
3099
3100 /*
3101 * Set the mode mask for creation of filesystem nodes.
3102 *
3103 * MP SAFE
3104 */
3105 #ifndef _SYS_SYSPROTO_H_
3106 struct umask_args {
3107 int newmask;
3108 };
3109 #endif
3110 int
3111 umask(p, uap)
3112 struct proc *p;
3113 struct umask_args /* {
3114 syscallarg(int) newmask;
3115 } */ *uap;
3116 {
3117 register struct filedesc *fdp;
3118
3119 fdp = p->p_fd;
3120 p->p_retval[0] = fdp->fd_cmask;
3121 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
3122 return (0);
3123 }
3124
3125 /*
3126 * Void all references to file by ripping underlying filesystem
3127 * away from vnode.
3128 */
3129 #ifndef _SYS_SYSPROTO_H_
3130 struct revoke_args {
3131 char *path;
3132 };
3133 #endif
3134 /* ARGSUSED */
3135 int
3136 revoke(p, uap)
3137 struct proc *p;
3138 register struct revoke_args /* {
3139 syscallarg(char *) path;
3140 } */ *uap;
3141 {
3142 register struct vnode *vp;
3143 struct vattr vattr;
3144 int error;
3145 struct nameidata nd;
3146
3147 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
3148 if ((error = namei(&nd)) != 0)
3149 return (error);
3150 vp = nd.ni_vp;
3151 NDFREE(&nd, NDF_ONLY_PNBUF);
3152 if (vp->v_type != VCHR && vp->v_type != VBLK) {
3153 error = EINVAL;
3154 goto out;
3155 }
3156 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
3157 goto out;
3158 if (p->p_ucred->cr_uid != vattr.va_uid &&
3159 (error = suser_xxx(0, p, PRISON_ROOT)))
3160 goto out;
3161 if (vcount(vp) > 1)
3162 VOP_REVOKE(vp, REVOKEALL);
3163 out:
3164 vrele(vp);
3165 return (error);
3166 }
3167
3168 /*
3169 * Convert a user file descriptor to a kernel file entry.
3170 */
3171 int
3172 getvnode(fdp, fd, fpp)
3173 struct filedesc *fdp;
3174 int fd;
3175 struct file **fpp;
3176 {
3177 struct file *fp;
3178
3179 if ((u_int)fd >= fdp->fd_nfiles ||
3180 (fp = fdp->fd_ofiles[fd]) == NULL)
3181 return (EBADF);
3182 if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO)
3183 return (EINVAL);
3184 *fpp = fp;
3185 return (0);
3186 }
3187 /*
3188 * Get (NFS) file handle
3189 */
3190 #ifndef _SYS_SYSPROTO_H_
3191 struct getfh_args {
3192 char *fname;
3193 fhandle_t *fhp;
3194 };
3195 #endif
3196 int
3197 getfh(p, uap)
3198 struct proc *p;
3199 register struct getfh_args *uap;
3200 {
3201 struct nameidata nd;
3202 fhandle_t fh;
3203 register struct vnode *vp;
3204 int error;
3205
3206 /*
3207 * Must be super user
3208 */
3209 error = suser(p);
3210 if (error)
3211 return (error);
3212 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
3213 error = namei(&nd);
3214 if (error)
3215 return (error);
3216 NDFREE(&nd, NDF_ONLY_PNBUF);
3217 vp = nd.ni_vp;
3218 bzero(&fh, sizeof(fh));
3219 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
3220 error = VFS_VPTOFH(vp, &fh.fh_fid);
3221 vput(vp);
3222 if (error)
3223 return (error);
3224 error = copyout(&fh, uap->fhp, sizeof (fh));
3225 return (error);
3226 }
3227
3228 /*
3229 * syscall for the rpc.lockd to use to translate a NFS file handle into
3230 * an open descriptor.
3231 *
3232 * warning: do not remove the suser() call or this becomes one giant
3233 * security hole.
3234 */
3235 #ifndef _SYS_SYSPROTO_H_
3236 struct fhopen_args {
3237 const struct fhandle *u_fhp;
3238 int flags;
3239 };
3240 #endif
3241 int
3242 fhopen(p, uap)
3243 struct proc *p;
3244 struct fhopen_args /* {
3245 syscallarg(const struct fhandle *) u_fhp;
3246 syscallarg(int) flags;
3247 } */ *uap;
3248 {
3249 struct mount *mp;
3250 struct vnode *vp;
3251 struct fhandle fhp;
3252 struct vattr vat;
3253 struct vattr *vap = &vat;
3254 struct flock lf;
3255 struct file *fp;
3256 register struct filedesc *fdp = p->p_fd;
3257 int fmode, mode, error, type;
3258 struct file *nfp;
3259 int indx;
3260
3261 /*
3262 * Must be super user
3263 */
3264 error = suser(p);
3265 if (error)
3266 return (error);
3267
3268 fmode = FFLAGS(SCARG(uap, flags));
3269 /* why not allow a non-read/write open for our lockd? */
3270 if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
3271 return (EINVAL);
3272 error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp));
3273 if (error)
3274 return(error);
3275 /* find the mount point */
3276 mp = vfs_getvfs(&fhp.fh_fsid);
3277 if (mp == NULL)
3278 return (ESTALE);
3279 /* now give me my vnode, it gets returned to me locked */
3280 error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
3281 if (error)
3282 return (error);
3283 /*
3284 * from now on we have to make sure not
3285 * to forget about the vnode
3286 * any error that causes an abort must vput(vp)
3287 * just set error = err and 'goto bad;'.
3288 */
3289
3290 /*
3291 * from vn_open
3292 */
3293 if (vp->v_type == VLNK) {
3294 error = EMLINK;
3295 goto bad;
3296 }
3297 if (vp->v_type == VSOCK) {
3298 error = EOPNOTSUPP;
3299 goto bad;
3300 }
3301 mode = 0;
3302 if (fmode & (FWRITE | O_TRUNC)) {
3303 if (vp->v_type == VDIR) {
3304 error = EISDIR;
3305 goto bad;
3306 }
3307 error = vn_writechk(vp);
3308 if (error)
3309 goto bad;
3310 mode |= VWRITE;
3311 }
3312 if (fmode & FREAD)
3313 mode |= VREAD;
3314 if (mode) {
3315 error = VOP_ACCESS(vp, mode, p->p_ucred, p);
3316 if (error)
3317 goto bad;
3318 }
3319 if (fmode & O_TRUNC) {
3320 VOP_UNLOCK(vp, 0, p); /* XXX */
3321 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
3322 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */
3323 VATTR_NULL(vap);
3324 vap->va_size = 0;
3325 error = VOP_SETATTR(vp, vap, p->p_ucred, p);
3326 if (error)
3327 goto bad;
3328 }
3329 error = VOP_OPEN(vp, fmode, p->p_ucred, p);
3330 if (error)
3331 goto bad;
3332 /*
3333 * Make sure that a VM object is created for VMIO support.
3334 */
3335 if (vn_canvmio(vp) == TRUE) {
3336 if ((error = vfs_object_create(vp, p, p->p_ucred)) != 0)
3337 goto bad;
3338 }
3339 if (fmode & FWRITE)
3340 vp->v_writecount++;
3341
3342 /*
3343 * end of vn_open code
3344 */
3345
3346 if ((error = falloc(p, &nfp, &indx)) != 0) {
3347 if (fmode & FWRITE)
3348 vp->v_writecount--;
3349 goto bad;
3350 }
3351 fp = nfp;
3352
3353 /*
3354 * hold an extra reference to avoid having fp ripped out
3355 * from under us while we block in the lock op.
3356 */
3357 fhold(fp);
3358 nfp->f_data = (caddr_t)vp;
3359 nfp->f_flag = fmode & FMASK;
3360 nfp->f_ops = &vnops;
3361 nfp->f_type = DTYPE_VNODE;
3362 if (fmode & (O_EXLOCK | O_SHLOCK)) {
3363 lf.l_whence = SEEK_SET;
3364 lf.l_start = 0;
3365 lf.l_len = 0;
3366 if (fmode & O_EXLOCK)
3367 lf.l_type = F_WRLCK;
3368 else
3369 lf.l_type = F_RDLCK;
3370 type = F_FLOCK;
3371 if ((fmode & FNONBLOCK) == 0)
3372 type |= F_WAIT;
3373 VOP_UNLOCK(vp, 0, p);
3374 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
3375 /*
3376 * lock request failed. Normally close the descriptor
3377 * but handle the case where someone might have dup()d
3378 * or close()d it when we weren't looking.
3379 */
3380 if (fdp->fd_ofiles[indx] == fp) {
3381 fdp->fd_ofiles[indx] = NULL;
3382 fdrop(fp, p);
3383 }
3384
3385 /*
3386 * release our private reference.
3387 */
3388 fdrop(fp, p);
3389 return (error);
3390 }
3391 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
3392 fp->f_flag |= FHASLOCK;
3393 }
3394 if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0))
3395 vfs_object_create(vp, p, p->p_ucred);
3396
3397 VOP_UNLOCK(vp, 0, p);
3398 fdrop(fp, p);
3399 p->p_retval[0] = indx;
3400 return (0);
3401
3402 bad:
3403 vput(vp);
3404 return (error);
3405 }
3406
3407 #ifndef _SYS_SYSPROTO_H_
3408 struct fhstat_args {
3409 struct fhandle *u_fhp;
3410 struct stat *sb;
3411 };
3412 #endif
3413 int
3414 fhstat(p, uap)
3415 struct proc *p;
3416 register struct fhstat_args /* {
3417 syscallarg(struct fhandle *) u_fhp;
3418 syscallarg(struct stat *) sb;
3419 } */ *uap;
3420 {
3421 struct stat sb;
3422 fhandle_t fh;
3423 struct mount *mp;
3424 struct vnode *vp;
3425 int error;
3426
3427 /*
3428 * Must be super user
3429 */
3430 error = suser(p);
3431 if (error)
3432 return (error);
3433
3434 error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t));
3435 if (error)
3436 return (error);
3437
3438 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3439 return (ESTALE);
3440 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3441 return (error);
3442 error = vn_stat(vp, &sb, p);
3443 vput(vp);
3444 if (error)
3445 return (error);
3446 error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
3447 return (error);
3448 }
3449
3450 #ifndef _SYS_SYSPROTO_H_
3451 struct fhstatfs_args {
3452 struct fhandle *u_fhp;
3453 struct statfs *buf;
3454 };
3455 #endif
3456 int
3457 fhstatfs(p, uap)
3458 struct proc *p;
3459 struct fhstatfs_args /* {
3460 syscallarg(struct fhandle) *u_fhp;
3461 syscallarg(struct statfs) *buf;
3462 } */ *uap;
3463 {
3464 struct statfs *sp;
3465 struct mount *mp;
3466 struct vnode *vp;
3467 struct statfs sb;
3468 fhandle_t fh;
3469 int error;
3470
3471 /*
3472 * Must be super user
3473 */
3474 if ((error = suser(p)))
3475 return (error);
3476
3477 if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0)
3478 return (error);
3479
3480 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3481 return (ESTALE);
3482 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3483 return (error);
3484 mp = vp->v_mount;
3485 sp = &mp->mnt_stat;
3486 vput(vp);
3487 if ((error = VFS_STATFS(mp, sp, p)) != 0)
3488 return (error);
3489 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
3490 if (suser_xxx(p->p_ucred, 0, 0)) {
3491 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
3492 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
3493 sp = &sb;
3494 }
3495 return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
3496 }
3497
3498 /*
3499 * Syscall to push extended attribute configuration information into the
3500 * VFS. Accepts a path, which it converts to a mountpoint, as well as
3501 * a command (int cmd), and attribute name and misc data. For now, the
3502 * attribute name is left in userspace for consumption by the VFS_op.
3503 * It will probably be changed to be copied into sysspace by the
3504 * syscall in the future, once issues with various consumers of the
3505 * attribute code have raised their hands.
3506 *
3507 * Currently this is used only by UFS Extended Attributes.
3508 */
3509 int
3510 extattrctl(p, uap)
3511 struct proc *p;
3512 struct extattrctl_args *uap;
3513 {
3514 struct nameidata nd;
3515 struct mount *mp;
3516 int error;
3517
3518 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
3519 if ((error = namei(&nd)) != 0)
3520 return (error);
3521 mp = nd.ni_vp->v_mount;
3522 NDFREE(&nd, 0);
3523 return (VFS_EXTATTRCTL(mp, SCARG(uap, cmd), SCARG(uap, attrname),
3524 SCARG(uap, arg), p));
3525 }
3526
3527 /*
3528 * Syscall to set a named extended attribute on a file or directory.
3529 * Accepts attribute name, and a uio structure pointing to the data to set.
3530 * The uio is consumed in the style of writev(). The real work happens
3531 * in VOP_SETEXTATTR().
3532 */
3533 int
3534 extattr_set_file(p, uap)
3535 struct proc *p;
3536 struct extattr_set_file_args *uap;
3537 {
3538 struct nameidata nd;
3539 struct uio auio;
3540 struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV];
3541 char attrname[EXTATTR_MAXNAMELEN];
3542 u_int iovlen, cnt;
3543 int error, i;
3544
3545 error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
3546 if (error)
3547 return (error);
3548 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
3549 SCARG(uap, path), p);
3550 if ((error = namei(&nd)) != 0)
3551 return(error);
3552 iovlen = uap->iovcnt * sizeof(struct iovec);
3553 if (uap->iovcnt > UIO_SMALLIOV) {
3554 if (uap->iovcnt > UIO_MAXIOV) {
3555 error = EINVAL;
3556 goto done;
3557 }
3558 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
3559 needfree = iov;
3560 } else
3561 iov = aiov;
3562 auio.uio_iov = iov;
3563 auio.uio_iovcnt = uap->iovcnt;
3564 auio.uio_rw = UIO_WRITE;
3565 auio.uio_segflg = UIO_USERSPACE;
3566 auio.uio_procp = p;
3567 auio.uio_offset = 0;
3568 if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
3569 goto done;
3570 auio.uio_resid = 0;
3571 for (i = 0; i < uap->iovcnt; i++) {
3572 if (iov->iov_len > INT_MAX - auio.uio_resid) {
3573 error = EINVAL;
3574 goto done;
3575 }
3576 auio.uio_resid += iov->iov_len;
3577 iov++;
3578 }
3579 cnt = auio.uio_resid;
3580 error = VOP_SETEXTATTR(nd.ni_vp, attrname, &auio, p->p_cred->pc_ucred,
3581 p);
3582 cnt -= auio.uio_resid;
3583 p->p_retval[0] = cnt;
3584 done:
3585 if (needfree)
3586 FREE(needfree, M_IOV);
3587 NDFREE(&nd, 0);
3588 return (error);
3589 }
3590
3591 /*
3592 * Syscall to get a named extended attribute on a file or directory.
3593 * Accepts attribute name, and a uio structure pointing to a buffer for the
3594 * data. The uio is consumed in the style of readv(). The real work
3595 * happens in VOP_GETEXTATTR();
3596 */
3597 int
3598 extattr_get_file(p, uap)
3599 struct proc *p;
3600 struct extattr_get_file_args *uap;
3601 {
3602 struct nameidata nd;
3603 struct uio auio;
3604 struct iovec *iov, *needfree, aiov[UIO_SMALLIOV];
3605 char attrname[EXTATTR_MAXNAMELEN];
3606 u_int iovlen, cnt;
3607 int error, i;
3608
3609 error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
3610 if (error)
3611 return (error);
3612 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
3613 SCARG(uap, path), p);
3614 if ((error = namei(&nd)) != 0)
3615 return (error);
3616 iovlen = uap->iovcnt * sizeof (struct iovec);
3617 if (uap->iovcnt > UIO_SMALLIOV) {
3618 if (uap->iovcnt > UIO_MAXIOV) {
3619 NDFREE(&nd, 0);
3620 return (EINVAL);
3621 }
3622 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
3623 needfree = iov;
3624 } else {
3625 iov = aiov;
3626 needfree = NULL;
3627 }
3628 auio.uio_iov = iov;
3629 auio.uio_iovcnt = uap->iovcnt;
3630 auio.uio_rw = UIO_READ;
3631 auio.uio_segflg = UIO_USERSPACE;
3632 auio.uio_procp = p;
3633 auio.uio_offset = 0;
3634 if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
3635 goto done;
3636 auio.uio_resid = 0;
3637 for (i = 0; i < uap->iovcnt; i++) {
3638 if (iov->iov_len > INT_MAX - auio.uio_resid) {
3639 error = EINVAL;
3640 goto done;
3641 }
3642 auio.uio_resid += iov->iov_len;
3643 iov++;
3644 }
3645 cnt = auio.uio_resid;
3646 error = VOP_GETEXTATTR(nd.ni_vp, attrname, &auio, p->p_cred->pc_ucred,
3647 p);
3648 cnt -= auio.uio_resid;
3649 p->p_retval[0] = cnt;
3650 done:
3651 if (needfree)
3652 FREE(needfree, M_IOV);
3653 NDFREE(&nd, 0);
3654 return(error);
3655 }
3656
3657 /*
3658 * Syscall to delete a named extended attribute from a file or directory.
3659 * Accepts attribute name. The real work happens in VOP_SETEXTATTR().
3660 */
3661 int
3662 extattr_delete_file(p, uap)
3663 struct proc *p;
3664 struct extattr_delete_file_args *uap;
3665 {
3666 struct nameidata nd;
3667 char attrname[EXTATTR_MAXNAMELEN];
3668 int error;
3669
3670 error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
3671 if (error)
3672 return(error);
3673 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
3674 SCARG(uap, path), p);
3675 if ((error = namei(&nd)) != 0)
3676 return(error);
3677 error = VOP_SETEXTATTR(nd.ni_vp, attrname, NULL, p->p_cred->pc_ucred,
3678 p);
3679 NDFREE(&nd, 0);
3680 return(error);
3681 }
Cache object: 3e1f229b2f6dbef484ecf50b0fac407e
|