1/*
2 * Copyright (c) 2005, Junio C Hamano
3 */
4#include "cache.h"
5#include "sigchain.h"
6
7static struct lock_file *lock_file_list;
8static const char *alternate_index_output;
9
10static void remove_lock_file(void)
11{
12 pid_t me = getpid();
13
14 while (lock_file_list) {
15 if (lock_file_list->owner == me &&
16 lock_file_list->filename[0]) {
17 if (lock_file_list->fd >= 0)
18 close(lock_file_list->fd);
19 unlink_or_warn(lock_file_list->filename);
20 }
21 lock_file_list = lock_file_list->next;
22 }
23}
24
25static void remove_lock_file_on_signal(int signo)
26{
27 remove_lock_file();
28 sigchain_pop(signo);
29 raise(signo);
30}
31
32/*
33 * p = absolute or relative path name
34 *
35 * Return a pointer into p showing the beginning of the last path name
36 * element. If p is empty or the root directory ("/"), just return p.
37 */
38static char *last_path_elm(char *p)
39{
40 /* r starts pointing to null at the end of the string */
41 char *r = strchr(p, '\0');
42
43 if (r == p)
44 return p; /* just return empty string */
45
46 r--; /* back up to last non-null character */
47
48 /* back up past trailing slashes, if any */
49 while (r > p && *r == '/')
50 r--;
51
52 /*
53 * then go backwards until I hit a slash, or the beginning of
54 * the string
55 */
56 while (r > p && *(r-1) != '/')
57 r--;
58 return r;
59}
60
61
62/* We allow "recursive" symbolic links. Only within reason, though */
63#define MAXDEPTH 5
64
65/*
66 * p = path that may be a symlink
67 * s = full size of p
68 *
69 * If p is a symlink, attempt to overwrite p with a path to the real
70 * file or directory (which may or may not exist), following a chain of
71 * symlinks if necessary. Otherwise, leave p unmodified.
72 *
73 * This is a best-effort routine. If an error occurs, p will either be
74 * left unmodified or will name a different symlink in a symlink chain
75 * that started with p's initial contents.
76 *
77 * Always returns p.
78 */
79
80static char *resolve_symlink(char *p, size_t s)
81{
82 int depth = MAXDEPTH;
83
84 while (depth--) {
85 char link[PATH_MAX];
86 int link_len = readlink(p, link, sizeof(link));
87 if (link_len < 0) {
88 /* not a symlink anymore */
89 return p;
90 }
91 else if (link_len < sizeof(link))
92 /* readlink() never null-terminates */
93 link[link_len] = '\0';
94 else {
95 warning("%s: symlink too long", p);
96 return p;
97 }
98
99 if (is_absolute_path(link)) {
100 /* absolute path simply replaces p */
101 if (link_len < s)
102 strcpy(p, link);
103 else {
104 warning("%s: symlink too long", p);
105 return p;
106 }
107 } else {
108 /*
109 * link is a relative path, so I must replace the
110 * last element of p with it.
111 */
112 char *r = (char *)last_path_elm(p);
113 if (r - p + link_len < s)
114 strcpy(r, link);
115 else {
116 warning("%s: symlink too long", p);
117 return p;
118 }
119 }
120 }
121 return p;
122}
123
124/* Make sure errno contains a meaningful value on error */
125static int lock_file(struct lock_file *lk, const char *path, int flags)
126{
127 /*
128 * subtract 5 from size to make sure there's room for adding
129 * ".lock" for the lock file name
130 */
131 static const size_t max_path_len = sizeof(lk->filename) - 5;
132
133 if (strlen(path) >= max_path_len) {
134 errno = ENAMETOOLONG;
135 return -1;
136 }
137 strcpy(lk->filename, path);
138 if (!(flags & LOCK_NODEREF))
139 resolve_symlink(lk->filename, max_path_len);
140 strcat(lk->filename, ".lock");
141 lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
142 if (0 <= lk->fd) {
143 if (!lock_file_list) {
144 sigchain_push_common(remove_lock_file_on_signal);
145 atexit(remove_lock_file);
146 }
147 lk->owner = getpid();
148 if (!lk->on_list) {
149 lk->next = lock_file_list;
150 lock_file_list = lk;
151 lk->on_list = 1;
152 }
153 if (adjust_shared_perm(lk->filename)) {
154 int save_errno = errno;
155 error("cannot fix permission bits on %s",
156 lk->filename);
157 errno = save_errno;
158 return -1;
159 }
160 }
161 else
162 lk->filename[0] = 0;
163 return lk->fd;
164}
165
166void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
167{
168 if (err == EEXIST) {
169 strbuf_addf(buf, "Unable to create '%s.lock': %s.\n\n"
170 "If no other git process is currently running, this probably means a\n"
171 "git process crashed in this repository earlier. Make sure no other git\n"
172 "process is running and remove the file manually to continue.",
173 absolute_path(path), strerror(err));
174 } else
175 strbuf_addf(buf, "Unable to create '%s.lock': %s",
176 absolute_path(path), strerror(err));
177}
178
179int unable_to_lock_error(const char *path, int err)
180{
181 struct strbuf buf = STRBUF_INIT;
182
183 unable_to_lock_message(path, err, &buf);
184 error("%s", buf.buf);
185 strbuf_release(&buf);
186 return -1;
187}
188
189NORETURN void unable_to_lock_index_die(const char *path, int err)
190{
191 struct strbuf buf = STRBUF_INIT;
192
193 unable_to_lock_message(path, err, &buf);
194 die("%s", buf.buf);
195}
196
197/* This should return a meaningful errno on failure */
198int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
199{
200 int fd = lock_file(lk, path, flags);
201 if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
202 unable_to_lock_index_die(path, errno);
203 return fd;
204}
205
206int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
207{
208 int fd, orig_fd;
209
210 fd = lock_file(lk, path, flags);
211 if (fd < 0) {
212 if (flags & LOCK_DIE_ON_ERROR)
213 unable_to_lock_index_die(path, errno);
214 return fd;
215 }
216
217 orig_fd = open(path, O_RDONLY);
218 if (orig_fd < 0) {
219 if (errno != ENOENT) {
220 if (flags & LOCK_DIE_ON_ERROR)
221 die("cannot open '%s' for copying", path);
222 close(fd);
223 return error("cannot open '%s' for copying", path);
224 }
225 } else if (copy_fd(orig_fd, fd)) {
226 if (flags & LOCK_DIE_ON_ERROR)
227 exit(128);
228 close(fd);
229 return -1;
230 }
231 return fd;
232}
233
234int close_lock_file(struct lock_file *lk)
235{
236 int fd = lk->fd;
237 lk->fd = -1;
238 return close(fd);
239}
240
241int commit_lock_file(struct lock_file *lk)
242{
243 char result_file[PATH_MAX];
244 size_t i;
245 if (lk->fd >= 0 && close_lock_file(lk))
246 return -1;
247 strcpy(result_file, lk->filename);
248 i = strlen(result_file) - 5; /* .lock */
249 result_file[i] = 0;
250 if (rename(lk->filename, result_file))
251 return -1;
252 lk->filename[0] = 0;
253 return 0;
254}
255
256int hold_locked_index(struct lock_file *lk, int die_on_error)
257{
258 return hold_lock_file_for_update(lk, get_index_file(),
259 die_on_error
260 ? LOCK_DIE_ON_ERROR
261 : 0);
262}
263
264void set_alternate_index_output(const char *name)
265{
266 alternate_index_output = name;
267}
268
269int commit_locked_index(struct lock_file *lk)
270{
271 if (alternate_index_output) {
272 if (lk->fd >= 0 && close_lock_file(lk))
273 return -1;
274 if (rename(lk->filename, alternate_index_output))
275 return -1;
276 lk->filename[0] = 0;
277 return 0;
278 }
279 else
280 return commit_lock_file(lk);
281}
282
283void rollback_lock_file(struct lock_file *lk)
284{
285 if (lk->filename[0]) {
286 if (lk->fd >= 0)
287 close(lk->fd);
288 unlink_or_warn(lk->filename);
289 }
290 lk->filename[0] = 0;
291}