examine.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. /* This file is part of ilk.
  2. *
  3. * Ilk is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU Lesser General Public License as published by
  5. * the Free Software Foundation, either version 3 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * Ilk is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU Lesser General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public License
  14. * along with ilk. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include <dirent.h>
  17. #include <fcntl.h>
  18. #include <inttypes.h>
  19. #include <rid.h>
  20. #include <stdint.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #define STYLE_9
  25. #include <fn85.h>
  26. #include <rid_fn85.h>
  27. #include <unfy/unfy.h>
  28. #include <rls/rls.h>
  29. #include <rls/rlsp.h>
  30. #define NIT_SHORT_NAMES
  31. #include <nit/list.h>
  32. #include <nit/set.h>
  33. #include <nit/map.h>
  34. #include <nit/err.h>
  35. #include <nit/file.h>
  36. #include <nit/buf.h>
  37. #include <nit/gap.h>
  38. #include "utilize.h"
  39. #include "examine.h"
  40. void
  41. ilk_rule_path(Ilk_rule_path path, const Rid id)
  42. {
  43. memcpy(path, "rules/", sizeof("rules/") - 1);
  44. rid_fn85_path(path + sizeof("rules/") - 1, id);
  45. }
  46. void
  47. ilk_meta_path(Ilk_meta_path path, const Rid id)
  48. {
  49. memcpy(path, "metas/", sizeof("metas/") - 1);
  50. rid_fn85_path(path + sizeof("metas/") - 1, id);
  51. }
  52. void
  53. ilk_srch_path(Ilk_srch_path path, uint64_t srch_cnt)
  54. {
  55. char num_str[21];
  56. /* 6 + 2 + 1 + 20 + 9 + 1 = 38 */
  57. /* srchs/ + digit num + / + digits + / for every 2 digits + \0 */
  58. /* this is a maximum, it should be less than this most of the time */
  59. /* srchs/20/18/44/67/44/07/37/09/55/16/15 is max possible */
  60. size_t len;
  61. int i = 0;
  62. int even;
  63. /* convert to string */
  64. sprintf(num_str, "%" PRIu64, srch_cnt);
  65. memcpy(path, "srchs/", sizeof("srchs/") - 1);
  66. i += sizeof("srchs/") - 1;
  67. len = strlen(num_str);
  68. sprintf(path + i, "%zu", len);
  69. i += (len >= 10) ? 2 : 1;
  70. even = (len + 1) % 2;
  71. path[i++] = '/';
  72. for (int j = 0; num_str[j]; ++j) {
  73. path[i++] = num_str[j];
  74. /* makes sure 2 digits at end if two or more */
  75. if (!((j + even) % 2) && num_str[j + 1])
  76. path[i++] = '/';
  77. }
  78. path[i] = '\0';
  79. }
  80. static int
  81. path_content(Ilk_sys *sys, const char *path, size_t *len)
  82. {
  83. Nit_file file;
  84. Nit_err tmp;
  85. switch (file_exists(&sys->dir, path, &sys->lib->err)) {
  86. case 0:
  87. err_cust(&sys->lib->err, "File does not exist");
  88. err_where(&sys->lib->err, path);
  89. return -1;
  90. case 1:
  91. break;
  92. default:
  93. return -1;
  94. }
  95. if (file_open_mode(&file, &sys->dir, path,
  96. O_RDONLY, &sys->lib->err) < 0)
  97. return -1;
  98. if (!file.len) {
  99. err_cust(&sys->lib->err, "Empty file");
  100. err_where(&sys->lib->err, path);
  101. goto err;
  102. }
  103. if (file_content(&file, &sys->lib->buf.bytes,
  104. &sys->lib->buf.size, &sys->lib->err) < 0)
  105. goto err;
  106. *len = file.len;
  107. if (file_close(&file, &sys->lib->err) < 0)
  108. goto err;
  109. return 0;
  110. err:
  111. file_close(&file, &tmp); /* There's already an error */
  112. return -1;
  113. }
  114. int
  115. ilk_path_grp(Ilk_grp *grp, const char *path, int check, Ilk_sys *sys)
  116. {
  117. const char *error;
  118. size_t len;
  119. size_t pos = 0;
  120. if (path_content(sys, path, &len) < 0)
  121. return -1;
  122. if (len < sizeof(Rid)) {
  123. err_cust(&sys->lib->err, "Not enough space for id");
  124. goto err;
  125. }
  126. if (check) {
  127. if (rid_cmp(grp->id, sys->lib->buf.bytes)) {
  128. err_cust(&sys->lib->err, "Differing id for grp");
  129. goto err;
  130. }
  131. } else {
  132. rid_set(grp->id, sys->lib->buf.bytes);
  133. }
  134. pos = sizeof(Rid);
  135. if ((error = rlsp_rule_deserable(sys->lib->buf.bytes + pos, &pos,
  136. len, &sys->lib->srlz, NULL))) {
  137. err_cust(&sys->lib->err, error);
  138. goto err;
  139. }
  140. pos = sizeof(Rid);
  141. if (rlsp_rule_deser(&grp->rules, sys->lib->buf.bytes + pos, &pos,
  142. &sys->lib->srlz, sys, &sys->lib->rec) < 0) {
  143. err_cust(&sys->lib->err, "Failed to deserialize rules");
  144. goto err;
  145. }
  146. grp->accessed = 1;
  147. grp->changed = 0;
  148. return 0;
  149. err:
  150. err_where(&sys->lib->err, path);
  151. err_pos(&sys->lib->err, pos);
  152. return -1;
  153. }
  154. static void
  155. more_free(void *dat, void *extra)
  156. {
  157. Ilk_more *more = dat;
  158. Ilk_sys *sys = extra;
  159. *(Ilk_more **) more = sys->lib->old_mores;
  160. sys->lib->old_mores = more;
  161. }
  162. void
  163. ilk_grp_dispose(Ilk_grp *grp, Ilk_sys *sys)
  164. {
  165. rls_recycle_rule(&sys->lib->rec, grp->rules, more_free, sys);
  166. }
  167. int
  168. ilk_path_meta(Ilk_meta *meta, const char *path, int check, Ilk_sys *sys)
  169. {
  170. const char *error;
  171. size_t len;
  172. size_t pos = 0;
  173. if (path_content(sys, path, &len) < 0)
  174. return -1;
  175. if (len < sizeof(Rid)) {
  176. err_cust(&sys->lib->err, "Not enough space for id");
  177. goto err;
  178. }
  179. if (check && rid_cmp(meta->id, sys->lib->buf.bytes)) {
  180. err_cust(&sys->lib->err, "Differing id for grp");
  181. goto err;
  182. }
  183. if ((error = ilk_meta_deserable(sys->lib->buf.bytes, &pos, len))) {
  184. err_cust(&sys->lib->err, error);
  185. goto err;
  186. }
  187. pos = 0;
  188. if (ilk_meta_deser(meta, sys->lib->buf.bytes, &pos) < 0) {
  189. err_cust(&sys->lib->err, "Failed to deserialize meta");
  190. goto err;
  191. }
  192. return 0;
  193. err:
  194. err_where(&sys->lib->err, path);
  195. err_pos(&sys->lib->err, pos);
  196. return -1;
  197. }
  198. int
  199. ilk_path_srch(Rls_srch **srch_ref, const char *path, Ilk_sys *sys)
  200. {
  201. const char *error;
  202. size_t len;
  203. size_t pos = 0;
  204. unsigned char *buf;
  205. size_t size;
  206. if (path_content(sys, path, &len) < 0)
  207. return -1;
  208. if ((error = rlsp_srch_deserable(sys->lib->buf.bytes, &pos, len))) {
  209. err_cust(&sys->lib->err, error);
  210. goto err;
  211. }
  212. pos = 0;
  213. buf = sys->lib->buf.bytes;
  214. /* swap buffer since it can be overwritten */
  215. sys->lib->buf.bytes = NULL;
  216. size = sys->lib->buf.size;
  217. sys->lib->buf.size = 0;
  218. if ((error = rlsp_srch_deser(srch_ref, buf, &pos, NULL,
  219. sys->lib->bend, sys, &sys->lib->rec))) {
  220. /* unswap buffer */
  221. free(sys->lib->buf.bytes);
  222. sys->lib->buf.bytes = buf;
  223. sys->lib->buf.size = size;
  224. if (sys->lib->err.occured)
  225. return -1;
  226. err_cust(&sys->lib->err, error);
  227. goto err;
  228. }
  229. /* unswap buffer */
  230. free(sys->lib->buf.bytes);
  231. sys->lib->buf.bytes = buf;
  232. sys->lib->buf.size = size;
  233. return 0;
  234. err:
  235. err_where(&sys->lib->err, path);
  236. err_pos(&sys->lib->err, pos);
  237. return -1;
  238. }
  239. int
  240. ilk_path_meta_dep(Ilk_sys *sys, const char *path, uint64_t srch_cnt)
  241. {
  242. Nit_file file;
  243. uint64_t deps_len;
  244. Nit_err tmp;
  245. switch (file_exists(&sys->dir, path, &sys->lib->err)) {
  246. case 1:
  247. break;
  248. case 0:
  249. err_cust(&sys->lib->err, "No file found for meta");
  250. /* fallthru */
  251. default:
  252. /* error without file */
  253. goto err_no_file;
  254. }
  255. if (file_open(&file, &sys->dir, path, &sys->lib->err))
  256. goto err_no_file;
  257. if ((size_t) file.len < 2 * sizeof(Rid) + 2 * sizeof(uint64_t)) {
  258. err_cust(&sys->lib->err, "File too small for meta");
  259. goto err_file;
  260. }
  261. if (file_pos(&file, 2 * sizeof(Rid) + sizeof(uint64_t),
  262. &sys->lib->err) < 0)
  263. goto err_file;
  264. if (file_read(&file, &deps_len, sizeof(deps_len), &sys->lib->err) < 0)
  265. goto err_file;
  266. deps_len = le64toh(deps_len);
  267. deps_len += sizeof(srch_cnt);
  268. deps_len = htole64(deps_len);
  269. if (file_pos(&file, 2 * sizeof(Rid) + sizeof(uint64_t),
  270. &sys->lib->err) < 0)
  271. goto err_file;
  272. if (file_write(&file, &deps_len, sizeof(deps_len), &sys->lib->err) < 0)
  273. goto err_file;
  274. file_end(&file);
  275. if (file_write(&file, &srch_cnt, sizeof(srch_cnt), &sys->lib->err) < 0)
  276. goto err_file;
  277. if (file_close(&file, &sys->lib->err) < 0)
  278. goto err_file;
  279. return 0;
  280. err_file:
  281. file_close(&file, &tmp); /* There's already an error */
  282. err_no_file:
  283. err_where(&sys->lib->err, path);
  284. return -1;
  285. }
  286. int
  287. ilk_meta_ser(Ilk_meta *meta, unsigned char **buf_ref,
  288. size_t *size, size_t *pos)
  289. {
  290. uint64_t deps_len = gap_len(&meta->deps);
  291. size_t len = 2 * sizeof(Rid) + 2 * sizeof(uint64_t) +
  292. deps_len;
  293. unsigned char *buf = *buf_ref;
  294. if (len > *size) {
  295. if (!(buf = realloc(buf, len)))
  296. return -1;
  297. *size = len;
  298. *buf_ref = buf;
  299. }
  300. rid_set(buf, meta->id);
  301. buf += sizeof(Rid);
  302. rid_set(buf, meta->grp_id);
  303. buf += sizeof(Rid);
  304. *(uint64_t *) buf = htole64(meta->srch_cnt);
  305. buf += sizeof(uint64_t);
  306. *(uint64_t *) buf = htole64(deps_len);
  307. buf += sizeof(uint64_t);
  308. gap_read(&meta->deps, buf, deps_len);
  309. *pos = len;
  310. return 0;
  311. }
  312. const char *
  313. ilk_meta_deserable(const unsigned char *buf, size_t *pos,
  314. const size_t max)
  315. {
  316. uint64_t deps_len;
  317. if (!buf)
  318. return "Not enough space for meta";
  319. if (*pos + 2 * sizeof(Rid) + 2 * sizeof(uint64_t) > max) {
  320. *pos = max;
  321. return "Not enough space for meta";
  322. }
  323. buf += 2 * sizeof(Rid) + sizeof(uint64_t);
  324. deps_len = le64toh(*(uint64_t *) buf);
  325. *pos += 2 * sizeof(Rid) + 2 * sizeof(uint64_t);
  326. if ((*pos += deps_len) > max)
  327. return "Deps len for meta too large";
  328. return NULL;
  329. }
  330. int
  331. ilk_meta_deser(Ilk_meta *meta, const unsigned char *buf, size_t *pos)
  332. {
  333. uint64_t deps_len;
  334. rid_set(meta->id, buf);
  335. buf += sizeof(Rid);
  336. rid_set(meta->grp_id, buf);
  337. buf += sizeof(Rid);
  338. meta->srch_cnt = le64toh(*(uint64_t *) buf);
  339. buf += sizeof(uint64_t);
  340. deps_len = le64toh(*(uint64_t *) buf);
  341. buf += sizeof(uint64_t);
  342. *pos += 2 * sizeof(Rid) + 2 * sizeof(uint64_t);
  343. if (gap_init(&meta->deps, deps_len) < 0)
  344. return -1;
  345. gap_write(&meta->deps, buf, deps_len);
  346. *pos += deps_len;
  347. meta->changed = 0;
  348. return 0;
  349. }