1
+#include "basics.h"
2
+#include "reftable-fsck.h"
3
+#include "reftable-table.h"
4
+#include "stack.h"
5
+
6
+static bool table_has_valid_name(const char *name)
7
+{
8
+ const char *ptr = name;
9
+ char *endptr;
10
+
11
+ /* strtoull doesn't set errno on success */
12
+ errno = 0;
13
+
14
+ strtoull(ptr, &endptr, 16);
15
+ if (errno)
16
+ return false;
17
+ ptr = endptr;
18
+
19
+ if (*ptr != '-')
20
+ return false;
21
+ ptr++;
22
+
23
+ strtoull(ptr, &endptr, 16);
24
+ if (errno)
25
+ return false;
26
+ ptr = endptr;
27
+
28
+ if (*ptr != '-')
29
+ return false;
30
+ ptr++;
31
+
32
+ strtoul(ptr, &endptr, 16);
33
+ if (errno)
34
+ return false;
35
+ ptr = endptr;
36
+
37
+ if (strcmp(ptr, ".ref") && strcmp(ptr, ".log"))
38
+ return false;
39
+
40
+ return true;
41
+}
42
+
43
+typedef int (*table_check_fn)(struct reftable_table *table,
44
+ reftable_fsck_report_fn report_fn,
45
+ void *cb_data);
46
+
47
+static int table_check_name(struct reftable_table *table,
48
+ reftable_fsck_report_fn report_fn,
49
+ void *cb_data)
50
+{
51
+ if (!table_has_valid_name(table->name)) {
52
+ struct reftable_fsck_info info;
53
+
54
+ info.error = REFTABLE_FSCK_ERROR_TABLE_NAME;
55
+ info.msg = "invalid reftable table name";
56
+ info.path = table->name;
57
+
58
+ return report_fn(&info, cb_data);
59
+ }
60
+
61
+ return 0;
62
+}
63
+
64
+static int table_checks(struct reftable_table *table,
65
+ reftable_fsck_report_fn report_fn,
66
+ reftable_fsck_verbose_fn verbose_fn UNUSED,
67
+ void *cb_data)
68
+{
69
+ table_check_fn table_check_fns[] = {
70
+ table_check_name,
71
+ NULL,
72
+ };
73
+ int err = 0;
74
+
75
+ for (size_t i = 0; table_check_fns[i]; i++)
76
+ err |= table_check_fns[i](table, report_fn, cb_data);
77
+
78
+ return err;
79
+}
80
+
81
+int reftable_fsck_check(struct reftable_stack *stack,
82
+ reftable_fsck_report_fn report_fn,
83
+ reftable_fsck_verbose_fn verbose_fn,
84
+ void *cb_data)
85
+{
86
+ struct reftable_buf msg = REFTABLE_BUF_INIT;
87
+ int err = 0;
88
+
89
+ for (size_t i = 0; i < stack->tables_len; i++) {
90
+ reftable_buf_reset(&msg);
91
+ reftable_buf_addstr(&msg, "Checking table: ");
92
+ reftable_buf_addstr(&msg, stack->tables[i]->name);
93
+ verbose_fn(msg.buf, cb_data);
94
+
95
+ err |= table_checks(stack->tables[i], report_fn, verbose_fn, cb_data);
96
+ }
97
+
98
+ reftable_buf_release(&msg);
99
+ return err;
100
+}