{"thread":{"id":"26343","subject":"[PATCH] fsck: do not give up too early in fsck_dir()","startedAt":"2011-01-26T21:01:54Z","lastAt":"2011-01-26T21:01:54Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"159914","messageId":"7vlj27js59.fsf@alter.siamese.dyndns.org","threadId":"26343","inReplyTo":null,"subject":"[PATCH] fsck: do not give up too early in fsck_dir()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-01-26T21:01:54Z","receivedAt":"2011-01-26T21:01:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"When there is a random garbage file whose name happens to be 38-byte\nlong in a .git/objects/??/ directory, the loop terminated prematurely\nwithout marking all the other files that it hasn't checked in the\nreaddir() loop.\n\nTreat such a file just like any other garbage file, and do not break out\nof the readdir() loop.\n\nWhile at it, replace repeated sprintf() calls to a single one outside the\nloop.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\n * For readability, I think it also makes sense to move the surrounding\n   code so that \"tmp_obj_\" check and the \"is_dot_or_dotdot\" check are next\n   to each other, as they are both in \"we know this is not a loose object\n   file, and we don't want to warn about its existence\" category, but that\n   is a minor point.\n\n builtin/fsck.c |   18 ++++++++++++------\n 1 files changed, 12 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex 91409a0..795aba0 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -392,10 +392,20 @@ static void add_sha1_list(unsigned char *sha1, unsigned long ino)\n \tsha1_list.nr = ++nr;\n }\n \n+static inline int is_loose_object_file(struct dirent *de,\n+\t\t\t\t       char *name, unsigned char *sha1)\n+{\n+\tif (strlen(de->d_name) != 38)\n+\t\treturn 0;\n+\tmemcpy(name + 2, de->d_name, 39);\n+\treturn !get_sha1_hex(name, sha1);\n+}\n+\n static void fsck_dir(int i, char *path)\n {\n \tDIR *dir = opendir(path);\n \tstruct dirent *de;\n+\tchar name[100];\n \n \tif (!dir)\n \t\treturn;\n@@ -403,17 +413,13 @@ static void fsck_dir(int i, char *path)\n \tif (verbose)\n \t\tfprintf(stderr, \"Checking directory %s\\n\", path);\n \n+\tsprintf(name, \"%02x\", i);\n \twhile ((de = readdir(dir)) != NULL) {\n-\t\tchar name[100];\n \t\tunsigned char sha1[20];\n \n \t\tif (is_dot_or_dotdot(de->d_name))\n \t\t\tcontinue;\n-\t\tif (strlen(de->d_name) == 38) {\n-\t\t\tsprintf(name, \"%02x\", i);\n-\t\t\tmemcpy(name+2, de->d_name, 39);\n-\t\t\tif (get_sha1_hex(name, sha1) < 0)\n-\t\t\t\tbreak;\n+\t\tif (is_loose_object_file(de, name, sha1)) {\n \t\t\tadd_sha1_list(sha1, DIRENT_SORT_HINT(de));\n \t\t\tcontinue;\n \t\t}\n"}]}