linux-bk/fs/efs/namei.c
<<
>>
Prefs
   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
  14static 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
  60struct 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
  78struct 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
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.