Merge branch 'mh/lockfile'
[git/mingw/j6t.git] / lockfile.c
blob7bfec4b773bc710b474677b808c4bdacf53af91b
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(void)
12 pid_t me = getpid();
14 while (lock_file_list) {
15 if (lock_file_list->owner == me)
16 rollback_lock_file(lock_file_list);
17 lock_file_list = lock_file_list->next;
21 static void remove_lock_files_on_signal(int signo)
23 remove_lock_files();
24 sigchain_pop(signo);
25 raise(signo);
29 * path = absolute or relative path name
31 * Remove the last path name element from path (leaving the preceding
32 * "/", if any). If path is empty or the root directory ("/"), set
33 * path to the empty string.
35 static void trim_last_path_component(struct strbuf *path)
37 int i = path->len;
39 /* back up past trailing slashes, if any */
40 while (i && path->buf[i - 1] == '/')
41 i--;
44 * then go backwards until a slash, or the beginning of the
45 * string
47 while (i && path->buf[i - 1] != '/')
48 i--;
50 strbuf_setlen(path, i);
54 /* We allow "recursive" symbolic links. Only within reason, though */
55 #define MAXDEPTH 5
58 * path contains a path that might be a symlink.
60 * If path is a symlink, attempt to overwrite it with a path to the
61 * real file or directory (which may or may not exist), following a
62 * chain of symlinks if necessary. Otherwise, leave path unmodified.
64 * This is a best-effort routine. If an error occurs, path will
65 * either be left unmodified or will name a different symlink in a
66 * symlink chain that started with the original path.
68 static void resolve_symlink(struct strbuf *path)
70 int depth = MAXDEPTH;
71 static struct strbuf link = STRBUF_INIT;
73 while (depth--) {
74 if (strbuf_readlink(&link, path->buf, path->len) < 0)
75 break;
77 if (is_absolute_path(link.buf))
78 /* absolute path simply replaces p */
79 strbuf_reset(path);
80 else
82 * link is a relative path, so replace the
83 * last element of p with it.
85 trim_last_path_component(path);
87 strbuf_addbuf(path, &link);
89 strbuf_reset(&link);
92 /* Make sure errno contains a meaningful value on error */
93 static int lock_file(struct lock_file *lk, const char *path, int flags)
95 size_t pathlen = strlen(path);
97 if (!lock_file_list) {
98 /* One-time initialization */
99 sigchain_push_common(remove_lock_files_on_signal);
100 atexit(remove_lock_files);
103 if (lk->active)
104 die("BUG: cannot lock_file(\"%s\") using active struct lock_file",
105 path);
106 if (!lk->on_list) {
107 /* Initialize *lk and add it to lock_file_list: */
108 lk->fd = -1;
109 lk->active = 0;
110 lk->owner = 0;
111 strbuf_init(&lk->filename, pathlen + LOCK_SUFFIX_LEN);
112 lk->next = lock_file_list;
113 lock_file_list = lk;
114 lk->on_list = 1;
115 } else if (lk->filename.len) {
116 /* This shouldn't happen, but better safe than sorry. */
117 die("BUG: lock_file(\"%s\") called with improperly-reset lock_file object",
118 path);
121 strbuf_add(&lk->filename, path, pathlen);
122 if (!(flags & LOCK_NO_DEREF))
123 resolve_symlink(&lk->filename);
124 strbuf_addstr(&lk->filename, LOCK_SUFFIX);
125 lk->fd = open(lk->filename.buf, O_RDWR | O_CREAT | O_EXCL, 0666);
126 if (lk->fd < 0) {
127 strbuf_reset(&lk->filename);
128 return -1;
130 lk->owner = getpid();
131 lk->active = 1;
132 if (adjust_shared_perm(lk->filename.buf)) {
133 int save_errno = errno;
134 error("cannot fix permission bits on %s", lk->filename.buf);
135 rollback_lock_file(lk);
136 errno = save_errno;
137 return -1;
139 return lk->fd;
142 void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
144 if (err == EEXIST) {
145 strbuf_addf(buf, "Unable to create '%s.lock': %s.\n\n"
146 "If no other git process is currently running, this probably means a\n"
147 "git process crashed in this repository earlier. Make sure no other git\n"
148 "process is running and remove the file manually to continue.",
149 absolute_path(path), strerror(err));
150 } else
151 strbuf_addf(buf, "Unable to create '%s.lock': %s",
152 absolute_path(path), strerror(err));
155 int unable_to_lock_error(const char *path, int err)
157 struct strbuf buf = STRBUF_INIT;
159 unable_to_lock_message(path, err, &buf);
160 error("%s", buf.buf);
161 strbuf_release(&buf);
162 return -1;
165 NORETURN void unable_to_lock_die(const char *path, int err)
167 struct strbuf buf = STRBUF_INIT;
169 unable_to_lock_message(path, err, &buf);
170 die("%s", buf.buf);
173 /* This should return a meaningful errno on failure */
174 int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
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;
182 int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
184 int fd, orig_fd;
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;
193 orig_fd = open(path, O_RDONLY);
194 if (orig_fd < 0) {
195 if (errno != ENOENT) {
196 int save_errno = errno;
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;
205 } else if (copy_fd(orig_fd, fd)) {
206 int save_errno = errno;
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);
217 return fd;
220 char *get_locked_file_path(struct lock_file *lk)
222 if (!lk->active)
223 die("BUG: get_locked_file_path() called for unlocked object");
224 if (lk->filename.len <= LOCK_SUFFIX_LEN)
225 die("BUG: get_locked_file_path() called for malformed lock object");
226 return xmemdupz(lk->filename.buf, lk->filename.len - LOCK_SUFFIX_LEN);
229 int close_lock_file(struct lock_file *lk)
231 int fd = lk->fd;
233 if (fd < 0)
234 return 0;
236 lk->fd = -1;
237 if (close(fd)) {
238 int save_errno = errno;
239 rollback_lock_file(lk);
240 errno = save_errno;
241 return -1;
243 return 0;
246 int reopen_lock_file(struct lock_file *lk)
248 if (0 <= lk->fd)
249 die(_("BUG: reopen a lockfile that is still open"));
250 if (!lk->active)
251 die(_("BUG: reopen a lockfile that has been committed"));
252 lk->fd = open(lk->filename.buf, O_WRONLY);
253 return lk->fd;
256 int commit_lock_file_to(struct lock_file *lk, const char *path)
258 if (!lk->active)
259 die("BUG: attempt to commit unlocked object to \"%s\"", path);
261 if (close_lock_file(lk))
262 return -1;
264 if (rename(lk->filename.buf, path)) {
265 int save_errno = errno;
266 rollback_lock_file(lk);
267 errno = save_errno;
268 return -1;
271 lk->active = 0;
272 strbuf_reset(&lk->filename);
273 return 0;
276 int commit_lock_file(struct lock_file *lk)
278 static struct strbuf result_file = STRBUF_INIT;
279 int err;
281 if (!lk->active)
282 die("BUG: attempt to commit unlocked object");
284 if (lk->filename.len <= LOCK_SUFFIX_LEN ||
285 strcmp(lk->filename.buf + lk->filename.len - LOCK_SUFFIX_LEN, LOCK_SUFFIX))
286 die("BUG: lockfile filename corrupt");
288 /* remove ".lock": */
289 strbuf_add(&result_file, lk->filename.buf,
290 lk->filename.len - LOCK_SUFFIX_LEN);
291 err = commit_lock_file_to(lk, result_file.buf);
292 strbuf_reset(&result_file);
293 return err;
296 void rollback_lock_file(struct lock_file *lk)
298 if (!lk->active)
299 return;
301 if (!close_lock_file(lk)) {
302 unlink_or_warn(lk->filename.buf);
303 lk->active = 0;
304 strbuf_reset(&lk->filename);