diff options
Diffstat (limited to 'reftable')
| -rw-r--r-- | reftable/basics.c | 37 | ||||
| -rw-r--r-- | reftable/basics.h | 7 | ||||
| -rw-r--r-- | reftable/fsck.c | 100 | ||||
| -rw-r--r-- | reftable/reftable-fsck.h | 40 | ||||
| -rw-r--r-- | reftable/reftable-stack.h | 9 | ||||
| -rw-r--r-- | reftable/reftable-writer.h | 4 | ||||
| -rw-r--r-- | reftable/stack.c | 446 | ||||
| -rw-r--r-- | reftable/system.c | 2 | ||||
| -rw-r--r-- | reftable/system.h | 4 | ||||
| -rw-r--r-- | reftable/writer.c | 23 |
10 files changed, 407 insertions, 265 deletions
diff --git a/reftable/basics.c b/reftable/basics.c index 9988ebd635..e969927b61 100644 --- a/reftable/basics.c +++ b/reftable/basics.c @@ -195,44 +195,55 @@ size_t names_length(const char **names) return p - names; } -char **parse_names(char *buf, int size) +int parse_names(char *buf, int size, char ***out) { char **names = NULL; size_t names_cap = 0; size_t names_len = 0; char *p = buf; char *end = buf + size; + int err = 0; while (p < end) { char *next = strchr(p, '\n'); - if (next && next < end) { - *next = 0; + if (!next) { + err = REFTABLE_FORMAT_ERROR; + goto done; + } else if (next < end) { + *next = '\0'; } else { next = end; } + if (p < next) { if (REFTABLE_ALLOC_GROW(names, names_len + 1, - names_cap)) - goto err; + names_cap)) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } names[names_len] = reftable_strdup(p); - if (!names[names_len++]) - goto err; + if (!names[names_len++]) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } } p = next + 1; } - if (REFTABLE_ALLOC_GROW(names, names_len + 1, names_cap)) - goto err; + if (REFTABLE_ALLOC_GROW(names, names_len + 1, names_cap)) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto done; + } names[names_len] = NULL; - return names; - -err: + *out = names; + return 0; +done: for (size_t i = 0; i < names_len; i++) reftable_free(names[i]); reftable_free(names); - return NULL; + return err; } int names_equal(const char **a, const char **b) diff --git a/reftable/basics.h b/reftable/basics.h index 7d22f96261..e4b83b2b03 100644 --- a/reftable/basics.h +++ b/reftable/basics.h @@ -167,10 +167,11 @@ void free_names(char **a); /* * Parse a newline separated list of names. `size` is the length of the buffer, - * without terminating '\0'. Empty names are discarded. Returns a `NULL` - * pointer when allocations fail. + * without terminating '\0'. Empty names are discarded. + * + * Returns 0 on success, a reftable error code on error. */ -char **parse_names(char *buf, int size); +int parse_names(char *buf, int size, char ***out); /* compares two NULL-terminated arrays of strings. */ int names_equal(const char **a, const char **b); diff --git a/reftable/fsck.c b/reftable/fsck.c new file mode 100644 index 0000000000..26b9115b14 --- /dev/null +++ b/reftable/fsck.c @@ -0,0 +1,100 @@ +#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; +} diff --git a/reftable/reftable-fsck.h b/reftable/reftable-fsck.h new file mode 100644 index 0000000000..007a392cf9 --- /dev/null +++ b/reftable/reftable-fsck.h @@ -0,0 +1,40 @@ +#ifndef REFTABLE_FSCK_H +#define REFTABLE_FSCK_H + +#include "reftable-stack.h" + +enum reftable_fsck_error { + /* Invalid table name */ + REFTABLE_FSCK_ERROR_TABLE_NAME = 0, + /* Used for bounds checking, must be last */ + REFTABLE_FSCK_MAX_VALUE, +}; + +/* Represents an individual error encountered during the FSCK checks. */ +struct reftable_fsck_info { + enum reftable_fsck_error error; + const char *msg; + const char *path; +}; + +typedef int reftable_fsck_report_fn(struct reftable_fsck_info *info, + void *cb_data); +typedef void reftable_fsck_verbose_fn(const char *msg, void *cb_data); + +/* + * Given a reftable stack, perform consistency checks on the stack. + * + * If an issue is encountered, the issue is reported to the callee via the + * provided 'report_fn'. If the issue is non-recoverable the flow will not + * continue. If it is recoverable, the flow will continue and further issues + * will be reported as identified. + * + * The 'verbose_fn' will be invoked to provide verbose information about + * the progress and state of the consistency checks. + */ +int reftable_fsck_check(struct reftable_stack *stack, + reftable_fsck_report_fn report_fn, + reftable_fsck_verbose_fn verbose_fn, + void *cb_data); + +#endif /* REFTABLE_FSCK_H */ diff --git a/reftable/reftable-stack.h b/reftable/reftable-stack.h index 910ec6ef3a..d70fcb705d 100644 --- a/reftable/reftable-stack.h +++ b/reftable/reftable-stack.h @@ -68,12 +68,15 @@ int reftable_addition_commit(struct reftable_addition *add); * transaction. Releases the lock if held. */ void reftable_addition_destroy(struct reftable_addition *add); -/* add a new table to the stack. The write_table function must call - * reftable_writer_set_limits, add refs and return an error value. */ +/* + * Add a new table to the stack. The write_table function must call + * reftable_writer_set_limits, add refs and return an error value. + * The flags are passed through to `reftable_stack_new_addition()`. + */ int reftable_stack_add(struct reftable_stack *st, int (*write_table)(struct reftable_writer *wr, void *write_arg), - void *write_arg); + void *write_arg, unsigned flags); struct reftable_iterator; diff --git a/reftable/reftable-writer.h b/reftable/reftable-writer.h index 0fbeff17f4..1e7003cd69 100644 --- a/reftable/reftable-writer.h +++ b/reftable/reftable-writer.h @@ -156,7 +156,7 @@ int reftable_writer_add_ref(struct reftable_writer *w, the records before adding them, reordering the records array passed in. */ int reftable_writer_add_refs(struct reftable_writer *w, - struct reftable_ref_record *refs, int n); + struct reftable_ref_record *refs, size_t n); /* adds reftable_log_records. Log records are keyed by (refname, decreasing @@ -171,7 +171,7 @@ int reftable_writer_add_log(struct reftable_writer *w, the records before adding them, reordering records array passed in. */ int reftable_writer_add_logs(struct reftable_writer *w, - struct reftable_log_record *logs, int n); + struct reftable_log_record *logs, size_t n); /* reftable_writer_close finalizes the reftable. The writer is retained so * statistics can be inspected. */ diff --git a/reftable/stack.c b/reftable/stack.c index 4caf96aa1d..65d89820bd 100644 --- a/reftable/stack.c +++ b/reftable/stack.c @@ -17,18 +17,6 @@ #include "table.h" #include "writer.h" -static int stack_try_add(struct reftable_stack *st, - int (*write_table)(struct reftable_writer *wr, - void *arg), - void *arg); -static int stack_write_compact(struct reftable_stack *st, - struct reftable_writer *wr, - size_t first, size_t last, - struct reftable_log_expiry_config *config); -static void reftable_addition_close(struct reftable_addition *add); -static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st, - int reuse_open); - static int stack_filename(struct reftable_buf *dest, struct reftable_stack *st, const char *name) { @@ -84,54 +72,6 @@ static int fd_writer_flush(void *arg) return stack_fsync(writer->opts, writer->fd); } -int reftable_new_stack(struct reftable_stack **dest, const char *dir, - const struct reftable_write_options *_opts) -{ - struct reftable_buf list_file_name = REFTABLE_BUF_INIT; - struct reftable_write_options opts = { 0 }; - struct reftable_stack *p; - int err; - - p = reftable_calloc(1, sizeof(*p)); - if (!p) { - err = REFTABLE_OUT_OF_MEMORY_ERROR; - goto out; - } - - if (_opts) - opts = *_opts; - if (opts.hash_id == 0) - opts.hash_id = REFTABLE_HASH_SHA1; - - *dest = NULL; - - reftable_buf_reset(&list_file_name); - if ((err = reftable_buf_addstr(&list_file_name, dir)) < 0 || - (err = reftable_buf_addstr(&list_file_name, "/tables.list")) < 0) - goto out; - - p->list_file = reftable_buf_detach(&list_file_name); - p->list_fd = -1; - p->opts = opts; - p->reftable_dir = reftable_strdup(dir); - if (!p->reftable_dir) { - err = REFTABLE_OUT_OF_MEMORY_ERROR; - goto out; - } - - err = reftable_stack_reload_maybe_reuse(p, 1); - if (err < 0) - goto out; - - *dest = p; - err = 0; - -out: - if (err < 0) - reftable_stack_destroy(p); - return err; -} - static int fd_read_lines(int fd, char ***namesp) { char *buf = NULL; @@ -169,12 +109,7 @@ static int fd_read_lines(int fd, char ***namesp) } buf[size] = 0; - *namesp = parse_names(buf, size); - if (!*namesp) { - err = REFTABLE_OUT_OF_MEMORY_ERROR; - goto done; - } - + err = parse_names(buf, size, namesp); done: reftable_free(buf); return err; @@ -591,9 +526,59 @@ out: return err; } -/* -1 = error - 0 = up to date - 1 = changed. */ +int reftable_new_stack(struct reftable_stack **dest, const char *dir, + const struct reftable_write_options *_opts) +{ + struct reftable_buf list_file_name = REFTABLE_BUF_INIT; + struct reftable_write_options opts = { 0 }; + struct reftable_stack *p; + int err; + + p = reftable_calloc(1, sizeof(*p)); + if (!p) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto out; + } + + if (_opts) + opts = *_opts; + if (opts.hash_id == 0) + opts.hash_id = REFTABLE_HASH_SHA1; + + *dest = NULL; + + reftable_buf_reset(&list_file_name); + if ((err = reftable_buf_addstr(&list_file_name, dir)) < 0 || + (err = reftable_buf_addstr(&list_file_name, "/tables.list")) < 0) + goto out; + + p->list_file = reftable_buf_detach(&list_file_name); + p->list_fd = -1; + p->opts = opts; + p->reftable_dir = reftable_strdup(dir); + if (!p->reftable_dir) { + err = REFTABLE_OUT_OF_MEMORY_ERROR; + goto out; + } + + err = reftable_stack_reload_maybe_reuse(p, 1); + if (err < 0) + goto out; + + *dest = p; + err = 0; + +out: + if (err < 0) + reftable_stack_destroy(p); + return err; +} + +/* + * Check whether the given stack is up-to-date with what we have in memory. + * Returns 0 if so, 1 if the stack is out-of-date or a negative error code + * otherwise. + */ static int stack_uptodate(struct reftable_stack *st) { char **names = NULL; @@ -667,34 +652,6 @@ int reftable_stack_reload(struct reftable_stack *st) return err; } -int reftable_stack_add(struct reftable_stack *st, - int (*write)(struct reftable_writer *wr, void *arg), - void *arg) -{ - int err = stack_try_add(st, write, arg); - if (err < 0) { - if (err == REFTABLE_OUTDATED_ERROR) { - /* Ignore error return, we want to propagate - REFTABLE_OUTDATED_ERROR. - */ - reftable_stack_reload(st); - } - return err; - } - - return 0; -} - -static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max) -{ - char buf[100]; - uint32_t rnd = reftable_rand(); - snprintf(buf, sizeof(buf), "0x%012" PRIx64 "-0x%012" PRIx64 "-%08x", - min, max, rnd); - reftable_buf_reset(dest); - return reftable_buf_addstr(dest, buf); -} - struct reftable_addition { struct reftable_flock tables_list_lock; struct reftable_stack *stack; @@ -704,7 +661,25 @@ struct reftable_addition { uint64_t next_update_index; }; -#define REFTABLE_ADDITION_INIT {0} +static void reftable_addition_close(struct reftable_addition *add) +{ + struct reftable_buf nm = REFTABLE_BUF_INIT; + size_t i; + + for (i = 0; i < add->new_tables_len; i++) { + if (!stack_filename(&nm, add->stack, add->new_tables[i])) + unlink(nm.buf); + reftable_free(add->new_tables[i]); + add->new_tables[i] = NULL; + } + reftable_free(add->new_tables); + add->new_tables = NULL; + add->new_tables_len = 0; + add->new_tables_cap = 0; + + flock_release(&add->tables_list_lock); + reftable_buf_release(&nm); +} static int reftable_stack_init_addition(struct reftable_addition *add, struct reftable_stack *st, @@ -713,18 +688,14 @@ static int reftable_stack_init_addition(struct reftable_addition *add, struct reftable_buf lock_file_name = REFTABLE_BUF_INIT; int err; + memset(add, 0, sizeof(*add)); add->stack = st; err = flock_acquire(&add->tables_list_lock, st->list_file, st->opts.lock_timeout_ms); - if (err < 0) { - if (errno == EEXIST) { - err = REFTABLE_LOCK_ERROR; - } else { - err = REFTABLE_IO_ERROR; - } + if (err < 0) goto done; - } + if (st->opts.default_permissions) { if (chmod(add->tables_list_lock.path, st->opts.default_permissions) < 0) { @@ -754,24 +725,54 @@ done: return err; } -static void reftable_addition_close(struct reftable_addition *add) +static int stack_try_add(struct reftable_stack *st, + int (*write_table)(struct reftable_writer *wr, + void *arg), + void *arg, unsigned flags) { - struct reftable_buf nm = REFTABLE_BUF_INIT; - size_t i; + struct reftable_addition add; + int err; - for (i = 0; i < add->new_tables_len; i++) { - if (!stack_filename(&nm, add->stack, add->new_tables[i])) - unlink(nm.buf); - reftable_free(add->new_tables[i]); - add->new_tables[i] = NULL; + err = reftable_stack_init_addition(&add, st, flags); + if (err < 0) + goto done; + + err = reftable_addition_add(&add, write_table, arg); + if (err < 0) + goto done; + + err = reftable_addition_commit(&add); +done: + reftable_addition_close(&add); + return err; +} + +int reftable_stack_add(struct reftable_stack *st, + int (*write)(struct reftable_writer *wr, void *arg), + void *arg, unsigned flags) +{ + int err = stack_try_add(st, write, arg, flags); + if (err < 0) { + if (err == REFTABLE_OUTDATED_ERROR) { + /* Ignore error return, we want to propagate + REFTABLE_OUTDATED_ERROR. + */ + reftable_stack_reload(st); + } + return err; } - reftable_free(add->new_tables); - add->new_tables = NULL; - add->new_tables_len = 0; - add->new_tables_cap = 0; - flock_release(&add->tables_list_lock); - reftable_buf_release(&nm); + return 0; +} + +static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max) +{ + char buf[100]; + uint32_t rnd = reftable_rand(); + snprintf(buf, sizeof(buf), "0x%012" PRIx64 "-0x%012" PRIx64 "-%08x", + min, max, rnd); + reftable_buf_reset(dest); + return reftable_buf_addstr(dest, buf); } void reftable_addition_destroy(struct reftable_addition *add) @@ -841,10 +842,13 @@ int reftable_addition_commit(struct reftable_addition *add) * control. It is possible that a concurrent writer is already * trying to compact parts of the stack, which would lead to a * `REFTABLE_LOCK_ERROR` because parts of the stack are locked - * already. This is a benign error though, so we ignore it. + * already. Similarly, the stack may have been rewritten by a + * concurrent writer, which causes `REFTABLE_OUTDATED_ERROR`. + * Both of these errors are benign, so we simply ignore them. */ err = reftable_stack_auto_compact(add->stack); - if (err < 0 && err != REFTABLE_LOCK_ERROR) + if (err < 0 && err != REFTABLE_LOCK_ERROR && + err != REFTABLE_OUTDATED_ERROR) goto done; err = 0; } @@ -858,39 +862,18 @@ int reftable_stack_new_addition(struct reftable_addition **dest, struct reftable_stack *st, unsigned int flags) { - int err = 0; - struct reftable_addition empty = REFTABLE_ADDITION_INIT; + int err; REFTABLE_CALLOC_ARRAY(*dest, 1); if (!*dest) return REFTABLE_OUT_OF_MEMORY_ERROR; - **dest = empty; err = reftable_stack_init_addition(*dest, st, flags); if (err) { reftable_free(*dest); *dest = NULL; } - return err; -} -static int stack_try_add(struct reftable_stack *st, - int (*write_table)(struct reftable_writer *wr, - void *arg), - void *arg) -{ - struct reftable_addition add = REFTABLE_ADDITION_INIT; - int err = reftable_stack_init_addition(&add, st, 0); - if (err < 0) - goto done; - - err = reftable_addition_add(&add, write_table, arg); - if (err < 0) - goto done; - - err = reftable_addition_commit(&add); -done: - reftable_addition_close(&add); return err; } @@ -1007,72 +990,6 @@ uint64_t reftable_stack_next_update_index(struct reftable_stack *st) return 1; } -static int stack_compact_locked(struct reftable_stack *st, - size_t first, size_t last, - struct reftable_log_expiry_config *config, - struct reftable_tmpfile *tab_file_out) -{ - struct reftable_buf next_name = REFTABLE_BUF_INIT; - struct reftable_buf tab_file_path = REFTABLE_BUF_INIT; - struct reftable_writer *wr = NULL; - struct fd_writer writer= { - .opts = &st->opts, - }; - struct reftable_tmpfile tab_file = REFTABLE_TMPFILE_INIT; - int err = 0; - - err = format_name(&next_name, reftable_table_min_update_index(st->tables[first]), - reftable_table_max_update_index(st->tables[last])); - if (err < 0) - goto done; - - err = stack_filename(&tab_file_path, st, next_name.buf); - if (err < 0) - goto done; - - err = reftable_buf_addstr(&tab_file_path, ".temp.XXXXXX"); - if (err < 0) - goto done; - - err = tmpfile_from_pattern(&tab_file, tab_file_path.buf); - if (err < 0) - goto done; - - if (st->opts.default_permissions && - chmod(tab_file.path, st->opts.default_permissions) < 0) { - err = REFTABLE_IO_ERROR; - goto done; - } - - writer.fd = tab_file.fd; - err = reftable_writer_new(&wr, fd_writer_write, fd_writer_flush, - &writer, &st->opts); - if (err < 0) - goto done; - - err = stack_write_compact(st, wr, first, last, config); - if (err < 0) - goto done; - - err = reftable_writer_close(wr); - if (err < 0) - goto done; - - err = tmpfile_close(&tab_file); - if (err < 0) - goto done; - - *tab_file_out = tab_file; - tab_file = REFTABLE_TMPFILE_INIT; - -done: - tmpfile_delete(&tab_file); - reftable_writer_free(wr); - reftable_buf_release(&next_name); - reftable_buf_release(&tab_file_path); - return err; -} - static int stack_write_compact(struct reftable_stack *st, struct reftable_writer *wr, size_t first, size_t last, @@ -1172,6 +1089,72 @@ done: return err; } +static int stack_compact_locked(struct reftable_stack *st, + size_t first, size_t last, + struct reftable_log_expiry_config *config, + struct reftable_tmpfile *tab_file_out) +{ + struct reftable_buf next_name = REFTABLE_BUF_INIT; + struct reftable_buf tab_file_path = REFTABLE_BUF_INIT; + struct reftable_writer *wr = NULL; + struct fd_writer writer= { + .opts = &st->opts, + }; + struct reftable_tmpfile tab_file = REFTABLE_TMPFILE_INIT; + int err = 0; + + err = format_name(&next_name, reftable_table_min_update_index(st->tables[first]), + reftable_table_max_update_index(st->tables[last])); + if (err < 0) + goto done; + + err = stack_filename(&tab_file_path, st, next_name.buf); + if (err < 0) + goto done; + + err = reftable_buf_addstr(&tab_file_path, ".temp.XXXXXX"); + if (err < 0) + goto done; + + err = tmpfile_from_pattern(&tab_file, tab_file_path.buf); + if (err < 0) + goto done; + + if (st->opts.default_permissions && + chmod(tab_file.path, st->opts.default_permissions) < 0) { + err = REFTABLE_IO_ERROR; + goto done; + } + + writer.fd = tab_file.fd; + err = reftable_writer_new(&wr, fd_writer_write, fd_writer_flush, + &writer, &st->opts); + if (err < 0) + goto done; + + err = stack_write_compact(st, wr, first, last, config); + if (err < 0) + goto done; + + err = reftable_writer_close(wr); + if (err < 0) + goto done; + + err = tmpfile_close(&tab_file); + if (err < 0) + goto done; + + *tab_file_out = tab_file; + tab_file = REFTABLE_TMPFILE_INIT; + +done: + tmpfile_delete(&tab_file); + reftable_writer_free(wr); + reftable_buf_release(&next_name); + reftable_buf_release(&tab_file_path); + return err; +} + enum stack_compact_range_flags { /* * Perform a best-effort compaction. That is, even if we cannot lock @@ -1219,17 +1202,27 @@ static int stack_compact_range(struct reftable_stack *st, * which are part of the user-specified range. */ err = flock_acquire(&tables_list_lock, st->list_file, st->opts.lock_timeout_ms); - if (err < 0) { - if (errno == EEXIST) - err = REFTABLE_LOCK_ERROR; - else - err = REFTABLE_IO_ERROR; + if (err < 0) goto done; - } + /* + * Check whether the stack is up-to-date. We unfortunately cannot + * handle the situation gracefully in case it's _not_ up-to-date + * because the range of tables that the user has requested us to + * compact may have been changed. So instead we abort. + * + * We could in theory improve the situation by having the caller not + * pass in a range, but instead the list of tables to compact. If so, + * we could check that relevant tables still exist. But for now it's + * good enough to just abort. + */ err = stack_uptodate(st); - if (err) + if (err < 0) + goto done; + if (err > 0) { + err = REFTABLE_OUTDATED_ERROR; goto done; + } /* * Lock all tables in the user-provided range. This is the slice of our @@ -1264,7 +1257,7 @@ static int stack_compact_range(struct reftable_stack *st, * tables, otherwise there would be nothing to compact. * In that case, we return a lock error to our caller. */ - if (errno == EEXIST && last - (i - 1) >= 2 && + if (err == REFTABLE_LOCK_ERROR && last - (i - 1) >= 2 && flags & STACK_COMPACT_RANGE_BEST_EFFORT) { err = 0; /* @@ -1276,13 +1269,9 @@ static int stack_compact_range(struct reftable_stack *st, */ first = (i - 1) + 1; break; - } else if (errno == EEXIST) { - err = REFTABLE_LOCK_ERROR; - goto done; - } else { - err = REFTABLE_IO_ERROR; - goto done; } + + goto done; } /* @@ -1291,10 +1280,8 @@ static int stack_compact_range(struct reftable_stack *st, * of tables. */ err = flock_close(&table_locks[nlocks++]); - if (err < 0) { - err = REFTABLE_IO_ERROR; + if (err < 0) goto done; - } } /* @@ -1326,13 +1313,8 @@ static int stack_compact_range(struct reftable_stack *st, * the new table. */ err = flock_acquire(&tables_list_lock, st->list_file, st->opts.lock_timeout_ms); - if (err < 0) { - if (errno == EEXIST) - err = REFTABLE_LOCK_ERROR; - else - err = REFTABLE_IO_ERROR; + if (err < 0) goto done; - } if (st->opts.default_permissions) { if (chmod(tables_list_lock.path, diff --git a/reftable/system.c b/reftable/system.c index 1ee268b125..725a25844e 100644 --- a/reftable/system.c +++ b/reftable/system.c @@ -72,7 +72,7 @@ int flock_acquire(struct reftable_flock *l, const char *target_path, reftable_free(lockfile); if (errno == EEXIST) return REFTABLE_LOCK_ERROR; - return -1; + return REFTABLE_IO_ERROR; } l->fd = get_lock_file_fd(lockfile); diff --git a/reftable/system.h b/reftable/system.h index beb9d2431f..c54ed4cad6 100644 --- a/reftable/system.h +++ b/reftable/system.h @@ -81,7 +81,9 @@ struct reftable_flock { * to acquire the lock. If `timeout_ms` is 0 we don't wait, if it is negative * we block indefinitely. * - * Retrun 0 on success, a reftable error code on error. + * Retrun 0 on success, a reftable error code on error. Specifically, + * `REFTABLE_LOCK_ERROR` should be returned in case the target path is already + * locked. */ int flock_acquire(struct reftable_flock *l, const char *target_path, long timeout_ms); diff --git a/reftable/writer.c b/reftable/writer.c index 3b4ebdd6dc..0133b64975 100644 --- a/reftable/writer.c +++ b/reftable/writer.c @@ -395,14 +395,16 @@ out: } int reftable_writer_add_refs(struct reftable_writer *w, - struct reftable_ref_record *refs, int n) + struct reftable_ref_record *refs, size_t n) { int err = 0; - int i = 0; - QSORT(refs, n, reftable_ref_record_compare_name); - for (i = 0; err == 0 && i < n; i++) { + + if (n) + qsort(refs, n, sizeof(*refs), reftable_ref_record_compare_name); + + for (size_t i = 0; err == 0 && i < n; i++) err = reftable_writer_add_ref(w, &refs[i]); - } + return err; } @@ -486,15 +488,16 @@ done: } int reftable_writer_add_logs(struct reftable_writer *w, - struct reftable_log_record *logs, int n) + struct reftable_log_record *logs, size_t n) { int err = 0; - int i = 0; - QSORT(logs, n, reftable_log_record_compare_key); - for (i = 0; err == 0 && i < n; i++) { + if (n) + qsort(logs, n, sizeof(*logs), reftable_log_record_compare_key); + + for (size_t i = 0; err == 0 && i < n; i++) err = reftable_writer_add_log(w, &logs[i]); - } + return err; } |
