lockfile: unlock file if lockfile permissions cannot be adjusted
[git/git.git] / lockfile.c
CommitLineData
021b6e45
JH
1/*
2 * Copyright (c) 2005, Junio C Hamano
3 */
021b6e45 4#include "cache.h"
4a16d072 5#include "sigchain.h"
021b6e45
JH
6
7static struct lock_file *lock_file_list;
8
9static void remove_lock_file(void)
10{
5e635e39
JH
11 pid_t me = getpid();
12
021b6e45 13 while (lock_file_list) {
5e635e39 14 if (lock_file_list->owner == me &&
4723ee99 15 lock_file_list->filename[0]) {
d6cf61bf
BC
16 if (lock_file_list->fd >= 0)
17 close(lock_file_list->fd);
691f1a28 18 unlink_or_warn(lock_file_list->filename);
4723ee99 19 }
021b6e45
JH
20 lock_file_list = lock_file_list->next;
21 }
22}
23
24static void remove_lock_file_on_signal(int signo)
25{
26 remove_lock_file();
4a16d072 27 sigchain_pop(signo);
021b6e45
JH
28 raise(signo);
29}
30
5d5a7a67
BS
31/*
32 * p = absolute or relative path name
33 *
34 * Return a pointer into p showing the beginning of the last path name
35 * element. If p is empty or the root directory ("/"), just return p.
36 */
37static char *last_path_elm(char *p)
38{
39 /* r starts pointing to null at the end of the string */
40 char *r = strchr(p, '\0');
41
42 if (r == p)
43 return p; /* just return empty string */
44
45 r--; /* back up to last non-null character */
46
47 /* back up past trailing slashes, if any */
48 while (r > p && *r == '/')
49 r--;
50
51 /*
52 * then go backwards until I hit a slash, or the beginning of
53 * the string
54 */
55 while (r > p && *(r-1) != '/')
56 r--;
57 return r;
58}
59
60
61/* We allow "recursive" symbolic links. Only within reason, though */
62#define MAXDEPTH 5
63
64/*
65 * p = path that may be a symlink
66 * s = full size of p
67 *
68 * If p is a symlink, attempt to overwrite p with a path to the real
69 * file or directory (which may or may not exist), following a chain of
70 * symlinks if necessary. Otherwise, leave p unmodified.
71 *
72 * This is a best-effort routine. If an error occurs, p will either be
73 * left unmodified or will name a different symlink in a symlink chain
74 * that started with p's initial contents.
75 *
76 * Always returns p.
77 */
78
79static char *resolve_symlink(char *p, size_t s)
80{
81 int depth = MAXDEPTH;
82
83 while (depth--) {
84 char link[PATH_MAX];
85 int link_len = readlink(p, link, sizeof(link));
86 if (link_len < 0) {
87 /* not a symlink anymore */
88 return p;
89 }
90 else if (link_len < sizeof(link))
91 /* readlink() never null-terminates */
92 link[link_len] = '\0';
93 else {
94 warning("%s: symlink too long", p);
95 return p;
96 }
97
ecf4831d 98 if (is_absolute_path(link)) {
5d5a7a67
BS
99 /* absolute path simply replaces p */
100 if (link_len < s)
101 strcpy(p, link);
102 else {
103 warning("%s: symlink too long", p);
104 return p;
105 }
106 } else {
107 /*
108 * link is a relative path, so I must replace the
109 * last element of p with it.
110 */
4b25d091 111 char *r = (char *)last_path_elm(p);
5d5a7a67
BS
112 if (r - p + link_len < s)
113 strcpy(r, link);
114 else {
115 warning("%s: symlink too long", p);
116 return p;
117 }
118 }
119 }
120 return p;
121}
122
447ff1bf 123/* Make sure errno contains a meaningful value on error */
acd3b9ec 124static int lock_file(struct lock_file *lk, const char *path, int flags)
021b6e45 125{
5d5a7a67
BS
126 /*
127 * subtract 5 from size to make sure there's room for adding
128 * ".lock" for the lock file name
129 */
2fbd4f92
MH
130 static const size_t max_path_len = sizeof(lk->filename) - 5;
131
447ff1bf
RS
132 if (strlen(path) >= max_path_len) {
133 errno = ENAMETOOLONG;
2fbd4f92 134 return -1;
447ff1bf 135 }
2fbd4f92 136 strcpy(lk->filename, path);
acd3b9ec 137 if (!(flags & LOCK_NODEREF))
2fbd4f92 138 resolve_symlink(lk->filename, max_path_len);
5d5a7a67 139 strcat(lk->filename, ".lock");
4723ee99
JS
140 lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
141 if (0 <= lk->fd) {
9a4cbdca 142 if (!lock_file_list) {
57b235a4 143 sigchain_push_common(remove_lock_file_on_signal);
9a4cbdca
SV
144 atexit(remove_lock_file);
145 }
5e635e39 146 lk->owner = getpid();
1084b845 147 if (!lk->on_list) {
138086a7
JH
148 lk->next = lock_file_list;
149 lock_file_list = lk;
1084b845
JH
150 lk->on_list = 1;
151 }
447ff1bf
RS
152 if (adjust_shared_perm(lk->filename)) {
153 int save_errno = errno;
154 error("cannot fix permission bits on %s",
155 lk->filename);
41dd4ffa 156 rollback_lock_file(lk);
447ff1bf
RS
157 errno = save_errno;
158 return -1;
159 }
021b6e45 160 }
1084b845
JH
161 else
162 lk->filename[0] = 0;
4723ee99 163 return lk->fd;
021b6e45
JH
164}
165
6af926e8 166void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
e43a6fd3 167{
bdfd739d 168 if (err == EEXIST) {
6af926e8 169 strbuf_addf(buf, "Unable to create '%s.lock': %s.\n\n"
e43a6fd3
MM
170 "If no other git process is currently running, this probably means a\n"
171 "git process crashed in this repository earlier. Make sure no other git\n"
172 "process is running and remove the file manually to continue.",
e2a57aac 173 absolute_path(path), strerror(err));
1b018fd9 174 } else
6af926e8 175 strbuf_addf(buf, "Unable to create '%s.lock': %s",
e2a57aac 176 absolute_path(path), strerror(err));
1b018fd9
MV
177}
178
179int unable_to_lock_error(const char *path, int err)
180{
6af926e8
RS
181 struct strbuf buf = STRBUF_INIT;
182
183 unable_to_lock_message(path, err, &buf);
184 error("%s", buf.buf);
185 strbuf_release(&buf);
1b018fd9
MV
186 return -1;
187}
188
e197c218 189NORETURN void unable_to_lock_die(const char *path, int err)
1b018fd9 190{
6af926e8
RS
191 struct strbuf buf = STRBUF_INIT;
192
193 unable_to_lock_message(path, err, &buf);
194 die("%s", buf.buf);
e43a6fd3
MM
195}
196
447ff1bf 197/* This should return a meaningful errno on failure */
acd3b9ec 198int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
40aaae88 199{
acd3b9ec
JH
200 int fd = lock_file(lk, path, flags);
201 if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
e197c218 202 unable_to_lock_die(path, errno);
40aaae88
JH
203 return fd;
204}
205
acd3b9ec 206int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
ea3cd5c7
DB
207{
208 int fd, orig_fd;
209
acd3b9ec 210 fd = lock_file(lk, path, flags);
ea3cd5c7 211 if (fd < 0) {
acd3b9ec 212 if (flags & LOCK_DIE_ON_ERROR)
e197c218 213 unable_to_lock_die(path, errno);
ea3cd5c7
DB
214 return fd;
215 }
216
217 orig_fd = open(path, O_RDONLY);
218 if (orig_fd < 0) {
219 if (errno != ENOENT) {
acd3b9ec 220 if (flags & LOCK_DIE_ON_ERROR)
ea3cd5c7
DB
221 die("cannot open '%s' for copying", path);
222 close(fd);
223 return error("cannot open '%s' for copying", path);
224 }
225 } else if (copy_fd(orig_fd, fd)) {
acd3b9ec 226 if (flags & LOCK_DIE_ON_ERROR)
ea3cd5c7
DB
227 exit(128);
228 close(fd);
229 return -1;
230 }
231 return fd;
232}
233
d6cf61bf
BC
234int close_lock_file(struct lock_file *lk)
235{
236 int fd = lk->fd;
419f0c0f
MH
237
238 if (fd < 0)
239 return 0;
240
d6cf61bf
BC
241 lk->fd = -1;
242 return close(fd);
243}
244
93dcaea2
JH
245int reopen_lock_file(struct lock_file *lk)
246{
247 if (0 <= lk->fd)
248 die(_("BUG: reopen a lockfile that is still open"));
249 if (!lk->filename[0])
250 die(_("BUG: reopen a lockfile that has been committed"));
251 lk->fd = open(lk->filename, O_WRONLY);
252 return lk->fd;
253}
254
021b6e45
JH
255int commit_lock_file(struct lock_file *lk)
256{
257 char result_file[PATH_MAX];
d6cf61bf 258 size_t i;
419f0c0f 259 if (close_lock_file(lk))
d6cf61bf 260 return -1;
021b6e45
JH
261 strcpy(result_file, lk->filename);
262 i = strlen(result_file) - 5; /* .lock */
263 result_file[i] = 0;
d6cf61bf
BC
264 if (rename(lk->filename, result_file))
265 return -1;
021b6e45 266 lk->filename[0] = 0;
d6cf61bf 267 return 0;
021b6e45
JH
268}
269
30ca07a2
JH
270int hold_locked_index(struct lock_file *lk, int die_on_error)
271{
acd3b9ec
JH
272 return hold_lock_file_for_update(lk, get_index_file(),
273 die_on_error
274 ? LOCK_DIE_ON_ERROR
275 : 0);
30ca07a2
JH
276}
277
021b6e45
JH
278void rollback_lock_file(struct lock_file *lk)
279{
9085f8e2
MH
280 if (!lk->filename[0])
281 return;
282
26f5d3b6 283 close_lock_file(lk);
9085f8e2
MH
284 unlink_or_warn(lk->filename);
285 lk->filename[0] = 0;
021b6e45 286}