This source file includes following definitions.
- namecompare
- affs_match
- affs_toupper
- affs_hash_name
- affs_find_entry
- affs_lookup
1
2
3
4
5
6
7
8
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,
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
33
34
35
36
37
38 static int affs_match(int len,const char * name, char * compare, int dlen)
39 {
40 if (!compare) return 0;
41
42
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
54
55 static int affs_toupper (int ch)
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)
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;
70 }
71
72 static struct buffer_head *affs_find_entry(struct inode *dir,
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,
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
160
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
181
182 if (ino_back) (*result)->u.affs_i.i_backlink = ino_back;
183
184 iput(dir);
185 return 0;
186 #endif
187 }