diff options
-rw-r--r-- | apply.c | 12 | ||||
-rw-r--r-- | builtin/cat-file.c | 11 | ||||
-rw-r--r-- | builtin/checkout.c | 2 | ||||
-rw-r--r-- | builtin/fast-export.c | 2 | ||||
-rw-r--r-- | builtin/fast-import.c | 12 | ||||
-rw-r--r-- | builtin/grep.c | 4 | ||||
-rw-r--r-- | builtin/hash-object.c | 2 | ||||
-rw-r--r-- | builtin/index-pack.c | 10 | ||||
-rw-r--r-- | builtin/mktag.c | 9 | ||||
-rw-r--r-- | builtin/mktree.c | 2 | ||||
-rw-r--r-- | builtin/notes.c | 2 | ||||
-rw-r--r-- | builtin/pack-objects.c | 2 | ||||
-rw-r--r-- | builtin/receive-pack.c | 2 | ||||
-rw-r--r-- | builtin/replace.c | 4 | ||||
-rw-r--r-- | builtin/tag.c | 2 | ||||
-rw-r--r-- | builtin/unpack-objects.c | 8 | ||||
-rw-r--r-- | bulk-checkin.c | 4 | ||||
-rw-r--r-- | cache-tree.c | 8 | ||||
-rw-r--r-- | cache.h | 20 | ||||
-rw-r--r-- | commit.c | 2 | ||||
-rw-r--r-- | convert.c | 2 | ||||
-rw-r--r-- | diffcore-rename.c | 2 | ||||
-rw-r--r-- | dir.c | 2 | ||||
-rw-r--r-- | http-push.c | 2 | ||||
-rw-r--r-- | log-tree.c | 2 | ||||
-rw-r--r-- | match-trees.c | 2 | ||||
-rw-r--r-- | merge-ort.c | 4 | ||||
-rw-r--r-- | merge-recursive.c | 2 | ||||
-rw-r--r-- | notes-cache.c | 2 | ||||
-rw-r--r-- | notes.c | 8 | ||||
-rw-r--r-- | object-file.c | 145 | ||||
-rw-r--r-- | object-store.h | 24 | ||||
-rw-r--r-- | object.c | 5 | ||||
-rw-r--r-- | pack-check.c | 9 | ||||
-rw-r--r-- | read-cache.c | 2 | ||||
-rw-r--r-- | tree-walk.c | 6 |
36 files changed, 202 insertions, 137 deletions
@@ -3164,7 +3164,7 @@ static int apply_binary(struct apply_state *state, * See if the old one matches what the patch * applies to. */ - hash_object_file(the_hash_algo, img->buf, img->len, blob_type, + hash_object_file(the_hash_algo, img->buf, img->len, OBJ_BLOB, &oid); if (strcmp(oid_to_hex(&oid), patch->old_oid_prefix)) return error(_("the patch applies to '%s' (%s), " @@ -3210,7 +3210,7 @@ static int apply_binary(struct apply_state *state, name); /* verify that the result matches */ - hash_object_file(the_hash_algo, img->buf, img->len, blob_type, + hash_object_file(the_hash_algo, img->buf, img->len, OBJ_BLOB, &oid); if (strcmp(oid_to_hex(&oid), patch->new_oid_prefix)) return error(_("binary patch to '%s' creates incorrect result (expecting %s, got %s)"), @@ -3599,7 +3599,7 @@ static int try_threeway(struct apply_state *state, /* Preimage the patch was prepared for */ if (patch->is_new) - write_object_file("", 0, blob_type, &pre_oid); + write_object_file("", 0, OBJ_BLOB, &pre_oid); else if (get_oid(patch->old_oid_prefix, &pre_oid) || read_blob_object(&buf, &pre_oid, patch->old_mode)) return error(_("repository lacks the necessary blob to perform 3-way merge.")); @@ -3615,7 +3615,7 @@ static int try_threeway(struct apply_state *state, return -1; } /* post_oid is theirs */ - write_object_file(tmp_image.buf, tmp_image.len, blob_type, &post_oid); + write_object_file(tmp_image.buf, tmp_image.len, OBJ_BLOB, &post_oid); clear_image(&tmp_image); /* our_oid is ours */ @@ -3628,7 +3628,7 @@ static int try_threeway(struct apply_state *state, return error(_("cannot read the current contents of '%s'"), patch->old_name); } - write_object_file(tmp_image.buf, tmp_image.len, blob_type, &our_oid); + write_object_file(tmp_image.buf, tmp_image.len, OBJ_BLOB, &our_oid); clear_image(&tmp_image); /* in-core three-way merge between post and our using pre as base */ @@ -4328,7 +4328,7 @@ static int add_index_file(struct apply_state *state, } fill_stat_cache_info(state->repo->index, ce, &st); } - if (write_object_file(buf, size, blob_type, &ce->oid) < 0) { + if (write_object_file(buf, size, OBJ_BLOB, &ce->oid) < 0) { discard_cache_entry(ce); return error(_("unable to create backing store " "for newly created file %s"), path); diff --git a/builtin/cat-file.c b/builtin/cat-file.c index e75e110302..0663661c0b 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -156,7 +156,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, break; case 0: - if (type_from_string(exp_type) == OBJ_BLOB) { + { + enum object_type exp_type_id = type_from_string(exp_type); + + if (exp_type_id == OBJ_BLOB) { struct object_id blob_oid; if (oid_object_info(the_repository, &oid, NULL) == OBJ_TAG) { char *buffer = read_object_file(&oid, &type, @@ -178,10 +181,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, * fall-back to the usual case. */ } - buf = read_object_with_reference(the_repository, - &oid, exp_type, &size, NULL); + buf = read_object_with_reference(the_repository, &oid, + exp_type_id, &size, NULL); break; - + } default: die("git cat-file: unknown option: %s", exp_type); } diff --git a/builtin/checkout.c b/builtin/checkout.c index 1afc0773d5..797681481d 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -303,7 +303,7 @@ static int checkout_merged(int pos, const struct checkout *state, * (it also writes the merge result to the object database even * when it may contain conflicts). */ - if (write_object_file(result_buf.ptr, result_buf.size, blob_type, &oid)) + if (write_object_file(result_buf.ptr, result_buf.size, OBJ_BLOB, &oid)) die(_("Unable to add merge result for '%s'"), path); free(result_buf.ptr); ce = make_transient_cache_entry(mode, &oid, path, 2, ce_mem_pool); diff --git a/builtin/fast-export.c b/builtin/fast-export.c index 510139e9b5..a7d72697fb 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -300,7 +300,7 @@ static void export_blob(const struct object_id *oid) if (!buf) die("could not read blob %s", oid_to_hex(oid)); if (check_object_signature(the_repository, oid, buf, size, - type_name(type), NULL) < 0) + type) < 0) die("oid mismatch in blob %s", oid_to_hex(oid)); object = parse_object_buffer(the_repository, oid, type, size, buf, &eaten); diff --git a/builtin/fast-import.c b/builtin/fast-import.c index b7105fcad9..ad045c7c2d 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -944,8 +944,8 @@ static int store_object( git_hash_ctx c; git_zstream s; - hdrlen = xsnprintf((char *)hdr, sizeof(hdr), "%s %lu", - type_name(type), (unsigned long)dat->len) + 1; + hdrlen = format_object_header((char *)hdr, sizeof(hdr), type, + dat->len); the_hash_algo->init_fn(&c); the_hash_algo->update_fn(&c, hdr, hdrlen); the_hash_algo->update_fn(&c, dat->buf, dat->len); @@ -1098,7 +1098,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark) hashfile_checkpoint(pack_file, &checkpoint); offset = checkpoint.offset; - hdrlen = xsnprintf((char *)out_buf, out_sz, "blob %" PRIuMAX, len) + 1; + hdrlen = format_object_header((char *)out_buf, out_sz, OBJ_BLOB, len); the_hash_algo->init_fn(&c); the_hash_algo->update_fn(&c, out_buf, hdrlen); @@ -2490,7 +2490,7 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa unsigned long size; char *buf = read_object_with_reference(the_repository, &commit_oid, - commit_type, &size, + OBJ_COMMIT, &size, &commit_oid); if (!buf || size < the_hash_algo->hexsz + 6) die("Not a valid commit: %s", p); @@ -2562,7 +2562,7 @@ static void parse_from_existing(struct branch *b) char *buf; buf = read_object_with_reference(the_repository, - &b->oid, commit_type, &size, + &b->oid, OBJ_COMMIT, &size, &b->oid); parse_from_commit(b, buf, size); free(buf); @@ -2658,7 +2658,7 @@ static struct hash_list *parse_merge(unsigned int *count) unsigned long size; char *buf = read_object_with_reference(the_repository, &n->oid, - commit_type, + OBJ_COMMIT, &size, &n->oid); if (!buf || size < the_hash_algo->hexsz + 6) die("Not a valid commit: %s", from); diff --git a/builtin/grep.c b/builtin/grep.c index f1a924eade..bcb07ea7f7 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -484,7 +484,7 @@ static int grep_submodule(struct grep_opt *opt, object_type = oid_object_info(subrepo, oid, NULL); obj_read_unlock(); data = read_object_with_reference(subrepo, - oid, tree_type, + oid, OBJ_TREE, &size, NULL); if (!data) die(_("unable to read tree (%s)"), oid_to_hex(oid)); @@ -653,7 +653,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, int hit, len; data = read_object_with_reference(opt->repo, - &obj->oid, tree_type, + &obj->oid, OBJ_TREE, &size, NULL); if (!data) die(_("unable to read tree (%s)"), oid_to_hex(&obj->oid)); diff --git a/builtin/hash-object.c b/builtin/hash-object.c index 0837849288..fbae878c2b 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -25,7 +25,7 @@ static int hash_literally(struct object_id *oid, int fd, const char *type, unsig if (strbuf_read(&buf, fd, 4096) < 0) ret = -1; else - ret = hash_object_file_literally(buf.buf, buf.len, type, oid, + ret = write_object_file_literally(buf.buf, buf.len, type, oid, flags); strbuf_release(&buf); return ret; diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 38fb4f4e55..2b2e6eeb82 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -453,8 +453,7 @@ static void *unpack_entry_data(off_t offset, unsigned long size, int hdrlen; if (!is_delta_type(type)) { - hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX, - type_name(type),(uintmax_t)size) + 1; + hdrlen = format_object_header(hdr, sizeof(hdr), type, size); the_hash_algo->init_fn(&c); the_hash_algo->update_fn(&c, hdr, hdrlen); } else @@ -975,7 +974,7 @@ static struct base_data *resolve_delta(struct object_entry *delta_obj, if (!result_data) bad_object(delta_obj->idx.offset, _("failed to apply delta")); hash_object_file(the_hash_algo, result_data, result_size, - type_name(delta_obj->real_type), &delta_obj->idx.oid); + delta_obj->real_type, &delta_obj->idx.oid); sha1_object(result_data, NULL, result_size, delta_obj->real_type, &delta_obj->idx.oid); @@ -1419,9 +1418,8 @@ static void fix_unresolved_deltas(struct hashfile *f) if (!data) continue; - if (check_object_signature(the_repository, &d->oid, - data, size, - type_name(type), NULL)) + if (check_object_signature(the_repository, &d->oid, data, size, + type) < 0) die(_("local object %s is corrupt"), oid_to_hex(&d->oid)); /* diff --git a/builtin/mktag.c b/builtin/mktag.c index c7b905c614..5d22909122 100644 --- a/builtin/mktag.c +++ b/builtin/mktag.c @@ -61,9 +61,8 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type) type_name(*tagged_type), type_name(type)); repl = lookup_replace_object(the_repository, tagged_oid); - ret = check_object_signature(the_repository, repl, - buffer, size, type_name(*tagged_type), - NULL); + ret = check_object_signature(the_repository, repl, buffer, size, + *tagged_type); free(buffer); return ret; @@ -97,10 +96,10 @@ int cmd_mktag(int argc, const char **argv, const char *prefix) &tagged_oid, &tagged_type)) die(_("tag on stdin did not pass our strict fsck check")); - if (verify_object_in_tag(&tagged_oid, &tagged_type)) + if (verify_object_in_tag(&tagged_oid, &tagged_type) < 0) die(_("tag on stdin did not refer to a valid object")); - if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0) + if (write_object_file(buf.buf, buf.len, OBJ_TAG, &result) < 0) die(_("unable to write tag file")); strbuf_release(&buf); diff --git a/builtin/mktree.c b/builtin/mktree.c index 8bdaada922..902edba6d2 100644 --- a/builtin/mktree.c +++ b/builtin/mktree.c @@ -58,7 +58,7 @@ static void write_tree(struct object_id *oid) strbuf_add(&buf, ent->oid.hash, the_hash_algo->rawsz); } - write_object_file(buf.buf, buf.len, tree_type, oid); + write_object_file(buf.buf, buf.len, OBJ_TREE, oid); strbuf_release(&buf); } diff --git a/builtin/notes.c b/builtin/notes.c index f99593a185..a3d0d15a22 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -199,7 +199,7 @@ static void prepare_note_data(const struct object_id *object, struct note_data * static void write_note_data(struct note_data *d, struct object_id *oid) { - if (write_object_file(d->buf.buf, d->buf.len, blob_type, oid)) { + if (write_object_file(d->buf.buf, d->buf.len, OBJ_BLOB, oid)) { int status = die_message(_("unable to write note object")); if (d->edit_path) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 178e611f09..47b0e1da7d 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1802,7 +1802,7 @@ static void add_preferred_base(struct object_id *oid) return; data = read_object_with_reference(the_repository, oid, - tree_type, &size, &tree_oid); + OBJ_TREE, &size, &tree_oid); if (!data) return; diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index d10aeb7e78..380259869d 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -749,7 +749,7 @@ static void prepare_push_cert_sha1(struct child_process *proc) int bogs /* beginning_of_gpg_sig */; already_done = 1; - if (write_object_file(push_cert.buf, push_cert.len, "blob", + if (write_object_file(push_cert.buf, push_cert.len, OBJ_BLOB, &push_cert_oid)) oidclr(&push_cert_oid); diff --git a/builtin/replace.c b/builtin/replace.c index ac92337c0e..5068f4f0b2 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -409,7 +409,7 @@ static int check_one_mergetag(struct commit *commit, int i; hash_object_file(the_hash_algo, extra->value, extra->len, - type_name(OBJ_TAG), &tag_oid); + OBJ_TAG, &tag_oid); tag = lookup_tag(the_repository, &tag_oid); if (!tag) return error(_("bad mergetag in commit '%s'"), ref); @@ -474,7 +474,7 @@ static int create_graft(int argc, const char **argv, int force, int gentle) return -1; } - if (write_object_file(buf.buf, buf.len, commit_type, &new_oid)) { + if (write_object_file(buf.buf, buf.len, OBJ_COMMIT, &new_oid)) { strbuf_release(&buf); return error(_("could not write replacement commit for: '%s'"), old_ref); diff --git a/builtin/tag.c b/builtin/tag.c index 2479da0704..e5a8f85693 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -239,7 +239,7 @@ static int build_tag_object(struct strbuf *buf, int sign, struct object_id *resu { if (sign && do_sign(buf) < 0) return error(_("unable to sign the tag")); - if (write_object_file(buf->buf, buf->len, tag_type, result) < 0) + if (write_object_file(buf->buf, buf->len, OBJ_TAG, result) < 0) return error(_("unable to write tag file")); return 0; } diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 4a9466295b..dbeb0680a5 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -177,7 +177,7 @@ static void write_cached_object(struct object *obj, struct obj_buffer *obj_buf) struct object_id oid; if (write_object_file(obj_buf->buffer, obj_buf->size, - type_name(obj->type), &oid) < 0) + obj->type, &oid) < 0) die("failed to write object %s", oid_to_hex(&obj->oid)); obj->flags |= FLAG_WRITTEN; } @@ -243,7 +243,7 @@ static void write_object(unsigned nr, enum object_type type, void *buf, unsigned long size) { if (!strict) { - if (write_object_file(buf, size, type_name(type), + if (write_object_file(buf, size, type, &obj_list[nr].oid) < 0) die("failed to write object"); added_object(nr, type, buf, size); @@ -251,7 +251,7 @@ static void write_object(unsigned nr, enum object_type type, obj_list[nr].obj = NULL; } else if (type == OBJ_BLOB) { struct blob *blob; - if (write_object_file(buf, size, type_name(type), + if (write_object_file(buf, size, type, &obj_list[nr].oid) < 0) die("failed to write object"); added_object(nr, type, buf, size); @@ -266,7 +266,7 @@ static void write_object(unsigned nr, enum object_type type, } else { struct object *obj; int eaten; - hash_object_file(the_hash_algo, buf, size, type_name(type), + hash_object_file(the_hash_algo, buf, size, type, &obj_list[nr].oid); added_object(nr, type, buf, size); obj = parse_object_buffer(the_repository, &obj_list[nr].oid, diff --git a/bulk-checkin.c b/bulk-checkin.c index 8785b2ac80..85b3ebaf97 100644 --- a/bulk-checkin.c +++ b/bulk-checkin.c @@ -220,8 +220,8 @@ static int deflate_to_pack(struct bulk_checkin_state *state, if (seekback == (off_t) -1) return error("cannot find the current offset"); - header_len = xsnprintf((char *)obuf, sizeof(obuf), "%s %" PRIuMAX, - type_name(type), (uintmax_t)size) + 1; + header_len = format_object_header((char *)obuf, sizeof(obuf), + type, size); the_hash_algo->init_fn(&ctx); the_hash_algo->update_fn(&ctx, obuf, header_len); diff --git a/cache-tree.c b/cache-tree.c index 65ca993361..6752f69d51 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -432,15 +432,15 @@ static int update_one(struct cache_tree *it, if (repair) { struct object_id oid; hash_object_file(the_hash_algo, buffer.buf, buffer.len, - tree_type, &oid); + OBJ_TREE, &oid); if (has_object_file_with_flags(&oid, OBJECT_INFO_SKIP_FETCH_OBJECT)) oidcpy(&it->oid, &oid); else to_invalidate = 1; } else if (dryrun) { hash_object_file(the_hash_algo, buffer.buf, buffer.len, - tree_type, &it->oid); - } else if (write_object_file_flags(buffer.buf, buffer.len, tree_type, + OBJ_TREE, &it->oid); + } else if (write_object_file_flags(buffer.buf, buffer.len, OBJ_TREE, &it->oid, flags & WRITE_TREE_SILENT ? HASH_SILENT : 0)) { strbuf_release(&buffer); @@ -948,7 +948,7 @@ static int verify_one(struct repository *r, strbuf_addf(&tree_buf, "%o %.*s%c", mode, entlen, name, '\0'); strbuf_add(&tree_buf, oid->hash, r->hash_algo->rawsz); } - hash_object_file(r->hash_algo, tree_buf.buf, tree_buf.len, tree_type, + hash_object_file(r->hash_algo, tree_buf.buf, tree_buf.len, OBJ_TREE, &new_oid); if (!oideq(&new_oid, &it->oid)) BUG("cache-tree for path %.*s does not match. " @@ -1320,9 +1320,23 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream, struct object_info; int parse_loose_header(const char *hdr, struct object_info *oi); +/** + * With in-core object data in "buf", rehash it to make sure the + * object name actually matches "oid" to detect object corruption. + * + * A negative value indicates an error, usually that the OID is not + * what we expected, but it might also indicate another error. + */ int check_object_signature(struct repository *r, const struct object_id *oid, - void *buf, unsigned long size, const char *type, - struct object_id *real_oidp); + void *map, unsigned long size, + enum object_type type); + +/** + * A streaming version of check_object_signature(). + * Try reading the object named with "oid" using + * the streaming interface and rehash it to do the same. + */ +int stream_object_signature(struct repository *r, const struct object_id *oid); int finalize_object_file(const char *tmpfile, const char *filename); @@ -1549,7 +1563,7 @@ int cache_name_stage_compare(const char *name1, int len1, int stage1, const char void *read_object_with_reference(struct repository *r, const struct object_id *oid, - const char *required_type, + enum object_type required_type, unsigned long *size, struct object_id *oid_ret); @@ -1568,7 +1568,7 @@ int commit_tree_extended(const char *msg, size_t msg_len, goto out; } - result = write_object_file(buffer.buf, buffer.len, commit_type, ret); + result = write_object_file(buffer.buf, buffer.len, OBJ_COMMIT, ret); out: strbuf_release(&buffer); return result; @@ -1159,7 +1159,7 @@ static int ident_to_worktree(const char *src, size_t len, /* are we "faking" in place editing ? */ if (src == buf->buf) to_free = strbuf_detach(buf, NULL); - hash_object_file(the_hash_algo, src, len, "blob", &oid); + hash_object_file(the_hash_algo, src, len, OBJ_BLOB, &oid); strbuf_grow(buf, len + cnt * (the_hash_algo->hexsz + 3)); for (;;) { diff --git a/diffcore-rename.c b/diffcore-rename.c index bebd4ed6a4..c0422d9e70 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -261,7 +261,7 @@ static unsigned int hash_filespec(struct repository *r, if (diff_populate_filespec(r, filespec, NULL)) return 0; hash_object_file(r->hash_algo, filespec->data, filespec->size, - "blob", &filespec->oid); + OBJ_BLOB, &filespec->oid); } return oidhash(&filespec->oid); } @@ -1113,7 +1113,7 @@ static int add_patterns(const char *fname, const char *base, int baselen, &istate->cache[pos]->oid); else hash_object_file(the_hash_algo, buf, size, - "blob", &oid_stat->oid); + OBJ_BLOB, &oid_stat->oid); fill_stat_data(&oid_stat->stat, &st); oid_stat->valid = 1; } diff --git a/http-push.c b/http-push.c index 3309aaf004..f0c044dcf7 100644 --- a/http-push.c +++ b/http-push.c @@ -363,7 +363,7 @@ static void start_put(struct transfer_request *request) git_zstream stream; unpacked = read_object_file(&request->obj->oid, &type, &len); - hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX , type_name(type), (uintmax_t)len) + 1; + hdrlen = format_object_header(hdr, sizeof(hdr), type, len); /* Set it up */ git_deflate_init(&stream, zlib_compression_level); diff --git a/log-tree.c b/log-tree.c index 25165e2a91..38e5cccc1a 100644 --- a/log-tree.c +++ b/log-tree.c @@ -565,7 +565,7 @@ static int show_one_mergetag(struct commit *commit, struct strbuf signature = STRBUF_INIT; hash_object_file(the_hash_algo, extra->value, extra->len, - type_name(OBJ_TAG), &oid); + OBJ_TAG, &oid); tag = lookup_tag(the_repository, &oid); if (!tag) return -1; /* error message already given */ diff --git a/match-trees.c b/match-trees.c index df413989fa..49398e599f 100644 --- a/match-trees.c +++ b/match-trees.c @@ -235,7 +235,7 @@ static int splice_tree(const struct object_id *oid1, const char *prefix, rewrite_with = oid2; } hashcpy(rewrite_here, rewrite_with->hash); - status = write_object_file(buf, sz, tree_type, result); + status = write_object_file(buf, sz, OBJ_TREE, result); free(buf); return status; } diff --git a/merge-ort.c b/merge-ort.c index 97da477c7e..dc3fc0efc7 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -1938,7 +1938,7 @@ static int handle_content_merge(struct merge_options *opt, if (!ret && write_object_file(result_buf.ptr, result_buf.size, - blob_type, &result->oid)) + OBJ_BLOB, &result->oid)) ret = err(opt, _("Unable to add %s to database"), path); @@ -3392,7 +3392,7 @@ static void write_tree(struct object_id *result_oid, } /* Write this object file out, and record in result_oid */ - write_object_file(buf.buf, buf.len, tree_type, result_oid); + write_object_file(buf.buf, buf.len, OBJ_TREE, result_oid); strbuf_release(&buf); } diff --git a/merge-recursive.c b/merge-recursive.c index 9ec1e6d043..1ee6364e8b 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -1376,7 +1376,7 @@ static int merge_mode_and_contents(struct merge_options *opt, if (!ret && write_object_file(result_buf.ptr, result_buf.size, - blob_type, &result->blob.oid)) + OBJ_BLOB, &result->blob.oid)) ret = err(opt, _("Unable to add %s to database"), a->path); diff --git a/notes-cache.c b/notes-cache.c index 2473314d68..9dfd251a81 100644 --- a/notes-cache.c +++ b/notes-cache.c @@ -92,7 +92,7 @@ int notes_cache_put(struct notes_cache *c, struct object_id *key_oid, { struct object_id value_oid; - if (write_object_file(data, size, "blob", &value_oid) < 0) + if (write_object_file(data, size, OBJ_BLOB, &value_oid) < 0) return -1; return add_note(&c->tree, key_oid, &value_oid, NULL); } @@ -675,7 +675,7 @@ static int tree_write_stack_finish_subtree(struct tree_write_stack *tws) ret = tree_write_stack_finish_subtree(n); if (ret) return ret; - ret = write_object_file(n->buf.buf, n->buf.len, tree_type, &s); + ret = write_object_file(n->buf.buf, n->buf.len, OBJ_TREE, &s); if (ret) return ret; strbuf_release(&n->buf); @@ -836,7 +836,7 @@ int combine_notes_concatenate(struct object_id *cur_oid, free(new_msg); /* create a new blob object from buf */ - ret = write_object_file(buf, buf_len, blob_type, cur_oid); + ret = write_object_file(buf, buf_len, OBJ_BLOB, cur_oid); free(buf); return ret; } @@ -916,7 +916,7 @@ int combine_notes_cat_sort_uniq(struct object_id *cur_oid, string_list_join_lines_helper, &buf)) goto out; - ret = write_object_file(buf.buf, buf.len, blob_type, cur_oid); + ret = write_object_file(buf.buf, buf.len, OBJ_BLOB, cur_oid); out: strbuf_release(&buf); @@ -1192,7 +1192,7 @@ int write_notes_tree(struct notes_tree *t, struct object_id *result) ret = for_each_note(t, flags, write_each_note, &cb_data) || write_each_non_note_until(NULL, &cb_data) || tree_write_stack_finish_subtree(&root) || - write_object_file(root.buf.buf, root.buf.len, tree_type, result); + write_object_file(root.buf.buf, root.buf.len, OBJ_TREE, result); strbuf_release(&root.buf); return ret; } diff --git a/object-file.c b/object-file.c index 03bd6a3baf..bdc5cbdd38 100644 --- a/object-file.c +++ b/object-file.c @@ -1049,35 +1049,50 @@ void *xmmap(void *start, size_t length, return ret; } -/* - * With an in-core object data in "map", rehash it to make sure the - * object name actually matches "oid" to detect object corruption. - * With "map" == NULL, try reading the object named with "oid" using - * the streaming interface and rehash it to do the same. - */ +static int format_object_header_literally(char *str, size_t size, + const char *type, size_t objsize) +{ + return xsnprintf(str, size, "%s %"PRIuMAX, type, (uintmax_t)objsize) + 1; +} + +int format_object_header(char *str, size_t size, enum object_type type, + size_t objsize) +{ + const char *name = type_name(type); + + if (!name) + BUG("could not get a type name for 'enum object_type' value %d", type); + + return format_object_header_literally(str, size, name, objsize); +} + int check_object_signature(struct repository *r, const struct object_id *oid, - void *map, unsigned long size, const char *type, - struct object_id *real_oidp) + void *buf, unsigned long size, + enum object_type type) { - struct object_id tmp; - struct object_id *real_oid = real_oidp ? real_oidp : &tmp; + struct object_id real_oid; + + hash_object_file(r->hash_algo, buf, size, type, &real_oid); + + return !oideq(oid, &real_oid) ? -1 : 0; +} + +int stream_object_signature(struct repository *r, const struct object_id *oid) +{ + struct object_id real_oid; + unsigned long size; enum object_type obj_type; struct git_istream *st; git_hash_ctx c; char hdr[MAX_HEADER_LEN]; int hdrlen; - if (map) { - hash_object_file(r->hash_algo, map, size, type, real_oid); - return !oideq(oid, real_oid) ? -1 : 0; - } - st = open_istream(r, oid, &obj_type, &size, NULL); if (!st) return -1; /* Generate the header */ - hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX , type_name(obj_type), (uintmax_t)size) + 1; + hdrlen = format_object_header(hdr, sizeof(hdr), obj_type, size); /* Sha1.. */ r->hash_algo->init_fn(&c); @@ -1094,9 +1109,9 @@ int check_object_signature(struct repository *r, const struct object_id *oid, break; r->hash_algo->update_fn(&c, buf, readlen); } - r->hash_algo->final_oid_fn(real_oid, &c); + r->hash_algo->final_oid_fn(&real_oid, &c); close_istream(st); - return !oideq(oid, real_oid) ? -1 : 0; + return !oideq(oid, &real_oid) ? -1 : 0; } int git_open_cloexec(const char *name, int flags) @@ -1662,7 +1677,7 @@ int pretend_object_file(void *buf, unsigned long len, enum object_type type, { struct cached_object *co; - hash_object_file(the_hash_algo, buf, len, type_name(type), oid); + hash_object_file(the_hash_algo, buf, len, type, oid); if (has_object_file_with_flags(oid, OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT) || find_cached_object(oid)) return 0; @@ -1722,16 +1737,15 @@ void *read_object_file_extended(struct repository *r, void *read_object_with_reference(struct repository *r, const struct object_id *oid, - const char *required_type_name, + enum object_type required_type, unsigned long *size, struct object_id *actual_oid_return) { - enum object_type type, required_type; + enum object_type type; void *buffer; unsigned long isize; struct object_id actual_oid; - required_type = type_from_string(required_type_name); oidcpy(&actual_oid, oid); while (1) { int ref_length = -1; @@ -1769,21 +1783,40 @@ void *read_object_with_reference(struct repository *r, } } +static void hash_object_body(const struct git_hash_algo *algo, git_hash_ctx *c, + const void *buf, unsigned long len, + struct object_id *oid, + char *hdr, int *hdrlen) +{ + algo->init_fn(c); + algo->update_fn(c, hdr, *hdrlen); + algo->update_fn(c, buf, len); + algo->final_oid_fn(oid, c); +} + static void write_object_file_prepare(const struct git_hash_algo *algo, const void *buf, unsigned long len, - const char *type, struct object_id *oid, + enum object_type type, struct object_id *oid, char *hdr, int *hdrlen) { git_hash_ctx c; /* Generate the header */ - *hdrlen = xsnprintf(hdr, *hdrlen, "%s %"PRIuMAX , type, (uintmax_t)len)+1; + *hdrlen = format_object_header(hdr, *hdrlen, type, len); /* Sha1.. */ - algo->init_fn(&c); - algo->update_fn(&c, hdr, *hdrlen); - algo->update_fn(&c, buf, len); - algo->final_oid_fn(oid, &c); + hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen); +} + +static void write_object_file_prepare_literally(const struct git_hash_algo *algo, + const void *buf, unsigned long len, + const char *type, struct object_id *oid, + char *hdr, int *hdrlen) +{ + git_hash_ctx c; + + *hdrlen = format_object_header_literally(hdr, *hdrlen, type, len); + hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen); } /* @@ -1836,14 +1869,21 @@ static int write_buffer(int fd, const void *buf, size_t len) return 0; } -int hash_object_file(const struct git_hash_algo *algo, const void *buf, - unsigned long len, const char *type, - struct object_id *oid) +static void hash_object_file_literally(const struct git_hash_algo *algo, + const void *buf, unsigned long len, + const char *type, struct object_id *oid) { char hdr[MAX_HEADER_LEN]; int hdrlen = sizeof(hdr); - write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen); - return 0; + + write_object_file_prepare_literally(algo, buf, len, type, oid, hdr, &hdrlen); +} + +void hash_object_file(const struct git_hash_algo *algo, const void *buf, + unsigned long len, enum object_type type, + struct object_id *oid) +{ + hash_object_file_literally(algo, buf, len, type_name(type), oid); } /* Finalize a file on disk, and close it. */ @@ -1998,7 +2038,7 @@ static int freshen_packed_object(const struct object_id *oid) } int write_object_file_flags(const void *buf, unsigned long len, - const char *type, struct object_id *oid, + enum object_type type, struct object_id *oid, unsigned flags) { char hdr[MAX_HEADER_LEN]; @@ -2014,9 +2054,9 @@ int write_object_file_flags(const void *buf, unsigned long len, return write_loose_object(oid, hdr, hdrlen, buf, len, 0, flags); } -int hash_object_file_literally(const void *buf, unsigned long len, - const char *type, struct object_id *oid, - unsigned flags) +int write_object_file_literally(const void *buf, unsigned long len, + const char *type, struct object_id *oid, + unsigned flags) { char *header; int hdrlen, status = 0; @@ -2024,8 +2064,8 @@ int hash_object_file_literally(const void *buf, unsigned long len, /* type string, SP, %lu of the length plus NUL must fit this */ hdrlen = strlen(type) + MAX_HEADER_LEN; header = xmalloc(hdrlen); - write_object_file_prepare(the_hash_algo, buf, len, type, oid, header, - &hdrlen); + write_object_file_prepare_literally(the_hash_algo, buf, len, type, + oid, header, &hdrlen); if (!(flags & HASH_WRITE_OBJECT)) goto cleanup; @@ -2052,7 +2092,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime) buf = read_object(the_repository, oid, &type, &len); if (!buf) return error(_("cannot read object for %s"), oid_to_hex(oid)); - hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX , type_name(type), (uintmax_t)len) + 1; + hdrlen = format_object_header(hdr, sizeof(hdr), type, len); ret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime, 0); free(buf); @@ -2118,7 +2158,8 @@ static int index_mem(struct index_state *istate, enum object_type type, const char *path, unsigned flags) { - int ret, re_allocated = 0; + int ret = 0; + int re_allocated = 0; int write_object = flags & HASH_WRITE_OBJECT; if (!type) @@ -2145,10 +2186,9 @@ static int index_mem(struct index_state *istate, } if (write_object) - ret = write_object_file(buf, size, type_name(type), oid); + ret = write_object_file(buf, size, type, oid); else - ret = hash_object_file(the_hash_algo, buf, size, - type_name(type), oid); + hash_object_file(the_hash_algo, buf, size, type, oid); if (re_allocated) free(buf); return ret; @@ -2160,7 +2200,7 @@ static int index_stream_convert_blob(struct index_state *istate, const char *path, unsigned flags) { - int ret; + int ret = 0; const int write_object = flags & HASH_WRITE_OBJECT; struct strbuf sbuf = STRBUF_INIT; @@ -2171,11 +2211,11 @@ static int index_stream_convert_blob(struct index_state *istate, get_conv_flags(flags)); if (write_object) - ret = write_object_file(sbuf.buf, sbuf.len, type_name(OBJ_BLOB), + ret = write_object_file(sbuf.buf, sbuf.len, OBJ_BLOB, oid); else - ret = hash_object_file(the_hash_algo, sbuf.buf, sbuf.len, - type_name(OBJ_BLOB), oid); + hash_object_file(the_hash_algo, sbuf.buf, sbuf.len, OBJ_BLOB, + oid); strbuf_release(&sbuf); return ret; } @@ -2294,8 +2334,8 @@ int index_path(struct index_state *istate, struct object_id *oid, return error_errno("readlink(\"%s\")", path); if (!(flags & HASH_WRITE_OBJECT)) hash_object_file(the_hash_algo, sb.buf, sb.len, - blob_type, oid); - else if (write_object_file(sb.buf, sb.len, blob_type, oid)) + OBJ_BLOB, oid); + else if (write_object_file(sb.buf, sb.len, OBJ_BLOB, oid)) rc = error(_("%s: failed to insert into database"), path); strbuf_release(&sb); break; @@ -2599,9 +2639,10 @@ int read_loose_object(const char *path, git_inflate_end(&stream); goto out; } - if (check_object_signature(the_repository, expected_oid, + hash_object_file_literally(the_repository->hash_algo, *contents, *size, - oi->type_name->buf, real_oid)) + oi->type_name->buf, real_oid); + if (!oideq(expected_oid, real_oid)) goto out; } diff --git a/object-store.h b/object-store.h index 6f89482df0..bd2322ed8c 100644 --- a/object-store.h +++ b/object-store.h @@ -245,22 +245,22 @@ static inline void *repo_read_object_file(struct repository *r, /* Read and unpack an object file into memory, write memory to an object file */ int oid_object_info(struct repository *r, const struct object_id *, unsigned long *); -int hash_object_file(const struct git_hash_algo *algo, const void *buf, - unsigned long len, const char *type, - struct object_id *oid); +void hash_object_file(const struct git_hash_algo *algo, const void *buf, + unsigned long len, enum object_type type, + struct object_id *oid); int write_object_file_flags(const void *buf, unsigned long len, - const char *type, struct object_id *oid, + enum object_type type, struct object_id *oid, unsigned flags); static inline int write_object_file(const void *buf, unsigned long len, - const char *type, struct object_id *oid) + enum object_type type, struct object_id *oid) { return write_object_file_flags(buf, len, type, oid, 0); } -int hash_object_file_literally(const void *buf, unsigned long len, - const char *type, struct object_id *oid, - unsigned flags); +int write_object_file_literally(const void *buf, unsigned long len, + const char *type, struct object_id *oid, + unsigned flags); /* * Add an object file to the in-memory object store, without writing it @@ -331,6 +331,14 @@ int repo_has_object_file_with_flags(struct repository *r, */ int has_loose_object_nonlocal(const struct object_id *); +/** + * format_object_header() is a thin wrapper around s xsnprintf() that + * writes the initial "<type> <obj-len>" part of the loose object + * header. It returns the size that snprintf() returns + 1. + */ +int format_object_header(char *str, size_t size, enum object_type type, + size_t objsize); + void assert_oid_type(const struct object_id *oid, enum object_type expect); /* @@ -279,7 +279,7 @@ struct object *parse_object(struct repository *r, const struct object_id *oid) if ((obj && obj->type == OBJ_BLOB && repo_has_object_file(r, oid)) || (!obj && repo_has_object_file(r, oid) && oid_object_info(r, oid, NULL) == OBJ_BLOB)) { - if (check_object_signature(r, repl, NULL, 0, NULL, NULL) < 0) { + if (stream_object_signature(r, repl) < 0) { error(_("hash mismatch %s"), oid_to_hex(oid)); return NULL; } @@ -289,8 +289,7 @@ struct object *parse_object(struct repository *r, const struct object_id *oid) buffer = repo_read_object_file(r, oid, &type, &size); if (buffer) { - if (check_object_signature(r, repl, buffer, size, - type_name(type), NULL) < 0) { + if (check_object_signature(r, repl, buffer, size, type) < 0) { free(buffer); error(_("hash mismatch %s"), oid_to_hex(repl)); return NULL; diff --git a/pack-check.c b/pack-check.c index 3f418e3a6a..bfb593ba72 100644 --- a/pack-check.c +++ b/pack-check.c @@ -127,7 +127,7 @@ static int verify_packfile(struct repository *r, if (type == OBJ_BLOB && big_file_threshold <= size) { /* - * Let check_object_signature() check it with + * Let stream_object_signature() check it with * the streaming interface; no point slurping * the data in-core only to discard. */ @@ -142,8 +142,11 @@ static int verify_packfile(struct repository *r, err = error("cannot unpack %s from %s at offset %"PRIuMAX"", oid_to_hex(&oid), p->pack_name, (uintmax_t)entries[i].offset); - else if (check_object_signature(r, &oid, data, size, - type_name(type), NULL)) + else if (data && check_object_signature(r, &oid, data, size, + type) < 0) + err = error("packed %s from %s is corrupt", + oid_to_hex(&oid), p->pack_name); + else if (!data && stream_object_signature(r, &oid) < 0) err = error("packed %s from %s is corrupt", oid_to_hex(&oid), p->pack_name); else if (fn) { diff --git a/read-cache.c b/read-cache.c index 79b9b99ebf..1ad56d02e1 100644 --- a/read-cache.c +++ b/read-cache.c @@ -736,7 +736,7 @@ static struct cache_entry *create_alias_ce(struct index_state *istate, void set_object_name_for_intent_to_add_entry(struct cache_entry *ce) { struct object_id oid; - if (write_object_file("", 0, blob_type, &oid)) + if (write_object_file("", 0, OBJ_BLOB, &oid)) die(_("cannot create an empty blob in the object database")); oidcpy(&ce->oid, &oid); } diff --git a/tree-walk.c b/tree-walk.c index 3a94959d64..506234b4b8 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -89,7 +89,7 @@ void *fill_tree_descriptor(struct repository *r, void *buf = NULL; if (oid) { - buf = read_object_with_reference(r, oid, tree_type, &size, NULL); + buf = read_object_with_reference(r, oid, OBJ_TREE, &size, NULL); if (!buf) die("unable to read tree %s", oid_to_hex(oid)); } @@ -605,7 +605,7 @@ int get_tree_entry(struct repository *r, unsigned long size; struct object_id root; - tree = read_object_with_reference(r, tree_oid, tree_type, &size, &root); + tree = read_object_with_reference(r, tree_oid, OBJ_TREE, &size, &root); if (!tree) return -1; @@ -677,7 +677,7 @@ enum get_oid_result get_tree_entry_follow_symlinks(struct repository *r, unsigned long size; tree = read_object_with_reference(r, ¤t_tree_oid, - tree_type, &size, + OBJ_TREE, &size, &root); if (!tree) goto done; |