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