Merge branch 'po/everyday-doc'
[git/mjg.git] / lockfile.c
blobd098adebf1454ea9c9204c9dd2fda4d51b63a1e5
1 /*
2 * Copyright (c) 2005, Junio C Hamano
3 */
4 #include "cache.h"
5 #include "lockfile.h"
6 #include "sigchain.h"
8 static struct lock_file *volatile lock_file_list;
10 static void remove_lock_files(int skip_fclose)
12 pid_t me = getpid();
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);
21 lock_file_list = lock_file_list->next;
25 static void remove_lock_files_on_exit(void)
27 remove_lock_files(0);
30 static void remove_lock_files_on_signal(int signo)
32 remove_lock_files(1);
33 sigchain_pop(signo);
34 raise(signo);
38 * path = absolute or relative path name
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.
44 static void trim_last_path_component(struct strbuf *path)
46 int i = path->len;
48 /* back up past trailing slashes, if any */
49 while (i && path->buf[i - 1] == '/')
50 i--;
53 * then go backwards until a slash, or the beginning of the
54 * string
56 while (i && path->buf[i - 1] != '/')
57 i--;
59 strbuf_setlen(path, i);
63 /* We allow "recursive" symbolic links. Only within reason, though */
64 #define MAXDEPTH 5
67 * path contains a path that might be a symlink.
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.
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.
77 static void resolve_symlink(struct strbuf *path)
79 int depth = MAXDEPTH;
80 static struct strbuf link = STRBUF_INIT;
82 while (depth--) {
83 if (strbuf_readlink(&link, path->buf, path->len) < 0)
84 break;
86 if (is_absolute_path(link.buf))
87 /* absolute path simply replaces p */
88 strbuf_reset(path);
89 else
91 * link is a relative path, so replace the
92 * last element of p with it.
94 trim_last_path_component(path);
96 strbuf_addbuf(path, &link);
98 strbuf_reset(&link);
101 /* Make sure errno contains a meaningful value on error */
102 static int lock_file(struct lock_file *lk, const char *path, int flags)
104 size_t pathlen = strlen(path);
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);
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);
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;
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;
149 return lk->fd;
152 void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
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));
165 int unable_to_lock_error(const char *path, int err)
167 struct strbuf buf = STRBUF_INIT;
169 unable_to_lock_message(path, err, &buf);
170 error("%s", buf.buf);
171 strbuf_release(&buf);
172 return -1;
175 NORETURN void unable_to_lock_die(const char *path, int err)
177 struct strbuf buf = STRBUF_INIT;
179 unable_to_lock_message(path, err, &buf);
180 die("%s", buf.buf);
183 /* This should return a meaningful errno on failure */
184 int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
186 int fd = lock_file(lk, path, flags);
187 if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
188 unable_to_lock_die(path, errno);
189 return fd;
192 int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
194 int fd, orig_fd;
196 fd = lock_file(lk, path, flags);
197 if (fd < 0) {
198 if (flags & LOCK_DIE_ON_ERROR)
199 unable_to_lock_die(path, errno);
200 return fd;
203 orig_fd = open(path, O_RDONLY);
204 if (orig_fd < 0) {
205 if (errno != ENOENT) {
206 int save_errno = errno;
208 if (flags & LOCK_DIE_ON_ERROR)
209 die("cannot open '%s' for copying", path);
210 rollback_lock_file(lk);
211 error("cannot open '%s' for copying", path);
212 errno = save_errno;
213 return -1;
215 } else if (copy_fd(orig_fd, fd)) {
216 int save_errno = errno;
218 if (flags & LOCK_DIE_ON_ERROR)
219 exit(128);
220 close(orig_fd);
221 rollback_lock_file(lk);
222 errno = save_errno;
223 return -1;
224 } else {
225 close(orig_fd);
227 return fd;
230 FILE *fdopen_lock_file(struct lock_file *lk, const char *mode)
232 if (!lk->active)
233 die("BUG: fdopen_lock_file() called for unlocked object");
234 if (lk->fp)
235 die("BUG: fdopen_lock_file() called twice for file '%s'", lk->filename.buf);
237 lk->fp = fdopen(lk->fd, mode);
238 return lk->fp;
241 char *get_locked_file_path(struct lock_file *lk)
243 if (!lk->active)
244 die("BUG: get_locked_file_path() called for unlocked object");
245 if (lk->filename.len <= LOCK_SUFFIX_LEN)
246 die("BUG: get_locked_file_path() called for malformed lock object");
247 return xmemdupz(lk->filename.buf, lk->filename.len - LOCK_SUFFIX_LEN);
250 int close_lock_file(struct lock_file *lk)
252 int fd = lk->fd;
253 FILE *fp = lk->fp;
254 int err;
256 if (fd < 0)
257 return 0;
259 lk->fd = -1;
260 if (fp) {
261 lk->fp = NULL;
264 * Note: no short-circuiting here; we want to fclose()
265 * in any case!
267 err = ferror(fp) | fclose(fp);
268 } else {
269 err = close(fd);
272 if (err) {
273 int save_errno = errno;
274 rollback_lock_file(lk);
275 errno = save_errno;
276 return -1;
279 return 0;
282 int reopen_lock_file(struct lock_file *lk)
284 if (0 <= lk->fd)
285 die(_("BUG: reopen a lockfile that is still open"));
286 if (!lk->active)
287 die(_("BUG: reopen a lockfile that has been committed"));
288 lk->fd = open(lk->filename.buf, O_WRONLY);
289 return lk->fd;
292 int commit_lock_file_to(struct lock_file *lk, const char *path)
294 if (!lk->active)
295 die("BUG: attempt to commit unlocked object to \"%s\"", path);
297 if (close_lock_file(lk))
298 return -1;
300 if (rename(lk->filename.buf, path)) {
301 int save_errno = errno;
302 rollback_lock_file(lk);
303 errno = save_errno;
304 return -1;
307 lk->active = 0;
308 strbuf_reset(&lk->filename);
309 return 0;
312 int commit_lock_file(struct lock_file *lk)
314 static struct strbuf result_file = STRBUF_INIT;
315 int err;
317 if (!lk->active)
318 die("BUG: attempt to commit unlocked object");
320 if (lk->filename.len <= LOCK_SUFFIX_LEN ||
321 strcmp(lk->filename.buf + lk->filename.len - LOCK_SUFFIX_LEN, LOCK_SUFFIX))
322 die("BUG: lockfile filename corrupt");
324 /* remove ".lock": */
325 strbuf_add(&result_file, lk->filename.buf,
326 lk->filename.len - LOCK_SUFFIX_LEN);
327 err = commit_lock_file_to(lk, result_file.buf);
328 strbuf_reset(&result_file);
329 return err;
332 void rollback_lock_file(struct lock_file *lk)
334 if (!lk->active)
335 return;
337 if (!close_lock_file(lk)) {
338 unlink_or_warn(lk->filename.buf);
339 lk->active = 0;
340 strbuf_reset(&lk->filename);