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: releng/5.0/sys/kern/vfs_syscalls.c 108822 2003-01-06 21:20:54Z nectar $
40 */
41
42 /* For 4.3 integer FS ID compatibility */
43 #include "opt_compat.h"
44 #include "opt_mac.h"
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/bio.h>
49 #include <sys/buf.h>
50 #include <sys/sysent.h>
51 #include <sys/mac.h>
52 #include <sys/malloc.h>
53 #include <sys/mount.h>
54 #include <sys/mutex.h>
55 #include <sys/sysproto.h>
56 #include <sys/namei.h>
57 #include <sys/filedesc.h>
58 #include <sys/kernel.h>
59 #include <sys/fcntl.h>
60 #include <sys/file.h>
61 #include <sys/linker.h>
62 #include <sys/stat.h>
63 #include <sys/sx.h>
64 #include <sys/unistd.h>
65 #include <sys/vnode.h>
66 #include <sys/proc.h>
67 #include <sys/dirent.h>
68 #include <sys/extattr.h>
69 #include <sys/jail.h>
70 #include <sys/syscallsubr.h>
71 #include <sys/sysctl.h>
72
73 #include <machine/limits.h>
74 #include <machine/stdarg.h>
75
76 #include <vm/vm.h>
77 #include <vm/vm_object.h>
78 #include <vm/vm_page.h>
79 #include <vm/uma.h>
80
81 static int change_dir(struct nameidata *ndp, struct thread *td);
82 static int chroot_refuse_vdir_fds(struct filedesc *fdp);
83 static int getutimes(const struct timeval *, enum uio_seg, struct timespec *);
84 static int setfown(struct thread *td, struct vnode *, uid_t, gid_t);
85 static int setfmode(struct thread *td, struct vnode *, int);
86 static int setfflags(struct thread *td, struct vnode *, int);
87 static int setutimes(struct thread *td, struct vnode *,
88 const struct timespec *, int, int);
89 static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
90 struct thread *td);
91
92 int (*union_dircheckp)(struct thread *td, struct vnode **, struct file *);
93 int (*softdep_fsync_hook)(struct vnode *);
94
95 /*
96 * The module initialization routine for POSIX asynchronous I/O will
97 * set this to the version of AIO that it implements. (Zero means
98 * that it is not implemented.) This value is used here by pathconf()
99 * and in kern_descrip.c by fpathconf().
100 */
101 int async_io_version;
102
103 /*
104 * Sync each mounted filesystem.
105 */
106 #ifndef _SYS_SYSPROTO_H_
107 struct sync_args {
108 int dummy;
109 };
110 #endif
111
112 #ifdef DEBUG
113 static int syncprt = 0;
114 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
115 #endif
116
117 /* ARGSUSED */
118 int
119 sync(td, uap)
120 struct thread *td;
121 struct sync_args *uap;
122 {
123 struct mount *mp, *nmp;
124 int asyncflag;
125
126 mtx_lock(&mountlist_mtx);
127 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
128 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
129 nmp = TAILQ_NEXT(mp, mnt_list);
130 continue;
131 }
132 if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
133 vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
134 asyncflag = mp->mnt_flag & MNT_ASYNC;
135 mp->mnt_flag &= ~MNT_ASYNC;
136 vfs_msync(mp, MNT_NOWAIT);
137 VFS_SYNC(mp, MNT_NOWAIT,
138 ((td != NULL) ? td->td_ucred : NOCRED), td);
139 mp->mnt_flag |= asyncflag;
140 vn_finished_write(mp);
141 }
142 mtx_lock(&mountlist_mtx);
143 nmp = TAILQ_NEXT(mp, mnt_list);
144 vfs_unbusy(mp, td);
145 }
146 mtx_unlock(&mountlist_mtx);
147 #if 0
148 /*
149 * XXX don't call vfs_bufstats() yet because that routine
150 * was not imported in the Lite2 merge.
151 */
152 #ifdef DIAGNOSTIC
153 if (syncprt)
154 vfs_bufstats();
155 #endif /* DIAGNOSTIC */
156 #endif
157 return (0);
158 }
159
160 /* XXX PRISON: could be per prison flag */
161 static int prison_quotas;
162 #if 0
163 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
164 #endif
165
166 /*
167 * Change filesystem quotas.
168 */
169 #ifndef _SYS_SYSPROTO_H_
170 struct quotactl_args {
171 char *path;
172 int cmd;
173 int uid;
174 caddr_t arg;
175 };
176 #endif
177 /* ARGSUSED */
178 int
179 quotactl(td, uap)
180 struct thread *td;
181 register struct quotactl_args /* {
182 char *path;
183 int cmd;
184 int uid;
185 caddr_t arg;
186 } */ *uap;
187 {
188 struct mount *mp;
189 int error;
190 struct nameidata nd;
191
192 if (jailed(td->td_ucred) && !prison_quotas)
193 return (EPERM);
194 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
195 if ((error = namei(&nd)) != 0)
196 return (error);
197 NDFREE(&nd, NDF_ONLY_PNBUF);
198 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
199 vrele(nd.ni_vp);
200 if (error)
201 return (error);
202 error = VFS_QUOTACTL(mp, uap->cmd, uap->uid,
203 uap->arg, td);
204 vn_finished_write(mp);
205 return (error);
206 }
207
208 /*
209 * Get filesystem statistics.
210 */
211 #ifndef _SYS_SYSPROTO_H_
212 struct statfs_args {
213 char *path;
214 struct statfs *buf;
215 };
216 #endif
217 /* ARGSUSED */
218 int
219 statfs(td, uap)
220 struct thread *td;
221 register struct statfs_args /* {
222 char *path;
223 struct statfs *buf;
224 } */ *uap;
225 {
226 register struct mount *mp;
227 register struct statfs *sp;
228 int error;
229 struct nameidata nd;
230 struct statfs sb;
231
232 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
233 if ((error = namei(&nd)) != 0)
234 return (error);
235 mp = nd.ni_vp->v_mount;
236 sp = &mp->mnt_stat;
237 NDFREE(&nd, NDF_ONLY_PNBUF);
238 vrele(nd.ni_vp);
239 #ifdef MAC
240 error = mac_check_mount_stat(td->td_ucred, mp);
241 if (error)
242 return (error);
243 #endif
244 error = VFS_STATFS(mp, sp, td);
245 if (error)
246 return (error);
247 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
248 if (suser(td)) {
249 bcopy(sp, &sb, sizeof(sb));
250 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
251 sp = &sb;
252 }
253 return (copyout(sp, uap->buf, sizeof(*sp)));
254 }
255
256 /*
257 * Get filesystem statistics.
258 */
259 #ifndef _SYS_SYSPROTO_H_
260 struct fstatfs_args {
261 int fd;
262 struct statfs *buf;
263 };
264 #endif
265 /* ARGSUSED */
266 int
267 fstatfs(td, uap)
268 struct thread *td;
269 register struct fstatfs_args /* {
270 int fd;
271 struct statfs *buf;
272 } */ *uap;
273 {
274 struct file *fp;
275 struct mount *mp;
276 register struct statfs *sp;
277 int error;
278 struct statfs sb;
279
280 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
281 return (error);
282 mp = ((struct vnode *)fp->f_data)->v_mount;
283 fdrop(fp, td);
284 if (mp == NULL)
285 return (EBADF);
286 #ifdef MAC
287 error = mac_check_mount_stat(td->td_ucred, mp);
288 if (error)
289 return (error);
290 #endif
291 sp = &mp->mnt_stat;
292 error = VFS_STATFS(mp, sp, td);
293 if (error)
294 return (error);
295 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
296 if (suser(td)) {
297 bcopy(sp, &sb, sizeof(sb));
298 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
299 sp = &sb;
300 }
301 return (copyout(sp, uap->buf, sizeof(*sp)));
302 }
303
304 /*
305 * Get statistics on all filesystems.
306 */
307 #ifndef _SYS_SYSPROTO_H_
308 struct getfsstat_args {
309 struct statfs *buf;
310 long bufsize;
311 int flags;
312 };
313 #endif
314 int
315 getfsstat(td, uap)
316 struct thread *td;
317 register struct getfsstat_args /* {
318 struct statfs *buf;
319 long bufsize;
320 int flags;
321 } */ *uap;
322 {
323 register struct mount *mp, *nmp;
324 register struct statfs *sp;
325 caddr_t sfsp;
326 long count, maxcount, error;
327
328 maxcount = uap->bufsize / sizeof(struct statfs);
329 sfsp = (caddr_t)uap->buf;
330 count = 0;
331 mtx_lock(&mountlist_mtx);
332 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
333 #ifdef MAC
334 if (mac_check_mount_stat(td->td_ucred, mp) != 0) {
335 nmp = TAILQ_NEXT(mp, mnt_list);
336 continue;
337 }
338 #endif
339 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
340 nmp = TAILQ_NEXT(mp, mnt_list);
341 continue;
342 }
343 if (sfsp && count < maxcount) {
344 sp = &mp->mnt_stat;
345 /*
346 * If MNT_NOWAIT or MNT_LAZY is specified, do not
347 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
348 * overrides MNT_WAIT.
349 */
350 if (((uap->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
351 (uap->flags & MNT_WAIT)) &&
352 (error = VFS_STATFS(mp, sp, td))) {
353 mtx_lock(&mountlist_mtx);
354 nmp = TAILQ_NEXT(mp, mnt_list);
355 vfs_unbusy(mp, td);
356 continue;
357 }
358 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
359 error = copyout(sp, sfsp, sizeof(*sp));
360 if (error) {
361 vfs_unbusy(mp, td);
362 return (error);
363 }
364 sfsp += sizeof(*sp);
365 }
366 count++;
367 mtx_lock(&mountlist_mtx);
368 nmp = TAILQ_NEXT(mp, mnt_list);
369 vfs_unbusy(mp, td);
370 }
371 mtx_unlock(&mountlist_mtx);
372 if (sfsp && count > maxcount)
373 td->td_retval[0] = maxcount;
374 else
375 td->td_retval[0] = count;
376 return (0);
377 }
378
379 /*
380 * Change current working directory to a given file descriptor.
381 */
382 #ifndef _SYS_SYSPROTO_H_
383 struct fchdir_args {
384 int fd;
385 };
386 #endif
387 /* ARGSUSED */
388 int
389 fchdir(td, uap)
390 struct thread *td;
391 struct fchdir_args /* {
392 int fd;
393 } */ *uap;
394 {
395 register struct filedesc *fdp = td->td_proc->p_fd;
396 struct vnode *vp, *tdp, *vpold;
397 struct mount *mp;
398 struct file *fp;
399 int error;
400
401 if ((error = getvnode(fdp, uap->fd, &fp)) != 0)
402 return (error);
403 vp = (struct vnode *)fp->f_data;
404 VREF(vp);
405 fdrop(fp, td);
406 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
407 if (vp->v_type != VDIR)
408 error = ENOTDIR;
409 #ifdef MAC
410 else if ((error = mac_check_vnode_chdir(td->td_ucred, vp)) != 0) {
411 }
412 #endif
413 else
414 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
415 while (!error && (mp = vp->v_mountedhere) != NULL) {
416 if (vfs_busy(mp, 0, 0, td))
417 continue;
418 error = VFS_ROOT(mp, &tdp);
419 vfs_unbusy(mp, td);
420 if (error)
421 break;
422 vput(vp);
423 vp = tdp;
424 }
425 if (error) {
426 vput(vp);
427 return (error);
428 }
429 VOP_UNLOCK(vp, 0, td);
430 FILEDESC_LOCK(fdp);
431 vpold = fdp->fd_cdir;
432 fdp->fd_cdir = vp;
433 FILEDESC_UNLOCK(fdp);
434 vrele(vpold);
435 return (0);
436 }
437
438 /*
439 * Change current working directory (``.'').
440 */
441 #ifndef _SYS_SYSPROTO_H_
442 struct chdir_args {
443 char *path;
444 };
445 #endif
446 /* ARGSUSED */
447 int
448 chdir(td, uap)
449 struct thread *td;
450 struct chdir_args /* {
451 char *path;
452 } */ *uap;
453 {
454
455 return (kern_chdir(td, uap->path, UIO_USERSPACE));
456 }
457
458 int
459 kern_chdir(struct thread *td, char *path, enum uio_seg pathseg)
460 {
461 register struct filedesc *fdp = td->td_proc->p_fd;
462 int error;
463 struct nameidata nd;
464 struct vnode *vp;
465
466 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, pathseg, path, td);
467 if ((error = change_dir(&nd, td)) != 0)
468 return (error);
469 NDFREE(&nd, NDF_ONLY_PNBUF);
470 FILEDESC_LOCK(fdp);
471 vp = fdp->fd_cdir;
472 fdp->fd_cdir = nd.ni_vp;
473 FILEDESC_UNLOCK(fdp);
474 vrele(vp);
475 return (0);
476 }
477
478 /*
479 * Helper function for raised chroot(2) security function: Refuse if
480 * any filedescriptors are open directories.
481 */
482 static int
483 chroot_refuse_vdir_fds(fdp)
484 struct filedesc *fdp;
485 {
486 struct vnode *vp;
487 struct file *fp;
488 int fd;
489
490 FILEDESC_LOCK_ASSERT(fdp, MA_OWNED);
491 for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
492 fp = fget_locked(fdp, fd);
493 if (fp == NULL)
494 continue;
495 if (fp->f_type == DTYPE_VNODE) {
496 vp = (struct vnode *)fp->f_data;
497 if (vp->v_type == VDIR)
498 return (EPERM);
499 }
500 }
501 return (0);
502 }
503
504 /*
505 * This sysctl determines if we will allow a process to chroot(2) if it
506 * has a directory open:
507 * 0: disallowed for all processes.
508 * 1: allowed for processes that were not already chroot(2)'ed.
509 * 2: allowed for all processes.
510 */
511
512 static int chroot_allow_open_directories = 1;
513
514 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
515 &chroot_allow_open_directories, 0, "");
516
517 /*
518 * Change notion of root (``/'') directory.
519 */
520 #ifndef _SYS_SYSPROTO_H_
521 struct chroot_args {
522 char *path;
523 };
524 #endif
525 /* ARGSUSED */
526 int
527 chroot(td, uap)
528 struct thread *td;
529 struct chroot_args /* {
530 char *path;
531 } */ *uap;
532 {
533 register struct filedesc *fdp = td->td_proc->p_fd;
534 int error;
535 struct nameidata nd;
536 struct vnode *vp;
537
538 error = suser_cred(td->td_ucred, PRISON_ROOT);
539 if (error)
540 return (error);
541 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
542 uap->path, td);
543 mtx_lock(&Giant);
544 if ((error = change_dir(&nd, td)) != 0)
545 goto error;
546 #ifdef MAC
547 if ((error = mac_check_vnode_chroot(td->td_ucred, nd.ni_vp)))
548 goto error;
549 #endif
550 FILEDESC_LOCK(fdp);
551 if (chroot_allow_open_directories == 0 ||
552 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
553 error = chroot_refuse_vdir_fds(fdp);
554 if (error)
555 goto error_unlock;
556 }
557 vp = fdp->fd_rdir;
558 fdp->fd_rdir = nd.ni_vp;
559 if (!fdp->fd_jdir) {
560 fdp->fd_jdir = nd.ni_vp;
561 VREF(fdp->fd_jdir);
562 }
563 FILEDESC_UNLOCK(fdp);
564 NDFREE(&nd, NDF_ONLY_PNBUF);
565 vrele(vp);
566 mtx_unlock(&Giant);
567 return (0);
568 error_unlock:
569 FILEDESC_UNLOCK(fdp);
570 error:
571 mtx_unlock(&Giant);
572 NDFREE(&nd, 0);
573 return (error);
574 }
575
576 /*
577 * Common routine for chroot and chdir.
578 */
579 static int
580 change_dir(ndp, td)
581 register struct nameidata *ndp;
582 struct thread *td;
583 {
584 struct vnode *vp;
585 int error;
586
587 error = namei(ndp);
588 if (error)
589 return (error);
590 vp = ndp->ni_vp;
591 if (vp->v_type != VDIR)
592 error = ENOTDIR;
593 #ifdef MAC
594 else if ((error = mac_check_vnode_chdir(td->td_ucred, vp)) != 0) {
595 }
596 #endif
597 else
598 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
599 if (error)
600 vput(vp);
601 else
602 VOP_UNLOCK(vp, 0, td);
603 return (error);
604 }
605
606 /*
607 * Check permissions, allocate an open file structure,
608 * and call the device open routine if any.
609 */
610 #ifndef _SYS_SYSPROTO_H_
611 struct open_args {
612 char *path;
613 int flags;
614 int mode;
615 };
616 #endif
617 int
618 open(td, uap)
619 struct thread *td;
620 register struct open_args /* {
621 char *path;
622 int flags;
623 int mode;
624 } */ *uap;
625 {
626
627 return (kern_open(td, uap->path, UIO_USERSPACE, uap->flags, uap->mode));
628 }
629
630 int
631 kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags,
632 int mode)
633 {
634 struct proc *p = td->td_proc;
635 struct filedesc *fdp = p->p_fd;
636 struct file *fp;
637 struct vnode *vp;
638 struct vattr vat;
639 struct mount *mp;
640 int cmode, oflags;
641 struct file *nfp;
642 int type, indx, error;
643 struct flock lf;
644 struct nameidata nd;
645
646 if ((flags & O_ACCMODE) == O_ACCMODE)
647 return (EINVAL);
648 oflags = flags;
649 flags = FFLAGS(flags);
650 error = falloc(td, &nfp, &indx);
651 if (error)
652 return (error);
653 fp = nfp;
654 FILEDESC_LOCK(fdp);
655 cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
656 FILEDESC_UNLOCK(fdp);
657 NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
658 td->td_dupfd = -indx - 1; /* XXX check for fdopen */
659 /*
660 * Bump the ref count to prevent another process from closing
661 * the descriptor while we are blocked in vn_open()
662 */
663 fhold(fp);
664 error = vn_open(&nd, &flags, cmode);
665 if (error) {
666 /*
667 * release our own reference
668 */
669 fdrop(fp, td);
670
671 /*
672 * handle special fdopen() case. bleh. dupfdopen() is
673 * responsible for dropping the old contents of ofiles[indx]
674 * if it succeeds.
675 */
676 if ((error == ENODEV || error == ENXIO) &&
677 td->td_dupfd >= 0 && /* XXX from fdopen */
678 (error =
679 dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) {
680 td->td_retval[0] = indx;
681 return (0);
682 }
683 /*
684 * Clean up the descriptor, but only if another thread hadn't
685 * replaced or closed it.
686 */
687 FILEDESC_LOCK(fdp);
688 if (fdp->fd_ofiles[indx] == fp) {
689 fdp->fd_ofiles[indx] = NULL;
690 FILEDESC_UNLOCK(fdp);
691 fdrop(fp, td);
692 } else
693 FILEDESC_UNLOCK(fdp);
694
695 if (error == ERESTART)
696 error = EINTR;
697 return (error);
698 }
699 td->td_dupfd = 0;
700 NDFREE(&nd, NDF_ONLY_PNBUF);
701 vp = nd.ni_vp;
702
703 /*
704 * There should be 2 references on the file, one from the descriptor
705 * table, and one for us.
706 *
707 * Handle the case where someone closed the file (via its file
708 * descriptor) while we were blocked. The end result should look
709 * like opening the file succeeded but it was immediately closed.
710 */
711 FILEDESC_LOCK(fdp);
712 FILE_LOCK(fp);
713 if (fp->f_count == 1) {
714 KASSERT(fdp->fd_ofiles[indx] != fp,
715 ("Open file descriptor lost all refs"));
716 FILEDESC_UNLOCK(fdp);
717 FILE_UNLOCK(fp);
718 VOP_UNLOCK(vp, 0, td);
719 vn_close(vp, flags & FMASK, fp->f_cred, td);
720 fdrop(fp, td);
721 td->td_retval[0] = indx;
722 return 0;
723 }
724
725 /* assert that vn_open created a backing object if one is needed */
726 KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0,
727 ("open: vmio vnode has no backing object after vn_open"));
728
729 fp->f_data = vp;
730 fp->f_flag = flags & FMASK;
731 fp->f_ops = &vnops;
732 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
733 FILEDESC_UNLOCK(fdp);
734 FILE_UNLOCK(fp);
735 VOP_UNLOCK(vp, 0, td);
736 if (flags & (O_EXLOCK | O_SHLOCK)) {
737 lf.l_whence = SEEK_SET;
738 lf.l_start = 0;
739 lf.l_len = 0;
740 if (flags & O_EXLOCK)
741 lf.l_type = F_WRLCK;
742 else
743 lf.l_type = F_RDLCK;
744 type = F_FLOCK;
745 if ((flags & FNONBLOCK) == 0)
746 type |= F_WAIT;
747 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
748 type)) != 0)
749 goto bad;
750 fp->f_flag |= FHASLOCK;
751 }
752 if (flags & O_TRUNC) {
753 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
754 goto bad;
755 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
756 VATTR_NULL(&vat);
757 vat.va_size = 0;
758 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
759 #ifdef MAC
760 error = mac_check_vnode_write(td->td_ucred, fp->f_cred, vp);
761 if (error == 0)
762 #endif
763 error = VOP_SETATTR(vp, &vat, td->td_ucred, td);
764 VOP_UNLOCK(vp, 0, td);
765 vn_finished_write(mp);
766 if (error)
767 goto bad;
768 }
769 /*
770 * Release our private reference, leaving the one associated with
771 * the descriptor table intact.
772 */
773 fdrop(fp, td);
774 td->td_retval[0] = indx;
775 return (0);
776 bad:
777 FILEDESC_LOCK(fdp);
778 if (fdp->fd_ofiles[indx] == fp) {
779 fdp->fd_ofiles[indx] = NULL;
780 FILEDESC_UNLOCK(fdp);
781 fdrop(fp, td);
782 } else
783 FILEDESC_UNLOCK(fdp);
784 fdrop(fp, td);
785 return (error);
786 }
787
788 #ifdef COMPAT_43
789 /*
790 * Create a file.
791 */
792 #ifndef _SYS_SYSPROTO_H_
793 struct ocreat_args {
794 char *path;
795 int mode;
796 };
797 #endif
798 int
799 ocreat(td, uap)
800 struct thread *td;
801 register struct ocreat_args /* {
802 char *path;
803 int mode;
804 } */ *uap;
805 {
806 struct open_args /* {
807 char *path;
808 int flags;
809 int mode;
810 } */ nuap;
811
812 nuap.path = uap->path;
813 nuap.mode = uap->mode;
814 nuap.flags = O_WRONLY | O_CREAT | O_TRUNC;
815 return (open(td, &nuap));
816 }
817 #endif /* COMPAT_43 */
818
819 /*
820 * Create a special file.
821 */
822 #ifndef _SYS_SYSPROTO_H_
823 struct mknod_args {
824 char *path;
825 int mode;
826 int dev;
827 };
828 #endif
829 /* ARGSUSED */
830 int
831 mknod(td, uap)
832 struct thread *td;
833 register struct mknod_args /* {
834 char *path;
835 int mode;
836 int dev;
837 } */ *uap;
838 {
839
840 return (kern_mknod(td, uap->path, UIO_USERSPACE, uap->mode, uap->dev));
841 }
842
843 int
844 kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode,
845 int dev)
846 {
847 struct vnode *vp;
848 struct mount *mp;
849 struct vattr vattr;
850 int error;
851 int whiteout = 0;
852 struct nameidata nd;
853
854 switch (mode & S_IFMT) {
855 case S_IFCHR:
856 case S_IFBLK:
857 error = suser(td);
858 break;
859 default:
860 error = suser_cred(td->td_ucred, PRISON_ROOT);
861 break;
862 }
863 if (error)
864 return (error);
865 restart:
866 bwillwrite();
867 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, pathseg, path, td);
868 if ((error = namei(&nd)) != 0)
869 return (error);
870 vp = nd.ni_vp;
871 if (vp != NULL) {
872 vrele(vp);
873 error = EEXIST;
874 } else {
875 VATTR_NULL(&vattr);
876 FILEDESC_LOCK(td->td_proc->p_fd);
877 vattr.va_mode = (mode & ALLPERMS) &
878 ~td->td_proc->p_fd->fd_cmask;
879 FILEDESC_UNLOCK(td->td_proc->p_fd);
880 vattr.va_rdev = dev;
881 whiteout = 0;
882
883 switch (mode & S_IFMT) {
884 case S_IFMT: /* used by badsect to flag bad sectors */
885 vattr.va_type = VBAD;
886 break;
887 case S_IFCHR:
888 vattr.va_type = VCHR;
889 break;
890 case S_IFBLK:
891 vattr.va_type = VBLK;
892 break;
893 case S_IFWHT:
894 whiteout = 1;
895 break;
896 default:
897 error = EINVAL;
898 break;
899 }
900 }
901 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
902 NDFREE(&nd, NDF_ONLY_PNBUF);
903 vput(nd.ni_dvp);
904 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
905 return (error);
906 goto restart;
907 }
908 #ifdef MAC
909 if (error == 0 && !whiteout)
910 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp,
911 &nd.ni_cnd, &vattr);
912 #endif
913 if (!error) {
914 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
915 if (whiteout)
916 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
917 else {
918 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
919 &nd.ni_cnd, &vattr);
920 if (error == 0)
921 vput(nd.ni_vp);
922 }
923 }
924 NDFREE(&nd, NDF_ONLY_PNBUF);
925 vput(nd.ni_dvp);
926 vn_finished_write(mp);
927 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod");
928 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod");
929 return (error);
930 }
931
932 /*
933 * Create a named pipe.
934 */
935 #ifndef _SYS_SYSPROTO_H_
936 struct mkfifo_args {
937 char *path;
938 int mode;
939 };
940 #endif
941 /* ARGSUSED */
942 int
943 mkfifo(td, uap)
944 struct thread *td;
945 register struct mkfifo_args /* {
946 char *path;
947 int mode;
948 } */ *uap;
949 {
950
951 return (kern_mkfifo(td, uap->path, UIO_USERSPACE, uap->mode));
952 }
953
954 int
955 kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode)
956 {
957 struct mount *mp;
958 struct vattr vattr;
959 int error;
960 struct nameidata nd;
961
962 restart:
963 bwillwrite();
964 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, pathseg, path, td);
965 if ((error = namei(&nd)) != 0)
966 return (error);
967 if (nd.ni_vp != NULL) {
968 NDFREE(&nd, NDF_ONLY_PNBUF);
969 vrele(nd.ni_vp);
970 vput(nd.ni_dvp);
971 return (EEXIST);
972 }
973 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
974 NDFREE(&nd, NDF_ONLY_PNBUF);
975 vput(nd.ni_dvp);
976 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
977 return (error);
978 goto restart;
979 }
980 VATTR_NULL(&vattr);
981 vattr.va_type = VFIFO;
982 FILEDESC_LOCK(td->td_proc->p_fd);
983 vattr.va_mode = (mode & ALLPERMS) & ~td->td_proc->p_fd->fd_cmask;
984 FILEDESC_UNLOCK(td->td_proc->p_fd);
985 #ifdef MAC
986 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
987 &vattr);
988 if (error)
989 goto out;
990 #endif
991 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
992 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
993 if (error == 0)
994 vput(nd.ni_vp);
995 #ifdef MAC
996 out:
997 #endif
998 NDFREE(&nd, NDF_ONLY_PNBUF);
999 vput(nd.ni_dvp);
1000 vn_finished_write(mp);
1001 return (error);
1002 }
1003
1004 /*
1005 * Make a hard file link.
1006 */
1007 #ifndef _SYS_SYSPROTO_H_
1008 struct link_args {
1009 char *path;
1010 char *link;
1011 };
1012 #endif
1013 /* ARGSUSED */
1014 int
1015 link(td, uap)
1016 struct thread *td;
1017 register struct link_args /* {
1018 char *path;
1019 char *link;
1020 } */ *uap;
1021 {
1022
1023 return (kern_link(td, uap->path, uap->link, UIO_USERSPACE));
1024 }
1025
1026 int
1027 kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg)
1028 {
1029 struct vnode *vp;
1030 struct mount *mp;
1031 struct nameidata nd;
1032 int error;
1033
1034 bwillwrite();
1035 NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, segflg, path, td);
1036 if ((error = namei(&nd)) != 0)
1037 return (error);
1038 NDFREE(&nd, NDF_ONLY_PNBUF);
1039 vp = nd.ni_vp;
1040 if (vp->v_type == VDIR) {
1041 vrele(vp);
1042 return (EPERM); /* POSIX */
1043 }
1044 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
1045 vrele(vp);
1046 return (error);
1047 }
1048 NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME, segflg, link, td);
1049 if ((error = namei(&nd)) == 0) {
1050 if (nd.ni_vp != NULL) {
1051 vrele(nd.ni_vp);
1052 error = EEXIST;
1053 } else if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td))
1054 == 0) {
1055 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1056 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1057 #ifdef MAC
1058 error = mac_check_vnode_link(td->td_ucred, nd.ni_dvp,
1059 vp, &nd.ni_cnd);
1060 if (error == 0)
1061 #endif
1062 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1063 VOP_UNLOCK(vp, 0, td);
1064 }
1065 NDFREE(&nd, NDF_ONLY_PNBUF);
1066 vput(nd.ni_dvp);
1067 }
1068 vrele(vp);
1069 vn_finished_write(mp);
1070 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link");
1071 ASSERT_VOP_UNLOCKED(nd.ni_vp, "link");
1072 return (error);
1073 }
1074
1075 /*
1076 * Make a symbolic link.
1077 */
1078 #ifndef _SYS_SYSPROTO_H_
1079 struct symlink_args {
1080 char *path;
1081 char *link;
1082 };
1083 #endif
1084 /* ARGSUSED */
1085 int
1086 symlink(td, uap)
1087 struct thread *td;
1088 register struct symlink_args /* {
1089 char *path;
1090 char *link;
1091 } */ *uap;
1092 {
1093
1094 return (kern_symlink(td, uap->path, uap->link, UIO_USERSPACE));
1095 }
1096
1097 int
1098 kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg)
1099 {
1100 struct mount *mp;
1101 struct vattr vattr;
1102 char *syspath;
1103 int error;
1104 struct nameidata nd;
1105
1106 if (segflg == UIO_SYSSPACE) {
1107 syspath = path;
1108 } else {
1109 syspath = uma_zalloc(namei_zone, M_WAITOK);
1110 if ((error = copyinstr(path, syspath, MAXPATHLEN, NULL)) != 0)
1111 goto out;
1112 }
1113 restart:
1114 bwillwrite();
1115 NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME, segflg, link, td);
1116 if ((error = namei(&nd)) != 0)
1117 goto out;
1118 if (nd.ni_vp) {
1119 NDFREE(&nd, NDF_ONLY_PNBUF);
1120 vrele(nd.ni_vp);
1121 vput(nd.ni_dvp);
1122 error = EEXIST;
1123 goto out;
1124 }
1125 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1126 NDFREE(&nd, NDF_ONLY_PNBUF);
1127 vput(nd.ni_dvp);
1128 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1129 return (error);
1130 goto restart;
1131 }
1132 VATTR_NULL(&vattr);
1133 FILEDESC_LOCK(td->td_proc->p_fd);
1134 vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask;
1135 FILEDESC_UNLOCK(td->td_proc->p_fd);
1136 #ifdef MAC
1137 vattr.va_type = VLNK;
1138 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
1139 &vattr);
1140 if (error)
1141 goto out2;
1142 #endif
1143 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1144 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath);
1145 if (error == 0)
1146 vput(nd.ni_vp);
1147 #ifdef MAC
1148 out2:
1149 #endif
1150 NDFREE(&nd, NDF_ONLY_PNBUF);
1151 vput(nd.ni_dvp);
1152 vn_finished_write(mp);
1153 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink");
1154 ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink");
1155 out:
1156 if (segflg != UIO_SYSSPACE)
1157 uma_zfree(namei_zone, syspath);
1158 return (error);
1159 }
1160
1161 /*
1162 * Delete a whiteout from the filesystem.
1163 */
1164 /* ARGSUSED */
1165 int
1166 undelete(td, uap)
1167 struct thread *td;
1168 register struct undelete_args /* {
1169 char *path;
1170 } */ *uap;
1171 {
1172 int error;
1173 struct mount *mp;
1174 struct nameidata nd;
1175
1176 restart:
1177 bwillwrite();
1178 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
1179 uap->path, td);
1180 error = namei(&nd);
1181 if (error)
1182 return (error);
1183
1184 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1185 NDFREE(&nd, NDF_ONLY_PNBUF);
1186 if (nd.ni_vp)
1187 vrele(nd.ni_vp);
1188 vput(nd.ni_dvp);
1189 return (EEXIST);
1190 }
1191 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1192 NDFREE(&nd, NDF_ONLY_PNBUF);
1193 vput(nd.ni_dvp);
1194 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1195 return (error);
1196 goto restart;
1197 }
1198 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1199 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
1200 NDFREE(&nd, NDF_ONLY_PNBUF);
1201 vput(nd.ni_dvp);
1202 vn_finished_write(mp);
1203 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete");
1204 ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete");
1205 return (error);
1206 }
1207
1208 /*
1209 * Delete a name from the filesystem.
1210 */
1211 #ifndef _SYS_SYSPROTO_H_
1212 struct unlink_args {
1213 char *path;
1214 };
1215 #endif
1216 /* ARGSUSED */
1217 int
1218 unlink(td, uap)
1219 struct thread *td;
1220 struct unlink_args /* {
1221 char *path;
1222 } */ *uap;
1223 {
1224
1225 return (kern_unlink(td, uap->path, UIO_USERSPACE));
1226 }
1227
1228 int
1229 kern_unlink(struct thread *td, char *path, enum uio_seg pathseg)
1230 {
1231 struct mount *mp;
1232 struct vnode *vp;
1233 int error;
1234 struct nameidata nd;
1235
1236 restart:
1237 bwillwrite();
1238 NDINIT(&nd, DELETE, LOCKPARENT|LOCKLEAF, pathseg, path, td);
1239 if ((error = namei(&nd)) != 0)
1240 return (error);
1241 vp = nd.ni_vp;
1242 if (vp->v_type == VDIR)
1243 error = EPERM; /* POSIX */
1244 else {
1245 /*
1246 * The root of a mounted filesystem cannot be deleted.
1247 *
1248 * XXX: can this only be a VDIR case?
1249 */
1250 if (vp->v_vflag & VV_ROOT)
1251 error = EBUSY;
1252 }
1253 if (error == 0) {
1254 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1255 NDFREE(&nd, NDF_ONLY_PNBUF);
1256 if (vp == nd.ni_dvp)
1257 vrele(vp);
1258 else
1259 vput(vp);
1260 vput(nd.ni_dvp);
1261 if ((error = vn_start_write(NULL, &mp,
1262 V_XSLEEP | PCATCH)) != 0)
1263 return (error);
1264 goto restart;
1265 }
1266 #ifdef MAC
1267 error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp,
1268 &nd.ni_cnd);
1269 if (error)
1270 goto out;
1271 #endif
1272 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1273 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
1274 #ifdef MAC
1275 out:
1276 #endif
1277 vn_finished_write(mp);
1278 }
1279 NDFREE(&nd, NDF_ONLY_PNBUF);
1280 if (vp == nd.ni_dvp)
1281 vrele(vp);
1282 else
1283 vput(vp);
1284 vput(nd.ni_dvp);
1285 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
1286 ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
1287 return (error);
1288 }
1289
1290 /*
1291 * Reposition read/write file offset.
1292 */
1293 #ifndef _SYS_SYSPROTO_H_
1294 struct lseek_args {
1295 int fd;
1296 int pad;
1297 off_t offset;
1298 int whence;
1299 };
1300 #endif
1301 int
1302 lseek(td, uap)
1303 struct thread *td;
1304 register struct lseek_args /* {
1305 int fd;
1306 int pad;
1307 off_t offset;
1308 int whence;
1309 } */ *uap;
1310 {
1311 struct ucred *cred = td->td_ucred;
1312 struct file *fp;
1313 struct vnode *vp;
1314 struct vattr vattr;
1315 off_t offset;
1316 int error, noneg;
1317
1318 if ((error = fget(td, uap->fd, &fp)) != 0)
1319 return (error);
1320 if (fp->f_type != DTYPE_VNODE) {
1321 fdrop(fp, td);
1322 return (ESPIPE);
1323 }
1324 vp = (struct vnode *)fp->f_data;
1325 noneg = (vp->v_type != VCHR);
1326 offset = uap->offset;
1327 switch (uap->whence) {
1328 case L_INCR:
1329 if (noneg &&
1330 (fp->f_offset < 0 ||
1331 (offset > 0 && fp->f_offset > OFF_MAX - offset))) {
1332 error = EOVERFLOW;
1333 break;
1334 }
1335 offset += fp->f_offset;
1336 break;
1337 case L_XTND:
1338 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1339 error = VOP_GETATTR(vp, &vattr, cred, td);
1340 VOP_UNLOCK(vp, 0, td);
1341 if (error)
1342 break;
1343 if (noneg &&
1344 (vattr.va_size > OFF_MAX ||
1345 (offset > 0 && vattr.va_size > OFF_MAX - offset))) {
1346 error = EOVERFLOW;
1347 break;
1348 }
1349 offset += vattr.va_size;
1350 break;
1351 case L_SET:
1352 break;
1353 default:
1354 error = EINVAL;
1355 }
1356 if (error == 0 && noneg && offset < 0)
1357 error = EINVAL;
1358 if (error != 0) {
1359 fdrop(fp, td);
1360 return (error);
1361 }
1362 fp->f_offset = offset;
1363 *(off_t *)(td->td_retval) = fp->f_offset;
1364 fdrop(fp, td);
1365 return (0);
1366 }
1367
1368 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1369 /*
1370 * Reposition read/write file offset.
1371 */
1372 #ifndef _SYS_SYSPROTO_H_
1373 struct olseek_args {
1374 int fd;
1375 long offset;
1376 int whence;
1377 };
1378 #endif
1379 int
1380 olseek(td, uap)
1381 struct thread *td;
1382 register struct olseek_args /* {
1383 int fd;
1384 long offset;
1385 int whence;
1386 } */ *uap;
1387 {
1388 struct lseek_args /* {
1389 int fd;
1390 int pad;
1391 off_t offset;
1392 int whence;
1393 } */ nuap;
1394 int error;
1395
1396 nuap.fd = uap->fd;
1397 nuap.offset = uap->offset;
1398 nuap.whence = uap->whence;
1399 error = lseek(td, &nuap);
1400 return (error);
1401 }
1402 #endif /* COMPAT_43 */
1403
1404 /*
1405 * Check access permissions using passed credentials.
1406 */
1407 static int
1408 vn_access(vp, user_flags, cred, td)
1409 struct vnode *vp;
1410 int user_flags;
1411 struct ucred *cred;
1412 struct thread *td;
1413 {
1414 int error, flags;
1415
1416 /* Flags == 0 means only check for existence. */
1417 error = 0;
1418 if (user_flags) {
1419 flags = 0;
1420 if (user_flags & R_OK)
1421 flags |= VREAD;
1422 if (user_flags & W_OK)
1423 flags |= VWRITE;
1424 if (user_flags & X_OK)
1425 flags |= VEXEC;
1426 #ifdef MAC
1427 error = mac_check_vnode_access(cred, vp, flags);
1428 if (error)
1429 return (error);
1430 #endif
1431 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1432 error = VOP_ACCESS(vp, flags, cred, td);
1433 }
1434 return (error);
1435 }
1436
1437 /*
1438 * Check access permissions using "real" credentials.
1439 */
1440 #ifndef _SYS_SYSPROTO_H_
1441 struct access_args {
1442 char *path;
1443 int flags;
1444 };
1445 #endif
1446 int
1447 access(td, uap)
1448 struct thread *td;
1449 register struct access_args /* {
1450 char *path;
1451 int flags;
1452 } */ *uap;
1453 {
1454
1455 return (kern_access(td, uap->path, UIO_USERSPACE, uap->flags));
1456 }
1457
1458 int
1459 kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags)
1460 {
1461 struct ucred *cred, *tmpcred;
1462 register struct vnode *vp;
1463 int error;
1464 struct nameidata nd;
1465
1466 /*
1467 * Create and modify a temporary credential instead of one that
1468 * is potentially shared. This could also mess up socket
1469 * buffer accounting which can run in an interrupt context.
1470 *
1471 * XXX - Depending on how "threads" are finally implemented, it
1472 * may be better to explicitly pass the credential to namei()
1473 * rather than to modify the potentially shared process structure.
1474 */
1475 cred = td->td_ucred;
1476 tmpcred = crdup(cred);
1477 tmpcred->cr_uid = cred->cr_ruid;
1478 tmpcred->cr_groups[0] = cred->cr_rgid;
1479 td->td_ucred = tmpcred;
1480 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, pathseg, path, td);
1481 if ((error = namei(&nd)) != 0)
1482 goto out1;
1483 vp = nd.ni_vp;
1484
1485 error = vn_access(vp, flags, tmpcred, td);
1486 NDFREE(&nd, NDF_ONLY_PNBUF);
1487 vput(vp);
1488 out1:
1489 td->td_ucred = cred;
1490 crfree(tmpcred);
1491 return (error);
1492 }
1493
1494 /*
1495 * Check access permissions using "effective" credentials.
1496 */
1497 #ifndef _SYS_SYSPROTO_H_
1498 struct eaccess_args {
1499 char *path;
1500 int flags;
1501 };
1502 #endif
1503 int
1504 eaccess(td, uap)
1505 struct thread *td;
1506 register struct eaccess_args /* {
1507 char *path;
1508 int flags;
1509 } */ *uap;
1510 {
1511 struct nameidata nd;
1512 struct vnode *vp;
1513 int error;
1514
1515 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1516 uap->path, td);
1517 if ((error = namei(&nd)) != 0)
1518 return (error);
1519 vp = nd.ni_vp;
1520
1521 error = vn_access(vp, uap->flags, td->td_ucred, td);
1522 NDFREE(&nd, NDF_ONLY_PNBUF);
1523 vput(vp);
1524 return (error);
1525 }
1526
1527 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1528 /*
1529 * Get file status; this version follows links.
1530 */
1531 #ifndef _SYS_SYSPROTO_H_
1532 struct ostat_args {
1533 char *path;
1534 struct ostat *ub;
1535 };
1536 #endif
1537 /* ARGSUSED */
1538 int
1539 ostat(td, uap)
1540 struct thread *td;
1541 register struct ostat_args /* {
1542 char *path;
1543 struct ostat *ub;
1544 } */ *uap;
1545 {
1546 struct stat sb;
1547 struct ostat osb;
1548 int error;
1549 struct nameidata nd;
1550
1551 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1552 uap->path, td);
1553 if ((error = namei(&nd)) != 0)
1554 return (error);
1555 NDFREE(&nd, NDF_ONLY_PNBUF);
1556 error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
1557 vput(nd.ni_vp);
1558 if (error)
1559 return (error);
1560 cvtstat(&sb, &osb);
1561 error = copyout(&osb, uap->ub, sizeof (osb));
1562 return (error);
1563 }
1564
1565 /*
1566 * Get file status; this version does not follow links.
1567 */
1568 #ifndef _SYS_SYSPROTO_H_
1569 struct olstat_args {
1570 char *path;
1571 struct ostat *ub;
1572 };
1573 #endif
1574 /* ARGSUSED */
1575 int
1576 olstat(td, uap)
1577 struct thread *td;
1578 register struct olstat_args /* {
1579 char *path;
1580 struct ostat *ub;
1581 } */ *uap;
1582 {
1583 struct vnode *vp;
1584 struct stat sb;
1585 struct ostat osb;
1586 int error;
1587 struct nameidata nd;
1588
1589 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1590 uap->path, td);
1591 if ((error = namei(&nd)) != 0)
1592 return (error);
1593 vp = nd.ni_vp;
1594 error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
1595 NDFREE(&nd, NDF_ONLY_PNBUF);
1596 vput(vp);
1597 if (error)
1598 return (error);
1599 cvtstat(&sb, &osb);
1600 error = copyout(&osb, uap->ub, sizeof (osb));
1601 return (error);
1602 }
1603
1604 /*
1605 * Convert from an old to a new stat structure.
1606 */
1607 void
1608 cvtstat(st, ost)
1609 struct stat *st;
1610 struct ostat *ost;
1611 {
1612
1613 ost->st_dev = st->st_dev;
1614 ost->st_ino = st->st_ino;
1615 ost->st_mode = st->st_mode;
1616 ost->st_nlink = st->st_nlink;
1617 ost->st_uid = st->st_uid;
1618 ost->st_gid = st->st_gid;
1619 ost->st_rdev = st->st_rdev;
1620 if (st->st_size < (quad_t)1 << 32)
1621 ost->st_size = st->st_size;
1622 else
1623 ost->st_size = -2;
1624 ost->st_atime = st->st_atime;
1625 ost->st_mtime = st->st_mtime;
1626 ost->st_ctime = st->st_ctime;
1627 ost->st_blksize = st->st_blksize;
1628 ost->st_blocks = st->st_blocks;
1629 ost->st_flags = st->st_flags;
1630 ost->st_gen = st->st_gen;
1631 }
1632 #endif /* COMPAT_43 || COMPAT_SUNOS */
1633
1634 /*
1635 * Get file status; this version follows links.
1636 */
1637 #ifndef _SYS_SYSPROTO_H_
1638 struct stat_args {
1639 char *path;
1640 struct stat *ub;
1641 };
1642 #endif
1643 /* ARGSUSED */
1644 int
1645 stat(td, uap)
1646 struct thread *td;
1647 register struct stat_args /* {
1648 char *path;
1649 struct stat *ub;
1650 } */ *uap;
1651 {
1652 struct stat sb;
1653 int error;
1654 struct nameidata nd;
1655
1656 #ifdef LOOKUP_SHARED
1657 NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | NOOBJ,
1658 UIO_USERSPACE, uap->path, td);
1659 #else
1660 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1661 uap->path, td);
1662 #endif
1663 if ((error = namei(&nd)) != 0)
1664 return (error);
1665 error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
1666 NDFREE(&nd, NDF_ONLY_PNBUF);
1667 vput(nd.ni_vp);
1668 if (error)
1669 return (error);
1670 error = copyout(&sb, uap->ub, sizeof (sb));
1671 return (error);
1672 }
1673
1674 /*
1675 * Get file status; this version does not follow links.
1676 */
1677 #ifndef _SYS_SYSPROTO_H_
1678 struct lstat_args {
1679 char *path;
1680 struct stat *ub;
1681 };
1682 #endif
1683 /* ARGSUSED */
1684 int
1685 lstat(td, uap)
1686 struct thread *td;
1687 register struct lstat_args /* {
1688 char *path;
1689 struct stat *ub;
1690 } */ *uap;
1691 {
1692 int error;
1693 struct vnode *vp;
1694 struct stat sb;
1695 struct nameidata nd;
1696
1697 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1698 uap->path, td);
1699 if ((error = namei(&nd)) != 0)
1700 return (error);
1701 vp = nd.ni_vp;
1702 error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
1703 NDFREE(&nd, NDF_ONLY_PNBUF);
1704 vput(vp);
1705 if (error)
1706 return (error);
1707 error = copyout(&sb, uap->ub, sizeof (sb));
1708 return (error);
1709 }
1710
1711 /*
1712 * Implementation of the NetBSD stat() function.
1713 * XXX This should probably be collapsed with the FreeBSD version,
1714 * as the differences are only due to vn_stat() clearing spares at
1715 * the end of the structures. vn_stat could be split to avoid this,
1716 * and thus collapse the following to close to zero code.
1717 */
1718 void
1719 cvtnstat(sb, nsb)
1720 struct stat *sb;
1721 struct nstat *nsb;
1722 {
1723 bzero(nsb, sizeof *nsb);
1724 nsb->st_dev = sb->st_dev;
1725 nsb->st_ino = sb->st_ino;
1726 nsb->st_mode = sb->st_mode;
1727 nsb->st_nlink = sb->st_nlink;
1728 nsb->st_uid = sb->st_uid;
1729 nsb->st_gid = sb->st_gid;
1730 nsb->st_rdev = sb->st_rdev;
1731 nsb->st_atimespec = sb->st_atimespec;
1732 nsb->st_mtimespec = sb->st_mtimespec;
1733 nsb->st_ctimespec = sb->st_ctimespec;
1734 nsb->st_size = sb->st_size;
1735 nsb->st_blocks = sb->st_blocks;
1736 nsb->st_blksize = sb->st_blksize;
1737 nsb->st_flags = sb->st_flags;
1738 nsb->st_gen = sb->st_gen;
1739 nsb->st_birthtimespec = sb->st_birthtimespec;
1740 }
1741
1742 #ifndef _SYS_SYSPROTO_H_
1743 struct nstat_args {
1744 char *path;
1745 struct nstat *ub;
1746 };
1747 #endif
1748 /* ARGSUSED */
1749 int
1750 nstat(td, uap)
1751 struct thread *td;
1752 register struct nstat_args /* {
1753 char *path;
1754 struct nstat *ub;
1755 } */ *uap;
1756 {
1757 struct stat sb;
1758 struct nstat nsb;
1759 int error;
1760 struct nameidata nd;
1761
1762 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1763 uap->path, td);
1764 if ((error = namei(&nd)) != 0)
1765 return (error);
1766 NDFREE(&nd, NDF_ONLY_PNBUF);
1767 error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
1768 vput(nd.ni_vp);
1769 if (error)
1770 return (error);
1771 cvtnstat(&sb, &nsb);
1772 error = copyout(&nsb, uap->ub, sizeof (nsb));
1773 return (error);
1774 }
1775
1776 /*
1777 * NetBSD lstat. Get file status; this version does not follow links.
1778 */
1779 #ifndef _SYS_SYSPROTO_H_
1780 struct lstat_args {
1781 char *path;
1782 struct stat *ub;
1783 };
1784 #endif
1785 /* ARGSUSED */
1786 int
1787 nlstat(td, uap)
1788 struct thread *td;
1789 register struct nlstat_args /* {
1790 char *path;
1791 struct nstat *ub;
1792 } */ *uap;
1793 {
1794 int error;
1795 struct vnode *vp;
1796 struct stat sb;
1797 struct nstat nsb;
1798 struct nameidata nd;
1799
1800 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1801 uap->path, td);
1802 if ((error = namei(&nd)) != 0)
1803 return (error);
1804 vp = nd.ni_vp;
1805 NDFREE(&nd, NDF_ONLY_PNBUF);
1806 error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
1807 vput(vp);
1808 if (error)
1809 return (error);
1810 cvtnstat(&sb, &nsb);
1811 error = copyout(&nsb, uap->ub, sizeof (nsb));
1812 return (error);
1813 }
1814
1815 /*
1816 * Get configurable pathname variables.
1817 */
1818 #ifndef _SYS_SYSPROTO_H_
1819 struct pathconf_args {
1820 char *path;
1821 int name;
1822 };
1823 #endif
1824 /* ARGSUSED */
1825 int
1826 pathconf(td, uap)
1827 struct thread *td;
1828 register struct pathconf_args /* {
1829 char *path;
1830 int name;
1831 } */ *uap;
1832 {
1833 int error;
1834 struct nameidata nd;
1835
1836 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1837 uap->path, td);
1838 if ((error = namei(&nd)) != 0)
1839 return (error);
1840 NDFREE(&nd, NDF_ONLY_PNBUF);
1841
1842 /* If asynchronous I/O is available, it works for all files. */
1843 if (uap->name == _PC_ASYNC_IO)
1844 td->td_retval[0] = async_io_version;
1845 else
1846 error = VOP_PATHCONF(nd.ni_vp, uap->name, td->td_retval);
1847 vput(nd.ni_vp);
1848 return (error);
1849 }
1850
1851 /*
1852 * Return target name of a symbolic link.
1853 */
1854 #ifndef _SYS_SYSPROTO_H_
1855 struct readlink_args {
1856 char *path;
1857 char *buf;
1858 int count;
1859 };
1860 #endif
1861 /* ARGSUSED */
1862 int
1863 readlink(td, uap)
1864 struct thread *td;
1865 register struct readlink_args /* {
1866 char *path;
1867 char *buf;
1868 int count;
1869 } */ *uap;
1870 {
1871
1872 return (kern_readlink(td, uap->path, UIO_USERSPACE, uap->buf,
1873 UIO_USERSPACE, uap->count));
1874 }
1875
1876 int
1877 kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf,
1878 enum uio_seg bufseg, int count)
1879 {
1880 register struct vnode *vp;
1881 struct iovec aiov;
1882 struct uio auio;
1883 int error;
1884 struct nameidata nd;
1885
1886 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, pathseg, path, td);
1887 if ((error = namei(&nd)) != 0)
1888 return (error);
1889 NDFREE(&nd, NDF_ONLY_PNBUF);
1890 vp = nd.ni_vp;
1891 #ifdef MAC
1892 error = mac_check_vnode_readlink(td->td_ucred, vp);
1893 if (error) {
1894 vput(vp);
1895 return (error);
1896 }
1897 #endif
1898 if (vp->v_type != VLNK)
1899 error = EINVAL;
1900 else {
1901 aiov.iov_base = buf;
1902 aiov.iov_len = count;
1903 auio.uio_iov = &aiov;
1904 auio.uio_iovcnt = 1;
1905 auio.uio_offset = 0;
1906 auio.uio_rw = UIO_READ;
1907 auio.uio_segflg = bufseg;
1908 auio.uio_td = td;
1909 auio.uio_resid = count;
1910 error = VOP_READLINK(vp, &auio, td->td_ucred);
1911 }
1912 vput(vp);
1913 td->td_retval[0] = count - auio.uio_resid;
1914 return (error);
1915 }
1916
1917 /*
1918 * Common implementation code for chflags() and fchflags().
1919 */
1920 static int
1921 setfflags(td, vp, flags)
1922 struct thread *td;
1923 struct vnode *vp;
1924 int flags;
1925 {
1926 int error;
1927 struct mount *mp;
1928 struct vattr vattr;
1929
1930 /*
1931 * Prevent non-root users from setting flags on devices. When
1932 * a device is reused, users can retain ownership of the device
1933 * if they are allowed to set flags and programs assume that
1934 * chown can't fail when done as root.
1935 */
1936 if (vp->v_type == VCHR || vp->v_type == VBLK) {
1937 error = suser_cred(td->td_ucred, PRISON_ROOT);
1938 if (error)
1939 return (error);
1940 }
1941
1942 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
1943 return (error);
1944 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1945 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1946 #ifdef MAC
1947 error = mac_check_vnode_setflags(td->td_ucred, vp, vattr.va_flags);
1948 if (error == 0) {
1949 #endif
1950 VATTR_NULL(&vattr);
1951 vattr.va_flags = flags;
1952 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
1953 #ifdef MAC
1954 }
1955 #endif
1956 VOP_UNLOCK(vp, 0, td);
1957 vn_finished_write(mp);
1958 return (error);
1959 }
1960
1961 /*
1962 * Change flags of a file given a path name.
1963 */
1964 #ifndef _SYS_SYSPROTO_H_
1965 struct chflags_args {
1966 char *path;
1967 int flags;
1968 };
1969 #endif
1970 /* ARGSUSED */
1971 int
1972 chflags(td, uap)
1973 struct thread *td;
1974 register struct chflags_args /* {
1975 char *path;
1976 int flags;
1977 } */ *uap;
1978 {
1979 int error;
1980 struct nameidata nd;
1981
1982 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
1983 if ((error = namei(&nd)) != 0)
1984 return (error);
1985 NDFREE(&nd, NDF_ONLY_PNBUF);
1986 error = setfflags(td, nd.ni_vp, uap->flags);
1987 vrele(nd.ni_vp);
1988 return error;
1989 }
1990
1991 /*
1992 * Same as chflags() but doesn't follow symlinks.
1993 */
1994 int
1995 lchflags(td, uap)
1996 struct thread *td;
1997 register struct lchflags_args /* {
1998 char *path;
1999 int flags;
2000 } */ *uap;
2001 {
2002 int error;
2003 struct nameidata nd;
2004
2005 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
2006 if ((error = namei(&nd)) != 0)
2007 return (error);
2008 NDFREE(&nd, NDF_ONLY_PNBUF);
2009 error = setfflags(td, nd.ni_vp, uap->flags);
2010 vrele(nd.ni_vp);
2011 return error;
2012 }
2013
2014 /*
2015 * Change flags of a file given a file descriptor.
2016 */
2017 #ifndef _SYS_SYSPROTO_H_
2018 struct fchflags_args {
2019 int fd;
2020 int flags;
2021 };
2022 #endif
2023 /* ARGSUSED */
2024 int
2025 fchflags(td, uap)
2026 struct thread *td;
2027 register struct fchflags_args /* {
2028 int fd;
2029 int flags;
2030 } */ *uap;
2031 {
2032 struct file *fp;
2033 int error;
2034
2035 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2036 return (error);
2037 error = setfflags(td, (struct vnode *) fp->f_data, uap->flags);
2038 fdrop(fp, td);
2039 return (error);
2040 }
2041
2042 /*
2043 * Common implementation code for chmod(), lchmod() and fchmod().
2044 */
2045 static int
2046 setfmode(td, vp, mode)
2047 struct thread *td;
2048 struct vnode *vp;
2049 int mode;
2050 {
2051 int error;
2052 struct mount *mp;
2053 struct vattr vattr;
2054
2055 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2056 return (error);
2057 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2058 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2059 VATTR_NULL(&vattr);
2060 vattr.va_mode = mode & ALLPERMS;
2061 #ifdef MAC
2062 error = mac_check_vnode_setmode(td->td_ucred, vp, vattr.va_mode);
2063 if (error == 0)
2064 #endif
2065 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2066 VOP_UNLOCK(vp, 0, td);
2067 vn_finished_write(mp);
2068 return error;
2069 }
2070
2071 /*
2072 * Change mode of a file given path name.
2073 */
2074 #ifndef _SYS_SYSPROTO_H_
2075 struct chmod_args {
2076 char *path;
2077 int mode;
2078 };
2079 #endif
2080 /* ARGSUSED */
2081 int
2082 chmod(td, uap)
2083 struct thread *td;
2084 register struct chmod_args /* {
2085 char *path;
2086 int mode;
2087 } */ *uap;
2088 {
2089
2090 return (kern_chmod(td, uap->path, UIO_USERSPACE, uap->mode));
2091 }
2092
2093 int
2094 kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int mode)
2095 {
2096 int error;
2097 struct nameidata nd;
2098
2099 NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
2100 if ((error = namei(&nd)) != 0)
2101 return (error);
2102 NDFREE(&nd, NDF_ONLY_PNBUF);
2103 error = setfmode(td, nd.ni_vp, mode);
2104 vrele(nd.ni_vp);
2105 return error;
2106 }
2107
2108 /*
2109 * Change mode of a file given path name (don't follow links.)
2110 */
2111 #ifndef _SYS_SYSPROTO_H_
2112 struct lchmod_args {
2113 char *path;
2114 int mode;
2115 };
2116 #endif
2117 /* ARGSUSED */
2118 int
2119 lchmod(td, uap)
2120 struct thread *td;
2121 register struct lchmod_args /* {
2122 char *path;
2123 int mode;
2124 } */ *uap;
2125 {
2126 int error;
2127 struct nameidata nd;
2128
2129 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
2130 if ((error = namei(&nd)) != 0)
2131 return (error);
2132 NDFREE(&nd, NDF_ONLY_PNBUF);
2133 error = setfmode(td, nd.ni_vp, uap->mode);
2134 vrele(nd.ni_vp);
2135 return error;
2136 }
2137
2138 /*
2139 * Change mode of a file given a file descriptor.
2140 */
2141 #ifndef _SYS_SYSPROTO_H_
2142 struct fchmod_args {
2143 int fd;
2144 int mode;
2145 };
2146 #endif
2147 /* ARGSUSED */
2148 int
2149 fchmod(td, uap)
2150 struct thread *td;
2151 register struct fchmod_args /* {
2152 int fd;
2153 int mode;
2154 } */ *uap;
2155 {
2156 struct file *fp;
2157 struct vnode *vp;
2158 int error;
2159
2160 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2161 return (error);
2162 vp = (struct vnode *)fp->f_data;
2163 error = setfmode(td, (struct vnode *)fp->f_data, uap->mode);
2164 fdrop(fp, td);
2165 return (error);
2166 }
2167
2168 /*
2169 * Common implementation for chown(), lchown(), and fchown()
2170 */
2171 static int
2172 setfown(td, vp, uid, gid)
2173 struct thread *td;
2174 struct vnode *vp;
2175 uid_t uid;
2176 gid_t gid;
2177 {
2178 int error;
2179 struct mount *mp;
2180 struct vattr vattr;
2181
2182 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2183 return (error);
2184 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2185 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2186 VATTR_NULL(&vattr);
2187 vattr.va_uid = uid;
2188 vattr.va_gid = gid;
2189 #ifdef MAC
2190 error = mac_check_vnode_setowner(td->td_ucred, vp, vattr.va_uid,
2191 vattr.va_gid);
2192 if (error == 0)
2193 #endif
2194 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2195 VOP_UNLOCK(vp, 0, td);
2196 vn_finished_write(mp);
2197 return error;
2198 }
2199
2200 /*
2201 * Set ownership given a path name.
2202 */
2203 #ifndef _SYS_SYSPROTO_H_
2204 struct chown_args {
2205 char *path;
2206 int uid;
2207 int gid;
2208 };
2209 #endif
2210 /* ARGSUSED */
2211 int
2212 chown(td, uap)
2213 struct thread *td;
2214 register struct chown_args /* {
2215 char *path;
2216 int uid;
2217 int gid;
2218 } */ *uap;
2219 {
2220
2221 return (kern_chown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid));
2222 }
2223
2224 int
2225 kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
2226 int gid)
2227 {
2228 int error;
2229 struct nameidata nd;
2230
2231 NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
2232 if ((error = namei(&nd)) != 0)
2233 return (error);
2234 NDFREE(&nd, NDF_ONLY_PNBUF);
2235 error = setfown(td, nd.ni_vp, uid, gid);
2236 vrele(nd.ni_vp);
2237 return (error);
2238 }
2239
2240 /*
2241 * Set ownership given a path name, do not cross symlinks.
2242 */
2243 #ifndef _SYS_SYSPROTO_H_
2244 struct lchown_args {
2245 char *path;
2246 int uid;
2247 int gid;
2248 };
2249 #endif
2250 /* ARGSUSED */
2251 int
2252 lchown(td, uap)
2253 struct thread *td;
2254 register struct lchown_args /* {
2255 char *path;
2256 int uid;
2257 int gid;
2258 } */ *uap;
2259 {
2260
2261 return (kern_lchown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid));
2262 }
2263
2264 int
2265 kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
2266 int gid)
2267 {
2268 int error;
2269 struct nameidata nd;
2270
2271 NDINIT(&nd, LOOKUP, NOFOLLOW, pathseg, path, td);
2272 if ((error = namei(&nd)) != 0)
2273 return (error);
2274 NDFREE(&nd, NDF_ONLY_PNBUF);
2275 error = setfown(td, nd.ni_vp, uid, gid);
2276 vrele(nd.ni_vp);
2277 return (error);
2278 }
2279
2280 /*
2281 * Set ownership given a file descriptor.
2282 */
2283 #ifndef _SYS_SYSPROTO_H_
2284 struct fchown_args {
2285 int fd;
2286 int uid;
2287 int gid;
2288 };
2289 #endif
2290 /* ARGSUSED */
2291 int
2292 fchown(td, uap)
2293 struct thread *td;
2294 register struct fchown_args /* {
2295 int fd;
2296 int uid;
2297 int gid;
2298 } */ *uap;
2299 {
2300 struct file *fp;
2301 struct vnode *vp;
2302 int error;
2303
2304 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2305 return (error);
2306 vp = (struct vnode *)fp->f_data;
2307 error = setfown(td, (struct vnode *)fp->f_data,
2308 uap->uid, uap->gid);
2309 fdrop(fp, td);
2310 return (error);
2311 }
2312
2313 /*
2314 * Common implementation code for utimes(), lutimes(), and futimes().
2315 */
2316 static int
2317 getutimes(usrtvp, tvpseg, tsp)
2318 const struct timeval *usrtvp;
2319 enum uio_seg tvpseg;
2320 struct timespec *tsp;
2321 {
2322 struct timeval tv[2];
2323 const struct timeval *tvp;
2324 int error;
2325
2326 if (usrtvp == NULL) {
2327 microtime(&tv[0]);
2328 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2329 tsp[1] = tsp[0];
2330 } else {
2331 if (tvpseg == UIO_SYSSPACE) {
2332 tvp = usrtvp;
2333 } else {
2334 if ((error = copyin(usrtvp, tv, sizeof(tv))) != 0)
2335 return (error);
2336 tvp = tv;
2337 }
2338
2339 TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]);
2340 TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]);
2341 }
2342 return 0;
2343 }
2344
2345 /*
2346 * Common implementation code for utimes(), lutimes(), and futimes().
2347 */
2348 static int
2349 setutimes(td, vp, ts, numtimes, nullflag)
2350 struct thread *td;
2351 struct vnode *vp;
2352 const struct timespec *ts;
2353 int numtimes;
2354 int nullflag;
2355 {
2356 int error, setbirthtime;
2357 struct mount *mp;
2358 struct vattr vattr;
2359
2360 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2361 return (error);
2362 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2363 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2364 setbirthtime = 0;
2365 if (numtimes < 3 && VOP_GETATTR(vp, &vattr, td->td_ucred, td) == 0 &&
2366 timespeccmp(&ts[1], &vattr.va_birthtime, < ))
2367 setbirthtime = 1;
2368 VATTR_NULL(&vattr);
2369 vattr.va_atime = ts[0];
2370 vattr.va_mtime = ts[1];
2371 if (setbirthtime)
2372 vattr.va_birthtime = ts[1];
2373 if (numtimes > 2)
2374 vattr.va_birthtime = ts[2];
2375 if (nullflag)
2376 vattr.va_vaflags |= VA_UTIMES_NULL;
2377 #ifdef MAC
2378 error = mac_check_vnode_setutimes(td->td_ucred, vp, vattr.va_atime,
2379 vattr.va_mtime);
2380 #endif
2381 if (error == 0)
2382 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2383 VOP_UNLOCK(vp, 0, td);
2384 vn_finished_write(mp);
2385 return error;
2386 }
2387
2388 /*
2389 * Set the access and modification times of a file.
2390 */
2391 #ifndef _SYS_SYSPROTO_H_
2392 struct utimes_args {
2393 char *path;
2394 struct timeval *tptr;
2395 };
2396 #endif
2397 /* ARGSUSED */
2398 int
2399 utimes(td, uap)
2400 struct thread *td;
2401 register struct utimes_args /* {
2402 char *path;
2403 struct timeval *tptr;
2404 } */ *uap;
2405 {
2406
2407 return (kern_utimes(td, uap->path, UIO_USERSPACE, uap->tptr,
2408 UIO_USERSPACE));
2409 }
2410
2411 int
2412 kern_utimes(struct thread *td, char *path, enum uio_seg pathseg,
2413 struct timeval *tptr, enum uio_seg tptrseg)
2414 {
2415 struct timespec ts[2];
2416 int error;
2417 struct nameidata nd;
2418
2419 if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2420 return (error);
2421 NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
2422 if ((error = namei(&nd)) != 0)
2423 return (error);
2424 NDFREE(&nd, NDF_ONLY_PNBUF);
2425 error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
2426 vrele(nd.ni_vp);
2427 return (error);
2428 }
2429
2430 /*
2431 * Set the access and modification times of a file.
2432 */
2433 #ifndef _SYS_SYSPROTO_H_
2434 struct lutimes_args {
2435 char *path;
2436 struct timeval *tptr;
2437 };
2438 #endif
2439 /* ARGSUSED */
2440 int
2441 lutimes(td, uap)
2442 struct thread *td;
2443 register struct lutimes_args /* {
2444 char *path;
2445 struct timeval *tptr;
2446 } */ *uap;
2447 {
2448
2449 return (kern_lutimes(td, uap->path, UIO_USERSPACE, uap->tptr,
2450 UIO_USERSPACE));
2451 }
2452
2453 int
2454 kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg,
2455 struct timeval *tptr, enum uio_seg tptrseg)
2456 {
2457 struct timespec ts[2];
2458 int error;
2459 struct nameidata nd;
2460
2461 if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2462 return (error);
2463 NDINIT(&nd, LOOKUP, NOFOLLOW, pathseg, path, td);
2464 if ((error = namei(&nd)) != 0)
2465 return (error);
2466 NDFREE(&nd, NDF_ONLY_PNBUF);
2467 error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
2468 vrele(nd.ni_vp);
2469 return (error);
2470 }
2471
2472 /*
2473 * Set the access and modification times of a file.
2474 */
2475 #ifndef _SYS_SYSPROTO_H_
2476 struct futimes_args {
2477 int fd;
2478 struct timeval *tptr;
2479 };
2480 #endif
2481 /* ARGSUSED */
2482 int
2483 futimes(td, uap)
2484 struct thread *td;
2485 register struct futimes_args /* {
2486 int fd;
2487 struct timeval *tptr;
2488 } */ *uap;
2489 {
2490
2491 return (kern_futimes(td, uap->fd, uap->tptr, UIO_USERSPACE));
2492 }
2493
2494 int
2495 kern_futimes(struct thread *td, int fd, struct timeval *tptr,
2496 enum uio_seg tptrseg)
2497 {
2498 struct timespec ts[2];
2499 struct file *fp;
2500 int error;
2501
2502 if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2503 return (error);
2504 if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0)
2505 return (error);
2506 error = setutimes(td, (struct vnode *)fp->f_data, ts, 2, tptr == NULL);
2507 fdrop(fp, td);
2508 return (error);
2509 }
2510
2511 /*
2512 * Truncate a file given its path name.
2513 */
2514 #ifndef _SYS_SYSPROTO_H_
2515 struct truncate_args {
2516 char *path;
2517 int pad;
2518 off_t length;
2519 };
2520 #endif
2521 /* ARGSUSED */
2522 int
2523 truncate(td, uap)
2524 struct thread *td;
2525 register struct truncate_args /* {
2526 char *path;
2527 int pad;
2528 off_t length;
2529 } */ *uap;
2530 {
2531
2532 return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length));
2533 }
2534
2535 int
2536 kern_truncate(struct thread *td, char *path, enum uio_seg pathseg, off_t length)
2537 {
2538 struct mount *mp;
2539 struct vnode *vp;
2540 struct vattr vattr;
2541 int error;
2542 struct nameidata nd;
2543
2544 if (length < 0)
2545 return(EINVAL);
2546 NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
2547 if ((error = namei(&nd)) != 0)
2548 return (error);
2549 vp = nd.ni_vp;
2550 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2551 vrele(vp);
2552 return (error);
2553 }
2554 NDFREE(&nd, NDF_ONLY_PNBUF);
2555 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2556 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2557 if (vp->v_type == VDIR)
2558 error = EISDIR;
2559 #ifdef MAC
2560 else if ((error = mac_check_vnode_write(td->td_ucred, NOCRED, vp))) {
2561 }
2562 #endif
2563 else if ((error = vn_writechk(vp)) == 0 &&
2564 (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) {
2565 VATTR_NULL(&vattr);
2566 vattr.va_size = length;
2567 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2568 }
2569 vput(vp);
2570 vn_finished_write(mp);
2571 return (error);
2572 }
2573
2574 /*
2575 * Truncate a file given a file descriptor.
2576 */
2577 #ifndef _SYS_SYSPROTO_H_
2578 struct ftruncate_args {
2579 int fd;
2580 int pad;
2581 off_t length;
2582 };
2583 #endif
2584 /* ARGSUSED */
2585 int
2586 ftruncate(td, uap)
2587 struct thread *td;
2588 register struct ftruncate_args /* {
2589 int fd;
2590 int pad;
2591 off_t length;
2592 } */ *uap;
2593 {
2594 struct mount *mp;
2595 struct vattr vattr;
2596 struct vnode *vp;
2597 struct file *fp;
2598 int error;
2599
2600 if (uap->length < 0)
2601 return(EINVAL);
2602 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2603 return (error);
2604 if ((fp->f_flag & FWRITE) == 0) {
2605 fdrop(fp, td);
2606 return (EINVAL);
2607 }
2608 vp = (struct vnode *)fp->f_data;
2609 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2610 fdrop(fp, td);
2611 return (error);
2612 }
2613 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2614 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2615 if (vp->v_type == VDIR)
2616 error = EISDIR;
2617 #ifdef MAC
2618 else if ((error = mac_check_vnode_write(td->td_ucred, fp->f_cred,
2619 vp))) {
2620 }
2621 #endif
2622 else if ((error = vn_writechk(vp)) == 0) {
2623 VATTR_NULL(&vattr);
2624 vattr.va_size = uap->length;
2625 error = VOP_SETATTR(vp, &vattr, fp->f_cred, td);
2626 }
2627 VOP_UNLOCK(vp, 0, td);
2628 vn_finished_write(mp);
2629 fdrop(fp, td);
2630 return (error);
2631 }
2632
2633 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2634 /*
2635 * Truncate a file given its path name.
2636 */
2637 #ifndef _SYS_SYSPROTO_H_
2638 struct otruncate_args {
2639 char *path;
2640 long length;
2641 };
2642 #endif
2643 /* ARGSUSED */
2644 int
2645 otruncate(td, uap)
2646 struct thread *td;
2647 register struct otruncate_args /* {
2648 char *path;
2649 long length;
2650 } */ *uap;
2651 {
2652 struct truncate_args /* {
2653 char *path;
2654 int pad;
2655 off_t length;
2656 } */ nuap;
2657
2658 nuap.path = uap->path;
2659 nuap.length = uap->length;
2660 return (truncate(td, &nuap));
2661 }
2662
2663 /*
2664 * Truncate a file given a file descriptor.
2665 */
2666 #ifndef _SYS_SYSPROTO_H_
2667 struct oftruncate_args {
2668 int fd;
2669 long length;
2670 };
2671 #endif
2672 /* ARGSUSED */
2673 int
2674 oftruncate(td, uap)
2675 struct thread *td;
2676 register struct oftruncate_args /* {
2677 int fd;
2678 long length;
2679 } */ *uap;
2680 {
2681 struct ftruncate_args /* {
2682 int fd;
2683 int pad;
2684 off_t length;
2685 } */ nuap;
2686
2687 nuap.fd = uap->fd;
2688 nuap.length = uap->length;
2689 return (ftruncate(td, &nuap));
2690 }
2691 #endif /* COMPAT_43 || COMPAT_SUNOS */
2692
2693 /*
2694 * Sync an open file.
2695 */
2696 #ifndef _SYS_SYSPROTO_H_
2697 struct fsync_args {
2698 int fd;
2699 };
2700 #endif
2701 /* ARGSUSED */
2702 int
2703 fsync(td, uap)
2704 struct thread *td;
2705 struct fsync_args /* {
2706 int fd;
2707 } */ *uap;
2708 {
2709 struct vnode *vp;
2710 struct mount *mp;
2711 struct file *fp;
2712 vm_object_t obj;
2713 int error;
2714
2715 GIANT_REQUIRED;
2716
2717 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2718 return (error);
2719 vp = (struct vnode *)fp->f_data;
2720 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2721 fdrop(fp, td);
2722 return (error);
2723 }
2724 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2725 if (VOP_GETVOBJECT(vp, &obj) == 0) {
2726 vm_object_page_clean(obj, 0, 0, 0);
2727 }
2728 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, td);
2729 if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP)
2730 && softdep_fsync_hook != NULL)
2731 error = (*softdep_fsync_hook)(vp);
2732
2733 VOP_UNLOCK(vp, 0, td);
2734 vn_finished_write(mp);
2735 fdrop(fp, td);
2736 return (error);
2737 }
2738
2739 /*
2740 * Rename files. Source and destination must either both be directories,
2741 * or both not be directories. If target is a directory, it must be empty.
2742 */
2743 #ifndef _SYS_SYSPROTO_H_
2744 struct rename_args {
2745 char *from;
2746 char *to;
2747 };
2748 #endif
2749 /* ARGSUSED */
2750 int
2751 rename(td, uap)
2752 struct thread *td;
2753 register struct rename_args /* {
2754 char *from;
2755 char *to;
2756 } */ *uap;
2757 {
2758
2759 return (kern_rename(td, uap->from, uap->to, UIO_USERSPACE));
2760 }
2761
2762 int
2763 kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg)
2764 {
2765 struct mount *mp = NULL;
2766 struct vnode *tvp, *fvp, *tdvp;
2767 struct nameidata fromnd, tond;
2768 int error;
2769
2770 bwillwrite();
2771 #ifdef MAC
2772 NDINIT(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART, pathseg,
2773 from, td);
2774 #else
2775 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, pathseg, from, td);
2776 #endif
2777 if ((error = namei(&fromnd)) != 0)
2778 return (error);
2779 #ifdef MAC
2780 error = mac_check_vnode_rename_from(td->td_ucred, fromnd.ni_dvp,
2781 fromnd.ni_vp, &fromnd.ni_cnd);
2782 VOP_UNLOCK(fromnd.ni_dvp, 0, td);
2783 VOP_UNLOCK(fromnd.ni_vp, 0, td);
2784 #endif
2785 fvp = fromnd.ni_vp;
2786 if (error == 0)
2787 error = vn_start_write(fvp, &mp, V_WAIT | PCATCH);
2788 if (error != 0) {
2789 NDFREE(&fromnd, NDF_ONLY_PNBUF);
2790 vrele(fromnd.ni_dvp);
2791 vrele(fvp);
2792 goto out1;
2793 }
2794 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART |
2795 NOOBJ, pathseg, to, td);
2796 if (fromnd.ni_vp->v_type == VDIR)
2797 tond.ni_cnd.cn_flags |= WILLBEDIR;
2798 if ((error = namei(&tond)) != 0) {
2799 /* Translate error code for rename("dir1", "dir2/."). */
2800 if (error == EISDIR && fvp->v_type == VDIR)
2801 error = EINVAL;
2802 NDFREE(&fromnd, NDF_ONLY_PNBUF);
2803 vrele(fromnd.ni_dvp);
2804 vrele(fvp);
2805 goto out1;
2806 }
2807 tdvp = tond.ni_dvp;
2808 tvp = tond.ni_vp;
2809 if (tvp != NULL) {
2810 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2811 error = ENOTDIR;
2812 goto out;
2813 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2814 error = EISDIR;
2815 goto out;
2816 }
2817 }
2818 if (fvp == tdvp)
2819 error = EINVAL;
2820 /*
2821 * If the source is the same as the destination (that is, if they
2822 * are links to the same vnode), then there is nothing to do.
2823 */
2824 if (fvp == tvp)
2825 error = -1;
2826 #ifdef MAC
2827 else
2828 error = mac_check_vnode_rename_to(td->td_ucred, tdvp,
2829 tond.ni_vp, fromnd.ni_dvp == tdvp, &tond.ni_cnd);
2830 #endif
2831 out:
2832 if (!error) {
2833 VOP_LEASE(tdvp, td, td->td_ucred, LEASE_WRITE);
2834 if (fromnd.ni_dvp != tdvp) {
2835 VOP_LEASE(fromnd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
2836 }
2837 if (tvp) {
2838 VOP_LEASE(tvp, td, td->td_ucred, LEASE_WRITE);
2839 }
2840 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2841 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2842 NDFREE(&fromnd, NDF_ONLY_PNBUF);
2843 NDFREE(&tond, NDF_ONLY_PNBUF);
2844 } else {
2845 NDFREE(&fromnd, NDF_ONLY_PNBUF);
2846 NDFREE(&tond, NDF_ONLY_PNBUF);
2847 if (tdvp == tvp)
2848 vrele(tdvp);
2849 else
2850 vput(tdvp);
2851 if (tvp)
2852 vput(tvp);
2853 vrele(fromnd.ni_dvp);
2854 vrele(fvp);
2855 }
2856 vrele(tond.ni_startdir);
2857 ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename");
2858 ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename");
2859 ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename");
2860 ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename");
2861 out1:
2862 vn_finished_write(mp);
2863 if (fromnd.ni_startdir)
2864 vrele(fromnd.ni_startdir);
2865 if (error == -1)
2866 return (0);
2867 return (error);
2868 }
2869
2870 /*
2871 * Make a directory file.
2872 */
2873 #ifndef _SYS_SYSPROTO_H_
2874 struct mkdir_args {
2875 char *path;
2876 int mode;
2877 };
2878 #endif
2879 /* ARGSUSED */
2880 int
2881 mkdir(td, uap)
2882 struct thread *td;
2883 register struct mkdir_args /* {
2884 char *path;
2885 int mode;
2886 } */ *uap;
2887 {
2888
2889 return (kern_mkdir(td, uap->path, UIO_USERSPACE, uap->mode));
2890 }
2891
2892 int
2893 kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode)
2894 {
2895 struct mount *mp;
2896 struct vnode *vp;
2897 struct vattr vattr;
2898 int error;
2899 struct nameidata nd;
2900
2901 restart:
2902 bwillwrite();
2903 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, segflg, path, td);
2904 nd.ni_cnd.cn_flags |= WILLBEDIR;
2905 if ((error = namei(&nd)) != 0)
2906 return (error);
2907 vp = nd.ni_vp;
2908 if (vp != NULL) {
2909 NDFREE(&nd, NDF_ONLY_PNBUF);
2910 vrele(vp);
2911 /*
2912 * XXX namei called with LOCKPARENT but not LOCKLEAF has
2913 * the strange behaviour of leaving the vnode unlocked
2914 * if the target is the same vnode as the parent.
2915 */
2916 if (vp == nd.ni_dvp)
2917 vrele(nd.ni_dvp);
2918 else
2919 vput(nd.ni_dvp);
2920 return (EEXIST);
2921 }
2922 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
2923 NDFREE(&nd, NDF_ONLY_PNBUF);
2924 vput(nd.ni_dvp);
2925 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
2926 return (error);
2927 goto restart;
2928 }
2929 VATTR_NULL(&vattr);
2930 vattr.va_type = VDIR;
2931 FILEDESC_LOCK(td->td_proc->p_fd);
2932 vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask;
2933 FILEDESC_UNLOCK(td->td_proc->p_fd);
2934 #ifdef MAC
2935 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
2936 &vattr);
2937 if (error)
2938 goto out;
2939 #endif
2940 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
2941 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
2942 #ifdef MAC
2943 out:
2944 #endif
2945 NDFREE(&nd, NDF_ONLY_PNBUF);
2946 vput(nd.ni_dvp);
2947 if (!error)
2948 vput(nd.ni_vp);
2949 vn_finished_write(mp);
2950 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir");
2951 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir");
2952 return (error);
2953 }
2954
2955 /*
2956 * Remove a directory file.
2957 */
2958 #ifndef _SYS_SYSPROTO_H_
2959 struct rmdir_args {
2960 char *path;
2961 };
2962 #endif
2963 /* ARGSUSED */
2964 int
2965 rmdir(td, uap)
2966 struct thread *td;
2967 struct rmdir_args /* {
2968 char *path;
2969 } */ *uap;
2970 {
2971
2972 return (kern_rmdir(td, uap->path, UIO_USERSPACE));
2973 }
2974
2975 int
2976 kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg)
2977 {
2978 struct mount *mp;
2979 struct vnode *vp;
2980 int error;
2981 struct nameidata nd;
2982
2983 restart:
2984 bwillwrite();
2985 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, pathseg, path, td);
2986 if ((error = namei(&nd)) != 0)
2987 return (error);
2988 vp = nd.ni_vp;
2989 if (vp->v_type != VDIR) {
2990 error = ENOTDIR;
2991 goto out;
2992 }
2993 /*
2994 * No rmdir "." please.
2995 */
2996 if (nd.ni_dvp == vp) {
2997 error = EINVAL;
2998 goto out;
2999 }
3000 /*
3001 * The root of a mounted filesystem cannot be deleted.
3002 */
3003 if (vp->v_vflag & VV_ROOT) {
3004 error = EBUSY;
3005 goto out;
3006 }
3007 #ifdef MAC
3008 error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp,
3009 &nd.ni_cnd);
3010 if (error)
3011 goto out;
3012 #endif
3013 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3014 NDFREE(&nd, NDF_ONLY_PNBUF);
3015 if (nd.ni_dvp == vp)
3016 vrele(nd.ni_dvp);
3017 else
3018 vput(nd.ni_dvp);
3019 vput(vp);
3020 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3021 return (error);
3022 goto restart;
3023 }
3024 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3025 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3026 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
3027 vn_finished_write(mp);
3028 out:
3029 NDFREE(&nd, NDF_ONLY_PNBUF);
3030 if (nd.ni_dvp == vp)
3031 vrele(nd.ni_dvp);
3032 else
3033 vput(nd.ni_dvp);
3034 vput(vp);
3035 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir");
3036 ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir");
3037 return (error);
3038 }
3039
3040 #ifdef COMPAT_43
3041 /*
3042 * Read a block of directory entries in a filesystem independent format.
3043 */
3044 #ifndef _SYS_SYSPROTO_H_
3045 struct ogetdirentries_args {
3046 int fd;
3047 char *buf;
3048 u_int count;
3049 long *basep;
3050 };
3051 #endif
3052 int
3053 ogetdirentries(td, uap)
3054 struct thread *td;
3055 register struct ogetdirentries_args /* {
3056 int fd;
3057 char *buf;
3058 u_int count;
3059 long *basep;
3060 } */ *uap;
3061 {
3062 struct vnode *vp;
3063 struct file *fp;
3064 struct uio auio, kuio;
3065 struct iovec aiov, kiov;
3066 struct dirent *dp, *edp;
3067 caddr_t dirbuf;
3068 int error, eofflag, readcnt;
3069 long loff;
3070
3071 /* XXX arbitrary sanity limit on `count'. */
3072 if (uap->count > 64 * 1024)
3073 return (EINVAL);
3074 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3075 return (error);
3076 if ((fp->f_flag & FREAD) == 0) {
3077 fdrop(fp, td);
3078 return (EBADF);
3079 }
3080 vp = (struct vnode *)fp->f_data;
3081 unionread:
3082 if (vp->v_type != VDIR) {
3083 fdrop(fp, td);
3084 return (EINVAL);
3085 }
3086 aiov.iov_base = uap->buf;
3087 aiov.iov_len = uap->count;
3088 auio.uio_iov = &aiov;
3089 auio.uio_iovcnt = 1;
3090 auio.uio_rw = UIO_READ;
3091 auio.uio_segflg = UIO_USERSPACE;
3092 auio.uio_td = td;
3093 auio.uio_resid = uap->count;
3094 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3095 loff = auio.uio_offset = fp->f_offset;
3096 #ifdef MAC
3097 error = mac_check_vnode_readdir(td->td_ucred, vp);
3098 if (error) {
3099 VOP_UNLOCK(vp, 0, td);
3100 fdrop(fp, td);
3101 return (error);
3102 }
3103 #endif
3104 # if (BYTE_ORDER != LITTLE_ENDIAN)
3105 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
3106 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
3107 NULL, NULL);
3108 fp->f_offset = auio.uio_offset;
3109 } else
3110 # endif
3111 {
3112 kuio = auio;
3113 kuio.uio_iov = &kiov;
3114 kuio.uio_segflg = UIO_SYSSPACE;
3115 kiov.iov_len = uap->count;
3116 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
3117 kiov.iov_base = dirbuf;
3118 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
3119 NULL, NULL);
3120 fp->f_offset = kuio.uio_offset;
3121 if (error == 0) {
3122 readcnt = uap->count - kuio.uio_resid;
3123 edp = (struct dirent *)&dirbuf[readcnt];
3124 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
3125 # if (BYTE_ORDER == LITTLE_ENDIAN)
3126 /*
3127 * The expected low byte of
3128 * dp->d_namlen is our dp->d_type.
3129 * The high MBZ byte of dp->d_namlen
3130 * is our dp->d_namlen.
3131 */
3132 dp->d_type = dp->d_namlen;
3133 dp->d_namlen = 0;
3134 # else
3135 /*
3136 * The dp->d_type is the high byte
3137 * of the expected dp->d_namlen,
3138 * so must be zero'ed.
3139 */
3140 dp->d_type = 0;
3141 # endif
3142 if (dp->d_reclen > 0) {
3143 dp = (struct dirent *)
3144 ((char *)dp + dp->d_reclen);
3145 } else {
3146 error = EIO;
3147 break;
3148 }
3149 }
3150 if (dp >= edp)
3151 error = uiomove(dirbuf, readcnt, &auio);
3152 }
3153 FREE(dirbuf, M_TEMP);
3154 }
3155 VOP_UNLOCK(vp, 0, td);
3156 if (error) {
3157 fdrop(fp, td);
3158 return (error);
3159 }
3160 if (uap->count == auio.uio_resid) {
3161 if (union_dircheckp) {
3162 error = union_dircheckp(td, &vp, fp);
3163 if (error == -1)
3164 goto unionread;
3165 if (error) {
3166 fdrop(fp, td);
3167 return (error);
3168 }
3169 }
3170 /*
3171 * XXX We could delay dropping the lock above but
3172 * union_dircheckp complicates things.
3173 */
3174 vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, td);
3175 if ((vp->v_vflag & VV_ROOT) &&
3176 (vp->v_mount->mnt_flag & MNT_UNION)) {
3177 struct vnode *tvp = vp;
3178 vp = vp->v_mount->mnt_vnodecovered;
3179 VREF(vp);
3180 fp->f_data = vp;
3181 fp->f_offset = 0;
3182 vput(tvp);
3183 goto unionread;
3184 }
3185 VOP_UNLOCK(vp, 0, td);
3186 }
3187 error = copyout(&loff, uap->basep, sizeof(long));
3188 fdrop(fp, td);
3189 td->td_retval[0] = uap->count - auio.uio_resid;
3190 return (error);
3191 }
3192 #endif /* COMPAT_43 */
3193
3194 /*
3195 * Read a block of directory entries in a filesystem independent format.
3196 */
3197 #ifndef _SYS_SYSPROTO_H_
3198 struct getdirentries_args {
3199 int fd;
3200 char *buf;
3201 u_int count;
3202 long *basep;
3203 };
3204 #endif
3205 int
3206 getdirentries(td, uap)
3207 struct thread *td;
3208 register struct getdirentries_args /* {
3209 int fd;
3210 char *buf;
3211 u_int count;
3212 long *basep;
3213 } */ *uap;
3214 {
3215 struct vnode *vp;
3216 struct file *fp;
3217 struct uio auio;
3218 struct iovec aiov;
3219 long loff;
3220 int error, eofflag;
3221
3222 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3223 return (error);
3224 if ((fp->f_flag & FREAD) == 0) {
3225 fdrop(fp, td);
3226 return (EBADF);
3227 }
3228 vp = (struct vnode *)fp->f_data;
3229 unionread:
3230 if (vp->v_type != VDIR) {
3231 fdrop(fp, td);
3232 return (EINVAL);
3233 }
3234 aiov.iov_base = uap->buf;
3235 aiov.iov_len = uap->count;
3236 auio.uio_iov = &aiov;
3237 auio.uio_iovcnt = 1;
3238 auio.uio_rw = UIO_READ;
3239 auio.uio_segflg = UIO_USERSPACE;
3240 auio.uio_td = td;
3241 auio.uio_resid = uap->count;
3242 /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */
3243 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3244 loff = auio.uio_offset = fp->f_offset;
3245 #ifdef MAC
3246 error = mac_check_vnode_readdir(td->td_ucred, vp);
3247 if (error == 0)
3248 #endif
3249 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL,
3250 NULL);
3251 fp->f_offset = auio.uio_offset;
3252 VOP_UNLOCK(vp, 0, td);
3253 if (error) {
3254 fdrop(fp, td);
3255 return (error);
3256 }
3257 if (uap->count == auio.uio_resid) {
3258 if (union_dircheckp) {
3259 error = union_dircheckp(td, &vp, fp);
3260 if (error == -1)
3261 goto unionread;
3262 if (error) {
3263 fdrop(fp, td);
3264 return (error);
3265 }
3266 }
3267 /*
3268 * XXX We could delay dropping the lock above but
3269 * union_dircheckp complicates things.
3270 */
3271 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3272 if ((vp->v_vflag & VV_ROOT) &&
3273 (vp->v_mount->mnt_flag & MNT_UNION)) {
3274 struct vnode *tvp = vp;
3275 vp = vp->v_mount->mnt_vnodecovered;
3276 VREF(vp);
3277 fp->f_data = vp;
3278 fp->f_offset = 0;
3279 vput(tvp);
3280 goto unionread;
3281 }
3282 VOP_UNLOCK(vp, 0, td);
3283 }
3284 if (uap->basep != NULL) {
3285 error = copyout(&loff, uap->basep, sizeof(long));
3286 }
3287 td->td_retval[0] = uap->count - auio.uio_resid;
3288 fdrop(fp, td);
3289 return (error);
3290 }
3291 #ifndef _SYS_SYSPROTO_H_
3292 struct getdents_args {
3293 int fd;
3294 char *buf;
3295 size_t count;
3296 };
3297 #endif
3298 int
3299 getdents(td, uap)
3300 struct thread *td;
3301 register struct getdents_args /* {
3302 int fd;
3303 char *buf;
3304 u_int count;
3305 } */ *uap;
3306 {
3307 struct getdirentries_args ap;
3308 ap.fd = uap->fd;
3309 ap.buf = uap->buf;
3310 ap.count = uap->count;
3311 ap.basep = NULL;
3312 return getdirentries(td, &ap);
3313 }
3314
3315 /*
3316 * Set the mode mask for creation of filesystem nodes.
3317 *
3318 * MP SAFE
3319 */
3320 #ifndef _SYS_SYSPROTO_H_
3321 struct umask_args {
3322 int newmask;
3323 };
3324 #endif
3325 int
3326 umask(td, uap)
3327 struct thread *td;
3328 struct umask_args /* {
3329 int newmask;
3330 } */ *uap;
3331 {
3332 register struct filedesc *fdp;
3333
3334 FILEDESC_LOCK(td->td_proc->p_fd);
3335 fdp = td->td_proc->p_fd;
3336 td->td_retval[0] = fdp->fd_cmask;
3337 fdp->fd_cmask = uap->newmask & ALLPERMS;
3338 FILEDESC_UNLOCK(td->td_proc->p_fd);
3339 return (0);
3340 }
3341
3342 /*
3343 * Void all references to file by ripping underlying filesystem
3344 * away from vnode.
3345 */
3346 #ifndef _SYS_SYSPROTO_H_
3347 struct revoke_args {
3348 char *path;
3349 };
3350 #endif
3351 /* ARGSUSED */
3352 int
3353 revoke(td, uap)
3354 struct thread *td;
3355 register struct revoke_args /* {
3356 char *path;
3357 } */ *uap;
3358 {
3359 struct mount *mp;
3360 struct vnode *vp;
3361 struct vattr vattr;
3362 int error;
3363 struct nameidata nd;
3364
3365 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path,
3366 td);
3367 if ((error = namei(&nd)) != 0)
3368 return (error);
3369 vp = nd.ni_vp;
3370 NDFREE(&nd, NDF_ONLY_PNBUF);
3371 if (vp->v_type != VCHR) {
3372 vput(vp);
3373 return (EINVAL);
3374 }
3375 #ifdef MAC
3376 error = mac_check_vnode_revoke(td->td_ucred, vp);
3377 if (error) {
3378 vput(vp);
3379 return (error);
3380 }
3381 #endif
3382 error = VOP_GETATTR(vp, &vattr, td->td_ucred, td);
3383 if (error) {
3384 vput(vp);
3385 return (error);
3386 }
3387 VOP_UNLOCK(vp, 0, td);
3388 if (td->td_ucred->cr_uid != vattr.va_uid) {
3389 error = suser_cred(td->td_ucred, PRISON_ROOT);
3390 if (error)
3391 goto out;
3392 }
3393 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3394 goto out;
3395 if (vcount(vp) > 1)
3396 VOP_REVOKE(vp, REVOKEALL);
3397 vn_finished_write(mp);
3398 out:
3399 vrele(vp);
3400 return (error);
3401 }
3402
3403 /*
3404 * Convert a user file descriptor to a kernel file entry.
3405 * The file entry is locked upon returning.
3406 */
3407 int
3408 getvnode(fdp, fd, fpp)
3409 struct filedesc *fdp;
3410 int fd;
3411 struct file **fpp;
3412 {
3413 int error;
3414 struct file *fp;
3415
3416 fp = NULL;
3417 if (fdp == NULL)
3418 error = EBADF;
3419 else {
3420 FILEDESC_LOCK(fdp);
3421 if ((u_int)fd >= fdp->fd_nfiles ||
3422 (fp = fdp->fd_ofiles[fd]) == NULL)
3423 error = EBADF;
3424 else if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) {
3425 fp = NULL;
3426 error = EINVAL;
3427 } else {
3428 fhold(fp);
3429 error = 0;
3430 }
3431 FILEDESC_UNLOCK(fdp);
3432 }
3433 *fpp = fp;
3434 return (error);
3435 }
3436 /*
3437 * Get (NFS) file handle
3438 */
3439 #ifndef _SYS_SYSPROTO_H_
3440 struct getfh_args {
3441 char *fname;
3442 fhandle_t *fhp;
3443 };
3444 #endif
3445 int
3446 getfh(td, uap)
3447 struct thread *td;
3448 register struct getfh_args *uap;
3449 {
3450 struct nameidata nd;
3451 fhandle_t fh;
3452 register struct vnode *vp;
3453 int error;
3454
3455 /*
3456 * Must be super user
3457 */
3458 error = suser(td);
3459 if (error)
3460 return (error);
3461 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, td);
3462 error = namei(&nd);
3463 if (error)
3464 return (error);
3465 NDFREE(&nd, NDF_ONLY_PNBUF);
3466 vp = nd.ni_vp;
3467 bzero(&fh, sizeof(fh));
3468 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
3469 error = VFS_VPTOFH(vp, &fh.fh_fid);
3470 vput(vp);
3471 if (error)
3472 return (error);
3473 error = copyout(&fh, uap->fhp, sizeof (fh));
3474 return (error);
3475 }
3476
3477 /*
3478 * syscall for the rpc.lockd to use to translate a NFS file handle into
3479 * an open descriptor.
3480 *
3481 * warning: do not remove the suser() call or this becomes one giant
3482 * security hole.
3483 */
3484 #ifndef _SYS_SYSPROTO_H_
3485 struct fhopen_args {
3486 const struct fhandle *u_fhp;
3487 int flags;
3488 };
3489 #endif
3490 int
3491 fhopen(td, uap)
3492 struct thread *td;
3493 struct fhopen_args /* {
3494 const struct fhandle *u_fhp;
3495 int flags;
3496 } */ *uap;
3497 {
3498 struct proc *p = td->td_proc;
3499 struct mount *mp;
3500 struct vnode *vp;
3501 struct fhandle fhp;
3502 struct vattr vat;
3503 struct vattr *vap = &vat;
3504 struct flock lf;
3505 struct file *fp;
3506 register struct filedesc *fdp = p->p_fd;
3507 int fmode, mode, error, type;
3508 struct file *nfp;
3509 int indx;
3510
3511 /*
3512 * Must be super user
3513 */
3514 error = suser(td);
3515 if (error)
3516 return (error);
3517
3518 fmode = FFLAGS(uap->flags);
3519 /* why not allow a non-read/write open for our lockd? */
3520 if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
3521 return (EINVAL);
3522 error = copyin(uap->u_fhp, &fhp, sizeof(fhp));
3523 if (error)
3524 return(error);
3525 /* find the mount point */
3526 mp = vfs_getvfs(&fhp.fh_fsid);
3527 if (mp == NULL)
3528 return (ESTALE);
3529 /* now give me my vnode, it gets returned to me locked */
3530 error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
3531 if (error)
3532 return (error);
3533 /*
3534 * from now on we have to make sure not
3535 * to forget about the vnode
3536 * any error that causes an abort must vput(vp)
3537 * just set error = err and 'goto bad;'.
3538 */
3539
3540 /*
3541 * from vn_open
3542 */
3543 if (vp->v_type == VLNK) {
3544 error = EMLINK;
3545 goto bad;
3546 }
3547 if (vp->v_type == VSOCK) {
3548 error = EOPNOTSUPP;
3549 goto bad;
3550 }
3551 mode = 0;
3552 if (fmode & (FWRITE | O_TRUNC)) {
3553 if (vp->v_type == VDIR) {
3554 error = EISDIR;
3555 goto bad;
3556 }
3557 error = vn_writechk(vp);
3558 if (error)
3559 goto bad;
3560 mode |= VWRITE;
3561 }
3562 if (fmode & FREAD)
3563 mode |= VREAD;
3564 if (fmode & O_APPEND)
3565 mode |= VAPPEND;
3566 #ifdef MAC
3567 error = mac_check_vnode_open(td->td_ucred, vp, mode);
3568 if (error)
3569 goto bad;
3570 #endif
3571 if (mode) {
3572 error = VOP_ACCESS(vp, mode, td->td_ucred, td);
3573 if (error)
3574 goto bad;
3575 }
3576 if (fmode & O_TRUNC) {
3577 VOP_UNLOCK(vp, 0, td); /* XXX */
3578 if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) {
3579 vrele(vp);
3580 return (error);
3581 }
3582 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3583 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */
3584 #ifdef MAC
3585 /*
3586 * We don't yet have fp->f_cred, so use td->td_ucred, which
3587 * should be right.
3588 */
3589 error = mac_check_vnode_write(td->td_ucred, td->td_ucred, vp);
3590 if (error == 0) {
3591 #endif
3592 VATTR_NULL(vap);
3593 vap->va_size = 0;
3594 error = VOP_SETATTR(vp, vap, td->td_ucred, td);
3595 #ifdef MAC
3596 }
3597 #endif
3598 vn_finished_write(mp);
3599 if (error)
3600 goto bad;
3601 }
3602 error = VOP_OPEN(vp, fmode, td->td_ucred, td);
3603 if (error)
3604 goto bad;
3605 /*
3606 * Make sure that a VM object is created for VMIO support.
3607 */
3608 if (vn_canvmio(vp) == TRUE) {
3609 if ((error = vfs_object_create(vp, td, td->td_ucred)) != 0)
3610 goto bad;
3611 }
3612 if (fmode & FWRITE)
3613 vp->v_writecount++;
3614
3615 /*
3616 * end of vn_open code
3617 */
3618
3619 if ((error = falloc(td, &nfp, &indx)) != 0) {
3620 if (fmode & FWRITE)
3621 vp->v_writecount--;
3622 goto bad;
3623 }
3624 fp = nfp;
3625
3626 /*
3627 * Hold an extra reference to avoid having fp ripped out
3628 * from under us while we block in the lock op
3629 */
3630 fhold(fp);
3631 nfp->f_data = vp;
3632 nfp->f_flag = fmode & FMASK;
3633 nfp->f_ops = &vnops;
3634 nfp->f_type = DTYPE_VNODE;
3635 if (fmode & (O_EXLOCK | O_SHLOCK)) {
3636 lf.l_whence = SEEK_SET;
3637 lf.l_start = 0;
3638 lf.l_len = 0;
3639 if (fmode & O_EXLOCK)
3640 lf.l_type = F_WRLCK;
3641 else
3642 lf.l_type = F_RDLCK;
3643 type = F_FLOCK;
3644 if ((fmode & FNONBLOCK) == 0)
3645 type |= F_WAIT;
3646 VOP_UNLOCK(vp, 0, td);
3647 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
3648 type)) != 0) {
3649 /*
3650 * The lock request failed. Normally close the
3651 * descriptor but handle the case where someone might
3652 * have dup()d or close()d it when we weren't looking.
3653 */
3654 FILEDESC_LOCK(fdp);
3655 if (fdp->fd_ofiles[indx] == fp) {
3656 fdp->fd_ofiles[indx] = NULL;
3657 FILEDESC_UNLOCK(fdp);
3658 fdrop(fp, td);
3659 } else
3660 FILEDESC_UNLOCK(fdp);
3661 /*
3662 * release our private reference
3663 */
3664 fdrop(fp, td);
3665 return(error);
3666 }
3667 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3668 fp->f_flag |= FHASLOCK;
3669 }
3670 if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0))
3671 vfs_object_create(vp, td, td->td_ucred);
3672
3673 VOP_UNLOCK(vp, 0, td);
3674 fdrop(fp, td);
3675 td->td_retval[0] = indx;
3676 return (0);
3677
3678 bad:
3679 vput(vp);
3680 return (error);
3681 }
3682
3683 /*
3684 * Stat an (NFS) file handle.
3685 */
3686 #ifndef _SYS_SYSPROTO_H_
3687 struct fhstat_args {
3688 struct fhandle *u_fhp;
3689 struct stat *sb;
3690 };
3691 #endif
3692 int
3693 fhstat(td, uap)
3694 struct thread *td;
3695 register struct fhstat_args /* {
3696 struct fhandle *u_fhp;
3697 struct stat *sb;
3698 } */ *uap;
3699 {
3700 struct stat sb;
3701 fhandle_t fh;
3702 struct mount *mp;
3703 struct vnode *vp;
3704 int error;
3705
3706 /*
3707 * Must be super user
3708 */
3709 error = suser(td);
3710 if (error)
3711 return (error);
3712
3713 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
3714 if (error)
3715 return (error);
3716
3717 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3718 return (ESTALE);
3719 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3720 return (error);
3721 error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
3722 vput(vp);
3723 if (error)
3724 return (error);
3725 error = copyout(&sb, uap->sb, sizeof(sb));
3726 return (error);
3727 }
3728
3729 /*
3730 * Implement fstatfs() for (NFS) file handles.
3731 */
3732 #ifndef _SYS_SYSPROTO_H_
3733 struct fhstatfs_args {
3734 struct fhandle *u_fhp;
3735 struct statfs *buf;
3736 };
3737 #endif
3738 int
3739 fhstatfs(td, uap)
3740 struct thread *td;
3741 struct fhstatfs_args /* {
3742 struct fhandle *u_fhp;
3743 struct statfs *buf;
3744 } */ *uap;
3745 {
3746 struct statfs *sp;
3747 struct mount *mp;
3748 struct vnode *vp;
3749 struct statfs sb;
3750 fhandle_t fh;
3751 int error;
3752
3753 /*
3754 * Must be super user
3755 */
3756 error = suser(td);
3757 if (error)
3758 return (error);
3759
3760 if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
3761 return (error);
3762
3763 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3764 return (ESTALE);
3765 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3766 return (error);
3767 mp = vp->v_mount;
3768 sp = &mp->mnt_stat;
3769 vput(vp);
3770 #ifdef MAC
3771 error = mac_check_mount_stat(td->td_ucred, mp);
3772 if (error)
3773 return (error);
3774 #endif
3775 if ((error = VFS_STATFS(mp, sp, td)) != 0)
3776 return (error);
3777 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
3778 if (suser(td)) {
3779 bcopy(sp, &sb, sizeof(sb));
3780 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
3781 sp = &sb;
3782 }
3783 return (copyout(sp, uap->buf, sizeof(*sp)));
3784 }
3785
3786 /*
3787 * Syscall to push extended attribute configuration information into the
3788 * VFS. Accepts a path, which it converts to a mountpoint, as well as
3789 * a command (int cmd), and attribute name and misc data. For now, the
3790 * attribute name is left in userspace for consumption by the VFS_op.
3791 * It will probably be changed to be copied into sysspace by the
3792 * syscall in the future, once issues with various consumers of the
3793 * attribute code have raised their hands.
3794 *
3795 * Currently this is used only by UFS Extended Attributes.
3796 */
3797 int
3798 extattrctl(td, uap)
3799 struct thread *td;
3800 struct extattrctl_args /* {
3801 const char *path;
3802 int cmd;
3803 const char *filename;
3804 int attrnamespace;
3805 const char *attrname;
3806 } */ *uap;
3807 {
3808 struct vnode *filename_vp;
3809 struct nameidata nd;
3810 struct mount *mp, *mp_writable;
3811 char attrname[EXTATTR_MAXNAMELEN];
3812 int error;
3813
3814 /*
3815 * uap->attrname is not always defined. We check again later when we
3816 * invoke the VFS call so as to pass in NULL there if needed.
3817 */
3818 if (uap->attrname != NULL) {
3819 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN,
3820 NULL);
3821 if (error)
3822 return (error);
3823 }
3824
3825 /*
3826 * uap->filename is not always defined. If it is, grab a vnode lock,
3827 * which VFS_EXTATTRCTL() will later release.
3828 */
3829 filename_vp = NULL;
3830 if (uap->filename != NULL) {
3831 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
3832 uap->filename, td);
3833 error = namei(&nd);
3834 if (error)
3835 return (error);
3836 filename_vp = nd.ni_vp;
3837 NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK);
3838 }
3839
3840 /* uap->path is always defined. */
3841 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
3842 error = namei(&nd);
3843 if (error) {
3844 if (filename_vp != NULL)
3845 vput(filename_vp);
3846 return (error);
3847 }
3848 mp = nd.ni_vp->v_mount;
3849 error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
3850 NDFREE(&nd, 0);
3851 if (error) {
3852 if (filename_vp != NULL)
3853 vput(filename_vp);
3854 return (error);
3855 }
3856
3857 error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, uap->attrnamespace,
3858 uap->attrname != NULL ? attrname : NULL, td);
3859
3860 vn_finished_write(mp_writable);
3861 /*
3862 * VFS_EXTATTRCTL will have unlocked, but not de-ref'd,
3863 * filename_vp, so vrele it if it is defined.
3864 */
3865 if (filename_vp != NULL)
3866 vrele(filename_vp);
3867 return (error);
3868 }
3869
3870 /*-
3871 * Set a named extended attribute on a file or directory
3872 *
3873 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
3874 * kernelspace string pointer "attrname", userspace buffer
3875 * pointer "data", buffer length "nbytes", thread "td".
3876 * Returns: 0 on success, an error number otherwise
3877 * Locks: none
3878 * References: vp must be a valid reference for the duration of the call
3879 */
3880 static int
3881 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
3882 void *data, size_t nbytes, struct thread *td)
3883 {
3884 struct mount *mp;
3885 struct uio auio;
3886 struct iovec aiov;
3887 ssize_t cnt;
3888 int error;
3889
3890 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3891 if (error)
3892 return (error);
3893 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3894 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3895
3896 aiov.iov_base = data;
3897 aiov.iov_len = nbytes;
3898 auio.uio_iov = &aiov;
3899 auio.uio_iovcnt = 1;
3900 auio.uio_offset = 0;
3901 if (nbytes > INT_MAX) {
3902 error = EINVAL;
3903 goto done;
3904 }
3905 auio.uio_resid = nbytes;
3906 auio.uio_rw = UIO_WRITE;
3907 auio.uio_segflg = UIO_USERSPACE;
3908 auio.uio_td = td;
3909 cnt = nbytes;
3910
3911 #ifdef MAC
3912 error = mac_check_vnode_setextattr(td->td_ucred, vp, attrnamespace,
3913 attrname, &auio);
3914 if (error)
3915 goto done;
3916 #endif
3917
3918 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
3919 td->td_ucred, td);
3920 cnt -= auio.uio_resid;
3921 td->td_retval[0] = cnt;
3922
3923 done:
3924 VOP_UNLOCK(vp, 0, td);
3925 vn_finished_write(mp);
3926 return (error);
3927 }
3928
3929 int
3930 extattr_set_fd(td, uap)
3931 struct thread *td;
3932 struct extattr_set_fd_args /* {
3933 int fd;
3934 int attrnamespace;
3935 const char *attrname;
3936 void *data;
3937 size_t nbytes;
3938 } */ *uap;
3939 {
3940 struct file *fp;
3941 char attrname[EXTATTR_MAXNAMELEN];
3942 int error;
3943
3944 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
3945 if (error)
3946 return (error);
3947
3948 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
3949 if (error)
3950 return (error);
3951
3952 error = extattr_set_vp((struct vnode *)fp->f_data, uap->attrnamespace,
3953 attrname, uap->data, uap->nbytes, td);
3954 fdrop(fp, td);
3955
3956 return (error);
3957 }
3958
3959 int
3960 extattr_set_file(td, uap)
3961 struct thread *td;
3962 struct extattr_set_file_args /* {
3963 const char *path;
3964 int attrnamespace;
3965 const char *attrname;
3966 void *data;
3967 size_t nbytes;
3968 } */ *uap;
3969 {
3970 struct nameidata nd;
3971 char attrname[EXTATTR_MAXNAMELEN];
3972 int error;
3973
3974 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
3975 if (error)
3976 return (error);
3977
3978 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
3979 error = namei(&nd);
3980 if (error)
3981 return (error);
3982 NDFREE(&nd, NDF_ONLY_PNBUF);
3983
3984 error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
3985 uap->data, uap->nbytes, td);
3986
3987 vrele(nd.ni_vp);
3988 return (error);
3989 }
3990
3991 int
3992 extattr_set_link(td, uap)
3993 struct thread *td;
3994 struct extattr_set_link_args /* {
3995 const char *path;
3996 int attrnamespace;
3997 const char *attrname;
3998 void *data;
3999 size_t nbytes;
4000 } */ *uap;
4001 {
4002 struct nameidata nd;
4003 char attrname[EXTATTR_MAXNAMELEN];
4004 int error;
4005
4006 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4007 if (error)
4008 return (error);
4009
4010 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
4011 error = namei(&nd);
4012 if (error)
4013 return (error);
4014 NDFREE(&nd, NDF_ONLY_PNBUF);
4015
4016 error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
4017 uap->data, uap->nbytes, td);
4018
4019 vrele(nd.ni_vp);
4020 return (error);
4021 }
4022
4023 /*-
4024 * Get a named extended attribute on a file or directory
4025 *
4026 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4027 * kernelspace string pointer "attrname", userspace buffer
4028 * pointer "data", buffer length "nbytes", thread "td".
4029 * Returns: 0 on success, an error number otherwise
4030 * Locks: none
4031 * References: vp must be a valid reference for the duration of the call
4032 */
4033 static int
4034 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4035 void *data, size_t nbytes, struct thread *td)
4036 {
4037 struct uio auio, *auiop;
4038 struct iovec aiov;
4039 ssize_t cnt;
4040 size_t size, *sizep;
4041 int error;
4042
4043 VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
4044 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4045
4046 /*
4047 * Slightly unusual semantics: if the user provides a NULL data
4048 * pointer, they don't want to receive the data, just the
4049 * maximum read length.
4050 */
4051 auiop = NULL;
4052 sizep = NULL;
4053 cnt = 0;
4054 if (data != NULL) {
4055 aiov.iov_base = data;
4056 aiov.iov_len = nbytes;
4057 auio.uio_iov = &aiov;
4058 auio.uio_offset = 0;
4059 if (nbytes > INT_MAX) {
4060 error = EINVAL;
4061 goto done;
4062 }
4063 auio.uio_resid = nbytes;
4064 auio.uio_rw = UIO_READ;
4065 auio.uio_segflg = UIO_USERSPACE;
4066 auio.uio_td = td;
4067 auiop = &auio;
4068 cnt = nbytes;
4069 } else
4070 sizep = &size;
4071
4072 #ifdef MAC
4073 error = mac_check_vnode_getextattr(td->td_ucred, vp, attrnamespace,
4074 attrname, &auio);
4075 if (error)
4076 goto done;
4077 #endif
4078
4079 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
4080 td->td_ucred, td);
4081
4082 if (auiop != NULL) {
4083 cnt -= auio.uio_resid;
4084 td->td_retval[0] = cnt;
4085 } else
4086 td->td_retval[0] = size;
4087
4088 done:
4089 VOP_UNLOCK(vp, 0, td);
4090 return (error);
4091 }
4092
4093 int
4094 extattr_get_fd(td, uap)
4095 struct thread *td;
4096 struct extattr_get_fd_args /* {
4097 int fd;
4098 int attrnamespace;
4099 const char *attrname;
4100 void *data;
4101 size_t nbytes;
4102 } */ *uap;
4103 {
4104 struct file *fp;
4105 char attrname[EXTATTR_MAXNAMELEN];
4106 int error;
4107
4108 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4109 if (error)
4110 return (error);
4111
4112 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4113 if (error)
4114 return (error);
4115
4116 error = extattr_get_vp((struct vnode *)fp->f_data, uap->attrnamespace,
4117 attrname, uap->data, uap->nbytes, td);
4118
4119 fdrop(fp, td);
4120 return (error);
4121 }
4122
4123 int
4124 extattr_get_file(td, uap)
4125 struct thread *td;
4126 struct extattr_get_file_args /* {
4127 const char *path;
4128 int attrnamespace;
4129 const char *attrname;
4130 void *data;
4131 size_t nbytes;
4132 } */ *uap;
4133 {
4134 struct nameidata nd;
4135 char attrname[EXTATTR_MAXNAMELEN];
4136 int error;
4137
4138 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4139 if (error)
4140 return (error);
4141
4142 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
4143 error = namei(&nd);
4144 if (error)
4145 return (error);
4146 NDFREE(&nd, NDF_ONLY_PNBUF);
4147
4148 error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
4149 uap->data, uap->nbytes, td);
4150
4151 vrele(nd.ni_vp);
4152 return (error);
4153 }
4154
4155 int
4156 extattr_get_link(td, uap)
4157 struct thread *td;
4158 struct extattr_get_link_args /* {
4159 const char *path;
4160 int attrnamespace;
4161 const char *attrname;
4162 void *data;
4163 size_t nbytes;
4164 } */ *uap;
4165 {
4166 struct nameidata nd;
4167 char attrname[EXTATTR_MAXNAMELEN];
4168 int error;
4169
4170 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4171 if (error)
4172 return (error);
4173
4174 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
4175 error = namei(&nd);
4176 if (error)
4177 return (error);
4178 NDFREE(&nd, NDF_ONLY_PNBUF);
4179
4180 error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
4181 uap->data, uap->nbytes, td);
4182
4183 vrele(nd.ni_vp);
4184 return (error);
4185 }
4186
4187 /*
4188 * extattr_delete_vp(): Delete a named extended attribute on a file or
4189 * directory
4190 *
4191 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4192 * kernelspace string pointer "attrname", proc "p"
4193 * Returns: 0 on success, an error number otherwise
4194 * Locks: none
4195 * References: vp must be a valid reference for the duration of the call
4196 */
4197 static int
4198 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4199 struct thread *td)
4200 {
4201 struct mount *mp;
4202 int error;
4203
4204 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
4205 if (error)
4206 return (error);
4207 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4208 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4209
4210 #ifdef MAC
4211 error = mac_check_vnode_setextattr(td->td_ucred, vp, attrnamespace,
4212 attrname, NULL);
4213 if (error)
4214 goto done;
4215 #endif
4216
4217 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL, td->td_ucred,
4218 td);
4219 #ifdef MAC
4220 done:
4221 #endif
4222 VOP_UNLOCK(vp, 0, td);
4223 vn_finished_write(mp);
4224 return (error);
4225 }
4226
4227 int
4228 extattr_delete_fd(td, uap)
4229 struct thread *td;
4230 struct extattr_delete_fd_args /* {
4231 int fd;
4232 int attrnamespace;
4233 const char *attrname;
4234 } */ *uap;
4235 {
4236 struct file *fp;
4237 struct vnode *vp;
4238 char attrname[EXTATTR_MAXNAMELEN];
4239 int error;
4240
4241 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4242 if (error)
4243 return (error);
4244
4245 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4246 if (error)
4247 return (error);
4248 vp = (struct vnode *)fp->f_data;
4249
4250 error = extattr_delete_vp(vp, uap->attrnamespace, attrname, td);
4251 fdrop(fp, td);
4252 return (error);
4253 }
4254
4255 int
4256 extattr_delete_file(td, uap)
4257 struct thread *td;
4258 struct extattr_delete_file_args /* {
4259 const char *path;
4260 int attrnamespace;
4261 const char *attrname;
4262 } */ *uap;
4263 {
4264 struct nameidata nd;
4265 char attrname[EXTATTR_MAXNAMELEN];
4266 int error;
4267
4268 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4269 if (error)
4270 return(error);
4271
4272 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
4273 error = namei(&nd);
4274 if (error)
4275 return(error);
4276 NDFREE(&nd, NDF_ONLY_PNBUF);
4277
4278 error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
4279 vrele(nd.ni_vp);
4280 return(error);
4281 }
4282
4283 int
4284 extattr_delete_link(td, uap)
4285 struct thread *td;
4286 struct extattr_delete_link_args /* {
4287 const char *path;
4288 int attrnamespace;
4289 const char *attrname;
4290 } */ *uap;
4291 {
4292 struct nameidata nd;
4293 char attrname[EXTATTR_MAXNAMELEN];
4294 int error;
4295
4296 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4297 if (error)
4298 return(error);
4299
4300 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
4301 error = namei(&nd);
4302 if (error)
4303 return(error);
4304 NDFREE(&nd, NDF_ONLY_PNBUF);
4305
4306 error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
4307 vrele(nd.ni_vp);
4308 return(error);
4309 }
Cache object: 3a99423c41a9c635abca8b574281a099
|