summaryrefslogtreecommitdiff
path: root/lockfile.c
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <gitster@pobox.com>2011-11-10 09:05:31 -0800
committerLibravatar Junio C Hamano <gitster@pobox.com>2011-11-10 09:05:31 -0800
commit77f143bf3e218857ec8e5244d7e862e8e0c1a041 (patch)
tree9f720e61941241b53a4f258d0dc62e5a9a360aa8 /lockfile.c
parentmktree: fix a memory leak in write_tree() (diff)
parentbuild-in git-mktree (diff)
downloadtgif-77f143bf3e218857ec8e5244d7e862e8e0c1a041.tar.xz
Merge 'build-in git-mktree'
* commit '633e3556ccbc': (5835 commits) build-in git-mktree allow -t abbreviation for --track in git branch gitweb: Remove function prototypes (cleanup) Documentation: cloning to empty directory is allowed Clarify kind of conflict in merge-one-file helper git config: clarify --add and --get-color archive-tar.c: squelch a type mismatch warning Start 1.6.4 development Start 1.6.3.1 maintenance series. GIT 1.6.3 t4029: use sh instead of bash t4200: convert sed expression which operates on non-text file to perl t4200: remove two unnecessary lines t/annotate-tests.sh: avoid passing a non-newline terminated file to sed t4118: avoid sed invocation on file without terminating newline t4118: add missing '&&' t8005: use egrep when extended regular expressions are required git-clean doc: the command only affects paths under $(cwd) improve error message in config.c t4018-diff-funcname: add cpp xfuncname pattern to syntax test ...
Diffstat (limited to 'lockfile.c')
-rw-r--r--lockfile.c111
1 files changed, 88 insertions, 23 deletions
diff --git a/lockfile.c b/lockfile.c
index 9a1f64d8d7..828d19f452 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -2,6 +2,7 @@
* Copyright (c) 2005, Junio C Hamano
*/
#include "cache.h"
+#include "sigchain.h"
static struct lock_file *lock_file_list;
static const char *alternate_index_output;
@@ -12,8 +13,11 @@ static void remove_lock_file(void)
while (lock_file_list) {
if (lock_file_list->owner == me &&
- lock_file_list->filename[0])
+ lock_file_list->filename[0]) {
+ if (lock_file_list->fd >= 0)
+ close(lock_file_list->fd);
unlink(lock_file_list->filename);
+ }
lock_file_list = lock_file_list->next;
}
}
@@ -21,7 +25,7 @@ static void remove_lock_file(void)
static void remove_lock_file_on_signal(int signo)
{
remove_lock_file();
- signal(SIGINT, SIG_DFL);
+ sigchain_pop(signo);
raise(signo);
}
@@ -92,7 +96,7 @@ static char *resolve_symlink(char *p, size_t s)
return p;
}
- if (link[0] == '/') {
+ if (is_absolute_path(link)) {
/* absolute path simply replaces p */
if (link_len < s)
strcpy(p, link);
@@ -105,7 +109,7 @@ static char *resolve_symlink(char *p, size_t s)
* link is a relative path, so I must replace the
* last element of p with it.
*/
- char *r = (char*)last_path_elm(p);
+ char *r = (char *)last_path_elm(p);
if (r - p + link_len < s)
strcpy(r, link);
else {
@@ -118,22 +122,22 @@ static char *resolve_symlink(char *p, size_t s)
}
-static int lock_file(struct lock_file *lk, const char *path)
+static int lock_file(struct lock_file *lk, const char *path, int flags)
{
- int fd;
-
- if (strlen(path) >= sizeof(lk->filename)) return -1;
+ if (strlen(path) >= sizeof(lk->filename))
+ return -1;
strcpy(lk->filename, path);
/*
* subtract 5 from size to make sure there's room for adding
* ".lock" for the lock file name
*/
- resolve_symlink(lk->filename, sizeof(lk->filename)-5);
+ if (!(flags & LOCK_NODEREF))
+ resolve_symlink(lk->filename, sizeof(lk->filename)-5);
strcat(lk->filename, ".lock");
- fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
- if (0 <= fd) {
+ lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
+ if (0 <= lk->fd) {
if (!lock_file_list) {
- signal(SIGINT, remove_lock_file_on_signal);
+ sigchain_push_common(remove_lock_file_on_signal);
atexit(remove_lock_file);
}
lk->owner = getpid();
@@ -148,32 +152,87 @@ static int lock_file(struct lock_file *lk, const char *path)
}
else
lk->filename[0] = 0;
+ return lk->fd;
+}
+
+
+NORETURN void unable_to_lock_index_die(const char *path, int err)
+{
+ if (err == EEXIST) {
+ die("Unable to create '%s.lock': %s.\n\n"
+ "If no other git process is currently running, this probably means a\n"
+ "git process crashed in this repository earlier. Make sure no other git\n"
+ "process is running and remove the file manually to continue.",
+ path, strerror(err));
+ } else {
+ die("Unable to create '%s.lock': %s", path, strerror(err));
+ }
+}
+
+int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
+{
+ int fd = lock_file(lk, path, flags);
+ if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
+ unable_to_lock_index_die(path, errno);
return fd;
}
-int hold_lock_file_for_update(struct lock_file *lk, const char *path, int die_on_error)
+int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
{
- int fd = lock_file(lk, path);
- if (fd < 0 && die_on_error)
- die("unable to create '%s.lock': %s", path, strerror(errno));
+ int fd, orig_fd;
+
+ fd = lock_file(lk, path, flags);
+ if (fd < 0) {
+ if (flags & LOCK_DIE_ON_ERROR)
+ unable_to_lock_index_die(path, errno);
+ return fd;
+ }
+
+ orig_fd = open(path, O_RDONLY);
+ if (orig_fd < 0) {
+ if (errno != ENOENT) {
+ if (flags & LOCK_DIE_ON_ERROR)
+ die("cannot open '%s' for copying", path);
+ close(fd);
+ return error("cannot open '%s' for copying", path);
+ }
+ } else if (copy_fd(orig_fd, fd)) {
+ if (flags & LOCK_DIE_ON_ERROR)
+ exit(128);
+ close(fd);
+ return -1;
+ }
return fd;
}
+int close_lock_file(struct lock_file *lk)
+{
+ int fd = lk->fd;
+ lk->fd = -1;
+ return close(fd);
+}
+
int commit_lock_file(struct lock_file *lk)
{
char result_file[PATH_MAX];
- int i;
+ size_t i;
+ if (lk->fd >= 0 && close_lock_file(lk))
+ return -1;
strcpy(result_file, lk->filename);
i = strlen(result_file) - 5; /* .lock */
result_file[i] = 0;
- i = rename(lk->filename, result_file);
+ if (rename(lk->filename, result_file))
+ return -1;
lk->filename[0] = 0;
- return i;
+ return 0;
}
int hold_locked_index(struct lock_file *lk, int die_on_error)
{
- return hold_lock_file_for_update(lk, get_index_file(), die_on_error);
+ return hold_lock_file_for_update(lk, get_index_file(),
+ die_on_error
+ ? LOCK_DIE_ON_ERROR
+ : 0);
}
void set_alternate_index_output(const char *name)
@@ -184,9 +243,12 @@ void set_alternate_index_output(const char *name)
int commit_locked_index(struct lock_file *lk)
{
if (alternate_index_output) {
- int result = rename(lk->filename, alternate_index_output);
+ if (lk->fd >= 0 && close_lock_file(lk))
+ return -1;
+ if (rename(lk->filename, alternate_index_output))
+ return -1;
lk->filename[0] = 0;
- return result;
+ return 0;
}
else
return commit_lock_file(lk);
@@ -194,7 +256,10 @@ int commit_locked_index(struct lock_file *lk)
void rollback_lock_file(struct lock_file *lk)
{
- if (lk->filename[0])
+ if (lk->filename[0]) {
+ if (lk->fd >= 0)
+ close(lk->fd);
unlink(lk->filename);
+ }
lk->filename[0] = 0;
}