1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)vfs_lookup.c 7.14 (Berkeley) 06/27/89 18 */ 19 20 #include "param.h" 21 #include "time.h" 22 #include "namei.h" 23 #include "vnode.h" 24 #include "mount.h" 25 #include "errno.h" 26 #include "malloc.h" 27 28 #ifdef KTRACE 29 #include "user.h" 30 #include "proc.h" 31 #include "ktrace.h" 32 #endif 33 34 /* 35 * Convert a pathname into a pointer to a locked inode. 36 * This is a very central and rather complicated routine. 37 * 38 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on 39 * whether the name is to be looked up, created, renamed, or deleted. 40 * When CREATE, RENAME, or DELETE is specified, information usable in 41 * creating, renaming, or deleting a directory entry may be calculated. 42 * If flag has LOCKPARENT or'ed into it and the target of the pathname 43 * exists, namei returns both the target and its parent directory locked. 44 * When creating or renaming and LOCKPARENT is specified, the target may not 45 * be ".". When deleting and LOCKPARENT is specified, the target may be ".". 46 * 47 * The FOLLOW flag is set when symbolic links are to be followed 48 * when they occur at the end of the name translation process. 49 * Symbolic links are always followed for all other pathname 50 * components other than the last. 51 * 52 * The segflg defines whether the name is to be copied from user 53 * space or kernel space. 54 * 55 * Overall outline of namei: 56 * 57 * copy in name 58 * get starting directory 59 * dirloop: 60 * copy next component of name to ndp->ni_dent 61 * handle degenerate case where name is null string 62 * if .. and on mounted filesys, find parent 63 * call lookup routine for next component name 64 * directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set 65 * component vnode returned in ni_vp (if it exists), locked. 66 * if symbolic link, massage name in buffer and continue at dirloop 67 * if result inode is mounted on, find mounted on vnode 68 * if more components of name, do next level at dirloop 69 * return the answer in ni_vp as locked vnode; 70 * if LOCKPARENT set, return locked parent in ni_dvp 71 * 72 * NOTE: (LOOKUP | LOCKPARENT) currently returns the parent vnode unlocked. 73 */ 74 namei(ndp) 75 register struct nameidata *ndp; 76 { 77 register char *cp; /* pointer into pathname argument */ 78 register struct vnode *dp = 0; /* the directory we are searching */ 79 register int i; /* Temp counter */ 80 struct vnode *tdp; /* saved dp */ 81 struct mount *mp; /* mount table entry */ 82 int docache; /* == 0 do not cache last component */ 83 int flag; /* LOOKUP, CREATE, RENAME or DELETE */ 84 int wantparent; /* 1 => wantparent or lockparent flag */ 85 int lockparent; /* 1 => lockparent flag */ 86 int error = 0; 87 88 flag = ndp->ni_nameiop & OPFLAG; 89 wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT); 90 lockparent = ndp->ni_nameiop & LOCKPARENT; 91 docache = (ndp->ni_nameiop & NOCACHE) ^ NOCACHE; 92 if (flag == DELETE || wantparent) 93 docache = 0; 94 /* 95 * Get a buffer for the name to be translated, and copy the 96 * name into the buffer. 97 */ 98 MALLOC(ndp->ni_pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK); 99 if (ndp->ni_segflg == UIO_SYSSPACE) 100 error = copystr(ndp->ni_dirp, ndp->ni_pnbuf, MAXPATHLEN, 101 &ndp->ni_pathlen); 102 else 103 error = copyinstr(ndp->ni_dirp, ndp->ni_pnbuf, MAXPATHLEN, 104 &ndp->ni_pathlen); 105 if (error) { 106 free(ndp->ni_pnbuf, M_NAMEI); 107 ndp->ni_vp = NULL; 108 return (error); 109 } 110 ndp->ni_ptr = ndp->ni_pnbuf; 111 ndp->ni_loopcnt = 0; 112 dp = ndp->ni_cdir; 113 VREF(dp); 114 #ifdef KTRACE 115 if (KTRPOINT(u.u_procp, KTR_NAMEI)) 116 ktrnamei(u.u_procp->p_tracep, ndp->ni_pnbuf); 117 #endif 118 119 start: 120 /* 121 * Get starting directory. 122 * Done at start of translation and after symbolic link. 123 */ 124 if (*ndp->ni_ptr == '/') { 125 vrele(dp); 126 while (*ndp->ni_ptr == '/') { 127 ndp->ni_ptr++; 128 ndp->ni_pathlen--; 129 } 130 if ((dp = ndp->ni_rdir) == NULL) 131 dp = rootdir; 132 VREF(dp); 133 } 134 VOP_LOCK(dp); 135 ndp->ni_endoff = 0; 136 137 /* 138 * We come to dirloop to search a new directory. 139 */ 140 dirloop: 141 /* 142 * Copy next component of name to ndp->ni_dent. 143 * XXX kern_exec looks at d_name 144 * ??? The ni_hash value may be useful for vfs_cache 145 * XXX There must be the last component of the filename left 146 * somewhere accessible via. ndp for NFS (and any other stateless file 147 * systems) in case they are doing a CREATE. The "Towards a..." noted 148 * that ni_ptr would be left pointing to the last component, but since 149 * the ni_pnbuf gets free'd, that is not a good idea. 150 */ 151 #ifdef notdef 152 for (cp = ndp->ni_ptr; *cp != 0 && *cp != '/'; cp++) { 153 if ((*cp & 0200) == 0) 154 continue; 155 if ((*cp&0377) == ('/'|0200) || flag != DELETE) { 156 error = EINVAL; 157 goto bad; 158 } 159 } 160 ndp->ni_namelen = cp - ndp->ni_ptr; 161 if (ndp->ni_namelen >= MAXNAMLEN) { 162 error = ENAMETOOLONG; 163 goto bad; 164 } 165 ndp->ni_pathlen -= ndp->ni_namelen; 166 #ifdef NAMEI_DIAGNOSTIC 167 { char c = *cp; 168 *cp = '\0'; 169 printf("{%s}: ", ndp->ni_ptr); 170 *cp = c; } 171 #endif 172 #else fornow 173 ndp->ni_hash = 0; 174 for (cp = ndp->ni_ptr, i = 0; *cp != 0 && *cp != '/'; cp++) { 175 if (i >= MAXNAMLEN) { 176 error = ENAMETOOLONG; 177 goto bad; 178 } 179 if (*cp & 0200) 180 if ((*cp&0377) == ('/'|0200) || flag != DELETE) { 181 error = EINVAL; 182 goto bad; 183 } 184 ndp->ni_dent.d_name[i++] = *cp; 185 ndp->ni_hash += (unsigned char)*cp * i; 186 } 187 ndp->ni_namelen = i; 188 ndp->ni_dent.d_namlen = i; 189 ndp->ni_dent.d_name[i] = '\0'; 190 ndp->ni_pathlen -= i; 191 #ifdef NAMEI_DIAGNOSTIC 192 printf("{%s}: ", ndp->ni_dent.d_name); 193 #endif 194 #endif fornow 195 ndp->ni_next = cp; 196 ndp->ni_makeentry = 1; 197 if (*cp == '\0' && docache == 0) 198 ndp->ni_makeentry = 0; 199 ndp->ni_isdotdot = (ndp->ni_namelen == 2 && 200 ndp->ni_dent.d_name[1] == '.' && ndp->ni_dent.d_name[0] == '.'); 201 202 /* 203 * Check for degenerate name (e.g. / or "") 204 * which is a way of talking about a directory, 205 * e.g. like "/." or ".". 206 */ 207 if (ndp->ni_ptr[0] == '\0') { 208 if (flag != LOOKUP || wantparent) { 209 error = EISDIR; 210 goto bad; 211 } 212 free(ndp->ni_pnbuf, M_NAMEI); 213 if (!(ndp->ni_nameiop & LOCKLEAF)) 214 VOP_UNLOCK(dp); 215 ndp->ni_vp = dp; 216 return (0); 217 } 218 219 /* 220 * Handle "..": two special cases. 221 * 1. If at root directory (e.g. after chroot) 222 * then ignore it so can't get out. 223 * 2. If this vnode is the root of a mounted 224 * file system, then replace it with the 225 * vnode which was mounted on so we take the 226 * .. in the other file system. 227 */ 228 if (ndp->ni_isdotdot) { 229 for (;;) { 230 if (dp == ndp->ni_rdir || dp == rootdir) { 231 ndp->ni_dvp = dp; 232 VREF(dp); 233 goto nextname; 234 } 235 if ((dp->v_flag & VROOT) == 0) 236 break; 237 tdp = dp; 238 dp = dp->v_mount->m_vnodecovered; 239 vput(tdp); 240 VOP_LOCK(dp); 241 VREF(dp); 242 } 243 } 244 245 /* 246 * We now have a segment name to search for, and a directory to search. 247 */ 248 if (error = VOP_LOOKUP(dp, ndp)) { 249 if (ndp->ni_vp != NULL) 250 panic("leaf should be empty"); 251 #ifdef NAMEI_DIAGNOSTIC 252 printf("not found\n"); 253 #endif 254 /* 255 * If creating and at end of pathname, then can consider 256 * allowing file to be created. 257 */ 258 if (ndp->ni_dvp->v_mount->m_flag & M_RDONLY) 259 error = EROFS; 260 if (flag == LOOKUP || flag == DELETE || 261 error != ENOENT || *cp != 0) 262 goto bad; 263 /* 264 * We return with ni_vp NULL to indicate that the entry 265 * doesn't currently exist, leaving a pointer to the 266 * (possibly locked) directory inode in ndp->ni_dvp. 267 */ 268 FREE(ndp->ni_pnbuf, M_NAMEI); 269 return (0); /* should this be ENOENT? */ 270 } 271 #ifdef NAMEI_DIAGNOSTIC 272 printf("found\n"); 273 #endif 274 275 /* 276 * Check for symbolic link 277 */ 278 dp = ndp->ni_vp; 279 if ((dp->v_type == VLNK) && 280 ((ndp->ni_nameiop & FOLLOW) || *ndp->ni_next == '/')) { 281 struct iovec aiov; 282 struct uio auio; 283 int linklen; 284 285 if (++ndp->ni_loopcnt > MAXSYMLINKS) { 286 error = ELOOP; 287 goto bad2; 288 } 289 if (ndp->ni_pathlen > 1) 290 MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 291 else 292 cp = ndp->ni_pnbuf; 293 aiov.iov_base = cp; 294 aiov.iov_len = MAXPATHLEN; 295 auio.uio_iov = &aiov; 296 auio.uio_iovcnt = 1; 297 auio.uio_offset = 0; 298 auio.uio_rw = UIO_READ; 299 auio.uio_segflg = UIO_SYSSPACE; 300 auio.uio_resid = MAXPATHLEN; 301 if (error = VOP_READLINK(dp, &auio, ndp->ni_cred)) { 302 if (ndp->ni_pathlen > 1) 303 free(cp, M_NAMEI); 304 goto bad2; 305 } 306 linklen = MAXPATHLEN - auio.uio_resid; 307 if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { 308 if (ndp->ni_pathlen > 1) 309 free(cp, M_NAMEI); 310 error = ENAMETOOLONG; 311 goto bad2; 312 } 313 if (ndp->ni_pathlen > 1) { 314 bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen); 315 FREE(ndp->ni_pnbuf, M_NAMEI); 316 ndp->ni_pnbuf = cp; 317 } else 318 ndp->ni_pnbuf[linklen] = '\0'; 319 ndp->ni_ptr = cp; 320 ndp->ni_pathlen += linklen; 321 vput(dp); 322 dp = ndp->ni_dvp; 323 if (lockparent && *ndp->ni_next == '\0') 324 VOP_UNLOCK(dp); 325 goto start; 326 } 327 328 /* 329 * Check to see if the vnode has been mounted on; 330 * if so find the root of the mounted file system. 331 */ 332 mntloop: 333 while (dp->v_type == VDIR && (mp = dp->v_mountedhere)) { 334 while(mp->m_flag & M_MLOCK) { 335 mp->m_flag |= M_MWAIT; 336 sleep((caddr_t)mp, PVFS); 337 goto mntloop; 338 } 339 error = VFS_ROOT(dp->v_mountedhere, &tdp); 340 if (error) 341 goto bad2; 342 vput(dp); 343 ndp->ni_vp = dp = tdp; 344 } 345 346 nextname: 347 /* 348 * Not a symbolic link. If more pathname, 349 * continue at next component, else return. 350 */ 351 ndp->ni_ptr = ndp->ni_next; 352 if (*ndp->ni_ptr == '/') { 353 while (*ndp->ni_ptr == '/') { 354 ndp->ni_ptr++; 355 ndp->ni_pathlen--; 356 } 357 vrele(ndp->ni_dvp); 358 goto dirloop; 359 } 360 /* 361 * Check for read-only file systems and executing texts 362 */ 363 if (flag != LOOKUP) { 364 /* 365 * Disallow write attempts on read-only file systems; 366 * unless the file is a socket or a block or character 367 * device resident on the file system. 368 */ 369 if ((dp->v_mount->m_flag & M_RDONLY) && 370 dp->v_type != VCHR && 371 dp->v_type != VBLK && 372 dp->v_type != VSOCK) { 373 error = EROFS; 374 goto bad2; 375 } 376 /* 377 * If there's shared text associated with 378 * the inode, try to free it up once. If 379 * we fail, we can't allow writing. 380 */ 381 if (dp->v_flag & VTEXT) 382 xrele(dp); 383 if (dp->v_flag & VTEXT) { 384 error = ETXTBSY; 385 goto bad2; 386 } 387 if (wantparent && flag != CREATE && 388 (ndp->ni_dvp->v_mount->m_flag & M_RDONLY)) { 389 error = EROFS; 390 goto bad2; 391 } 392 } 393 if (!wantparent) 394 vrele(ndp->ni_dvp); 395 if ((ndp->ni_nameiop & LOCKLEAF) == 0) 396 VOP_UNLOCK(dp); 397 FREE(ndp->ni_pnbuf, M_NAMEI); 398 return (0); 399 400 bad2: 401 if (lockparent && *ndp->ni_next == '\0') 402 VOP_UNLOCK(ndp->ni_dvp); 403 vrele(ndp->ni_dvp); 404 bad: 405 vput(dp); 406 ndp->ni_vp = NULL; 407 FREE(ndp->ni_pnbuf, M_NAMEI); 408 return (error); 409 } 410