123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427 |
- /* This file is part of ilk.
- *
- * Ilk is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Ilk is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with ilk. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <dirent.h>
- #include <fcntl.h>
- #include <inttypes.h>
- #include <rid.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define STYLE_9
- #include <fn85.h>
- #include <rid_fn85.h>
- #include <unfy/unfy.h>
- #include <rls/rls.h>
- #include <rls/rlsp.h>
- #define NIT_SHORT_NAMES
- #include <nit/list.h>
- #include <nit/set.h>
- #include <nit/map.h>
- #include <nit/err.h>
- #include <nit/file.h>
- #include <nit/buf.h>
- #include <nit/gap.h>
- #include "utilize.h"
- #include "examine.h"
- void
- ilk_rule_path(Ilk_rule_path path, const Rid id)
- {
- memcpy(path, "rules/", sizeof("rules/") - 1);
- rid_fn85_path(path + sizeof("rules/") - 1, id);
- }
- void
- ilk_meta_path(Ilk_meta_path path, const Rid id)
- {
- memcpy(path, "metas/", sizeof("metas/") - 1);
- rid_fn85_path(path + sizeof("metas/") - 1, id);
- }
- void
- ilk_srch_path(Ilk_srch_path path, uint64_t srch_cnt)
- {
- char num_str[21];
- /* 6 + 2 + 1 + 20 + 9 + 1 = 38 */
- /* srchs/ + digit num + / + digits + / for every 2 digits + \0 */
- /* this is a maximum, it should be less than this most of the time */
- /* srchs/20/18/44/67/44/07/37/09/55/16/15 is max possible */
- size_t len;
- int i = 0;
- int even;
- /* convert to string */
- sprintf(num_str, "%" PRIu64, srch_cnt);
- memcpy(path, "srchs/", sizeof("srchs/") - 1);
- i += sizeof("srchs/") - 1;
- len = strlen(num_str);
- sprintf(path + i, "%zu", len);
- i += (len >= 10) ? 2 : 1;
- even = (len + 1) % 2;
- path[i++] = '/';
- for (int j = 0; num_str[j]; ++j) {
- path[i++] = num_str[j];
- /* makes sure 2 digits at end if two or more */
- if (!((j + even) % 2) && num_str[j + 1])
- path[i++] = '/';
- }
- path[i] = '\0';
- }
- static int
- path_content(Ilk_sys *sys, const char *path, size_t *len)
- {
- Nit_file file;
- Nit_err tmp;
- switch (file_exists(&sys->dir, path, &sys->lib->err)) {
- case 0:
- err_cust(&sys->lib->err, "File does not exist");
- err_where(&sys->lib->err, path);
- return -1;
- case 1:
- break;
- default:
- return -1;
- }
- if (file_open_mode(&file, &sys->dir, path,
- O_RDONLY, &sys->lib->err) < 0)
- return -1;
- if (!file.len) {
- err_cust(&sys->lib->err, "Empty file");
- err_where(&sys->lib->err, path);
- goto err;
- }
- if (file_content(&file, &sys->lib->buf.bytes,
- &sys->lib->buf.size, &sys->lib->err) < 0)
- goto err;
- *len = file.len;
- if (file_close(&file, &sys->lib->err) < 0)
- goto err;
- return 0;
- err:
- file_close(&file, &tmp); /* There's already an error */
- return -1;
- }
- int
- ilk_path_grp(Ilk_grp *grp, const char *path, int check, Ilk_sys *sys)
- {
- const char *error;
- size_t len;
- size_t pos = 0;
- if (path_content(sys, path, &len) < 0)
- return -1;
- if (len < sizeof(Rid)) {
- err_cust(&sys->lib->err, "Not enough space for id");
- goto err;
- }
- if (check) {
- if (rid_cmp(grp->id, sys->lib->buf.bytes)) {
- err_cust(&sys->lib->err, "Differing id for grp");
- goto err;
- }
- } else {
- rid_set(grp->id, sys->lib->buf.bytes);
- }
- pos = sizeof(Rid);
- if ((error = rlsp_rule_deserable(sys->lib->buf.bytes + pos, &pos,
- len, &sys->lib->srlz, NULL))) {
- err_cust(&sys->lib->err, error);
- goto err;
- }
- pos = sizeof(Rid);
- if (rlsp_rule_deser(&grp->rules, sys->lib->buf.bytes + pos, &pos,
- &sys->lib->srlz, sys, &sys->lib->rec) < 0) {
- err_cust(&sys->lib->err, "Failed to deserialize rules");
- goto err;
- }
- grp->accessed = 1;
- grp->changed = 0;
- return 0;
- err:
- err_where(&sys->lib->err, path);
- err_pos(&sys->lib->err, pos);
- return -1;
- }
- static void
- more_free(void *dat, void *extra)
- {
- Ilk_more *more = dat;
- Ilk_sys *sys = extra;
- *(Ilk_more **) more = sys->lib->old_mores;
- sys->lib->old_mores = more;
- }
- void
- ilk_grp_dispose(Ilk_grp *grp, Ilk_sys *sys)
- {
- rls_recycle_rule(&sys->lib->rec, grp->rules, more_free, sys);
- }
- int
- ilk_path_meta(Ilk_meta *meta, const char *path, int check, Ilk_sys *sys)
- {
- const char *error;
- size_t len;
- size_t pos = 0;
- if (path_content(sys, path, &len) < 0)
- return -1;
- if (len < sizeof(Rid)) {
- err_cust(&sys->lib->err, "Not enough space for id");
- goto err;
- }
- if (check && rid_cmp(meta->id, sys->lib->buf.bytes)) {
- err_cust(&sys->lib->err, "Differing id for grp");
- goto err;
- }
- if ((error = ilk_meta_deserable(sys->lib->buf.bytes, &pos, len))) {
- err_cust(&sys->lib->err, error);
- goto err;
- }
- pos = 0;
- if (ilk_meta_deser(meta, sys->lib->buf.bytes, &pos) < 0) {
- err_cust(&sys->lib->err, "Failed to deserialize meta");
- goto err;
- }
- return 0;
- err:
- err_where(&sys->lib->err, path);
- err_pos(&sys->lib->err, pos);
- return -1;
- }
- int
- ilk_path_srch(Rls_srch **srch_ref, const char *path, Ilk_sys *sys)
- {
- const char *error;
- size_t len;
- size_t pos = 0;
- unsigned char *buf;
- size_t size;
- if (path_content(sys, path, &len) < 0)
- return -1;
- if ((error = rlsp_srch_deserable(sys->lib->buf.bytes, &pos, len))) {
- err_cust(&sys->lib->err, error);
- goto err;
- }
- pos = 0;
- buf = sys->lib->buf.bytes;
- /* swap buffer since it can be overwritten */
- sys->lib->buf.bytes = NULL;
- size = sys->lib->buf.size;
- sys->lib->buf.size = 0;
- if ((error = rlsp_srch_deser(srch_ref, buf, &pos, NULL,
- sys->lib->bend, sys, &sys->lib->rec))) {
- /* unswap buffer */
- free(sys->lib->buf.bytes);
- sys->lib->buf.bytes = buf;
- sys->lib->buf.size = size;
- if (sys->lib->err.occured)
- return -1;
- err_cust(&sys->lib->err, error);
- goto err;
- }
- /* unswap buffer */
- free(sys->lib->buf.bytes);
- sys->lib->buf.bytes = buf;
- sys->lib->buf.size = size;
- return 0;
- err:
- err_where(&sys->lib->err, path);
- err_pos(&sys->lib->err, pos);
- return -1;
- }
- int
- ilk_path_meta_dep(Ilk_sys *sys, const char *path, uint64_t srch_cnt)
- {
- Nit_file file;
- uint64_t deps_len;
- Nit_err tmp;
- switch (file_exists(&sys->dir, path, &sys->lib->err)) {
- case 1:
- break;
- case 0:
- err_cust(&sys->lib->err, "No file found for meta");
- /* fallthru */
- default:
- /* error without file */
- goto err_no_file;
- }
- if (file_open(&file, &sys->dir, path, &sys->lib->err))
- goto err_no_file;
- if ((size_t) file.len < 2 * sizeof(Rid) + 2 * sizeof(uint64_t)) {
- err_cust(&sys->lib->err, "File too small for meta");
- goto err_file;
- }
- if (file_pos(&file, 2 * sizeof(Rid) + sizeof(uint64_t),
- &sys->lib->err) < 0)
- goto err_file;
- if (file_read(&file, &deps_len, sizeof(deps_len), &sys->lib->err) < 0)
- goto err_file;
- deps_len = le64toh(deps_len);
- deps_len += sizeof(srch_cnt);
- deps_len = htole64(deps_len);
- if (file_pos(&file, 2 * sizeof(Rid) + sizeof(uint64_t),
- &sys->lib->err) < 0)
- goto err_file;
- if (file_write(&file, &deps_len, sizeof(deps_len), &sys->lib->err) < 0)
- goto err_file;
- file_end(&file);
- if (file_write(&file, &srch_cnt, sizeof(srch_cnt), &sys->lib->err) < 0)
- goto err_file;
- if (file_close(&file, &sys->lib->err) < 0)
- goto err_file;
- return 0;
- err_file:
- file_close(&file, &tmp); /* There's already an error */
- err_no_file:
- err_where(&sys->lib->err, path);
- return -1;
- }
- int
- ilk_meta_ser(Ilk_meta *meta, unsigned char **buf_ref,
- size_t *size, size_t *pos)
- {
- uint64_t deps_len = gap_len(&meta->deps);
- size_t len = 2 * sizeof(Rid) + 2 * sizeof(uint64_t) +
- deps_len;
- unsigned char *buf = *buf_ref;
- if (len > *size) {
- if (!(buf = realloc(buf, len)))
- return -1;
- *size = len;
- *buf_ref = buf;
- }
- rid_set(buf, meta->id);
- buf += sizeof(Rid);
- rid_set(buf, meta->grp_id);
- buf += sizeof(Rid);
- *(uint64_t *) buf = htole64(meta->srch_cnt);
- buf += sizeof(uint64_t);
- *(uint64_t *) buf = htole64(deps_len);
- buf += sizeof(uint64_t);
- gap_read(&meta->deps, buf, deps_len);
- *pos = len;
- return 0;
- }
- const char *
- ilk_meta_deserable(const unsigned char *buf, size_t *pos,
- const size_t max)
- {
- uint64_t deps_len;
- if (!buf)
- return "Not enough space for meta";
- if (*pos + 2 * sizeof(Rid) + 2 * sizeof(uint64_t) > max) {
- *pos = max;
- return "Not enough space for meta";
- }
- buf += 2 * sizeof(Rid) + sizeof(uint64_t);
- deps_len = le64toh(*(uint64_t *) buf);
- *pos += 2 * sizeof(Rid) + 2 * sizeof(uint64_t);
- if ((*pos += deps_len) > max)
- return "Deps len for meta too large";
- return NULL;
- }
- int
- ilk_meta_deser(Ilk_meta *meta, const unsigned char *buf, size_t *pos)
- {
- uint64_t deps_len;
- rid_set(meta->id, buf);
- buf += sizeof(Rid);
- rid_set(meta->grp_id, buf);
- buf += sizeof(Rid);
- meta->srch_cnt = le64toh(*(uint64_t *) buf);
- buf += sizeof(uint64_t);
- deps_len = le64toh(*(uint64_t *) buf);
- buf += sizeof(uint64_t);
- *pos += 2 * sizeof(Rid) + 2 * sizeof(uint64_t);
- if (gap_init(&meta->deps, deps_len) < 0)
- return -1;
- gap_write(&meta->deps, buf, deps_len);
- *pos += deps_len;
- meta->changed = 0;
- return 0;
- }
|