/* ??? Copyright 2002 Johan Rydberg, jrydberg@rtmk.org. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include "io-vfs.h" #include "proc.h" #include "nova-intern.h" extern struct vnode *rootvp; /* Look up vnode PATH in file system. Return vnode in VPP. */ int lookup (int vla, struct proc *p, char *path, struct vnode **vpp) { char cname[128], *s, *cp; struct vnode *dvp, *vp; int err; /* If we are trying to look up an absolute path, start at the root -- otherwise at the current working directory. */ if (*path == '/') { path++; dvp = rootvp; /* p->p_root ? p->p_root : rootvnode; */ } else dvp = p ? (p->p_cwd ? p->p_cwd : rootvp) : rootvp; /* Loop through all components of PATH, until we find the vnode that we are looking for -- or encounters an error. */ for (cp = path; true;) { if (cp[0] == '\0') { cp = 0; goto cp_might_be_null; } s = strchr (cp, '/'); if (s) { strncpy (cname, cp, (s - cp)); cname [(int) (s - cp)] = '\0'; } else strcpy (cname, cp); cp = s ? s + 1 : NULL; /* If we are trying to access `..' at the root, just continue to the next component -- if none, we return. */ #if 1 if (! strcmp (cname, "..")) { #if 0 if (dvp == rootvnode) continue; #endif #if 0 else if (dvp->v_flags & VROOT) dvp = dvp->v_vfsp->vfs_covered; #endif } #endif /* ??? VOP_ACCESS? */ /* Look up CNAME in the current searching directory. */ err = VOP_LOOKUP (dvp, cname, &vp); /* If the component was not found, check to see if the this is the last component. If so, return success (the caller may have intended to have to create the file). */ if (err == ENOENT && !cp && vla == VLA_CREATE) { *vpp = dvp; return 0; } else if (err) return err; /* If this was the last component (cp == NULL), we now have the vnode in VP. Let us just return it, otherwise continue with the next component. */ cp_might_be_null: if (cp == NULL) { if (vla == VLA_CREATE) { *vpp = dvp; return EEXIST; } /* If we are not trying to create the vnode, we can return now since there's no more components. */ else { *vpp = vp; return 0; } } else /* ??? still more components */ { /* We can only traverse directories. */ if (vp->v_type != VDIR) return ENOTDIR; dvp = vp; } } }