ea.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/fs/hpfs/ea.c
  3.  *
  4.  *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
  5.  *
  6.  *  handling extended attributes
  7.  */
  8. #include <linux/string.h>
  9. #include "hpfs_fn.h"
  10. /* Remove external extended attributes. ano specifies whether a is a 
  11.    direct sector where eas starts or an anode */
  12. void hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len)
  13. {
  14. unsigned pos = 0;
  15. while (pos < len) {
  16. char ex[4 + 255 + 1 + 8];
  17. struct extended_attribute *ea = (struct extended_attribute *)ex;
  18. if (pos + 4 > len) {
  19. hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
  20. ano ? "anode" : "sectors", a, len);
  21. return;
  22. }
  23. if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return;
  24. if (ea->indirect) {
  25. if (ea->valuelen != 8) {
  26. hpfs_error(s, "ea->indirect set while ea->valuelen!=8, %s %08x, pos %08x",
  27. ano ? "anode" : "sectors", a, pos);
  28. return;
  29. }
  30. if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 9, ex+4))
  31. return;
  32. hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea));
  33. }
  34. pos += ea->namelen + ea->valuelen + 5;
  35. }
  36. if (!ano) hpfs_free_sectors(s, a, (len+511) >> 9);
  37. else {
  38. struct buffer_head *bh;
  39. struct anode *anode;
  40. if ((anode = hpfs_map_anode(s, a, &bh))) {
  41. hpfs_remove_btree(s, &anode->btree);
  42. brelse(bh);
  43. hpfs_free_sectors(s, a, 1);
  44. }
  45. }
  46. }
  47. static char *get_indirect_ea(struct super_block *s, int ano, secno a, int size)
  48. {
  49. char *ret;
  50. if (!(ret = kmalloc(size + 1, GFP_KERNEL))) {
  51. printk("HPFS: out of memory for EAn");
  52. return NULL;
  53. }
  54. if (hpfs_ea_read(s, a, ano, 0, size, ret)) {
  55. kfree(ret);
  56. return NULL;
  57. }
  58. ret[size] = 0;
  59. return ret;
  60. }
  61. static void set_indirect_ea(struct super_block *s, int ano, secno a, char *data,
  62.     int size)
  63. {
  64. hpfs_ea_write(s, a, ano, 0, size, data);
  65. }
  66. /* Read an extended attribute named 'key' into the provided buffer */
  67. int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,
  68. char *buf, int size)
  69. {
  70. unsigned pos;
  71. int ano, len;
  72. secno a;
  73. struct extended_attribute *ea;
  74. struct extended_attribute *ea_end = fnode_end_ea(fnode);
  75. for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
  76. if (!strcmp(ea->name, key)) {
  77. if (ea->indirect)
  78. goto indirect;
  79. if (ea->valuelen >= size)
  80. return -EINVAL;
  81. memcpy(buf, ea_data(ea), ea->valuelen);
  82. buf[ea->valuelen] = 0;
  83. return 0;
  84. }
  85. a = fnode->ea_secno;
  86. len = fnode->ea_size_l;
  87. ano = fnode->ea_anode;
  88. pos = 0;
  89. while (pos < len) {
  90. char ex[4 + 255 + 1 + 8];
  91. ea = (struct extended_attribute *)ex;
  92. if (pos + 4 > len) {
  93. hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
  94. ano ? "anode" : "sectors", a, len);
  95. return -EIO;
  96. }
  97. if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return -EIO;
  98. if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4))
  99. return -EIO;
  100. if (!strcmp(ea->name, key)) {
  101. if (ea->indirect)
  102. goto indirect;
  103. if (ea->valuelen >= size)
  104. return -EINVAL;
  105. if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea->valuelen, buf))
  106. return -EIO;
  107. buf[ea->valuelen] = 0;
  108. return 0;
  109. }
  110. pos += ea->namelen + ea->valuelen + 5;
  111. }
  112. return -ENOENT;
  113. indirect:
  114. if (ea_len(ea) >= size)
  115. return -EINVAL;
  116. if (hpfs_ea_read(s, ea_sec(ea), ea->anode, 0, ea_len(ea), buf))
  117. return -EIO;
  118. buf[ea_len(ea)] = 0;
  119. return 0;
  120. }
  121. /* Read an extended attribute named 'key' */
  122. char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *size)
  123. {
  124. char *ret;
  125. unsigned pos;
  126. int ano, len;
  127. secno a;
  128. struct extended_attribute *ea;
  129. struct extended_attribute *ea_end = fnode_end_ea(fnode);
  130. for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
  131. if (!strcmp(ea->name, key)) {
  132. if (ea->indirect)
  133. return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea));
  134. if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_KERNEL))) {
  135. printk("HPFS: out of memory for EAn");
  136. return NULL;
  137. }
  138. memcpy(ret, ea_data(ea), ea->valuelen);
  139. ret[ea->valuelen] = 0;
  140. return ret;
  141. }
  142. a = fnode->ea_secno;
  143. len = fnode->ea_size_l;
  144. ano = fnode->ea_anode;
  145. pos = 0;
  146. while (pos < len) {
  147. char ex[4 + 255 + 1 + 8];
  148. ea = (struct extended_attribute *)ex;
  149. if (pos + 4 > len) {
  150. hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
  151. ano ? "anode" : "sectors", a, len);
  152. return NULL;
  153. }
  154. if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return NULL;
  155. if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4))
  156. return NULL;
  157. if (!strcmp(ea->name, key)) {
  158. if (ea->indirect)
  159. return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea));
  160. if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_KERNEL))) {
  161. printk("HPFS: out of memory for EAn");
  162. return NULL;
  163. }
  164. if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea->valuelen, ret)) {
  165. kfree(ret);
  166. return NULL;
  167. }
  168. ret[ea->valuelen] = 0;
  169. return ret;
  170. }
  171. pos += ea->namelen + ea->valuelen + 5;
  172. }
  173. return NULL;
  174. }
  175. /* 
  176.  * Update or create extended attribute 'key' with value 'data'. Note that
  177.  * when this ea exists, it MUST have the same size as size of data.
  178.  * This driver can't change sizes of eas ('cause I just don't need it).
  179.  */
  180. void hpfs_set_ea(struct inode *inode, struct fnode *fnode, char *key, char *data, int size)
  181. {
  182. fnode_secno fno = inode->i_ino;
  183. struct super_block *s = inode->i_sb;
  184. unsigned pos;
  185. int ano, len;
  186. secno a;
  187. unsigned char h[4];
  188. struct extended_attribute *ea;
  189. struct extended_attribute *ea_end = fnode_end_ea(fnode);
  190. for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
  191. if (!strcmp(ea->name, key)) {
  192. if (ea->indirect) {
  193. if (ea_len(ea) == size)
  194. set_indirect_ea(s, ea->anode, ea_sec(ea), data, size);
  195. } else if (ea->valuelen == size) {
  196. memcpy(ea_data(ea), data, size);
  197. }
  198. return;
  199. }
  200. a = fnode->ea_secno;
  201. len = fnode->ea_size_l;
  202. ano = fnode->ea_anode;
  203. pos = 0;
  204. while (pos < len) {
  205. char ex[4 + 255 + 1 + 8];
  206. ea = (struct extended_attribute *)ex;
  207. if (pos + 4 > len) {
  208. hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
  209. ano ? "anode" : "sectors", a, len);
  210. return;
  211. }
  212. if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return;
  213. if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4))
  214. return;
  215. if (!strcmp(ea->name, key)) {
  216. if (ea->indirect) {
  217. if (ea_len(ea) == size)
  218. set_indirect_ea(s, ea->anode, ea_sec(ea), data, size);
  219. }
  220. else {
  221. if (ea->valuelen == size)
  222. hpfs_ea_write(s, a, ano, pos + 4 + ea->namelen + 1, size, data);
  223. }
  224. return;
  225. }
  226. pos += ea->namelen + ea->valuelen + 5;
  227. }
  228. if (!fnode->ea_size_s) {
  229. /*if (fnode->ea_size_s) {
  230. hpfs_error(s, "fnode %08x: ea_size_s == %03x, ea_offs == 0",
  231. inode->i_ino, fnode->ea_size_s);
  232. return;
  233. }*/
  234. fnode->ea_offs = 0xc4;
  235. }
  236. if (fnode->ea_offs < 0xc4 || fnode->ea_offs + fnode->ea_size_s > 0x200) {
  237. hpfs_error(s, "fnode %08x: ea_offs == %03x, ea_size_s == %03x",
  238. inode->i_ino, fnode->ea_offs, fnode->ea_size_s);
  239. return;
  240. }
  241. if ((fnode->ea_size_s || !fnode->ea_size_l) &&
  242.      fnode->ea_offs + fnode->ea_size_s + strlen(key) + size + 5 <= 0x200) {
  243. /* I'm not sure ... maybe we overwrite ACL here. I have no info
  244.    on it right now :-( */
  245. ea = fnode_end_ea(fnode);
  246. *(char *)ea = 0;
  247. ea->namelen = strlen(key);
  248. ea->valuelen = size;
  249. strcpy(ea->name, key);
  250. memcpy(ea_data(ea), data, size);
  251. fnode->ea_size_s += strlen(key) + size + 5;
  252. goto ret;
  253. }
  254. /* Most the code here is 99.9993422% unused. I hope there are no bugs.
  255.    But what .. HPFS.IFS has also bugs in ea management. */
  256. if (fnode->ea_size_s && !fnode->ea_size_l) {
  257. secno n;
  258. struct buffer_head *bh;
  259. char *data;
  260. if (!(n = hpfs_alloc_sector(s, fno, 1, 0, 1))) return;
  261. if (!(data = hpfs_get_sector(s, n, &bh))) {
  262. hpfs_free_sectors(s, n, 1);
  263. return;
  264. }
  265. memcpy(data, fnode_ea(fnode), fnode->ea_size_s);
  266. fnode->ea_size_l = fnode->ea_size_s;
  267. fnode->ea_size_s = 0;
  268. fnode->ea_secno = n;
  269. fnode->ea_anode = 0;
  270. mark_buffer_dirty(bh);
  271. brelse(bh);
  272. }
  273. pos = fnode->ea_size_l + 5 + strlen(key) + size;
  274. len = (fnode->ea_size_l + 511) >> 9;
  275. if (pos >= 30000) goto bail;
  276. while (((pos + 511) >> 9) > len) {
  277. if (!len) {
  278. if (!(fnode->ea_secno = hpfs_alloc_sector(s, fno, 1, 0, 1)))
  279. goto bail;
  280. fnode->ea_anode = 0;
  281. len++;
  282. } else if (!fnode->ea_anode) {
  283. if (hpfs_alloc_if_possible(s, fnode->ea_secno + len)) {
  284. len++;
  285. } else {
  286. /* Aargh... don't know how to create ea anodes :-( */
  287. /*struct buffer_head *bh;
  288. struct anode *anode;
  289. anode_secno a_s;
  290. if (!(anode = hpfs_alloc_anode(s, fno, &a_s, &bh)))
  291. goto bail;
  292. anode->up = fno;
  293. anode->btree.fnode_parent = 1;
  294. anode->btree.n_free_nodes--;
  295. anode->btree.n_used_nodes++;
  296. anode->btree.first_free += 12;
  297. anode->u.external[0].disk_secno = fnode->ea_secno;
  298. anode->u.external[0].file_secno = 0;
  299. anode->u.external[0].length = len;
  300. mark_buffer_dirty(bh);
  301. brelse(bh);
  302. fnode->ea_anode = 1;
  303. fnode->ea_secno = a_s;*/
  304. secno new_sec;
  305. int i;
  306. if (!(new_sec = hpfs_alloc_sector(s, fno, 1, 1 - ((pos + 511) >> 9), 1)))
  307. goto bail;
  308. for (i = 0; i < len; i++) {
  309. struct buffer_head *bh1, *bh2;
  310. void *b1, *b2;
  311. if (!(b1 = hpfs_map_sector(s, fnode->ea_secno + i, &bh1, len - i - 1))) {
  312. hpfs_free_sectors(s, new_sec, (pos + 511) >> 9);
  313. goto bail;
  314. }
  315. if (!(b2 = hpfs_get_sector(s, new_sec + i, &bh2))) {
  316. brelse(bh1);
  317. hpfs_free_sectors(s, new_sec, (pos + 511) >> 9);
  318. goto bail;
  319. }
  320. memcpy(b2, b1, 512);
  321. brelse(bh1);
  322. mark_buffer_dirty(bh2);
  323. brelse(bh2);
  324. }
  325. hpfs_free_sectors(s, fnode->ea_secno, len);
  326. fnode->ea_secno = new_sec;
  327. len = (pos + 511) >> 9;
  328. }
  329. }
  330. if (fnode->ea_anode) {
  331. if (hpfs_add_sector_to_btree(s, fnode->ea_secno,
  332.      0, len) != -1) {
  333. len++;
  334. } else {
  335. goto bail;
  336. }
  337. }
  338. }
  339. h[0] = 0;
  340. h[1] = strlen(key);
  341. h[2] = size & 0xff;
  342. h[3] = size >> 8;
  343. if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l, 4, h)) goto bail;
  344. if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l + 4, h[1] + 1, key)) goto bail;
  345. if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l + 5 + h[1], size, data)) goto bail;
  346. fnode->ea_size_l = pos;
  347. ret:
  348. inode->i_hpfs_ea_size += 5 + strlen(key) + size;
  349. return;
  350. bail:
  351. if (fnode->ea_secno)
  352. if (fnode->ea_anode) hpfs_truncate_btree(s, fnode->ea_secno, 1, (fnode->ea_size_l + 511) >> 9);
  353. else hpfs_free_sectors(s, fnode->ea_secno + ((fnode->ea_size_l + 511) >> 9), len - ((fnode->ea_size_l + 511) >> 9));
  354. else fnode->ea_secno = fnode->ea_size_l = 0;
  355. }