/libfaith.h

https://github.com/yaku/Faith · C Header · 453 lines · 289 code · 155 blank · 9 comment · 56 complexity · 0f21d2393630c91043e1333918d903f8 MD5 · raw file

  1. /*
  2. * Immersion theory library.
  3. *
  4. * Copyright (C) 2010 Denis Yakunchikov <toi.yaku@gmail.com>
  5. *
  6. * This file is licensed under GPLv3.
  7. *
  8. */
  9. /* Globals. Need fix */
  10. int space1fd;
  11. int space2fd;
  12. void gamma_cipher(uchar *out, uchar *in, uchar *key, int len)
  13. {
  14. while(len--)
  15. *out++ = *in++ ^ *key++;
  16. }
  17. void archive2skey(uchar *buffer, off_t *skey, uint skeysize)
  18. {
  19. int i = 0;
  20. for (i = 0; i < skeysize; i++)
  21. memcpy(skey + i, buffer + i * SKEYRECORDSIZE, SKEYRECORDSIZE);
  22. }
  23. void skey2archive(off_t *skey, uchar *buffer, uint skeysize)
  24. {
  25. int i = 0;
  26. for (i = 0; i < skeysize; i++)
  27. memcpy(buffer + i * SKEYRECORDSIZE, skey + i, SKEYRECORDSIZE);
  28. }
  29. void write_data(int destination_file, uchar *block, off_t length, off_t address)
  30. {
  31. extern int errno;
  32. lseek(destination_file, address, SEEK_SET);
  33. trusted_write(destination_file, block, length);
  34. }
  35. void read_data(struct device *dev, uchar *block, uint length, off_t address)
  36. {
  37. extern int errno;
  38. lseek(dev->descriptor, address, SEEK_SET);
  39. int bytes_read = 0;
  40. while (length) {
  41. if ((bytes_read = read(dev->descriptor, block, length)) < 0) {
  42. if (errno == EINTR)
  43. continue;
  44. else
  45. pdie("Read failed");
  46. }
  47. length -= bytes_read;
  48. block += bytes_read;
  49. }
  50. }
  51. void write_skey(struct device *dev, int skeyfile, uint skeylen, off_t address)
  52. {
  53. lseek(dev->descriptor, address, SEEK_SET);
  54. lseek(skeyfile, 0, SEEK_SET);
  55. copy(skeyfile, dev->descriptor, skeylen * SKEYRECORDSIZE);
  56. }
  57. struct space {
  58. off_t begin;
  59. off_t end;
  60. };
  61. int off_t_cmp(const void *long1, const void *long2)
  62. {
  63. if (*((off_t *) long1) > *((off_t *) long2))
  64. return 1;
  65. else if (*((off_t *) long1) == *((off_t *) long1))
  66. return 0;
  67. else
  68. return -1;
  69. }
  70. int uint_cmp(const void *uint1, const void *uint2)
  71. {
  72. if (*((uint *) uint1) > *((uint *) uint2))
  73. return 1;
  74. else if (*((uint *) uint1) == *((uint *) uint2))
  75. return 0;
  76. else
  77. return -1;
  78. }
  79. int int_cmp(const void *int1, const void *int2)
  80. {
  81. return *((int *) int2) - *((int *) int1);
  82. }
  83. void read_space(int spacefile, uint index, struct space *outspace)
  84. {
  85. uchar *buffer = calloc(SKEYRECORDSIZE * 2, 1);
  86. if (pread(spacefile, buffer, SKEYRECORDSIZE * 2,
  87. index * SKEYRECORDSIZE * 2) < 0)
  88. pdie("Read failed");
  89. archive2skey(buffer, &(outspace->begin), 1);
  90. archive2skey(buffer + SKEYRECORDSIZE, &(outspace->end), 1);
  91. free(buffer);
  92. }
  93. void rewrite_space(int *spacefile, uint *used, off_t *skey, int lastused,
  94. int blocksize)
  95. {
  96. extern int space1fd;
  97. extern int space2fd;
  98. int newspacefile;
  99. if (*spacefile == space1fd) {
  100. if (ftruncate(space2fd, 0) < 0)
  101. pdie("Truncate failed");
  102. newspacefile = space2fd;
  103. } else {
  104. if (ftruncate(space1fd, 0) < 0)
  105. pdie("Truncate failed");
  106. newspacefile = space1fd;
  107. }
  108. uchar *buffer = calloc(2 * SKEYRECORDSIZE * BUFFERED_BLOCKS, 1);
  109. uchar *skeyarchive = calloc(2 * SKEYRECORDSIZE, 1);
  110. int lastwritten_bytes = 0;
  111. int towrite = 0;
  112. struct space newspace;
  113. lseek(*spacefile, 0, SEEK_SET);
  114. lseek(newspacefile, 0, SEEK_SET);
  115. while (lastused--) {
  116. towrite = *used - lastwritten_bytes;
  117. copy(*spacefile, newspacefile, towrite * 2 * SKEYRECORDSIZE);
  118. if (read(*spacefile, buffer, 2 * SKEYRECORDSIZE) < 0)
  119. pdie("Read failed");
  120. archive2skey(buffer, &(newspace.begin), 1);
  121. newspace.end = *skey;
  122. if (newspace.end > (newspace.begin + BLOCKSIZE)) {
  123. skey2archive(&(newspace.begin), skeyarchive, 1);
  124. skey2archive(&(newspace.end), skeyarchive + SKEYRECORDSIZE, 1);
  125. trusted_write(newspacefile, skeyarchive, 2 * SKEYRECORDSIZE);
  126. }
  127. newspace.begin = *skey + blocksize;
  128. archive2skey(buffer + SKEYRECORDSIZE, &(newspace.end), 1);
  129. if (newspace.end > (newspace.begin + BLOCKSIZE)) {
  130. skey2archive(&(newspace.begin), skeyarchive, 1);
  131. skey2archive(&(newspace.end), skeyarchive + SKEYRECORDSIZE, 1);
  132. trusted_write(newspacefile, skeyarchive, 2 * SKEYRECORDSIZE);
  133. }
  134. lastwritten_bytes = *used + 1;
  135. used++;
  136. skey++;
  137. }
  138. int readbytes;
  139. while ((readbytes = read(*spacefile, buffer,
  140. 2 * SKEYRECORDSIZE * BUFFERED_BLOCKS))) {
  141. if (readbytes < 0)
  142. pdie("Read failed");
  143. trusted_write(newspacefile, buffer, readbytes);
  144. }
  145. *spacefile = newspacefile;
  146. free(buffer);
  147. free(skeyarchive);
  148. }
  149. off_t get_skey_in_space(struct space *activespace, int blocksize)
  150. {
  151. uint random_space_offset = 0;
  152. int found = 0;
  153. off_t result = 0;
  154. uint max_offset = activespace->end - activespace->begin; /*potential error uint*/
  155. while (!found) {
  156. random_space_offset = rand() % max_offset;
  157. if (activespace->end >
  158. (activespace->begin + random_space_offset + blocksize)) {
  159. result = activespace->begin + random_space_offset;
  160. found = 1;
  161. } else {
  162. max_offset = random_space_offset;
  163. }
  164. }
  165. return result;
  166. }
  167. int simple_search(uint key, uint *array, int maxindex)
  168. {
  169. int i;
  170. for (i = 0; i < maxindex; i++)
  171. if (array[i] == key)
  172. return 1;
  173. return 0;
  174. }
  175. uint calc_spaces(int spacefile)
  176. {
  177. uint spaces = ffile_size(spacefile) / (SKEYRECORDSIZE * 2);
  178. if (spaces == 0) {
  179. printf("Input is too big for this device\nExiting.\n");
  180. exit(1);
  181. }
  182. return spaces;
  183. }
  184. void make_skey(int *spacefile, off_t *skey, uint keysize, int blocksize)
  185. {
  186. uint spaces = calc_spaces(*spacefile);
  187. uint *usedids = calloc(keysize, sizeof(uint));
  188. int i;
  189. for (i = 0; i < keysize; i++)
  190. *(usedids + i) = (uint) -1;
  191. int lastused = 0;
  192. off_t *sortedskey = calloc(keysize, 8);
  193. struct space newspace = {0, 0};
  194. uint newspaceid = 0;
  195. uint completed = 0;
  196. int level = 0;
  197. while (completed < keysize) {
  198. newspaceid = rand() % spaces;
  199. if (simple_search(newspaceid, usedids, lastused + 1) == 0) {
  200. read_space(*spacefile, newspaceid, &newspace);
  201. if (newspace.end > (newspace.begin + blocksize)) {
  202. *(skey + lastused) = get_skey_in_space(&newspace,
  203. blocksize);
  204. *(usedids + lastused) = newspaceid;
  205. lastused++;
  206. completed++;
  207. level = 0;
  208. spaces--;
  209. }
  210. } else {
  211. level += 1;
  212. }
  213. if ((spaces == 0) || (level == MAXLEVEL)) {
  214. qsort(usedids, lastused, sizeof(uint), uint_cmp);
  215. memcpy(sortedskey, skey, lastused * 8); /**/
  216. qsort(sortedskey, lastused, 8, off_t_cmp);
  217. rewrite_space(spacefile, usedids, sortedskey, lastused,
  218. blocksize);
  219. skey += lastused;
  220. spaces = calc_spaces(*spacefile);
  221. for (i = 0; i < lastused; i++)
  222. *(usedids + i) = (uint) -1;
  223. lastused = 0;
  224. }
  225. }
  226. if (lastused != 0) {
  227. qsort(usedids, lastused, sizeof(uint), uint_cmp);
  228. memcpy(sortedskey, skey, lastused * 8); /**/
  229. qsort(sortedskey, lastused, 8, off_t_cmp);
  230. rewrite_space(spacefile, usedids, sortedskey, lastused, blocksize);
  231. }
  232. free(usedids);
  233. free(sortedskey);
  234. }
  235. void make_skey_main(int *spacefile, int skeyfile, uint keysize)
  236. {
  237. off_t *skey = calloc(BUFFERED_BLOCKS, 8);
  238. uchar *buffer = calloc(BUFFERED_BLOCKS * SKEYRECORDSIZE, 1);
  239. int to_make;
  240. while (keysize) {
  241. to_make = MIN(keysize, BUFFERED_BLOCKS);
  242. make_skey(spacefile, skey, to_make, BLOCKSIZE);
  243. skey2archive(skey, buffer, to_make);
  244. trusted_write(skeyfile, buffer, to_make * SKEYRECORDSIZE);
  245. keysize -= to_make;
  246. }
  247. free(buffer);
  248. free(skey);
  249. }
  250. off_t buffer_for_skey(int *spacefile, uint skeylen)
  251. {
  252. off_t result = 0;
  253. make_skey(spacefile, &result, 1, skeylen * SKEYRECORDSIZE);
  254. return result;
  255. }
  256. void write_by_skey(struct device *dev, int datafile, int skeyfile, uint blocks)
  257. {
  258. off_t *skey = calloc(BUFFERED_BLOCKS, 8);
  259. uchar *buffer = calloc(BUFFERED_BLOCKS * SKEYRECORDSIZE, 1);
  260. uchar *block = calloc(BLOCKSIZE * BUFFERED_BLOCKS, 1);
  261. int i, to_write;
  262. while (blocks) {
  263. to_write = MIN(blocks, BUFFERED_BLOCKS);
  264. if (read(skeyfile, buffer, SKEYRECORDSIZE * to_write) < 0)
  265. pdie("Read failed");
  266. archive2skey(buffer, skey, to_write);
  267. if (read(datafile, block, BLOCKSIZE * to_write) < 0)
  268. pdie("Read failed");
  269. for (i = 0; i < to_write; i++)
  270. write_data(dev->descriptor, block + i * BLOCKSIZE,
  271. BLOCKSIZE, *(skey + i));
  272. blocks -= to_write;
  273. }
  274. free(skey);
  275. free(buffer);
  276. free(block);
  277. }
  278. void get_data(struct device *dev, int datafile, off_t skeyaddress, uint keysize)
  279. {
  280. off_t *skey = calloc(BUFFERED_BLOCKS, 8);
  281. uchar *buffer = calloc(BUFFERED_BLOCKS * SKEYRECORDSIZE, 1);
  282. uchar *block = calloc(BLOCKSIZE * BUFFERED_BLOCKS, 1);
  283. int i, to_read;
  284. while (keysize) {
  285. to_read = MIN(keysize, BUFFERED_BLOCKS);
  286. read_data(dev, buffer, to_read * SKEYRECORDSIZE, skeyaddress);
  287. archive2skey(buffer, skey, to_read);
  288. for (i = 0; i < to_read; i++)
  289. read_data(dev, block + i * BLOCKSIZE, BLOCKSIZE, *(skey + i));
  290. if (write(datafile, block, BLOCKSIZE * to_read) < 0)
  291. pdie("Write failed");
  292. skeyaddress += to_read * SKEYRECORDSIZE;
  293. keysize -= to_read;
  294. }
  295. free(skey);
  296. free(buffer);
  297. free(block);
  298. }