t1700: new tests for split-index mode
[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
123
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
132 if (strlen(path) >= max_path_len)
133 return -1;
134 strcpy(lk->filename, path);
acd3b9ec 135 if (!(flags & LOCK_NODEREF))
2fbd4f92 136 resolve_symlink(lk->filename, max_path_len);
5d5a7a67 137 strcat(lk->filename, ".lock");
4723ee99
JS
138 lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
139 if (0 <= lk->fd) {
9a4cbdca 140 if (!lock_file_list) {
57b235a4 141 sigchain_push_common(remove_lock_file_on_signal);
9a4cbdca
SV
142 atexit(remove_lock_file);
143 }
5e635e39 144 lk->owner = getpid();
1084b845 145 if (!lk->on_list) {
138086a7
JH
146 lk->next = lock_file_list;
147 lock_file_list = lk;
1084b845
JH
148 lk->on_list = 1;
149 }
138086a7
JH
150 if (adjust_shared_perm(lk->filename))
151 return error("cannot fix permission bits on %s",
152 lk->filename);
021b6e45 153 }
1084b845
JH
154 else
155 lk->filename[0] = 0;
4723ee99 156 return lk->fd;
021b6e45
JH
157}
158
1b018fd9 159static char *unable_to_lock_message(const char *path, int err)
e43a6fd3 160{
1b018fd9
MV
161 struct strbuf buf = STRBUF_INIT;
162
bdfd739d 163 if (err == EEXIST) {
1b018fd9 164 strbuf_addf(&buf, "Unable to create '%s.lock': %s.\n\n"
e43a6fd3
MM
165 "If no other git process is currently running, this probably means a\n"
166 "git process crashed in this repository earlier. Make sure no other git\n"
167 "process is running and remove the file manually to continue.",
e2a57aac 168 absolute_path(path), strerror(err));
1b018fd9 169 } else
a8c37a0e 170 strbuf_addf(&buf, "Unable to create '%s.lock': %s",
e2a57aac 171 absolute_path(path), strerror(err));
1b018fd9
MV
172 return strbuf_detach(&buf, NULL);
173}
174
175int unable_to_lock_error(const char *path, int err)
176{
177 char *msg = unable_to_lock_message(path, err);
178 error("%s", msg);
179 free(msg);
180 return -1;
181}
182
183NORETURN void unable_to_lock_index_die(const char *path, int err)
184{
185 die("%s", unable_to_lock_message(path, err));
e43a6fd3
MM
186}
187
acd3b9ec 188int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
40aaae88 189{
acd3b9ec
JH
190 int fd = lock_file(lk, path, flags);
191 if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
e43a6fd3 192 unable_to_lock_index_die(path, errno);
40aaae88
JH
193 return fd;
194}
195
acd3b9ec 196int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
ea3cd5c7
DB
197{
198 int fd, orig_fd;
199
acd3b9ec 200 fd = lock_file(lk, path, flags);
ea3cd5c7 201 if (fd < 0) {
acd3b9ec 202 if (flags & LOCK_DIE_ON_ERROR)
bdfd739d 203 unable_to_lock_index_die(path, errno);
ea3cd5c7
DB
204 return fd;
205 }
206
207 orig_fd = open(path, O_RDONLY);
208 if (orig_fd < 0) {
209 if (errno != ENOENT) {
acd3b9ec 210 if (flags & LOCK_DIE_ON_ERROR)
ea3cd5c7
DB
211 die("cannot open '%s' for copying", path);
212 close(fd);
213 return error("cannot open '%s' for copying", path);
214 }
215 } else if (copy_fd(orig_fd, fd)) {
acd3b9ec 216 if (flags & LOCK_DIE_ON_ERROR)
ea3cd5c7
DB
217 exit(128);
218 close(fd);
219 return -1;
220 }
221 return fd;
222}
223
d6cf61bf
BC
224int close_lock_file(struct lock_file *lk)
225{
226 int fd = lk->fd;
227 lk->fd = -1;
228 return close(fd);
229}
230
021b6e45
JH
231int commit_lock_file(struct lock_file *lk)
232{
233 char result_file[PATH_MAX];
d6cf61bf
BC
234 size_t i;
235 if (lk->fd >= 0 && close_lock_file(lk))
236 return -1;
021b6e45
JH
237 strcpy(result_file, lk->filename);
238 i = strlen(result_file) - 5; /* .lock */
239 result_file[i] = 0;
d6cf61bf
BC
240 if (rename(lk->filename, result_file))
241 return -1;
021b6e45 242 lk->filename[0] = 0;
d6cf61bf 243 return 0;
021b6e45
JH
244}
245
30ca07a2
JH
246int hold_locked_index(struct lock_file *lk, int die_on_error)
247{
acd3b9ec
JH
248 return hold_lock_file_for_update(lk, get_index_file(),
249 die_on_error
250 ? LOCK_DIE_ON_ERROR
251 : 0);
30ca07a2
JH
252}
253
021b6e45
JH
254void rollback_lock_file(struct lock_file *lk)
255{
4723ee99 256 if (lk->filename[0]) {
d6cf61bf
BC
257 if (lk->fd >= 0)
258 close(lk->fd);
691f1a28 259 unlink_or_warn(lk->filename);
4723ee99 260 }
021b6e45
JH
261 lk->filename[0] = 0;
262}