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