git/reftable/fsck.c

101 lines
2.0 KiB
C

#include "basics.h"
#include "reftable-fsck.h"
#include "reftable-table.h"
#include "stack.h"
static bool table_has_valid_name(const char *name)
{
const char *ptr = name;
char *endptr;
/* strtoull doesn't set errno on success */
errno = 0;
strtoull(ptr, &endptr, 16);
if (errno)
return false;
ptr = endptr;
if (*ptr != '-')
return false;
ptr++;
strtoull(ptr, &endptr, 16);
if (errno)
return false;
ptr = endptr;
if (*ptr != '-')
return false;
ptr++;
strtoul(ptr, &endptr, 16);
if (errno)
return false;
ptr = endptr;
if (strcmp(ptr, ".ref") && strcmp(ptr, ".log"))
return false;
return true;
}
typedef int (*table_check_fn)(struct reftable_table *table,
reftable_fsck_report_fn report_fn,
void *cb_data);
static int table_check_name(struct reftable_table *table,
reftable_fsck_report_fn report_fn,
void *cb_data)
{
if (!table_has_valid_name(table->name)) {
struct reftable_fsck_info info;
info.error = REFTABLE_FSCK_ERROR_TABLE_NAME;
info.msg = "invalid reftable table name";
info.path = table->name;
return report_fn(&info, cb_data);
}
return 0;
}
static int table_checks(struct reftable_table *table,
reftable_fsck_report_fn report_fn,
reftable_fsck_verbose_fn verbose_fn UNUSED,
void *cb_data)
{
table_check_fn table_check_fns[] = {
table_check_name,
NULL,
};
int err = 0;
for (size_t i = 0; table_check_fns[i]; i++)
err |= table_check_fns[i](table, report_fn, cb_data);
return err;
}
int reftable_fsck_check(struct reftable_stack *stack,
reftable_fsck_report_fn report_fn,
reftable_fsck_verbose_fn verbose_fn,
void *cb_data)
{
struct reftable_buf msg = REFTABLE_BUF_INIT;
int err = 0;
for (size_t i = 0; i < stack->tables_len; i++) {
reftable_buf_reset(&msg);
reftable_buf_addstr(&msg, "Checking table: ");
reftable_buf_addstr(&msg, stack->tables[i]->name);
verbose_fn(msg.buf, cb_data);
err |= table_checks(stack->tables[i], report_fn, verbose_fn, cb_data);
}
reftable_buf_release(&msg);
return err;
}