1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)vfs_lookup.c 7.39 (Berkeley) 05/14/92 8 */ 9 10 #include "param.h" 11 #include "syslimits.h" 12 #include "time.h" 13 #include "namei.h" 14 #include "vnode.h" 15 #include "mount.h" 16 #include "errno.h" 17 #include "malloc.h" 18 #include "filedesc.h" 19 #include "proc.h" 20 21 #ifdef KTRACE 22 #include "ktrace.h" 23 #endif 24 25 /* 26 * Convert a pathname into a pointer to a locked inode. 27 * 28 * The FOLLOW flag is set when symbolic links are to be followed 29 * when they occur at the end of the name translation process. 30 * Symbolic links are always followed for all other pathname 31 * components other than the last. 32 * 33 * The segflg defines whether the name is to be copied from user 34 * space or kernel space. 35 * 36 * Overall outline of namei: 37 * 38 * copy in name 39 * get starting directory 40 * while (!done && !error) { 41 * call lookup to search path. 42 * if symbolic link, massage name in buffer and continue 43 * } 44 */ 45 int 46 namei(ndp) 47 register struct nameidata *ndp; 48 { 49 USES_VOP_READLINK; 50 USES_VOP_UNLOCK; 51 register struct filedesc *fdp; /* pointer to file descriptor state */ 52 register char *cp; /* pointer into pathname argument */ 53 register struct vnode *dp; /* the directory we are searching */ 54 struct iovec aiov; /* uio for reading symbolic links */ 55 struct uio auio; 56 int error, linklen; 57 struct componentname *cnp = &ndp->ni_cnd; 58 59 ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_proc->p_ucred; 60 #ifdef DIAGNOSTIC 61 if (!cnp->cn_cred || !cnp->cn_proc) 62 panic ("namei: bad cred/proc"); 63 if (cnp->cn_nameiop & (~OPMASK)) 64 panic ("namei: nameiop contaminated with flags"); 65 if (cnp->cn_flags & OPMASK) 66 panic ("namei: flags contaminated with nameiops"); 67 #endif 68 fdp = cnp->cn_proc->p_fd; 69 70 /* 71 * Get a buffer for the name to be translated, and copy the 72 * name into the buffer. 73 */ 74 if ((cnp->cn_flags & HASBUF) == 0) 75 MALLOC(cnp->cn_pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK); 76 if (ndp->ni_segflg == UIO_SYSSPACE) 77 error = copystr(ndp->ni_dirp, cnp->cn_pnbuf, 78 MAXPATHLEN, &ndp->ni_pathlen); 79 else 80 error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf, 81 MAXPATHLEN, &ndp->ni_pathlen); 82 if (error) { 83 free(cnp->cn_pnbuf, M_NAMEI); 84 ndp->ni_vp = NULL; 85 return (error); 86 } 87 ndp->ni_loopcnt = 0; 88 #ifdef KTRACE 89 if (KTRPOINT(cnp->cn_proc, KTR_NAMEI)) 90 ktrnamei(cnp->cn_proc->p_tracep, cnp->cn_pnbuf); 91 #endif 92 93 /* 94 * Get starting point for the translation. 95 */ 96 if ((ndp->ni_rootdir = fdp->fd_rdir) == NULL) 97 ndp->ni_rootdir = rootdir; 98 dp = fdp->fd_cdir; 99 VREF(dp); 100 for (;;) { 101 /* 102 * Check if root directory should replace current directory. 103 * Done at start of translation and after symbolic link. 104 */ 105 cnp->cn_nameptr = cnp->cn_pnbuf; 106 if (*(cnp->cn_nameptr) == '/') { 107 vrele(dp); 108 while (*(cnp->cn_nameptr) == '/') { 109 cnp->cn_nameptr++; 110 ndp->ni_pathlen--; 111 } 112 dp = ndp->ni_rootdir; 113 VREF(dp); 114 } 115 ndp->ni_startdir = dp; 116 if (error = lookup(ndp)) { 117 FREE(cnp->cn_pnbuf, M_NAMEI); 118 return (error); 119 } 120 /* 121 * Check for symbolic link 122 */ 123 if ((cnp->cn_flags & ISSYMLINK) == 0) { 124 if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0) 125 FREE(cnp->cn_pnbuf, M_NAMEI); 126 else 127 cnp->cn_flags |= HASBUF; 128 return (0); 129 } 130 if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1) 131 VOP_UNLOCK(ndp->ni_dvp); 132 if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { 133 error = ELOOP; 134 break; 135 } 136 if (ndp->ni_pathlen > 1) 137 MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 138 else 139 cp = cnp->cn_pnbuf; 140 aiov.iov_base = cp; 141 aiov.iov_len = MAXPATHLEN; 142 auio.uio_iov = &aiov; 143 auio.uio_iovcnt = 1; 144 auio.uio_offset = 0; 145 auio.uio_rw = UIO_READ; 146 auio.uio_segflg = UIO_SYSSPACE; 147 auio.uio_procp = (struct proc *)0; 148 auio.uio_resid = MAXPATHLEN; 149 if (error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred)) { 150 if (ndp->ni_pathlen > 1) 151 free(cp, M_NAMEI); 152 break; 153 } 154 linklen = MAXPATHLEN - auio.uio_resid; 155 if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { 156 if (ndp->ni_pathlen > 1) 157 free(cp, M_NAMEI); 158 error = ENAMETOOLONG; 159 break; 160 } 161 if (ndp->ni_pathlen > 1) { 162 bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen); 163 FREE(cnp->cn_pnbuf, M_NAMEI); 164 cnp->cn_pnbuf = cp; 165 } else 166 cnp->cn_pnbuf[linklen] = '\0'; 167 ndp->ni_pathlen += linklen; 168 vput(ndp->ni_vp); 169 dp = ndp->ni_dvp; 170 } 171 FREE(cnp->cn_pnbuf, M_NAMEI); 172 vrele(ndp->ni_dvp); 173 vput(ndp->ni_vp); 174 ndp->ni_vp = NULL; 175 return (error); 176 } 177 178 /* 179 * Search a pathname. 180 * This is a very central and rather complicated routine. 181 * 182 * The pathname is pointed to by ni_ptr and is of length ni_pathlen. 183 * The starting directory is taken from ni_startdir. The pathname is 184 * descended until done, or a symbolic link is encountered. The variable 185 * ni_more is clear if the path is completed; it is set to one if a 186 * symbolic link needing interpretation is encountered. 187 * 188 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on 189 * whether the name is to be looked up, created, renamed, or deleted. 190 * When CREATE, RENAME, or DELETE is specified, information usable in 191 * creating, renaming, or deleting a directory entry may be calculated. 192 * If flag has LOCKPARENT or'ed into it, the parent directory is returned 193 * locked. If flag has WANTPARENT or'ed into it, the parent directory is 194 * returned unlocked. Otherwise the parent directory is not returned. If 195 * the target of the pathname exists and LOCKLEAF is or'ed into the flag 196 * the target is returned locked, otherwise it is returned unlocked. 197 * When creating or renaming and LOCKPARENT is specified, the target may not 198 * be ".". When deleting and LOCKPARENT is specified, the target may be ".". 199 * NOTE: (LOOKUP | LOCKPARENT) currently returns the parent vnode unlocked. 200 * 201 * Overall outline of lookup: 202 * 203 * dirloop: 204 * identify next component of name at ndp->ni_ptr 205 * handle degenerate case where name is null string 206 * if .. and crossing mount points and on mounted filesys, find parent 207 * call VOP_LOOKUP routine for next component name 208 * directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set 209 * component vnode returned in ni_vp (if it exists), locked. 210 * if result vnode is mounted on and crossing mount points, 211 * find mounted on vnode 212 * if more components of name, do next level at dirloop 213 * return the answer in ni_vp, locked if LOCKLEAF set 214 * if LOCKPARENT set, return locked parent in ni_dvp 215 * if WANTPARENT set, return unlocked parent in ni_dvp 216 */ 217 int 218 lookup(ndp) 219 register struct nameidata *ndp; 220 { 221 USES_VOP_LOCK; 222 USES_VOP_LOOKUP; 223 USES_VOP_UNLOCK; 224 register char *cp; /* pointer into pathname argument */ 225 register struct vnode *dp = 0; /* the directory we are searching */ 226 struct vnode *tdp; /* saved dp */ 227 struct mount *mp; /* mount table entry */ 228 int docache; /* == 0 do not cache last component */ 229 int wantparent; /* 1 => wantparent or lockparent flag */ 230 int rdonly; /* lookup read-only flag bit */ 231 int error = 0; 232 struct componentname *cnp = &ndp->ni_cnd; 233 234 /* 235 * Setup: break out flag bits into variables. 236 */ 237 wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT); 238 docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE; 239 if (cnp->cn_nameiop == DELETE || 240 (wantparent && cnp->cn_nameiop != CREATE)) 241 docache = 0; 242 rdonly = cnp->cn_flags & RDONLY; 243 ndp->ni_dvp = NULL; 244 cnp->cn_flags &= ~ISSYMLINK; 245 dp = ndp->ni_startdir; 246 ndp->ni_startdir = NULLVP; 247 VOP_LOCK(dp); 248 249 dirloop: 250 /* 251 * Search a new directory. 252 * 253 * The cn_hash value is for use by vfs_cache. 254 * The last component of the filename is left accessible via 255 * cnp->cn_nameptr for callers that need the name. Callers needing 256 * the name set the SAVENAME flag. When done, they assume 257 * responsibility for freeing the pathname buffer. 258 */ 259 cnp->cn_hash = 0; 260 for (cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++) 261 cnp->cn_hash += (unsigned char)*cp; 262 cnp->cn_namelen = cp - cnp->cn_nameptr; 263 if (cnp->cn_namelen >= NAME_MAX) { 264 error = ENAMETOOLONG; 265 goto bad; 266 } 267 #ifdef NAMEI_DIAGNOSTIC 268 { char c = *cp; 269 *cp = '\0'; 270 printf("{%s}: ", cnp->cn_nameptr); 271 *cp = c; } 272 #endif 273 ndp->ni_pathlen -= cnp->cn_namelen; 274 ndp->ni_next = cp; 275 cnp->cn_flags |= MAKEENTRY; 276 if (*cp == '\0' && docache == 0) 277 cnp->cn_flags &= ~MAKEENTRY; 278 if (cnp->cn_namelen == 2 && 279 cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.') 280 cnp->cn_flags |= ISDOTDOT; 281 else cnp->cn_flags &= ~ISDOTDOT; 282 if (*ndp->ni_next == 0) 283 cnp->cn_flags |= ISLASTCN; 284 else cnp->cn_flags &= ~ISLASTCN; 285 286 287 /* 288 * Check for degenerate name (e.g. / or "") 289 * which is a way of talking about a directory, 290 * e.g. like "/." or ".". 291 */ 292 if (cnp->cn_nameptr[0] == '\0') { 293 if (cnp->cn_nameiop != LOOKUP || wantparent) { 294 error = EISDIR; 295 goto bad; 296 } 297 if (dp->v_type != VDIR) { 298 error = ENOTDIR; 299 goto bad; 300 } 301 if (!(cnp->cn_flags & LOCKLEAF)) 302 VOP_UNLOCK(dp); 303 ndp->ni_vp = dp; 304 if (cnp->cn_flags & SAVESTART) 305 panic("lookup: SAVESTART"); 306 return (0); 307 } 308 309 /* 310 * Handle "..": two special cases. 311 * 1. If at root directory (e.g. after chroot) 312 * then ignore it so can't get out. 313 * 2. If this vnode is the root of a mounted 314 * filesystem, then replace it with the 315 * vnode which was mounted on so we take the 316 * .. in the other file system. 317 */ 318 if (cnp->cn_flags & ISDOTDOT) { 319 for (;;) { 320 if (dp == ndp->ni_rootdir) { 321 ndp->ni_dvp = dp; 322 ndp->ni_vp = dp; 323 VREF(dp); 324 goto nextname; 325 } 326 if ((dp->v_flag & VROOT) == 0 || 327 (cnp->cn_flags & NOCROSSMOUNT)) 328 break; 329 tdp = dp; 330 dp = dp->v_mount->mnt_vnodecovered; 331 vput(tdp); 332 VREF(dp); 333 VOP_LOCK(dp); 334 } 335 } 336 337 /* 338 * We now have a segment name to search for, and a directory to search. 339 */ 340 ndp->ni_dvp = dp; 341 if (error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) { 342 #ifdef DIAGNOSTIC 343 if (ndp->ni_vp != NULL) 344 panic("leaf should be empty"); 345 #endif 346 #ifdef NAMEI_DIAGNOSTIC 347 printf("not found\n"); 348 #endif 349 if (error != EJUSTRETURN) 350 goto bad; 351 /* 352 * If creating and at end of pathname, then can consider 353 * allowing file to be created. 354 */ 355 if (rdonly || (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY)) { 356 error = EROFS; 357 goto bad; 358 } 359 /* 360 * We return with ni_vp NULL to indicate that the entry 361 * doesn't currently exist, leaving a pointer to the 362 * (possibly locked) directory inode in ndp->ni_dvp. 363 */ 364 if (cnp->cn_flags & SAVESTART) { 365 ndp->ni_startdir = ndp->ni_dvp; 366 VREF(ndp->ni_startdir); 367 } 368 return (0); 369 } 370 #ifdef NAMEI_DIAGNOSTIC 371 printf("found\n"); 372 #endif 373 374 dp = ndp->ni_vp; 375 /* 376 * Check for symbolic link 377 */ 378 if ((dp->v_type == VLNK) && 379 ((cnp->cn_flags & FOLLOW) || *ndp->ni_next == '/')) { 380 cnp->cn_flags |= ISSYMLINK; 381 return (0); 382 } 383 384 /* 385 * Check to see if the vnode has been mounted on; 386 * if so find the root of the mounted file system. 387 */ 388 while (dp->v_type == VDIR && (mp = dp->v_mountedhere) && 389 (cnp->cn_flags & NOCROSSMOUNT) == 0) { 390 if (mp->mnt_flag & MNT_MLOCK) { 391 mp->mnt_flag |= MNT_MWAIT; 392 sleep((caddr_t)mp, PVFS); 393 continue; 394 } 395 if (error = VFS_ROOT(dp->v_mountedhere, &tdp)) 396 goto bad2; 397 vput(dp); 398 ndp->ni_vp = dp = tdp; 399 } 400 401 nextname: 402 /* 403 * Not a symbolic link. If more pathname, 404 * continue at next component, else return. 405 */ 406 if (*ndp->ni_next == '/') { 407 cnp->cn_nameptr = ndp->ni_next; 408 while (*cnp->cn_nameptr == '/') { 409 cnp->cn_nameptr++; 410 ndp->ni_pathlen--; 411 } 412 vrele(ndp->ni_dvp); 413 goto dirloop; 414 } 415 /* 416 * Check for read-only file systems. 417 */ 418 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) { 419 /* 420 * Disallow directory write attempts on read-only 421 * file systems. 422 */ 423 if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) || 424 (wantparent && 425 (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY))) { 426 error = EROFS; 427 goto bad2; 428 } 429 } 430 if (cnp->cn_flags & SAVESTART) { 431 ndp->ni_startdir = ndp->ni_dvp; 432 VREF(ndp->ni_startdir); 433 } 434 if (!wantparent) 435 vrele(ndp->ni_dvp); 436 if ((cnp->cn_flags & LOCKLEAF) == 0) 437 VOP_UNLOCK(dp); 438 return (0); 439 440 bad2: 441 if ((cnp->cn_flags & LOCKPARENT) && *ndp->ni_next == '\0') 442 VOP_UNLOCK(ndp->ni_dvp); 443 vrele(ndp->ni_dvp); 444 bad: 445 vput(dp); 446 ndp->ni_vp = NULL; 447 return (error); 448 } 449 450 451