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.9 (Berkeley) 05/09/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 error = 0; 86 87 flag = ndp->ni_nameiop & OPFLAG; 88 wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT); 89 docache = (ndp->ni_nameiop & NOCACHE) ^ NOCACHE; 90 if (flag == DELETE || wantparent) 91 docache = 0; 92 /* 93 * Get a buffer for the name to be translated, and copy the 94 * name into the buffer. 95 */ 96 MALLOC(ndp->ni_pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK); 97 if (ndp->ni_segflg == UIO_SYSSPACE) 98 error = copystr(ndp->ni_dirp, ndp->ni_pnbuf, MAXPATHLEN, 99 &ndp->ni_pathlen); 100 else 101 error = copyinstr(ndp->ni_dirp, ndp->ni_pnbuf, MAXPATHLEN, 102 &ndp->ni_pathlen); 103 if (error) { 104 free(ndp->ni_pnbuf, M_NAMEI); 105 return (error); 106 } 107 ndp->ni_ptr = ndp->ni_pnbuf; 108 ndp->ni_loopcnt = 0; 109 dp = ndp->ni_cdir; 110 dp->v_count++; 111 #ifdef KTRACE 112 if (KTRPOINT(u.u_procp, KTR_NAMEI)) 113 ktrnamei(u.u_procp->p_tracep, ndp->ni_pnbuf); 114 #endif 115 116 start: 117 /* 118 * Get starting directory. 119 * Done at start of translation and after symbolic link. 120 */ 121 if (*ndp->ni_ptr == '/') { 122 vrele(dp); 123 while (*ndp->ni_ptr == '/') { 124 ndp->ni_ptr++; 125 ndp->ni_pathlen--; 126 } 127 if ((dp = ndp->ni_rdir) == NULL) 128 dp = rootdir; 129 dp->v_count++; 130 } 131 VOP_LOCK(dp); 132 ndp->ni_endoff = 0; 133 134 /* 135 * We come to dirloop to search a new directory. 136 */ 137 dirloop: 138 /* 139 * Copy next component of name to ndp->ni_dent. 140 * XXX kern_exec looks at d_name 141 * ??? The ni_hash value may be useful for vfs_cache 142 * XXX There must be the last component of the filename left 143 * somewhere accessible via. ndp for NFS (and any other stateless file 144 * systems) in case they are doing a CREATE. The "Towards a..." noted 145 * that ni_ptr would be left pointing to the last component, but since 146 * the ni_pnbuf gets free'd, that is not a good idea. 147 */ 148 #ifdef notdef 149 for (cp = ndp->ni_ptr; *cp != 0 && *cp != '/'; cp++) { 150 if ((*cp & 0200) == 0) 151 continue; 152 if ((*cp&0377) == ('/'|0200) || flag != DELETE) { 153 error = EINVAL; 154 goto bad; 155 } 156 } 157 ndp->ni_namelen = cp - ndp->ni_ptr; 158 if (ndp->ni_namelen >= MAXNAMLEN) { 159 error = ENAMETOOLONG; 160 goto bad; 161 } 162 ndp->ni_pathlen -= ndp->ni_namelen; 163 #ifdef NAMEI_DIAGNOSTIC 164 { char c = *cp; 165 *cp = '\0'; 166 printf("{%s}: ", ndp->ni_ptr); 167 *cp = c; } 168 #endif 169 #else fornow 170 ndp->ni_hash = 0; 171 for (cp = ndp->ni_ptr, i = 0; *cp != 0 && *cp != '/'; cp++) { 172 if (i >= MAXNAMLEN) { 173 error = ENAMETOOLONG; 174 goto bad; 175 } 176 if (*cp & 0200) 177 if ((*cp&0377) == ('/'|0200) || flag != DELETE) { 178 error = EINVAL; 179 goto bad; 180 } 181 ndp->ni_dent.d_name[i++] = *cp; 182 ndp->ni_hash += (unsigned char)*cp * i; 183 } 184 ndp->ni_namelen = i; 185 ndp->ni_dent.d_namlen = i; 186 ndp->ni_dent.d_name[i] = '\0'; 187 ndp->ni_pathlen -= i; 188 #ifdef NAMEI_DIAGNOSTIC 189 printf("{%s}: ", ndp->ni_dent.d_name); 190 #endif 191 #endif fornow 192 ndp->ni_next = cp; 193 ndp->ni_makeentry = 1; 194 if (*cp == '\0' && docache == 0) 195 ndp->ni_makeentry = 0; 196 ndp->ni_isdotdot = (ndp->ni_namelen == 2 && 197 ndp->ni_dent.d_name[1] == '.' && ndp->ni_dent.d_name[0] == '.'); 198 199 /* 200 * Check for degenerate name (e.g. / or "") 201 * which is a way of talking about a directory, 202 * e.g. like "/." or ".". 203 */ 204 if (ndp->ni_ptr[0] == '\0') { 205 if (flag != LOOKUP || wantparent) { 206 error = EISDIR; 207 goto bad; 208 } 209 free(ndp->ni_pnbuf, M_NAMEI); 210 if (!(ndp->ni_nameiop & LOCKLEAF)) 211 VOP_UNLOCK(dp); 212 ndp->ni_vp = dp; 213 return (0); 214 } 215 216 /* 217 * Handle "..": two special cases. 218 * 1. If at root directory (e.g. after chroot) 219 * then ignore it so can't get out. 220 * 2. If this vnode is the root of a mounted 221 * file system, then replace it with the 222 * vnode which was mounted on so we take the 223 * .. in the other file system. 224 */ 225 if (ndp->ni_isdotdot) { 226 for (;;) { 227 if (dp == ndp->ni_rdir || dp == rootdir) { 228 ndp->ni_dvp = dp; 229 dp->v_count++; 230 goto nextname; 231 } 232 if ((dp->v_flag & VROOT) == 0) 233 break; 234 tdp = dp; 235 dp = dp->v_mount->m_vnodecovered; 236 vput(tdp); 237 VOP_LOCK(dp); 238 dp->v_count++; 239 } 240 } 241 242 /* 243 * We now have a segment name to search for, and a directory to search. 244 */ 245 if (error = VOP_LOOKUP(dp, ndp)) { 246 if (ndp->ni_vp != NULL) 247 panic("leaf should be empty"); 248 #ifdef NAMEI_DIAGNOSTIC 249 printf("not found\n"); 250 #endif 251 /* 252 * If creating and at end of pathname, then can consider 253 * allowing file to be created. 254 */ 255 if (ndp->ni_dvp->v_mount->m_flag & M_RDONLY) 256 error = EROFS; 257 if (flag == LOOKUP || flag == DELETE || 258 error != ENOENT || *cp != 0) 259 goto bad; 260 /* 261 * We return with ni_vp NULL to indicate that the entry 262 * doesn't currently exist, leaving a pointer to the 263 * (possibly locked) directory inode in ndp->ni_dvp. 264 */ 265 FREE(ndp->ni_pnbuf, M_NAMEI); 266 return (0); /* should this be ENOENT? */ 267 } 268 #ifdef NAMEI_DIAGNOSTIC 269 printf("found\n"); 270 #endif 271 272 /* 273 * Check for symbolic link 274 */ 275 dp = ndp->ni_vp; 276 if ((dp->v_type == VLNK) && 277 ((ndp->ni_nameiop & FOLLOW) || *ndp->ni_next == '/')) { 278 struct iovec aiov; 279 struct uio auio; 280 int linklen; 281 282 if (++ndp->ni_loopcnt > MAXSYMLINKS) { 283 error = ELOOP; 284 goto bad2; 285 } 286 if (ndp->ni_pathlen == 1) 287 MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 288 else 289 cp = ndp->ni_pnbuf; 290 aiov.iov_base = cp; 291 aiov.iov_len = MAXPATHLEN; 292 auio.uio_iov = &aiov; 293 auio.uio_iovcnt = 1; 294 auio.uio_offset = 0; 295 auio.uio_rw = UIO_READ; 296 auio.uio_segflg = UIO_SYSSPACE; 297 auio.uio_resid = MAXPATHLEN; 298 if (error = VOP_READLINK(dp, &auio, ndp->ni_cred)) { 299 if (ndp->ni_pathlen == 1) 300 free(cp, M_NAMEI); 301 goto bad2; 302 } 303 linklen = MAXPATHLEN - auio.uio_resid; 304 if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { 305 if (ndp->ni_pathlen == 1) 306 free(cp, M_NAMEI); 307 error = ENAMETOOLONG; 308 goto bad2; 309 } 310 if (ndp->ni_pathlen == 1) { 311 bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen); 312 FREE(ndp->ni_pnbuf, M_NAMEI); 313 ndp->ni_pnbuf = cp; 314 } else 315 ndp->ni_pnbuf[linklen] = '\0'; 316 ndp->ni_ptr = cp; 317 ndp->ni_pathlen += linklen; 318 vput(dp); 319 dp = ndp->ni_dvp; 320 goto start; 321 } 322 323 /* 324 * Check to see if the vnode has been mounted on; 325 * if so find the root of the mounted file system. 326 */ 327 mntloop: 328 while (dp->v_type == VDIR && (mp = dp->v_mountedhere)) { 329 while(mp->m_flag & M_MLOCK) { 330 mp->m_flag |= M_MWAIT; 331 sleep((caddr_t)mp, PVFS); 332 goto mntloop; 333 } 334 error = VFS_ROOT(dp->v_mountedhere, &tdp); 335 if (error) 336 goto bad2; 337 vput(dp); 338 ndp->ni_vp = dp = tdp; 339 } 340 341 nextname: 342 /* 343 * Not a symbolic link. If more pathname, 344 * continue at next component, else return. 345 */ 346 ndp->ni_ptr = ndp->ni_next; 347 if (*ndp->ni_ptr == '/') { 348 while (*ndp->ni_ptr == '/') { 349 ndp->ni_ptr++; 350 ndp->ni_pathlen--; 351 } 352 vrele(ndp->ni_dvp); 353 goto dirloop; 354 } 355 /* 356 * Check for read-only file systems and executing texts 357 */ 358 if (flag != LOOKUP && (error = vn_access(dp, VWRITE, ndp->ni_cred))) 359 goto bad2; 360 if (!wantparent) 361 vrele(ndp->ni_dvp); 362 if ((ndp->ni_nameiop & LOCKLEAF) == 0) 363 VOP_UNLOCK(dp); 364 FREE(ndp->ni_pnbuf, M_NAMEI); 365 return (0); 366 367 bad2: 368 vrele(ndp->ni_dvp); 369 bad: 370 vput(dp); 371 ndp->ni_vp = NULL; 372 FREE(ndp->ni_pnbuf, M_NAMEI); 373 return (error); 374 } 375