static int ufs_open_namei(uufsd_t *ufs, ino_t root, ino_t base, const char *path, int pathlen, ino_t *res_inode) { int retval, namelen; const char *base_name; ino_t dir, inode; retval = ufs_dir_namei(ufs, root, base, path, pathlen, &base_name, &namelen, &dir); if (retval) return retval; if (!namelen) { *res_inode = dir; return 0; } retval = ufs_lookup(ufs, dir, base_name, namelen, &inode); if (retval) { *res_inode = 0; } else { *res_inode = inode; } return retval; }
static int ufs_dir_namei(uufsd_t *ufs, ino_t root, ino_t dir, const char *pathname, int pathlen, const char **name, int *namelen, ino_t *res_ino) { char c; const char *thisname; int len; ino_t inode; int retval; if ((c = *pathname) == '/') { dir = root; pathname++; pathlen--; } while (1) { thisname = pathname; for (len=0; --pathlen >= 0;len++) { c = *(pathname++); if (c == '/') break; } if (pathlen < 0) break; retval = ufs_lookup (ufs, dir, thisname, len, &inode); if (retval) return retval; dir = inode; } *name = thisname; *namelen = len; *res_ino = dir; return 0; }
/* * look-up a file in absolute pathname from the root directory */ ino32_t ufs_lookup_path(const char *path) { char fn[FFS_MAXNAMLEN + 1]; char *p; ino32_t ino = UFS_ROOTINO; do { while (*path == '/') path++; for (p = fn; *path && *path != '/'; ) *p++ = *path++; *p++ = '\0'; ino = ufs_lookup(ino, fn); } while (ino && *path); return ino; }
static int ufs_extattr_lookup(struct vnode *start_dvp, int lockparent, char *dirname, struct vnode **vp, struct thread *td) { struct vop_cachedlookup_args vargs; struct componentname cnp; struct vnode *target_vp; int error; bzero(&cnp, sizeof(cnp)); cnp.cn_nameiop = LOOKUP; cnp.cn_flags = ISLASTCN; if (lockparent == UE_GETDIR_LOCKPARENT) cnp.cn_flags |= LOCKPARENT; cnp.cn_lkflags = LK_EXCLUSIVE; cnp.cn_thread = td; cnp.cn_cred = td->td_ucred; cnp.cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK); cnp.cn_nameptr = cnp.cn_pnbuf; error = copystr(dirname, cnp.cn_pnbuf, MAXPATHLEN, (size_t *) &cnp.cn_namelen); if (error) { if (lockparent == UE_GETDIR_LOCKPARENT_DONT) { VOP_UNLOCK(start_dvp, 0); } uma_zfree(namei_zone, cnp.cn_pnbuf); printf("ufs_extattr_lookup: copystr failed\n"); return (error); } cnp.cn_namelen--; /* trim nul termination */ vargs.a_gen.a_desc = NULL; vargs.a_dvp = start_dvp; vargs.a_vpp = &target_vp; vargs.a_cnp = &cnp; error = ufs_lookup(&vargs); uma_zfree(namei_zone, cnp.cn_pnbuf); if (error) { /* * Error condition, may have to release the lock on the parent * if ufs_lookup() didn't. */ if (lockparent == UE_GETDIR_LOCKPARENT_DONT) VOP_UNLOCK(start_dvp, 0); /* * Check that ufs_lookup() didn't release the lock when we * didn't want it to. */ if (lockparent == UE_GETDIR_LOCKPARENT) ASSERT_VOP_LOCKED(start_dvp, "ufs_extattr_lookup"); return (error); } /* if (target_vp == start_dvp) panic("ufs_extattr_lookup: target_vp == start_dvp"); */ if (target_vp != start_dvp && lockparent == UE_GETDIR_LOCKPARENT_DONT) VOP_UNLOCK(start_dvp, 0); if (lockparent == UE_GETDIR_LOCKPARENT) ASSERT_VOP_LOCKED(start_dvp, "ufs_extattr_lookup"); /* printf("ufs_extattr_lookup: success\n"); */ *vp = target_vp; return (0); }
static int ufs_mkdir(uufsd_t *ufs, ino_t parent, ino_t inum, char *name) { int retval; struct ufs_vnode *parent_vnode = NULL, *vnode = NULL; struct inode *parent_inode, *inode; ino_t ino = inum; ino_t scratch_ino; ufs2_daddr_t blk; char *block = 0; struct fs *fs = &ufs->d_fs; int dirsize = DIRBLKSIZ; int blocksize = fragroundup(fs, dirsize); parent_vnode = vnode_get(ufs, parent); if (!parent_vnode) { return ENOENT; } parent_inode = vnode2inode(parent_vnode); /* * Allocate an inode, if necessary */ if (!ino) { retval = ufs_valloc(parent_vnode, DTTOIF(DT_DIR), &vnode); if (retval) goto cleanup; ino = vnode->inode.i_number; inode = vnode2inode(vnode); } /* * Allocate a data block for the directory */ retval = ufs_block_alloc(ufs, inode, fragroundup(fs, dirsize), &blk); if (retval) goto cleanup; /* * Create a scratch template for the directory */ retval = ufs_new_dir_block(ufs, vnode->inode.i_number, parent_vnode, &block); if (retval) goto cleanup; /* * Get the parent's inode, if necessary if (parent != ino) { parent_vnode = vnode_get(ufs, parent); if (retval) goto cleanup; } else memset(&parent_inode, 0, sizeof(parent_inode)); */ /* * Create the inode structure.... */ inode->i_mode = DT_DIR | (0777); inode->i_uid = inode->i_gid = 0; UFS_DINODE(inode)->di_db[0] = blk; inode->i_nlink = 1; inode->i_size = dirsize; /* * Write out the inode and inode data block */ retval = blkwrite(ufs, fsbtodb(fs, blk), block, blocksize); if (retval == -1) goto cleanup; /* * Link the directory into the filesystem hierarchy */ if (name) { retval = ufs_lookup(ufs, parent, name, strlen(name), &scratch_ino); if (!retval) { retval = EEXIST; name = 0; goto cleanup; } if (retval != ENOENT) goto cleanup; retval = ufs_link(ufs, parent, name, vnode, DTTOIF(DT_DIR)); if (retval) goto cleanup; } /* * Update parent inode's counts */ if (parent != ino) { parent_inode->i_nlink++; } cleanup: if (vnode) vnode_put(vnode, 1); if (parent_vnode) vnode_put(parent_vnode, 1); if (block) ufs_free_mem(&block); return retval; }
static int ufs_extattr_lookup(struct vnode *start_dvp, int lockparent, char *dirname, struct vnode **vp, struct proc *p) { struct vop_lookup_args vargs; struct componentname cnp; struct vnode *target_vp; int error; bzero(&cnp, sizeof(cnp)); cnp.cn_nameiop = LOOKUP; cnp.cn_flags = ISLASTCN; if (lockparent == UE_GETDIR_LOCKPARENT) cnp.cn_flags |= LOCKPARENT; cnp.cn_proc = p; cnp.cn_cred = p->p_ucred; MALLOC(cnp.cn_pnbuf, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); cnp.cn_nameptr = cnp.cn_pnbuf; error = copystr(dirname, cnp.cn_pnbuf, MAXPATHLEN, (size_t *) &cnp.cn_namelen); if (error) { if (lockparent == UE_GETDIR_LOCKPARENT_DONT) { VOP_UNLOCK(start_dvp, 0, p); } FREE(cnp.cn_pnbuf, M_NAMEI); printf("ufs_extattr_lookup: copystr failed\n"); return (error); } cnp.cn_namelen--; /* trim nul termination */ vargs.a_desc = NULL; vargs.a_dvp = start_dvp; vargs.a_vpp = &target_vp; vargs.a_cnp = &cnp; error = ufs_lookup(&vargs); FREE(cnp.cn_pnbuf, M_NAMEI); if (error) { /* * Error condition, may have to release the lock on the parent * if ufs_lookup() didn't. */ if(lockparent == UE_GETDIR_LOCKPARENT_DONT) VOP_UNLOCK(start_dvp, 0, p); #if 0 /* -XXX does OpenBSD ufs_lookup always unlock on error? */ /* * Check that ufs_lookup() didn't release the lock when we * didn't want it to. */ if ((cnp.cn_flags & PDIRUNLOCK) && (lockparent == UE_GETDIR_LOCKPARENT)) panic("ufs_extattr_lookup: lockparent but PDIRUNLOCK"); #endif return (error); } /* if (target_vp == start_dvp) panic("ufs_extattr_lookup: target_vp == start_dvp"); */ #if 0 /* PDIRUNLOCK does not exist on OpenBSD */ if (target_vp != start_dvp && !(cnp.cn_flags & PDIRUNLOCK) && (lockparent == UE_GETDIR_LOCKPARENT_DONT)) panic("ufs_extattr_lookup: !lockparent but !PDIRUNLOCK"); if ((cnp.cn_flags & PDIRUNLOCK) && (lockparent == UE_GETDIR_LOCKPARENT)) panic("ufs_extattr_lookup: lockparent but PDIRUNLOCK"); #endif /* printf("ufs_extattr_lookup: success\n"); */ *vp = target_vp; return (0); }