- pre4:
[davej-history.git] / fs / udf / directory.c
blob1200e74f7ad6b0f5b6c67e91b9c96b6c55dff348
1 /*
2 * directory.c
4 * PURPOSE
5 * Directory related functions
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
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.
19 #include "udfdecl.h"
21 #if defined(__linux__) && defined(__KERNEL__)
23 #include <linux/fs.h>
24 #include <linux/string.h>
25 #include <linux/udf_fs.h>
27 #else
29 #include <sys/types.h>
30 #include <stdio.h>
31 #include <unistd.h>
33 #endif
35 #ifdef __KERNEL__
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)
40 int loffset = *offset;
41 int block;
42 Uint8 *ad;
43 int remainder;
45 *error = 0;
47 ad = (Uint8 *)(*bh)->b_data + *offset;
48 *offset += ad_size;
50 if (!ad)
52 udf_release_data(*bh);
53 *error = 1;
54 return NULL;
57 if (*offset == dir->i_sb->s_blocksize)
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;
66 else if (*offset > dir->i_sb->s_blocksize)
68 ad = tmpad;
70 remainder = dir->i_sb->s_blocksize - loffset;
71 memcpy((Uint8 *)ad, (*bh)->b_data + loffset, remainder);
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;
80 memcpy((Uint8 *)ad + remainder, (*bh)->b_data, ad_size - remainder);
81 *offset = ad_size - remainder;
83 return ad;
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)
94 struct FileIdentDesc *fi;
95 int block;
97 fibh->soffset = fibh->eoffset;
99 if (fibh->eoffset == dir->i_sb->s_blocksize)
101 int lextoffset = *extoffset;
103 if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
104 EXTENT_RECORDED_ALLOCATED)
106 return NULL;
109 block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
111 (*offset) ++;
113 if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
114 *offset = 0;
115 else
116 *extoffset = lextoffset;
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;
123 else if (fibh->sbh != fibh->ebh)
125 udf_release_data(fibh->sbh);
126 fibh->sbh = fibh->ebh;
129 fi = udf_get_fileident(fibh->sbh->b_data, dir->i_sb->s_blocksize,
130 &(fibh->eoffset));
132 if (!fi)
133 return NULL;
135 *nf_pos += ((fibh->eoffset - fibh->soffset) >> 2);
137 if (fibh->eoffset <= dir->i_sb->s_blocksize)
139 memcpy((Uint8 *)cfi, (Uint8 *)fi, sizeof(struct FileIdentDesc));
141 else if (fibh->eoffset > dir->i_sb->s_blocksize)
143 int lextoffset = *extoffset;
145 if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
146 EXTENT_RECORDED_ALLOCATED)
148 return NULL;
151 block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
153 (*offset) ++;
155 if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
156 *offset = 0;
157 else
158 *extoffset = lextoffset;
160 fibh->soffset -= dir->i_sb->s_blocksize;
161 fibh->eoffset -= dir->i_sb->s_blocksize;
163 if (!(fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
164 return NULL;
166 if (sizeof(struct FileIdentDesc) > - fibh->soffset)
168 int fi_len;
170 memcpy((Uint8 *)cfi, (Uint8 *)fi, - fibh->soffset);
171 memcpy((Uint8 *)cfi - fibh->soffset, fibh->ebh->b_data,
172 sizeof(struct FileIdentDesc) + fibh->soffset);
174 fi_len = (sizeof(struct FileIdentDesc) + cfi->lengthFileIdent +
175 le16_to_cpu(cfi->lengthOfImpUse) + 3) & ~3;
177 *nf_pos += ((fi_len - (fibh->eoffset - fibh->soffset)) >> 2);
178 fibh->eoffset = fibh->soffset + fi_len;
180 else
182 memcpy((Uint8 *)cfi, (Uint8 *)fi, sizeof(struct FileIdentDesc));
185 return fi;
187 #endif
189 struct FileIdentDesc *
190 udf_get_fileident(void * buffer, int bufsize, int * offset)
192 struct FileIdentDesc *fi;
193 int lengthThisIdent;
194 Uint8 * ptr;
195 int padlen;
197 if ( (!buffer) || (!offset) ) {
198 #ifdef __KERNEL__
199 udf_debug("invalidparms\n, buffer=%p, offset=%p\n", buffer, offset);
200 #endif
201 return NULL;
204 ptr = buffer;
206 if ( (*offset > 0) && (*offset < bufsize) ) {
207 ptr += *offset;
209 fi=(struct FileIdentDesc *)ptr;
210 if (le16_to_cpu(fi->descTag.tagIdent) != TID_FILE_IDENT_DESC)
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;
220 if ( (*offset + sizeof(struct FileIdentDesc)) > bufsize )
222 lengthThisIdent = sizeof(struct FileIdentDesc);
224 else
225 lengthThisIdent = sizeof(struct FileIdentDesc) +
226 fi->lengthFileIdent + le16_to_cpu(fi->lengthOfImpUse);
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;
234 return fi;
237 extent_ad *
238 udf_get_fileextent(void * buffer, int bufsize, int * offset)
240 extent_ad * ext;
241 struct FileEntry *fe;
242 Uint8 * ptr;
244 if ( (!buffer) || (!offset) )
246 #ifdef __KERNEL__
247 printk(KERN_ERR "udf: udf_get_fileextent() invalidparms\n");
248 #endif
249 return NULL;
252 fe = (struct FileEntry *)buffer;
254 if ( le16_to_cpu(fe->descTag.tagIdent) != TID_FILE_ENTRY )
256 #ifdef __KERNEL__
257 udf_debug("0x%x != TID_FILE_ENTRY\n",
258 le16_to_cpu(fe->descTag.tagIdent));
259 #endif
260 return NULL;
263 ptr=(Uint8 *)(fe->extendedAttr) + le32_to_cpu(fe->lengthExtendedAttr);
265 if ( (*offset > 0) && (*offset < le32_to_cpu(fe->lengthAllocDescs)) )
267 ptr += *offset;
270 ext = (extent_ad *)ptr;
272 *offset = *offset + sizeof(extent_ad);
273 return ext;
276 short_ad *
277 udf_get_fileshortad(void * buffer, int maxoffset, int *offset, int inc)
279 short_ad * sa;
280 Uint8 * ptr;
282 if ( (!buffer) || (!offset) )
284 #ifdef __KERNEL__
285 printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n");
286 #endif
287 return NULL;
290 ptr = (Uint8 *)buffer;
292 if ( (*offset > 0) && (*offset < maxoffset) )
293 ptr += *offset;
294 else
295 return NULL;
297 if ((sa = (short_ad *)ptr)->extLength == 0)
298 return NULL;
299 else if (inc)
300 (*offset) += sizeof(short_ad);
301 return sa;
304 long_ad *
305 udf_get_filelongad(void * buffer, int maxoffset, int * offset, int inc)
307 long_ad * la;
308 Uint8 * ptr;
310 if ( (!buffer) || !(offset) )
312 #ifdef __KERNEL__
313 printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n");
314 #endif
315 return NULL;
318 ptr = (Uint8 *)buffer;
320 if ( (*offset > 0) && (*offset < maxoffset) )
321 ptr += *offset;
322 else
323 return NULL;
325 if ((la = (long_ad *)ptr)->extLength == 0)
326 return NULL;
327 else if (inc)
328 (*offset) += sizeof(long_ad);
329 return la;