3
0

irel_ma.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /*
  2. * irel_ma.c
  3. *
  4. * Copyright (C) 1996, 1997 Theodore Ts'o.
  5. *
  6. * %Begin-Header%
  7. * This file may be redistributed under the terms of the GNU Public
  8. * License.
  9. * %End-Header%
  10. */
  11. #include <fcntl.h>
  12. #include <stdio.h>
  13. #include <string.h>
  14. #if HAVE_UNISTD_H
  15. #include <unistd.h>
  16. #endif
  17. #if HAVE_ERRNO_H
  18. #include <errno.h>
  19. #endif
  20. #include "ext2_fs.h"
  21. #include "ext2fs.h"
  22. #include "irel.h"
  23. static errcode_t ima_put(ext2_irel irel, ext2_ino_t old,
  24. struct ext2_inode_relocate_entry *ent);
  25. static errcode_t ima_get(ext2_irel irel, ext2_ino_t old,
  26. struct ext2_inode_relocate_entry *ent);
  27. static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
  28. struct ext2_inode_relocate_entry *ent);
  29. static errcode_t ima_start_iter(ext2_irel irel);
  30. static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old,
  31. struct ext2_inode_relocate_entry *ent);
  32. static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino,
  33. struct ext2_inode_reference *ref);
  34. static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino);
  35. static errcode_t ima_next_ref(ext2_irel irel, struct ext2_inode_reference *ref);
  36. static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new);
  37. static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old);
  38. static errcode_t ima_free(ext2_irel irel);
  39. /*
  40. * This data structure stores the array of inode references; there is
  41. * a structure for each inode.
  42. */
  43. struct inode_reference_entry {
  44. __u16 num;
  45. struct ext2_inode_reference *refs;
  46. };
  47. struct irel_ma {
  48. __u32 magic;
  49. ext2_ino_t max_inode;
  50. ext2_ino_t ref_current;
  51. int ref_iter;
  52. ext2_ino_t *orig_map;
  53. struct ext2_inode_relocate_entry *entries;
  54. struct inode_reference_entry *ref_entries;
  55. };
  56. errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode,
  57. ext2_irel *new_irel)
  58. {
  59. ext2_irel irel = 0;
  60. errcode_t retval;
  61. struct irel_ma *ma = 0;
  62. size_t size;
  63. *new_irel = 0;
  64. /*
  65. * Allocate memory structures
  66. */
  67. retval = ext2fs_get_mem(sizeof(struct ext2_inode_relocation_table),
  68. &irel);
  69. if (retval)
  70. goto errout;
  71. memset(irel, 0, sizeof(struct ext2_inode_relocation_table));
  72. retval = ext2fs_get_mem(strlen(name)+1, &irel->name);
  73. if (retval)
  74. goto errout;
  75. strcpy(irel->name, name);
  76. retval = ext2fs_get_mem(sizeof(struct irel_ma), &ma);
  77. if (retval)
  78. goto errout;
  79. memset(ma, 0, sizeof(struct irel_ma));
  80. irel->priv_data = ma;
  81. size = (size_t) (sizeof(ext2_ino_t) * (max_inode+1));
  82. retval = ext2fs_get_mem(size, &ma->orig_map);
  83. if (retval)
  84. goto errout;
  85. memset(ma->orig_map, 0, size);
  86. size = (size_t) (sizeof(struct ext2_inode_relocate_entry) *
  87. (max_inode+1));
  88. retval = ext2fs_get_mem(size, &ma->entries);
  89. if (retval)
  90. goto errout;
  91. memset(ma->entries, 0, size);
  92. size = (size_t) (sizeof(struct inode_reference_entry) *
  93. (max_inode+1));
  94. retval = ext2fs_get_mem(size, &ma->ref_entries);
  95. if (retval)
  96. goto errout;
  97. memset(ma->ref_entries, 0, size);
  98. ma->max_inode = max_inode;
  99. /*
  100. * Fill in the irel data structure
  101. */
  102. irel->put = ima_put;
  103. irel->get = ima_get;
  104. irel->get_by_orig = ima_get_by_orig;
  105. irel->start_iter = ima_start_iter;
  106. irel->next = ima_next;
  107. irel->add_ref = ima_add_ref;
  108. irel->start_iter_ref = ima_start_iter_ref;
  109. irel->next_ref = ima_next_ref;
  110. irel->move = ima_move;
  111. irel->delete = ima_delete;
  112. irel->free = ima_free;
  113. *new_irel = irel;
  114. return 0;
  115. errout:
  116. ima_free(irel);
  117. return retval;
  118. }
  119. static errcode_t ima_put(ext2_irel irel, ext2_ino_t old,
  120. struct ext2_inode_relocate_entry *ent)
  121. {
  122. struct inode_reference_entry *ref_ent;
  123. struct irel_ma *ma;
  124. errcode_t retval;
  125. size_t size, old_size;
  126. ma = irel->priv_data;
  127. if (old > ma->max_inode)
  128. return EXT2_ET_INVALID_ARGUMENT;
  129. /*
  130. * Force the orig field to the correct value; the application
  131. * program shouldn't be messing with this field.
  132. */
  133. if (ma->entries[(unsigned) old].new == 0)
  134. ent->orig = old;
  135. else
  136. ent->orig = ma->entries[(unsigned) old].orig;
  137. /*
  138. * If max_refs has changed, reallocate the refs array
  139. */
  140. ref_ent = ma->ref_entries + (unsigned) old;
  141. if (ref_ent->refs && ent->max_refs !=
  142. ma->entries[(unsigned) old].max_refs) {
  143. size = (sizeof(struct ext2_inode_reference) * ent->max_refs);
  144. old_size = (sizeof(struct ext2_inode_reference) *
  145. ma->entries[(unsigned) old].max_refs);
  146. retval = ext2fs_resize_mem(old_size, size, &ref_ent->refs);
  147. if (retval)
  148. return retval;
  149. }
  150. ma->entries[(unsigned) old] = *ent;
  151. ma->orig_map[(unsigned) ent->orig] = old;
  152. return 0;
  153. }
  154. static errcode_t ima_get(ext2_irel irel, ext2_ino_t old,
  155. struct ext2_inode_relocate_entry *ent)
  156. {
  157. struct irel_ma *ma;
  158. ma = irel->priv_data;
  159. if (old > ma->max_inode)
  160. return EXT2_ET_INVALID_ARGUMENT;
  161. if (ma->entries[(unsigned) old].new == 0)
  162. return ENOENT;
  163. *ent = ma->entries[(unsigned) old];
  164. return 0;
  165. }
  166. static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
  167. struct ext2_inode_relocate_entry *ent)
  168. {
  169. struct irel_ma *ma;
  170. ext2_ino_t ino;
  171. ma = irel->priv_data;
  172. if (orig > ma->max_inode)
  173. return EXT2_ET_INVALID_ARGUMENT;
  174. ino = ma->orig_map[(unsigned) orig];
  175. if (ino == 0)
  176. return ENOENT;
  177. *old = ino;
  178. *ent = ma->entries[(unsigned) ino];
  179. return 0;
  180. }
  181. static errcode_t ima_start_iter(ext2_irel irel)
  182. {
  183. irel->current = 0;
  184. return 0;
  185. }
  186. static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old,
  187. struct ext2_inode_relocate_entry *ent)
  188. {
  189. struct irel_ma *ma;
  190. ma = irel->priv_data;
  191. while (++irel->current < ma->max_inode) {
  192. if (ma->entries[(unsigned) irel->current].new == 0)
  193. continue;
  194. *old = irel->current;
  195. *ent = ma->entries[(unsigned) irel->current];
  196. return 0;
  197. }
  198. *old = 0;
  199. return 0;
  200. }
  201. static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino,
  202. struct ext2_inode_reference *ref)
  203. {
  204. struct irel_ma *ma;
  205. size_t size;
  206. struct inode_reference_entry *ref_ent;
  207. struct ext2_inode_relocate_entry *ent;
  208. errcode_t retval;
  209. ma = irel->priv_data;
  210. if (ino > ma->max_inode)
  211. return EXT2_ET_INVALID_ARGUMENT;
  212. ref_ent = ma->ref_entries + (unsigned) ino;
  213. ent = ma->entries + (unsigned) ino;
  214. /*
  215. * If the inode reference array doesn't exist, create it.
  216. */
  217. if (ref_ent->refs == 0) {
  218. size = (size_t) ((sizeof(struct ext2_inode_reference) *
  219. ent->max_refs));
  220. retval = ext2fs_get_mem(size, &ref_ent->refs);
  221. if (retval)
  222. return retval;
  223. memset(ref_ent->refs, 0, size);
  224. ref_ent->num = 0;
  225. }
  226. if (ref_ent->num >= ent->max_refs)
  227. return EXT2_ET_TOO_MANY_REFS;
  228. ref_ent->refs[(unsigned) ref_ent->num++] = *ref;
  229. return 0;
  230. }
  231. static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino)
  232. {
  233. struct irel_ma *ma;
  234. ma = irel->priv_data;
  235. if (ino > ma->max_inode)
  236. return EXT2_ET_INVALID_ARGUMENT;
  237. if (ma->entries[(unsigned) ino].new == 0)
  238. return ENOENT;
  239. ma->ref_current = ino;
  240. ma->ref_iter = 0;
  241. return 0;
  242. }
  243. static errcode_t ima_next_ref(ext2_irel irel,
  244. struct ext2_inode_reference *ref)
  245. {
  246. struct irel_ma *ma;
  247. struct inode_reference_entry *ref_ent;
  248. ma = irel->priv_data;
  249. ref_ent = ma->ref_entries + ma->ref_current;
  250. if ((ref_ent->refs == NULL) ||
  251. (ma->ref_iter >= ref_ent->num)) {
  252. ref->block = 0;
  253. ref->offset = 0;
  254. return 0;
  255. }
  256. *ref = ref_ent->refs[ma->ref_iter++];
  257. return 0;
  258. }
  259. static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new)
  260. {
  261. struct irel_ma *ma;
  262. ma = irel->priv_data;
  263. if ((old > ma->max_inode) || (new > ma->max_inode))
  264. return EXT2_ET_INVALID_ARGUMENT;
  265. if (ma->entries[(unsigned) old].new == 0)
  266. return ENOENT;
  267. ma->entries[(unsigned) new] = ma->entries[(unsigned) old];
  268. if (ma->ref_entries[(unsigned) new].refs)
  269. ext2fs_free_mem(&ma->ref_entries[(unsigned) new].refs);
  270. ma->ref_entries[(unsigned) new] = ma->ref_entries[(unsigned) old];
  271. ma->entries[(unsigned) old].new = 0;
  272. ma->ref_entries[(unsigned) old].num = 0;
  273. ma->ref_entries[(unsigned) old].refs = 0;
  274. ma->orig_map[ma->entries[new].orig] = new;
  275. return 0;
  276. }
  277. static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old)
  278. {
  279. struct irel_ma *ma;
  280. ma = irel->priv_data;
  281. if (old > ma->max_inode)
  282. return EXT2_ET_INVALID_ARGUMENT;
  283. if (ma->entries[(unsigned) old].new == 0)
  284. return ENOENT;
  285. ma->entries[old].new = 0;
  286. if (ma->ref_entries[(unsigned) old].refs)
  287. ext2fs_free_mem(&ma->ref_entries[(unsigned) old].refs);
  288. ma->orig_map[ma->entries[(unsigned) old].orig] = 0;
  289. ma->ref_entries[(unsigned) old].num = 0;
  290. ma->ref_entries[(unsigned) old].refs = 0;
  291. return 0;
  292. }
  293. static errcode_t ima_free(ext2_irel irel)
  294. {
  295. struct irel_ma *ma;
  296. ext2_ino_t ino;
  297. if (!irel)
  298. return 0;
  299. ma = irel->priv_data;
  300. if (ma) {
  301. if (ma->orig_map)
  302. ext2fs_free_mem(&ma->orig_map);
  303. if (ma->entries)
  304. ext2fs_free_mem(&ma->entries);
  305. if (ma->ref_entries) {
  306. for (ino = 0; ino <= ma->max_inode; ino++) {
  307. if (ma->ref_entries[(unsigned) ino].refs)
  308. ext2fs_free_mem(&ma->ref_entries[(unsigned) ino].refs);
  309. }
  310. ext2fs_free_mem(&ma->ref_entries);
  311. }
  312. ext2fs_free_mem(&ma);
  313. }
  314. if (irel->name)
  315. ext2fs_free_mem(&irel->name);
  316. ext2fs_free_mem(&irel);
  317. return 0;
  318. }