root/fs/affs/namei.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. namecompare
  2. affs_match
  3. affs_toupper
  4. affs_hash_name
  5. affs_find_entry
  6. affs_lookup

   1 /*
   2  *  linux/fs/affs/namei.c
   3  *
   4  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
   5  *
   6  *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
   7  *
   8  *  (C) 1991  Linus Torvalds - minix filesystem
   9  */
  10 
  11 #include <linux/sched.h>
  12 #include <linux/affs_fs.h>
  13 #include <linux/kernel.h>
  14 #include <linux/string.h>
  15 #include <linux/stat.h>
  16 #include <linux/fcntl.h>
  17 #include <asm/segment.h>
  18 
  19 #include <linux/errno.h>
  20 
  21 
  22 static inline int namecompare(int len, int maxlen,
     /* [previous][next][first][last][top][bottom][index][help] */
  23         const char * name, const char * buffer)
  24 {
  25         if (len >= maxlen || !buffer[len]) {
  26                 return strncmp (name, buffer, len) == 0;
  27         }
  28         return 0;
  29 }
  30 
  31 /*
  32  * ok, we cannot use strncmp, as the name is not in our data space.
  33  * Thus we'll have to use affs_match. No big problem. Match also makes
  34  * some sanity tests.
  35  *
  36  * NOTE! unlike strncmp, affs_match returns 1 for success, 0 for failure.
  37  */
  38 static int affs_match(int len,const char * name, char * compare, int dlen)
     /* [previous][next][first][last][top][bottom][index][help] */
  39 {
  40         if (!compare) return 0;
  41 
  42         /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
  43         if (!len && dlen == 1 && compare[0] == '.')
  44                 return 1;
  45         
  46 #if 0
  47         if (len <= 2) printk("Match: %d %d %s %d %d \n",len,dlen,compare,de->name[0], dlen);
  48 #endif
  49         
  50         return namecompare(len,dlen,name,compare);
  51 }
  52 
  53 /* Avoid pulling in ctype stuff. */
  54 
  55 static int affs_toupper (int ch)
     /* [previous][next][first][last][top][bottom][index][help] */
  56 {
  57         if (ch >= 'a' && ch <= 'z')
  58                 ch -= ('a' - 'A');
  59         return ch;
  60 }
  61 
  62 static int affs_hash_name (const char *name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
  63 {
  64         int i, x;
  65 
  66         x = len;
  67         for (i = 0; i < len; i++)
  68                 x = (x * 13 + affs_toupper (name[i])) & 0x7ff;
  69         return x % 72;  /* FIXME: Assumes 512 byte blocks. */
  70 }
  71 
  72 static struct buffer_head *affs_find_entry(struct inode *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
  73         const char *name, int namelen, int *ino)
  74 {
  75         struct buffer_head *bh;
  76         void *dir_data;
  77         int key;
  78 
  79         *ino = 0;
  80 
  81         bh = affs_pread (dir, dir->i_ino, &dir_data);
  82         if (!bh)
  83                 return NULL;
  84 
  85         if (affs_match (namelen, name, ".", 1)) {
  86                 *ino = dir->i_ino;
  87                 return bh;
  88         }
  89         if (affs_match (namelen, name, "..", 2)) {
  90                 *ino = affs_parent_ino (dir);
  91                 return bh;
  92         }
  93         key = affs_get_key_entry (AFFS_I2BSIZE (dir), dir_data,
  94                                   affs_hash_name (name, namelen));
  95 
  96         for (;;) {
  97                 char *cname;
  98                 int cnamelen;
  99 
 100                 brelse (bh);
 101                 if (key <= 0)
 102                         return NULL;
 103                 bh = affs_pread (dir, key, &dir_data);
 104                 if (!bh)
 105                         return NULL;
 106                 cnamelen = affs_get_file_name (AFFS_I2BSIZE (dir),
 107                                                dir_data, &cname);
 108                 if (affs_match (namelen, name, cname, cnamelen))
 109                         break;
 110                 key = affs_get_fh_hash_link (AFFS_I2BSIZE (dir), dir_data);
 111         }
 112                 
 113         *ino = key;
 114 
 115         return bh;
 116 }
 117 
 118 int affs_lookup(struct inode * dir,const char * name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 119         struct inode ** result)
 120 {
 121         int ino;
 122         struct buffer_head *bh;
 123 
 124         *result = NULL;
 125         if (!dir)
 126                 return -ENOENT;
 127 
 128 #ifdef DEBUG
 129         printk ("lookup: %d %d\n", dir->i_ino, len);
 130 #endif
 131 
 132         if (!S_ISDIR(dir->i_mode)) {
 133                 iput(dir);
 134                 return -ENOENT;
 135         }
 136         if (!(bh = affs_find_entry(dir, name, len, &ino))) {
 137           iput(dir);
 138           return -ENOENT;
 139         }
 140         brelse(bh);
 141         if (!(*result = iget(dir->i_sb, ino))) {
 142                 iput(dir);
 143                 return -EACCES;
 144         }
 145         iput (dir);
 146         return 0;
 147 
 148 #if 0
 149         ino = 0;
 150         while(cache.lock);
 151         cache.lock = 1;
 152         if (dir->i_dev == cache.dev && 
 153             dir->i_ino == cache.dir &&
 154             len == cache.dlen && 
 155             affs_match(len, name, cache.filename, cache.dlen))
 156           {
 157             ino = cache.ino;
 158             ino_back = dir->i_ino;
 159             /* These two cases are special, but since they are at the start
 160                of the directory, we can just as easily search there */
 161             if (cache.dlen == 1 && cache.filename[0] == '.') ino = 0;
 162             if (cache.dlen == 2 && cache.filename[0] == '.' && 
 163                 cache.filename[1] == '.') ino = 0;
 164           };
 165         cache.lock = 0;
 166 
 167         if (!ino) {
 168           if (!(bh = affs_find_entry(dir,name,len, &ino, &ino_back))) {
 169             iput(dir);
 170             return -ENOENT;
 171           }
 172           brelse(bh);
 173         };
 174 
 175         if (!(*result = iget(dir->i_sb,ino))) {
 176                 iput(dir);
 177                 return -EACCES;
 178         }
 179 
 180         /* We need this backlink for the .. entry */
 181         
 182         if (ino_back) (*result)->u.affs_i.i_backlink = ino_back; 
 183         
 184         iput(dir);
 185         return 0;
 186 #endif
 187 }

/* [previous][next][first][last][top][bottom][index][help] */