lockfile.c 2.4 KB
Newer Older
1 2 3 4 5 6
/*
 * Copyright (c) 2005, Junio C Hamano
 */
#include "cache.h"

static struct lock_file *lock_file_list;
7
static const char *alternate_index_output;
8 9 10

static void remove_lock_file(void)
{
11 12
	pid_t me = getpid();

13
	while (lock_file_list) {
14 15
		if (lock_file_list->owner == me &&
		    lock_file_list->filename[0])
16 17 18 19 20 21 22 23 24 25 26 27
			unlink(lock_file_list->filename);
		lock_file_list = lock_file_list->next;
	}
}

static void remove_lock_file_on_signal(int signo)
{
	remove_lock_file();
	signal(SIGINT, SIG_DFL);
	raise(signo);
}

28
static int lock_file(struct lock_file *lk, const char *path)
29 30
{
	int fd;
31 32 33 34 35 36 37 38 39 40 41 42 43
	struct stat st;

	if ((!lstat(path, &st)) && S_ISLNK(st.st_mode)) {
		ssize_t sz;
		static char target[PATH_MAX];
		sz = readlink(path, target, sizeof(target));
		if (sz < 0)
			warning("Cannot readlink %s", path);
		else if (target[0] != '/')
			warning("Cannot lock target of relative symlink %s", path);
		else
			path = target;
	}
44 45
	sprintf(lk->filename, "%s.lock", path);
	fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
46
	if (0 <= fd) {
47 48 49 50
		if (!lock_file_list) {
			signal(SIGINT, remove_lock_file_on_signal);
			atexit(remove_lock_file);
		}
51
		lk->owner = getpid();
52
		if (!lk->on_list) {
53 54
			lk->next = lock_file_list;
			lock_file_list = lk;
55 56
			lk->on_list = 1;
		}
57 58 59
		if (adjust_shared_perm(lk->filename))
			return error("cannot fix permission bits on %s",
				     lk->filename);
60
	}
61 62
	else
		lk->filename[0] = 0;
63 64 65
	return fd;
}

66 67 68 69
int hold_lock_file_for_update(struct lock_file *lk, const char *path, int die_on_error)
{
	int fd = lock_file(lk, path);
	if (fd < 0 && die_on_error)
70
		die("unable to create '%s.lock': %s", path, strerror(errno));
71 72 73
	return fd;
}

74 75 76 77 78 79 80 81 82 83 84 85
int commit_lock_file(struct lock_file *lk)
{
	char result_file[PATH_MAX];
	int i;
	strcpy(result_file, lk->filename);
	i = strlen(result_file) - 5; /* .lock */
	result_file[i] = 0;
	i = rename(lk->filename, result_file);
	lk->filename[0] = 0;
	return i;
}

86 87 88 89 90
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);
}

91 92 93 94 95
void set_alternate_index_output(const char *name)
{
	alternate_index_output = name;
}

96 97
int commit_locked_index(struct lock_file *lk)
{
98 99
	if (alternate_index_output) {
		int result = rename(lk->filename, alternate_index_output);
100 101 102 103 104 105 106
		lk->filename[0] = 0;
		return result;
	}
	else
		return commit_lock_file(lk);
}

107 108 109 110 111 112
void rollback_lock_file(struct lock_file *lk)
{
	if (lk->filename[0])
		unlink(lk->filename);
	lk->filename[0] = 0;
}