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