5 * Directory related functions
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@hpesjro.fc.hp.com
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.
22 #include <linux/string.h>
24 uint8_t * udf_filead_read(struct inode *dir, uint8_t *tmpad, uint8_t ad_size,
25 lb_addr fe_loc, int *pos, int *offset, struct buffer_head **bh, int *error)
27 int loffset = *offset;
34 ad = (uint8_t *)(*bh)->b_data + *offset;
39 udf_release_data(*bh);
44 if (*offset == dir->i_sb->s_blocksize)
46 udf_release_data(*bh);
47 block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos);
50 if (!(*bh = udf_tread(dir->i_sb, block)))
53 else if (*offset > dir->i_sb->s_blocksize)
57 remainder = dir->i_sb->s_blocksize - loffset;
58 memcpy((uint8_t *)ad, (*bh)->b_data + loffset, remainder);
60 udf_release_data(*bh);
61 block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos);
64 if (!((*bh) = udf_tread(dir->i_sb, block)))
67 memcpy((uint8_t *)ad + remainder, (*bh)->b_data, ad_size - remainder);
68 *offset = ad_size - remainder;
73 struct fileIdentDesc *
74 udf_fileident_read(struct inode *dir, loff_t *nf_pos,
75 struct udf_fileident_bh *fibh,
76 struct fileIdentDesc *cfi,
77 lb_addr *bloc, uint32_t *extoffset,
78 lb_addr *eloc, uint32_t *elen,
79 uint32_t *offset, struct buffer_head **bh)
81 struct fileIdentDesc *fi;
83 struct buffer_head * tmp, * bha[16];
85 fibh->soffset = fibh->eoffset;
87 if (fibh->eoffset == dir->i_sb->s_blocksize)
89 int lextoffset = *extoffset;
91 if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
92 (EXT_RECORDED_ALLOCATED >> 30))
97 block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
101 if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
104 *extoffset = lextoffset;
106 udf_release_data(fibh->sbh);
107 if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
109 fibh->soffset = fibh->eoffset = 0;
111 if (!(*offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1)))
113 i = 16 >> (dir->i_sb->s_blocksize_bits - 9);
114 if (i+*offset > (*elen >> dir->i_sb->s_blocksize_bits))
115 i = (*elen >> dir->i_sb->s_blocksize_bits)-*offset;
116 for (num=0; i>0; i--)
118 block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset+i);
119 tmp = udf_tgetblk(dir->i_sb, block);
120 if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
127 ll_rw_block(READA, num, bha);
128 for (i=0; i<num; i++)
133 else if (fibh->sbh != fibh->ebh)
135 udf_release_data(fibh->sbh);
136 fibh->sbh = fibh->ebh;
139 fi = udf_get_fileident(fibh->sbh->b_data, dir->i_sb->s_blocksize,
145 *nf_pos += ((fibh->eoffset - fibh->soffset) >> 2);
147 if (fibh->eoffset <= dir->i_sb->s_blocksize)
149 memcpy((uint8_t *)cfi, (uint8_t *)fi, sizeof(struct fileIdentDesc));
151 else if (fibh->eoffset > dir->i_sb->s_blocksize)
153 int lextoffset = *extoffset;
155 if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
156 (EXT_RECORDED_ALLOCATED >> 30))
161 block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
165 if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
168 *extoffset = lextoffset;
170 fibh->soffset -= dir->i_sb->s_blocksize;
171 fibh->eoffset -= dir->i_sb->s_blocksize;
173 if (!(fibh->ebh = udf_tread(dir->i_sb, block)))
176 if (sizeof(struct fileIdentDesc) > - fibh->soffset)
180 memcpy((uint8_t *)cfi, (uint8_t *)fi, - fibh->soffset);
181 memcpy((uint8_t *)cfi - fibh->soffset, fibh->ebh->b_data,
182 sizeof(struct fileIdentDesc) + fibh->soffset);
184 fi_len = (sizeof(struct fileIdentDesc) + cfi->lengthFileIdent +
185 le16_to_cpu(cfi->lengthOfImpUse) + 3) & ~3;
187 *nf_pos += ((fi_len - (fibh->eoffset - fibh->soffset)) >> 2);
188 fibh->eoffset = fibh->soffset + fi_len;
192 memcpy((uint8_t *)cfi, (uint8_t *)fi, sizeof(struct fileIdentDesc));
198 struct fileIdentDesc *
199 udf_get_fileident(void * buffer, int bufsize, int * offset)
201 struct fileIdentDesc *fi;
206 if ( (!buffer) || (!offset) ) {
207 udf_debug("invalidparms\n, buffer=%p, offset=%p\n", buffer, offset);
213 if ( (*offset > 0) && (*offset < bufsize) ) {
216 fi=(struct fileIdentDesc *)ptr;
217 if (le16_to_cpu(fi->descTag.tagIdent) != TAG_IDENT_FID)
219 udf_debug("0x%x != TAG_IDENT_FID\n",
220 le16_to_cpu(fi->descTag.tagIdent));
221 udf_debug("offset: %u sizeof: %lu bufsize: %u\n",
222 *offset, (unsigned long)sizeof(struct fileIdentDesc), bufsize);
225 if ( (*offset + sizeof(struct fileIdentDesc)) > bufsize )
227 lengthThisIdent = sizeof(struct fileIdentDesc);
230 lengthThisIdent = sizeof(struct fileIdentDesc) +
231 fi->lengthFileIdent + le16_to_cpu(fi->lengthOfImpUse);
233 /* we need to figure padding, too! */
234 padlen = lengthThisIdent % UDF_NAME_PAD;
236 lengthThisIdent += (UDF_NAME_PAD - padlen);
237 *offset = *offset + lengthThisIdent;
243 udf_get_fileextent(void * buffer, int bufsize, int * offset)
246 struct fileEntry *fe;
249 if ( (!buffer) || (!offset) )
251 printk(KERN_ERR "udf: udf_get_fileextent() invalidparms\n");
255 fe = (struct fileEntry *)buffer;
257 if ( le16_to_cpu(fe->descTag.tagIdent) != TAG_IDENT_FE )
259 udf_debug("0x%x != TAG_IDENT_FE\n",
260 le16_to_cpu(fe->descTag.tagIdent));
264 ptr=(uint8_t *)(fe->extendedAttr) + le32_to_cpu(fe->lengthExtendedAttr);
266 if ( (*offset > 0) && (*offset < le32_to_cpu(fe->lengthAllocDescs)) )
271 ext = (extent_ad *)ptr;
273 *offset = *offset + sizeof(extent_ad);
278 udf_get_fileshortad(void * buffer, int maxoffset, int *offset, int inc)
283 if ( (!buffer) || (!offset) )
285 printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n");
289 ptr = (uint8_t *)buffer;
291 if ( (*offset > 0) && (*offset < maxoffset) )
296 if ((sa = (short_ad *)ptr)->extLength == 0)
299 (*offset) += sizeof(short_ad);
304 udf_get_filelongad(void * buffer, int maxoffset, int * offset, int inc)
309 if ( (!buffer) || !(offset) )
311 printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n");
315 ptr = (uint8_t *)buffer;
317 if ( (*offset > 0) && (*offset < maxoffset) )
322 if ((la = (long_ad *)ptr)->extLength == 0)
325 (*offset) += sizeof(long_ad);