1/*
2* Copyright (c) 2005, Junio C Hamano
3*/
4#include "cache.h"
56
static struct lock_file *lock_file_list;
7static const char *alternate_index_output;
89
static void remove_lock_file(void)
10{
11pid_t me = getpid();
1213
while (lock_file_list) {
14if (lock_file_list->owner == me &&
15lock_file_list->filename[0]) {
16close(lock_file_list->fd);
17unlink(lock_file_list->filename);
18}
19lock_file_list = lock_file_list->next;
20}
21}
2223
static void remove_lock_file_on_signal(int signo)
24{
25remove_lock_file();
26signal(SIGINT, SIG_DFL);
27raise(signo);
28}
2930
/*
31* p = absolute or relative path name
32*
33* Return a pointer into p showing the beginning of the last path name
34* element. If p is empty or the root directory ("/"), just return p.
35*/
36static char *last_path_elm(char *p)
37{
38/* r starts pointing to null at the end of the string */
39char *r = strchr(p, '\0');
4041
if (r == p)
42return p; /* just return empty string */
4344
r--; /* back up to last non-null character */
4546
/* back up past trailing slashes, if any */
47while (r > p && *r == '/')
48r--;
4950
/*
51* then go backwards until I hit a slash, or the beginning of
52* the string
53*/
54while (r > p && *(r-1) != '/')
55r--;
56return r;
57}
5859
60
/* We allow "recursive" symbolic links. Only within reason, though */
61#define MAXDEPTH 5
6263
/*
64* p = path that may be a symlink
65* s = full size of p
66*
67* If p is a symlink, attempt to overwrite p with a path to the real
68* file or directory (which may or may not exist), following a chain of
69* symlinks if necessary. Otherwise, leave p unmodified.
70*
71* This is a best-effort routine. If an error occurs, p will either be
72* left unmodified or will name a different symlink in a symlink chain
73* that started with p's initial contents.
74*
75* Always returns p.
76*/
7778
static char *resolve_symlink(char *p, size_t s)
79{
80int depth = MAXDEPTH;
8182
while (depth--) {
83char link[PATH_MAX];
84int link_len = readlink(p, link, sizeof(link));
85if (link_len < 0) {
86/* not a symlink anymore */
87return p;
88}
89else if (link_len < sizeof(link))
90/* readlink() never null-terminates */
91link[link_len] = '\0';
92else {
93warning("%s: symlink too long", p);
94return p;
95}
9697
if (is_absolute_path(link)) {
98/* absolute path simply replaces p */
99if (link_len < s)
100strcpy(p, link);
101else {
102warning("%s: symlink too long", p);
103return p;
104}
105} else {
106/*
107* link is a relative path, so I must replace the
108* last element of p with it.
109*/
110char *r = (char*)last_path_elm(p);
111if (r - p + link_len < s)
112strcpy(r, link);
113else {
114warning("%s: symlink too long", p);
115return p;
116}
117}
118}
119return p;
120}
121122
123
static int lock_file(struct lock_file *lk, const char *path)
124{
125if (strlen(path) >= sizeof(lk->filename)) return -1;
126strcpy(lk->filename, path);
127/*
128* subtract 5 from size to make sure there's room for adding
129* ".lock" for the lock file name
130*/
131resolve_symlink(lk->filename, sizeof(lk->filename)-5);
132strcat(lk->filename, ".lock");
133lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
134if (0 <= lk->fd) {
135if (!lock_file_list) {
136signal(SIGINT, remove_lock_file_on_signal);
137atexit(remove_lock_file);
138}
139lk->owner = getpid();
140if (!lk->on_list) {
141lk->next = lock_file_list;
142lock_file_list = lk;
143lk->on_list = 1;
144}
145if (adjust_shared_perm(lk->filename))
146return error("cannot fix permission bits on %s",
147lk->filename);
148}
149else
150lk->filename[0] = 0;
151return lk->fd;
152}
153154
int hold_lock_file_for_update(struct lock_file *lk, const char *path, int die_on_error)
155{
156int fd = lock_file(lk, path);
157if (fd < 0 && die_on_error)
158die("unable to create '%s.lock': %s", path, strerror(errno));
159return fd;
160}
161162
int commit_lock_file(struct lock_file *lk)
163{
164char result_file[PATH_MAX];
165int i;
166close(lk->fd);
167strcpy(result_file, lk->filename);
168i = strlen(result_file) - 5; /* .lock */
169result_file[i] = 0;
170i = rename(lk->filename, result_file);
171lk->filename[0] = 0;
172return i;
173}
174175
int hold_locked_index(struct lock_file *lk, int die_on_error)
176{
177return hold_lock_file_for_update(lk, get_index_file(), die_on_error);
178}
179180
void set_alternate_index_output(const char *name)
181{
182alternate_index_output = name;
183}
184185
int commit_locked_index(struct lock_file *lk)
186{
187if (alternate_index_output) {
188int result = rename(lk->filename, alternate_index_output);
189lk->filename[0] = 0;
190return result;
191}
192else
193return commit_lock_file(lk);
194}
195196
void rollback_lock_file(struct lock_file *lk)
197{
198if (lk->filename[0]) {
199close(lk->fd);
200unlink(lk->filename);
201}
202lk->filename[0] = 0;
203}