1/*
2 * Copyright (c) 2005, Junio C Hamano
3 */
4#include "cache.h"
5#include "lockfile.h"
6#include "sigchain.h"
7
8static struct lock_file *volatile lock_file_list;
9
10static void remove_lock_files(int skip_fclose)
11{
12 pid_t me = getpid();
13
14 while (lock_file_list) {
15 if (lock_file_list->owner == me) {
16 /* fclose() is not safe to call in a signal handler */
17 if (skip_fclose)
18 lock_file_list->fp = NULL;
19 rollback_lock_file(lock_file_list);
20 }
21 lock_file_list = lock_file_list->next;
22 }
23}
24
25static void remove_lock_files_on_exit(void)
26{
27 remove_lock_files(0);
28}
29
30static void remove_lock_files_on_signal(int signo)
31{
32 remove_lock_files(1);
33 sigchain_pop(signo);
34 raise(signo);
35}
36
37/*
38 * path = absolute or relative path name
39 *
40 * Remove the last path name element from path (leaving the preceding
41 * "/", if any). If path is empty or the root directory ("/"), set
42 * path to the empty string.
43 */
44static void trim_last_path_component(struct strbuf *path)
45{
46 int i = path->len;
47
48 /* back up past trailing slashes, if any */
49 while (i && path->buf[i - 1] == '/')
50 i--;
51
52 /*
53 * then go backwards until a slash, or the beginning of the
54 * string
55 */
56 while (i && path->buf[i - 1] != '/')
57 i--;
58
59 strbuf_setlen(path, i);
60}
61
62
63/* We allow "recursive" symbolic links. Only within reason, though */
64#define MAXDEPTH 5
65
66/*
67 * path contains a path that might be a symlink.
68 *
69 * If path is a symlink, attempt to overwrite it with a path to the
70 * real file or directory (which may or may not exist), following a
71 * chain of symlinks if necessary. Otherwise, leave path unmodified.
72 *
73 * This is a best-effort routine. If an error occurs, path will
74 * either be left unmodified or will name a different symlink in a
75 * symlink chain that started with the original path.
76 */
77static void resolve_symlink(struct strbuf *path)
78{
79 int depth = MAXDEPTH;
80 static struct strbuf link = STRBUF_INIT;
81
82 while (depth--) {
83 if (strbuf_readlink(&link, path->buf, path->len) < 0)
84 break;
85
86 if (is_absolute_path(link.buf))
87 /* absolute path simply replaces p */
88 strbuf_reset(path);
89 else
90 /*
91 * link is a relative path, so replace the
92 * last element of p with it.
93 */
94 trim_last_path_component(path);
95
96 strbuf_addbuf(path, &link);
97 }
98 strbuf_reset(&link);
99}
100
101/* Make sure errno contains a meaningful value on error */
102static int lock_file(struct lock_file *lk, const char *path, int flags)
103{
104 size_t pathlen = strlen(path);
105
106 if (!lock_file_list) {
107 /* One-time initialization */
108 sigchain_push_common(remove_lock_files_on_signal);
109 atexit(remove_lock_files_on_exit);
110 }
111
112 if (lk->active)
113 die("BUG: cannot lock_file(\"%s\") using active struct lock_file",
114 path);
115 if (!lk->on_list) {
116 /* Initialize *lk and add it to lock_file_list: */
117 lk->fd = -1;
118 lk->fp = NULL;
119 lk->active = 0;
120 lk->owner = 0;
121 strbuf_init(&lk->filename, pathlen + LOCK_SUFFIX_LEN);
122 lk->next = lock_file_list;
123 lock_file_list = lk;
124 lk->on_list = 1;
125 } else if (lk->filename.len) {
126 /* This shouldn't happen, but better safe than sorry. */
127 die("BUG: lock_file(\"%s\") called with improperly-reset lock_file object",
128 path);
129 }
130
131 strbuf_add(&lk->filename, path, pathlen);
132 if (!(flags & LOCK_NO_DEREF))
133 resolve_symlink(&lk->filename);
134 strbuf_addstr(&lk->filename, LOCK_SUFFIX);
135 lk->fd = open(lk->filename.buf, O_RDWR | O_CREAT | O_EXCL, 0666);
136 if (lk->fd < 0) {
137 strbuf_reset(&lk->filename);
138 return -1;
139 }
140 lk->owner = getpid();
141 lk->active = 1;
142 if (adjust_shared_perm(lk->filename.buf)) {
143 int save_errno = errno;
144 error("cannot fix permission bits on %s", lk->filename.buf);
145 rollback_lock_file(lk);
146 errno = save_errno;
147 return -1;
148 }
149 return lk->fd;
150}
151
152void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
153{
154 if (err == EEXIST) {
155 strbuf_addf(buf, "Unable to create '%s.lock': %s.\n\n"
156 "If no other git process is currently running, this probably means a\n"
157 "git process crashed in this repository earlier. Make sure no other git\n"
158 "process is running and remove the file manually to continue.",
159 absolute_path(path), strerror(err));
160 } else
161 strbuf_addf(buf, "Unable to create '%s.lock': %s",
162 absolute_path(path), strerror(err));
163}
164
165NORETURN void unable_to_lock_die(const char *path, int err)
166{
167 struct strbuf buf = STRBUF_INIT;
168
169 unable_to_lock_message(path, err, &buf);
170 die("%s", buf.buf);
171}
172
173/* This should return a meaningful errno on failure */
174int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
175{
176 int fd = lock_file(lk, path, flags);
177 if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
178 unable_to_lock_die(path, errno);
179 return fd;
180}
181
182int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
183{
184 int fd, orig_fd;
185
186 fd = lock_file(lk, path, flags);
187 if (fd < 0) {
188 if (flags & LOCK_DIE_ON_ERROR)
189 unable_to_lock_die(path, errno);
190 return fd;
191 }
192
193 orig_fd = open(path, O_RDONLY);
194 if (orig_fd < 0) {
195 if (errno != ENOENT) {
196 int save_errno = errno;
197
198 if (flags & LOCK_DIE_ON_ERROR)
199 die("cannot open '%s' for copying", path);
200 rollback_lock_file(lk);
201 error("cannot open '%s' for copying", path);
202 errno = save_errno;
203 return -1;
204 }
205 } else if (copy_fd(orig_fd, fd)) {
206 int save_errno = errno;
207
208 if (flags & LOCK_DIE_ON_ERROR)
209 exit(128);
210 close(orig_fd);
211 rollback_lock_file(lk);
212 errno = save_errno;
213 return -1;
214 } else {
215 close(orig_fd);
216 }
217 return fd;
218}
219
220FILE *fdopen_lock_file(struct lock_file *lk, const char *mode)
221{
222 if (!lk->active)
223 die("BUG: fdopen_lock_file() called for unlocked object");
224 if (lk->fp)
225 die("BUG: fdopen_lock_file() called twice for file '%s'", lk->filename.buf);
226
227 lk->fp = fdopen(lk->fd, mode);
228 return lk->fp;
229}
230
231char *get_locked_file_path(struct lock_file *lk)
232{
233 if (!lk->active)
234 die("BUG: get_locked_file_path() called for unlocked object");
235 if (lk->filename.len <= LOCK_SUFFIX_LEN)
236 die("BUG: get_locked_file_path() called for malformed lock object");
237 return xmemdupz(lk->filename.buf, lk->filename.len - LOCK_SUFFIX_LEN);
238}
239
240int close_lock_file(struct lock_file *lk)
241{
242 int fd = lk->fd;
243 FILE *fp = lk->fp;
244 int err;
245
246 if (fd < 0)
247 return 0;
248
249 lk->fd = -1;
250 if (fp) {
251 lk->fp = NULL;
252
253 /*
254 * Note: no short-circuiting here; we want to fclose()
255 * in any case!
256 */
257 err = ferror(fp) | fclose(fp);
258 } else {
259 err = close(fd);
260 }
261
262 if (err) {
263 int save_errno = errno;
264 rollback_lock_file(lk);
265 errno = save_errno;
266 return -1;
267 }
268
269 return 0;
270}
271
272int reopen_lock_file(struct lock_file *lk)
273{
274 if (0 <= lk->fd)
275 die(_("BUG: reopen a lockfile that is still open"));
276 if (!lk->active)
277 die(_("BUG: reopen a lockfile that has been committed"));
278 lk->fd = open(lk->filename.buf, O_WRONLY);
279 return lk->fd;
280}
281
282int commit_lock_file_to(struct lock_file *lk, const char *path)
283{
284 if (!lk->active)
285 die("BUG: attempt to commit unlocked object to \"%s\"", path);
286
287 if (close_lock_file(lk))
288 return -1;
289
290 if (rename(lk->filename.buf, path)) {
291 int save_errno = errno;
292 rollback_lock_file(lk);
293 errno = save_errno;
294 return -1;
295 }
296
297 lk->active = 0;
298 strbuf_reset(&lk->filename);
299 return 0;
300}
301
302int commit_lock_file(struct lock_file *lk)
303{
304 static struct strbuf result_file = STRBUF_INIT;
305 int err;
306
307 if (!lk->active)
308 die("BUG: attempt to commit unlocked object");
309
310 if (lk->filename.len <= LOCK_SUFFIX_LEN ||
311 strcmp(lk->filename.buf + lk->filename.len - LOCK_SUFFIX_LEN, LOCK_SUFFIX))
312 die("BUG: lockfile filename corrupt");
313
314 /* remove ".lock": */
315 strbuf_add(&result_file, lk->filename.buf,
316 lk->filename.len - LOCK_SUFFIX_LEN);
317 err = commit_lock_file_to(lk, result_file.buf);
318 strbuf_reset(&result_file);
319 return err;
320}
321
322void rollback_lock_file(struct lock_file *lk)
323{
324 if (!lk->active)
325 return;
326
327 if (!close_lock_file(lk)) {
328 unlink_or_warn(lk->filename.buf);
329 lk->active = 0;
330 strbuf_reset(&lk->filename);
331 }
332}