]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * directory.c | |
3 | * | |
4 | * PURPOSE | |
5 | * Directory related functions | |
6 | * | |
1da177e4 LT |
7 | * COPYRIGHT |
8 | * This file is distributed under the terms of the GNU General Public | |
9 | * License (GPL). Copies of the GPL can be obtained from: | |
10 | * ftp://prep.ai.mit.edu/pub/gnu/GPL | |
11 | * Each contributing author retains all rights to their own work. | |
12 | */ | |
13 | ||
14 | #include "udfdecl.h" | |
15 | #include "udf_i.h" | |
16 | ||
17 | #include <linux/fs.h> | |
18 | #include <linux/string.h> | |
19 | #include <linux/buffer_head.h> | |
20 | ||
21 | #if 0 | |
22 | static uint8_t * | |
23 | udf_filead_read(struct inode *dir, uint8_t *tmpad, uint8_t ad_size, | |
24 | kernel_lb_addr fe_loc, int *pos, int *offset, | |
25 | struct buffer_head **bh, int *error) | |
26 | { | |
27 | int loffset = *offset; | |
28 | int block; | |
29 | uint8_t *ad; | |
30 | int remainder; | |
31 | ||
32 | *error = 0; | |
33 | ||
34 | ad = (uint8_t *)(*bh)->b_data + *offset; | |
35 | *offset += ad_size; | |
36 | ||
37 | if (!ad) | |
38 | { | |
3bf25cb4 | 39 | brelse(*bh); |
1da177e4 LT |
40 | *error = 1; |
41 | return NULL; | |
42 | } | |
43 | ||
44 | if (*offset == dir->i_sb->s_blocksize) | |
45 | { | |
3bf25cb4 | 46 | brelse(*bh); |
1da177e4 LT |
47 | block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos); |
48 | if (!block) | |
49 | return NULL; | |
50 | if (!(*bh = udf_tread(dir->i_sb, block))) | |
51 | return NULL; | |
52 | } | |
53 | else if (*offset > dir->i_sb->s_blocksize) | |
54 | { | |
55 | ad = tmpad; | |
56 | ||
57 | remainder = dir->i_sb->s_blocksize - loffset; | |
58 | memcpy((uint8_t *)ad, (*bh)->b_data + loffset, remainder); | |
59 | ||
3bf25cb4 | 60 | brelse(*bh); |
1da177e4 LT |
61 | block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos); |
62 | if (!block) | |
63 | return NULL; | |
64 | if (!((*bh) = udf_tread(dir->i_sb, block))) | |
65 | return NULL; | |
66 | ||
67 | memcpy((uint8_t *)ad + remainder, (*bh)->b_data, ad_size - remainder); | |
68 | *offset = ad_size - remainder; | |
69 | } | |
70 | return ad; | |
71 | } | |
72 | #endif | |
73 | ||
74 | struct fileIdentDesc * | |
75 | udf_fileident_read(struct inode *dir, loff_t *nf_pos, | |
76 | struct udf_fileident_bh *fibh, | |
77 | struct fileIdentDesc *cfi, | |
ff116fc8 | 78 | struct extent_position *epos, |
1da177e4 | 79 | kernel_lb_addr *eloc, uint32_t *elen, |
ff116fc8 | 80 | sector_t *offset) |
1da177e4 LT |
81 | { |
82 | struct fileIdentDesc *fi; | |
83 | int i, num, block; | |
84 | struct buffer_head * tmp, * bha[16]; | |
85 | ||
86 | fibh->soffset = fibh->eoffset; | |
87 | ||
88 | if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) | |
89 | { | |
90 | fi = udf_get_fileident(UDF_I_DATA(dir) - | |
91 | (UDF_I_EFE(dir) ? | |
92 | sizeof(struct extendedFileEntry) : | |
93 | sizeof(struct fileEntry)), | |
94 | dir->i_sb->s_blocksize, &(fibh->eoffset)); | |
95 | ||
96 | if (!fi) | |
97 | return NULL; | |
98 | ||
99 | *nf_pos += ((fibh->eoffset - fibh->soffset) >> 2); | |
100 | ||
101 | memcpy((uint8_t *)cfi, (uint8_t *)fi, sizeof(struct fileIdentDesc)); | |
102 | ||
103 | return fi; | |
104 | } | |
105 | ||
106 | if (fibh->eoffset == dir->i_sb->s_blocksize) | |
107 | { | |
ff116fc8 | 108 | int lextoffset = epos->offset; |
1da177e4 | 109 | |
ff116fc8 | 110 | if (udf_next_aext(dir, epos, eloc, elen, 1) != |
1da177e4 | 111 | (EXT_RECORDED_ALLOCATED >> 30)) |
1da177e4 | 112 | return NULL; |
1da177e4 LT |
113 | |
114 | block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset); | |
115 | ||
116 | (*offset) ++; | |
117 | ||
118 | if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen) | |
119 | *offset = 0; | |
120 | else | |
ff116fc8 | 121 | epos->offset = lextoffset; |
1da177e4 | 122 | |
3bf25cb4 | 123 | brelse(fibh->sbh); |
1da177e4 LT |
124 | if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block))) |
125 | return NULL; | |
126 | fibh->soffset = fibh->eoffset = 0; | |
127 | ||
128 | if (!(*offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1))) | |
129 | { | |
130 | i = 16 >> (dir->i_sb->s_blocksize_bits - 9); | |
131 | if (i+*offset > (*elen >> dir->i_sb->s_blocksize_bits)) | |
132 | i = (*elen >> dir->i_sb->s_blocksize_bits)-*offset; | |
133 | for (num=0; i>0; i--) | |
134 | { | |
135 | block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset+i); | |
136 | tmp = udf_tgetblk(dir->i_sb, block); | |
137 | if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp)) | |
138 | bha[num++] = tmp; | |
139 | else | |
140 | brelse(tmp); | |
141 | } | |
142 | if (num) | |
143 | { | |
144 | ll_rw_block(READA, num, bha); | |
145 | for (i=0; i<num; i++) | |
146 | brelse(bha[i]); | |
147 | } | |
148 | } | |
149 | } | |
150 | else if (fibh->sbh != fibh->ebh) | |
151 | { | |
3bf25cb4 | 152 | brelse(fibh->sbh); |
1da177e4 LT |
153 | fibh->sbh = fibh->ebh; |
154 | } | |
155 | ||
156 | fi = udf_get_fileident(fibh->sbh->b_data, dir->i_sb->s_blocksize, | |
157 | &(fibh->eoffset)); | |
158 | ||
159 | if (!fi) | |
160 | return NULL; | |
161 | ||
162 | *nf_pos += ((fibh->eoffset - fibh->soffset) >> 2); | |
163 | ||
164 | if (fibh->eoffset <= dir->i_sb->s_blocksize) | |
165 | { | |
166 | memcpy((uint8_t *)cfi, (uint8_t *)fi, sizeof(struct fileIdentDesc)); | |
167 | } | |
168 | else if (fibh->eoffset > dir->i_sb->s_blocksize) | |
169 | { | |
ff116fc8 | 170 | int lextoffset = epos->offset; |
1da177e4 | 171 | |
ff116fc8 | 172 | if (udf_next_aext(dir, epos, eloc, elen, 1) != |
1da177e4 | 173 | (EXT_RECORDED_ALLOCATED >> 30)) |
1da177e4 | 174 | return NULL; |
1da177e4 LT |
175 | |
176 | block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset); | |
177 | ||
178 | (*offset) ++; | |
179 | ||
180 | if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen) | |
181 | *offset = 0; | |
182 | else | |
ff116fc8 | 183 | epos->offset = lextoffset; |
1da177e4 LT |
184 | |
185 | fibh->soffset -= dir->i_sb->s_blocksize; | |
186 | fibh->eoffset -= dir->i_sb->s_blocksize; | |
187 | ||
188 | if (!(fibh->ebh = udf_tread(dir->i_sb, block))) | |
189 | return NULL; | |
190 | ||
191 | if (sizeof(struct fileIdentDesc) > - fibh->soffset) | |
192 | { | |
193 | int fi_len; | |
194 | ||
195 | memcpy((uint8_t *)cfi, (uint8_t *)fi, - fibh->soffset); | |
196 | memcpy((uint8_t *)cfi - fibh->soffset, fibh->ebh->b_data, | |
197 | sizeof(struct fileIdentDesc) + fibh->soffset); | |
198 | ||
199 | fi_len = (sizeof(struct fileIdentDesc) + cfi->lengthFileIdent + | |
200 | le16_to_cpu(cfi->lengthOfImpUse) + 3) & ~3; | |
201 | ||
202 | *nf_pos += ((fi_len - (fibh->eoffset - fibh->soffset)) >> 2); | |
203 | fibh->eoffset = fibh->soffset + fi_len; | |
204 | } | |
205 | else | |
206 | { | |
207 | memcpy((uint8_t *)cfi, (uint8_t *)fi, sizeof(struct fileIdentDesc)); | |
208 | } | |
209 | } | |
210 | return fi; | |
211 | } | |
212 | ||
213 | struct fileIdentDesc * | |
214 | udf_get_fileident(void * buffer, int bufsize, int * offset) | |
215 | { | |
216 | struct fileIdentDesc *fi; | |
217 | int lengthThisIdent; | |
218 | uint8_t * ptr; | |
219 | int padlen; | |
220 | ||
221 | if ( (!buffer) || (!offset) ) { | |
222 | udf_debug("invalidparms\n, buffer=%p, offset=%p\n", buffer, offset); | |
223 | return NULL; | |
224 | } | |
225 | ||
226 | ptr = buffer; | |
227 | ||
228 | if ( (*offset > 0) && (*offset < bufsize) ) { | |
229 | ptr += *offset; | |
230 | } | |
231 | fi=(struct fileIdentDesc *)ptr; | |
232 | if (le16_to_cpu(fi->descTag.tagIdent) != TAG_IDENT_FID) | |
233 | { | |
234 | udf_debug("0x%x != TAG_IDENT_FID\n", | |
235 | le16_to_cpu(fi->descTag.tagIdent)); | |
236 | udf_debug("offset: %u sizeof: %lu bufsize: %u\n", | |
237 | *offset, (unsigned long)sizeof(struct fileIdentDesc), bufsize); | |
238 | return NULL; | |
239 | } | |
240 | if ( (*offset + sizeof(struct fileIdentDesc)) > bufsize ) | |
241 | { | |
242 | lengthThisIdent = sizeof(struct fileIdentDesc); | |
243 | } | |
244 | else | |
245 | lengthThisIdent = sizeof(struct fileIdentDesc) + | |
246 | fi->lengthFileIdent + le16_to_cpu(fi->lengthOfImpUse); | |
247 | ||
248 | /* we need to figure padding, too! */ | |
249 | padlen = lengthThisIdent % UDF_NAME_PAD; | |
250 | if (padlen) | |
251 | lengthThisIdent += (UDF_NAME_PAD - padlen); | |
252 | *offset = *offset + lengthThisIdent; | |
253 | ||
254 | return fi; | |
255 | } | |
256 | ||
257 | #if 0 | |
258 | static extent_ad * | |
259 | udf_get_fileextent(void * buffer, int bufsize, int * offset) | |
260 | { | |
261 | extent_ad * ext; | |
262 | struct fileEntry *fe; | |
263 | uint8_t * ptr; | |
264 | ||
265 | if ( (!buffer) || (!offset) ) | |
266 | { | |
267 | printk(KERN_ERR "udf: udf_get_fileextent() invalidparms\n"); | |
268 | return NULL; | |
269 | } | |
270 | ||
271 | fe = (struct fileEntry *)buffer; | |
272 | ||
273 | if ( le16_to_cpu(fe->descTag.tagIdent) != TAG_IDENT_FE ) | |
274 | { | |
275 | udf_debug("0x%x != TAG_IDENT_FE\n", | |
276 | le16_to_cpu(fe->descTag.tagIdent)); | |
277 | return NULL; | |
278 | } | |
279 | ||
280 | ptr=(uint8_t *)(fe->extendedAttr) + le32_to_cpu(fe->lengthExtendedAttr); | |
281 | ||
282 | if ( (*offset > 0) && (*offset < le32_to_cpu(fe->lengthAllocDescs)) ) | |
283 | { | |
284 | ptr += *offset; | |
285 | } | |
286 | ||
287 | ext = (extent_ad *)ptr; | |
288 | ||
289 | *offset = *offset + sizeof(extent_ad); | |
290 | return ext; | |
291 | } | |
292 | #endif | |
293 | ||
294 | short_ad * | |
295 | udf_get_fileshortad(uint8_t *ptr, int maxoffset, int *offset, int inc) | |
296 | { | |
297 | short_ad *sa; | |
298 | ||
299 | if ( (!ptr) || (!offset) ) | |
300 | { | |
301 | printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n"); | |
302 | return NULL; | |
303 | } | |
304 | ||
305 | if ( (*offset < 0) || ((*offset + sizeof(short_ad)) > maxoffset) ) | |
306 | return NULL; | |
307 | else if ((sa = (short_ad *)ptr)->extLength == 0) | |
308 | return NULL; | |
309 | ||
310 | if (inc) | |
311 | *offset += sizeof(short_ad); | |
312 | return sa; | |
313 | } | |
314 | ||
315 | long_ad * | |
316 | udf_get_filelongad(uint8_t *ptr, int maxoffset, int * offset, int inc) | |
317 | { | |
318 | long_ad *la; | |
319 | ||
320 | if ( (!ptr) || (!offset) ) | |
321 | { | |
322 | printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n"); | |
323 | return NULL; | |
324 | } | |
325 | ||
326 | if ( (*offset < 0) || ((*offset + sizeof(long_ad)) > maxoffset) ) | |
327 | return NULL; | |
328 | else if ((la = (long_ad *)ptr)->extLength == 0) | |
329 | return NULL; | |
330 | ||
331 | if (inc) | |
332 | *offset += sizeof(long_ad); | |
333 | return la; | |
334 | } |