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