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.
22 #if defined(__linux__) && defined(__KERNEL__)
25 #include <linux/string.h>
26 #include <linux/udf_fs.h>
30 #include <sys/types.h>
38 Uint8
* udf_filead_read(struct inode
*dir
, Uint8
*tmpad
, Uint8 ad_size
,
39 lb_addr fe_loc
, int *pos
, int *offset
, struct buffer_head
**bh
, int *error
)
41 int loffset
= *offset
;
48 ad
= (Uint8
*)(*bh
)->b_data
+ *offset
;
53 udf_release_data(*bh
);
58 if (*offset
== dir
->i_sb
->s_blocksize
)
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
, dir
->i_sb
->s_blocksize
)))
67 else if (*offset
> dir
->i_sb
->s_blocksize
)
71 remainder
= dir
->i_sb
->s_blocksize
- loffset
;
72 memcpy((Uint8
*)ad
, (*bh
)->b_data
+ loffset
, remainder
);
74 udf_release_data(*bh
);
75 block
= udf_get_lb_pblock(dir
->i_sb
, fe_loc
, ++*pos
);
78 if (!((*bh
) = udf_tread(dir
->i_sb
, block
, dir
->i_sb
->s_blocksize
)))
81 memcpy((Uint8
*)ad
+ remainder
, (*bh
)->b_data
, ad_size
- remainder
);
82 *offset
= ad_size
- remainder
;
87 struct FileIdentDesc
*
88 udf_fileident_read(struct inode
*dir
, int *nf_pos
,
89 struct udf_fileident_bh
*fibh
,
90 struct FileIdentDesc
*cfi
,
91 lb_addr
*bloc
, Uint32
*extoffset
,
92 Uint32
*offset
, struct buffer_head
**bh
)
94 struct FileIdentDesc
*fi
;
99 fibh
->soffset
= fibh
->eoffset
;
101 if (fibh
->eoffset
== dir
->i_sb
->s_blocksize
)
103 int lextoffset
= *extoffset
;
105 if (udf_next_aext(dir
, bloc
, extoffset
, &eloc
, &elen
, bh
, 1) !=
106 EXTENT_RECORDED_ALLOCATED
)
111 block
= udf_get_lb_pblock(dir
->i_sb
, eloc
, *offset
);
115 if (*offset
>= (elen
>> dir
->i_sb
->s_blocksize_bits
))
118 *extoffset
= lextoffset
;
120 udf_release_data(fibh
->sbh
);
121 if (!(fibh
->sbh
= fibh
->ebh
= udf_tread(dir
->i_sb
, block
, dir
->i_sb
->s_blocksize
)))
123 fibh
->soffset
= fibh
->eoffset
= 0;
125 else if (fibh
->sbh
!= fibh
->ebh
)
127 udf_release_data(fibh
->sbh
);
128 fibh
->sbh
= fibh
->ebh
;
131 fi
= udf_get_fileident(fibh
->sbh
->b_data
, dir
->i_sb
->s_blocksize
,
137 *nf_pos
+= ((fibh
->eoffset
- fibh
->soffset
) >> 2);
139 if (fibh
->eoffset
<= dir
->i_sb
->s_blocksize
)
141 memcpy((Uint8
*)cfi
, (Uint8
*)fi
, sizeof(struct FileIdentDesc
));
143 else if (fibh
->eoffset
> dir
->i_sb
->s_blocksize
)
145 int lextoffset
= *extoffset
;
147 if (udf_next_aext(dir
, bloc
, extoffset
, &eloc
, &elen
, bh
, 1) !=
148 EXTENT_RECORDED_ALLOCATED
)
153 block
= udf_get_lb_pblock(dir
->i_sb
, eloc
, *offset
);
157 if (*offset
>= (elen
>> dir
->i_sb
->s_blocksize_bits
))
160 *extoffset
= lextoffset
;
162 fibh
->soffset
-= dir
->i_sb
->s_blocksize
;
163 fibh
->eoffset
-= dir
->i_sb
->s_blocksize
;
165 if (!(fibh
->ebh
= udf_tread(dir
->i_sb
, block
, dir
->i_sb
->s_blocksize
)))
168 if (sizeof(struct FileIdentDesc
) > - fibh
->soffset
)
172 memcpy((Uint8
*)cfi
, (Uint8
*)fi
, - fibh
->soffset
);
173 memcpy((Uint8
*)cfi
- fibh
->soffset
, fibh
->ebh
->b_data
,
174 sizeof(struct FileIdentDesc
) + fibh
->soffset
);
176 fi_len
= (sizeof(struct FileIdentDesc
) + cfi
->lengthFileIdent
+
177 le16_to_cpu(cfi
->lengthOfImpUse
) + 3) & ~3;
179 *nf_pos
+= ((fi_len
- (fibh
->eoffset
- fibh
->soffset
)) >> 2);
180 fibh
->eoffset
= fibh
->soffset
+ fi_len
;
184 memcpy((Uint8
*)cfi
, (Uint8
*)fi
, sizeof(struct FileIdentDesc
));
191 struct FileIdentDesc
*
192 udf_get_fileident(void * buffer
, int bufsize
, int * offset
)
194 struct FileIdentDesc
*fi
;
199 if ( (!buffer
) || (!offset
) ) {
201 udf_debug("invalidparms\n, buffer=%p, offset=%p\n", buffer
, offset
);
208 if ( (*offset
> 0) && (*offset
< bufsize
) ) {
211 fi
=(struct FileIdentDesc
*)ptr
;
212 if (le16_to_cpu(fi
->descTag
.tagIdent
) != TID_FILE_IDENT_DESC
)
215 udf_debug("0x%x != TID_FILE_IDENT_DESC\n",
216 le16_to_cpu(fi
->descTag
.tagIdent
));
217 udf_debug("offset: %u sizeof: %u bufsize: %u\n",
218 *offset
, sizeof(struct FileIdentDesc
), bufsize
);
222 if ( (*offset
+ sizeof(struct FileIdentDesc
)) > bufsize
)
224 lengthThisIdent
= sizeof(struct FileIdentDesc
);
227 lengthThisIdent
= sizeof(struct FileIdentDesc
) +
228 fi
->lengthFileIdent
+ le16_to_cpu(fi
->lengthOfImpUse
);
230 /* we need to figure padding, too! */
231 padlen
= lengthThisIdent
% UDF_NAME_PAD
;
233 lengthThisIdent
+= (UDF_NAME_PAD
- padlen
);
234 *offset
= *offset
+ lengthThisIdent
;
240 udf_get_fileextent(void * buffer
, int bufsize
, int * offset
)
243 struct FileEntry
*fe
;
246 if ( (!buffer
) || (!offset
) )
249 printk(KERN_ERR
"udf: udf_get_fileextent() invalidparms\n");
254 fe
= (struct FileEntry
*)buffer
;
256 if ( le16_to_cpu(fe
->descTag
.tagIdent
) != TID_FILE_ENTRY
)
259 udf_debug("0x%x != TID_FILE_ENTRY\n",
260 le16_to_cpu(fe
->descTag
.tagIdent
));
265 ptr
=(Uint8
*)(fe
->extendedAttr
) + le32_to_cpu(fe
->lengthExtendedAttr
);
267 if ( (*offset
> 0) && (*offset
< le32_to_cpu(fe
->lengthAllocDescs
)) )
272 ext
= (extent_ad
*)ptr
;
274 *offset
= *offset
+ sizeof(extent_ad
);
279 udf_get_fileshortad(void * buffer
, int maxoffset
, int *offset
, int inc
)
284 if ( (!buffer
) || (!offset
) )
287 printk(KERN_ERR
"udf: udf_get_fileshortad() invalidparms\n");
292 ptr
= (Uint8
*)buffer
;
294 if ( (*offset
> 0) && (*offset
< maxoffset
) )
299 if ((sa
= (short_ad
*)ptr
)->extLength
== 0)
302 (*offset
) += sizeof(short_ad
);
307 udf_get_filelongad(void * buffer
, int maxoffset
, int * offset
, int inc
)
312 if ( (!buffer
) || !(offset
) )
315 printk(KERN_ERR
"udf: udf_get_filelongad() invalidparms\n");
320 ptr
= (Uint8
*)buffer
;
322 if ( (*offset
> 0) && (*offset
< maxoffset
) )
327 if ((la
= (long_ad
*)ptr
)->extLength
== 0)
330 (*offset
) += sizeof(long_ad
);