]> git.ipfire.org Git - thirdparty/git.git/blame - lockfile.c
Name make_*_path functions more accurately
[thirdparty/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;
5e7f56ac 8static const char *alternate_index_output;
021b6e45
JH
9
10static void remove_lock_file(void)
11{
5e635e39
JH
12 pid_t me = getpid();
13
021b6e45 14 while (lock_file_list) {
5e635e39 15 if (lock_file_list->owner == me &&
4723ee99 16 lock_file_list->filename[0]) {
d6cf61bf
BC
17 if (lock_file_list->fd >= 0)
18 close(lock_file_list->fd);
691f1a28 19 unlink_or_warn(lock_file_list->filename);
4723ee99 20 }
021b6e45
JH
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();
4a16d072 28 sigchain_pop(signo);
021b6e45
JH
29 raise(signo);
30}
31
5d5a7a67
BS
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
ecf4831d 99 if (is_absolute_path(link)) {
5d5a7a67
BS
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 */
4b25d091 112 char *r = (char *)last_path_elm(p);
5d5a7a67
BS
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
acd3b9ec 125static int lock_file(struct lock_file *lk, const char *path, int flags)
021b6e45 126{
acd3b9ec
JH
127 if (strlen(path) >= sizeof(lk->filename))
128 return -1;
5d5a7a67
BS
129 strcpy(lk->filename, path);
130 /*
131 * subtract 5 from size to make sure there's room for adding
132 * ".lock" for the lock file name
133 */
acd3b9ec
JH
134 if (!(flags & LOCK_NODEREF))
135 resolve_symlink(lk->filename, sizeof(lk->filename)-5);
5d5a7a67 136 strcat(lk->filename, ".lock");
4723ee99
JS
137 lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
138 if (0 <= lk->fd) {
9a4cbdca 139 if (!lock_file_list) {
57b235a4 140 sigchain_push_common(remove_lock_file_on_signal);
9a4cbdca
SV
141 atexit(remove_lock_file);
142 }
5e635e39 143 lk->owner = getpid();
1084b845 144 if (!lk->on_list) {
138086a7
JH
145 lk->next = lock_file_list;
146 lock_file_list = lk;
1084b845
JH
147 lk->on_list = 1;
148 }
138086a7
JH
149 if (adjust_shared_perm(lk->filename))
150 return error("cannot fix permission bits on %s",
151 lk->filename);
021b6e45 152 }
1084b845
JH
153 else
154 lk->filename[0] = 0;
4723ee99 155 return lk->fd;
021b6e45
JH
156}
157
1b018fd9 158static char *unable_to_lock_message(const char *path, int err)
e43a6fd3 159{
1b018fd9
MV
160 struct strbuf buf = STRBUF_INIT;
161
bdfd739d 162 if (err == EEXIST) {
1b018fd9 163 strbuf_addf(&buf, "Unable to create '%s.lock': %s.\n\n"
e43a6fd3
MM
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.",
e2a57aac 167 absolute_path(path), strerror(err));
1b018fd9 168 } else
a8c37a0e 169 strbuf_addf(&buf, "Unable to create '%s.lock': %s",
e2a57aac 170 absolute_path(path), strerror(err));
1b018fd9
MV
171 return strbuf_detach(&buf, NULL);
172}
173
174int unable_to_lock_error(const char *path, int err)
175{
176 char *msg = unable_to_lock_message(path, err);
177 error("%s", msg);
178 free(msg);
179 return -1;
180}
181
182NORETURN void unable_to_lock_index_die(const char *path, int err)
183{
184 die("%s", unable_to_lock_message(path, err));
e43a6fd3
MM
185}
186
acd3b9ec 187int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
40aaae88 188{
acd3b9ec
JH
189 int fd = lock_file(lk, path, flags);
190 if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
e43a6fd3 191 unable_to_lock_index_die(path, errno);
40aaae88
JH
192 return fd;
193}
194
acd3b9ec 195int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
ea3cd5c7
DB
196{
197 int fd, orig_fd;
198
acd3b9ec 199 fd = lock_file(lk, path, flags);
ea3cd5c7 200 if (fd < 0) {
acd3b9ec 201 if (flags & LOCK_DIE_ON_ERROR)
bdfd739d 202 unable_to_lock_index_die(path, errno);
ea3cd5c7
DB
203 return fd;
204 }
205
206 orig_fd = open(path, O_RDONLY);
207 if (orig_fd < 0) {
208 if (errno != ENOENT) {
acd3b9ec 209 if (flags & LOCK_DIE_ON_ERROR)
ea3cd5c7
DB
210 die("cannot open '%s' for copying", path);
211 close(fd);
212 return error("cannot open '%s' for copying", path);
213 }
214 } else if (copy_fd(orig_fd, fd)) {
acd3b9ec 215 if (flags & LOCK_DIE_ON_ERROR)
ea3cd5c7
DB
216 exit(128);
217 close(fd);
218 return -1;
219 }
220 return fd;
221}
222
d6cf61bf
BC
223int close_lock_file(struct lock_file *lk)
224{
225 int fd = lk->fd;
226 lk->fd = -1;
227 return close(fd);
228}
229
021b6e45
JH
230int commit_lock_file(struct lock_file *lk)
231{
232 char result_file[PATH_MAX];
d6cf61bf
BC
233 size_t i;
234 if (lk->fd >= 0 && close_lock_file(lk))
235 return -1;
021b6e45
JH
236 strcpy(result_file, lk->filename);
237 i = strlen(result_file) - 5; /* .lock */
238 result_file[i] = 0;
d6cf61bf
BC
239 if (rename(lk->filename, result_file))
240 return -1;
021b6e45 241 lk->filename[0] = 0;
d6cf61bf 242 return 0;
021b6e45
JH
243}
244
30ca07a2
JH
245int hold_locked_index(struct lock_file *lk, int die_on_error)
246{
acd3b9ec
JH
247 return hold_lock_file_for_update(lk, get_index_file(),
248 die_on_error
249 ? LOCK_DIE_ON_ERROR
250 : 0);
30ca07a2
JH
251}
252
5e7f56ac
JH
253void set_alternate_index_output(const char *name)
254{
255 alternate_index_output = name;
256}
257
30ca07a2
JH
258int commit_locked_index(struct lock_file *lk)
259{
5e7f56ac 260 if (alternate_index_output) {
d6cf61bf
BC
261 if (lk->fd >= 0 && close_lock_file(lk))
262 return -1;
263 if (rename(lk->filename, alternate_index_output))
264 return -1;
30ca07a2 265 lk->filename[0] = 0;
d6cf61bf 266 return 0;
30ca07a2
JH
267 }
268 else
269 return commit_lock_file(lk);
270}
271
021b6e45
JH
272void rollback_lock_file(struct lock_file *lk)
273{
4723ee99 274 if (lk->filename[0]) {
d6cf61bf
BC
275 if (lk->fd >= 0)
276 close(lk->fd);
691f1a28 277 unlink_or_warn(lk->filename);
4723ee99 278 }
021b6e45
JH
279 lk->filename[0] = 0;
280}