1 /* 2 * namei.c 3 * 4 * Copyright (c) 1999 Al Smith 5 * 6 * Portions derived from work (c) 1995,1996 Christian Vogelgsang. 7 */ 8 9 #include <linux/buffer_head.h> 10 #include <linux/string.h> 11 #include <linux/efs_fs.h> 12 #include <linux/smp_lock.h> 13 14 static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) { 15 struct buffer_head *bh; 16 17 int slot, namelen; 18 char *nameptr; 19 struct efs_dir *dirblock; 20 struct efs_dentry *dirslot; 21 efs_ino_t inodenum; 22 efs_block_t block; 23 24 if (inode->i_size & (EFS_DIRBSIZE-1)) 25 printk(KERN_WARNING "EFS: WARNING: find_entry(): directory size not a multiple of EFS_DIRBSIZE\n"); 26 27 for(block = 0; block < inode->i_blocks; block++) { 28 29 bh = sb_bread(inode->i_sb, efs_bmap(inode, block)); 30 if (!bh) { 31 printk(KERN_ERR "EFS: find_entry(): failed to read dir block %d\n", block); 32 return 0; 33 } 34 35 dirblock = (struct efs_dir *) bh->b_data; 36 37 if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) { 38 printk(KERN_ERR "EFS: find_entry(): invalid directory block\n"); 39 brelse(bh); 40 return(0); 41 } 42 43 for(slot = 0; slot < dirblock->slots; slot++) { 44 dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot)); 45 46 namelen = dirslot->namelen; 47 nameptr = dirslot->name; 48 49 if ((namelen == len) && (!memcmp(name, nameptr, len))) { 50 inodenum = be32_to_cpu(dirslot->inode); 51 brelse(bh); 52 return(inodenum); 53 } 54 } 55 brelse(bh); 56 } 57 return(0); 58 } 59 60 struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { 61 efs_ino_t inodenum; 62 struct inode * inode = NULL; 63 64 lock_kernel(); 65 inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len); 66 if (inodenum) { 67 if (!(inode = iget(dir->i_sb, inodenum))) { 68 unlock_kernel(); 69 return ERR_PTR(-EACCES); 70 } 71 } 72 unlock_kernel(); 73 74 d_add(dentry, inode); 75 return NULL; 76 } 77 78 struct dentry *efs_get_parent(struct dentry *child) 79 { 80 struct dentry *parent; 81 struct inode *inode; 82 efs_ino_t ino; 83 int error; 84 85 lock_kernel(); 86 87 error = -ENOENT; 88 ino = efs_find_entry(child->d_inode, "..", 2); 89 if (!ino) 90 goto fail; 91 92 error = -EACCES; 93 inode = iget(child->d_inode->i_sb, ino); 94 if (!inode) 95 goto fail; 96 97 error = -ENOMEM; 98 parent = d_alloc_anon(inode); 99 if (!parent) 100 goto fail_iput; 101 102 unlock_kernel(); 103 return parent; 104 105 fail_iput: 106 iput(inode); 107 fail: 108 unlock_kernel(); 109 return ERR_PTR(error); 110 } 111