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