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