directory.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:7k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * directory.c
  3.  *
  4.  * PURPOSE
  5.  * Directory related functions
  6.  *
  7.  * CONTACTS
  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@hpesjro.fc.hp.com
  11.  *
  12.  * COPYRIGHT
  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.
  17.  */
  18. #include "udfdecl.h"
  19. #if defined(__linux__) && defined(__KERNEL__)
  20. #include <linux/fs.h>
  21. #include <linux/string.h>
  22. #include <linux/udf_fs.h>
  23. #else
  24. #include <sys/types.h>
  25. #include <stdio.h>
  26. #include <unistd.h>
  27. #endif
  28. #ifdef __KERNEL__
  29. Uint8 * udf_filead_read(struct inode *dir, Uint8 *tmpad, Uint8 ad_size,
  30. lb_addr fe_loc, int *pos, int *offset, struct buffer_head **bh, int *error)
  31. {
  32. int loffset = *offset;
  33. int block;
  34. Uint8 *ad;
  35. int remainder;
  36. *error = 0;
  37. ad = (Uint8 *)(*bh)->b_data + *offset;
  38. *offset += ad_size;
  39. if (!ad)
  40. {
  41. udf_release_data(*bh);
  42. *error = 1;
  43. return NULL;
  44. }
  45. if (*offset == dir->i_sb->s_blocksize)
  46. {
  47. udf_release_data(*bh);
  48. block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos);
  49. if (!block)
  50. return NULL;
  51. if (!(*bh = udf_tread(dir->i_sb, block)))
  52. return NULL;
  53. }
  54. else if (*offset > dir->i_sb->s_blocksize)
  55. {
  56. ad = tmpad;
  57. remainder = dir->i_sb->s_blocksize - loffset;
  58. memcpy((Uint8 *)ad, (*bh)->b_data + loffset, remainder);
  59. udf_release_data(*bh);
  60. block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos);
  61. if (!block)
  62. return NULL;
  63. if (!((*bh) = udf_tread(dir->i_sb, block)))
  64. return NULL;
  65. memcpy((Uint8 *)ad + remainder, (*bh)->b_data, ad_size - remainder);
  66. *offset = ad_size - remainder;
  67. }
  68. return ad;
  69. }
  70. struct FileIdentDesc *
  71. udf_fileident_read(struct inode *dir, loff_t *nf_pos,
  72. struct udf_fileident_bh *fibh,
  73. struct FileIdentDesc *cfi,
  74. lb_addr *bloc, Uint32 *extoffset, 
  75. lb_addr *eloc, Uint32 *elen,
  76. Uint32 *offset, struct buffer_head **bh)
  77. {
  78. struct FileIdentDesc *fi;
  79. int i, num, block;
  80. struct buffer_head * tmp, * bha[16];
  81. fibh->soffset = fibh->eoffset;
  82. if (fibh->eoffset == dir->i_sb->s_blocksize)
  83. {
  84. int lextoffset = *extoffset;
  85. if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
  86. EXTENT_RECORDED_ALLOCATED)
  87. {
  88. return NULL;
  89. }
  90. block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
  91. (*offset) ++;
  92. if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
  93. *offset = 0;
  94. else
  95. *extoffset = lextoffset;
  96. udf_release_data(fibh->sbh);
  97. if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
  98. return NULL;
  99. fibh->soffset = fibh->eoffset = 0;
  100. if (!(*offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1)))
  101. {
  102. i = 16 >> (dir->i_sb->s_blocksize_bits - 9);
  103. if (i+*offset > (*elen >> dir->i_sb->s_blocksize_bits))
  104. i = (*elen >> dir->i_sb->s_blocksize_bits)-*offset;
  105. for (num=0; i>0; i--)
  106. {
  107. block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset+i);
  108. tmp = udf_tgetblk(dir->i_sb, block);
  109. if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
  110. bha[num++] = tmp;
  111. else
  112. brelse(tmp);
  113. }
  114. if (num)
  115. {
  116. ll_rw_block(READA, num, bha);
  117. for (i=0; i<num; i++)
  118. brelse(bha[i]);
  119. }
  120. }
  121. }
  122. else if (fibh->sbh != fibh->ebh)
  123. {
  124. udf_release_data(fibh->sbh);
  125. fibh->sbh = fibh->ebh;
  126. }
  127. fi = udf_get_fileident(fibh->sbh->b_data, dir->i_sb->s_blocksize,
  128. &(fibh->eoffset));
  129. if (!fi)
  130. return NULL;
  131. *nf_pos += ((fibh->eoffset - fibh->soffset) >> 2);
  132. if (fibh->eoffset <= dir->i_sb->s_blocksize)
  133. {
  134. memcpy((Uint8 *)cfi, (Uint8 *)fi, sizeof(struct FileIdentDesc));
  135. }
  136. else if (fibh->eoffset > dir->i_sb->s_blocksize)
  137. {
  138. int lextoffset = *extoffset;
  139. if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
  140. EXTENT_RECORDED_ALLOCATED)
  141. {
  142. return NULL;
  143. }
  144. block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
  145. (*offset) ++;
  146. if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
  147. *offset = 0;
  148. else
  149. *extoffset = lextoffset;
  150. fibh->soffset -= dir->i_sb->s_blocksize;
  151. fibh->eoffset -= dir->i_sb->s_blocksize;
  152. if (!(fibh->ebh = udf_tread(dir->i_sb, block)))
  153. return NULL;
  154. if (sizeof(struct FileIdentDesc) > - fibh->soffset)
  155. {
  156. int fi_len;
  157. memcpy((Uint8 *)cfi, (Uint8 *)fi, - fibh->soffset);
  158. memcpy((Uint8 *)cfi - fibh->soffset, fibh->ebh->b_data,
  159. sizeof(struct FileIdentDesc) + fibh->soffset);
  160. fi_len = (sizeof(struct FileIdentDesc) + cfi->lengthFileIdent +
  161. le16_to_cpu(cfi->lengthOfImpUse) + 3) & ~3;
  162. *nf_pos += ((fi_len - (fibh->eoffset - fibh->soffset)) >> 2);
  163. fibh->eoffset = fibh->soffset + fi_len;
  164. }
  165. else
  166. {
  167. memcpy((Uint8 *)cfi, (Uint8 *)fi, sizeof(struct FileIdentDesc));
  168. }
  169. }
  170. return fi;
  171. }
  172. #endif
  173. struct FileIdentDesc * 
  174. udf_get_fileident(void * buffer, int bufsize, int * offset)
  175. {
  176. struct FileIdentDesc *fi;
  177. int lengthThisIdent;
  178. Uint8 * ptr;
  179. int padlen;
  180. if ( (!buffer) || (!offset) ) {
  181. #ifdef __KERNEL__
  182. udf_debug("invalidparmsn, buffer=%p, offset=%pn", buffer, offset);
  183. #endif
  184. return NULL;
  185. }
  186. ptr = buffer;
  187. if ( (*offset > 0) && (*offset < bufsize) ) {
  188. ptr += *offset;
  189. }
  190. fi=(struct FileIdentDesc *)ptr;
  191. if (le16_to_cpu(fi->descTag.tagIdent) != TID_FILE_IDENT_DESC)
  192. {
  193. #ifdef __KERNEL__
  194. udf_debug("0x%x != TID_FILE_IDENT_DESCn",
  195. le16_to_cpu(fi->descTag.tagIdent));
  196. udf_debug("offset: %u sizeof: %lu bufsize: %un",
  197. *offset, (unsigned long)sizeof(struct FileIdentDesc), bufsize);
  198. #endif
  199. return NULL;
  200. }
  201. if ( (*offset + sizeof(struct FileIdentDesc)) > bufsize )
  202. {
  203. lengthThisIdent = sizeof(struct FileIdentDesc);
  204. }
  205. else
  206. lengthThisIdent = sizeof(struct FileIdentDesc) +
  207. fi->lengthFileIdent + le16_to_cpu(fi->lengthOfImpUse);
  208. /* we need to figure padding, too! */
  209. padlen = lengthThisIdent % UDF_NAME_PAD;
  210. if (padlen)
  211. lengthThisIdent += (UDF_NAME_PAD - padlen);
  212. *offset = *offset + lengthThisIdent;
  213. return fi;
  214. }
  215. extent_ad *
  216. udf_get_fileextent(void * buffer, int bufsize, int * offset)
  217. {
  218. extent_ad * ext;
  219. struct FileEntry *fe;
  220. Uint8 * ptr;
  221. if ( (!buffer) || (!offset) )
  222. {
  223. #ifdef __KERNEL__
  224. printk(KERN_ERR "udf: udf_get_fileextent() invalidparmsn");
  225. #endif
  226. return NULL;
  227. }
  228. fe = (struct FileEntry *)buffer;
  229. if ( le16_to_cpu(fe->descTag.tagIdent) != TID_FILE_ENTRY )
  230. {
  231. #ifdef __KERNEL__
  232. udf_debug("0x%x != TID_FILE_ENTRYn",
  233. le16_to_cpu(fe->descTag.tagIdent));
  234. #endif
  235. return NULL;
  236. }
  237. ptr=(Uint8 *)(fe->extendedAttr) + le32_to_cpu(fe->lengthExtendedAttr);
  238. if ( (*offset > 0) && (*offset < le32_to_cpu(fe->lengthAllocDescs)) )
  239. {
  240. ptr += *offset;
  241. }
  242. ext = (extent_ad *)ptr;
  243. *offset = *offset + sizeof(extent_ad);
  244. return ext;
  245. }
  246. short_ad *
  247. udf_get_fileshortad(void * buffer, int maxoffset, int *offset, int inc)
  248. {
  249. short_ad * sa;
  250. Uint8 * ptr;
  251. if ( (!buffer) || (!offset) )
  252. {
  253. #ifdef __KERNEL__
  254. printk(KERN_ERR "udf: udf_get_fileshortad() invalidparmsn");
  255. #endif
  256. return NULL;
  257. }
  258. ptr = (Uint8 *)buffer;
  259. if ( (*offset > 0) && (*offset < maxoffset) )
  260. ptr += *offset;
  261. else
  262. return NULL;
  263. if ((sa = (short_ad *)ptr)->extLength == 0)
  264. return NULL;
  265. else if (inc)
  266. (*offset) += sizeof(short_ad);
  267. return sa;
  268. }
  269. long_ad *
  270. udf_get_filelongad(void * buffer, int maxoffset, int * offset, int inc)
  271. {
  272. long_ad * la;
  273. Uint8 * ptr;
  274. if ( (!buffer) || !(offset) ) 
  275. {
  276. #ifdef __KERNEL__
  277. printk(KERN_ERR "udf: udf_get_filelongad() invalidparmsn");
  278. #endif
  279. return NULL;
  280. }
  281. ptr = (Uint8 *)buffer;
  282. if ( (*offset > 0) && (*offset < maxoffset) )
  283. ptr += *offset;
  284. else
  285. return NULL;
  286. if ((la = (long_ad *)ptr)->extLength == 0)
  287. return NULL;
  288. else if (inc)
  289. (*offset) += sizeof(long_ad);
  290. return la;
  291. }