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