vfs_lookup.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  1. /* $OpenBSD: vfs_lookup.c,v 1.54 2015/07/19 02:35:35 deraadt Exp $ */
  2. /* $NetBSD: vfs_lookup.c,v 1.17 1996/02/09 19:00:59 christos Exp $ */
  3. /*
  4. * Copyright (c) 1982, 1986, 1989, 1993
  5. * The Regents of the University of California. All rights reserved.
  6. * (c) UNIX System Laboratories, Inc.
  7. * All or some portions of this file are derived from material licensed
  8. * to the University of California by American Telephone and Telegraph
  9. * Co. or Unix System Laboratories, Inc. and are reproduced herein with
  10. * the permission of UNIX System Laboratories, Inc.
  11. *
  12. * Redistribution and use in source and binary forms, with or without
  13. * modification, are permitted provided that the following conditions
  14. * are met:
  15. * 1. Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. * 2. Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in the
  19. * documentation and/or other materials provided with the distribution.
  20. * 3. Neither the name of the University nor the names of its contributors
  21. * may be used to endorse or promote products derived from this software
  22. * without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34. * SUCH DAMAGE.
  35. *
  36. * @(#)vfs_lookup.c 8.6 (Berkeley) 11/21/94
  37. */
  38. #include <sys/param.h>
  39. #include <sys/systm.h>
  40. #include <sys/syslimits.h>
  41. #include <sys/time.h>
  42. #include <sys/namei.h>
  43. #include <sys/vnode.h>
  44. #include <sys/lock.h>
  45. #include <sys/mount.h>
  46. #include <sys/errno.h>
  47. #include <sys/pool.h>
  48. #include <sys/filedesc.h>
  49. #include <sys/proc.h>
  50. #include <sys/file.h>
  51. #include <sys/fcntl.h>
  52. #include <sys/tame.h>
  53. #ifdef KTRACE
  54. #include <sys/ktrace.h>
  55. #endif
  56. #include "systrace.h"
  57. #if NSYSTRACE > 0
  58. #include <dev/systrace.h>
  59. #endif
  60. /*
  61. * Convert a pathname into a pointer to a vnode.
  62. *
  63. * The FOLLOW flag is set when symbolic links are to be followed
  64. * when they occur at the end of the name translation process.
  65. * Symbolic links are always followed for all other pathname
  66. * components other than the last.
  67. *
  68. * If the LOCKLEAF flag is set, a locked vnode is returned.
  69. *
  70. * The segflg defines whether the name is to be copied from user
  71. * space or kernel space.
  72. *
  73. * Overall outline of namei:
  74. *
  75. * copy in name
  76. * get starting directory
  77. * while (!done && !error) {
  78. * call lookup to search path.
  79. * if symbolic link, massage name in buffer and continue
  80. * }
  81. */
  82. int
  83. namei(struct nameidata *ndp)
  84. {
  85. struct filedesc *fdp; /* pointer to file descriptor state */
  86. char *cp; /* pointer into pathname argument */
  87. struct vnode *dp; /* the directory we are searching */
  88. struct iovec aiov; /* uio for reading symbolic links */
  89. struct uio auio;
  90. int error, linklen;
  91. struct componentname *cnp = &ndp->ni_cnd;
  92. struct proc *p = cnp->cn_proc;
  93. ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_proc->p_ucred;
  94. #ifdef DIAGNOSTIC
  95. if (!cnp->cn_cred || !cnp->cn_proc)
  96. panic ("namei: bad cred/proc");
  97. if (cnp->cn_nameiop & (~OPMASK))
  98. panic ("namei: nameiop contaminated with flags");
  99. if (cnp->cn_flags & OPMASK)
  100. panic ("namei: flags contaminated with nameiops");
  101. #endif
  102. fdp = cnp->cn_proc->p_fd;
  103. /*
  104. * Get a buffer for the name to be translated, and copy the
  105. * name into the buffer.
  106. */
  107. if ((cnp->cn_flags & HASBUF) == 0)
  108. cnp->cn_pnbuf = pool_get(&namei_pool, PR_WAITOK);
  109. if (ndp->ni_segflg == UIO_SYSSPACE)
  110. error = copystr(ndp->ni_dirp, cnp->cn_pnbuf,
  111. MAXPATHLEN, &ndp->ni_pathlen);
  112. else
  113. error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf,
  114. MAXPATHLEN, &ndp->ni_pathlen);
  115. /*
  116. * Fail on null pathnames
  117. */
  118. if (error == 0 && ndp->ni_pathlen == 1)
  119. error = ENOENT;
  120. if (error) {
  121. fail:
  122. pool_put(&namei_pool, cnp->cn_pnbuf);
  123. ndp->ni_vp = NULL;
  124. return (error);
  125. }
  126. #ifdef KTRACE
  127. if (KTRPOINT(cnp->cn_proc, KTR_NAMEI))
  128. ktrnamei(cnp->cn_proc, cnp->cn_pnbuf);
  129. #endif
  130. #if NSYSTRACE > 0
  131. if (ISSET(cnp->cn_proc->p_flag, P_SYSTRACE))
  132. systrace_namei(ndp);
  133. #endif
  134. /*
  135. * Strip trailing slashes, as requested
  136. */
  137. if (cnp->cn_flags & STRIPSLASHES) {
  138. char *end = cnp->cn_pnbuf + ndp->ni_pathlen - 2;
  139. cp = end;
  140. while (cp >= cnp->cn_pnbuf && (*cp == '/'))
  141. cp--;
  142. /* Still some remaining characters in the buffer */
  143. if (cp >= cnp->cn_pnbuf) {
  144. ndp->ni_pathlen -= (end - cp);
  145. *(cp + 1) = '\0';
  146. }
  147. }
  148. ndp->ni_loopcnt = 0;
  149. /*
  150. * Get starting point for the translation.
  151. */
  152. if ((ndp->ni_rootdir = fdp->fd_rdir) == NULL)
  153. ndp->ni_rootdir = rootvnode;
  154. if ((p->p_p->ps_flags & PS_TAMED)) {
  155. error = tame_namei(p, cnp->cn_pnbuf);
  156. if (error)
  157. goto fail;
  158. }
  159. /*
  160. * Check if starting from root directory or current directory.
  161. */
  162. if (cnp->cn_pnbuf[0] == '/') {
  163. dp = ndp->ni_rootdir;
  164. vref(dp);
  165. } else if (ndp->ni_dirfd == AT_FDCWD) {
  166. dp = fdp->fd_cdir;
  167. vref(dp);
  168. } else {
  169. struct file *fp = fd_getfile(fdp, ndp->ni_dirfd);
  170. if (fp == NULL) {
  171. pool_put(&namei_pool, cnp->cn_pnbuf);
  172. return (EBADF);
  173. }
  174. dp = (struct vnode *)fp->f_data;
  175. if (fp->f_type != DTYPE_VNODE || dp->v_type != VDIR) {
  176. pool_put(&namei_pool, cnp->cn_pnbuf);
  177. return (ENOTDIR);
  178. }
  179. vref(dp);
  180. }
  181. for (;;) {
  182. if (!dp->v_mount) {
  183. /* Give up if the directory is no longer mounted */
  184. pool_put(&namei_pool, cnp->cn_pnbuf);
  185. return (ENOENT);
  186. }
  187. cnp->cn_nameptr = cnp->cn_pnbuf;
  188. ndp->ni_startdir = dp;
  189. if ((error = vfs_lookup(ndp)) != 0) {
  190. pool_put(&namei_pool, cnp->cn_pnbuf);
  191. return (error);
  192. }
  193. /*
  194. * If not a symbolic link, return search result.
  195. */
  196. if ((cnp->cn_flags & ISSYMLINK) == 0) {
  197. if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0)
  198. pool_put(&namei_pool, cnp->cn_pnbuf);
  199. else
  200. cnp->cn_flags |= HASBUF;
  201. return (0);
  202. }
  203. if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN))
  204. VOP_UNLOCK(ndp->ni_dvp, 0, p);
  205. if (ndp->ni_loopcnt++ >= SYMLOOP_MAX) {
  206. error = ELOOP;
  207. break;
  208. }
  209. if (ndp->ni_pathlen > 1)
  210. cp = pool_get(&namei_pool, PR_WAITOK);
  211. else
  212. cp = cnp->cn_pnbuf;
  213. aiov.iov_base = cp;
  214. aiov.iov_len = MAXPATHLEN;
  215. auio.uio_iov = &aiov;
  216. auio.uio_iovcnt = 1;
  217. auio.uio_offset = 0;
  218. auio.uio_rw = UIO_READ;
  219. auio.uio_segflg = UIO_SYSSPACE;
  220. auio.uio_procp = cnp->cn_proc;
  221. auio.uio_resid = MAXPATHLEN;
  222. error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
  223. if (error) {
  224. badlink:
  225. if (ndp->ni_pathlen > 1)
  226. pool_put(&namei_pool, cp);
  227. break;
  228. }
  229. linklen = MAXPATHLEN - auio.uio_resid;
  230. if (linklen == 0) {
  231. error = ENOENT;
  232. goto badlink;
  233. }
  234. if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
  235. error = ENAMETOOLONG;
  236. goto badlink;
  237. }
  238. if (ndp->ni_pathlen > 1) {
  239. memcpy(cp + linklen, ndp->ni_next, ndp->ni_pathlen);
  240. pool_put(&namei_pool, cnp->cn_pnbuf);
  241. cnp->cn_pnbuf = cp;
  242. } else
  243. cnp->cn_pnbuf[linklen] = '\0';
  244. ndp->ni_pathlen += linklen;
  245. vput(ndp->ni_vp);
  246. dp = ndp->ni_dvp;
  247. /*
  248. * Check if root directory should replace current directory.
  249. */
  250. if (cnp->cn_pnbuf[0] == '/') {
  251. vrele(dp);
  252. dp = ndp->ni_rootdir;
  253. vref(dp);
  254. }
  255. }
  256. pool_put(&namei_pool, cnp->cn_pnbuf);
  257. vrele(ndp->ni_dvp);
  258. vput(ndp->ni_vp);
  259. ndp->ni_vp = NULL;
  260. return (error);
  261. }
  262. /*
  263. * Search a pathname.
  264. * This is a very central and rather complicated routine.
  265. *
  266. * The pathname is pointed to by ni_cnd.cn_nameptr and is of length
  267. * ni_pathlen. The starting directory is taken from ni_startdir. The
  268. * pathname is descended until done, or a symbolic link is encountered.
  269. * If the path is completed the flag ISLASTCN is set in ni_cnd.cn_flags.
  270. * If a symbolic link need interpretation is encountered, the flag ISSYMLINK
  271. * is set in ni_cnd.cn_flags.
  272. *
  273. * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
  274. * whether the name is to be looked up, created, renamed, or deleted.
  275. * When CREATE, RENAME, or DELETE is specified, information usable in
  276. * creating, renaming, or deleting a directory entry may be calculated.
  277. * If flag has LOCKPARENT or'ed into it, the parent directory is returned
  278. * locked. If flag has WANTPARENT or'ed into it, the parent directory is
  279. * returned unlocked. Otherwise the parent directory is not returned. If
  280. * the target of the pathname exists and LOCKLEAF is or'ed into the flag
  281. * the target is returned locked, otherwise it is returned unlocked.
  282. * When creating or renaming and LOCKPARENT is specified, the target may not
  283. * be ".". When deleting and LOCKPARENT is specified, the target may be ".".
  284. *
  285. * Overall outline of lookup:
  286. *
  287. * dirloop:
  288. * identify next component of name at ndp->ni_ptr
  289. * handle degenerate case where name is null string
  290. * if .. and crossing mount points and on mounted filesys, find parent
  291. * call VOP_LOOKUP routine for next component name
  292. * directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set
  293. * component vnode returned in ni_vp (if it exists), locked.
  294. * if result vnode is mounted on and crossing mount points,
  295. * find mounted on vnode
  296. * if more components of name, do next level at dirloop
  297. * return the answer in ni_vp, locked if LOCKLEAF set
  298. * if LOCKPARENT set, return locked parent in ni_dvp
  299. * if WANTPARENT set, return unlocked parent in ni_dvp
  300. */
  301. int
  302. vfs_lookup(struct nameidata *ndp)
  303. {
  304. char *cp; /* pointer into pathname argument */
  305. struct vnode *dp = 0; /* the directory we are searching */
  306. struct vnode *tdp; /* saved dp */
  307. struct mount *mp; /* mount table entry */
  308. int docache; /* == 0 do not cache last component */
  309. int wantparent; /* 1 => wantparent or lockparent flag */
  310. int rdonly; /* lookup read-only flag bit */
  311. int error = 0;
  312. int dpunlocked = 0; /* dp has already been unlocked */
  313. int slashes;
  314. struct componentname *cnp = &ndp->ni_cnd;
  315. struct proc *p = cnp->cn_proc;
  316. /*
  317. * Setup: break out flag bits into variables.
  318. */
  319. wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT);
  320. docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE;
  321. if (cnp->cn_nameiop == DELETE ||
  322. (wantparent && cnp->cn_nameiop != CREATE))
  323. docache = 0;
  324. rdonly = cnp->cn_flags & RDONLY;
  325. ndp->ni_dvp = NULL;
  326. cnp->cn_flags &= ~ISSYMLINK;
  327. dp = ndp->ni_startdir;
  328. ndp->ni_startdir = NULLVP;
  329. vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
  330. /*
  331. * If we have a leading string of slashes, remove them, and just make
  332. * sure the current node is a directory.
  333. */
  334. cp = cnp->cn_nameptr;
  335. if (*cp == '/') {
  336. do {
  337. cp++;
  338. } while (*cp == '/');
  339. ndp->ni_pathlen -= cp - cnp->cn_nameptr;
  340. cnp->cn_nameptr = cp;
  341. if (dp->v_type != VDIR) {
  342. error = ENOTDIR;
  343. goto bad;
  344. }
  345. /*
  346. * If we've exhausted the path name, then just return the
  347. * current node. If the caller requested the parent node (i.e.
  348. * it's a CREATE, DELETE, or RENAME), and we don't have one
  349. * (because this is the root directory), then we must fail.
  350. */
  351. if (cnp->cn_nameptr[0] == '\0') {
  352. if (ndp->ni_dvp == NULL && wantparent) {
  353. error = EISDIR;
  354. goto bad;
  355. }
  356. ndp->ni_vp = dp;
  357. cnp->cn_flags |= ISLASTCN;
  358. goto terminal;
  359. }
  360. }
  361. dirloop:
  362. /*
  363. * Search a new directory.
  364. *
  365. * The last component of the filename is left accessible via
  366. * cnp->cn_nameptr for callers that need the name. Callers needing
  367. * the name set the SAVENAME flag. When done, they assume
  368. * responsibility for freeing the pathname buffer.
  369. */
  370. cnp->cn_consume = 0;
  371. /* XXX: Figure out the length of the last component. */
  372. cp = cnp->cn_nameptr;
  373. while (*cp && (*cp != '/'))
  374. cp++;
  375. cnp->cn_namelen = cp - cnp->cn_nameptr;
  376. if (cnp->cn_namelen > NAME_MAX) {
  377. error = ENAMETOOLONG;
  378. goto bad;
  379. }
  380. #ifdef NAMEI_DIAGNOSTIC
  381. { char c = *cp;
  382. *cp = '\0';
  383. printf("{%s}: ", cnp->cn_nameptr);
  384. *cp = c; }
  385. #endif
  386. ndp->ni_pathlen -= cnp->cn_namelen;
  387. ndp->ni_next = cp;
  388. /*
  389. * If this component is followed by a slash, then move the pointer to
  390. * the next component forward, and remember that this component must be
  391. * a directory.
  392. */
  393. if (*cp == '/') {
  394. do {
  395. cp++;
  396. } while (*cp == '/');
  397. slashes = cp - ndp->ni_next;
  398. ndp->ni_pathlen -= slashes;
  399. ndp->ni_next = cp;
  400. cnp->cn_flags |= REQUIREDIR;
  401. } else {
  402. slashes = 0;
  403. cnp->cn_flags &= ~REQUIREDIR;
  404. }
  405. /*
  406. * We do special processing on the last component, whether or not it's
  407. * a directory. Cache all intervening lookups, but not the final one.
  408. */
  409. if (*cp == '\0') {
  410. if (docache)
  411. cnp->cn_flags |= MAKEENTRY;
  412. else
  413. cnp->cn_flags &= ~MAKEENTRY;
  414. cnp->cn_flags |= ISLASTCN;
  415. } else {
  416. cnp->cn_flags |= MAKEENTRY;
  417. cnp->cn_flags &= ~ISLASTCN;
  418. }
  419. if (cnp->cn_namelen == 2 &&
  420. cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.')
  421. cnp->cn_flags |= ISDOTDOT;
  422. else
  423. cnp->cn_flags &= ~ISDOTDOT;
  424. /*
  425. * Handle "..": two special cases.
  426. * 1. If at root directory (e.g. after chroot)
  427. * or at absolute root directory
  428. * then ignore it so can't get out.
  429. * 2. If this vnode is the root of a mounted
  430. * filesystem, then replace it with the
  431. * vnode which was mounted on so we take the
  432. * .. in the other file system.
  433. */
  434. if (cnp->cn_flags & ISDOTDOT) {
  435. for (;;) {
  436. if (dp == ndp->ni_rootdir || dp == rootvnode) {
  437. ndp->ni_dvp = dp;
  438. ndp->ni_vp = dp;
  439. vref(dp);
  440. goto nextname;
  441. }
  442. if ((dp->v_flag & VROOT) == 0 ||
  443. (cnp->cn_flags & NOCROSSMOUNT))
  444. break;
  445. tdp = dp;
  446. dp = dp->v_mount->mnt_vnodecovered;
  447. vput(tdp);
  448. vref(dp);
  449. vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
  450. }
  451. }
  452. /*
  453. * We now have a segment name to search for, and a directory to search.
  454. */
  455. ndp->ni_dvp = dp;
  456. ndp->ni_vp = NULL;
  457. cnp->cn_flags &= ~PDIRUNLOCK;
  458. if ((error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) != 0) {
  459. #ifdef DIAGNOSTIC
  460. if (ndp->ni_vp != NULL)
  461. panic("leaf should be empty");
  462. #endif
  463. #ifdef NAMEI_DIAGNOSTIC
  464. printf("not found\n");
  465. #endif
  466. if (error != EJUSTRETURN)
  467. goto bad;
  468. /*
  469. * If this was not the last component, or there were trailing
  470. * slashes, then the name must exist.
  471. */
  472. if (cnp->cn_flags & REQUIREDIR) {
  473. error = ENOENT;
  474. goto bad;
  475. }
  476. /*
  477. * If creating and at end of pathname, then can consider
  478. * allowing file to be created.
  479. */
  480. if (rdonly || (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY)) {
  481. error = EROFS;
  482. goto bad;
  483. }
  484. /*
  485. * We return with ni_vp NULL to indicate that the entry
  486. * doesn't currently exist, leaving a pointer to the
  487. * (possibly locked) directory inode in ndp->ni_dvp.
  488. */
  489. if (cnp->cn_flags & SAVESTART) {
  490. ndp->ni_startdir = ndp->ni_dvp;
  491. vref(ndp->ni_startdir);
  492. }
  493. return (0);
  494. }
  495. #ifdef NAMEI_DIAGNOSTIC
  496. printf("found\n");
  497. #endif
  498. /*
  499. * Take into account any additional components consumed by the
  500. * underlying filesystem. This will include any trailing slashes after
  501. * the last component consumed.
  502. */
  503. if (cnp->cn_consume > 0) {
  504. if (cnp->cn_consume >= slashes) {
  505. cnp->cn_flags &= ~REQUIREDIR;
  506. }
  507. ndp->ni_pathlen -= cnp->cn_consume - slashes;
  508. ndp->ni_next += cnp->cn_consume - slashes;
  509. cnp->cn_consume = 0;
  510. if (ndp->ni_next[0] == '\0')
  511. cnp->cn_flags |= ISLASTCN;
  512. }
  513. dp = ndp->ni_vp;
  514. /*
  515. * Check to see if the vnode has been mounted on;
  516. * if so find the root of the mounted file system.
  517. */
  518. while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
  519. (cnp->cn_flags & NOCROSSMOUNT) == 0) {
  520. if (vfs_busy(mp, VB_READ|VB_WAIT))
  521. continue;
  522. VOP_UNLOCK(dp, 0, p);
  523. error = VFS_ROOT(mp, &tdp);
  524. vfs_unbusy(mp);
  525. if (error) {
  526. dpunlocked = 1;
  527. goto bad2;
  528. }
  529. vrele(dp);
  530. ndp->ni_vp = dp = tdp;
  531. }
  532. /*
  533. * Check for symbolic link. Back up over any slashes that we skipped,
  534. * as we will need them again.
  535. */
  536. if ((dp->v_type == VLNK) && (cnp->cn_flags & (FOLLOW|REQUIREDIR))) {
  537. ndp->ni_pathlen += slashes;
  538. ndp->ni_next -= slashes;
  539. cnp->cn_flags |= ISSYMLINK;
  540. return (0);
  541. }
  542. /*
  543. * Check for directory, if the component was followed by a series of
  544. * slashes.
  545. */
  546. if ((dp->v_type != VDIR) && (cnp->cn_flags & REQUIREDIR)) {
  547. error = ENOTDIR;
  548. goto bad2;
  549. }
  550. nextname:
  551. /*
  552. * Not a symbolic link. If this was not the last component, then
  553. * continue at the next component, else return.
  554. */
  555. if (!(cnp->cn_flags & ISLASTCN)) {
  556. cnp->cn_nameptr = ndp->ni_next;
  557. vrele(ndp->ni_dvp);
  558. goto dirloop;
  559. }
  560. terminal:
  561. /*
  562. * Check for read-only file systems.
  563. */
  564. if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) {
  565. /*
  566. * Disallow directory write attempts on read-only
  567. * file systems.
  568. */
  569. if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) ||
  570. (wantparent &&
  571. (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY))) {
  572. error = EROFS;
  573. goto bad2;
  574. }
  575. }
  576. if (ndp->ni_dvp != NULL) {
  577. if (cnp->cn_flags & SAVESTART) {
  578. ndp->ni_startdir = ndp->ni_dvp;
  579. vref(ndp->ni_startdir);
  580. }
  581. if (!wantparent)
  582. vrele(ndp->ni_dvp);
  583. }
  584. if ((cnp->cn_flags & LOCKLEAF) == 0)
  585. VOP_UNLOCK(dp, 0, p);
  586. return (0);
  587. bad2:
  588. if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN) &&
  589. ((cnp->cn_flags & PDIRUNLOCK) == 0))
  590. VOP_UNLOCK(ndp->ni_dvp, 0, p);
  591. vrele(ndp->ni_dvp);
  592. bad:
  593. if (dpunlocked)
  594. vrele(dp);
  595. else
  596. vput(dp);
  597. ndp->ni_vp = NULL;
  598. return (error);
  599. }
  600. /*
  601. * Reacquire a path name component.
  602. */
  603. int
  604. vfs_relookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp)
  605. {
  606. struct proc *p = cnp->cn_proc;
  607. struct vnode *dp = 0; /* the directory we are searching */
  608. int wantparent; /* 1 => wantparent or lockparent flag */
  609. int rdonly; /* lookup read-only flag bit */
  610. int error = 0;
  611. #ifdef NAMEI_DIAGNOSTIC
  612. char *cp; /* DEBUG: check name ptr/len */
  613. #endif
  614. /*
  615. * Setup: break out flag bits into variables.
  616. */
  617. wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT);
  618. rdonly = cnp->cn_flags & RDONLY;
  619. cnp->cn_flags &= ~ISSYMLINK;
  620. dp = dvp;
  621. vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
  622. /* dirloop: */
  623. /*
  624. * Search a new directory.
  625. *
  626. * The last component of the filename is left accessible via
  627. * cnp->cn_nameptr for callers that need the name. Callers needing
  628. * the name set the SAVENAME flag. When done, they assume
  629. * responsibility for freeing the pathname buffer.
  630. */
  631. #ifdef NAMEI_DIAGNOSTIC
  632. /* XXX: Figure out the length of the last component. */
  633. cp = cnp->cn_nameptr;
  634. while (*cp && (*cp != '/')) {
  635. cp++;
  636. }
  637. if (cnp->cn_namelen != cp - cnp->cn_nameptr)
  638. panic("relookup: bad len");
  639. if (*cp != 0)
  640. panic("relookup: not last component");
  641. printf("{%s}: ", cnp->cn_nameptr);
  642. #endif
  643. /*
  644. * Check for degenerate name (e.g. / or "")
  645. * which is a way of talking about a directory,
  646. * e.g. like "/." or ".".
  647. */
  648. if (cnp->cn_nameptr[0] == '\0')
  649. panic("relookup: null name");
  650. if (cnp->cn_flags & ISDOTDOT)
  651. panic ("relookup: lookup on dot-dot");
  652. /*
  653. * We now have a segment name to search for, and a directory to search.
  654. */
  655. if ((error = VOP_LOOKUP(dp, vpp, cnp)) != 0) {
  656. #ifdef DIAGNOSTIC
  657. if (*vpp != NULL)
  658. panic("leaf should be empty");
  659. #endif
  660. if (error != EJUSTRETURN)
  661. goto bad;
  662. /*
  663. * If creating and at end of pathname, then can consider
  664. * allowing file to be created.
  665. */
  666. if (rdonly || (dvp->v_mount->mnt_flag & MNT_RDONLY)) {
  667. error = EROFS;
  668. goto bad;
  669. }
  670. /* ASSERT(dvp == ndp->ni_startdir) */
  671. if (cnp->cn_flags & SAVESTART)
  672. vref(dvp);
  673. /*
  674. * We return with ni_vp NULL to indicate that the entry
  675. * doesn't currently exist, leaving a pointer to the
  676. * (possibly locked) directory inode in ndp->ni_dvp.
  677. */
  678. return (0);
  679. }
  680. dp = *vpp;
  681. #ifdef DIAGNOSTIC
  682. /*
  683. * Check for symbolic link
  684. */
  685. if (dp->v_type == VLNK && (cnp->cn_flags & FOLLOW))
  686. panic ("relookup: symlink found.");
  687. #endif
  688. /*
  689. * Check for read-only file systems.
  690. */
  691. if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) {
  692. /*
  693. * Disallow directory write attempts on read-only
  694. * file systems.
  695. */
  696. if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) ||
  697. (wantparent &&
  698. (dvp->v_mount->mnt_flag & MNT_RDONLY))) {
  699. error = EROFS;
  700. goto bad2;
  701. }
  702. }
  703. /* ASSERT(dvp == ndp->ni_startdir) */
  704. if (cnp->cn_flags & SAVESTART)
  705. vref(dvp);
  706. if (!wantparent)
  707. vrele(dvp);
  708. if ((cnp->cn_flags & LOCKLEAF) == 0)
  709. VOP_UNLOCK(dp, 0, p);
  710. return (0);
  711. bad2:
  712. if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN))
  713. VOP_UNLOCK(dvp, 0, p);
  714. vrele(dvp);
  715. bad:
  716. vput(dp);
  717. *vpp = NULL;
  718. return (error);
  719. }