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@hootie.lvld.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.
21 #if defined(__linux__) && defined(__KERNEL__)
24 #include <linux/string.h>
25 #include <linux/udf_fs.h>
29 #include <sys/types.h>
37 Uint8
* udf_filead_read(struct inode
*dir
, Uint8
*tmpad
, Uint8 ad_size
,
38 lb_addr fe_loc
, int *pos
, int *offset
, struct buffer_head
**bh
, int *error
)
40 int loffset
= *offset
;
47 ad
= (Uint8
*)(*bh
)->b_data
+ *offset
;
52 udf_release_data(*bh
);
57 if (*offset
== dir
->i_sb
->s_blocksize
)
59 udf_release_data(*bh
);
60 block
= udf_get_lb_pblock(dir
->i_sb
, fe_loc
, ++*pos
);
63 if (!(*bh
= udf_tread(dir
->i_sb
, block
, dir
->i_sb
->s_blocksize
)))
66 else if (*offset
> dir
->i_sb
->s_blocksize
)
70 remainder
= dir
->i_sb
->s_blocksize
- loffset
;
71 memcpy((Uint8
*)ad
, (*bh
)->b_data
+ loffset
, remainder
);
73 udf_release_data(*bh
);
74 block
= udf_get_lb_pblock(dir
->i_sb
, fe_loc
, ++*pos
);
77 if (!((*bh
) = udf_tread(dir
->i_sb
, block
, dir
->i_sb
->s_blocksize
)))
80 memcpy((Uint8
*)ad
+ remainder
, (*bh
)->b_data
, ad_size
- remainder
);
81 *offset
= ad_size
- remainder
;
86 struct FileIdentDesc
*
87 udf_fileident_read(struct inode
*dir
, loff_t
*nf_pos
,
88 struct udf_fileident_bh
*fibh
,
89 struct FileIdentDesc
*cfi
,
90 lb_addr
*bloc
, Uint32
*extoffset
,
91 lb_addr
*eloc
, Uint32
*elen
,
92 Uint32
*offset
, struct buffer_head
**bh
)
94 struct FileIdentDesc
*fi
;
97 fibh
->soffset
= fibh
->eoffset
;
99 if (fibh
->eoffset
== dir
->i_sb
->s_blocksize
)
101 int lextoffset
= *extoffset
;
103 if (udf_next_aext(dir
, bloc
, extoffset
, eloc
, elen
, bh
, 1) !=
104 EXTENT_RECORDED_ALLOCATED
)
109 block
= udf_get_lb_pblock(dir
->i_sb
, *eloc
, *offset
);
113 if ((*offset
<< dir
->i_sb
->s_blocksize_bits
) >= *elen
)
116 *extoffset
= lextoffset
;
118 udf_release_data(fibh
->sbh
);
119 if (!(fibh
->sbh
= fibh
->ebh
= udf_tread(dir
->i_sb
, block
, dir
->i_sb
->s_blocksize
)))
121 fibh
->soffset
= fibh
->eoffset
= 0;
123 else if (fibh
->sbh
!= fibh
->ebh
)
125 udf_release_data(fibh
->sbh
);
126 fibh
->sbh
= fibh
->ebh
;
129 fi
= udf_get_fileident(fibh
->sbh
->b_data
, dir
->i_sb
->s_blocksize
,
135 *nf_pos
+= ((fibh
->eoffset
- fibh
->soffset
) >> 2);
137 if (fibh
->eoffset
<= dir
->i_sb
->s_blocksize
)
139 memcpy((Uint8
*)cfi
, (Uint8
*)fi
, sizeof(struct FileIdentDesc
));
141 else if (fibh
->eoffset
> dir
->i_sb
->s_blocksize
)
143 int lextoffset
= *extoffset
;
145 if (udf_next_aext(dir
, bloc
, extoffset
, eloc
, elen
, bh
, 1) !=
146 EXTENT_RECORDED_ALLOCATED
)
151 block
= udf_get_lb_pblock(dir
->i_sb
, *eloc
, *offset
);
155 if ((*offset
<< dir
->i_sb
->s_blocksize_bits
) >= *elen
)
158 *extoffset
= lextoffset
;
160 fibh
->soffset
-= dir
->i_sb
->s_blocksize
;
161 fibh
->eoffset
-= dir
->i_sb
->s_blocksize
;
163 if (!(fibh
->ebh
= udf_tread(dir
->i_sb
, block
, dir
->i_sb
->s_blocksize
)))
166 if (sizeof(struct FileIdentDesc
) > - fibh
->soffset
)
170 memcpy((Uint8
*)cfi
, (Uint8
*)fi
, - fibh
->soffset
);
171 memcpy((Uint8
*)cfi
- fibh
->soffset
, fibh
->ebh
->b_data
,
172 sizeof(struct FileIdentDesc
) + fibh
->soffset
);
174 fi_len
= (sizeof(struct FileIdentDesc
) + cfi
->lengthFileIdent
+
175 le16_to_cpu(cfi
->lengthOfImpUse
) + 3) & ~3;
177 *nf_pos
+= ((fi_len
- (fibh
->eoffset
- fibh
->soffset
)) >> 2);
178 fibh
->eoffset
= fibh
->soffset
+ fi_len
;
182 memcpy((Uint8
*)cfi
, (Uint8
*)fi
, sizeof(struct FileIdentDesc
));
189 struct FileIdentDesc
*
190 udf_get_fileident(void * buffer
, int bufsize
, int * offset
)
192 struct FileIdentDesc
*fi
;
197 if ( (!buffer
) || (!offset
) ) {
199 udf_debug("invalidparms\n, buffer=%p, offset=%p\n", buffer
, offset
);
206 if ( (*offset
> 0) && (*offset
< bufsize
) ) {
209 fi
=(struct FileIdentDesc
*)ptr
;
210 if (le16_to_cpu(fi
->descTag
.tagIdent
) != TID_FILE_IDENT_DESC
)
213 udf_debug("0x%x != TID_FILE_IDENT_DESC\n",
214 le16_to_cpu(fi
->descTag
.tagIdent
));
215 udf_debug("offset: %u sizeof: %lu bufsize: %u\n",
216 *offset
, (unsigned long)sizeof(struct FileIdentDesc
), bufsize
);
220 if ( (*offset
+ sizeof(struct FileIdentDesc
)) > bufsize
)
222 lengthThisIdent
= sizeof(struct FileIdentDesc
);
225 lengthThisIdent
= sizeof(struct FileIdentDesc
) +
226 fi
->lengthFileIdent
+ le16_to_cpu(fi
->lengthOfImpUse
);
228 /* we need to figure padding, too! */
229 padlen
= lengthThisIdent
% UDF_NAME_PAD
;
231 lengthThisIdent
+= (UDF_NAME_PAD
- padlen
);
232 *offset
= *offset
+ lengthThisIdent
;
238 udf_get_fileextent(void * buffer
, int bufsize
, int * offset
)
241 struct FileEntry
*fe
;
244 if ( (!buffer
) || (!offset
) )
247 printk(KERN_ERR
"udf: udf_get_fileextent() invalidparms\n");
252 fe
= (struct FileEntry
*)buffer
;
254 if ( le16_to_cpu(fe
->descTag
.tagIdent
) != TID_FILE_ENTRY
)
257 udf_debug("0x%x != TID_FILE_ENTRY\n",
258 le16_to_cpu(fe
->descTag
.tagIdent
));
263 ptr
=(Uint8
*)(fe
->extendedAttr
) + le32_to_cpu(fe
->lengthExtendedAttr
);
265 if ( (*offset
> 0) && (*offset
< le32_to_cpu(fe
->lengthAllocDescs
)) )
270 ext
= (extent_ad
*)ptr
;
272 *offset
= *offset
+ sizeof(extent_ad
);
277 udf_get_fileshortad(void * buffer
, int maxoffset
, int *offset
, int inc
)
282 if ( (!buffer
) || (!offset
) )
285 printk(KERN_ERR
"udf: udf_get_fileshortad() invalidparms\n");
290 ptr
= (Uint8
*)buffer
;
292 if ( (*offset
> 0) && (*offset
< maxoffset
) )
297 if ((sa
= (short_ad
*)ptr
)->extLength
== 0)
300 (*offset
) += sizeof(short_ad
);
305 udf_get_filelongad(void * buffer
, int maxoffset
, int * offset
, int inc
)
310 if ( (!buffer
) || !(offset
) )
313 printk(KERN_ERR
"udf: udf_get_filelongad() invalidparms\n");
318 ptr
= (Uint8
*)buffer
;
320 if ( (*offset
> 0) && (*offset
< maxoffset
) )
325 if ((la
= (long_ad
*)ptr
)->extLength
== 0)
328 (*offset
) += sizeof(long_ad
);