int slice_write(void *buf, size_t len, unsigned char *outsha1) { int count = DIV_ROUND_UP(len, SLICE_SIZE); size_t slen = count * SHA1_DIGEST_SIZE; char *sbuf = xmalloc(slen); char *p = buf; for (int i = 0; i < count; i++, p += SLICE_SIZE) { unsigned char sha1[SHA1_DIGEST_SIZE]; size_t wlen = (ssize_t)len - SLICE_SIZE > 0 ? SLICE_SIZE : len; len -= SLICE_SIZE; if (sha1_file_write(p, wlen, sha1) < 0) goto err; memcpy(sbuf + i * SHA1_DIGEST_SIZE, sha1, SHA1_DIGEST_SIZE); } if (sha1_file_write(sbuf, slen, outsha1) < 0) goto err; free(sbuf); return 0; err: free(sbuf); return -1; }
int snap_file_write(uint32_t epoch, struct sd_node *nodes, int nr_nodes, unsigned char *trunksha1, unsigned char *outsha1) { int ret = 0; struct strbuf buf = STRBUF_INIT; struct sha1_file_hdr hdr; memcpy(hdr.tag, TAG_SNAP, TAG_LEN); hdr.size = nr_nodes * sizeof(*nodes) + SHA1_LEN; hdr.priv = epoch; hdr.reserved = 0; strbuf_add(&buf, &hdr, sizeof(hdr)); strbuf_add(&buf, trunksha1, SHA1_LEN); strbuf_add(&buf, (char *)nodes, nr_nodes * sizeof(*nodes)); if (sha1_file_write((void *)buf.buf, buf.len, outsha1) < 0) { ret = -1; goto err; } dprintf("epoch: %" PRIu32 ", sha1: %s\n", epoch, sha1_to_hex(outsha1)); err: strbuf_release(&buf); return ret; }
int snap_file_write(uint32_t epoch, unsigned char *trunksha1, unsigned char *outsha1, int user) { int ret = 0; struct strbuf buf = STRBUF_INIT; struct sd_node nodes[SD_MAX_NODES]; int tgt_epoch = user ? sys_epoch() : epoch; uint64_t epoch_size; struct sha1_file_hdr hdr; epoch_size = epoch_log_read(tgt_epoch, (char *)nodes, sizeof(nodes)); if (epoch_size == -1) return -1; memcpy(hdr.tag, TAG_SNAP, TAG_LEN); hdr.size = epoch_size + SHA1_LEN; hdr.priv = tgt_epoch; hdr.reserved = 0; strbuf_add(&buf, &hdr, sizeof(hdr)); strbuf_add(&buf, trunksha1, SHA1_LEN); strbuf_add(&buf, (char *)nodes, epoch_size); if (sha1_file_write((void *)buf.buf, buf.len, outsha1) < 0) { ret = -1; goto err; } dprintf("epoch %u, sha1: %s\n", epoch, sha1_to_hex(outsha1)); err: strbuf_release(&buf); return ret; }
int snap_file_write(uint32_t idx, unsigned char *trunk_sha1, unsigned char *outsha1) { struct snap_file snap; snap.idx = idx; memcpy(snap.trunk_sha1, trunk_sha1, SHA1_DIGEST_SIZE); return sha1_file_write(&snap, sizeof(struct snap_file), outsha1); }
int trunk_file_write(unsigned char *outsha1) { struct strbuf buf; struct sha1_file_hdr hdr = {}; struct trunk_entry entry = {}; struct dirent *d; DIR *dir; uint64_t data_size, oid, object_nr = 0; int ret = 0; /* Add the hdr first */ for_each_object_in_wd(inc_object_nr, false, &object_nr); data_size = sizeof(struct trunk_entry) * object_nr; hdr.size = data_size; hdr.priv = object_nr; memcpy(hdr.tag, TAG_TRUNK, TAG_LEN); strbuf_init(&buf, sizeof(hdr) + data_size); strbuf_add(&buf, &hdr, sizeof(hdr)); dir = opendir(obj_path); if (!dir) { ret = -1; goto out; } while ((d = readdir(dir))) { if (!strncmp(d->d_name, ".", 1)) continue; oid = strtoull(d->d_name, NULL, 16); if (oid == 0 || oid == ULLONG_MAX) continue; entry.oid = oid; if (fill_entry_new_sha1(&entry) < 0) { ret = -1; goto out; } strbuf_add(&buf, &entry, sizeof(struct trunk_entry)); } if (sha1_file_write((void *)buf.buf, buf.len, outsha1) < 0) { ret = -1; goto out; } dprintf("trunk sha1: %s\n", sha1_to_hex(outsha1)); out: closedir(dir); strbuf_release(&buf); return ret; }
static int fill_entry_new_sha1(struct trunk_entry *entry) { struct strbuf buf = STRBUF_INIT; int fd, ret = 0; struct sha1_file_hdr hdr = { .priv = 0 }; memcpy(hdr.tag, TAG_DATA, TAG_LEN); strbuf_addstr(&buf, obj_path); strbuf_addf(&buf, "%016" PRIx64, entry->oid); fd = open(buf.buf, O_RDONLY); strbuf_reset(&buf); if (fd < 0) { dprintf("%m\n"); ret = -1; goto out; } if (!strbuf_read(&buf, fd, SD_DATA_OBJ_SIZE) == SD_DATA_OBJ_SIZE) { dprintf("strbuf_read fail to read full\n"); ret = -1; goto out_close; } hdr.size = buf.len; strbuf_insert(&buf, 0, &hdr, sizeof(hdr)); if (sha1_file_write((void *)buf.buf, buf.len, entry->sha1) < 0) { ret = -1; goto out_close; } dprintf("data sha1:%s, %"PRIx64"\n", sha1_to_hex(entry->sha1), entry->oid); out_close: close(fd); out: strbuf_release(&buf); return ret; } static int inc_object_nr(uint64_t oid, void *arg) { uint64_t *object_nr = arg; (*object_nr)++; return 0; }
static int fill_entry_new_sha1(struct trunk_entry_incore *entry) { struct strbuf buf = STRBUF_INIT; int fd, ret = 0; struct sha1_file_hdr hdr = { .priv = 0 }; memcpy(hdr.tag, TAG_DATA, TAG_LEN); strbuf_addstr(&buf, obj_path); strbuf_addf(&buf, "%016" PRIx64, entry->raw.oid); fd = open(buf.buf, O_RDONLY); strbuf_reset(&buf); if (fd < 0) { dprintf("%m\n"); ret = -1; goto out; } if (!strbuf_read(&buf, fd, SD_DATA_OBJ_SIZE) == SD_DATA_OBJ_SIZE) { dprintf("strbuf_read fail to read full\n"); ret = -1; goto out_close; } hdr.size = buf.len; strbuf_insert(&buf, 0, &hdr, sizeof(hdr)); if (sha1_file_write((void *)buf.buf, buf.len, entry->raw.sha1) < 0) { ret = -1; goto out_close; } dprintf("data sha1:%s, %"PRIx64"\n", sha1_to_hex(entry->raw.sha1), entry->raw.oid); out_close: close(fd); out: strbuf_release(&buf); return ret; } static inline int trunk_entry_no_sha1(struct trunk_entry_incore *entry) { unsigned char empty[SHA1_LEN] = {0}; return memcmp(entry->raw.sha1, empty, SHA1_LEN) == 0; }