PageRenderTime 49ms CodeModel.GetById 9ms RepoModel.GetById 1ms app.codeStats 0ms

/netbsd/src/sys/kern/vfs_syscalls.c

https://bitbucket.org/mischief/oskit
C | 2114 lines | 1609 code | 115 blank | 390 comment | 363 complexity | 2e4908f50cc0f97808dd585eea860811 MD5 | raw file
Possible License(s): GPL-2.0
  1. /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */
  2. /*
  3. * Copyright (c) 1989, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. * (c) UNIX System Laboratories, Inc.
  6. * All or some portions of this file are derived from material licensed
  7. * to the University of California by American Telephone and Telegraph
  8. * Co. or Unix System Laboratories, Inc. and are reproduced herein with
  9. * the permission of UNIX System Laboratories, Inc.
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions
  13. * are met:
  14. * 1. Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. * 2. Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in the
  18. * documentation and/or other materials provided with the distribution.
  19. * 3. All advertising materials mentioning features or use of this software
  20. * must display the following acknowledgement:
  21. * This product includes software developed by the University of
  22. * California, Berkeley and its contributors.
  23. * 4. Neither the name of the University nor the names of its contributors
  24. * may be used to endorse or promote products derived from this software
  25. * without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  28. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  31. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  32. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  33. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  34. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  35. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  36. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  37. * SUCH DAMAGE.
  38. *
  39. * @(#)vfs_syscalls.c 8.28 (Berkeley) 12/10/94
  40. */
  41. #include <sys/param.h>
  42. #include <sys/systm.h>
  43. #include <sys/namei.h>
  44. #include <sys/filedesc.h>
  45. #include <sys/kernel.h>
  46. #include <sys/file.h>
  47. #include <sys/stat.h>
  48. #include <sys/vnode.h>
  49. #include <sys/mount.h>
  50. #include <sys/proc.h>
  51. #include <sys/uio.h>
  52. #include <sys/malloc.h>
  53. #include <sys/dirent.h>
  54. #include <sys/syscallargs.h>
  55. #include <vm/vm.h>
  56. #include <sys/sysctl.h>
  57. static int change_dir __P((struct nameidata *, struct proc *));
  58. void checkdirs __P((struct vnode *));
  59. int dounmount __P((struct mount *, int, struct proc *));
  60. /*
  61. * Virtual File System System Calls
  62. */
  63. /*
  64. * Mount a file system.
  65. */
  66. /* ARGSUSED */
  67. int
  68. sys_mount(p, v, retval)
  69. struct proc *p;
  70. void *v;
  71. register_t *retval;
  72. {
  73. register struct sys_mount_args /* {
  74. syscallarg(char *) type;
  75. syscallarg(char *) path;
  76. syscallarg(int) flags;
  77. syscallarg(caddr_t) data;
  78. } */ *uap = v;
  79. register struct vnode *vp;
  80. register struct mount *mp;
  81. int error, flag = 0;
  82. u_long fsindex = 0;
  83. char fstypename[MFSNAMELEN];
  84. struct vattr va;
  85. struct nameidata nd;
  86. /*
  87. * Get vnode to be covered
  88. */
  89. NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  90. SCARG(uap, path), p);
  91. if ((error = namei(&nd)) != 0)
  92. return (error);
  93. vp = nd.ni_vp;
  94. if (SCARG(uap, flags) & MNT_UPDATE) {
  95. if ((vp->v_flag & VROOT) == 0) {
  96. vput(vp);
  97. return (EINVAL);
  98. }
  99. mp = vp->v_mount;
  100. flag = mp->mnt_flag;
  101. /*
  102. * We only allow the filesystem to be reloaded if it
  103. * is currently mounted read-only.
  104. */
  105. if ((SCARG(uap, flags) & MNT_RELOAD) &&
  106. ((mp->mnt_flag & MNT_RDONLY) == 0)) {
  107. vput(vp);
  108. return (EOPNOTSUPP); /* Needs translation */
  109. }
  110. mp->mnt_flag |=
  111. SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
  112. /*
  113. * Only root, or the user that did the original mount is
  114. * permitted to update it.
  115. */
  116. if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
  117. (error = suser(p->p_ucred, &p->p_acflag))) {
  118. vput(vp);
  119. return (error);
  120. }
  121. /*
  122. * Do not allow NFS export by non-root users. Silently
  123. * enforce MNT_NOSUID and MNT_NODEV for non-root users.
  124. */
  125. if (p->p_ucred->cr_uid != 0) {
  126. if (SCARG(uap, flags) & MNT_EXPORTED) {
  127. vput(vp);
  128. return (EPERM);
  129. }
  130. SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
  131. }
  132. VOP_UNLOCK(vp);
  133. goto update;
  134. }
  135. /*
  136. * If the user is not root, ensure that they own the directory
  137. * onto which we are attempting to mount.
  138. */
  139. if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
  140. (va.va_uid != p->p_ucred->cr_uid &&
  141. (error = suser(p->p_ucred, &p->p_acflag)))) {
  142. vput(vp);
  143. return (error);
  144. }
  145. /*
  146. * Do not allow NFS export by non-root users. Silently
  147. * enforce MNT_NOSUID and MNT_NODEV for non-root users.
  148. */
  149. if (p->p_ucred->cr_uid != 0) {
  150. if (SCARG(uap, flags) & MNT_EXPORTED) {
  151. vput(vp);
  152. return (EPERM);
  153. }
  154. SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
  155. }
  156. if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
  157. return (error);
  158. if (vp->v_type != VDIR) {
  159. vput(vp);
  160. return (ENOTDIR);
  161. }
  162. error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL);
  163. if (error) {
  164. #if defined(COMPAT_09) || defined(COMPAT_43)
  165. /*
  166. * Historically filesystem types were identified by number.
  167. * If we get an integer for the filesystem type instead of a
  168. * string, we check to see if it matches one of the historic
  169. * filesystem types.
  170. */
  171. fsindex = (u_long)SCARG(uap, type);
  172. if (fsindex >= nvfssw || vfssw[fsindex] == NULL) {
  173. vput(vp);
  174. return (ENODEV);
  175. }
  176. strncpy(fstypename, vfssw[fsindex]->vfs_name, MFSNAMELEN);
  177. #else
  178. vput(vp);
  179. return (error);
  180. #endif
  181. }
  182. #ifdef COMPAT_10
  183. /* Accept `ufs' as an alias for `ffs'. */
  184. if (!strncmp(fstypename, "ufs", MFSNAMELEN))
  185. strncpy(fstypename, "ffs", MFSNAMELEN);
  186. #endif
  187. for (fsindex = 0; fsindex < nvfssw; fsindex++)
  188. if (vfssw[fsindex] != NULL &&
  189. !strncmp(vfssw[fsindex]->vfs_name, fstypename, MFSNAMELEN))
  190. break;
  191. if (fsindex >= nvfssw) {
  192. vput(vp);
  193. return (ENODEV);
  194. }
  195. if (vp->v_mountedhere != NULL) {
  196. vput(vp);
  197. return (EBUSY);
  198. }
  199. /*
  200. * Allocate and initialize the file system.
  201. */
  202. mp = (struct mount *)malloc((u_long)sizeof(struct mount),
  203. M_MOUNT, M_WAITOK);
  204. bzero((char *)mp, (u_long)sizeof(struct mount));
  205. mp->mnt_op = vfssw[fsindex];
  206. if ((error = vfs_lock(mp)) != 0) {
  207. free((caddr_t)mp, M_MOUNT);
  208. vput(vp);
  209. return (error);
  210. }
  211. /* Do this early in case we block later. */
  212. vfssw[fsindex]->vfs_refcount++;
  213. vp->v_mountedhere = mp;
  214. mp->mnt_vnodecovered = vp;
  215. mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
  216. update:
  217. /*
  218. * Set the mount level flags.
  219. */
  220. if (SCARG(uap, flags) & MNT_RDONLY)
  221. mp->mnt_flag |= MNT_RDONLY;
  222. else if (mp->mnt_flag & MNT_RDONLY)
  223. mp->mnt_flag |= MNT_WANTRDWR;
  224. mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
  225. MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
  226. mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
  227. MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
  228. /*
  229. * Mount the filesystem.
  230. */
  231. error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
  232. if (mp->mnt_flag & MNT_UPDATE) {
  233. vrele(vp);
  234. if (mp->mnt_flag & MNT_WANTRDWR)
  235. mp->mnt_flag &= ~MNT_RDONLY;
  236. mp->mnt_flag &=~
  237. (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
  238. if (error)
  239. mp->mnt_flag = flag;
  240. return (error);
  241. }
  242. /*
  243. * Put the new filesystem on the mount list after root.
  244. */
  245. cache_purge(vp);
  246. if (!error) {
  247. CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
  248. checkdirs(vp);
  249. VOP_UNLOCK(vp);
  250. vfs_unlock(mp);
  251. (void) VFS_STATFS(mp, &mp->mnt_stat, p);
  252. error = VFS_START(mp, 0, p);
  253. } else {
  254. mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
  255. vfssw[fsindex]->vfs_refcount--;
  256. vfs_unlock(mp);
  257. free((caddr_t)mp, M_MOUNT);
  258. vput(vp);
  259. }
  260. return (error);
  261. }
  262. /*
  263. * Scan all active processes to see if any of them have a current
  264. * or root directory onto which the new filesystem has just been
  265. * mounted. If so, replace them with the new mount point.
  266. */
  267. void
  268. checkdirs(olddp)
  269. struct vnode *olddp;
  270. {
  271. struct filedesc *fdp;
  272. struct vnode *newdp;
  273. struct proc *p;
  274. if (olddp->v_usecount == 1)
  275. return;
  276. if (VFS_ROOT(olddp->v_mountedhere, &newdp))
  277. panic("mount: lost mount");
  278. for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
  279. fdp = p->p_fd;
  280. if (fdp->fd_cdir == olddp) {
  281. vrele(fdp->fd_cdir);
  282. VREF(newdp);
  283. fdp->fd_cdir = newdp;
  284. }
  285. if (fdp->fd_rdir == olddp) {
  286. vrele(fdp->fd_rdir);
  287. VREF(newdp);
  288. fdp->fd_rdir = newdp;
  289. }
  290. }
  291. if (rootvnode == olddp) {
  292. vrele(rootvnode);
  293. VREF(newdp);
  294. rootvnode = newdp;
  295. }
  296. vput(newdp);
  297. }
  298. /*
  299. * Unmount a file system.
  300. *
  301. * Note: unmount takes a path to the vnode mounted on as argument,
  302. * not special file (as before).
  303. */
  304. /* ARGSUSED */
  305. int
  306. sys_unmount(p, v, retval)
  307. struct proc *p;
  308. void *v;
  309. register_t *retval;
  310. {
  311. register struct sys_unmount_args /* {
  312. syscallarg(char *) path;
  313. syscallarg(int) flags;
  314. } */ *uap = v;
  315. register struct vnode *vp;
  316. struct mount *mp;
  317. int error;
  318. struct nameidata nd;
  319. NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  320. SCARG(uap, path), p);
  321. if ((error = namei(&nd)) != 0)
  322. return (error);
  323. vp = nd.ni_vp;
  324. mp = vp->v_mount;
  325. /*
  326. * Only root, or the user that did the original mount is
  327. * permitted to unmount this filesystem.
  328. */
  329. if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
  330. (error = suser(p->p_ucred, &p->p_acflag))) {
  331. vput(vp);
  332. return (error);
  333. }
  334. /*
  335. * Don't allow unmounting the root file system.
  336. */
  337. if (mp->mnt_flag & MNT_ROOTFS) {
  338. vput(vp);
  339. return (EINVAL);
  340. }
  341. /*
  342. * Must be the root of the filesystem
  343. */
  344. if ((vp->v_flag & VROOT) == 0) {
  345. vput(vp);
  346. return (EINVAL);
  347. }
  348. vput(vp);
  349. return (dounmount(mp, SCARG(uap, flags), p));
  350. }
  351. /*
  352. * Do the actual file system unmount.
  353. */
  354. int
  355. dounmount(mp, flags, p)
  356. register struct mount *mp;
  357. int flags;
  358. struct proc *p;
  359. {
  360. struct vnode *coveredvp;
  361. int error;
  362. coveredvp = mp->mnt_vnodecovered;
  363. if (vfs_busy(mp))
  364. return (EBUSY);
  365. mp->mnt_flag |= MNT_UNMOUNT;
  366. if ((error = vfs_lock(mp)) != 0)
  367. return (error);
  368. mp->mnt_flag &=~ MNT_ASYNC;
  369. vnode_pager_umount(mp); /* release cached vnodes */
  370. cache_purgevfs(mp); /* remove cache entries for this file sys */
  371. if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 ||
  372. (flags & MNT_FORCE))
  373. error = VFS_UNMOUNT(mp, flags, p);
  374. mp->mnt_flag &= ~MNT_UNMOUNT;
  375. vfs_unbusy(mp);
  376. if (error) {
  377. vfs_unlock(mp);
  378. } else {
  379. CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
  380. if (coveredvp != NULLVP) {
  381. vrele(coveredvp);
  382. coveredvp->v_mountedhere = (struct mount *)0;
  383. }
  384. mp->mnt_op->vfs_refcount--;
  385. vfs_unlock(mp);
  386. if (mp->mnt_vnodelist.lh_first != NULL)
  387. panic("unmount: dangling vnode");
  388. free((caddr_t)mp, M_MOUNT);
  389. }
  390. return (error);
  391. }
  392. /*
  393. * Sync each mounted filesystem.
  394. */
  395. #ifdef DEBUG
  396. int syncprt = 0;
  397. struct ctldebug debug0 = { "syncprt", &syncprt };
  398. #endif
  399. /* ARGSUSED */
  400. int
  401. sys_sync(p, v, retval)
  402. struct proc *p;
  403. void *v;
  404. register_t *retval;
  405. {
  406. register struct mount *mp, *nmp;
  407. int asyncflag;
  408. for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
  409. /*
  410. * Get the next pointer in case we hang on vfs_busy
  411. * while we are being unmounted.
  412. */
  413. nmp = mp->mnt_list.cqe_next;
  414. /*
  415. * The lock check below is to avoid races with mount
  416. * and unmount.
  417. */
  418. if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 &&
  419. !vfs_busy(mp)) {
  420. asyncflag = mp->mnt_flag & MNT_ASYNC;
  421. mp->mnt_flag &= ~MNT_ASYNC;
  422. VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
  423. if (asyncflag)
  424. mp->mnt_flag |= MNT_ASYNC;
  425. /*
  426. * Get the next pointer again, as the next filesystem
  427. * might have been unmounted while we were sync'ing.
  428. */
  429. nmp = mp->mnt_list.cqe_next;
  430. vfs_unbusy(mp);
  431. }
  432. }
  433. #ifdef DEBUG
  434. if (syncprt)
  435. vfs_bufstats();
  436. #endif /* DEBUG */
  437. return (0);
  438. }
  439. /*
  440. * Change filesystem quotas.
  441. */
  442. /* ARGSUSED */
  443. int
  444. sys_quotactl(p, v, retval)
  445. struct proc *p;
  446. void *v;
  447. register_t *retval;
  448. {
  449. register struct sys_quotactl_args /* {
  450. syscallarg(char *) path;
  451. syscallarg(int) cmd;
  452. syscallarg(int) uid;
  453. syscallarg(caddr_t) arg;
  454. } */ *uap = v;
  455. register struct mount *mp;
  456. int error;
  457. struct nameidata nd;
  458. NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  459. if ((error = namei(&nd)) != 0)
  460. return (error);
  461. mp = nd.ni_vp->v_mount;
  462. vrele(nd.ni_vp);
  463. return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
  464. SCARG(uap, arg), p));
  465. }
  466. /*
  467. * Get filesystem statistics.
  468. */
  469. /* ARGSUSED */
  470. int
  471. sys_statfs(p, v, retval)
  472. struct proc *p;
  473. void *v;
  474. register_t *retval;
  475. {
  476. register struct sys_statfs_args /* {
  477. syscallarg(char *) path;
  478. syscallarg(struct statfs *) buf;
  479. } */ *uap = v;
  480. register struct mount *mp;
  481. register struct statfs *sp;
  482. int error;
  483. struct nameidata nd;
  484. NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  485. if ((error = namei(&nd)) != 0)
  486. return (error);
  487. mp = nd.ni_vp->v_mount;
  488. sp = &mp->mnt_stat;
  489. vrele(nd.ni_vp);
  490. if ((error = VFS_STATFS(mp, sp, p)) != 0)
  491. return (error);
  492. sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  493. return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
  494. }
  495. /*
  496. * Get filesystem statistics.
  497. */
  498. /* ARGSUSED */
  499. int
  500. sys_fstatfs(p, v, retval)
  501. struct proc *p;
  502. void *v;
  503. register_t *retval;
  504. {
  505. register struct sys_fstatfs_args /* {
  506. syscallarg(int) fd;
  507. syscallarg(struct statfs *) buf;
  508. } */ *uap = v;
  509. struct file *fp;
  510. struct mount *mp;
  511. register struct statfs *sp;
  512. int error;
  513. if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
  514. return (error);
  515. mp = ((struct vnode *)fp->f_data)->v_mount;
  516. sp = &mp->mnt_stat;
  517. if ((error = VFS_STATFS(mp, sp, p)) != 0)
  518. return (error);
  519. sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  520. return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
  521. }
  522. /*
  523. * Get statistics on all filesystems.
  524. */
  525. int
  526. sys_getfsstat(p, v, retval)
  527. struct proc *p;
  528. void *v;
  529. register_t *retval;
  530. {
  531. register struct sys_getfsstat_args /* {
  532. syscallarg(struct statfs *) buf;
  533. syscallarg(long) bufsize;
  534. syscallarg(int) flags;
  535. } */ *uap = v;
  536. register struct mount *mp, *nmp;
  537. register struct statfs *sp;
  538. caddr_t sfsp;
  539. long count, maxcount, error;
  540. maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
  541. sfsp = (caddr_t)SCARG(uap, buf);
  542. for (count = 0,
  543. mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
  544. nmp = mp->mnt_list.cqe_next;
  545. if (sfsp && count < maxcount &&
  546. ((mp->mnt_flag & MNT_MLOCK) == 0)) {
  547. sp = &mp->mnt_stat;
  548. /*
  549. * If MNT_NOWAIT is specified, do not refresh the
  550. * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
  551. */
  552. if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 ||
  553. (SCARG(uap, flags) & MNT_WAIT)) &&
  554. (error = VFS_STATFS(mp, sp, p)))
  555. continue;
  556. sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  557. error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
  558. if (error)
  559. return (error);
  560. sfsp += sizeof(*sp);
  561. }
  562. count++;
  563. }
  564. if (sfsp && count > maxcount)
  565. *retval = maxcount;
  566. else
  567. *retval = count;
  568. return (0);
  569. }
  570. /*
  571. * Change current working directory to a given file descriptor.
  572. */
  573. /* ARGSUSED */
  574. int
  575. sys_fchdir(p, v, retval)
  576. struct proc *p;
  577. void *v;
  578. register_t *retval;
  579. {
  580. struct sys_fchdir_args /* {
  581. syscallarg(int) fd;
  582. } */ *uap = v;
  583. register struct filedesc *fdp = p->p_fd;
  584. struct vnode *vp, *tdp;
  585. struct mount *mp;
  586. struct file *fp;
  587. int error;
  588. if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
  589. return (error);
  590. vp = (struct vnode *)fp->f_data;
  591. VREF(vp);
  592. VOP_LOCK(vp);
  593. if (vp->v_type != VDIR)
  594. error = ENOTDIR;
  595. else
  596. error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
  597. while (!error && (mp = vp->v_mountedhere) != NULL) {
  598. if (mp->mnt_flag & MNT_MLOCK) {
  599. mp->mnt_flag |= MNT_MWAIT;
  600. sleep((caddr_t)mp, PVFS);
  601. continue;
  602. }
  603. if ((error = VFS_ROOT(mp, &tdp)) != 0)
  604. break;
  605. vput(vp);
  606. vp = tdp;
  607. }
  608. VOP_UNLOCK(vp);
  609. if (error) {
  610. vrele(vp);
  611. return (error);
  612. }
  613. vrele(fdp->fd_cdir);
  614. fdp->fd_cdir = vp;
  615. return (0);
  616. }
  617. /*
  618. * Change current working directory (``.'').
  619. */
  620. /* ARGSUSED */
  621. int
  622. sys_chdir(p, v, retval)
  623. struct proc *p;
  624. void *v;
  625. register_t *retval;
  626. {
  627. struct sys_chdir_args /* {
  628. syscallarg(char *) path;
  629. } */ *uap = v;
  630. register struct filedesc *fdp = p->p_fd;
  631. int error;
  632. struct nameidata nd;
  633. NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  634. SCARG(uap, path), p);
  635. if ((error = change_dir(&nd, p)) != 0)
  636. return (error);
  637. vrele(fdp->fd_cdir);
  638. fdp->fd_cdir = nd.ni_vp;
  639. return (0);
  640. }
  641. /*
  642. * Change notion of root (``/'') directory.
  643. */
  644. /* ARGSUSED */
  645. int
  646. sys_chroot(p, v, retval)
  647. struct proc *p;
  648. void *v;
  649. register_t *retval;
  650. {
  651. struct sys_chroot_args /* {
  652. syscallarg(char *) path;
  653. } */ *uap = v;
  654. register struct filedesc *fdp = p->p_fd;
  655. int error;
  656. struct nameidata nd;
  657. if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
  658. return (error);
  659. NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  660. SCARG(uap, path), p);
  661. if ((error = change_dir(&nd, p)) != 0)
  662. return (error);
  663. if (fdp->fd_rdir != NULL)
  664. vrele(fdp->fd_rdir);
  665. fdp->fd_rdir = nd.ni_vp;
  666. return (0);
  667. }
  668. /*
  669. * Common routine for chroot and chdir.
  670. */
  671. static int
  672. change_dir(ndp, p)
  673. register struct nameidata *ndp;
  674. struct proc *p;
  675. {
  676. struct vnode *vp;
  677. int error;
  678. if ((error = namei(ndp)) != 0)
  679. return (error);
  680. vp = ndp->ni_vp;
  681. if (vp->v_type != VDIR)
  682. error = ENOTDIR;
  683. else
  684. error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
  685. VOP_UNLOCK(vp);
  686. if (error)
  687. vrele(vp);
  688. return (error);
  689. }
  690. /*
  691. * Check permissions, allocate an open file structure,
  692. * and call the device open routine if any.
  693. */
  694. int
  695. sys_open(p, v, retval)
  696. struct proc *p;
  697. void *v;
  698. register_t *retval;
  699. {
  700. register struct sys_open_args /* {
  701. syscallarg(char *) path;
  702. syscallarg(int) flags;
  703. syscallarg(int) mode;
  704. } */ *uap = v;
  705. register struct filedesc *fdp = p->p_fd;
  706. register struct file *fp;
  707. register struct vnode *vp;
  708. int flags, cmode;
  709. struct file *nfp;
  710. int type, indx, error;
  711. struct flock lf;
  712. struct nameidata nd;
  713. extern struct fileops vnops;
  714. if ((error = falloc(p, &nfp, &indx)) != 0)
  715. return (error);
  716. fp = nfp;
  717. flags = FFLAGS(SCARG(uap, flags));
  718. cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
  719. NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  720. p->p_dupfd = -indx - 1; /* XXX check for fdopen */
  721. if ((error = vn_open(&nd, flags, cmode)) != 0) {
  722. ffree(fp);
  723. if ((error == ENODEV || error == ENXIO) &&
  724. p->p_dupfd >= 0 && /* XXX from fdopen */
  725. (error =
  726. dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
  727. *retval = indx;
  728. return (0);
  729. }
  730. if (error == ERESTART)
  731. error = EINTR;
  732. fdp->fd_ofiles[indx] = NULL;
  733. return (error);
  734. }
  735. p->p_dupfd = 0;
  736. vp = nd.ni_vp;
  737. fp->f_flag = flags & FMASK;
  738. fp->f_type = DTYPE_VNODE;
  739. fp->f_ops = &vnops;
  740. fp->f_data = (caddr_t)vp;
  741. if (flags & (O_EXLOCK | O_SHLOCK)) {
  742. lf.l_whence = SEEK_SET;
  743. lf.l_start = 0;
  744. lf.l_len = 0;
  745. if (flags & O_EXLOCK)
  746. lf.l_type = F_WRLCK;
  747. else
  748. lf.l_type = F_RDLCK;
  749. type = F_FLOCK;
  750. if ((flags & FNONBLOCK) == 0)
  751. type |= F_WAIT;
  752. VOP_UNLOCK(vp);
  753. error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
  754. if (error) {
  755. (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
  756. ffree(fp);
  757. fdp->fd_ofiles[indx] = NULL;
  758. return (error);
  759. }
  760. VOP_LOCK(vp);
  761. fp->f_flag |= FHASLOCK;
  762. }
  763. VOP_UNLOCK(vp);
  764. *retval = indx;
  765. return (0);
  766. }
  767. /*
  768. * Create a special file.
  769. */
  770. /* ARGSUSED */
  771. int
  772. sys_mknod(p, v, retval)
  773. struct proc *p;
  774. void *v;
  775. register_t *retval;
  776. {
  777. register struct sys_mknod_args /* {
  778. syscallarg(char *) path;
  779. syscallarg(int) mode;
  780. syscallarg(int) dev;
  781. } */ *uap = v;
  782. register struct vnode *vp;
  783. struct vattr vattr;
  784. int error;
  785. int whiteout = 0;
  786. struct nameidata nd;
  787. if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
  788. return (error);
  789. NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
  790. if ((error = namei(&nd)) != 0)
  791. return (error);
  792. vp = nd.ni_vp;
  793. if (vp != NULL)
  794. error = EEXIST;
  795. else {
  796. VATTR_NULL(&vattr);
  797. vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
  798. vattr.va_rdev = SCARG(uap, dev);
  799. whiteout = 0;
  800. switch (SCARG(uap, mode) & S_IFMT) {
  801. case S_IFMT: /* used by badsect to flag bad sectors */
  802. vattr.va_type = VBAD;
  803. break;
  804. case S_IFCHR:
  805. vattr.va_type = VCHR;
  806. break;
  807. case S_IFBLK:
  808. vattr.va_type = VBLK;
  809. break;
  810. case S_IFWHT:
  811. whiteout = 1;
  812. break;
  813. default:
  814. error = EINVAL;
  815. break;
  816. }
  817. }
  818. if (!error) {
  819. VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
  820. if (whiteout) {
  821. error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
  822. if (error)
  823. VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
  824. vput(nd.ni_dvp);
  825. } else {
  826. error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
  827. &nd.ni_cnd, &vattr);
  828. }
  829. } else {
  830. VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
  831. if (nd.ni_dvp == vp)
  832. vrele(nd.ni_dvp);
  833. else
  834. vput(nd.ni_dvp);
  835. if (vp)
  836. vrele(vp);
  837. }
  838. return (error);
  839. }
  840. /*
  841. * Create a named pipe.
  842. */
  843. /* ARGSUSED */
  844. int
  845. sys_mkfifo(p, v, retval)
  846. struct proc *p;
  847. void *v;
  848. register_t *retval;
  849. {
  850. #ifndef FIFO
  851. return (EOPNOTSUPP);
  852. #else
  853. register struct sys_mkfifo_args /* {
  854. syscallarg(char *) path;
  855. syscallarg(int) mode;
  856. } */ *uap = v;
  857. struct vattr vattr;
  858. int error;
  859. struct nameidata nd;
  860. NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
  861. if ((error = namei(&nd)) != 0)
  862. return (error);
  863. if (nd.ni_vp != NULL) {
  864. VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
  865. if (nd.ni_dvp == nd.ni_vp)
  866. vrele(nd.ni_dvp);
  867. else
  868. vput(nd.ni_dvp);
  869. vrele(nd.ni_vp);
  870. return (EEXIST);
  871. }
  872. VATTR_NULL(&vattr);
  873. vattr.va_type = VFIFO;
  874. vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
  875. VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
  876. return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
  877. #endif /* FIFO */
  878. }
  879. /*
  880. * Make a hard file link.
  881. */
  882. /* ARGSUSED */
  883. int
  884. sys_link(p, v, retval)
  885. struct proc *p;
  886. void *v;
  887. register_t *retval;
  888. {
  889. register struct sys_link_args /* {
  890. syscallarg(char *) path;
  891. syscallarg(char *) link;
  892. } */ *uap = v;
  893. register struct vnode *vp;
  894. struct nameidata nd;
  895. int error;
  896. NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  897. if ((error = namei(&nd)) != 0)
  898. return (error);
  899. vp = nd.ni_vp;
  900. NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
  901. if ((error = namei(&nd)) != 0)
  902. goto out;
  903. if (nd.ni_vp) {
  904. VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
  905. if (nd.ni_dvp == nd.ni_vp)
  906. vrele(nd.ni_dvp);
  907. else
  908. vput(nd.ni_dvp);
  909. vrele(nd.ni_vp);
  910. error = EEXIST;
  911. goto out;
  912. }
  913. VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
  914. VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
  915. error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
  916. out:
  917. vrele(vp);
  918. return (error);
  919. }
  920. /*
  921. * Make a symbolic link.
  922. */
  923. /* ARGSUSED */
  924. int
  925. sys_symlink(p, v, retval)
  926. struct proc *p;
  927. void *v;
  928. register_t *retval;
  929. {
  930. register struct sys_symlink_args /* {
  931. syscallarg(char *) path;
  932. syscallarg(char *) link;
  933. } */ *uap = v;
  934. struct vattr vattr;
  935. char *path;
  936. int error;
  937. struct nameidata nd;
  938. MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
  939. error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL);
  940. if (error)
  941. goto out;
  942. NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
  943. if ((error = namei(&nd)) != 0)
  944. goto out;
  945. if (nd.ni_vp) {
  946. VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
  947. if (nd.ni_dvp == nd.ni_vp)
  948. vrele(nd.ni_dvp);
  949. else
  950. vput(nd.ni_dvp);
  951. vrele(nd.ni_vp);
  952. error = EEXIST;
  953. goto out;
  954. }
  955. VATTR_NULL(&vattr);
  956. vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
  957. VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
  958. error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
  959. out:
  960. FREE(path, M_NAMEI);
  961. return (error);
  962. }
  963. /*
  964. * Delete a whiteout from the filesystem.
  965. */
  966. /* ARGSUSED */
  967. int
  968. sys_undelete(p, v, retval)
  969. struct proc *p;
  970. void *v;
  971. register_t *retval;
  972. {
  973. register struct sys_undelete_args /* {
  974. syscallarg(char *) path;
  975. } */ *uap = v;
  976. int error;
  977. struct nameidata nd;
  978. NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
  979. SCARG(uap, path), p);
  980. error = namei(&nd);
  981. if (error)
  982. return (error);
  983. if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
  984. VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
  985. if (nd.ni_dvp == nd.ni_vp)
  986. vrele(nd.ni_dvp);
  987. else
  988. vput(nd.ni_dvp);
  989. if (nd.ni_vp)
  990. vrele(nd.ni_vp);
  991. return (EEXIST);
  992. }
  993. VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
  994. if ((error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) != 0)
  995. VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
  996. vput(nd.ni_dvp);
  997. return (error);
  998. }
  999. /*
  1000. * Delete a name from the filesystem.
  1001. */
  1002. /* ARGSUSED */
  1003. int
  1004. sys_unlink(p, v, retval)
  1005. struct proc *p;
  1006. void *v;
  1007. register_t *retval;
  1008. {
  1009. struct sys_unlink_args /* {
  1010. syscallarg(char *) path;
  1011. } */ *uap = v;
  1012. register struct vnode *vp;
  1013. int error;
  1014. struct nameidata nd;
  1015. NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
  1016. SCARG(uap, path), p);
  1017. if ((error = namei(&nd)) != 0)
  1018. return (error);
  1019. vp = nd.ni_vp;
  1020. /*
  1021. * The root of a mounted filesystem cannot be deleted.
  1022. */
  1023. if (vp->v_flag & VROOT) {
  1024. VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
  1025. if (nd.ni_dvp == vp)
  1026. vrele(nd.ni_dvp);
  1027. else
  1028. vput(nd.ni_dvp);
  1029. vput(vp);
  1030. error = EBUSY;
  1031. goto out;
  1032. }
  1033. (void)vnode_pager_uncache(vp);
  1034. VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
  1035. VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
  1036. error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
  1037. out:
  1038. return (error);
  1039. }
  1040. /*
  1041. * Reposition read/write file offset.
  1042. */
  1043. int
  1044. sys_lseek(p, v, retval)
  1045. struct proc *p;
  1046. void *v;
  1047. register_t *retval;
  1048. {
  1049. register struct sys_lseek_args /* {
  1050. syscallarg(int) fd;
  1051. syscallarg(int) pad;
  1052. syscallarg(off_t) offset;
  1053. syscallarg(int) whence;
  1054. } */ *uap = v;
  1055. struct ucred *cred = p->p_ucred;
  1056. register struct filedesc *fdp = p->p_fd;
  1057. register struct file *fp;
  1058. struct vattr vattr;
  1059. int error;
  1060. if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
  1061. (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
  1062. return (EBADF);
  1063. if (fp->f_type != DTYPE_VNODE)
  1064. return (ESPIPE);
  1065. switch (SCARG(uap, whence)) {
  1066. case L_INCR:
  1067. fp->f_offset += SCARG(uap, offset);
  1068. break;
  1069. case L_XTND:
  1070. error = VOP_GETATTR((struct vnode *)fp->f_data, &vattr,
  1071. cred, p);
  1072. if (error)
  1073. return (error);
  1074. fp->f_offset = SCARG(uap, offset) + vattr.va_size;
  1075. break;
  1076. case L_SET:
  1077. fp->f_offset = SCARG(uap, offset);
  1078. break;
  1079. default:
  1080. return (EINVAL);
  1081. }
  1082. *(off_t *)retval = fp->f_offset;
  1083. return (0);
  1084. }
  1085. /*
  1086. * Check access permissions.
  1087. */
  1088. int
  1089. sys_access(p, v, retval)
  1090. struct proc *p;
  1091. void *v;
  1092. register_t *retval;
  1093. {
  1094. register struct sys_access_args /* {
  1095. syscallarg(char *) path;
  1096. syscallarg(int) flags;
  1097. } */ *uap = v;
  1098. register struct ucred *cred = p->p_ucred;
  1099. register struct vnode *vp;
  1100. int error, flags, t_gid, t_uid;
  1101. struct nameidata nd;
  1102. t_uid = cred->cr_uid;
  1103. t_gid = cred->cr_gid;
  1104. cred->cr_uid = p->p_cred->p_ruid;
  1105. cred->cr_gid = p->p_cred->p_rgid;
  1106. NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  1107. SCARG(uap, path), p);
  1108. if ((error = namei(&nd)) != 0)
  1109. goto out1;
  1110. vp = nd.ni_vp;
  1111. /* Flags == 0 means only check for existence. */
  1112. if (SCARG(uap, flags)) {
  1113. flags = 0;
  1114. if (SCARG(uap, flags) & R_OK)
  1115. flags |= VREAD;
  1116. if (SCARG(uap, flags) & W_OK)
  1117. flags |= VWRITE;
  1118. if (SCARG(uap, flags) & X_OK)
  1119. flags |= VEXEC;
  1120. if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
  1121. error = VOP_ACCESS(vp, flags, cred, p);
  1122. }
  1123. vput(vp);
  1124. out1:
  1125. cred->cr_uid = t_uid;
  1126. cred->cr_gid = t_gid;
  1127. return (error);
  1128. }
  1129. /*
  1130. * Get file status; this version follows links.
  1131. */
  1132. /* ARGSUSED */
  1133. int
  1134. sys_stat(p, v, retval)
  1135. struct proc *p;
  1136. void *v;
  1137. register_t *retval;
  1138. {
  1139. register struct sys_stat_args /* {
  1140. syscallarg(char *) path;
  1141. syscallarg(struct stat *) ub;
  1142. } */ *uap = v;
  1143. struct stat sb;
  1144. int error;
  1145. struct nameidata nd;
  1146. NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  1147. SCARG(uap, path), p);
  1148. if ((error = namei(&nd)) != 0)
  1149. return (error);
  1150. error = vn_stat(nd.ni_vp, &sb, p);
  1151. vput(nd.ni_vp);
  1152. if (error)
  1153. return (error);
  1154. error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
  1155. return (error);
  1156. }
  1157. /*
  1158. * Get file status; this version does not follow links.
  1159. */
  1160. /* ARGSUSED */
  1161. int
  1162. sys_lstat(p, v, retval)
  1163. struct proc *p;
  1164. void *v;
  1165. register_t *retval;
  1166. {
  1167. register struct sys_lstat_args /* {
  1168. syscallarg(char *) path;
  1169. syscallarg(struct stat *) ub;
  1170. } */ *uap = v;
  1171. struct stat sb;
  1172. int error;
  1173. struct nameidata nd;
  1174. NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
  1175. SCARG(uap, path), p);
  1176. if ((error = namei(&nd)) != 0)
  1177. return (error);
  1178. error = vn_stat(nd.ni_vp, &sb, p);
  1179. vput(nd.ni_vp);
  1180. if (error)
  1181. return (error);
  1182. error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
  1183. return (error);
  1184. }
  1185. /*
  1186. * Get configurable pathname variables.
  1187. */
  1188. /* ARGSUSED */
  1189. int
  1190. sys_pathconf(p, v, retval)
  1191. struct proc *p;
  1192. void *v;
  1193. register_t *retval;
  1194. {
  1195. register struct sys_pathconf_args /* {
  1196. syscallarg(char *) path;
  1197. syscallarg(int) name;
  1198. } */ *uap = v;
  1199. int error;
  1200. struct nameidata nd;
  1201. NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  1202. SCARG(uap, path), p);
  1203. if ((error = namei(&nd)) != 0)
  1204. return (error);
  1205. error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
  1206. vput(nd.ni_vp);
  1207. return (error);
  1208. }
  1209. /*
  1210. * Return target name of a symbolic link.
  1211. */
  1212. /* ARGSUSED */
  1213. int
  1214. sys_readlink(p, v, retval)
  1215. struct proc *p;
  1216. void *v;
  1217. register_t *retval;
  1218. {
  1219. register struct sys_readlink_args /* {
  1220. syscallarg(char *) path;
  1221. syscallarg(char *) buf;
  1222. syscallarg(int) count;
  1223. } */ *uap = v;
  1224. register struct vnode *vp;
  1225. struct iovec aiov;
  1226. struct uio auio;
  1227. int error;
  1228. struct nameidata nd;
  1229. NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
  1230. SCARG(uap, path), p);
  1231. if ((error = namei(&nd)) != 0)
  1232. return (error);
  1233. vp = nd.ni_vp;
  1234. if (vp->v_type != VLNK)
  1235. error = EINVAL;
  1236. else {
  1237. aiov.iov_base = SCARG(uap, buf);
  1238. aiov.iov_len = SCARG(uap, count);
  1239. auio.uio_iov = &aiov;
  1240. auio.uio_iovcnt = 1;
  1241. auio.uio_offset = 0;
  1242. auio.uio_rw = UIO_READ;
  1243. auio.uio_segflg = UIO_USERSPACE;
  1244. auio.uio_procp = p;
  1245. auio.uio_resid = SCARG(uap, count);
  1246. error = VOP_READLINK(vp, &auio, p->p_ucred);
  1247. }
  1248. vput(vp);
  1249. *retval = SCARG(uap, count) - auio.uio_resid;
  1250. return (error);
  1251. }
  1252. /*
  1253. * Change flags of a file given a path name.
  1254. */
  1255. /* ARGSUSED */
  1256. int
  1257. sys_chflags(p, v, retval)
  1258. struct proc *p;
  1259. void *v;
  1260. register_t *retval;
  1261. {
  1262. register struct sys_chflags_args /* {
  1263. syscallarg(char *) path;
  1264. syscallarg(int) flags;
  1265. } */ *uap = v;
  1266. register struct vnode *vp;
  1267. struct vattr vattr;
  1268. int error;
  1269. struct nameidata nd;
  1270. NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  1271. if ((error = namei(&nd)) != 0)
  1272. return (error);
  1273. vp = nd.ni_vp;
  1274. VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
  1275. VOP_LOCK(vp);
  1276. if (vp->v_mount->mnt_flag & MNT_RDONLY)
  1277. error = EROFS;
  1278. else {
  1279. VATTR_NULL(&vattr);
  1280. vattr.va_flags = SCARG(uap, flags);
  1281. error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
  1282. }
  1283. vput(vp);
  1284. return (error);
  1285. }
  1286. /*
  1287. * Change flags of a file given a file descriptor.
  1288. */
  1289. /* ARGSUSED */
  1290. int
  1291. sys_fchflags(p, v, retval)
  1292. struct proc *p;
  1293. void *v;
  1294. register_t *retval;
  1295. {
  1296. register struct sys_fchflags_args /* {
  1297. syscallarg(int) fd;
  1298. syscallarg(int) flags;
  1299. } */ *uap = v;
  1300. struct vattr vattr;
  1301. struct vnode *vp;
  1302. struct file *fp;
  1303. int error;
  1304. if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
  1305. return (error);
  1306. vp = (struct vnode *)fp->f_data;
  1307. VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
  1308. VOP_LOCK(vp);
  1309. if (vp->v_mount->mnt_flag & MNT_RDONLY)
  1310. error = EROFS;
  1311. else {
  1312. VATTR_NULL(&vattr);
  1313. vattr.va_flags = SCARG(uap, flags);
  1314. error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
  1315. }
  1316. VOP_UNLOCK(vp);
  1317. return (error);
  1318. }
  1319. /*
  1320. * Change mode of a file given path name.
  1321. */
  1322. /* ARGSUSED */
  1323. int
  1324. sys_chmod(p, v, retval)
  1325. struct proc *p;
  1326. void *v;
  1327. register_t *retval;
  1328. {
  1329. register struct sys_chmod_args /* {
  1330. syscallarg(char *) path;
  1331. syscallarg(int) mode;
  1332. } */ *uap = v;
  1333. register struct vnode *vp;
  1334. struct vattr vattr;
  1335. int error;
  1336. struct nameidata nd;
  1337. NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  1338. if ((error = namei(&nd)) != 0)
  1339. return (error);
  1340. vp = nd.ni_vp;
  1341. VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
  1342. VOP_LOCK(vp);
  1343. if (vp->v_mount->mnt_flag & MNT_RDONLY)
  1344. error = EROFS;
  1345. else {
  1346. VATTR_NULL(&vattr);
  1347. vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
  1348. error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
  1349. }
  1350. vput(vp);
  1351. return (error);
  1352. }
  1353. /*
  1354. * Change mode of a file given a file descriptor.
  1355. */
  1356. /* ARGSUSED */
  1357. int
  1358. sys_fchmod(p, v, retval)
  1359. struct proc *p;
  1360. void *v;
  1361. register_t *retval;
  1362. {
  1363. register struct sys_fchmod_args /* {
  1364. syscallarg(int) fd;
  1365. syscallarg(int) mode;
  1366. } */ *uap = v;
  1367. struct vattr vattr;
  1368. struct vnode *vp;
  1369. struct file *fp;
  1370. int error;
  1371. if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
  1372. return (error);
  1373. vp = (struct vnode *)fp->f_data;
  1374. VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
  1375. VOP_LOCK(vp);
  1376. if (vp->v_mount->mnt_flag & MNT_RDONLY)
  1377. error = EROFS;
  1378. else {
  1379. VATTR_NULL(&vattr);
  1380. vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
  1381. error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
  1382. }
  1383. VOP_UNLOCK(vp);
  1384. return (error);
  1385. }
  1386. /*
  1387. * Set ownership given a path name.
  1388. */
  1389. /* ARGSUSED */
  1390. int
  1391. sys_chown(p, v, retval)
  1392. struct proc *p;
  1393. void *v;
  1394. register_t *retval;
  1395. {
  1396. register struct sys_chown_args /* {
  1397. syscallarg(char *) path;
  1398. syscallarg(int) uid;
  1399. syscallarg(int) gid;
  1400. } */ *uap = v;
  1401. register struct vnode *vp;
  1402. struct vattr vattr;
  1403. int error;
  1404. struct nameidata nd;
  1405. NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  1406. if ((error = namei(&nd)) != 0)
  1407. return (error);
  1408. vp = nd.ni_vp;
  1409. VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
  1410. VOP_LOCK(vp);
  1411. if (vp->v_mount->mnt_flag & MNT_RDONLY)
  1412. error = EROFS;
  1413. else {
  1414. VATTR_NULL(&vattr);
  1415. vattr.va_uid = SCARG(uap, uid);
  1416. vattr.va_gid = SCARG(uap, gid);
  1417. error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
  1418. }
  1419. vput(vp);
  1420. return (error);
  1421. }
  1422. /*
  1423. * Set ownership given a file descriptor.
  1424. */
  1425. /* ARGSUSED */
  1426. int
  1427. sys_fchown(p, v, retval)
  1428. struct proc *p;
  1429. void *v;
  1430. register_t *retval;
  1431. {
  1432. register struct sys_fchown_args /* {
  1433. syscallarg(int) fd;
  1434. syscallarg(int) uid;
  1435. syscallarg(int) gid;
  1436. } */ *uap = v;
  1437. register struct vnode *vp;
  1438. struct vattr vattr;
  1439. int error;
  1440. struct file *fp;
  1441. if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
  1442. return (error);
  1443. vp = (struct vnode *)fp->f_data;
  1444. VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
  1445. VOP_LOCK(vp);
  1446. if (vp->v_mount->mnt_flag & MNT_RDONLY)
  1447. error = EROFS;
  1448. else {
  1449. VATTR_NULL(&vattr);
  1450. vattr.va_uid = SCARG(uap, uid);
  1451. vattr.va_gid = SCARG(uap, gid);
  1452. error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
  1453. }
  1454. VOP_UNLOCK(vp);
  1455. return (error);
  1456. }
  1457. /*
  1458. * Set the access and modification times given a path name.
  1459. */
  1460. /* ARGSUSED */
  1461. int
  1462. sys_utimes(p, v, retval)
  1463. struct proc *p;
  1464. void *v;
  1465. register_t *retval;
  1466. {
  1467. register struct sys_utimes_args /* {
  1468. syscallarg(char *) path;
  1469. syscallarg(struct timeval *) tptr;
  1470. } */ *uap = v;
  1471. register struct vnode *vp;
  1472. struct timeval tv[2];
  1473. struct vattr vattr;
  1474. int error;
  1475. struct nameidata nd;
  1476. VATTR_NULL(&vattr);
  1477. if (SCARG(uap, tptr) == NULL) {
  1478. microtime(&tv[0]);
  1479. tv[1] = tv[0];
  1480. vattr.va_vaflags |= VA_UTIMES_NULL;
  1481. } else {
  1482. error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
  1483. sizeof (tv));
  1484. if (error)
  1485. return (error);
  1486. }
  1487. NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  1488. if ((error = namei(&nd)) != 0)
  1489. return (error);
  1490. vp = nd.ni_vp;
  1491. VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
  1492. VOP_LOCK(vp);
  1493. if (vp->v_mount->mnt_flag & MNT_RDONLY)
  1494. error = EROFS;
  1495. else {
  1496. vattr.va_atime.tv_sec = tv[0].tv_sec;
  1497. vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
  1498. vattr.va_mtime.tv_sec = tv[1].tv_sec;
  1499. vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
  1500. error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
  1501. }
  1502. vput(vp);
  1503. return (error);
  1504. }
  1505. /*
  1506. * Set the access and modification times given a file descriptor.
  1507. */
  1508. /* ARGSUSED */
  1509. int
  1510. sys_futimes(p, v, retval)
  1511. struct proc *p;
  1512. void *v;
  1513. register_t *retval;
  1514. {
  1515. register struct sys_futimes_args /* {
  1516. syscallarg(int) fd;
  1517. syscallarg(struct timeval *) tptr;
  1518. } */ *uap = v;
  1519. register struct vnode *vp;
  1520. struct timeval tv[2];
  1521. struct vattr vattr;
  1522. int error;
  1523. struct file *fp;
  1524. VATTR_NULL(&vattr);
  1525. if (SCARG(uap, tptr) == NULL) {
  1526. microtime(&tv[0]);
  1527. tv[1] = tv[0];
  1528. vattr.va_vaflags |= VA_UTIMES_NULL;
  1529. } else {
  1530. error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
  1531. sizeof (tv));
  1532. if (error)
  1533. return (error);
  1534. }
  1535. if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
  1536. return (error);
  1537. vp = (struct vnode *)fp->f_data;
  1538. VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
  1539. VOP_LOCK(vp);
  1540. if (vp->v_mount->mnt_flag & MNT_RDONLY)
  1541. error = EROFS;
  1542. else {
  1543. vattr.va_atime.tv_sec = tv[0].tv_sec;
  1544. vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
  1545. vattr.va_mtime.tv_sec = tv[1].tv_sec;
  1546. vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
  1547. error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
  1548. }
  1549. VOP_UNLOCK(vp);
  1550. return (error);
  1551. }
  1552. /*
  1553. * Truncate a file given its path name.
  1554. */
  1555. /* ARGSUSED */
  1556. int
  1557. sys_truncate(p, v, retval)
  1558. struct proc *p;
  1559. void *v;
  1560. register_t *retval;
  1561. {
  1562. register struct sys_truncate_args /* {
  1563. syscallarg(char *) path;
  1564. syscallarg(int) pad;
  1565. syscallarg(off_t) length;
  1566. } */ *uap = v;
  1567. register struct vnode *vp;
  1568. struct vattr vattr;
  1569. int error;
  1570. struct nameidata nd;
  1571. NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  1572. if ((error = namei(&nd)) != 0)
  1573. return (error);
  1574. vp = nd.ni_vp;
  1575. VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
  1576. VOP_LOCK(vp);
  1577. if (vp->v_type == VDIR)
  1578. error = EISDIR;
  1579. else if ((error = vn_writechk(vp)) == 0 &&
  1580. (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
  1581. VATTR_NULL(&vattr);
  1582. vattr.va_size = SCARG(uap, length);
  1583. error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
  1584. }
  1585. vput(vp);
  1586. return (error);
  1587. }
  1588. /*
  1589. * Truncate a file given a file descriptor.
  1590. */
  1591. /* ARGSUSED */
  1592. int
  1593. sys_ftruncate(p, v, retval)
  1594. struct proc *p;
  1595. void *v;
  1596. register_t *retval;
  1597. {
  1598. register struct sys_ftruncate_args /* {
  1599. syscallarg(int) fd;
  1600. syscallarg(int) pad;
  1601. syscallarg(off_t) length;
  1602. } */ *uap = v;
  1603. struct vattr vattr;
  1604. struct vnode *vp;
  1605. struct file *fp;
  1606. int error;
  1607. if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
  1608. return (error);
  1609. if ((fp->f_flag & FWRITE) == 0)
  1610. return (EINVAL);
  1611. vp = (struct vnode *)fp->f_data;
  1612. VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
  1613. VOP_LOCK(vp);
  1614. if (vp->v_type == VDIR)
  1615. error = EISDIR;
  1616. else if ((error = vn_writechk(vp)) == 0) {
  1617. VATTR_NULL(&vattr);
  1618. vattr.va_size = SCARG(uap, length);
  1619. error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
  1620. }
  1621. VOP_UNLOCK(vp);
  1622. return (error);
  1623. }
  1624. /*
  1625. * Sync an open file.
  1626. */
  1627. /* ARGSUSED */
  1628. int
  1629. sys_fsync(p, v, retval)
  1630. struct proc *p;
  1631. void *v;
  1632. register_t *retval;
  1633. {
  1634. struct sys_fsync_args /* {
  1635. syscallarg(int) fd;
  1636. } */ *uap = v;
  1637. register struct vnode *vp;
  1638. struct file *fp;
  1639. int error;
  1640. if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
  1641. return (error);
  1642. vp = (struct vnode *)fp->f_data;
  1643. VOP_LOCK(vp);
  1644. error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
  1645. VOP_UNLOCK(vp);
  1646. return (error);
  1647. }
  1648. /*
  1649. * Rename files. Source and destination must either both be directories,
  1650. * or both not be directories. If target is a directory, it must be empty.
  1651. */
  1652. /* ARGSUSED */
  1653. int
  1654. sys_rename(p, v, retval)
  1655. struct proc *p;
  1656. void *v;
  1657. register_t *retval;
  1658. {
  1659. register struct sys_rename_args /* {
  1660. syscallarg(char *) from;
  1661. syscallarg(char *) to;
  1662. } */ *uap = v;
  1663. register struct vnode *tvp, *fvp, *tdvp;
  1664. struct nameidata fromnd, tond;
  1665. int error;
  1666. NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
  1667. SCARG(uap, from), p);
  1668. if ((error = namei(&fromnd)) != 0)
  1669. return (error);
  1670. fvp = fromnd.ni_vp;
  1671. NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
  1672. UIO_USERSPACE, SCARG(uap, to), p);
  1673. if ((error = namei(&tond)) != 0) {
  1674. VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
  1675. vrele(fromnd.ni_dvp);
  1676. vrele(fvp);
  1677. goto out1;
  1678. }
  1679. tdvp = tond.ni_dvp;
  1680. tvp = tond.ni_vp;
  1681. if (tvp != NULL) {
  1682. if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
  1683. error = ENOTDIR;
  1684. goto out;
  1685. } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
  1686. error = EISDIR;
  1687. goto out;
  1688. }
  1689. }
  1690. if (fvp == tdvp)
  1691. error = EINVAL;
  1692. /*
  1693. * If source is the same as the destination (that is the
  1694. * same inode number with the same name in the same directory),
  1695. * then there is nothing to do.
  1696. */
  1697. if (fvp == tvp && fromnd.ni_dvp == tdvp &&
  1698. fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
  1699. !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
  1700. fromnd.ni_cnd.cn_namelen))
  1701. error = -1;
  1702. out:
  1703. if (!error) {
  1704. VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
  1705. if (fromnd.ni_dvp != tdvp)
  1706. VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
  1707. if (tvp)
  1708. VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
  1709. error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
  1710. tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
  1711. } else {
  1712. VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
  1713. if (tdvp == tvp)
  1714. vrele(tdvp);
  1715. else
  1716. vput(tdvp);
  1717. if (tvp)
  1718. vput(tvp);
  1719. VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
  1720. vrele(fromnd.ni_dvp);
  1721. vrele(fvp);
  1722. }
  1723. vrele(tond.ni_startdir);
  1724. FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
  1725. out1:
  1726. if (fromnd.ni_startdir)
  1727. vrele(fromnd.ni_startdir);
  1728. FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
  1729. if (error == -1)
  1730. return (0);
  1731. return (error);
  1732. }
  1733. /*
  1734. * Make a directory file.
  1735. */
  1736. /* ARGSUSED */
  1737. int
  1738. sys_mkdir(p, v, retval)
  1739. struct proc *p;
  1740. void *v;
  1741. register_t *retval;
  1742. {
  1743. register struct sys_mkdir_args /* {
  1744. syscallarg(char *) path;
  1745. syscallarg(int) mode;
  1746. } */ *uap = v;
  1747. register struct vnode *vp;
  1748. struct vattr vattr;
  1749. int error;
  1750. struct nameidata nd;
  1751. NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
  1752. if ((error = namei(&nd)) != 0)
  1753. return (error);
  1754. vp = nd.ni_vp;
  1755. if (vp != NULL) {
  1756. VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
  1757. if (nd.ni_dvp == vp)
  1758. vrele(nd.ni_dvp);
  1759. else
  1760. vput(nd.ni_dvp);
  1761. vrele(vp);
  1762. return (EEXIST);
  1763. }
  1764. VATTR_NULL(&vattr);
  1765. vattr.va_type = VDIR;
  1766. vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
  1767. VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
  1768. error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
  1769. if (!error)
  1770. vput(nd.ni_vp);
  1771. return (error);
  1772. }
  1773. /*
  1774. * Remove a directory file.
  1775. */
  1776. /* ARGSUSED */
  1777. int
  1778. sys_rmdir(p, v, retval)
  1779. struct proc *p;
  1780. void *v;
  1781. register_t *retval;
  1782. {
  1783. struct sys_rmdir_args /* {
  1784. syscallarg(char *) path;
  1785. } */ *uap = v;
  1786. register struct vnode *vp;
  1787. int error;
  1788. struct nameidata nd;
  1789. NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
  1790. SCARG(uap, path), p);
  1791. if ((error = namei(&nd)) != 0)
  1792. return (error);
  1793. vp = nd.ni_vp;
  1794. if (vp->v_type != VDIR) {
  1795. error = ENOTDIR;
  1796. goto out;
  1797. }
  1798. /*
  1799. * No rmdir "." please.
  1800. */
  1801. if (nd.ni_dvp == vp) {
  1802. error = EINVAL;
  1803. goto out;
  1804. }
  1805. /*
  1806. * The root of a mounted filesystem cannot be deleted.
  1807. */
  1808. if (vp->v_flag & VROOT)
  1809. error = EBUSY;
  1810. out:
  1811. if (!error) {
  1812. VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
  1813. VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
  1814. error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
  1815. } else {
  1816. VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
  1817. if (nd.ni_dvp == vp)
  1818. vrele(nd.ni_dvp);
  1819. else
  1820. vput(nd.ni_dvp);
  1821. vput(vp);
  1822. }
  1823. return (error);
  1824. }
  1825. /*
  1826. * Read a block of directory entries in a file system independent format.
  1827. */
  1828. int
  1829. sys_getdirentries(p, v, retval)
  1830. struct proc *p;
  1831. void *v;
  1832. register_t *retval;
  1833. {
  1834. register struct sys_getdirentries_args /* {
  1835. syscallarg(int) fd;
  1836. syscallarg(char *) buf;
  1837. syscallarg(u_int) count;
  1838. syscallarg(long *) basep;
  1839. } */ *uap = v;
  1840. register struct vnode *vp;
  1841. struct file *fp;
  1842. struct uio auio;
  1843. struct iovec aiov;
  1844. long loff;
  1845. int error, eofflag;
  1846. if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
  1847. return (error);
  1848. if ((fp->f_flag & FREAD) == 0)
  1849. return (EBADF);
  1850. vp = (struct vnode *)fp->f_data;
  1851. unionread:
  1852. if (vp->v_type != VDIR)
  1853. return (EINVAL);
  1854. aiov.iov_base = SCARG(uap, buf);
  1855. aiov.iov_len = SCARG(uap, count);
  1856. auio.uio_iov = &aiov;
  1857. auio.uio_iovcnt = 1;
  1858. auio.uio_rw = UIO_READ;
  1859. auio.uio_segflg = UIO_USERSPACE;
  1860. auio.uio_procp = p;
  1861. auio.uio_resid = SCARG(uap, count);
  1862. VOP_LOCK(vp);
  1863. loff = auio.uio_offset = fp->f_offset;
  1864. error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (u_long *)0, 0);
  1865. fp->f_offset = auio.uio_offset;
  1866. VOP_UNLOCK(vp);
  1867. if (error)
  1868. return (error);
  1869. #ifdef UNION
  1870. {
  1871. extern int (**union_vnodeop_p) __P((void *));
  1872. extern struct vnode *union_dircache __P((struct vnode *));
  1873. if ((SCARG(uap, count) == auio.uio_resid) &&
  1874. (vp->v_op == union_vnodeop_p)) {
  1875. struct vnode *lvp;
  1876. lvp = union_dircache(vp);
  1877. if (lvp != NULLVP) {
  1878. struct vattr va;
  1879. /*
  1880. * If the directory is opaque,
  1881. * then don't show lower entries
  1882. */
  1883. error = VOP_GETATTR(vp, &va, fp->f_cred, p);
  1884. if (va.va_flags & OPAQUE) {
  1885. vput(lvp);
  1886. lvp = NULL;
  1887. }
  1888. }
  1889. if (lvp != NULLVP) {
  1890. error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
  1891. VOP_UNLOCK(lvp);
  1892. if (error) {
  1893. vrele(lvp);
  1894. return (error);
  1895. }
  1896. fp->f_data = (caddr_t) lvp;
  1897. fp->f_offset = 0;
  1898. error = vn_close(vp, FREAD, fp->f_cred, p);
  1899. if (error)
  1900. return (error);
  1901. vp = lvp;
  1902. goto unionread;
  1903. }
  1904. }
  1905. }
  1906. #endif /* UNION */
  1907. if ((SCARG(uap, count) == auio.uio_resid) &&
  1908. (vp->v_flag & VROOT) &&
  1909. (vp->v_mount->mnt_flag & MNT_UNION)) {
  1910. struct vnode *tvp = vp;
  1911. vp = vp->v_mount->mnt_vnodecovered;
  1912. VREF(vp);
  1913. fp->f_data = (caddr_t) vp;
  1914. fp->f_offset = 0;
  1915. vrele(tvp);
  1916. goto unionread;
  1917. }
  1918. error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
  1919. sizeof(long));
  1920. *retval = SCARG(uap, count) - auio.uio_resid;
  1921. return (error);
  1922. }
  1923. /*
  1924. * Set the mode mask for creation of filesystem nodes.
  1925. */
  1926. int
  1927. sys_umask(p, v, retval)
  1928. struct proc *p;
  1929. void *v;
  1930. register_t *retval;
  1931. {
  1932. struct sys_umask_args /* {
  1933. syscallarg(int) newmask;
  1934. } */ *uap = v;
  1935. register struct filedesc *fdp;
  1936. fdp = p->p_fd;
  1937. *retval = fdp->fd_cmask;
  1938. fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
  1939. return (0);
  1940. }
  1941. /*
  1942. * Void all references to file by ripping underlying filesystem
  1943. * away from vnode.
  1944. */
  1945. /* ARGSUSED */
  1946. int
  1947. sys_revoke(p, v, retval)
  1948. struct proc *p;
  1949. void *v;
  1950. register_t *retval;
  1951. {
  1952. register struct sys_revoke_args /* {
  1953. syscallarg(char *) path;
  1954. } */ *uap = v;
  1955. register struct vnode *vp;
  1956. struct vattr vattr;
  1957. int error;
  1958. struct nameidata nd;
  1959. NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  1960. if ((error = namei(&nd)) != 0)
  1961. return (error);
  1962. vp = nd.ni_vp;
  1963. if (vp->v_type != VCHR && vp->v_type != VBLK) {
  1964. error = EINVAL;
  1965. goto out;
  1966. }
  1967. if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
  1968. goto out;
  1969. if (p->p_ucred->cr_uid != vattr.va_uid &&
  1970. (error = suser(p->p_ucred, &p->p_acflag)))
  1971. goto out;
  1972. if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
  1973. vgoneall(vp);
  1974. out:
  1975. vrele(vp);
  1976. return (error);
  1977. }
  1978. /*
  1979. * Convert a user file descriptor to a kernel file entry.
  1980. */
  1981. int
  1982. getvnode(fdp, fd, fpp)
  1983. struct filedesc *fdp;
  1984. int fd;
  1985. struct file **fpp;
  1986. {
  1987. struct vnode *vp;
  1988. struct file *fp;
  1989. if ((u_int)fd >= fdp->fd_nfiles ||
  1990. (fp = fdp->fd_ofiles[fd]) == NULL)
  1991. return (EBADF);
  1992. if (fp->f_type != DTYPE_VNODE)
  1993. return (EINVAL);
  1994. vp = (struct vnode *)fp->f_data;
  1995. if (vp->v_type == VBAD)
  1996. return (EBADF);
  1997. *fpp = fp;
  1998. return (0);
  1999. }