commit 52a7447583292df7a622b4c0d4d462c55554739c from: Stefan Sperling date: Mon Dec 24 15:46:13 2018 UTC implement got_fileindex_read() - not yet tested commit - b8bdcc21c2a597ea4af9b9dd1949a58fb8a62904 commit + 52a7447583292df7a622b4c0d4d462c55554739c blob - 217a29ff4bd01a13aeeedb194b456c8d73a8bfd1 blob + e7d37e6ced26afc644b84a7fc0cd12c351b63596 --- include/got_error.h +++ include/got_error.h @@ -64,6 +64,9 @@ #define GOT_ERR_EXPECTED 48 /* for use in regress tests only */ #define GOT_ERR_CANCELLED 49 #define GOT_ERR_NO_TREE_ENTRY 50 +#define GOT_ERR_FILEIDX_SIG 51 +#define GOT_ERR_FILEIDX_VER 52 +#define GOT_ERR_FILEIDX_CSUM 53 static const struct got_error { int code; @@ -116,6 +119,9 @@ static const struct got_error { { GOT_ERR_EXPECTED, "expected an error but have no error" }, { GOT_ERR_CANCELLED, "operation in progress has been cancelled" }, { GOT_ERR_NO_TREE_ENTRY,"no such entry found in tree" }, + { GOT_ERR_FILEIDX_SIG, "bad file index signature" }, + { GOT_ERR_FILEIDX_VER, "unknown file index format version" }, + { GOT_ERR_FILEIDX_CSUM, "bad file index checksum" }, }; /* blob - 6511dec1ab084d3e840d1133d5f07de1af53674e blob + ccd3f584d9191365c79b319787ea2189c0b21670 --- lib/fileindex.c +++ lib/fileindex.c @@ -262,6 +262,200 @@ got_fileindex_write(struct got_fileindex *fileindex, F n = fwrite(sha1, 1, sizeof(sha1), outfile); if (n != sizeof(sha1)) return got_ferror(outfile, GOT_ERR_IO); + + return NULL; +} + +static const struct got_error * +read_fileindex_val64(uint64_t *val, SHA1_CTX *ctx, FILE *infile) +{ + uint8_t buf[sizeof(uint64_t)]; + size_t n; + + n = fread(buf, 1, sizeof(buf), infile); + if (n != sizeof(buf)) + return got_ferror(infile, GOT_ERR_IO); + SHA1Update(ctx, buf, sizeof(buf)); + memcpy(val, buf, sizeof(*val)); + *val = htobe64(*val); + return NULL; +} + +static const struct got_error * +read_fileindex_val32(uint32_t *val, SHA1_CTX *ctx, FILE *infile) +{ + uint8_t buf[sizeof(uint32_t)]; + size_t n; + + n = fread(buf, 1, sizeof(buf), infile); + if (n != sizeof(buf)) + return got_ferror(infile, GOT_ERR_IO); + SHA1Update(ctx, buf, sizeof(buf)); + memcpy(val, buf, sizeof(*val)); + *val = htobe32(*val); + return NULL; +} + +static const struct got_error * +read_fileindex_val16(uint16_t *val, SHA1_CTX *ctx, FILE *infile) +{ + uint8_t buf[sizeof(uint16_t)]; + size_t n; + + n = fread(buf, 1, sizeof(buf), infile); + if (n != sizeof(buf)) + return got_ferror(infile, GOT_ERR_IO); + SHA1Update(ctx, buf, sizeof(buf)); + memcpy(val, buf, sizeof(*val)); + *val = htobe16(*val); + return NULL; +} + +static const struct got_error * +read_fileindex_path(char **path, SHA1_CTX *ctx, FILE *infile) +{ + const struct got_error *err = NULL; + uint8_t buf[8]; + size_t n, len = 0, totlen = sizeof(buf); + + *path = malloc(totlen); + if (*path == NULL) + return got_error_from_errno(); + + do { + n = fread(buf, 1, sizeof(buf), infile); + if (n != sizeof(buf)) + return got_ferror(infile, GOT_ERR_IO); + if (len + sizeof(buf) > totlen) { + char *p = reallocarray(*path, totlen + sizeof(buf), 1); + if (p == NULL) { + err = got_error_from_errno(); + break; + } + totlen += sizeof(buf); + *path = p; + } + SHA1Update(ctx, buf, sizeof(buf)); + memcpy(*path + len, buf, sizeof(buf)); + len += sizeof(buf); + } while (strchr(buf, '\0') == NULL); + + if (err) { + free(*path); + *path = NULL; + } + return err; +} + +static const struct got_error * +read_fileindex_entry(struct got_fileindex_entry **entryp, SHA1_CTX *ctx, + FILE *infile) +{ + const struct got_error *err; + struct got_fileindex_entry *entry; + size_t n; + + *entryp = NULL; + + entry = calloc(1, sizeof(*entry)); + if (entry == NULL) + return got_error_from_errno(); + err = read_fileindex_val64(&entry->ctime_sec, ctx, infile); + if (err) + goto done; + err = read_fileindex_val64(&entry->ctime_nsec, ctx, infile); + if (err) + goto done; + err = read_fileindex_val64(&entry->mtime_sec, ctx, infile); + if (err) + goto done; + err = read_fileindex_val64(&entry->mtime_nsec, ctx, infile); + if (err) + goto done; + + err = read_fileindex_val32(&entry->uid, ctx, infile); + if (err) + goto done; + err = read_fileindex_val32(&entry->gid, ctx, infile); + if (err) + goto done; + err = read_fileindex_val32(&entry->size, ctx, infile); + if (err) + goto done; + + err = read_fileindex_val16(&entry->mode, ctx, infile); + if (err) + goto done; + + n = fread(entry->blob_sha1, 1, SHA1_DIGEST_LENGTH, infile); + if (n != SHA1_DIGEST_LENGTH) { + err = got_ferror(infile, GOT_ERR_IO); + goto done; + } + SHA1Update(ctx, entry->blob_sha1, SHA1_DIGEST_LENGTH); + + err = read_fileindex_val32(&entry->flags, ctx, infile); + if (err) + goto done; + + err = read_fileindex_path(&entry->path, ctx, infile); +done: + if (err) + free(entry); + else + *entryp = entry; + return err; +} + +const struct got_error * +got_fileindex_read(struct got_fileindex *fileindex, FILE *infile) +{ + const struct got_error *err = NULL; + struct got_fileindex_hdr hdr; + SHA1_CTX ctx; + struct got_fileindex_entry *entry; + uint8_t sha1_expected[SHA1_DIGEST_LENGTH]; + uint8_t sha1[SHA1_DIGEST_LENGTH]; + size_t n; + const size_t len = sizeof(hdr.signature) + sizeof(hdr.version) + + sizeof(hdr.nentries); + uint8_t buf[len]; + int i; + + SHA1Init(&ctx); + + n = fread(buf, 1, len, infile); + if (n != len) + return got_ferror(infile, GOT_ERR_IO); + + SHA1Update(&ctx, buf, len); + + memcpy(&hdr, buf, len); + hdr.signature = htobe32(hdr.signature); + hdr.version = htobe32(hdr.version); + hdr.nentries = htobe32(hdr.nentries); + + if (hdr.signature != GOT_FILE_INDEX_SIGNATURE) + return got_error(GOT_ERR_FILEIDX_SIG); + if (hdr.version != GOT_FILE_INDEX_VERSION) + return got_error(GOT_ERR_FILEIDX_VER); + + for (i = 0; i < hdr.nentries; i++) { + err = read_fileindex_entry(&entry, &ctx, infile); + if (err) + return err; + err = got_fileindex_entry_add(fileindex, entry); + if (err) + return err; + } + + n = fread(sha1_expected, 1, sizeof(sha1_expected), infile); + if (n != sizeof(sha1_expected)) + return got_ferror(infile, GOT_ERR_IO); + SHA1Final(sha1, &ctx); + if (memcmp(sha1, sha1_expected, SHA1_DIGEST_LENGTH) != 0) + return got_error(GOT_ERR_FILEIDX_CSUM); + return NULL; } blob - 018f4f25c636bf8cfb37d7b1765211c73acae8e9 blob + d2a28dc5c55f8c97f58908fa8b50512e9d57100f --- lib/got_lib_fileindex.h +++ lib/got_lib_fileindex.h @@ -90,3 +90,4 @@ void got_fileindex_close(struct got_fileindex *); const struct got_error *got_fileindex_write(struct got_fileindex *, FILE *); const struct got_error *got_fileindex_entry_add(struct got_fileindex *, struct got_fileindex_entry *); +const struct got_error *got_fileindex_read(struct got_fileindex *, FILE *);