* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-2.3.21 / fs / udf / directory.c
blobbc2ced00998ee05bf6a094f73627caed962c1d8f
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"
20 #include "udf_sb.h"
22 #if defined(__linux__) && defined(__KERNEL__)
24 #include <linux/fs.h>
25 #include <linux/string.h>
26 #include <linux/udf_fs.h>
28 #else
30 #include <sys/types.h>
31 #include <stdio.h>
32 #include <unistd.h>
34 #endif
36 #ifdef __KERNEL__
38 Uint8 * udf_filead_read(struct inode *dir, Uint8 *tmpad, Uint8 ad_size,
39 lb_addr fe_loc, int *pos, int *offset, struct buffer_head **bh, int *error)
41 int loffset = *offset;
42 int block;
43 Uint8 *ad;
44 int remainder;
46 *error = 0;
48 ad = (Uint8 *)(*bh)->b_data + *offset;
49 *offset += ad_size;
51 if (!ad)
53 udf_release_data(*bh);
54 *error = 1;
55 return NULL;
58 if (*offset == dir->i_sb->s_blocksize)
60 udf_release_data(*bh);
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, dir->i_sb->s_blocksize)))
65 return NULL;
67 else if (*offset > dir->i_sb->s_blocksize)
69 ad = tmpad;
71 remainder = dir->i_sb->s_blocksize - loffset;
72 memcpy((Uint8 *)ad, (*bh)->b_data + loffset, remainder);
74 udf_release_data(*bh);
75 block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos);
76 if (!block)
77 return NULL;
78 if (!((*bh) = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
79 return NULL;
81 memcpy((Uint8 *)ad + remainder, (*bh)->b_data, ad_size - remainder);
82 *offset = ad_size - remainder;
84 return ad;
87 struct FileIdentDesc *
88 udf_fileident_read(struct inode *dir, int *nf_pos,
89 struct udf_fileident_bh *fibh,
90 struct FileIdentDesc *cfi,
91 lb_addr *bloc, Uint32 *extoffset,
92 Uint32 *offset, struct buffer_head **bh)
94 struct FileIdentDesc *fi;
95 lb_addr eloc;
96 Uint32 elen;
97 int block;
99 fibh->soffset = fibh->eoffset;
101 if (fibh->eoffset == dir->i_sb->s_blocksize)
103 int lextoffset = *extoffset;
105 if (udf_next_aext(dir, bloc, extoffset, &eloc, &elen, bh, 1) !=
106 EXTENT_RECORDED_ALLOCATED)
108 return NULL;
111 block = udf_get_lb_pblock(dir->i_sb, eloc, *offset);
113 (*offset) ++;
115 if (*offset >= (elen >> dir->i_sb->s_blocksize_bits))
116 *offset = 0;
117 else
118 *extoffset = lextoffset;
120 udf_release_data(fibh->sbh);
121 if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
122 return NULL;
123 fibh->soffset = fibh->eoffset = 0;
125 else if (fibh->sbh != fibh->ebh)
127 udf_release_data(fibh->sbh);
128 fibh->sbh = fibh->ebh;
131 fi = udf_get_fileident(fibh->sbh->b_data, dir->i_sb->s_blocksize,
132 &(fibh->eoffset));
134 if (!fi)
135 return NULL;
137 *nf_pos += ((fibh->eoffset - fibh->soffset) >> 2);
139 if (fibh->eoffset <= dir->i_sb->s_blocksize)
141 memcpy((Uint8 *)cfi, (Uint8 *)fi, sizeof(struct FileIdentDesc));
143 else if (fibh->eoffset > dir->i_sb->s_blocksize)
145 int lextoffset = *extoffset;
147 if (udf_next_aext(dir, bloc, extoffset, &eloc, &elen, bh, 1) !=
148 EXTENT_RECORDED_ALLOCATED)
150 return NULL;
153 block = udf_get_lb_pblock(dir->i_sb, eloc, *offset);
155 (*offset) ++;
157 if (*offset >= (elen >> dir->i_sb->s_blocksize_bits))
158 *offset = 0;
159 else
160 *extoffset = lextoffset;
162 fibh->soffset -= dir->i_sb->s_blocksize;
163 fibh->eoffset -= dir->i_sb->s_blocksize;
165 if (!(fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
166 return NULL;
168 if (sizeof(struct FileIdentDesc) > - fibh->soffset)
170 int fi_len;
172 memcpy((Uint8 *)cfi, (Uint8 *)fi, - fibh->soffset);
173 memcpy((Uint8 *)cfi - fibh->soffset, fibh->ebh->b_data,
174 sizeof(struct FileIdentDesc) + fibh->soffset);
176 fi_len = (sizeof(struct FileIdentDesc) + cfi->lengthFileIdent +
177 le16_to_cpu(cfi->lengthOfImpUse) + 3) & ~3;
179 *nf_pos += ((fi_len - (fibh->eoffset - fibh->soffset)) >> 2);
180 fibh->eoffset = fibh->soffset + fi_len;
182 else
184 memcpy((Uint8 *)cfi, (Uint8 *)fi, sizeof(struct FileIdentDesc));
187 return fi;
189 #endif
191 struct FileIdentDesc *
192 udf_get_fileident(void * buffer, int bufsize, int * offset)
194 struct FileIdentDesc *fi;
195 int lengthThisIdent;
196 Uint8 * ptr;
197 int padlen;
199 if ( (!buffer) || (!offset) ) {
200 #ifdef __KERNEL__
201 udf_debug("invalidparms\n, buffer=%p, offset=%p\n", buffer, offset);
202 #endif
203 return NULL;
206 ptr = buffer;
208 if ( (*offset > 0) && (*offset < bufsize) ) {
209 ptr += *offset;
211 fi=(struct FileIdentDesc *)ptr;
212 if (le16_to_cpu(fi->descTag.tagIdent) != TID_FILE_IDENT_DESC)
214 #ifdef __KERNEL__
215 udf_debug("0x%x != TID_FILE_IDENT_DESC\n",
216 le16_to_cpu(fi->descTag.tagIdent));
217 udf_debug("offset: %u sizeof: %u bufsize: %u\n",
218 *offset, sizeof(struct FileIdentDesc), bufsize);
219 #endif
220 return NULL;
222 if ( (*offset + sizeof(struct FileIdentDesc)) > bufsize )
224 lengthThisIdent = sizeof(struct FileIdentDesc);
226 else
227 lengthThisIdent = sizeof(struct FileIdentDesc) +
228 fi->lengthFileIdent + le16_to_cpu(fi->lengthOfImpUse);
230 /* we need to figure padding, too! */
231 padlen = lengthThisIdent % UDF_NAME_PAD;
232 if (padlen)
233 lengthThisIdent += (UDF_NAME_PAD - padlen);
234 *offset = *offset + lengthThisIdent;
236 return fi;
239 extent_ad *
240 udf_get_fileextent(void * buffer, int bufsize, int * offset)
242 extent_ad * ext;
243 struct FileEntry *fe;
244 Uint8 * ptr;
246 if ( (!buffer) || (!offset) )
248 #ifdef __KERNEL__
249 printk(KERN_ERR "udf: udf_get_fileextent() invalidparms\n");
250 #endif
251 return NULL;
254 fe = (struct FileEntry *)buffer;
256 if ( le16_to_cpu(fe->descTag.tagIdent) != TID_FILE_ENTRY )
258 #ifdef __KERNEL__
259 udf_debug("0x%x != TID_FILE_ENTRY\n",
260 le16_to_cpu(fe->descTag.tagIdent));
261 #endif
262 return NULL;
265 ptr=(Uint8 *)(fe->extendedAttr) + le32_to_cpu(fe->lengthExtendedAttr);
267 if ( (*offset > 0) && (*offset < le32_to_cpu(fe->lengthAllocDescs)) )
269 ptr += *offset;
272 ext = (extent_ad *)ptr;
274 *offset = *offset + sizeof(extent_ad);
275 return ext;
278 short_ad *
279 udf_get_fileshortad(void * buffer, int maxoffset, int *offset, int inc)
281 short_ad * sa;
282 Uint8 * ptr;
284 if ( (!buffer) || (!offset) )
286 #ifdef __KERNEL__
287 printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n");
288 #endif
289 return NULL;
292 ptr = (Uint8 *)buffer;
294 if ( (*offset > 0) && (*offset < maxoffset) )
295 ptr += *offset;
296 else
297 return NULL;
299 if ((sa = (short_ad *)ptr)->extLength == 0)
300 return NULL;
301 else if (inc)
302 (*offset) += sizeof(short_ad);
303 return sa;
306 long_ad *
307 udf_get_filelongad(void * buffer, int maxoffset, int * offset, int inc)
309 long_ad * la;
310 Uint8 * ptr;
312 if ( (!buffer) || !(offset) )
314 #ifdef __KERNEL__
315 printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n");
316 #endif
317 return NULL;
320 ptr = (Uint8 *)buffer;
322 if ( (*offset > 0) && (*offset < maxoffset) )
323 ptr += *offset;
324 else
325 return NULL;
327 if ((la = (long_ad *)ptr)->extLength == 0)
328 return NULL;
329 else if (inc)
330 (*offset) += sizeof(long_ad);
331 return la;