URI: 
       tutils.c - dedup - data deduplication program
  HTML git clone git://bitreich.org/dedup/ git://hg6vgqziawt5s4dj.onion/dedup/
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
   DIR LICENSE
       ---
       tutils.c (5534B)
       ---
            1 #include <sys/types.h>
            2 
            3 #include <err.h>
            4 #include <stdint.h>
            5 #include <stdio.h>
            6 #include <stdlib.h>
            7 #include <string.h>
            8 #include <unistd.h>
            9 
           10 #include "blake2.h"
           11 #include "dedup.h"
           12 
           13 static void
           14 match_ver(uint64_t v)
           15 {
           16         uint8_t maj, min;
           17 
           18         min = v & VER_MIN_MASK;
           19         maj = (v >> VER_MAJ_SHIFT) & VER_MAJ_MASK;
           20         if (maj == VER_MAJ && min == VER_MIN)
           21                 return;
           22         errx(1, "format version mismatch: expected %u.%u but got %u.%u",
           23              VER_MAJ, VER_MIN, maj, min);
           24 }
           25 
           26 void
           27 str2bin(char *s, uint8_t *d)
           28 {
           29         size_t i, size = strlen(s) / 2;
           30 
           31         for (i = 0; i < size; i++, s += 2)
           32                 sscanf(s, "%2hhx", &d[i]);
           33 }
           34 
           35 off_t
           36 xlseek(int fd, off_t offset, int whence)
           37 {
           38         off_t ret;
           39 
           40         ret = lseek(fd, offset, whence);
           41         if (ret < 0)
           42                 err(1, "lseek");
           43         return ret;
           44 }
           45 
           46 ssize_t
           47 xread(int fd, void *buf, size_t nbytes)
           48 {
           49         uint8_t *bp = buf;
           50         ssize_t total = 0;
           51 
           52         while (nbytes > 0) {
           53                 ssize_t n;
           54 
           55                 n = read(fd, &bp[total], nbytes);
           56                 if (n < 0)
           57                         err(1, "read");
           58                 else if (n == 0)
           59                         return total;
           60                 total += n;
           61                 nbytes -= n;
           62         }
           63         return total;
           64 }
           65 
           66 ssize_t
           67 xwrite(int fd, const void *buf, size_t nbytes)
           68 {
           69         const uint8_t *bp = buf;
           70         ssize_t total = 0;
           71 
           72         while (nbytes > 0) {
           73                 ssize_t n;
           74 
           75                 n = write(fd, &bp[total], nbytes);
           76                 if (n < 0)
           77                         err(1, "write");
           78                 else if (n == 0)
           79                         return total;
           80                 total += n;
           81                 nbytes -= n;
           82         }
           83         return total;
           84 }
           85 
           86 void
           87 init_blk_hdr(struct blk_hdr *hdr, int compr_algo, int hash_algo)
           88 {
           89         hdr->flags = (VER_MAJ << VER_MAJ_SHIFT) | VER_MIN;
           90         hdr->flags |= compr_algo << COMPR_ALGO_SHIFT;
           91         hdr->flags |= hash_algo << HASH_ALGO_SHIFT;
           92         hdr->size = BLK_HDR_SIZE;
           93 }
           94 
           95 void
           96 init_snap_hdr(struct snap_hdr *hdr)
           97 {
           98         hdr->flags = (VER_MAJ << VER_MAJ_SHIFT) | VER_MIN;
           99         hdr->size = SNAP_HDR_SIZE;
          100         hdr->st.min_blk_size = UINT64_MAX;
          101 }
          102 
          103 void
          104 load_blk_hdr(int fd, struct blk_hdr *hdr, int *compr_algo, int *hash_algo)
          105 {
          106         uint64_t v;
          107 
          108         read_blk_hdr(fd, hdr);
          109         match_ver(hdr->flags);
          110 
          111         v = hdr->flags >> COMPR_ALGO_SHIFT;
          112         v &= COMPR_ALGO_MASK;
          113         *compr_algo = v;
          114 
          115         if (*compr_algo < 0 || *compr_algo >= NR_COMPRS)
          116                 errx(1, "unsupported compression algorithm: %d", *compr_algo);
          117 
          118         v = hdr->flags >> HASH_ALGO_SHIFT;
          119         v &= HASH_ALGO_MASK;
          120         *hash_algo = v;
          121 
          122         if (*hash_algo < 0 || *hash_algo >= NR_HASHES)
          123                 errx(1, "unsupported hash algorithm: %d", *hash_algo);
          124 }
          125 
          126 void
          127 load_snap_hdr(int fd, struct snap_hdr *hdr)
          128 {
          129         read_snap_hdr(fd, hdr);
          130         match_ver(hdr->flags);
          131 }
          132 
          133 struct snap *
          134 alloc_snap(void)
          135 {
          136         struct snap *snap;
          137 
          138         snap = calloc(1, sizeof(*snap));
          139         if (snap == NULL)
          140                 err(1, "%s", __func__);
          141         return snap;
          142 }
          143 
          144 void
          145 free_snap(struct snap *snap)
          146 {
          147         free(snap);
          148 }
          149 
          150 struct snap *
          151 grow_snap(struct snap *snap, uint64_t nr_blk_descs)
          152 {
          153         size_t size;
          154 
          155         if (nr_blk_descs > SIZE_MAX / sizeof(snap->blk_desc[0]))
          156                 errx(1, "%s: overflow", __func__);
          157         size = nr_blk_descs * sizeof(snap->blk_desc[0]);
          158 
          159         if (size > SIZE_MAX - sizeof(*snap))
          160                 errx(1, "%s: overflow", __func__);
          161         size += sizeof(*snap);
          162 
          163         snap = realloc(snap, size);
          164         if (snap == NULL)
          165                 err(1, "%s", __func__);
          166         return snap;
          167 }
          168 
          169 void
          170 append_snap(int fd, struct snap_hdr *hdr, struct snap *snap)
          171 {
          172         if (snap->nr_blk_descs > UINT64_MAX / BLK_DESC_SIZE)
          173                 errx(1, "%s: overflow", __func__);
          174         snap->size = snap->nr_blk_descs * BLK_DESC_SIZE;
          175 
          176         if (snap->size > UINT64_MAX - SNAPSHOT_SIZE)
          177                 errx(1, "%s: overflow", __func__);
          178         snap->size += SNAPSHOT_SIZE;
          179 
          180         xlseek(fd, hdr->size, SEEK_SET);
          181         write_snap(fd, snap);
          182         write_snap_blk_descs(fd, snap);
          183 
          184         if (hdr->size > UINT64_MAX - snap->size)
          185                 errx(1, "%s: overflow", __func__);
          186         hdr->size += snap->size;
          187 
          188         if (hdr->nr_snaps > UINT64_MAX - 1)
          189                 errx(1, "%s: overflow", __func__);
          190         hdr->nr_snaps++;
          191 }
          192 
          193 /*
          194  * The snapshot hash is calculated over the
          195  * hash of its block descriptors.
          196  */
          197 void
          198 hash_snap(struct snap *snap, uint8_t *md, int hash_algo)
          199 {
          200         struct hash_ctx ctx;
          201         uint64_t i;
          202 
          203         if (hash_init(&ctx, hash_algo, MD_SIZE) < 0)
          204                 errx(1, "hash_init failed");
          205         for (i = 0; i < snap->nr_blk_descs; i++) {
          206                 struct blk_desc *blk_desc;
          207 
          208                 blk_desc = &snap->blk_desc[i];
          209                 hash_update(&ctx, blk_desc->md, sizeof(blk_desc->md));
          210         }
          211         hash_final(&ctx, md, MD_SIZE);
          212 }
          213 
          214 /* Walk through all snapshots and call fn() on each one */
          215 void
          216 walk_snap(int fd, struct snap_hdr *hdr,
          217           int (*fn)(struct snap *, void *), void *arg)
          218 {
          219         uint64_t i;
          220 
          221         xlseek(fd, SNAP_HDR_SIZE, SEEK_SET);
          222         for (i = 0; i < hdr->nr_snaps; i++) {
          223                 struct snap *snap;
          224                 int ret;
          225 
          226                 snap = alloc_snap();
          227                 read_snap(fd, snap);
          228                 snap = grow_snap(snap, snap->nr_blk_descs);
          229                 read_snap_descs(fd, snap);
          230 
          231                 ret = (*fn)(snap, arg);
          232                 free_snap(snap);
          233                 if (ret == WALK_STOP)
          234                         break;
          235         }
          236 }
          237 
          238 uint8_t *
          239 alloc_buf(size_t size)
          240 {
          241         void *p;
          242 
          243         p = calloc(1, size);
          244         if (p == NULL)
          245                 err(1, "%s", __func__);
          246         return p;
          247 }
          248 
          249 void
          250 free_buf(uint8_t *buf)
          251 {
          252         free(buf);
          253 }
          254 
          255 void
          256 read_blk(int fd, uint8_t *buf, struct blk_desc *blk_desc)
          257 {
          258         ssize_t n;
          259 
          260         xlseek(fd, blk_desc->offset, SEEK_SET);
          261         n = xread(fd, buf, blk_desc->size);
          262         if (n == 0)
          263                 errx(1, "%s: unexpected EOF", __func__);
          264         if (n != blk_desc->size)
          265                 errx(1, "%s: short read", __func__);
          266 }
          267 
          268 void
          269 append_blk(int fd, struct blk_hdr *hdr, uint8_t *buf, struct blk_desc *blk_desc)
          270 {
          271         xlseek(fd, hdr->size, SEEK_SET);
          272         xwrite(fd, buf, blk_desc->size);
          273 
          274         if (hdr->size > UINT64_MAX - blk_desc->size)
          275                 errx(1, "%s: overflow", __func__);
          276         hdr->size += blk_desc->size;
          277 }
          278 
          279 void
          280 hash_blk(uint8_t *buf, size_t size, uint8_t *md, int hash_algo)
          281 {
          282         struct hash_ctx ctx;
          283 
          284         if (hash_init(&ctx, hash_algo, MD_SIZE) < 0)
          285                 errx(1, "hash_init failed");
          286         hash_update(&ctx, buf, size);
          287         hash_final(&ctx, md, MD_SIZE);
          288 }