irel_ma.c 8.6 KB

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