]>
git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - fs/udf/directory.c
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>
22 static uint8_t *udf_filead_read(struct inode
*dir
, uint8_t * tmpad
,
23 uint8_t ad_size
, kernel_lb_addr fe_loc
,
24 int *pos
, int *offset
, struct buffer_head
**bh
,
27 int loffset
= *offset
;
34 ad
= (uint8_t *) (*bh
)->b_data
+ *offset
;
43 if (*offset
== dir
->i_sb
->s_blocksize
) {
45 block
= udf_get_lb_pblock(dir
->i_sb
, fe_loc
, ++*pos
);
48 if (!(*bh
= udf_tread(dir
->i_sb
, block
)))
50 } else if (*offset
> dir
->i_sb
->s_blocksize
) {
53 remainder
= dir
->i_sb
->s_blocksize
- loffset
;
54 memcpy((uint8_t *) ad
, (*bh
)->b_data
+ loffset
, remainder
);
57 block
= udf_get_lb_pblock(dir
->i_sb
, fe_loc
, ++*pos
);
60 if (!((*bh
) = udf_tread(dir
->i_sb
, block
)))
63 memcpy((uint8_t *) ad
+ remainder
, (*bh
)->b_data
,
65 *offset
= ad_size
- remainder
;
71 struct fileIdentDesc
*udf_fileident_read(struct inode
*dir
, loff_t
* nf_pos
,
72 struct udf_fileident_bh
*fibh
,
73 struct fileIdentDesc
*cfi
,
74 struct extent_position
*epos
,
75 kernel_lb_addr
* eloc
, uint32_t * elen
,
78 struct fileIdentDesc
*fi
;
80 struct buffer_head
*tmp
, *bha
[16];
82 fibh
->soffset
= fibh
->eoffset
;
84 if (UDF_I_ALLOCTYPE(dir
) == ICBTAG_FLAG_AD_IN_ICB
) {
85 fi
= udf_get_fileident(UDF_I_DATA(dir
) -
87 sizeof(struct extendedFileEntry
) :
88 sizeof(struct fileEntry
)),
89 dir
->i_sb
->s_blocksize
,
95 *nf_pos
+= ((fibh
->eoffset
- fibh
->soffset
) >> 2);
97 memcpy((uint8_t *) cfi
, (uint8_t *) fi
,
98 sizeof(struct fileIdentDesc
));
103 if (fibh
->eoffset
== dir
->i_sb
->s_blocksize
) {
104 int lextoffset
= epos
->offset
;
106 if (udf_next_aext(dir
, epos
, eloc
, elen
, 1) !=
107 (EXT_RECORDED_ALLOCATED
>> 30))
110 block
= udf_get_lb_pblock(dir
->i_sb
, *eloc
, *offset
);
114 if ((*offset
<< dir
->i_sb
->s_blocksize_bits
) >= *elen
)
117 epos
->offset
= lextoffset
;
120 if (!(fibh
->sbh
= fibh
->ebh
= udf_tread(dir
->i_sb
, block
)))
122 fibh
->soffset
= fibh
->eoffset
= 0;
125 (*offset
& ((16 >> (dir
->i_sb
->s_blocksize_bits
- 9)) - 1)))
127 i
= 16 >> (dir
->i_sb
->s_blocksize_bits
- 9);
129 (*elen
>> dir
->i_sb
->s_blocksize_bits
))
130 i
= (*elen
>> dir
->i_sb
->s_blocksize_bits
) -
132 for (num
= 0; i
> 0; i
--) {
134 udf_get_lb_pblock(dir
->i_sb
, *eloc
,
136 tmp
= udf_tgetblk(dir
->i_sb
, block
);
137 if (tmp
&& !buffer_uptodate(tmp
)
138 && !buffer_locked(tmp
))
144 ll_rw_block(READA
, num
, bha
);
145 for (i
= 0; i
< num
; i
++)
149 } else if (fibh
->sbh
!= fibh
->ebh
) {
151 fibh
->sbh
= fibh
->ebh
;
154 fi
= udf_get_fileident(fibh
->sbh
->b_data
, dir
->i_sb
->s_blocksize
,
160 *nf_pos
+= ((fibh
->eoffset
- fibh
->soffset
) >> 2);
162 if (fibh
->eoffset
<= dir
->i_sb
->s_blocksize
) {
163 memcpy((uint8_t *) cfi
, (uint8_t *) fi
,
164 sizeof(struct fileIdentDesc
));
165 } else if (fibh
->eoffset
> dir
->i_sb
->s_blocksize
) {
166 int lextoffset
= epos
->offset
;
168 if (udf_next_aext(dir
, epos
, eloc
, elen
, 1) !=
169 (EXT_RECORDED_ALLOCATED
>> 30))
172 block
= udf_get_lb_pblock(dir
->i_sb
, *eloc
, *offset
);
176 if ((*offset
<< dir
->i_sb
->s_blocksize_bits
) >= *elen
)
179 epos
->offset
= lextoffset
;
181 fibh
->soffset
-= dir
->i_sb
->s_blocksize
;
182 fibh
->eoffset
-= dir
->i_sb
->s_blocksize
;
184 if (!(fibh
->ebh
= udf_tread(dir
->i_sb
, block
)))
187 if (sizeof(struct fileIdentDesc
) > -fibh
->soffset
) {
190 memcpy((uint8_t *) cfi
, (uint8_t *) fi
, -fibh
->soffset
);
191 memcpy((uint8_t *) cfi
- fibh
->soffset
,
193 sizeof(struct fileIdentDesc
) + fibh
->soffset
);
196 (sizeof(struct fileIdentDesc
) +
197 cfi
->lengthFileIdent
+
198 le16_to_cpu(cfi
->lengthOfImpUse
) + 3) & ~3;
201 ((fi_len
- (fibh
->eoffset
- fibh
->soffset
)) >> 2);
202 fibh
->eoffset
= fibh
->soffset
+ fi_len
;
204 memcpy((uint8_t *) cfi
, (uint8_t *) fi
,
205 sizeof(struct fileIdentDesc
));
211 struct fileIdentDesc
*udf_get_fileident(void *buffer
, int bufsize
, int *offset
)
213 struct fileIdentDesc
*fi
;
218 if ((!buffer
) || (!offset
)) {
219 udf_debug("invalidparms\n, buffer=%p, offset=%p\n", buffer
,
226 if ((*offset
> 0) && (*offset
< bufsize
)) {
229 fi
= (struct fileIdentDesc
*)ptr
;
230 if (le16_to_cpu(fi
->descTag
.tagIdent
) != TAG_IDENT_FID
) {
231 udf_debug("0x%x != TAG_IDENT_FID\n",
232 le16_to_cpu(fi
->descTag
.tagIdent
));
233 udf_debug("offset: %u sizeof: %lu bufsize: %u\n",
234 *offset
, (unsigned long)sizeof(struct fileIdentDesc
),
238 if ((*offset
+ sizeof(struct fileIdentDesc
)) > bufsize
) {
239 lengthThisIdent
= sizeof(struct fileIdentDesc
);
241 lengthThisIdent
= sizeof(struct fileIdentDesc
) +
242 fi
->lengthFileIdent
+ le16_to_cpu(fi
->lengthOfImpUse
);
244 /* we need to figure padding, too! */
245 padlen
= lengthThisIdent
% UDF_NAME_PAD
;
247 lengthThisIdent
+= (UDF_NAME_PAD
- padlen
);
248 *offset
= *offset
+ lengthThisIdent
;
254 static extent_ad
*udf_get_fileextent(void *buffer
, int bufsize
, int *offset
)
257 struct fileEntry
*fe
;
260 if ((!buffer
) || (!offset
)) {
261 printk(KERN_ERR
"udf: udf_get_fileextent() invalidparms\n");
265 fe
= (struct fileEntry
*)buffer
;
267 if (le16_to_cpu(fe
->descTag
.tagIdent
) != TAG_IDENT_FE
) {
268 udf_debug("0x%x != TAG_IDENT_FE\n",
269 le16_to_cpu(fe
->descTag
.tagIdent
));
274 (uint8_t *) (fe
->extendedAttr
) +
275 le32_to_cpu(fe
->lengthExtendedAttr
);
277 if ((*offset
> 0) && (*offset
< le32_to_cpu(fe
->lengthAllocDescs
))) {
281 ext
= (extent_ad
*) ptr
;
283 *offset
= *offset
+ sizeof(extent_ad
);
288 short_ad
*udf_get_fileshortad(uint8_t * ptr
, int maxoffset
, int *offset
,
293 if ((!ptr
) || (!offset
)) {
294 printk(KERN_ERR
"udf: udf_get_fileshortad() invalidparms\n");
298 if ((*offset
< 0) || ((*offset
+ sizeof(short_ad
)) > maxoffset
))
300 else if ((sa
= (short_ad
*) ptr
)->extLength
== 0)
304 *offset
+= sizeof(short_ad
);
308 long_ad
*udf_get_filelongad(uint8_t * ptr
, int maxoffset
, int *offset
, int inc
)
312 if ((!ptr
) || (!offset
)) {
313 printk(KERN_ERR
"udf: udf_get_filelongad() invalidparms\n");
317 if ((*offset
< 0) || ((*offset
+ sizeof(long_ad
)) > maxoffset
))
319 else if ((la
= (long_ad
*) ptr
)->extLength
== 0)
323 *offset
+= sizeof(long_ad
);