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