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