misc.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. * misc.c
  3. *
  4. * PURPOSE
  5. * Miscellaneous routines for the OSTA-UDF(tm) filesystem.
  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. * (C) 1998 Dave Boynton
  19. * (C) 1998-2004 Ben Fennema
  20. * (C) 1999-2000 Stelias Computing Inc
  21. *
  22. * HISTORY
  23. *
  24. * 04/19/99 blf partial support for reading/writing specific EA's
  25. */
  26. #include "udfdecl.h"
  27. #include <linux/fs.h>
  28. #include <linux/string.h>
  29. #include <linux/udf_fs.h>
  30. #include <linux/buffer_head.h>
  31. #include "udf_i.h"
  32. #include "udf_sb.h"
  33. struct buffer_head *
  34. udf_tgetblk(struct super_block *sb, int block)
  35. {
  36. if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
  37. return sb_getblk(sb, udf_fixed_to_variable(block));
  38. else
  39. return sb_getblk(sb, block);
  40. }
  41. struct buffer_head *
  42. udf_tread(struct super_block *sb, int block)
  43. {
  44. if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
  45. return sb_bread(sb, udf_fixed_to_variable(block));
  46. else
  47. return sb_bread(sb, block);
  48. }
  49. struct genericFormat *
  50. udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type,
  51. uint8_t loc)
  52. {
  53. uint8_t *ea = NULL, *ad = NULL;
  54. int offset;
  55. uint16_t crclen;
  56. int i;
  57. ea = UDF_I_DATA(inode);
  58. if (UDF_I_LENEATTR(inode))
  59. ad = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
  60. else
  61. {
  62. ad = ea;
  63. size += sizeof(struct extendedAttrHeaderDesc);
  64. }
  65. offset = inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode) -
  66. UDF_I_LENALLOC(inode);
  67. /* TODO - Check for FreeEASpace */
  68. if (loc & 0x01 && offset >= size)
  69. {
  70. struct extendedAttrHeaderDesc *eahd;
  71. eahd = (struct extendedAttrHeaderDesc *)ea;
  72. if (UDF_I_LENALLOC(inode))
  73. {
  74. memmove(&ad[size], ad, UDF_I_LENALLOC(inode));
  75. }
  76. if (UDF_I_LENEATTR(inode))
  77. {
  78. /* check checksum/crc */
  79. if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD ||
  80. le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum)
  81. {
  82. return NULL;
  83. }
  84. }
  85. else
  86. {
  87. size -= sizeof(struct extendedAttrHeaderDesc);
  88. UDF_I_LENEATTR(inode) += sizeof(struct extendedAttrHeaderDesc);
  89. eahd->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EAHD);
  90. if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200)
  91. eahd->descTag.descVersion = cpu_to_le16(3);
  92. else
  93. eahd->descTag.descVersion = cpu_to_le16(2);
  94. eahd->descTag.tagSerialNum = cpu_to_le16(UDF_SB_SERIALNUM(inode->i_sb));
  95. eahd->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
  96. eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF);
  97. eahd->appAttrLocation = cpu_to_le32(0xFFFFFFFF);
  98. }
  99. offset = UDF_I_LENEATTR(inode);
  100. if (type < 2048)
  101. {
  102. if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode))
  103. {
  104. uint32_t aal = le32_to_cpu(eahd->appAttrLocation);
  105. memmove(&ea[offset - aal + size],
  106. &ea[aal], offset - aal);
  107. offset -= aal;
  108. eahd->appAttrLocation = cpu_to_le32(aal + size);
  109. }
  110. if (le32_to_cpu(eahd->impAttrLocation) < UDF_I_LENEATTR(inode))
  111. {
  112. uint32_t ial = le32_to_cpu(eahd->impAttrLocation);
  113. memmove(&ea[offset - ial + size],
  114. &ea[ial], offset - ial);
  115. offset -= ial;
  116. eahd->impAttrLocation = cpu_to_le32(ial + size);
  117. }
  118. }
  119. else if (type < 65536)
  120. {
  121. if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode))
  122. {
  123. uint32_t aal = le32_to_cpu(eahd->appAttrLocation);
  124. memmove(&ea[offset - aal + size],
  125. &ea[aal], offset - aal);
  126. offset -= aal;
  127. eahd->appAttrLocation = cpu_to_le32(aal + size);
  128. }
  129. }
  130. /* rewrite CRC + checksum of eahd */
  131. crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(tag);
  132. eahd->descTag.descCRCLength = cpu_to_le16(crclen);
  133. eahd->descTag.descCRC = cpu_to_le16(udf_crc((char *)eahd + sizeof(tag), crclen, 0));
  134. eahd->descTag.tagChecksum = 0;
  135. for (i=0; i<16; i++)
  136. if (i != 4)
  137. eahd->descTag.tagChecksum += ((uint8_t *)&(eahd->descTag))[i];
  138. UDF_I_LENEATTR(inode) += size;
  139. return (struct genericFormat *)&ea[offset];
  140. }
  141. if (loc & 0x02)
  142. {
  143. }
  144. return NULL;
  145. }
  146. struct genericFormat *
  147. udf_get_extendedattr(struct inode *inode, uint32_t type, uint8_t subtype)
  148. {
  149. struct genericFormat *gaf;
  150. uint8_t *ea = NULL;
  151. uint32_t offset;
  152. ea = UDF_I_DATA(inode);
  153. if (UDF_I_LENEATTR(inode))
  154. {
  155. struct extendedAttrHeaderDesc *eahd;
  156. eahd = (struct extendedAttrHeaderDesc *)ea;
  157. /* check checksum/crc */
  158. if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD ||
  159. le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum)
  160. {
  161. return NULL;
  162. }
  163. if (type < 2048)
  164. offset = sizeof(struct extendedAttrHeaderDesc);
  165. else if (type < 65536)
  166. offset = le32_to_cpu(eahd->impAttrLocation);
  167. else
  168. offset = le32_to_cpu(eahd->appAttrLocation);
  169. while (offset < UDF_I_LENEATTR(inode))
  170. {
  171. gaf = (struct genericFormat *)&ea[offset];
  172. if (le32_to_cpu(gaf->attrType) == type && gaf->attrSubtype == subtype)
  173. return gaf;
  174. else
  175. offset += le32_to_cpu(gaf->attrLength);
  176. }
  177. }
  178. return NULL;
  179. }
  180. /*
  181. * udf_read_tagged
  182. *
  183. * PURPOSE
  184. * Read the first block of a tagged descriptor.
  185. *
  186. * HISTORY
  187. * July 1, 1997 - Andrew E. Mileski
  188. * Written, tested, and released.
  189. */
  190. struct buffer_head *
  191. udf_read_tagged(struct super_block *sb, uint32_t block, uint32_t location, uint16_t *ident)
  192. {
  193. tag *tag_p;
  194. struct buffer_head *bh = NULL;
  195. register uint8_t checksum;
  196. register int i;
  197. /* Read the block */
  198. if (block == 0xFFFFFFFF)
  199. return NULL;
  200. bh = udf_tread(sb, block + UDF_SB_SESSION(sb));
  201. if (!bh)
  202. {
  203. udf_debug("block=%d, location=%d: read failed\n", block + UDF_SB_SESSION(sb), location);
  204. return NULL;
  205. }
  206. tag_p = (tag *)(bh->b_data);
  207. *ident = le16_to_cpu(tag_p->tagIdent);
  208. if ( location != le32_to_cpu(tag_p->tagLocation) )
  209. {
  210. udf_debug("location mismatch block %u, tag %u != %u\n",
  211. block + UDF_SB_SESSION(sb), le32_to_cpu(tag_p->tagLocation), location);
  212. goto error_out;
  213. }
  214. /* Verify the tag checksum */
  215. checksum = 0U;
  216. for (i = 0; i < 4; i++)
  217. checksum += (uint8_t)(bh->b_data[i]);
  218. for (i = 5; i < 16; i++)
  219. checksum += (uint8_t)(bh->b_data[i]);
  220. if (checksum != tag_p->tagChecksum) {
  221. printk(KERN_ERR "udf: tag checksum failed block %d\n", block);
  222. goto error_out;
  223. }
  224. /* Verify the tag version */
  225. if (le16_to_cpu(tag_p->descVersion) != 0x0002U &&
  226. le16_to_cpu(tag_p->descVersion) != 0x0003U)
  227. {
  228. udf_debug("tag version 0x%04x != 0x0002 || 0x0003 block %d\n",
  229. le16_to_cpu(tag_p->descVersion), block);
  230. goto error_out;
  231. }
  232. /* Verify the descriptor CRC */
  233. if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize ||
  234. le16_to_cpu(tag_p->descCRC) == udf_crc(bh->b_data + sizeof(tag),
  235. le16_to_cpu(tag_p->descCRCLength), 0))
  236. {
  237. return bh;
  238. }
  239. udf_debug("Crc failure block %d: crc = %d, crclen = %d\n",
  240. block + UDF_SB_SESSION(sb), le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
  241. error_out:
  242. brelse(bh);
  243. return NULL;
  244. }
  245. struct buffer_head *
  246. udf_read_ptagged(struct super_block *sb, kernel_lb_addr loc, uint32_t offset, uint16_t *ident)
  247. {
  248. return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset),
  249. loc.logicalBlockNum + offset, ident);
  250. }
  251. void udf_release_data(struct buffer_head *bh)
  252. {
  253. if (bh)
  254. brelse(bh);
  255. }
  256. void udf_update_tag(char *data, int length)
  257. {
  258. tag *tptr = (tag *)data;
  259. int i;
  260. length -= sizeof(tag);
  261. tptr->tagChecksum = 0;
  262. tptr->descCRCLength = cpu_to_le16(length);
  263. tptr->descCRC = cpu_to_le16(udf_crc(data + sizeof(tag), length, 0));
  264. for (i=0; i<16; i++)
  265. if (i != 4)
  266. tptr->tagChecksum += (uint8_t)(data[i]);
  267. }
  268. void udf_new_tag(char *data, uint16_t ident, uint16_t version, uint16_t snum,
  269. uint32_t loc, int length)
  270. {
  271. tag *tptr = (tag *)data;
  272. tptr->tagIdent = cpu_to_le16(ident);
  273. tptr->descVersion = cpu_to_le16(version);
  274. tptr->tagSerialNum = cpu_to_le16(snum);
  275. tptr->tagLocation = cpu_to_le32(loc);
  276. udf_update_tag(data, length);
  277. }