]> git.ipfire.org Git - thirdparty/git.git/blame - lockfile.c
Merge branch 'maint-1.6.0' into maint-1.6.1
[thirdparty/git.git] / lockfile.c
CommitLineData
021b6e45
JH
1/*
2 * Copyright (c) 2005, Junio C Hamano
3 */
021b6e45
JH
4#include "cache.h"
5
6static struct lock_file *lock_file_list;
5e7f56ac 7static const char *alternate_index_output;
021b6e45
JH
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);
021b6e45 18 unlink(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();
a1292939 27 signal(signo, SIG_DFL);
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 */
111 char *r = (char*)last_path_elm(p);
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{
acd3b9ec
JH
126 if (strlen(path) >= sizeof(lk->filename))
127 return -1;
5d5a7a67
BS
128 strcpy(lk->filename, path);
129 /*
130 * subtract 5 from size to make sure there's room for adding
131 * ".lock" for the lock file name
132 */
acd3b9ec
JH
133 if (!(flags & LOCK_NODEREF))
134 resolve_symlink(lk->filename, sizeof(lk->filename)-5);
5d5a7a67 135 strcat(lk->filename, ".lock");
4723ee99
JS
136 lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
137 if (0 <= lk->fd) {
9a4cbdca
SV
138 if (!lock_file_list) {
139 signal(SIGINT, remove_lock_file_on_signal);
ad5fa3cc
PB
140 signal(SIGHUP, remove_lock_file_on_signal);
141 signal(SIGTERM, remove_lock_file_on_signal);
142 signal(SIGQUIT, remove_lock_file_on_signal);
0693f9dd 143 signal(SIGPIPE, remove_lock_file_on_signal);
9a4cbdca
SV
144 atexit(remove_lock_file);
145 }
5e635e39 146 lk->owner = getpid();
1084b845 147 if (!lk->on_list) {
138086a7
JH
148 lk->next = lock_file_list;
149 lock_file_list = lk;
1084b845
JH
150 lk->on_list = 1;
151 }
138086a7
JH
152 if (adjust_shared_perm(lk->filename))
153 return error("cannot fix permission bits on %s",
154 lk->filename);
021b6e45 155 }
1084b845
JH
156 else
157 lk->filename[0] = 0;
4723ee99 158 return lk->fd;
021b6e45
JH
159}
160
e43a6fd3
MM
161
162NORETURN void unable_to_lock_index_die(const char *path, int err)
163{
164 if (errno == EEXIST) {
165 die("Unable to create '%s.lock': %s.\n\n"
166 "If no other git process is currently running, this probably means a\n"
167 "git process crashed in this repository earlier. Make sure no other git\n"
168 "process is running and remove the file manually to continue.",
169 path, strerror(err));
170 } else {
171 die("Unable to create '%s.lock': %s", path, strerror(err));
172 }
173}
174
acd3b9ec 175int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
40aaae88 176{
acd3b9ec
JH
177 int fd = lock_file(lk, path, flags);
178 if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
e43a6fd3 179 unable_to_lock_index_die(path, errno);
40aaae88
JH
180 return fd;
181}
182
acd3b9ec 183int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
ea3cd5c7
DB
184{
185 int fd, orig_fd;
186
acd3b9ec 187 fd = lock_file(lk, path, flags);
ea3cd5c7 188 if (fd < 0) {
acd3b9ec 189 if (flags & LOCK_DIE_ON_ERROR)
ea3cd5c7
DB
190 die("unable to create '%s.lock': %s", path, strerror(errno));
191 return fd;
192 }
193
194 orig_fd = open(path, O_RDONLY);
195 if (orig_fd < 0) {
196 if (errno != ENOENT) {
acd3b9ec 197 if (flags & LOCK_DIE_ON_ERROR)
ea3cd5c7
DB
198 die("cannot open '%s' for copying", path);
199 close(fd);
200 return error("cannot open '%s' for copying", path);
201 }
202 } else if (copy_fd(orig_fd, fd)) {
acd3b9ec 203 if (flags & LOCK_DIE_ON_ERROR)
ea3cd5c7
DB
204 exit(128);
205 close(fd);
206 return -1;
207 }
208 return fd;
209}
210
d6cf61bf
BC
211int close_lock_file(struct lock_file *lk)
212{
213 int fd = lk->fd;
214 lk->fd = -1;
215 return close(fd);
216}
217
021b6e45
JH
218int commit_lock_file(struct lock_file *lk)
219{
220 char result_file[PATH_MAX];
d6cf61bf
BC
221 size_t i;
222 if (lk->fd >= 0 && close_lock_file(lk))
223 return -1;
021b6e45
JH
224 strcpy(result_file, lk->filename);
225 i = strlen(result_file) - 5; /* .lock */
226 result_file[i] = 0;
d6cf61bf
BC
227 if (rename(lk->filename, result_file))
228 return -1;
021b6e45 229 lk->filename[0] = 0;
d6cf61bf 230 return 0;
021b6e45
JH
231}
232
30ca07a2
JH
233int hold_locked_index(struct lock_file *lk, int die_on_error)
234{
acd3b9ec
JH
235 return hold_lock_file_for_update(lk, get_index_file(),
236 die_on_error
237 ? LOCK_DIE_ON_ERROR
238 : 0);
30ca07a2
JH
239}
240
5e7f56ac
JH
241void set_alternate_index_output(const char *name)
242{
243 alternate_index_output = name;
244}
245
30ca07a2
JH
246int commit_locked_index(struct lock_file *lk)
247{
5e7f56ac 248 if (alternate_index_output) {
d6cf61bf
BC
249 if (lk->fd >= 0 && close_lock_file(lk))
250 return -1;
251 if (rename(lk->filename, alternate_index_output))
252 return -1;
30ca07a2 253 lk->filename[0] = 0;
d6cf61bf 254 return 0;
30ca07a2
JH
255 }
256 else
257 return commit_lock_file(lk);
258}
259
021b6e45
JH
260void rollback_lock_file(struct lock_file *lk)
261{
4723ee99 262 if (lk->filename[0]) {
d6cf61bf
BC
263 if (lk->fd >= 0)
264 close(lk->fd);
021b6e45 265 unlink(lk->filename);
4723ee99 266 }
021b6e45
JH
267 lk->filename[0] = 0;
268}