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