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/bio.h>
21 struct fileIdentDesc
*udf_fileident_read(struct inode
*dir
, loff_t
*nf_pos
,
22 struct udf_fileident_bh
*fibh
,
23 struct fileIdentDesc
*cfi
,
24 struct extent_position
*epos
,
25 struct kernel_lb_addr
*eloc
, uint32_t *elen
,
28 struct fileIdentDesc
*fi
;
30 struct buffer_head
*tmp
, *bha
[16];
31 struct udf_inode_info
*iinfo
= UDF_I(dir
);
33 fibh
->soffset
= fibh
->eoffset
;
35 if (iinfo
->i_alloc_type
== ICBTAG_FLAG_AD_IN_ICB
) {
36 fi
= udf_get_fileident(iinfo
->i_ext
.i_data
-
38 sizeof(struct extendedFileEntry
) :
39 sizeof(struct fileEntry
)),
40 dir
->i_sb
->s_blocksize
,
45 *nf_pos
+= fibh
->eoffset
- fibh
->soffset
;
47 memcpy((uint8_t *)cfi
, (uint8_t *)fi
,
48 sizeof(struct fileIdentDesc
));
53 if (fibh
->eoffset
== dir
->i_sb
->s_blocksize
) {
54 int lextoffset
= epos
->offset
;
55 unsigned char blocksize_bits
= dir
->i_sb
->s_blocksize_bits
;
57 if (udf_next_aext(dir
, epos
, eloc
, elen
, 1) !=
58 (EXT_RECORDED_ALLOCATED
>> 30))
61 block
= udf_get_lb_pblock(dir
->i_sb
, eloc
, *offset
);
65 if ((*offset
<< blocksize_bits
) >= *elen
)
68 epos
->offset
= lextoffset
;
71 fibh
->sbh
= fibh
->ebh
= udf_tread(dir
->i_sb
, block
);
74 fibh
->soffset
= fibh
->eoffset
= 0;
76 if (!(*offset
& ((16 >> (blocksize_bits
- 9)) - 1))) {
77 i
= 16 >> (blocksize_bits
- 9);
78 if (i
+ *offset
> (*elen
>> blocksize_bits
))
79 i
= (*elen
>> blocksize_bits
)-*offset
;
80 for (num
= 0; i
> 0; i
--) {
81 block
= udf_get_lb_pblock(dir
->i_sb
, eloc
,
83 tmp
= udf_tgetblk(dir
->i_sb
, block
);
84 if (tmp
&& !buffer_uptodate(tmp
) &&
91 ll_rw_block(REQ_OP_READ
, REQ_RAHEAD
, num
, bha
);
92 for (i
= 0; i
< num
; i
++)
96 } else if (fibh
->sbh
!= fibh
->ebh
) {
98 fibh
->sbh
= fibh
->ebh
;
101 fi
= udf_get_fileident(fibh
->sbh
->b_data
, dir
->i_sb
->s_blocksize
,
107 *nf_pos
+= fibh
->eoffset
- fibh
->soffset
;
109 if (fibh
->eoffset
<= dir
->i_sb
->s_blocksize
) {
110 memcpy((uint8_t *)cfi
, (uint8_t *)fi
,
111 sizeof(struct fileIdentDesc
));
112 } else if (fibh
->eoffset
> dir
->i_sb
->s_blocksize
) {
113 int lextoffset
= epos
->offset
;
115 if (udf_next_aext(dir
, epos
, eloc
, elen
, 1) !=
116 (EXT_RECORDED_ALLOCATED
>> 30))
119 block
= udf_get_lb_pblock(dir
->i_sb
, eloc
, *offset
);
123 if ((*offset
<< dir
->i_sb
->s_blocksize_bits
) >= *elen
)
126 epos
->offset
= lextoffset
;
128 fibh
->soffset
-= dir
->i_sb
->s_blocksize
;
129 fibh
->eoffset
-= dir
->i_sb
->s_blocksize
;
131 fibh
->ebh
= udf_tread(dir
->i_sb
, block
);
135 if (sizeof(struct fileIdentDesc
) > -fibh
->soffset
) {
138 memcpy((uint8_t *)cfi
, (uint8_t *)fi
, -fibh
->soffset
);
139 memcpy((uint8_t *)cfi
- fibh
->soffset
,
141 sizeof(struct fileIdentDesc
) + fibh
->soffset
);
143 fi_len
= (sizeof(struct fileIdentDesc
) +
144 cfi
->lengthFileIdent
+
145 le16_to_cpu(cfi
->lengthOfImpUse
) + 3) & ~3;
147 *nf_pos
+= fi_len
- (fibh
->eoffset
- fibh
->soffset
);
148 fibh
->eoffset
= fibh
->soffset
+ fi_len
;
150 memcpy((uint8_t *)cfi
, (uint8_t *)fi
,
151 sizeof(struct fileIdentDesc
));
154 /* Got last entry outside of dir size - fs is corrupted! */
155 if (*nf_pos
> dir
->i_size
)
160 struct fileIdentDesc
*udf_get_fileident(void *buffer
, int bufsize
, int *offset
)
162 struct fileIdentDesc
*fi
;
167 if ((!buffer
) || (!offset
)) {
168 udf_debug("invalidparms, buffer=%p, offset=%p\n",
175 if ((*offset
> 0) && (*offset
< bufsize
))
177 fi
= (struct fileIdentDesc
*)ptr
;
178 if (fi
->descTag
.tagIdent
!= cpu_to_le16(TAG_IDENT_FID
)) {
179 udf_debug("0x%x != TAG_IDENT_FID\n",
180 le16_to_cpu(fi
->descTag
.tagIdent
));
181 udf_debug("offset: %u sizeof: %lu bufsize: %u\n",
182 *offset
, (unsigned long)sizeof(struct fileIdentDesc
),
186 if ((*offset
+ sizeof(struct fileIdentDesc
)) > bufsize
)
187 lengthThisIdent
= sizeof(struct fileIdentDesc
);
189 lengthThisIdent
= sizeof(struct fileIdentDesc
) +
190 fi
->lengthFileIdent
+ le16_to_cpu(fi
->lengthOfImpUse
);
192 /* we need to figure padding, too! */
193 padlen
= lengthThisIdent
% UDF_NAME_PAD
;
195 lengthThisIdent
+= (UDF_NAME_PAD
- padlen
);
196 *offset
= *offset
+ lengthThisIdent
;
201 struct short_ad
*udf_get_fileshortad(uint8_t *ptr
, int maxoffset
, uint32_t *offset
,
206 if ((!ptr
) || (!offset
)) {
207 pr_err("%s: invalidparms\n", __func__
);
211 if ((*offset
+ sizeof(struct short_ad
)) > maxoffset
)
214 sa
= (struct short_ad
*)ptr
;
215 if (sa
->extLength
== 0)
220 *offset
+= sizeof(struct short_ad
);
224 struct long_ad
*udf_get_filelongad(uint8_t *ptr
, int maxoffset
, uint32_t *offset
, int inc
)
228 if ((!ptr
) || (!offset
)) {
229 pr_err("%s: invalidparms\n", __func__
);
233 if ((*offset
+ sizeof(struct long_ad
)) > maxoffset
)
236 la
= (struct long_ad
*)ptr
;
237 if (la
->extLength
== 0)
242 *offset
+= sizeof(struct long_ad
);