Add first cut at "fsck-cache" that validates the SHA1 object store.
[git/gitweb.git] / fsck-cache.c
blob81fd25a10050fd60d6f901191c9cc9e5cdb4f3d6
1 #include "cache.h"
3 #include <sys/types.h>
4 #include <dirent.h>
6 /*
7 * These three functions should build up a graph in memory about
8 * what objects we've referenced, and found, and types..
10 * Right now we don't do that kind of reachability checking. Yet.
12 static void fsck_tree(void *data, unsigned long size)
16 static void fsck_commit(void *data, unsigned long size)
20 static int mark_sha1_seen(unsigned char *sha1, char *tag)
22 return 0;
25 static int fsck_entry(unsigned char *sha1, char *tag, void *data, unsigned long size)
27 if (!strcmp(tag, "blob"))
28 /* Nothing to check */;
29 else if (!strcmp(tag, "tree"))
30 fsck_tree(data, size);
31 else if (!strcmp(tag, "commit"))
32 fsck_commit(data, size);
33 else
34 return -1;
35 return mark_sha1_seen(sha1, tag);
38 static int fsck_name(char *hex)
40 unsigned char sha1[20];
41 if (!get_sha1_hex(hex, sha1)) {
42 unsigned long mapsize;
43 void *map = map_sha1_file(sha1, &mapsize);
44 if (map) {
45 char type[100];
46 unsigned long size;
47 void *buffer = NULL;
48 if (!check_sha1_signature(sha1, map, mapsize))
49 buffer = unpack_sha1_file(map, mapsize, type, &size);
50 munmap(map, mapsize);
51 if (buffer && !fsck_entry(sha1, type, buffer, size))
52 return 0;
55 return -1;
58 static int fsck_dir(int i, char *path)
60 DIR *dir = opendir(path);
61 struct dirent *de;
63 if (!dir) {
64 fprintf(stderr, "missing sha1 directory '%s'", path);
65 return -1;
68 while ((de = readdir(dir)) != NULL) {
69 char name[100];
70 int len = strlen(de->d_name);
72 switch (len) {
73 case 2:
74 if (de->d_name[1] != '.')
75 break;
76 case 1:
77 if (de->d_name[0] != '.')
78 break;
79 continue;
80 case 38:
81 sprintf(name, "%02x", i);
82 memcpy(name+2, de->d_name, len+1);
83 if (!fsck_name(name))
84 continue;
86 fprintf(stderr, "bad sha1 file: %s/%s\n", path, de->d_name);
88 closedir(dir);
89 return 0;
92 int main(int argc, char **argv)
94 int i;
95 char *sha1_dir;
97 if (argc != 1)
98 usage("fsck-cache");
99 sha1_dir = getenv(DB_ENVIRONMENT) ? : DEFAULT_DB_ENVIRONMENT;
100 for (i = 0; i < 256; i++) {
101 static char dir[4096];
102 sprintf(dir, "%s/%02x", sha1_dir, i);
103 fsck_dir(i, dir);
105 return 0;