]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (c) 2005, Junio C Hamano | |
3 | */ | |
4 | #include "cache.h" | |
5 | #include "lockfile.h" | |
6 | #include "sigchain.h" | |
7 | ||
8 | static struct lock_file *volatile lock_file_list; | |
9 | ||
10 | static 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 | ||
25 | static void remove_lock_files_on_exit(void) | |
26 | { | |
27 | remove_lock_files(0); | |
28 | } | |
29 | ||
30 | static 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 | */ | |
44 | static 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 | */ | |
77 | static 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 */ | |
102 | static 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 | if (flags & LOCK_NO_DEREF) { | |
132 | strbuf_add_absolute_path(&lk->filename, path); | |
133 | } else { | |
134 | struct strbuf resolved_path = STRBUF_INIT; | |
135 | ||
136 | strbuf_add(&resolved_path, path, pathlen); | |
137 | resolve_symlink(&resolved_path); | |
138 | strbuf_add_absolute_path(&lk->filename, resolved_path.buf); | |
139 | strbuf_release(&resolved_path); | |
140 | } | |
141 | ||
142 | strbuf_addstr(&lk->filename, LOCK_SUFFIX); | |
143 | lk->fd = open(lk->filename.buf, O_RDWR | O_CREAT | O_EXCL, 0666); | |
144 | if (lk->fd < 0) { | |
145 | strbuf_reset(&lk->filename); | |
146 | return -1; | |
147 | } | |
148 | lk->owner = getpid(); | |
149 | lk->active = 1; | |
150 | if (adjust_shared_perm(lk->filename.buf)) { | |
151 | int save_errno = errno; | |
152 | error("cannot fix permission bits on %s", lk->filename.buf); | |
153 | rollback_lock_file(lk); | |
154 | errno = save_errno; | |
155 | return -1; | |
156 | } | |
157 | return lk->fd; | |
158 | } | |
159 | ||
160 | void unable_to_lock_message(const char *path, int err, struct strbuf *buf) | |
161 | { | |
162 | if (err == EEXIST) { | |
163 | strbuf_addf(buf, "Unable to create '%s.lock': %s.\n\n" | |
164 | "If no other git process is currently running, this probably means a\n" | |
165 | "git process crashed in this repository earlier. Make sure no other git\n" | |
166 | "process is running and remove the file manually to continue.", | |
167 | absolute_path(path), strerror(err)); | |
168 | } else | |
169 | strbuf_addf(buf, "Unable to create '%s.lock': %s", | |
170 | absolute_path(path), strerror(err)); | |
171 | } | |
172 | ||
173 | NORETURN void unable_to_lock_die(const char *path, int err) | |
174 | { | |
175 | struct strbuf buf = STRBUF_INIT; | |
176 | ||
177 | unable_to_lock_message(path, err, &buf); | |
178 | die("%s", buf.buf); | |
179 | } | |
180 | ||
181 | /* This should return a meaningful errno on failure */ | |
182 | int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags) | |
183 | { | |
184 | int fd = lock_file(lk, path, flags); | |
185 | if (fd < 0 && (flags & LOCK_DIE_ON_ERROR)) | |
186 | unable_to_lock_die(path, errno); | |
187 | return fd; | |
188 | } | |
189 | ||
190 | int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags) | |
191 | { | |
192 | int fd, orig_fd; | |
193 | ||
194 | fd = lock_file(lk, path, flags); | |
195 | if (fd < 0) { | |
196 | if (flags & LOCK_DIE_ON_ERROR) | |
197 | unable_to_lock_die(path, errno); | |
198 | return fd; | |
199 | } | |
200 | ||
201 | orig_fd = open(path, O_RDONLY); | |
202 | if (orig_fd < 0) { | |
203 | if (errno != ENOENT) { | |
204 | int save_errno = errno; | |
205 | ||
206 | if (flags & LOCK_DIE_ON_ERROR) | |
207 | die("cannot open '%s' for copying", path); | |
208 | rollback_lock_file(lk); | |
209 | error("cannot open '%s' for copying", path); | |
210 | errno = save_errno; | |
211 | return -1; | |
212 | } | |
213 | } else if (copy_fd(orig_fd, fd)) { | |
214 | int save_errno = errno; | |
215 | ||
216 | if (flags & LOCK_DIE_ON_ERROR) | |
217 | exit(128); | |
218 | close(orig_fd); | |
219 | rollback_lock_file(lk); | |
220 | errno = save_errno; | |
221 | return -1; | |
222 | } else { | |
223 | close(orig_fd); | |
224 | } | |
225 | return fd; | |
226 | } | |
227 | ||
228 | FILE *fdopen_lock_file(struct lock_file *lk, const char *mode) | |
229 | { | |
230 | if (!lk->active) | |
231 | die("BUG: fdopen_lock_file() called for unlocked object"); | |
232 | if (lk->fp) | |
233 | die("BUG: fdopen_lock_file() called twice for file '%s'", lk->filename.buf); | |
234 | ||
235 | lk->fp = fdopen(lk->fd, mode); | |
236 | return lk->fp; | |
237 | } | |
238 | ||
239 | char *get_locked_file_path(struct lock_file *lk) | |
240 | { | |
241 | if (!lk->active) | |
242 | die("BUG: get_locked_file_path() called for unlocked object"); | |
243 | if (lk->filename.len <= LOCK_SUFFIX_LEN) | |
244 | die("BUG: get_locked_file_path() called for malformed lock object"); | |
245 | return xmemdupz(lk->filename.buf, lk->filename.len - LOCK_SUFFIX_LEN); | |
246 | } | |
247 | ||
248 | int close_lock_file(struct lock_file *lk) | |
249 | { | |
250 | int fd = lk->fd; | |
251 | FILE *fp = lk->fp; | |
252 | int err; | |
253 | ||
254 | if (fd < 0) | |
255 | return 0; | |
256 | ||
257 | lk->fd = -1; | |
258 | if (fp) { | |
259 | lk->fp = NULL; | |
260 | ||
261 | /* | |
262 | * Note: no short-circuiting here; we want to fclose() | |
263 | * in any case! | |
264 | */ | |
265 | err = ferror(fp) | fclose(fp); | |
266 | } else { | |
267 | err = close(fd); | |
268 | } | |
269 | ||
270 | if (err) { | |
271 | int save_errno = errno; | |
272 | rollback_lock_file(lk); | |
273 | errno = save_errno; | |
274 | return -1; | |
275 | } | |
276 | ||
277 | return 0; | |
278 | } | |
279 | ||
280 | int reopen_lock_file(struct lock_file *lk) | |
281 | { | |
282 | if (0 <= lk->fd) | |
283 | die(_("BUG: reopen a lockfile that is still open")); | |
284 | if (!lk->active) | |
285 | die(_("BUG: reopen a lockfile that has been committed")); | |
286 | lk->fd = open(lk->filename.buf, O_WRONLY); | |
287 | return lk->fd; | |
288 | } | |
289 | ||
290 | int commit_lock_file_to(struct lock_file *lk, const char *path) | |
291 | { | |
292 | if (!lk->active) | |
293 | die("BUG: attempt to commit unlocked object to \"%s\"", path); | |
294 | ||
295 | if (close_lock_file(lk)) | |
296 | return -1; | |
297 | ||
298 | if (rename(lk->filename.buf, path)) { | |
299 | int save_errno = errno; | |
300 | rollback_lock_file(lk); | |
301 | errno = save_errno; | |
302 | return -1; | |
303 | } | |
304 | ||
305 | lk->active = 0; | |
306 | strbuf_reset(&lk->filename); | |
307 | return 0; | |
308 | } | |
309 | ||
310 | int commit_lock_file(struct lock_file *lk) | |
311 | { | |
312 | static struct strbuf result_file = STRBUF_INIT; | |
313 | int err; | |
314 | ||
315 | if (!lk->active) | |
316 | die("BUG: attempt to commit unlocked object"); | |
317 | ||
318 | if (lk->filename.len <= LOCK_SUFFIX_LEN || | |
319 | strcmp(lk->filename.buf + lk->filename.len - LOCK_SUFFIX_LEN, LOCK_SUFFIX)) | |
320 | die("BUG: lockfile filename corrupt"); | |
321 | ||
322 | /* remove ".lock": */ | |
323 | strbuf_add(&result_file, lk->filename.buf, | |
324 | lk->filename.len - LOCK_SUFFIX_LEN); | |
325 | err = commit_lock_file_to(lk, result_file.buf); | |
326 | strbuf_reset(&result_file); | |
327 | return err; | |
328 | } | |
329 | ||
330 | void rollback_lock_file(struct lock_file *lk) | |
331 | { | |
332 | if (!lk->active) | |
333 | return; | |
334 | ||
335 | if (!close_lock_file(lk)) { | |
336 | unlink_or_warn(lk->filename.buf); | |
337 | lk->active = 0; | |
338 | strbuf_reset(&lk->filename); | |
339 | } | |
340 | } |