This source file includes following definitions.
- isofs_match
- isofs_find_entry
- isofs_lookup
1
2
3
4
5
6
7
8
9 #include <linux/sched.h>
10 #include <linux/iso_fs.h>
11 #include <linux/kernel.h>
12 #include <linux/string.h>
13 #include <linux/stat.h>
14 #include <linux/fcntl.h>
15 #include <asm/segment.h>
16
17 #include <linux/errno.h>
18
19
20
21
22
23
24
25
26 static int isofs_match(int len,const char * name, char * compare, int dlen)
27 {
28 register int same __asm__("ax");
29
30 if (!compare) return 0;
31
32 if (!len && (compare[0]==0) && (dlen==1))
33 return 1;
34
35 if (compare[0]==0 && dlen==1 && len == 1)
36 compare = ".";
37 if (compare[0]==1 && dlen==1 && len == 2) {
38 compare = "..";
39 dlen = 2;
40 };
41 #if 0
42 if (len <= 2) printk("Match: %d %d %s %d %d \n",len,dlen,compare,de->name[0], dlen);
43 #endif
44
45 if (dlen != len)
46 return 0;
47 __asm__("cld\n\t"
48 "repe ; cmpsb\n\t"
49 "setz %%al"
50 :"=a" (same)
51 :"0" (0),"S" ((long) name),"D" ((long) compare),"c" (len)
52 :"cx","di","si");
53 return same;
54 }
55
56
57
58
59
60
61
62
63
64 static struct buffer_head * isofs_find_entry(struct inode * dir,
65 const char * name, int namelen, int * ino, int * ino_back)
66 {
67 unsigned int block,i, f_pos, offset, inode_number;
68 struct buffer_head * bh;
69 char * cpnt = 0;
70 unsigned int old_offset;
71 unsigned int backlink;
72 int dlen, rrflag, match;
73 char * dpnt;
74 struct iso_directory_record * de;
75 char c;
76
77 *ino = 0;
78 if (!dir) return NULL;
79
80 if (!(block = dir->u.isofs_i.i_first_extent)) return NULL;
81
82 f_pos = 0;
83
84 offset = f_pos & (ISOFS_BUFFER_SIZE - 1);
85 block = isofs_bmap(dir,f_pos >> ISOFS_BUFFER_BITS);
86 if (!block || !(bh = bread(dir->i_dev,block,ISOFS_BUFFER_SIZE))) return NULL;
87
88 while (f_pos < dir->i_size) {
89 de = (struct iso_directory_record *) (offset + bh->b_data);
90 backlink = dir->i_ino;
91 inode_number = (block << ISOFS_BUFFER_BITS)+(offset & (ISOFS_BUFFER_SIZE - 1));
92
93
94
95
96 if (*((unsigned char*) de) == 0) {
97 brelse(bh);
98 offset = 0;
99 f_pos =(f_pos & ~(ISOFS_BLOCK_SIZE - 1))+ISOFS_BLOCK_SIZE;
100 block = isofs_bmap(dir,(f_pos)>>ISOFS_BUFFER_BITS);
101 if (!block || !(bh = bread(dir->i_dev,block,ISOFS_BUFFER_SIZE)))
102 return 0;
103 continue;
104 };
105
106 old_offset = offset;
107 offset += *((unsigned char*) de);
108 f_pos += *((unsigned char*) de);
109
110
111
112
113 if (offset >= ISOFS_BUFFER_SIZE) {
114 cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL);
115 memcpy(cpnt, bh->b_data, ISOFS_BUFFER_SIZE);
116 de = (struct iso_directory_record *) (old_offset + cpnt);
117 brelse(bh);
118 offset = f_pos & (ISOFS_BUFFER_SIZE - 1);
119 block = isofs_bmap(dir,f_pos>>ISOFS_BUFFER_BITS);
120 if (!block || !(bh = bread(dir->i_dev,block,ISOFS_BUFFER_SIZE)))
121 return 0;
122 memcpy(cpnt+ISOFS_BUFFER_SIZE, bh->b_data, ISOFS_BUFFER_SIZE);
123 }
124
125
126
127 if (de->name[0]==0 && de->name_len[0]==1) {
128 inode_number = dir->i_ino;
129 backlink = 0;
130 }
131
132
133
134 if (de->name[0]==1 && de->name_len[0]==1) {
135 #if 0
136 printk("Doing .. (%d %d)",dir->i_sb->s_firstdatazone << ISOFS_BUFFER_BITS, dir->i_ino);
137 #endif
138 if((dir->i_sb->u.isofs_sb.s_firstdatazone << ISOFS_BUFFER_BITS) != dir->i_ino)
139 inode_number = dir->u.isofs_i.i_backlink;
140 else
141 inode_number = dir->i_ino;
142 backlink = 0;
143 }
144
145 dlen = de->name_len[0];
146 dpnt = de->name;
147
148 rrflag = get_rock_ridge_filename(de, &dpnt, &dlen, dir);
149 if (rrflag) {
150 if (rrflag == -1) goto out;
151 } else {
152 if(dir->i_sb->u.isofs_sb.s_mapping == 'n') {
153 for (i = 0; i < dlen; i++) {
154 c = dpnt[i];
155 if (c >= 'A' && c <= 'Z') c |= 0x20;
156 if (c == ';' && i == dlen-2 && dpnt[i+1] == '1') {
157 dlen -= 2;
158 break;
159 };
160 if (c == ';') c = '.';
161 de->name[i] = c;
162 };
163
164 if(dpnt[dlen-1] == '.' && namelen == dlen-1)
165 dlen--;
166 };
167 };
168 match = isofs_match(namelen,name,dpnt, dlen);
169 if (cpnt) { kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS); cpnt = 0;};
170
171 if(rrflag) kfree(dpnt);
172 if (match) {
173 if(inode_number == -1) {
174 inode_number =
175 isofs_lookup_grandparent(dir,
176 find_rock_ridge_relocation(de,dir));
177 if(inode_number == -1){
178 printk("Backlink not properly set.\n");
179 goto out;
180 };
181 };
182 *ino = inode_number;
183 *ino_back = backlink;
184 return bh;
185 }
186 }
187 out:
188 if (cpnt) kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
189 brelse(bh);
190 return NULL;
191 }
192
193 int isofs_lookup(struct inode * dir,const char * name, int len,
194 struct inode ** result)
195 {
196 int ino, ino_back;
197 struct buffer_head * bh;
198
199 #ifdef DEBUG
200 printk("lookup: %x %d\n",dir->i_ino, len);
201 #endif
202 *result = NULL;
203 if (!dir)
204 return -ENOENT;
205
206 if (!S_ISDIR(dir->i_mode)) {
207 iput(dir);
208 return -ENOENT;
209 }
210
211 ino = 0;
212 while(cache.lock);
213 cache.lock = 1;
214 if (dir->i_dev == cache.dev &&
215 dir->i_ino == cache.dir &&
216 len == cache.dlen &&
217 isofs_match(len, name, cache.filename, cache.dlen))
218 {
219 ino = cache.ino;
220 ino_back = dir->i_ino;
221
222
223 if (cache.dlen == 1 && cache.filename[0] == '.') ino = 0;
224 if (cache.dlen == 2 && cache.filename[0] == '.' &&
225 cache.filename[1] == '.') ino = 0;
226 };
227 cache.lock = 0;
228
229 if (!ino) {
230 if (!(bh = isofs_find_entry(dir,name,len, &ino, &ino_back))) {
231 iput(dir);
232 return -ENOENT;
233 }
234 brelse(bh);
235 };
236
237 if (!(*result = iget(dir->i_sb,ino))) {
238 iput(dir);
239 return -EACCES;
240 }
241
242
243
244 if (ino_back && !(*result)->i_pipe)
245 (*result)->u.isofs_i.i_backlink = ino_back;
246 iput(dir);
247 return 0;
248 }