diff options
author | Michael Haggerty <mhagger@alum.mit.edu> | 2014-10-01 13:14:47 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2014-10-01 14:08:10 -0700 |
commit | 013870cd2cb1b0d6719a7a9123e126a62426520b (patch) | |
tree | 235000196a837c275d3e7d72d06cd3cf197bc9f3 /lockfile.c | |
parent | 697cc8efd944a32ca472337cd6640004c474b788 (diff) | |
download | git-013870cd2cb1b0d6719a7a9123e126a62426520b.tar.gz |
fdopen_lock_file(): access a lockfile using stdio
Add a new function, fdopen_lock_file(), which returns a FILE pointer
open to the lockfile. If a stream is open on a lock_file object, it is
closed using fclose() on commit, rollback, or close_lock_file().
This change will allow callers to use stdio to write to a lockfile
without having to muck around in the internal representation of the
lock_file object (callers will be rewritten in upcoming commits).
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'lockfile.c')
-rw-r--r-- | lockfile.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/lockfile.c b/lockfile.c index d27e61cafc..e0460275e1 100644 --- a/lockfile.c +++ b/lockfile.c @@ -7,20 +7,29 @@ static struct lock_file *volatile lock_file_list; -static void remove_lock_files(void) +static void remove_lock_files(int skip_fclose) { pid_t me = getpid(); while (lock_file_list) { - if (lock_file_list->owner == me) + 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(); + remove_lock_files(1); sigchain_pop(signo); raise(signo); } @@ -97,7 +106,7 @@ static int lock_file(struct lock_file *lk, const char *path, int flags) if (!lock_file_list) { /* One-time initialization */ sigchain_push_common(remove_lock_files_on_signal); - atexit(remove_lock_files); + atexit(remove_lock_files_on_exit); } if (lk->active) @@ -106,6 +115,7 @@ static int lock_file(struct lock_file *lk, const char *path, int flags) 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); @@ -214,6 +224,17 @@ int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags) 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) @@ -226,17 +247,32 @@ char *get_locked_file_path(struct lock_file *lk) 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 (close(fd)) { + 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); + } + + if (err) { int save_errno = errno; rollback_lock_file(lk); errno = save_errno; return -1; } + return 0; } |