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