have to recompute the next pointer after possibly sleeping in sync
[unix-history] / usr / src / sys / kern / vfs_syscalls.c
CommitLineData
da7c5cc6 1/*
47a73614
KB
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
adb35f79
KB
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.
da7c5cc6 9 *
dbf0c423 10 * %sccs.include.redist.c%
fc2aed1e 11 *
1a7bccf6 12 * @(#)vfs_syscalls.c 8.21 (Berkeley) %G%
da7c5cc6 13 */
6459ebe0 14
38a01dbe
KB
15#include <sys/param.h>
16#include <sys/systm.h>
17#include <sys/namei.h>
18#include <sys/filedesc.h>
19#include <sys/kernel.h>
20#include <sys/file.h>
21#include <sys/stat.h>
22#include <sys/vnode.h>
23#include <sys/mount.h>
24#include <sys/proc.h>
25#include <sys/uio.h>
26#include <sys/malloc.h>
27#include <sys/dirent.h>
28
be320a2b 29#include <vm/vm.h>
6aecdd4c 30#include <sys/sysctl.h>
88a7a62a 31
7121fdf0
KB
32static int change_dir __P((struct nameidata *ndp, struct proc *p));
33
a5368812
KM
34#ifdef REF_DIAGNOSTIC
35#define CURCOUNT (curproc ? curproc->p_spare[0] : 0)
36#define CHECKPOINTREF int oldrefcount = CURCOUNT;
37#define CHECKREFS(F) if (oldrefcount != CURCOUNT) \
38 printf("REFCOUNT: %s, old=%d, new=%d\n", (F), oldrefcount, CURCOUNT);
39#else
40#define CHECKPOINTREF
41#define CHECKREFS(D)
42#endif
43
fc2aed1e
KM
44/*
45 * Virtual File System System Calls
46 */
3e78e260 47
4f083fd7 48/*
7121fdf0 49 * Mount a file system.
4f083fd7 50 */
9e97623a
CT
51struct mount_args {
52 int type;
7121fdf0 53 char *path;
9e97623a
CT
54 int flags;
55 caddr_t data;
56};
6a6a1e5f
KM
57/* ARGSUSED */
58mount(p, uap, retval)
5e00df3b 59 struct proc *p;
9e97623a 60 register struct mount_args *uap;
6a6a1e5f
KM
61 int *retval;
62{
d48157d5
KM
63 register struct vnode *vp;
64 register struct mount *mp;
47971887 65 int error, flag;
c5208eda 66 struct vattr va;
8429d022 67 struct nameidata nd;
3e78e260 68
fc2aed1e
KM
69 /*
70 * Get vnode to be covered
71 */
7121fdf0 72 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
dd4c01c2 73 if (error = namei(&nd))
8429d022 74 return (error);
dd4c01c2 75 vp = nd.ni_vp;
54fb9dc2 76 if (uap->flags & MNT_UPDATE) {
d48157d5
KM
77 if ((vp->v_flag & VROOT) == 0) {
78 vput(vp);
8429d022 79 return (EINVAL);
d48157d5
KM
80 }
81 mp = vp->v_mount;
db62a40f 82 flag = mp->mnt_flag;
d48157d5 83 /*
db62a40f
KM
84 * We only allow the filesystem to be reloaded if it
85 * is currently mounted read-only.
d48157d5 86 */
db62a40f
KM
87 if ((uap->flags & MNT_RELOAD) &&
88 ((mp->mnt_flag & MNT_RDONLY) == 0)) {
d48157d5 89 vput(vp);
8429d022 90 return (EOPNOTSUPP); /* Needs translation */
d48157d5 91 }
db62a40f
KM
92 mp->mnt_flag |=
93 uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
c5208eda
KM
94 /*
95 * Only root, or the user that did the original mount is
96 * permitted to update it.
97 */
98 if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
99 (error = suser(p->p_ucred, &p->p_acflag))) {
100 vput(vp);
101 return (error);
102 }
103 /*
104 * Do not allow NFS export by non-root users. Silently
105 * enforce MNT_NOSUID and MNT_NODEV for non-root users.
106 */
107 if (p->p_ucred->cr_uid != 0) {
108 if (uap->flags & MNT_EXPORTED) {
109 vput(vp);
110 return (EPERM);
111 }
112 uap->flags |= MNT_NOSUID | MNT_NODEV;
113 }
d48157d5
KM
114 VOP_UNLOCK(vp);
115 goto update;
116 }
c5208eda
KM
117 /*
118 * If the user is not root, ensure that they own the directory
119 * onto which we are attempting to mount.
120 */
121 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
122 (va.va_uid != p->p_ucred->cr_uid &&
123 (error = suser(p->p_ucred, &p->p_acflag)))) {
124 vput(vp);
125 return (error);
126 }
127 /*
128 * Do not allow NFS export by non-root users. Silently
129 * enforce MNT_NOSUID and MNT_NODEV for non-root users.
130 */
131 if (p->p_ucred->cr_uid != 0) {
132 if (uap->flags & MNT_EXPORTED) {
133 vput(vp);
134 return (EPERM);
135 }
136 uap->flags |= MNT_NOSUID | MNT_NODEV;
137 }
c05286bd 138 if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0))
09d2ef1a 139 return (error);
fc2aed1e
KM
140 if (vp->v_type != VDIR) {
141 vput(vp);
8429d022 142 return (ENOTDIR);
fc2aed1e 143 }
7121fdf0 144 if ((u_long)uap->type > MOUNT_MAXTYPE || vfssw[uap->type] == NULL) {
fc2aed1e 145 vput(vp);
8429d022 146 return (ENODEV);
fc2aed1e
KM
147 }
148
149 /*
d48157d5 150 * Allocate and initialize the file system.
fc2aed1e
KM
151 */
152 mp = (struct mount *)malloc((u_long)sizeof(struct mount),
153 M_MOUNT, M_WAITOK);
b1341251 154 bzero((char *)mp, (u_long)sizeof(struct mount));
54fb9dc2 155 mp->mnt_op = vfssw[uap->type];
d48157d5
KM
156 if (error = vfs_lock(mp)) {
157 free((caddr_t)mp, M_MOUNT);
158 vput(vp);
8429d022 159 return (error);
d48157d5 160 }
7121fdf0 161 if (vp->v_mountedhere != NULL) {
d48157d5
KM
162 vfs_unlock(mp);
163 free((caddr_t)mp, M_MOUNT);
164 vput(vp);
8429d022 165 return (EBUSY);
d48157d5 166 }
d48157d5 167 vp->v_mountedhere = mp;
54fb9dc2 168 mp->mnt_vnodecovered = vp;
c5208eda 169 mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
d48157d5
KM
170update:
171 /*
172 * Set the mount level flags.
173 */
54fb9dc2
KM
174 if (uap->flags & MNT_RDONLY)
175 mp->mnt_flag |= MNT_RDONLY;
db62a40f
KM
176 else if (mp->mnt_flag & MNT_RDONLY)
177 mp->mnt_flag |= MNT_WANTRDWR;
ac85da8a
KM
178 mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
179 MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
180 mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
181 MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
d48157d5
KM
182 /*
183 * Mount the filesystem.
184 */
7121fdf0 185 error = VFS_MOUNT(mp, uap->path, uap->data, &nd, p);
54fb9dc2 186 if (mp->mnt_flag & MNT_UPDATE) {
d48157d5 187 vrele(vp);
db62a40f
KM
188 if (mp->mnt_flag & MNT_WANTRDWR)
189 mp->mnt_flag &= ~MNT_RDONLY;
190 mp->mnt_flag &=~
191 (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
47971887 192 if (error)
54fb9dc2 193 mp->mnt_flag = flag;
8429d022 194 return (error);
d48157d5 195 }
92d0de98
KM
196 /*
197 * Put the new filesystem on the mount list after root.
198 */
fc2aed1e 199 cache_purge(vp);
fc2aed1e 200 if (!error) {
0f66cdec 201 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
d48157d5 202 VOP_UNLOCK(vp);
fc2aed1e 203 vfs_unlock(mp);
2c69fe14 204 error = VFS_START(mp, 0, p);
fc2aed1e 205 } else {
0f66cdec
KM
206 mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
207 vfs_unlock(mp);
fc2aed1e 208 free((caddr_t)mp, M_MOUNT);
d48157d5 209 vput(vp);
fc2aed1e 210 }
8429d022 211 return (error);
3e78e260
BJ
212}
213
4f083fd7 214/*
7121fdf0 215 * Unmount a file system.
fc2aed1e
KM
216 *
217 * Note: unmount takes a path to the vnode mounted on as argument,
218 * not special file (as before).
4f083fd7 219 */
9e97623a 220struct unmount_args {
7121fdf0 221 char *path;
9e97623a
CT
222 int flags;
223};
6a6a1e5f
KM
224/* ARGSUSED */
225unmount(p, uap, retval)
5e00df3b 226 struct proc *p;
9e97623a 227 register struct unmount_args *uap;
6a6a1e5f
KM
228 int *retval;
229{
fc2aed1e 230 register struct vnode *vp;
9151110e 231 struct mount *mp;
fc2aed1e 232 int error;
8429d022 233 struct nameidata nd;
fc2aed1e 234
7121fdf0 235 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
dd4c01c2 236 if (error = namei(&nd))
8429d022 237 return (error);
dd4c01c2 238 vp = nd.ni_vp;
c5208eda 239 mp = vp->v_mount;
f0e827e3
JSP
240
241 /*
c5208eda
KM
242 * Only root, or the user that did the original mount is
243 * permitted to unmount this filesystem.
f0e827e3 244 */
c5208eda 245 if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
f0e827e3
JSP
246 (error = suser(p->p_ucred, &p->p_acflag))) {
247 vput(vp);
248 return (error);
249 }
250
fc2aed1e
KM
251 /*
252 * Must be the root of the filesystem
253 */
254 if ((vp->v_flag & VROOT) == 0) {
255 vput(vp);
8429d022 256 return (EINVAL);
fc2aed1e 257 }
fc2aed1e 258 vput(vp);
2c69fe14 259 return (dounmount(mp, uap->flags, p));
9151110e
KM
260}
261
262/*
7121fdf0 263 * Do the actual file system unmount.
9151110e 264 */
2c69fe14 265dounmount(mp, flags, p)
9151110e
KM
266 register struct mount *mp;
267 int flags;
2c69fe14 268 struct proc *p;
9151110e
KM
269{
270 struct vnode *coveredvp;
271 int error;
272
54fb9dc2 273 coveredvp = mp->mnt_vnodecovered;
c001b1c3
KM
274 if (vfs_busy(mp))
275 return (EBUSY);
54fb9dc2 276 mp->mnt_flag |= MNT_UNMOUNT;
fc2aed1e 277 if (error = vfs_lock(mp))
9151110e 278 return (error);
fc2aed1e 279
1c295f6f 280 mp->mnt_flag &=~ MNT_ASYNC;
9db58063 281 vnode_pager_umount(mp); /* release cached vnodes */
fc2aed1e 282 cache_purgevfs(mp); /* remove cache entries for this file sys */
09d2ef1a
KM
283 if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 ||
284 (flags & MNT_FORCE))
2c69fe14 285 error = VFS_UNMOUNT(mp, flags, p);
54fb9dc2 286 mp->mnt_flag &= ~MNT_UNMOUNT;
c001b1c3 287 vfs_unbusy(mp);
fc2aed1e
KM
288 if (error) {
289 vfs_unlock(mp);
290 } else {
291 vrele(coveredvp);
0f66cdec
KM
292 TAILQ_REMOVE(&mountlist, mp, mnt_list);
293 mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
294 vfs_unlock(mp);
295 if (mp->mnt_vnodelist.lh_first != NULL)
ea2761aa 296 panic("unmount: dangling vnode");
fc2aed1e
KM
297 free((caddr_t)mp, M_MOUNT);
298 }
9151110e 299 return (error);
fc2aed1e
KM
300}
301
302/*
fc2aed1e
KM
303 * Sync each mounted filesystem.
304 */
b5e5c792 305#ifdef DEBUG
0649728d 306int syncprt = 0;
6aecdd4c 307struct ctldebug debug0 = { "syncprt", &syncprt };
0649728d
KM
308#endif
309
9e97623a
CT
310struct sync_args {
311 int dummy;
312};
ff4fb102 313/* ARGSUSED */
6a6a1e5f 314sync(p, uap, retval)
5e00df3b 315 struct proc *p;
9e97623a 316 struct sync_args *uap;
6a6a1e5f 317 int *retval;
3e78e260 318{
0f66cdec 319 register struct mount *mp, *nmp;
1c295f6f 320 int asyncflag;
fc2aed1e 321
0f66cdec 322 for (mp = mountlist.tqh_first; mp != NULL; mp = nmp) {
1a7bccf6
KM
323 /*
324 * Get the next pointer in case we hang on vfs_busy
325 * while we are being unmounted.
326 */
0f66cdec 327 nmp = mp->mnt_list.tqe_next;
62e35d50
KM
328 /*
329 * The lock check below is to avoid races with mount
330 * and unmount.
331 */
54fb9dc2 332 if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 &&
c001b1c3 333 !vfs_busy(mp)) {
1c295f6f
KM
334 asyncflag = mp->mnt_flag & MNT_ASYNC;
335 mp->mnt_flag &= ~MNT_ASYNC;
09d2ef1a 336 VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
1c295f6f
KM
337 if (asyncflag)
338 mp->mnt_flag |= MNT_ASYNC;
1a7bccf6
KM
339 /*
340 * Get the next pointer again, as the next filesystem
341 * might have been unmounted while we were sync'ing.
342 */
343 nmp = mp->mnt_list.tqe_next;
0f66cdec
KM
344 vfs_unbusy(mp);
345 }
346 }
0649728d
KM
347#ifdef DIAGNOSTIC
348 if (syncprt)
349 vfs_bufstats();
350#endif /* DIAGNOSTIC */
78eeb014 351 return (0);
fc2aed1e
KM
352}
353
c001b1c3 354/*
7121fdf0 355 * Change filesystem quotas.
c001b1c3 356 */
9e97623a
CT
357struct quotactl_args {
358 char *path;
359 int cmd;
360 int uid;
361 caddr_t arg;
362};
6a6a1e5f
KM
363/* ARGSUSED */
364quotactl(p, uap, retval)
5e00df3b 365 struct proc *p;
9e97623a 366 register struct quotactl_args *uap;
6a6a1e5f
KM
367 int *retval;
368{
c001b1c3 369 register struct mount *mp;
c001b1c3 370 int error;
8429d022 371 struct nameidata nd;
c001b1c3 372
dd4c01c2
KM
373 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
374 if (error = namei(&nd))
8429d022 375 return (error);
dd4c01c2
KM
376 mp = nd.ni_vp->v_mount;
377 vrele(nd.ni_vp);
2c69fe14 378 return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p));
c001b1c3
KM
379}
380
fc2aed1e 381/*
d4ed1dcd 382 * Get filesystem statistics.
fc2aed1e 383 */
9e97623a
CT
384struct statfs_args {
385 char *path;
386 struct statfs *buf;
387};
6a6a1e5f
KM
388/* ARGSUSED */
389statfs(p, uap, retval)
5e00df3b 390 struct proc *p;
9e97623a 391 register struct statfs_args *uap;
6a6a1e5f
KM
392 int *retval;
393{
3f705640 394 register struct mount *mp;
62e35d50 395 register struct statfs *sp;
fc2aed1e 396 int error;
8429d022 397 struct nameidata nd;
3e78e260 398
dd4c01c2
KM
399 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
400 if (error = namei(&nd))
8429d022 401 return (error);
dd4c01c2 402 mp = nd.ni_vp->v_mount;
54fb9dc2 403 sp = &mp->mnt_stat;
dd4c01c2 404 vrele(nd.ni_vp);
2c69fe14 405 if (error = VFS_STATFS(mp, sp, p))
8429d022 406 return (error);
54fb9dc2 407 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
8429d022 408 return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
fc2aed1e
KM
409}
410
6a6a1e5f 411/*
d4ed1dcd 412 * Get filesystem statistics.
6a6a1e5f 413 */
9e97623a
CT
414struct fstatfs_args {
415 int fd;
416 struct statfs *buf;
417};
6a6a1e5f
KM
418/* ARGSUSED */
419fstatfs(p, uap, retval)
5e00df3b 420 struct proc *p;
9e97623a 421 register struct fstatfs_args *uap;
6a6a1e5f
KM
422 int *retval;
423{
fc2aed1e 424 struct file *fp;
3f705640 425 struct mount *mp;
62e35d50 426 register struct statfs *sp;
fc2aed1e
KM
427 int error;
428
5e00df3b 429 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 430 return (error);
3f705640 431 mp = ((struct vnode *)fp->f_data)->v_mount;
54fb9dc2 432 sp = &mp->mnt_stat;
2c69fe14 433 if (error = VFS_STATFS(mp, sp, p))
8429d022 434 return (error);
54fb9dc2 435 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
8429d022 436 return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
3e78e260
BJ
437}
438
bfcdbfbf 439/*
d4ed1dcd 440 * Get statistics on all filesystems.
bfcdbfbf 441 */
9e97623a
CT
442struct getfsstat_args {
443 struct statfs *buf;
444 long bufsize;
445 int flags;
446};
6a6a1e5f 447getfsstat(p, uap, retval)
5e00df3b 448 struct proc *p;
9e97623a 449 register struct getfsstat_args *uap;
6a6a1e5f
KM
450 int *retval;
451{
0f66cdec 452 register struct mount *mp, *nmp;
62e35d50 453 register struct statfs *sp;
f62fad9a 454 caddr_t sfsp;
bfcdbfbf
KM
455 long count, maxcount, error;
456
457 maxcount = uap->bufsize / sizeof(struct statfs);
f62fad9a 458 sfsp = (caddr_t)uap->buf;
0f66cdec
KM
459 for (count = 0, mp = mountlist.tqh_first; mp != NULL; mp = nmp) {
460 nmp = mp->mnt_list.tqe_next;
54fb9dc2
KM
461 if (sfsp && count < maxcount &&
462 ((mp->mnt_flag & MNT_MLOCK) == 0)) {
463 sp = &mp->mnt_stat;
62e35d50
KM
464 /*
465 * If MNT_NOWAIT is specified, do not refresh the
466 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
467 */
468 if (((uap->flags & MNT_NOWAIT) == 0 ||
469 (uap->flags & MNT_WAIT)) &&
0f66cdec 470 (error = VFS_STATFS(mp, sp, p)))
fd8516be 471 continue;
54fb9dc2 472 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
62e35d50 473 if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp)))
8429d022 474 return (error);
62e35d50 475 sfsp += sizeof(*sp);
bfcdbfbf 476 }
f62fad9a 477 count++;
0f66cdec 478 }
bfcdbfbf 479 if (sfsp && count > maxcount)
6a6a1e5f 480 *retval = maxcount;
bfcdbfbf 481 else
6a6a1e5f 482 *retval = count;
8429d022 483 return (0);
bfcdbfbf
KM
484}
485
6995a2cb
KM
486/*
487 * Change current working directory to a given file descriptor.
488 */
9e97623a
CT
489struct fchdir_args {
490 int fd;
491};
6a6a1e5f
KM
492/* ARGSUSED */
493fchdir(p, uap, retval)
5e00df3b 494 struct proc *p;
9e97623a 495 struct fchdir_args *uap;
6a6a1e5f
KM
496 int *retval;
497{
5e00df3b 498 register struct filedesc *fdp = p->p_fd;
6995a2cb
KM
499 register struct vnode *vp;
500 struct file *fp;
501 int error;
502
5e00df3b 503 if (error = getvnode(fdp, uap->fd, &fp))
8429d022 504 return (error);
6995a2cb
KM
505 vp = (struct vnode *)fp->f_data;
506 VOP_LOCK(vp);
507 if (vp->v_type != VDIR)
508 error = ENOTDIR;
509 else
2c69fe14 510 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
6995a2cb 511 VOP_UNLOCK(vp);
ab214c34 512 if (error)
8429d022 513 return (error);
ab214c34 514 VREF(vp);
5e00df3b
KM
515 vrele(fdp->fd_cdir);
516 fdp->fd_cdir = vp;
8429d022 517 return (0);
6995a2cb
KM
518}
519
4f083fd7 520/*
fc2aed1e 521 * Change current working directory (``.'').
4f083fd7 522 */
9e97623a 523struct chdir_args {
7121fdf0 524 char *path;
9e97623a 525};
6a6a1e5f
KM
526/* ARGSUSED */
527chdir(p, uap, retval)
5e00df3b 528 struct proc *p;
9e97623a 529 struct chdir_args *uap;
6a6a1e5f
KM
530 int *retval;
531{
5e00df3b 532 register struct filedesc *fdp = p->p_fd;
fc2aed1e 533 int error;
8429d022 534 struct nameidata nd;
3e78e260 535
7121fdf0
KB
536 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
537 if (error = change_dir(&nd, p))
8429d022 538 return (error);
5e00df3b 539 vrele(fdp->fd_cdir);
dd4c01c2 540 fdp->fd_cdir = nd.ni_vp;
8429d022 541 return (0);
fc2aed1e
KM
542}
543
544/*
545 * Change notion of root (``/'') directory.
546 */
9e97623a 547struct chroot_args {
7121fdf0 548 char *path;
9e97623a 549};
6a6a1e5f
KM
550/* ARGSUSED */
551chroot(p, uap, retval)
5e00df3b 552 struct proc *p;
9e97623a 553 struct chroot_args *uap;
6a6a1e5f
KM
554 int *retval;
555{
5e00df3b 556 register struct filedesc *fdp = p->p_fd;
fc2aed1e 557 int error;
8429d022 558 struct nameidata nd;
fc2aed1e 559
8429d022
MK
560 if (error = suser(p->p_ucred, &p->p_acflag))
561 return (error);
7121fdf0
KB
562 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
563 if (error = change_dir(&nd, p))
8429d022 564 return (error);
5e00df3b
KM
565 if (fdp->fd_rdir != NULL)
566 vrele(fdp->fd_rdir);
dd4c01c2 567 fdp->fd_rdir = nd.ni_vp;
8429d022 568 return (0);
fc2aed1e
KM
569}
570
571/*
572 * Common routine for chroot and chdir.
573 */
7121fdf0
KB
574static int
575change_dir(ndp, p)
dd4c01c2 576 register struct nameidata *ndp;
8429d022 577 struct proc *p;
fc2aed1e
KM
578{
579 struct vnode *vp;
580 int error;
581
dd4c01c2 582 if (error = namei(ndp))
fc2aed1e
KM
583 return (error);
584 vp = ndp->ni_vp;
585 if (vp->v_type != VDIR)
586 error = ENOTDIR;
587 else
2c69fe14 588 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
fc2aed1e
KM
589 VOP_UNLOCK(vp);
590 if (error)
591 vrele(vp);
592 return (error);
3e78e260
BJ
593}
594
595/*
6a6a1e5f
KM
596 * Check permissions, allocate an open file structure,
597 * and call the device open routine if any.
3e78e260 598 */
9e97623a 599struct open_args {
7121fdf0
KB
600 char *path;
601 int flags;
9e97623a 602 int mode;
9e97623a 603};
6a6a1e5f 604open(p, uap, retval)
5e00df3b 605 struct proc *p;
9e97623a 606 register struct open_args *uap;
6a6a1e5f 607 int *retval;
3e78e260 608{
5e00df3b 609 register struct filedesc *fdp = p->p_fd;
3e78e260 610 register struct file *fp;
6aaf085a 611 register struct vnode *vp;
7121fdf0 612 int flags, cmode;
fc2aed1e 613 struct file *nfp;
ff8d1617
KM
614 int type, indx, error;
615 struct flock lf;
8429d022 616 struct nameidata nd;
fc2aed1e
KM
617 extern struct fileops vnops;
618
5e00df3b 619 if (error = falloc(p, &nfp, &indx))
8429d022 620 return (error);
fc2aed1e 621 fp = nfp;
7121fdf0
KB
622 flags = FFLAGS(uap->flags);
623 cmode = ((uap->mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
624 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
03951846 625 p->p_dupfd = -indx - 1; /* XXX check for fdopen */
7121fdf0 626 if (error = vn_open(&nd, flags, cmode)) {
336f999d 627 ffree(fp);
f0e12026
KM
628 if ((error == ENODEV || error == ENXIO) &&
629 p->p_dupfd >= 0 && /* XXX from fdopen */
7121fdf0
KB
630 (error =
631 dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
6a6a1e5f 632 *retval = indx;
8429d022 633 return (0);
6a6a1e5f 634 }
b10521d6
KM
635 if (error == ERESTART)
636 error = EINTR;
78eeb014 637 fdp->fd_ofiles[indx] = NULL;
8429d022 638 return (error);
528f664c 639 }
da5acac3 640 p->p_dupfd = 0;
dd4c01c2 641 vp = nd.ni_vp;
7121fdf0 642 fp->f_flag = flags & FMASK;
8932276d
KM
643 fp->f_type = DTYPE_VNODE;
644 fp->f_ops = &vnops;
645 fp->f_data = (caddr_t)vp;
7121fdf0 646 if (flags & (O_EXLOCK | O_SHLOCK)) {
ff8d1617
KM
647 lf.l_whence = SEEK_SET;
648 lf.l_start = 0;
649 lf.l_len = 0;
7121fdf0 650 if (flags & O_EXLOCK)
ff8d1617
KM
651 lf.l_type = F_WRLCK;
652 else
653 lf.l_type = F_RDLCK;
654 type = F_FLOCK;
7121fdf0 655 if ((flags & FNONBLOCK) == 0)
ff8d1617 656 type |= F_WAIT;
70b7fe1d 657 VOP_UNLOCK(vp);
6aaf085a 658 if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
6aaf085a 659 (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
336f999d 660 ffree(fp);
ff8d1617
KM
661 fdp->fd_ofiles[indx] = NULL;
662 return (error);
663 }
70b7fe1d 664 VOP_LOCK(vp);
b40ecf6f 665 fp->f_flag |= FHASLOCK;
ff8d1617 666 }
6aaf085a 667 VOP_UNLOCK(vp);
6a6a1e5f 668 *retval = indx;
8429d022 669 return (0);
3e78e260
BJ
670}
671
4fde03dc 672#ifdef COMPAT_43
3e78e260 673/*
7121fdf0 674 * Create a file.
3e78e260 675 */
9e97623a 676struct ocreat_args {
7121fdf0
KB
677 char *path;
678 int mode;
9e97623a 679};
4fde03dc 680ocreat(p, uap, retval)
6a6a1e5f 681 struct proc *p;
9e97623a 682 register struct ocreat_args *uap;
6a6a1e5f 683 int *retval;
3e78e260 684{
9e97623a 685 struct open_args openuap;
6a6a1e5f 686
7121fdf0
KB
687 openuap.path = uap->path;
688 openuap.mode = uap->mode;
689 openuap.flags = O_WRONLY | O_CREAT | O_TRUNC;
8429d022 690 return (open(p, &openuap, retval));
6a6a1e5f 691}
4fde03dc 692#endif /* COMPAT_43 */
6a6a1e5f
KM
693
694/*
7121fdf0 695 * Create a special file.
6a6a1e5f 696 */
9e97623a 697struct mknod_args {
7121fdf0
KB
698 char *path;
699 int mode;
9e97623a
CT
700 int dev;
701};
6a6a1e5f
KM
702/* ARGSUSED */
703mknod(p, uap, retval)
5e00df3b 704 struct proc *p;
9e97623a 705 register struct mknod_args *uap;
6a6a1e5f
KM
706 int *retval;
707{
fc2aed1e
KM
708 register struct vnode *vp;
709 struct vattr vattr;
710 int error;
88edbcd4 711 int whiteout;
8429d022 712 struct nameidata nd;
3e78e260 713
a5368812 714 CHECKPOINTREF;
8429d022
MK
715 if (error = suser(p->p_ucred, &p->p_acflag))
716 return (error);
7121fdf0 717 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
dd4c01c2 718 if (error = namei(&nd))
8429d022 719 return (error);
dd4c01c2 720 vp = nd.ni_vp;
cf5ef508 721 if (vp != NULL)
fc2aed1e 722 error = EEXIST;
cf5ef508
KB
723 else {
724 VATTR_NULL(&vattr);
725 vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
726 vattr.va_rdev = uap->dev;
88edbcd4 727 whiteout = 0;
cf5ef508
KB
728
729 switch (uap->mode & S_IFMT) {
730 case S_IFMT: /* used by badsect to flag bad sectors */
731 vattr.va_type = VBAD;
732 break;
733 case S_IFCHR:
734 vattr.va_type = VCHR;
735 break;
736 case S_IFBLK:
737 vattr.va_type = VBLK;
738 break;
88edbcd4
JSP
739 case S_IFWHT:
740 whiteout = 1;
741 break;
cf5ef508
KB
742 default:
743 error = EINVAL;
744 break;
745 }
3e78e260 746 }
88edbcd4
JSP
747 if (whiteout) {
748 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
749 vput(nd.ni_dvp);
750 } else if (!error) {
4c5d3e43 751 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
dd4c01c2 752 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
66955caf 753 } else {
dd4c01c2
KM
754 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
755 if (nd.ni_dvp == vp)
756 vrele(nd.ni_dvp);
6c44e83b 757 else
dd4c01c2 758 vput(nd.ni_dvp);
66955caf
KM
759 if (vp)
760 vrele(vp);
761 }
a5368812 762 CHECKREFS("mknod");
8429d022 763 return (error);
3e78e260
BJ
764}
765
4751dd21 766/*
7121fdf0 767 * Create named pipe.
4751dd21 768 */
9e97623a 769struct mkfifo_args {
7121fdf0
KB
770 char *path;
771 int mode;
9e97623a 772};
6a6a1e5f
KM
773/* ARGSUSED */
774mkfifo(p, uap, retval)
5e00df3b 775 struct proc *p;
9e97623a 776 register struct mkfifo_args *uap;
6a6a1e5f
KM
777 int *retval;
778{
4751dd21
KM
779 struct vattr vattr;
780 int error;
8429d022 781 struct nameidata nd;
4751dd21
KM
782
783#ifndef FIFO
8429d022 784 return (EOPNOTSUPP);
4751dd21 785#else
7121fdf0 786 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
dd4c01c2 787 if (error = namei(&nd))
8429d022 788 return (error);
dd4c01c2
KM
789 if (nd.ni_vp != NULL) {
790 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
791 if (nd.ni_dvp == nd.ni_vp)
792 vrele(nd.ni_dvp);
6c44e83b 793 else
dd4c01c2
KM
794 vput(nd.ni_dvp);
795 vrele(nd.ni_vp);
8429d022 796 return (EEXIST);
4751dd21 797 }
3658f091
KB
798 VATTR_NULL(&vattr);
799 vattr.va_type = VFIFO;
7121fdf0 800 vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
4c5d3e43 801 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
dd4c01c2 802 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
4751dd21
KM
803#endif /* FIFO */
804}
805
3e78e260 806/*
7121fdf0 807 * Make a hard file link.
3e78e260 808 */
9e97623a 809struct link_args {
7121fdf0
KB
810 char *path;
811 char *link;
9e97623a 812};
6a6a1e5f
KM
813/* ARGSUSED */
814link(p, uap, retval)
5e00df3b 815 struct proc *p;
9e97623a 816 register struct link_args *uap;
6a6a1e5f
KM
817 int *retval;
818{
7121fdf0 819 register struct vnode *vp;
8429d022 820 struct nameidata nd;
7121fdf0 821 int error;
3e78e260 822
a5368812 823 CHECKPOINTREF;
7121fdf0 824 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
dd4c01c2 825 if (error = namei(&nd))
8429d022 826 return (error);
dd4c01c2 827 vp = nd.ni_vp;
cf5ef508
KB
828 if (vp->v_type != VDIR ||
829 (error = suser(p->p_ucred, &p->p_acflag)) == 0) {
830 nd.ni_cnd.cn_nameiop = CREATE;
831 nd.ni_cnd.cn_flags = LOCKPARENT;
832 nd.ni_dirp = uap->link;
833 if ((error = namei(&nd)) == 0) {
834 if (nd.ni_vp != NULL)
835 error = EEXIST;
836 if (!error) {
4c5d3e43
KM
837 VOP_LEASE(nd.ni_dvp, p, p->p_ucred,
838 LEASE_WRITE);
839 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
cf5ef508
KB
840 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
841 } else {
842 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
843 if (nd.ni_dvp == nd.ni_vp)
844 vrele(nd.ni_dvp);
845 else
846 vput(nd.ni_dvp);
847 if (nd.ni_vp)
848 vrele(nd.ni_vp);
849 }
850 }
66955caf 851 }
cf5ef508 852 vrele(vp);
a5368812 853 CHECKREFS("link");
8429d022 854 return (error);
3e78e260
BJ
855}
856
857/*
d4ed1dcd 858 * Make a symbolic link.
3e78e260 859 */
9e97623a 860struct symlink_args {
7121fdf0
KB
861 char *path;
862 char *link;
9e97623a 863};
6a6a1e5f
KM
864/* ARGSUSED */
865symlink(p, uap, retval)
5e00df3b 866 struct proc *p;
9e97623a 867 register struct symlink_args *uap;
6a6a1e5f
KM
868 int *retval;
869{
fc2aed1e 870 struct vattr vattr;
7121fdf0 871 char *path;
fc2aed1e 872 int error;
8429d022 873 struct nameidata nd;
3e78e260 874
a5368812 875 CHECKPOINTREF;
7121fdf0
KB
876 MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
877 if (error = copyinstr(uap->path, path, MAXPATHLEN, NULL))
66955caf 878 goto out;
7121fdf0 879 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p);
dd4c01c2 880 if (error = namei(&nd))
66955caf 881 goto out;
dd4c01c2
KM
882 if (nd.ni_vp) {
883 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
884 if (nd.ni_dvp == nd.ni_vp)
885 vrele(nd.ni_dvp);
6c44e83b 886 else
dd4c01c2
KM
887 vput(nd.ni_dvp);
888 vrele(nd.ni_vp);
fc2aed1e
KM
889 error = EEXIST;
890 goto out;
3e78e260 891 }
3ee1461b 892 VATTR_NULL(&vattr);
7121fdf0 893 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
4c5d3e43 894 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
7121fdf0 895 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
fc2aed1e 896out:
7121fdf0 897 FREE(path, M_NAMEI);
a5368812 898 CHECKREFS("symlink");
8429d022 899 return (error);
3e78e260
BJ
900}
901
0411e53b
JSP
902/*
903 * Delete a whiteout from the filesystem.
904 */
905struct unwhiteout_args {
906 char *path;
907};
908/* ARGSUSED */
909unwhiteout(p, uap, retval)
910 struct proc *p;
911 struct unwhiteout_args *uap;
912 int *retval;
913{
914 int error;
915 struct nameidata nd;
916
88edbcd4
JSP
917 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, uap->path, p);
918 error = namei(&nd);
919 if (error)
0411e53b 920 return (error);
88edbcd4
JSP
921
922 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
0411e53b
JSP
923 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
924 if (nd.ni_dvp == nd.ni_vp)
925 vrele(nd.ni_dvp);
926 else
927 vput(nd.ni_dvp);
928 if (nd.ni_vp)
929 vrele(nd.ni_vp);
930 return (EEXIST);
931 }
88edbcd4 932
4c5d3e43 933 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
0411e53b 934 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
88edbcd4
JSP
935 if (error != 0)
936 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
0411e53b
JSP
937 vput(nd.ni_dvp);
938 return (error);
939}
940
3e78e260 941/*
d4ed1dcd 942 * Delete a name from the filesystem.
3e78e260 943 */
9e97623a 944struct unlink_args {
7121fdf0 945 char *path;
9e97623a 946};
6a6a1e5f
KM
947/* ARGSUSED */
948unlink(p, uap, retval)
5e00df3b 949 struct proc *p;
9e97623a 950 struct unlink_args *uap;
6a6a1e5f
KM
951 int *retval;
952{
fc2aed1e
KM
953 register struct vnode *vp;
954 int error;
8429d022 955 struct nameidata nd;
3e78e260 956
a5368812 957 CHECKPOINTREF;
7121fdf0 958 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
dd4c01c2 959 if (error = namei(&nd))
8429d022 960 return (error);
dd4c01c2 961 vp = nd.ni_vp;
4c5d3e43 962 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
dbcf7de6 963 VOP_LOCK(vp);
7121fdf0 964
cf5ef508
KB
965 if (vp->v_type != VDIR ||
966 (error = suser(p->p_ucred, &p->p_acflag)) == 0) {
967 /*
968 * The root of a mounted filesystem cannot be deleted.
969 */
970 if (vp->v_flag & VROOT)
971 error = EBUSY;
972 else
973 (void)vnode_pager_uncache(vp);
974 }
975
976 if (!error) {
4c5d3e43 977 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
dd4c01c2 978 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
66955caf 979 } else {
dd4c01c2
KM
980 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
981 if (nd.ni_dvp == vp)
982 vrele(nd.ni_dvp);
6c44e83b 983 else
dd4c01c2 984 vput(nd.ni_dvp);
88edbcd4
JSP
985 if (vp != NULLVP)
986 vput(vp);
66955caf 987 }
a5368812 988 CHECKREFS("unlink");
8429d022 989 return (error);
3e78e260
BJ
990}
991
7121fdf0
KB
992/*
993 * Reposition read/write file offset.
994 */
95c0eb1e 995struct lseek_args {
7121fdf0 996 int fd;
2f2b3b3d 997 int pad;
7121fdf0
KB
998 off_t offset;
999 int whence;
2f2b3b3d 1000};
201e5411 1001lseek(p, uap, retval)
5e00df3b 1002 struct proc *p;
95c0eb1e 1003 register struct lseek_args *uap;
9e97623a 1004 int *retval;
6a6a1e5f 1005{
8429d022 1006 struct ucred *cred = p->p_ucred;
5e00df3b 1007 register struct filedesc *fdp = p->p_fd;
6a6a1e5f 1008 register struct file *fp;
fc2aed1e
KM
1009 struct vattr vattr;
1010 int error;
1011
7121fdf0
KB
1012 if ((u_int)uap->fd >= fdp->fd_nfiles ||
1013 (fp = fdp->fd_ofiles[uap->fd]) == NULL)
8429d022 1014 return (EBADF);
fc2aed1e 1015 if (fp->f_type != DTYPE_VNODE)
8429d022 1016 return (ESPIPE);
7121fdf0 1017 switch (uap->whence) {
b4d1aee9 1018 case L_INCR:
7121fdf0 1019 fp->f_offset += uap->offset;
b4d1aee9 1020 break;
b4d1aee9 1021 case L_XTND:
7121fdf0
KB
1022 if (error =
1023 VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p))
8429d022 1024 return (error);
7121fdf0 1025 fp->f_offset = uap->offset + vattr.va_size;
b4d1aee9 1026 break;
b4d1aee9 1027 case L_SET:
7121fdf0 1028 fp->f_offset = uap->offset;
b4d1aee9 1029 break;
b4d1aee9 1030 default:
8429d022 1031 return (EINVAL);
b4d1aee9 1032 }
9e97623a 1033 *(off_t *)retval = fp->f_offset;
8429d022 1034 return (0);
3e78e260
BJ
1035}
1036
201e5411 1037#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
64deb204 1038/*
7121fdf0 1039 * Reposition read/write file offset.
64deb204 1040 */
95c0eb1e 1041struct olseek_args {
7121fdf0
KB
1042 int fd;
1043 long offset;
1044 int whence;
64deb204 1045};
201e5411 1046olseek(p, uap, retval)
64deb204 1047 struct proc *p;
95c0eb1e 1048 register struct olseek_args *uap;
64deb204
KM
1049 int *retval;
1050{
95c0eb1e 1051 struct lseek_args nuap;
64deb204
KM
1052 off_t qret;
1053 int error;
1054
7121fdf0
KB
1055 nuap.fd = uap->fd;
1056 nuap.offset = uap->offset;
1057 nuap.whence = uap->whence;
95c0eb1e 1058 error = lseek(p, &nuap, &qret);
64deb204
KM
1059 *(long *)retval = qret;
1060 return (error);
1061}
201e5411 1062#endif /* COMPAT_43 */
64deb204 1063
3e78e260 1064/*
d4ed1dcd 1065 * Check access permissions.
3e78e260 1066 */
b54e8954 1067struct access_args {
7121fdf0
KB
1068 char *path;
1069 int flags;
9e97623a 1070};
b54e8954 1071access(p, uap, retval)
5e00df3b 1072 struct proc *p;
b54e8954 1073 register struct access_args *uap;
6a6a1e5f
KM
1074 int *retval;
1075{
8429d022 1076 register struct ucred *cred = p->p_ucred;
fc2aed1e 1077 register struct vnode *vp;
cf5ef508 1078 int error, flags, t_gid, t_uid;
8429d022 1079 struct nameidata nd;
3e78e260 1080
cf5ef508
KB
1081 t_uid = cred->cr_uid;
1082 t_gid = cred->cr_groups[0];
8429d022
MK
1083 cred->cr_uid = p->p_cred->p_ruid;
1084 cred->cr_groups[0] = p->p_cred->p_rgid;
7121fdf0 1085 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
dd4c01c2 1086 if (error = namei(&nd))
fc2aed1e 1087 goto out1;
dd4c01c2 1088 vp = nd.ni_vp;
7121fdf0
KB
1089
1090 /* Flags == 0 means only check for existence. */
1091 if (uap->flags) {
1092 flags = 0;
1093 if (uap->flags & R_OK)
1094 flags |= VREAD;
1095 if (uap->flags & W_OK)
1096 flags |= VWRITE;
1097 if (uap->flags & X_OK)
1098 flags |= VEXEC;
1099 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1100 error = VOP_ACCESS(vp, flags, cred, p);
3e78e260 1101 }
fc2aed1e
KM
1102 vput(vp);
1103out1:
cf5ef508
KB
1104 cred->cr_uid = t_uid;
1105 cred->cr_groups[0] = t_gid;
8429d022 1106 return (error);
3e78e260 1107}
d67a03eb 1108
8932276d 1109#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
d67a03eb 1110/*
7121fdf0 1111 * Get file status; this version follows links.
d67a03eb 1112 */
9e97623a 1113struct ostat_args {
7121fdf0 1114 char *path;
9e97623a
CT
1115 struct ostat *ub;
1116};
6a6a1e5f 1117/* ARGSUSED */
ae9b6dc3 1118ostat(p, uap, retval)
be320a2b 1119 struct proc *p;
9e97623a 1120 register struct ostat_args *uap;
be320a2b
KM
1121 int *retval;
1122{
1123 struct stat sb;
1124 struct ostat osb;
1125 int error;
1126 struct nameidata nd;
1127
7121fdf0 1128 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
be320a2b
KM
1129 if (error = namei(&nd))
1130 return (error);
1131 error = vn_stat(nd.ni_vp, &sb, p);
1132 vput(nd.ni_vp);
1133 if (error)
1134 return (error);
1135 cvtstat(&sb, &osb);
1136 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
1137 return (error);
1138}
1139
1140/*
7121fdf0 1141 * Get file status; this version does not follow links.
be320a2b 1142 */
9e97623a 1143struct olstat_args {
7121fdf0 1144 char *path;
9e97623a
CT
1145 struct ostat *ub;
1146};
be320a2b 1147/* ARGSUSED */
ae9b6dc3 1148olstat(p, uap, retval)
be320a2b 1149 struct proc *p;
9e97623a 1150 register struct olstat_args *uap;
be320a2b
KM
1151 int *retval;
1152{
1153 struct stat sb;
1154 struct ostat osb;
1155 int error;
1156 struct nameidata nd;
1157
7121fdf0 1158 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
be320a2b
KM
1159 if (error = namei(&nd))
1160 return (error);
1161 error = vn_stat(nd.ni_vp, &sb, p);
1162 vput(nd.ni_vp);
1163 if (error)
1164 return (error);
1165 cvtstat(&sb, &osb);
1166 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
1167 return (error);
1168}
1169
1170/*
7121fdf0 1171 * Convert from an old to a new stat structure.
be320a2b
KM
1172 */
1173cvtstat(st, ost)
1174 struct stat *st;
1175 struct ostat *ost;
1176{
1177
1178 ost->st_dev = st->st_dev;
1179 ost->st_ino = st->st_ino;
1180 ost->st_mode = st->st_mode;
1181 ost->st_nlink = st->st_nlink;
1182 ost->st_uid = st->st_uid;
1183 ost->st_gid = st->st_gid;
1184 ost->st_rdev = st->st_rdev;
1185 if (st->st_size < (quad_t)1 << 32)
1186 ost->st_size = st->st_size;
1187 else
1188 ost->st_size = -2;
1189 ost->st_atime = st->st_atime;
1190 ost->st_mtime = st->st_mtime;
1191 ost->st_ctime = st->st_ctime;
1192 ost->st_blksize = st->st_blksize;
1193 ost->st_blocks = st->st_blocks;
1194 ost->st_flags = st->st_flags;
1195 ost->st_gen = st->st_gen;
1196}
8932276d 1197#endif /* COMPAT_43 || COMPAT_SUNOS */
be320a2b
KM
1198
1199/*
7121fdf0 1200 * Get file status; this version follows links.
be320a2b 1201 */
9e97623a 1202struct stat_args {
7121fdf0 1203 char *path;
9e97623a
CT
1204 struct stat *ub;
1205};
be320a2b 1206/* ARGSUSED */
ae9b6dc3 1207stat(p, uap, retval)
5e00df3b 1208 struct proc *p;
9e97623a 1209 register struct stat_args *uap;
6a6a1e5f 1210 int *retval;
d67a03eb 1211{
6a6a1e5f
KM
1212 struct stat sb;
1213 int error;
8429d022 1214 struct nameidata nd;
d67a03eb 1215
7121fdf0 1216 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
dd4c01c2 1217 if (error = namei(&nd))
8429d022 1218 return (error);
dd4c01c2
KM
1219 error = vn_stat(nd.ni_vp, &sb, p);
1220 vput(nd.ni_vp);
6a6a1e5f 1221 if (error)
8429d022 1222 return (error);
6a6a1e5f 1223 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
8429d022 1224 return (error);
d67a03eb
BJ
1225}
1226
5485e062 1227/*
7121fdf0 1228 * Get file status; this version does not follow links.
5485e062 1229 */
9e97623a 1230struct lstat_args {
7121fdf0 1231 char *path;
9e97623a
CT
1232 struct stat *ub;
1233};
6a6a1e5f 1234/* ARGSUSED */
ae9b6dc3 1235lstat(p, uap, retval)
5e00df3b 1236 struct proc *p;
9e97623a 1237 register struct lstat_args *uap;
6a6a1e5f
KM
1238 int *retval;
1239{
fc2aed1e 1240 int error;
49f762b8
KM
1241 struct vnode *vp, *dvp;
1242 struct stat sb, sb1;
8429d022 1243 struct nameidata nd;
5485e062 1244
49f762b8 1245 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
7121fdf0 1246 uap->path, p);
dd4c01c2 1247 if (error = namei(&nd))
8429d022 1248 return (error);
49f762b8
KM
1249 /*
1250 * For symbolic links, always return the attributes of its
1251 * containing directory, except for mode, size, and links.
1252 */
1253 vp = nd.ni_vp;
1254 dvp = nd.ni_dvp;
1255 if (vp->v_type != VLNK) {
1256 if (dvp == vp)
1257 vrele(dvp);
1258 else
1259 vput(dvp);
1260 error = vn_stat(vp, &sb, p);
1261 vput(vp);
1262 if (error)
1263 return (error);
1264 } else {
1265 error = vn_stat(dvp, &sb, p);
1266 vput(dvp);
1267 if (error) {
1268 vput(vp);
1269 return (error);
1270 }
1271 error = vn_stat(vp, &sb1, p);
1272 vput(vp);
1273 if (error)
1274 return (error);
1275 sb.st_mode &= ~S_IFDIR;
1276 sb.st_mode |= S_IFLNK;
1277 sb.st_nlink = sb1.st_nlink;
1278 sb.st_size = sb1.st_size;
1279 sb.st_blocks = sb1.st_blocks;
1280 }
fc2aed1e 1281 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
8429d022 1282 return (error);
d67a03eb
BJ
1283}
1284
201e5411 1285/*
7121fdf0 1286 * Get configurable pathname variables.
201e5411
KM
1287 */
1288struct pathconf_args {
7121fdf0 1289 char *path;
201e5411
KM
1290 int name;
1291};
1292/* ARGSUSED */
1293pathconf(p, uap, retval)
1294 struct proc *p;
1295 register struct pathconf_args *uap;
1296 int *retval;
1297{
1298 int error;
1299 struct nameidata nd;
1300
7121fdf0 1301 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
201e5411
KM
1302 if (error = namei(&nd))
1303 return (error);
1304 error = VOP_PATHCONF(nd.ni_vp, uap->name, retval);
1305 vput(nd.ni_vp);
1306 return (error);
1307}
1308
d67a03eb 1309/*
d4ed1dcd 1310 * Return target name of a symbolic link.
5485e062 1311 */
9e97623a 1312struct readlink_args {
7121fdf0 1313 char *path;
9e97623a
CT
1314 char *buf;
1315 int count;
1316};
6a6a1e5f
KM
1317/* ARGSUSED */
1318readlink(p, uap, retval)
5e00df3b 1319 struct proc *p;
9e97623a 1320 register struct readlink_args *uap;
6a6a1e5f
KM
1321 int *retval;
1322{
fc2aed1e
KM
1323 register struct vnode *vp;
1324 struct iovec aiov;
1325 struct uio auio;
1326 int error;
8429d022 1327 struct nameidata nd;
5485e062 1328
a5368812 1329 CHECKPOINTREF;
7121fdf0 1330 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
dd4c01c2 1331 if (error = namei(&nd))
8429d022 1332 return (error);
dd4c01c2 1333 vp = nd.ni_vp;
7121fdf0 1334 if (vp->v_type != VLNK)
fc2aed1e 1335 error = EINVAL;
7121fdf0
KB
1336 else {
1337 aiov.iov_base = uap->buf;
1338 aiov.iov_len = uap->count;
1339 auio.uio_iov = &aiov;
1340 auio.uio_iovcnt = 1;
1341 auio.uio_offset = 0;
1342 auio.uio_rw = UIO_READ;
1343 auio.uio_segflg = UIO_USERSPACE;
1344 auio.uio_procp = p;
1345 auio.uio_resid = uap->count;
1346 error = VOP_READLINK(vp, &auio, p->p_ucred);
5485e062 1347 }
fc2aed1e 1348 vput(vp);
6a6a1e5f 1349 *retval = uap->count - auio.uio_resid;
a5368812 1350 CHECKREFS("readlink");
8429d022 1351 return (error);
5485e062
BJ
1352}
1353
6995a2cb 1354/*
7121fdf0 1355 * Change flags of a file given a path name.
6995a2cb 1356 */
9e97623a 1357struct chflags_args {
7121fdf0 1358 char *path;
9e97623a
CT
1359 int flags;
1360};
6a6a1e5f
KM
1361/* ARGSUSED */
1362chflags(p, uap, retval)
5e00df3b 1363 struct proc *p;
9e97623a 1364 register struct chflags_args *uap;
6a6a1e5f
KM
1365 int *retval;
1366{
6995a2cb
KM
1367 register struct vnode *vp;
1368 struct vattr vattr;
1369 int error;
8429d022 1370 struct nameidata nd;
6995a2cb 1371
7121fdf0 1372 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
dd4c01c2 1373 if (error = namei(&nd))
8429d022 1374 return (error);
dd4c01c2 1375 vp = nd.ni_vp;
4c5d3e43 1376 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
dbcf7de6 1377 VOP_LOCK(vp);
7121fdf0 1378 if (vp->v_mount->mnt_flag & MNT_RDONLY)
6995a2cb 1379 error = EROFS;
7121fdf0
KB
1380 else {
1381 VATTR_NULL(&vattr);
1382 vattr.va_flags = uap->flags;
1383 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
6995a2cb 1384 }
6995a2cb 1385 vput(vp);
8429d022 1386 return (error);
6995a2cb
KM
1387}
1388
1389/*
1390 * Change flags of a file given a file descriptor.
1391 */
9e97623a
CT
1392struct fchflags_args {
1393 int fd;
1394 int flags;
1395};
6a6a1e5f
KM
1396/* ARGSUSED */
1397fchflags(p, uap, retval)
5e00df3b 1398 struct proc *p;
9e97623a 1399 register struct fchflags_args *uap;
6a6a1e5f
KM
1400 int *retval;
1401{
6995a2cb
KM
1402 struct vattr vattr;
1403 struct vnode *vp;
1404 struct file *fp;
1405 int error;
1406
5e00df3b 1407 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1408 return (error);
6995a2cb 1409 vp = (struct vnode *)fp->f_data;
4c5d3e43 1410 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
6995a2cb 1411 VOP_LOCK(vp);
7121fdf0 1412 if (vp->v_mount->mnt_flag & MNT_RDONLY)
6995a2cb 1413 error = EROFS;
7121fdf0
KB
1414 else {
1415 VATTR_NULL(&vattr);
1416 vattr.va_flags = uap->flags;
1417 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
6995a2cb 1418 }
6995a2cb 1419 VOP_UNLOCK(vp);
8429d022 1420 return (error);
6995a2cb
KM
1421}
1422
4f083fd7
SL
1423/*
1424 * Change mode of a file given path name.
1425 */
9e97623a 1426struct chmod_args {
7121fdf0
KB
1427 char *path;
1428 int mode;
9e97623a 1429};
6a6a1e5f
KM
1430/* ARGSUSED */
1431chmod(p, uap, retval)
5e00df3b 1432 struct proc *p;
9e97623a 1433 register struct chmod_args *uap;
6a6a1e5f
KM
1434 int *retval;
1435{
fc2aed1e
KM
1436 register struct vnode *vp;
1437 struct vattr vattr;
1438 int error;
8429d022 1439 struct nameidata nd;
5485e062 1440
7121fdf0 1441 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
dd4c01c2 1442 if (error = namei(&nd))
8429d022 1443 return (error);
dd4c01c2 1444 vp = nd.ni_vp;
4c5d3e43 1445 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
dbcf7de6 1446 VOP_LOCK(vp);
7121fdf0 1447 if (vp->v_mount->mnt_flag & MNT_RDONLY)
fc2aed1e 1448 error = EROFS;
7121fdf0
KB
1449 else {
1450 VATTR_NULL(&vattr);
1451 vattr.va_mode = uap->mode & ALLPERMS;
1452 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e 1453 }
fc2aed1e 1454 vput(vp);
8429d022 1455 return (error);
528f664c 1456}
f94ceb3b 1457
4f083fd7
SL
1458/*
1459 * Change mode of a file given a file descriptor.
1460 */
9e97623a
CT
1461struct fchmod_args {
1462 int fd;
7121fdf0 1463 int mode;
9e97623a 1464};
6a6a1e5f
KM
1465/* ARGSUSED */
1466fchmod(p, uap, retval)
5e00df3b 1467 struct proc *p;
9e97623a 1468 register struct fchmod_args *uap;
6a6a1e5f
KM
1469 int *retval;
1470{
fc2aed1e
KM
1471 struct vattr vattr;
1472 struct vnode *vp;
1473 struct file *fp;
1474 int error;
1475
5e00df3b 1476 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1477 return (error);
fc2aed1e 1478 vp = (struct vnode *)fp->f_data;
4c5d3e43 1479 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
fc2aed1e 1480 VOP_LOCK(vp);
7121fdf0 1481 if (vp->v_mount->mnt_flag & MNT_RDONLY)
fc2aed1e 1482 error = EROFS;
7121fdf0
KB
1483 else {
1484 VATTR_NULL(&vattr);
1485 vattr.va_mode = uap->mode & ALLPERMS;
1486 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
f94ceb3b 1487 }
fc2aed1e 1488 VOP_UNLOCK(vp);
8429d022 1489 return (error);
5485e062
BJ
1490}
1491
4f083fd7
SL
1492/*
1493 * Set ownership given a path name.
1494 */
9e97623a 1495struct chown_args {
7121fdf0 1496 char *path;
9e97623a
CT
1497 int uid;
1498 int gid;
1499};
6a6a1e5f
KM
1500/* ARGSUSED */
1501chown(p, uap, retval)
5e00df3b 1502 struct proc *p;
9e97623a 1503 register struct chown_args *uap;
6a6a1e5f
KM
1504 int *retval;
1505{
fc2aed1e
KM
1506 register struct vnode *vp;
1507 struct vattr vattr;
1508 int error;
8429d022 1509 struct nameidata nd;
d67a03eb 1510
12561664 1511 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
dd4c01c2 1512 if (error = namei(&nd))
8429d022 1513 return (error);
dd4c01c2 1514 vp = nd.ni_vp;
4c5d3e43 1515 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
dbcf7de6 1516 VOP_LOCK(vp);
7121fdf0 1517 if (vp->v_mount->mnt_flag & MNT_RDONLY)
fc2aed1e 1518 error = EROFS;
7121fdf0
KB
1519 else {
1520 VATTR_NULL(&vattr);
1521 vattr.va_uid = uap->uid;
1522 vattr.va_gid = uap->gid;
1523 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e 1524 }
fc2aed1e 1525 vput(vp);
8429d022 1526 return (error);
528f664c 1527}
f94ceb3b 1528
4f083fd7
SL
1529/*
1530 * Set ownership given a file descriptor.
1531 */
9e97623a
CT
1532struct fchown_args {
1533 int fd;
1534 int uid;
1535 int gid;
1536};
6a6a1e5f
KM
1537/* ARGSUSED */
1538fchown(p, uap, retval)
5e00df3b 1539 struct proc *p;
9e97623a 1540 register struct fchown_args *uap;
6a6a1e5f
KM
1541 int *retval;
1542{
fc2aed1e
KM
1543 struct vattr vattr;
1544 struct vnode *vp;
1545 struct file *fp;
1546 int error;
1547
5e00df3b 1548 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1549 return (error);
fc2aed1e 1550 vp = (struct vnode *)fp->f_data;
4c5d3e43 1551 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
fc2aed1e 1552 VOP_LOCK(vp);
7121fdf0 1553 if (vp->v_mount->mnt_flag & MNT_RDONLY)
fc2aed1e 1554 error = EROFS;
7121fdf0
KB
1555 else {
1556 VATTR_NULL(&vattr);
1557 vattr.va_uid = uap->uid;
1558 vattr.va_gid = uap->gid;
1559 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e 1560 }
fc2aed1e 1561 VOP_UNLOCK(vp);
8429d022 1562 return (error);
d67a03eb
BJ
1563}
1564
6a6a1e5f
KM
1565/*
1566 * Set the access and modification times of a file.
1567 */
9e97623a 1568struct utimes_args {
7121fdf0 1569 char *path;
9e97623a
CT
1570 struct timeval *tptr;
1571};
6a6a1e5f
KM
1572/* ARGSUSED */
1573utimes(p, uap, retval)
5e00df3b 1574 struct proc *p;
9e97623a 1575 register struct utimes_args *uap;
6a6a1e5f
KM
1576 int *retval;
1577{
fc2aed1e 1578 register struct vnode *vp;
bb1b75f4 1579 struct timeval tv[2];
fc2aed1e 1580 struct vattr vattr;
8e88b0cd 1581 int error;
8429d022 1582 struct nameidata nd;
bb1b75f4 1583
f8ee9a49
KB
1584 VATTR_NULL(&vattr);
1585 if (uap->tptr == NULL) {
1586 microtime(&tv[0]);
1587 tv[1] = tv[0];
fcba749b 1588 vattr.va_vaflags |= VA_UTIMES_NULL;
f8ee9a49
KB
1589 } else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
1590 return (error);
7121fdf0 1591 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
dd4c01c2 1592 if (error = namei(&nd))
8429d022 1593 return (error);
dd4c01c2 1594 vp = nd.ni_vp;
4c5d3e43 1595 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
dbcf7de6 1596 VOP_LOCK(vp);
7121fdf0 1597 if (vp->v_mount->mnt_flag & MNT_RDONLY)
fc2aed1e 1598 error = EROFS;
7121fdf0
KB
1599 else {
1600 vattr.va_atime.ts_sec = tv[0].tv_sec;
1601 vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;
1602 vattr.va_mtime.ts_sec = tv[1].tv_sec;
1603 vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;
1604 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
bb1b75f4 1605 }
fc2aed1e 1606 vput(vp);
8429d022 1607 return (error);
d67a03eb 1608}
64d3a787 1609
7121fdf0
KB
1610/*
1611 * Truncate a file given its path name.
1612 */
95c0eb1e 1613struct truncate_args {
7121fdf0 1614 char *path;
2f2b3b3d
CT
1615 int pad;
1616 off_t length;
1617};
be320a2b 1618/* ARGSUSED */
201e5411 1619truncate(p, uap, retval)
5e00df3b 1620 struct proc *p;
95c0eb1e 1621 register struct truncate_args *uap;
6a6a1e5f
KM
1622 int *retval;
1623{
fc2aed1e
KM
1624 register struct vnode *vp;
1625 struct vattr vattr;
1626 int error;
8429d022 1627 struct nameidata nd;
528f664c 1628
7121fdf0 1629 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
dd4c01c2 1630 if (error = namei(&nd))
8429d022 1631 return (error);
dd4c01c2 1632 vp = nd.ni_vp;
4c5d3e43 1633 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
dbcf7de6 1634 VOP_LOCK(vp);
7121fdf0 1635 if (vp->v_type == VDIR)
fc2aed1e 1636 error = EISDIR;
7121fdf0
KB
1637 else if ((error = vn_writechk(vp)) == 0 &&
1638 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
1639 VATTR_NULL(&vattr);
1640 vattr.va_size = uap->length;
1641 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
528f664c 1642 }
fc2aed1e 1643 vput(vp);
8429d022 1644 return (error);
528f664c
SL
1645}
1646
7121fdf0
KB
1647/*
1648 * Truncate a file given a file descriptor.
1649 */
95c0eb1e 1650struct ftruncate_args {
2f2b3b3d
CT
1651 int fd;
1652 int pad;
1653 off_t length;
1654};
6a6a1e5f 1655/* ARGSUSED */
201e5411 1656ftruncate(p, uap, retval)
5e00df3b 1657 struct proc *p;
95c0eb1e 1658 register struct ftruncate_args *uap;
6a6a1e5f
KM
1659 int *retval;
1660{
fc2aed1e
KM
1661 struct vattr vattr;
1662 struct vnode *vp;
528f664c 1663 struct file *fp;
fc2aed1e
KM
1664 int error;
1665
5e00df3b 1666 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1667 return (error);
fc2aed1e 1668 if ((fp->f_flag & FWRITE) == 0)
8429d022 1669 return (EINVAL);
fc2aed1e 1670 vp = (struct vnode *)fp->f_data;
4c5d3e43 1671 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
fc2aed1e 1672 VOP_LOCK(vp);
7121fdf0 1673 if (vp->v_type == VDIR)
fc2aed1e 1674 error = EISDIR;
7121fdf0
KB
1675 else if ((error = vn_writechk(vp)) == 0) {
1676 VATTR_NULL(&vattr);
1677 vattr.va_size = uap->length;
1678 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
528f664c 1679 }
fc2aed1e 1680 VOP_UNLOCK(vp);
8429d022 1681 return (error);
4f083fd7
SL
1682}
1683
2f2b3b3d
CT
1684#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1685/*
1686 * Truncate a file given its path name.
1687 */
95c0eb1e 1688struct otruncate_args {
7121fdf0 1689 char *path;
9e97623a
CT
1690 long length;
1691};
2f2b3b3d 1692/* ARGSUSED */
51a9a1cf 1693otruncate(p, uap, retval)
2f2b3b3d 1694 struct proc *p;
95c0eb1e 1695 register struct otruncate_args *uap;
2f2b3b3d
CT
1696 int *retval;
1697{
95c0eb1e 1698 struct truncate_args nuap;
2f2b3b3d 1699
7121fdf0 1700 nuap.path = uap->path;
2f2b3b3d 1701 nuap.length = uap->length;
95c0eb1e 1702 return (truncate(p, &nuap, retval));
2f2b3b3d
CT
1703}
1704
1705/*
1706 * Truncate a file given a file descriptor.
1707 */
95c0eb1e 1708struct oftruncate_args {
9e97623a
CT
1709 int fd;
1710 long length;
1711};
2f2b3b3d 1712/* ARGSUSED */
51a9a1cf 1713oftruncate(p, uap, retval)
2f2b3b3d 1714 struct proc *p;
95c0eb1e 1715 register struct oftruncate_args *uap;
2f2b3b3d
CT
1716 int *retval;
1717{
95c0eb1e 1718 struct ftruncate_args nuap;
2f2b3b3d
CT
1719
1720 nuap.fd = uap->fd;
1721 nuap.length = uap->length;
95c0eb1e 1722 return (ftruncate(p, &nuap, retval));
2f2b3b3d
CT
1723}
1724#endif /* COMPAT_43 || COMPAT_SUNOS */
1725
4f083fd7 1726/*
7121fdf0 1727 * Sync an open file.
4f083fd7 1728 */
9e97623a
CT
1729struct fsync_args {
1730 int fd;
1731};
6a6a1e5f
KM
1732/* ARGSUSED */
1733fsync(p, uap, retval)
5e00df3b 1734 struct proc *p;
9e97623a 1735 struct fsync_args *uap;
6a6a1e5f
KM
1736 int *retval;
1737{
e79467ea 1738 register struct vnode *vp;
4f083fd7 1739 struct file *fp;
fc2aed1e 1740 int error;
4f083fd7 1741
5e00df3b 1742 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1743 return (error);
e79467ea
KM
1744 vp = (struct vnode *)fp->f_data;
1745 VOP_LOCK(vp);
09d2ef1a 1746 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
e79467ea 1747 VOP_UNLOCK(vp);
8429d022 1748 return (error);
528f664c
SL
1749}
1750
4f083fd7 1751/*
7121fdf0
KB
1752 * Rename files. Source and destination must either both be directories,
1753 * or both not be directories. If target is a directory, it must be empty.
4f083fd7 1754 */
9e97623a
CT
1755struct rename_args {
1756 char *from;
1757 char *to;
1758};
6a6a1e5f
KM
1759/* ARGSUSED */
1760rename(p, uap, retval)
5e00df3b 1761 struct proc *p;
9e97623a 1762 register struct rename_args *uap;
6a6a1e5f
KM
1763 int *retval;
1764{
fc2aed1e 1765 register struct vnode *tvp, *fvp, *tdvp;
5718fad3 1766 struct nameidata fromnd, tond;
fc2aed1e 1767 int error;
4f083fd7 1768
a5368812 1769 CHECKPOINTREF;
dd4c01c2
KM
1770 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
1771 uap->from, p);
1772 if (error = namei(&fromnd))
8429d022 1773 return (error);
5718fad3 1774 fvp = fromnd.ni_vp;
dd4c01c2
KM
1775 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
1776 UIO_USERSPACE, uap->to, p);
1777 if (error = namei(&tond)) {
cfef4373 1778 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
5718fad3 1779 vrele(fromnd.ni_dvp);
66955caf
KM
1780 vrele(fvp);
1781 goto out1;
1782 }
fc2aed1e
KM
1783 tdvp = tond.ni_dvp;
1784 tvp = tond.ni_vp;
1785 if (tvp != NULL) {
1786 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
9259ee95 1787 error = ENOTDIR;
fc2aed1e
KM
1788 goto out;
1789 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
9259ee95 1790 error = EISDIR;
fc2aed1e 1791 goto out;
a5390dce 1792 }
64d3a787 1793 }
fe562f32 1794 if (fvp == tdvp)
fc2aed1e 1795 error = EINVAL;
fe562f32 1796 /*
5718fad3
KM
1797 * If source is the same as the destination (that is the
1798 * same inode number with the same name in the same directory),
fe562f32
KM
1799 * then there is nothing to do.
1800 */
5718fad3 1801 if (fvp == tvp && fromnd.ni_dvp == tdvp &&
dd4c01c2
KM
1802 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1803 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1804 fromnd.ni_cnd.cn_namelen))
fe562f32 1805 error = -1;
fc2aed1e 1806out:
66955caf 1807 if (!error) {
4c5d3e43 1808 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
e62d4143 1809 if (fromnd.ni_dvp != tdvp)
4c5d3e43 1810 VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
e62d4143 1811 if (tvp)
4c5d3e43 1812 VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
cfef4373
JH
1813 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1814 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
66955caf 1815 } else {
cfef4373 1816 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
6c44e83b
KM
1817 if (tdvp == tvp)
1818 vrele(tdvp);
1819 else
1820 vput(tdvp);
66955caf
KM
1821 if (tvp)
1822 vput(tvp);
cfef4373 1823 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
5718fad3 1824 vrele(fromnd.ni_dvp);
66955caf 1825 vrele(fvp);
64d3a787 1826 }
c03959f9 1827 p->p_spare[1]--;
5718fad3 1828 vrele(tond.ni_startdir);
dd4c01c2 1829 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
fc2aed1e 1830out1:
c03959f9 1831 p->p_spare[1]--;
bb9644de
KM
1832 if (fromnd.ni_startdir)
1833 vrele(fromnd.ni_startdir);
dd4c01c2 1834 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
a5368812 1835 CHECKREFS("rename");
fe562f32 1836 if (error == -1)
8429d022
MK
1837 return (0);
1838 return (error);
64d3a787 1839}
88a7a62a 1840
88a7a62a 1841/*
7121fdf0 1842 * Make a directory file.
88a7a62a 1843 */
9e97623a 1844struct mkdir_args {
7121fdf0
KB
1845 char *path;
1846 int mode;
9e97623a 1847};
6a6a1e5f
KM
1848/* ARGSUSED */
1849mkdir(p, uap, retval)
5e00df3b 1850 struct proc *p;
9e97623a 1851 register struct mkdir_args *uap;
6a6a1e5f
KM
1852 int *retval;
1853{
fc2aed1e
KM
1854 register struct vnode *vp;
1855 struct vattr vattr;
1856 int error;
8429d022 1857 struct nameidata nd;
88a7a62a 1858
a5368812 1859 CHECKPOINTREF;
7121fdf0 1860 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
dd4c01c2 1861 if (error = namei(&nd))
8429d022 1862 return (error);
dd4c01c2 1863 vp = nd.ni_vp;
fc2aed1e 1864 if (vp != NULL) {
dd4c01c2
KM
1865 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1866 if (nd.ni_dvp == vp)
1867 vrele(nd.ni_dvp);
6c44e83b 1868 else
dd4c01c2 1869 vput(nd.ni_dvp);
66955caf 1870 vrele(vp);
a5368812 1871 CHECKREFS("mkdir1");
8429d022 1872 return (EEXIST);
88a7a62a 1873 }
3ee1461b 1874 VATTR_NULL(&vattr);
fc2aed1e 1875 vattr.va_type = VDIR;
7121fdf0 1876 vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
4c5d3e43 1877 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
dd4c01c2 1878 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
5dfd04f0 1879 if (!error)
dd4c01c2 1880 vput(nd.ni_vp);
a5368812 1881 CHECKREFS("mkdir2");
8429d022 1882 return (error);
88a7a62a
SL
1883}
1884
1885/*
7121fdf0 1886 * Remove a directory file.
88a7a62a 1887 */
9e97623a 1888struct rmdir_args {
7121fdf0 1889 char *path;
9e97623a 1890};
6a6a1e5f
KM
1891/* ARGSUSED */
1892rmdir(p, uap, retval)
5e00df3b 1893 struct proc *p;
9e97623a 1894 struct rmdir_args *uap;
6a6a1e5f
KM
1895 int *retval;
1896{
fc2aed1e
KM
1897 register struct vnode *vp;
1898 int error;
8429d022 1899 struct nameidata nd;
88a7a62a 1900
a5368812 1901 CHECKPOINTREF;
7121fdf0 1902 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p);
dd4c01c2 1903 if (error = namei(&nd))
8429d022 1904 return (error);
dd4c01c2 1905 vp = nd.ni_vp;
fc2aed1e
KM
1906 if (vp->v_type != VDIR) {
1907 error = ENOTDIR;
88a7a62a
SL
1908 goto out;
1909 }
1910 /*
fc2aed1e 1911 * No rmdir "." please.
88a7a62a 1912 */
dd4c01c2 1913 if (nd.ni_dvp == vp) {
fc2aed1e 1914 error = EINVAL;
88a7a62a
SL
1915 goto out;
1916 }
1917 /*
d4ed1dcd 1918 * The root of a mounted filesystem cannot be deleted.
88a7a62a 1919 */
fc2aed1e
KM
1920 if (vp->v_flag & VROOT)
1921 error = EBUSY;
88a7a62a 1922out:
66955caf 1923 if (!error) {
4c5d3e43
KM
1924 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1925 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
dd4c01c2 1926 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
66955caf 1927 } else {
dd4c01c2
KM
1928 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1929 if (nd.ni_dvp == vp)
1930 vrele(nd.ni_dvp);
6c44e83b 1931 else
dd4c01c2 1932 vput(nd.ni_dvp);
66955caf
KM
1933 vput(vp);
1934 }
a5368812 1935 CHECKREFS("rmdir");
8429d022 1936 return (error);
88a7a62a
SL
1937}
1938
3d92fa10
KM
1939#ifdef COMPAT_43
1940/*
1941 * Read a block of directory entries in a file system independent format.
1942 */
9e97623a
CT
1943struct ogetdirentries_args {
1944 int fd;
1945 char *buf;
7121fdf0 1946 u_int count;
9e97623a
CT
1947 long *basep;
1948};
3d92fa10
KM
1949ogetdirentries(p, uap, retval)
1950 struct proc *p;
9e97623a 1951 register struct ogetdirentries_args *uap;
3d92fa10
KM
1952 int *retval;
1953{
3d92fa10
KM
1954 register struct vnode *vp;
1955 struct file *fp;
1956 struct uio auio, kuio;
1957 struct iovec aiov, kiov;
1958 struct dirent *dp, *edp;
1959 caddr_t dirbuf;
165bf940 1960 int error, eofflag, readcnt;
d80c3f56 1961 long loff;
3d92fa10
KM
1962
1963 if (error = getvnode(p->p_fd, uap->fd, &fp))
1964 return (error);
1965 if ((fp->f_flag & FREAD) == 0)
1966 return (EBADF);
1967 vp = (struct vnode *)fp->f_data;
165bf940 1968unionread:
3d92fa10
KM
1969 if (vp->v_type != VDIR)
1970 return (EINVAL);
1971 aiov.iov_base = uap->buf;
1972 aiov.iov_len = uap->count;
1973 auio.uio_iov = &aiov;
1974 auio.uio_iovcnt = 1;
1975 auio.uio_rw = UIO_READ;
1976 auio.uio_segflg = UIO_USERSPACE;
1977 auio.uio_procp = p;
1978 auio.uio_resid = uap->count;
1979 VOP_LOCK(vp);
d80c3f56 1980 loff = auio.uio_offset = fp->f_offset;
3d92fa10 1981# if (BYTE_ORDER != LITTLE_ENDIAN)
a801b5ab 1982 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
165bf940
KM
1983 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
1984 (u_long *)0, 0);
a801b5ab
KM
1985 fp->f_offset = auio.uio_offset;
1986 } else
3d92fa10
KM
1987# endif
1988 {
1989 kuio = auio;
1990 kuio.uio_iov = &kiov;
1991 kuio.uio_segflg = UIO_SYSSPACE;
1992 kiov.iov_len = uap->count;
1993 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
1994 kiov.iov_base = dirbuf;
165bf940
KM
1995 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
1996 (u_long *)0, 0);
a801b5ab 1997 fp->f_offset = kuio.uio_offset;
3d92fa10
KM
1998 if (error == 0) {
1999 readcnt = uap->count - kuio.uio_resid;
2000 edp = (struct dirent *)&dirbuf[readcnt];
2001 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
3d92fa10 2002# if (BYTE_ORDER == LITTLE_ENDIAN)
d80c3f56 2003 /*
30445fe6
KM
2004 * The expected low byte of
2005 * dp->d_namlen is our dp->d_type.
2006 * The high MBZ byte of dp->d_namlen
2007 * is our dp->d_namlen.
d80c3f56 2008 */
30445fe6
KM
2009 dp->d_type = dp->d_namlen;
2010 dp->d_namlen = 0;
2011# else
2012 /*
2013 * The dp->d_type is the high byte
2014 * of the expected dp->d_namlen,
2015 * so must be zero'ed.
2016 */
2017 dp->d_type = 0;
3d92fa10
KM
2018# endif
2019 if (dp->d_reclen > 0) {
2020 dp = (struct dirent *)
2021 ((char *)dp + dp->d_reclen);
2022 } else {
2023 error = EIO;
2024 break;
2025 }
2026 }
2027 if (dp >= edp)
2028 error = uiomove(dirbuf, readcnt, &auio);
2029 }
2030 FREE(dirbuf, M_TEMP);
2031 }
3d92fa10
KM
2032 VOP_UNLOCK(vp);
2033 if (error)
2034 return (error);
165bf940
KM
2035
2036#ifdef UNION
2037{
2038 extern int (**union_vnodeop_p)();
2039 extern struct vnode *union_lowervp __P((struct vnode *));
2040
2041 if ((uap->count == auio.uio_resid) &&
2042 (vp->v_op == union_vnodeop_p)) {
2043 struct vnode *lvp;
2044
2045 lvp = union_lowervp(vp);
88edbcd4
JSP
2046 if (lvp != NULLVP) {
2047 struct vattr va;
2048
2049 /*
2050 * If the directory is opaque,
2051 * then don't show lower entries
2052 */
2053 error = VOP_GETATTR(vp, &va, fp->f_cred, p);
2054 if (va.va_flags & OPAQUE) {
2055 vrele(lvp);
2056 lvp = NULL;
2057 }
2058 }
2059
165bf940
KM
2060 if (lvp != NULLVP) {
2061 VOP_LOCK(lvp);
2062 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
2063 VOP_UNLOCK(lvp);
2064
2065 if (error) {
2066 vrele(lvp);
2067 return (error);
2068 }
2069 fp->f_data = (caddr_t) lvp;
2070 fp->f_offset = 0;
2071 error = vn_close(vp, FREAD, fp->f_cred, p);
2072 if (error)
2073 return (error);
2074 vp = lvp;
2075 goto unionread;
2076 }
2077 }
2078}
2079#endif /* UNION */
2080
2081 if ((uap->count == auio.uio_resid) &&
2082 (vp->v_flag & VROOT) &&
2083 (vp->v_mount->mnt_flag & MNT_UNION)) {
2084 struct vnode *tvp = vp;
2085 vp = vp->v_mount->mnt_vnodecovered;
2086 VREF(vp);
2087 fp->f_data = (caddr_t) vp;
2088 fp->f_offset = 0;
2089 vrele(tvp);
2090 goto unionread;
2091 }
d80c3f56 2092 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
3d92fa10
KM
2093 *retval = uap->count - auio.uio_resid;
2094 return (error);
2095}
165bf940 2096#endif /* COMPAT_43 */
3d92fa10 2097
fc2aed1e 2098/*
d4ed1dcd 2099 * Read a block of directory entries in a file system independent format.
fc2aed1e 2100 */
9e97623a
CT
2101struct getdirentries_args {
2102 int fd;
2103 char *buf;
7121fdf0 2104 u_int count;
9e97623a
CT
2105 long *basep;
2106};
6a6a1e5f 2107getdirentries(p, uap, retval)
5e00df3b 2108 struct proc *p;
9e97623a 2109 register struct getdirentries_args *uap;
6a6a1e5f
KM
2110 int *retval;
2111{
e79467ea 2112 register struct vnode *vp;
8462a185 2113 struct file *fp;
fc2aed1e
KM
2114 struct uio auio;
2115 struct iovec aiov;
d80c3f56 2116 long loff;
165bf940 2117 int error, eofflag;
fc2aed1e 2118
5e00df3b 2119 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 2120 return (error);
fc2aed1e 2121 if ((fp->f_flag & FREAD) == 0)
8429d022 2122 return (EBADF);
e79467ea 2123 vp = (struct vnode *)fp->f_data;
95a9cadb 2124unionread:
e79467ea 2125 if (vp->v_type != VDIR)
8429d022 2126 return (EINVAL);
fc2aed1e
KM
2127 aiov.iov_base = uap->buf;
2128 aiov.iov_len = uap->count;
2129 auio.uio_iov = &aiov;
2130 auio.uio_iovcnt = 1;
2131 auio.uio_rw = UIO_READ;
2132 auio.uio_segflg = UIO_USERSPACE;
2c69fe14 2133 auio.uio_procp = p;
fc2aed1e 2134 auio.uio_resid = uap->count;
e79467ea 2135 VOP_LOCK(vp);
d80c3f56 2136 loff = auio.uio_offset = fp->f_offset;
165bf940 2137 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (u_long *)0, 0);
e79467ea
KM
2138 fp->f_offset = auio.uio_offset;
2139 VOP_UNLOCK(vp);
2140 if (error)
8429d022 2141 return (error);
57b06c10
JSP
2142
2143#ifdef UNION
2144{
2145 extern int (**union_vnodeop_p)();
2146 extern struct vnode *union_lowervp __P((struct vnode *));
2147
2148 if ((uap->count == auio.uio_resid) &&
2149 (vp->v_op == union_vnodeop_p)) {
cafc3164 2150 struct vnode *lvp;
57b06c10 2151
cafc3164 2152 lvp = union_lowervp(vp);
88edbcd4
JSP
2153 if (lvp != NULLVP) {
2154 struct vattr va;
2155
2156 /*
2157 * If the directory is opaque,
2158 * then don't show lower entries
2159 */
2160 error = VOP_GETATTR(vp, &va, fp->f_cred, p);
2161 if (va.va_flags & OPAQUE) {
2162 vrele(lvp);
2163 lvp = NULL;
2164 }
2165 }
2166
cafc3164
JSP
2167 if (lvp != NULLVP) {
2168 VOP_LOCK(lvp);
165bf940 2169 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
cafc3164 2170 VOP_UNLOCK(lvp);
57b06c10
JSP
2171
2172 if (error) {
cafc3164 2173 vrele(lvp);
57b06c10
JSP
2174 return (error);
2175 }
cafc3164 2176 fp->f_data = (caddr_t) lvp;
57b06c10 2177 fp->f_offset = 0;
cafc3164 2178 error = vn_close(vp, FREAD, fp->f_cred, p);
57b06c10
JSP
2179 if (error)
2180 return (error);
cafc3164 2181 vp = lvp;
57b06c10
JSP
2182 goto unionread;
2183 }
2184 }
2185}
2186#endif
2187
95a9cadb
JSP
2188 if ((uap->count == auio.uio_resid) &&
2189 (vp->v_flag & VROOT) &&
2190 (vp->v_mount->mnt_flag & MNT_UNION)) {
2191 struct vnode *tvp = vp;
2192 vp = vp->v_mount->mnt_vnodecovered;
2193 VREF(vp);
2194 fp->f_data = (caddr_t) vp;
2195 fp->f_offset = 0;
2196 vrele(tvp);
2197 goto unionread;
2198 }
d80c3f56 2199 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
6a6a1e5f 2200 *retval = uap->count - auio.uio_resid;
8429d022 2201 return (error);
88a7a62a
SL
2202}
2203
2204/*
d4ed1dcd 2205 * Set the mode mask for creation of filesystem nodes.
88a7a62a 2206 */
9e97623a 2207struct umask_args {
7121fdf0 2208 int newmask;
9e97623a
CT
2209};
2210mode_t /* XXX */
6a6a1e5f 2211umask(p, uap, retval)
5e00df3b 2212 struct proc *p;
9e97623a 2213 struct umask_args *uap;
6a6a1e5f
KM
2214 int *retval;
2215{
7121fdf0 2216 register struct filedesc *fdp;
88a7a62a 2217
7121fdf0 2218 fdp = p->p_fd;
5e00df3b 2219 *retval = fdp->fd_cmask;
7121fdf0 2220 fdp->fd_cmask = uap->newmask & ALLPERMS;
8429d022 2221 return (0);
fc2aed1e
KM
2222}
2223
b0a98f13
MT
2224/*
2225 * Void all references to file by ripping underlying filesystem
2226 * away from vnode.
2227 */
9e97623a 2228struct revoke_args {
7121fdf0 2229 char *path;
9e97623a 2230};
6a6a1e5f
KM
2231/* ARGSUSED */
2232revoke(p, uap, retval)
5e00df3b 2233 struct proc *p;
9e97623a 2234 register struct revoke_args *uap;
6a6a1e5f
KM
2235 int *retval;
2236{
b0a98f13
MT
2237 register struct vnode *vp;
2238 struct vattr vattr;
2239 int error;
8429d022 2240 struct nameidata nd;
b0a98f13 2241
7121fdf0 2242 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
dd4c01c2 2243 if (error = namei(&nd))
8429d022 2244 return (error);
dd4c01c2 2245 vp = nd.ni_vp;
b0a98f13
MT
2246 if (vp->v_type != VCHR && vp->v_type != VBLK) {
2247 error = EINVAL;
2248 goto out;
2249 }
2c69fe14 2250 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
b0a98f13 2251 goto out;
8429d022
MK
2252 if (p->p_ucred->cr_uid != vattr.va_uid &&
2253 (error = suser(p->p_ucred, &p->p_acflag)))
b0a98f13 2254 goto out;
8b81d198 2255 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
c9345cca 2256 vgoneall(vp);
b0a98f13
MT
2257out:
2258 vrele(vp);
8429d022 2259 return (error);
b0a98f13
MT
2260}
2261
d4ed1dcd
KM
2262/*
2263 * Convert a user file descriptor to a kernel file entry.
2264 */
7121fdf0 2265getvnode(fdp, fd, fpp)
5e00df3b 2266 struct filedesc *fdp;
fc2aed1e 2267 struct file **fpp;
7121fdf0 2268 int fd;
fc2aed1e
KM
2269{
2270 struct file *fp;
2271
7121fdf0
KB
2272 if ((u_int)fd >= fdp->fd_nfiles ||
2273 (fp = fdp->fd_ofiles[fd]) == NULL)
fc2aed1e
KM
2274 return (EBADF);
2275 if (fp->f_type != DTYPE_VNODE)
2276 return (EINVAL);
2277 *fpp = fp;
2278 return (0);
88a7a62a 2279}