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.
23 #include <linux/string.h>
24 #include <linux/buffer_head.h>
28 udf_filead_read(struct inode
*dir
, uint8_t *tmpad
, uint8_t ad_size
,
29 kernel_lb_addr fe_loc
, int *pos
, int *offset
,
30 struct buffer_head
**bh
, int *error
)
32 int loffset
= *offset
;
39 ad
= (uint8_t *)(*bh
)->b_data
+ *offset
;
44 udf_release_data(*bh
);
49 if (*offset
== dir
->i_sb
->s_blocksize
)
51 udf_release_data(*bh
);
52 block
= udf_get_lb_pblock(dir
->i_sb
, fe_loc
, ++*pos
);
55 if (!(*bh
= udf_tread(dir
->i_sb
, block
)))
58 else if (*offset
> dir
->i_sb
->s_blocksize
)
62 remainder
= dir
->i_sb
->s_blocksize
- loffset
;
63 memcpy((uint8_t *)ad
, (*bh
)->b_data
+ loffset
, remainder
);
65 udf_release_data(*bh
);
66 block
= udf_get_lb_pblock(dir
->i_sb
, fe_loc
, ++*pos
);
69 if (!((*bh
) = udf_tread(dir
->i_sb
, block
)))
72 memcpy((uint8_t *)ad
+ remainder
, (*bh
)->b_data
, ad_size
- remainder
);
73 *offset
= ad_size
- remainder
;
79 struct fileIdentDesc
*
80 udf_fileident_read(struct inode
*dir
, loff_t
*nf_pos
,
81 struct udf_fileident_bh
*fibh
,
82 struct fileIdentDesc
*cfi
,
83 kernel_lb_addr
*bloc
, uint32_t *extoffset
,
84 kernel_lb_addr
*eloc
, uint32_t *elen
,
85 uint32_t *offset
, struct buffer_head
**bh
)
87 struct fileIdentDesc
*fi
;
89 struct buffer_head
* tmp
, * bha
[16];
91 fibh
->soffset
= fibh
->eoffset
;
93 if (UDF_I_ALLOCTYPE(dir
) == ICBTAG_FLAG_AD_IN_ICB
)
95 fi
= udf_get_fileident(UDF_I_DATA(dir
) -
97 sizeof(struct extendedFileEntry
) :
98 sizeof(struct fileEntry
)),
99 dir
->i_sb
->s_blocksize
, &(fibh
->eoffset
));
104 *nf_pos
+= ((fibh
->eoffset
- fibh
->soffset
) >> 2);
106 memcpy((uint8_t *)cfi
, (uint8_t *)fi
, sizeof(struct fileIdentDesc
));
111 if (fibh
->eoffset
== dir
->i_sb
->s_blocksize
)
113 int lextoffset
= *extoffset
;
115 if (udf_next_aext(dir
, bloc
, extoffset
, eloc
, elen
, bh
, 1) !=
116 (EXT_RECORDED_ALLOCATED
>> 30))
121 block
= udf_get_lb_pblock(dir
->i_sb
, *eloc
, *offset
);
125 if ((*offset
<< dir
->i_sb
->s_blocksize_bits
) >= *elen
)
128 *extoffset
= lextoffset
;
130 udf_release_data(fibh
->sbh
);
131 if (!(fibh
->sbh
= fibh
->ebh
= udf_tread(dir
->i_sb
, block
)))
133 fibh
->soffset
= fibh
->eoffset
= 0;
135 if (!(*offset
& ((16 >> (dir
->i_sb
->s_blocksize_bits
- 9))-1)))
137 i
= 16 >> (dir
->i_sb
->s_blocksize_bits
- 9);
138 if (i
+*offset
> (*elen
>> dir
->i_sb
->s_blocksize_bits
))
139 i
= (*elen
>> dir
->i_sb
->s_blocksize_bits
)-*offset
;
140 for (num
=0; i
>0; i
--)
142 block
= udf_get_lb_pblock(dir
->i_sb
, *eloc
, *offset
+i
);
143 tmp
= udf_tgetblk(dir
->i_sb
, block
);
144 if (tmp
&& !buffer_uptodate(tmp
) && !buffer_locked(tmp
))
151 ll_rw_block(READA
, num
, bha
);
152 for (i
=0; i
<num
; i
++)
157 else if (fibh
->sbh
!= fibh
->ebh
)
159 udf_release_data(fibh
->sbh
);
160 fibh
->sbh
= fibh
->ebh
;
163 fi
= udf_get_fileident(fibh
->sbh
->b_data
, dir
->i_sb
->s_blocksize
,
169 *nf_pos
+= ((fibh
->eoffset
- fibh
->soffset
) >> 2);
171 if (fibh
->eoffset
<= dir
->i_sb
->s_blocksize
)
173 memcpy((uint8_t *)cfi
, (uint8_t *)fi
, sizeof(struct fileIdentDesc
));
175 else if (fibh
->eoffset
> dir
->i_sb
->s_blocksize
)
177 int lextoffset
= *extoffset
;
179 if (udf_next_aext(dir
, bloc
, extoffset
, eloc
, elen
, bh
, 1) !=
180 (EXT_RECORDED_ALLOCATED
>> 30))
185 block
= udf_get_lb_pblock(dir
->i_sb
, *eloc
, *offset
);
189 if ((*offset
<< dir
->i_sb
->s_blocksize_bits
) >= *elen
)
192 *extoffset
= lextoffset
;
194 fibh
->soffset
-= dir
->i_sb
->s_blocksize
;
195 fibh
->eoffset
-= dir
->i_sb
->s_blocksize
;
197 if (!(fibh
->ebh
= udf_tread(dir
->i_sb
, block
)))
200 if (sizeof(struct fileIdentDesc
) > - fibh
->soffset
)
204 memcpy((uint8_t *)cfi
, (uint8_t *)fi
, - fibh
->soffset
);
205 memcpy((uint8_t *)cfi
- fibh
->soffset
, fibh
->ebh
->b_data
,
206 sizeof(struct fileIdentDesc
) + fibh
->soffset
);
208 fi_len
= (sizeof(struct fileIdentDesc
) + cfi
->lengthFileIdent
+
209 le16_to_cpu(cfi
->lengthOfImpUse
) + 3) & ~3;
211 *nf_pos
+= ((fi_len
- (fibh
->eoffset
- fibh
->soffset
)) >> 2);
212 fibh
->eoffset
= fibh
->soffset
+ fi_len
;
216 memcpy((uint8_t *)cfi
, (uint8_t *)fi
, sizeof(struct fileIdentDesc
));
222 struct fileIdentDesc
*
223 udf_get_fileident(void * buffer
, int bufsize
, int * offset
)
225 struct fileIdentDesc
*fi
;
230 if ( (!buffer
) || (!offset
) ) {
231 udf_debug("invalidparms\n, buffer=%p, offset=%p\n", buffer
, offset
);
237 if ( (*offset
> 0) && (*offset
< bufsize
) ) {
240 fi
=(struct fileIdentDesc
*)ptr
;
241 if (le16_to_cpu(fi
->descTag
.tagIdent
) != TAG_IDENT_FID
)
243 udf_debug("0x%x != TAG_IDENT_FID\n",
244 le16_to_cpu(fi
->descTag
.tagIdent
));
245 udf_debug("offset: %u sizeof: %lu bufsize: %u\n",
246 *offset
, (unsigned long)sizeof(struct fileIdentDesc
), bufsize
);
249 if ( (*offset
+ sizeof(struct fileIdentDesc
)) > bufsize
)
251 lengthThisIdent
= sizeof(struct fileIdentDesc
);
254 lengthThisIdent
= sizeof(struct fileIdentDesc
) +
255 fi
->lengthFileIdent
+ le16_to_cpu(fi
->lengthOfImpUse
);
257 /* we need to figure padding, too! */
258 padlen
= lengthThisIdent
% UDF_NAME_PAD
;
260 lengthThisIdent
+= (UDF_NAME_PAD
- padlen
);
261 *offset
= *offset
+ lengthThisIdent
;
268 udf_get_fileextent(void * buffer
, int bufsize
, int * offset
)
271 struct fileEntry
*fe
;
274 if ( (!buffer
) || (!offset
) )
276 printk(KERN_ERR
"udf: udf_get_fileextent() invalidparms\n");
280 fe
= (struct fileEntry
*)buffer
;
282 if ( le16_to_cpu(fe
->descTag
.tagIdent
) != TAG_IDENT_FE
)
284 udf_debug("0x%x != TAG_IDENT_FE\n",
285 le16_to_cpu(fe
->descTag
.tagIdent
));
289 ptr
=(uint8_t *)(fe
->extendedAttr
) + le32_to_cpu(fe
->lengthExtendedAttr
);
291 if ( (*offset
> 0) && (*offset
< le32_to_cpu(fe
->lengthAllocDescs
)) )
296 ext
= (extent_ad
*)ptr
;
298 *offset
= *offset
+ sizeof(extent_ad
);
304 udf_get_fileshortad(uint8_t *ptr
, int maxoffset
, int *offset
, int inc
)
308 if ( (!ptr
) || (!offset
) )
310 printk(KERN_ERR
"udf: udf_get_fileshortad() invalidparms\n");
314 if ( (*offset
< 0) || ((*offset
+ sizeof(short_ad
)) > maxoffset
) )
316 else if ((sa
= (short_ad
*)ptr
)->extLength
== 0)
320 *offset
+= sizeof(short_ad
);
325 udf_get_filelongad(uint8_t *ptr
, int maxoffset
, int * offset
, int inc
)
329 if ( (!ptr
) || (!offset
) )
331 printk(KERN_ERR
"udf: udf_get_filelongad() invalidparms\n");
335 if ( (*offset
< 0) || ((*offset
+ sizeof(long_ad
)) > maxoffset
) )
337 else if ((la
= (long_ad
*)ptr
)->extLength
== 0)
341 *offset
+= sizeof(long_ad
);