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