diff options
Diffstat (limited to 'builtin/fsck.c')
-rw-r--r-- | builtin/fsck.c | 190 |
1 files changed, 52 insertions, 138 deletions
diff --git a/builtin/fsck.c b/builtin/fsck.c index b9a74f0cf6..55eac756f7 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -40,14 +40,6 @@ static int show_dangling = 1; #define ERROR_PACK 04 #define ERROR_REFS 010 -#ifdef NO_D_INO_IN_DIRENT -#define SORT_DIRENT 0 -#define DIRENT_SORT_HINT(de) 0 -#else -#define SORT_DIRENT 1 -#define DIRENT_SORT_HINT(de) ((de)->d_ino) -#endif - static int fsck_config(const char *var, const char *value, void *cb) { if (strcmp(var, "fsck.skiplist") == 0) { @@ -75,7 +67,7 @@ static void objreport(struct object *obj, const char *msg_type, const char *err) { fprintf(stderr, "%s in %s %s: %s\n", - msg_type, typename(obj->type), sha1_to_hex(obj->sha1), err); + msg_type, typename(obj->type), oid_to_hex(&obj->oid), err); } static int objerror(struct object *obj, const char *err) @@ -105,7 +97,7 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt if (!obj) { /* ... these references to parent->fld are safe here */ printf("broken link from %7s %s\n", - typename(parent->type), sha1_to_hex(parent->sha1)); + typename(parent->type), oid_to_hex(&parent->oid)); printf("broken link from %7s %s\n", (type == OBJ_ANY ? "unknown" : typename(type)), "unknown"); errors_found |= ERROR_REACHABLE; @@ -120,11 +112,11 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt return 0; obj->flags |= REACHABLE; if (!(obj->flags & HAS_OBJ)) { - if (parent && !has_sha1_file(obj->sha1)) { + if (parent && !has_object_file(&obj->oid)) { printf("broken link from %7s %s\n", - typename(parent->type), sha1_to_hex(parent->sha1)); + typename(parent->type), oid_to_hex(&parent->oid)); printf(" to %7s %s\n", - typename(obj->type), sha1_to_hex(obj->sha1)); + typename(obj->type), oid_to_hex(&obj->oid)); errors_found |= ERROR_REACHABLE; } return 1; @@ -194,11 +186,11 @@ static void check_reachable_object(struct object *obj) * do a full fsck */ if (!(obj->flags & HAS_OBJ)) { - if (has_sha1_pack(obj->sha1)) + if (has_sha1_pack(obj->oid.hash)) return; /* it is in pack - forget about it */ - if (connectivity_only && has_sha1_file(obj->sha1)) + if (connectivity_only && has_object_file(&obj->oid)) return; - printf("missing %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1)); + printf("missing %s %s\n", typename(obj->type), oid_to_hex(&obj->oid)); errors_found |= ERROR_REACHABLE; return; } @@ -223,7 +215,7 @@ static void check_unreachable_object(struct object *obj) * since this is something that is prunable. */ if (show_unreachable) { - printf("unreachable %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1)); + printf("unreachable %s %s\n", typename(obj->type), oid_to_hex(&obj->oid)); return; } @@ -242,11 +234,11 @@ static void check_unreachable_object(struct object *obj) if (!obj->used) { if (show_dangling) printf("dangling %s %s\n", typename(obj->type), - sha1_to_hex(obj->sha1)); + oid_to_hex(&obj->oid)); if (write_lost_and_found) { char *filename = git_pathdup("lost-found/%s/%s", obj->type == OBJ_COMMIT ? "commit" : "other", - sha1_to_hex(obj->sha1)); + oid_to_hex(&obj->oid)); FILE *f; if (safe_create_leading_directories_const(filename)) { @@ -257,10 +249,10 @@ static void check_unreachable_object(struct object *obj) if (!(f = fopen(filename, "w"))) die_errno("Could not open '%s'", filename); if (obj->type == OBJ_BLOB) { - if (stream_blob_to_fd(fileno(f), obj->sha1, NULL, 1)) + if (stream_blob_to_fd(fileno(f), obj->oid.hash, NULL, 1)) die_errno("Could not write '%s'", filename); } else - fprintf(f, "%s\n", sha1_to_hex(obj->sha1)); + fprintf(f, "%s\n", oid_to_hex(&obj->oid)); if (fclose(f)) die_errno("Could not finish '%s'", filename); @@ -279,7 +271,7 @@ static void check_unreachable_object(struct object *obj) static void check_object(struct object *obj) { if (verbose) - fprintf(stderr, "Checking %s\n", sha1_to_hex(obj->sha1)); + fprintf(stderr, "Checking %s\n", oid_to_hex(&obj->oid)); if (obj->flags & REACHABLE) check_reachable_object(obj); @@ -315,7 +307,7 @@ static int fsck_obj(struct object *obj) if (verbose) fprintf(stderr, "Checking %s %s\n", - typename(obj->type), sha1_to_hex(obj->sha1)); + typename(obj->type), oid_to_hex(&obj->oid)); if (fsck_walk(obj, NULL, &fsck_obj_options)) objerror(obj, "broken links"); @@ -334,15 +326,15 @@ static int fsck_obj(struct object *obj) free_commit_buffer(commit); if (!commit->parents && show_root) - printf("root %s\n", sha1_to_hex(commit->object.sha1)); + printf("root %s\n", oid_to_hex(&commit->object.oid)); } if (obj->type == OBJ_TAG) { struct tag *tag = (struct tag *) obj; if (show_tags && tag->tagged) { - printf("tagged %s %s", typename(tag->tagged->type), sha1_to_hex(tag->tagged->sha1)); - printf(" (%s) in %s\n", tag->tag, sha1_to_hex(tag->object.sha1)); + printf("tagged %s %s", typename(tag->tagged->type), oid_to_hex(&tag->tagged->oid)); + printf(" (%s) in %s\n", tag->tag, oid_to_hex(&tag->object.oid)); } } @@ -374,102 +366,6 @@ static int fsck_obj_buffer(const unsigned char *sha1, enum object_type type, return fsck_obj(obj); } -/* - * This is the sorting chunk size: make it reasonably - * big so that we can sort well.. - */ -#define MAX_SHA1_ENTRIES (1024) - -struct sha1_entry { - unsigned long ino; - unsigned char sha1[20]; -}; - -static struct { - unsigned long nr; - struct sha1_entry *entry[MAX_SHA1_ENTRIES]; -} sha1_list; - -static int ino_compare(const void *_a, const void *_b) -{ - const struct sha1_entry *a = _a, *b = _b; - unsigned long ino1 = a->ino, ino2 = b->ino; - return ino1 < ino2 ? -1 : ino1 > ino2 ? 1 : 0; -} - -static void fsck_sha1_list(void) -{ - int i, nr = sha1_list.nr; - - if (SORT_DIRENT) - qsort(sha1_list.entry, nr, - sizeof(struct sha1_entry *), ino_compare); - for (i = 0; i < nr; i++) { - struct sha1_entry *entry = sha1_list.entry[i]; - unsigned char *sha1 = entry->sha1; - - sha1_list.entry[i] = NULL; - if (fsck_sha1(sha1)) - errors_found |= ERROR_OBJECT; - free(entry); - } - sha1_list.nr = 0; -} - -static void add_sha1_list(unsigned char *sha1, unsigned long ino) -{ - struct sha1_entry *entry = xmalloc(sizeof(*entry)); - int nr; - - entry->ino = ino; - hashcpy(entry->sha1, sha1); - nr = sha1_list.nr; - if (nr == MAX_SHA1_ENTRIES) { - fsck_sha1_list(); - nr = 0; - } - sha1_list.entry[nr] = entry; - sha1_list.nr = ++nr; -} - -static inline int is_loose_object_file(struct dirent *de, - char *name, unsigned char *sha1) -{ - if (strlen(de->d_name) != 38) - return 0; - memcpy(name + 2, de->d_name, 39); - return !get_sha1_hex(name, sha1); -} - -static void fsck_dir(int i, char *path) -{ - DIR *dir = opendir(path); - struct dirent *de; - char name[100]; - - if (!dir) - return; - - if (verbose) - fprintf(stderr, "Checking directory %s\n", path); - - sprintf(name, "%02x", i); - while ((de = readdir(dir)) != NULL) { - unsigned char sha1[20]; - - if (is_dot_or_dotdot(de->d_name)) - continue; - if (is_loose_object_file(de, name, sha1)) { - add_sha1_list(sha1, DIRENT_SORT_HINT(de)); - continue; - } - if (starts_with(de->d_name, "tmp_obj_")) - continue; - fprintf(stderr, "bad sha1 file: %s/%s\n", path, de->d_name); - } - closedir(dir); -} - static int default_refs; static void fsck_handle_reflog_sha1(const char *refname, unsigned char *sha1) @@ -559,9 +455,28 @@ static void get_default_heads(void) } } +static int fsck_loose(const unsigned char *sha1, const char *path, void *data) +{ + if (fsck_sha1(sha1)) + errors_found |= ERROR_OBJECT; + return 0; +} + +static int fsck_cruft(const char *basename, const char *path, void *data) +{ + if (!starts_with(basename, "tmp_obj_")) + fprintf(stderr, "bad sha1 file: %s\n", path); + return 0; +} + +static int fsck_subdir(int nr, const char *path, void *progress) +{ + display_progress(progress, nr + 1); + return 0; +} + static void fsck_object_dir(const char *path) { - int i; struct progress *progress = NULL; if (verbose) @@ -569,14 +484,11 @@ static void fsck_object_dir(const char *path) if (show_progress) progress = start_progress(_("Checking object directories"), 256); - for (i = 0; i < 256; i++) { - static char dir[4096]; - sprintf(dir, "%s/%02x", path, i); - fsck_dir(i, dir); - display_progress(progress, i+1); - } + + for_each_loose_file_in_objdir(path, fsck_loose, fsck_cruft, fsck_subdir, + progress); + display_progress(progress, 256); stop_progress(&progress); - fsck_sha1_list(); } static int fsck_head_link(void) @@ -688,16 +600,18 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) git_config(fsck_config, NULL); fsck_head_link(); - if (!connectivity_only) + if (!connectivity_only) { fsck_object_dir(get_object_directory()); - prepare_alt_odb(); - for (alt = alt_odb_list; alt; alt = alt->next) { - char namebuf[PATH_MAX]; - int namelen = alt->name - alt->base; - memcpy(namebuf, alt->base, namelen); - namebuf[namelen - 1] = 0; - fsck_object_dir(namebuf); + prepare_alt_odb(); + for (alt = alt_odb_list; alt; alt = alt->next) { + /* directory name, minus trailing slash */ + size_t namelen = alt->name - alt->base - 1; + struct strbuf name = STRBUF_INIT; + strbuf_add(&name, alt->base, namelen); + fsck_object_dir(name.buf); + strbuf_release(&name); + } } if (check_full) { |