5 * Directory related functions
8 * This file is distributed under the terms of the GNU General Public
9 * License (GPL). Copies of the GPL can be obtained from:
10 * ftp://prep.ai.mit.edu/pub/gnu/GPL
11 * Each contributing author retains all rights to their own work.
18 #include <linux/string.h>
19 #include <linux/buffer_head.h>
23 udf_filead_read(struct inode
*dir
, uint8_t *tmpad
, uint8_t ad_size
,
24 kernel_lb_addr fe_loc
, int *pos
, int *offset
,
25 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
;
74 struct fileIdentDesc
*
75 udf_fileident_read(struct inode
*dir
, loff_t
*nf_pos
,
76 struct udf_fileident_bh
*fibh
,
77 struct fileIdentDesc
*cfi
,
78 kernel_lb_addr
*bloc
, uint32_t *extoffset
,
79 kernel_lb_addr
*eloc
, uint32_t *elen
,
80 uint32_t *offset
, struct buffer_head
**bh
)
82 struct fileIdentDesc
*fi
;
84 struct buffer_head
* tmp
, * bha
[16];
86 fibh
->soffset
= fibh
->eoffset
;
88 if (UDF_I_ALLOCTYPE(dir
) == ICBTAG_FLAG_AD_IN_ICB
)
90 fi
= udf_get_fileident(UDF_I_DATA(dir
) -
92 sizeof(struct extendedFileEntry
) :
93 sizeof(struct fileEntry
)),
94 dir
->i_sb
->s_blocksize
, &(fibh
->eoffset
));
99 *nf_pos
+= ((fibh
->eoffset
- fibh
->soffset
) >> 2);
101 memcpy((uint8_t *)cfi
, (uint8_t *)fi
, sizeof(struct fileIdentDesc
));
106 if (fibh
->eoffset
== dir
->i_sb
->s_blocksize
)
108 int lextoffset
= *extoffset
;
110 if (udf_next_aext(dir
, bloc
, extoffset
, eloc
, elen
, bh
, 1) !=
111 (EXT_RECORDED_ALLOCATED
>> 30))
116 block
= udf_get_lb_pblock(dir
->i_sb
, *eloc
, *offset
);
120 if ((*offset
<< dir
->i_sb
->s_blocksize_bits
) >= *elen
)
123 *extoffset
= lextoffset
;
125 udf_release_data(fibh
->sbh
);
126 if (!(fibh
->sbh
= fibh
->ebh
= udf_tread(dir
->i_sb
, block
)))
128 fibh
->soffset
= fibh
->eoffset
= 0;
130 if (!(*offset
& ((16 >> (dir
->i_sb
->s_blocksize_bits
- 9))-1)))
132 i
= 16 >> (dir
->i_sb
->s_blocksize_bits
- 9);
133 if (i
+*offset
> (*elen
>> dir
->i_sb
->s_blocksize_bits
))
134 i
= (*elen
>> dir
->i_sb
->s_blocksize_bits
)-*offset
;
135 for (num
=0; i
>0; i
--)
137 block
= udf_get_lb_pblock(dir
->i_sb
, *eloc
, *offset
+i
);
138 tmp
= udf_tgetblk(dir
->i_sb
, block
);
139 if (tmp
&& !buffer_uptodate(tmp
) && !buffer_locked(tmp
))
146 ll_rw_block(READA
, num
, bha
);
147 for (i
=0; i
<num
; i
++)
152 else if (fibh
->sbh
!= fibh
->ebh
)
154 udf_release_data(fibh
->sbh
);
155 fibh
->sbh
= fibh
->ebh
;
158 fi
= udf_get_fileident(fibh
->sbh
->b_data
, dir
->i_sb
->s_blocksize
,
164 *nf_pos
+= ((fibh
->eoffset
- fibh
->soffset
) >> 2);
166 if (fibh
->eoffset
<= dir
->i_sb
->s_blocksize
)
168 memcpy((uint8_t *)cfi
, (uint8_t *)fi
, sizeof(struct fileIdentDesc
));
170 else if (fibh
->eoffset
> dir
->i_sb
->s_blocksize
)
172 int lextoffset
= *extoffset
;
174 if (udf_next_aext(dir
, bloc
, extoffset
, eloc
, elen
, bh
, 1) !=
175 (EXT_RECORDED_ALLOCATED
>> 30))
180 block
= udf_get_lb_pblock(dir
->i_sb
, *eloc
, *offset
);
184 if ((*offset
<< dir
->i_sb
->s_blocksize_bits
) >= *elen
)
187 *extoffset
= lextoffset
;
189 fibh
->soffset
-= dir
->i_sb
->s_blocksize
;
190 fibh
->eoffset
-= dir
->i_sb
->s_blocksize
;
192 if (!(fibh
->ebh
= udf_tread(dir
->i_sb
, block
)))
195 if (sizeof(struct fileIdentDesc
) > - fibh
->soffset
)
199 memcpy((uint8_t *)cfi
, (uint8_t *)fi
, - fibh
->soffset
);
200 memcpy((uint8_t *)cfi
- fibh
->soffset
, fibh
->ebh
->b_data
,
201 sizeof(struct fileIdentDesc
) + fibh
->soffset
);
203 fi_len
= (sizeof(struct fileIdentDesc
) + cfi
->lengthFileIdent
+
204 le16_to_cpu(cfi
->lengthOfImpUse
) + 3) & ~3;
206 *nf_pos
+= ((fi_len
- (fibh
->eoffset
- fibh
->soffset
)) >> 2);
207 fibh
->eoffset
= fibh
->soffset
+ fi_len
;
211 memcpy((uint8_t *)cfi
, (uint8_t *)fi
, sizeof(struct fileIdentDesc
));
217 struct fileIdentDesc
*
218 udf_get_fileident(void * buffer
, int bufsize
, int * offset
)
220 struct fileIdentDesc
*fi
;
225 if ( (!buffer
) || (!offset
) ) {
226 udf_debug("invalidparms\n, buffer=%p, offset=%p\n", buffer
, offset
);
232 if ( (*offset
> 0) && (*offset
< bufsize
) ) {
235 fi
=(struct fileIdentDesc
*)ptr
;
236 if (le16_to_cpu(fi
->descTag
.tagIdent
) != TAG_IDENT_FID
)
238 udf_debug("0x%x != TAG_IDENT_FID\n",
239 le16_to_cpu(fi
->descTag
.tagIdent
));
240 udf_debug("offset: %u sizeof: %lu bufsize: %u\n",
241 *offset
, (unsigned long)sizeof(struct fileIdentDesc
), bufsize
);
244 if ( (*offset
+ sizeof(struct fileIdentDesc
)) > bufsize
)
246 lengthThisIdent
= sizeof(struct fileIdentDesc
);
249 lengthThisIdent
= sizeof(struct fileIdentDesc
) +
250 fi
->lengthFileIdent
+ le16_to_cpu(fi
->lengthOfImpUse
);
252 /* we need to figure padding, too! */
253 padlen
= lengthThisIdent
% UDF_NAME_PAD
;
255 lengthThisIdent
+= (UDF_NAME_PAD
- padlen
);
256 *offset
= *offset
+ lengthThisIdent
;
263 udf_get_fileextent(void * buffer
, int bufsize
, int * offset
)
266 struct fileEntry
*fe
;
269 if ( (!buffer
) || (!offset
) )
271 printk(KERN_ERR
"udf: udf_get_fileextent() invalidparms\n");
275 fe
= (struct fileEntry
*)buffer
;
277 if ( le16_to_cpu(fe
->descTag
.tagIdent
) != TAG_IDENT_FE
)
279 udf_debug("0x%x != TAG_IDENT_FE\n",
280 le16_to_cpu(fe
->descTag
.tagIdent
));
284 ptr
=(uint8_t *)(fe
->extendedAttr
) + le32_to_cpu(fe
->lengthExtendedAttr
);
286 if ( (*offset
> 0) && (*offset
< le32_to_cpu(fe
->lengthAllocDescs
)) )
291 ext
= (extent_ad
*)ptr
;
293 *offset
= *offset
+ sizeof(extent_ad
);
299 udf_get_fileshortad(uint8_t *ptr
, int maxoffset
, int *offset
, int inc
)
303 if ( (!ptr
) || (!offset
) )
305 printk(KERN_ERR
"udf: udf_get_fileshortad() invalidparms\n");
309 if ( (*offset
< 0) || ((*offset
+ sizeof(short_ad
)) > maxoffset
) )
311 else if ((sa
= (short_ad
*)ptr
)->extLength
== 0)
315 *offset
+= sizeof(short_ad
);
320 udf_get_filelongad(uint8_t *ptr
, int maxoffset
, int * offset
, int inc
)
324 if ( (!ptr
) || (!offset
) )
326 printk(KERN_ERR
"udf: udf_get_filelongad() invalidparms\n");
330 if ( (*offset
< 0) || ((*offset
+ sizeof(long_ad
)) > maxoffset
) )
332 else if ((la
= (long_ad
*)ptr
)->extLength
== 0)
336 *offset
+= sizeof(long_ad
);