diff options
Diffstat (limited to 'lockfile.c')
-rw-r--r-- | lockfile.c | 243 |
1 files changed, 23 insertions, 220 deletions
diff --git a/lockfile.c b/lockfile.c index 993bb82748..80d056d2ed 100644 --- a/lockfile.c +++ b/lockfile.c @@ -1,38 +1,9 @@ /* * Copyright (c) 2005, Junio C Hamano */ + #include "cache.h" #include "lockfile.h" -#include "sigchain.h" - -static struct lock_file *volatile lock_file_list; - -static void remove_lock_files(int skip_fclose) -{ - pid_t me = getpid(); - - while (lock_file_list) { - if (lock_file_list->owner == me) { - /* fclose() is not safe to call in a signal handler */ - if (skip_fclose) - lock_file_list->fp = NULL; - rollback_lock_file(lock_file_list); - } - lock_file_list = lock_file_list->next; - } -} - -static void remove_lock_files_on_exit(void) -{ - remove_lock_files(0); -} - -static void remove_lock_files_on_signal(int signo) -{ - remove_lock_files(1); - sigchain_pop(signo); - raise(signo); -} /* * path = absolute or relative path name @@ -101,60 +72,17 @@ static void resolve_symlink(struct strbuf *path) /* Make sure errno contains a meaningful value on error */ static int lock_file(struct lock_file *lk, const char *path, int flags) { - size_t pathlen = strlen(path); + int fd; + struct strbuf filename = STRBUF_INIT; - if (!lock_file_list) { - /* One-time initialization */ - sigchain_push_common(remove_lock_files_on_signal); - atexit(remove_lock_files_on_exit); - } - - if (lk->active) - die("BUG: cannot lock_file(\"%s\") using active struct lock_file", - path); - if (!lk->on_list) { - /* Initialize *lk and add it to lock_file_list: */ - lk->fd = -1; - lk->fp = NULL; - lk->active = 0; - lk->owner = 0; - strbuf_init(&lk->filename, pathlen + LOCK_SUFFIX_LEN); - lk->next = lock_file_list; - lock_file_list = lk; - lk->on_list = 1; - } else if (lk->filename.len) { - /* This shouldn't happen, but better safe than sorry. */ - die("BUG: lock_file(\"%s\") called with improperly-reset lock_file object", - path); - } + strbuf_addstr(&filename, path); + if (!(flags & LOCK_NO_DEREF)) + resolve_symlink(&filename); - if (flags & LOCK_NO_DEREF) { - strbuf_add_absolute_path(&lk->filename, path); - } else { - struct strbuf resolved_path = STRBUF_INIT; - - strbuf_add(&resolved_path, path, pathlen); - resolve_symlink(&resolved_path); - strbuf_add_absolute_path(&lk->filename, resolved_path.buf); - strbuf_release(&resolved_path); - } - - strbuf_addstr(&lk->filename, LOCK_SUFFIX); - lk->fd = open(lk->filename.buf, O_RDWR | O_CREAT | O_EXCL, 0666); - if (lk->fd < 0) { - strbuf_reset(&lk->filename); - return -1; - } - lk->owner = getpid(); - lk->active = 1; - if (adjust_shared_perm(lk->filename.buf)) { - int save_errno = errno; - error("cannot fix permission bits on %s", lk->filename.buf); - rollback_lock_file(lk); - errno = save_errno; - return -1; - } - return lk->fd; + strbuf_addstr(&filename, LOCK_SUFFIX); + fd = create_tempfile(&lk->tempfile, filename.buf); + strbuf_release(&filename); + return fd; } /* @@ -249,154 +177,29 @@ int hold_lock_file_for_update_timeout(struct lock_file *lk, const char *path, return fd; } -int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags) -{ - int fd, orig_fd; - - fd = lock_file(lk, path, flags); - if (fd < 0) { - if (flags & LOCK_DIE_ON_ERROR) - unable_to_lock_die(path, errno); - return fd; - } - - orig_fd = open(path, O_RDONLY); - if (orig_fd < 0) { - if (errno != ENOENT) { - int save_errno = errno; - - if (flags & LOCK_DIE_ON_ERROR) - die("cannot open '%s' for copying", path); - rollback_lock_file(lk); - error("cannot open '%s' for copying", path); - errno = save_errno; - return -1; - } - } else if (copy_fd(orig_fd, fd)) { - int save_errno = errno; - - if (flags & LOCK_DIE_ON_ERROR) - die("failed to prepare '%s' for appending", path); - close(orig_fd); - rollback_lock_file(lk); - errno = save_errno; - return -1; - } else { - close(orig_fd); - } - return fd; -} - -FILE *fdopen_lock_file(struct lock_file *lk, const char *mode) -{ - if (!lk->active) - die("BUG: fdopen_lock_file() called for unlocked object"); - if (lk->fp) - die("BUG: fdopen_lock_file() called twice for file '%s'", lk->filename.buf); - - lk->fp = fdopen(lk->fd, mode); - return lk->fp; -} - char *get_locked_file_path(struct lock_file *lk) { - if (!lk->active) - die("BUG: get_locked_file_path() called for unlocked object"); - if (lk->filename.len <= LOCK_SUFFIX_LEN) - die("BUG: get_locked_file_path() called for malformed lock object"); - return xmemdupz(lk->filename.buf, lk->filename.len - LOCK_SUFFIX_LEN); -} - -int close_lock_file(struct lock_file *lk) -{ - int fd = lk->fd; - FILE *fp = lk->fp; - int err; - - if (fd < 0) - return 0; - - lk->fd = -1; - if (fp) { - lk->fp = NULL; - - /* - * Note: no short-circuiting here; we want to fclose() - * in any case! - */ - err = ferror(fp) | fclose(fp); - } else { - err = close(fd); - } + struct strbuf ret = STRBUF_INIT; - if (err) { - int save_errno = errno; - rollback_lock_file(lk); - errno = save_errno; - return -1; - } - - return 0; -} - -int reopen_lock_file(struct lock_file *lk) -{ - if (0 <= lk->fd) - die(_("BUG: reopen a lockfile that is still open")); - if (!lk->active) - die(_("BUG: reopen a lockfile that has been committed")); - lk->fd = open(lk->filename.buf, O_WRONLY); - return lk->fd; + strbuf_addstr(&ret, get_tempfile_path(&lk->tempfile)); + if (ret.len <= LOCK_SUFFIX_LEN || + strcmp(ret.buf + ret.len - LOCK_SUFFIX_LEN, LOCK_SUFFIX)) + die("BUG: get_locked_file_path() called for malformed lock object"); + /* remove ".lock": */ + strbuf_setlen(&ret, ret.len - LOCK_SUFFIX_LEN); + return strbuf_detach(&ret, NULL); } -int commit_lock_file_to(struct lock_file *lk, const char *path) +int commit_lock_file(struct lock_file *lk) { - if (!lk->active) - die("BUG: attempt to commit unlocked object to \"%s\"", path); + char *result_path = get_locked_file_path(lk); - if (close_lock_file(lk)) - return -1; - - if (rename(lk->filename.buf, path)) { + if (commit_lock_file_to(lk, result_path)) { int save_errno = errno; - rollback_lock_file(lk); + free(result_path); errno = save_errno; return -1; } - - lk->active = 0; - strbuf_reset(&lk->filename); + free(result_path); return 0; } - -int commit_lock_file(struct lock_file *lk) -{ - static struct strbuf result_file = STRBUF_INIT; - int err; - - if (!lk->active) - die("BUG: attempt to commit unlocked object"); - - if (lk->filename.len <= LOCK_SUFFIX_LEN || - strcmp(lk->filename.buf + lk->filename.len - LOCK_SUFFIX_LEN, LOCK_SUFFIX)) - die("BUG: lockfile filename corrupt"); - - /* remove ".lock": */ - strbuf_add(&result_file, lk->filename.buf, - lk->filename.len - LOCK_SUFFIX_LEN); - err = commit_lock_file_to(lk, result_file.buf); - strbuf_reset(&result_file); - return err; -} - -void rollback_lock_file(struct lock_file *lk) -{ - if (!lk->active) - return; - - if (!close_lock_file(lk)) { - unlink_or_warn(lk->filename.buf); - lk->active = 0; - strbuf_reset(&lk->filename); - } -} |