api-lockfile: revise and expand the documentation
[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);
156 errno = save_errno;
157 return -1;
158 }
021b6e45 159 }
1084b845
JH
160 else
161 lk->filename[0] = 0;
4723ee99 162 return lk->fd;
021b6e45
JH
163}
164
6af926e8 165void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
e43a6fd3 166{
bdfd739d 167 if (err == EEXIST) {
6af926e8 168 strbuf_addf(buf, "Unable to create '%s.lock': %s.\n\n"
e43a6fd3
MM
169 "If no other git process is currently running, this probably means a\n"
170 "git process crashed in this repository earlier. Make sure no other git\n"
171 "process is running and remove the file manually to continue.",
e2a57aac 172 absolute_path(path), strerror(err));
1b018fd9 173 } else
6af926e8 174 strbuf_addf(buf, "Unable to create '%s.lock': %s",
e2a57aac 175 absolute_path(path), strerror(err));
1b018fd9
MV
176}
177
178int unable_to_lock_error(const char *path, int err)
179{
6af926e8
RS
180 struct strbuf buf = STRBUF_INIT;
181
182 unable_to_lock_message(path, err, &buf);
183 error("%s", buf.buf);
184 strbuf_release(&buf);
1b018fd9
MV
185 return -1;
186}
187
e197c218 188NORETURN void unable_to_lock_die(const char *path, int err)
1b018fd9 189{
6af926e8
RS
190 struct strbuf buf = STRBUF_INIT;
191
192 unable_to_lock_message(path, err, &buf);
193 die("%s", buf.buf);
e43a6fd3
MM
194}
195
447ff1bf 196/* This should return a meaningful errno on failure */
acd3b9ec 197int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
40aaae88 198{
acd3b9ec
JH
199 int fd = lock_file(lk, path, flags);
200 if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
e197c218 201 unable_to_lock_die(path, errno);
40aaae88
JH
202 return fd;
203}
204
acd3b9ec 205int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
ea3cd5c7
DB
206{
207 int fd, orig_fd;
208
acd3b9ec 209 fd = lock_file(lk, path, flags);
ea3cd5c7 210 if (fd < 0) {
acd3b9ec 211 if (flags & LOCK_DIE_ON_ERROR)
e197c218 212 unable_to_lock_die(path, errno);
ea3cd5c7
DB
213 return fd;
214 }
215
216 orig_fd = open(path, O_RDONLY);
217 if (orig_fd < 0) {
218 if (errno != ENOENT) {
acd3b9ec 219 if (flags & LOCK_DIE_ON_ERROR)
ea3cd5c7
DB
220 die("cannot open '%s' for copying", path);
221 close(fd);
222 return error("cannot open '%s' for copying", path);
223 }
224 } else if (copy_fd(orig_fd, fd)) {
acd3b9ec 225 if (flags & LOCK_DIE_ON_ERROR)
ea3cd5c7
DB
226 exit(128);
227 close(fd);
228 return -1;
229 }
230 return fd;
231}
232
d6cf61bf
BC
233int close_lock_file(struct lock_file *lk)
234{
235 int fd = lk->fd;
236 lk->fd = -1;
237 return close(fd);
238}
239
93dcaea2
JH
240int reopen_lock_file(struct lock_file *lk)
241{
242 if (0 <= lk->fd)
243 die(_("BUG: reopen a lockfile that is still open"));
244 if (!lk->filename[0])
245 die(_("BUG: reopen a lockfile that has been committed"));
246 lk->fd = open(lk->filename, O_WRONLY);
247 return lk->fd;
248}
249
021b6e45
JH
250int commit_lock_file(struct lock_file *lk)
251{
252 char result_file[PATH_MAX];
d6cf61bf
BC
253 size_t i;
254 if (lk->fd >= 0 && close_lock_file(lk))
255 return -1;
021b6e45
JH
256 strcpy(result_file, lk->filename);
257 i = strlen(result_file) - 5; /* .lock */
258 result_file[i] = 0;
d6cf61bf
BC
259 if (rename(lk->filename, result_file))
260 return -1;
021b6e45 261 lk->filename[0] = 0;
d6cf61bf 262 return 0;
021b6e45
JH
263}
264
30ca07a2
JH
265int hold_locked_index(struct lock_file *lk, int die_on_error)
266{
acd3b9ec
JH
267 return hold_lock_file_for_update(lk, get_index_file(),
268 die_on_error
269 ? LOCK_DIE_ON_ERROR
270 : 0);
30ca07a2
JH
271}
272
021b6e45
JH
273void rollback_lock_file(struct lock_file *lk)
274{
4723ee99 275 if (lk->filename[0]) {
d6cf61bf
BC
276 if (lk->fd >= 0)
277 close(lk->fd);
691f1a28 278 unlink_or_warn(lk->filename);
4723ee99 279 }
021b6e45
JH
280 lk->filename[0] = 0;
281}