Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 280 lines (249 sloc) 6.389 kb
021b6e45 » Junio C Hamano
2006-06-06 Make index file locking code reusable to others.
1 /*
2 * Copyright (c) 2005, Junio C Hamano
3 */
4 #include "cache.h"
4a16d072 » peff
2009-01-22 chain kill signals for cleanup functions
5 #include "sigchain.h"
021b6e45 » Junio C Hamano
2006-06-06 Make index file locking code reusable to others.
6
7 static struct lock_file *lock_file_list;
5e7f56ac » Junio C Hamano
2007-03-31 git-read-tree --index-output=<file>
8 static const char *alternate_index_output;
021b6e45 » Junio C Hamano
2006-06-06 Make index file locking code reusable to others.
9
10 static void remove_lock_file(void)
11 {
5e635e39 » Junio C Hamano
2007-04-21 lockfile: record the primary process.
12 pid_t me = getpid();
13
021b6e45 » Junio C Hamano
2006-06-06 Make index file locking code reusable to others.
14 while (lock_file_list) {
5e635e39 » Junio C Hamano
2007-04-21 lockfile: record the primary process.
15 if (lock_file_list->owner == me &&
4723ee99 » dscho
2007-11-13 Close files opened by lock_file() before unlinking.
16 lock_file_list->filename[0]) {
d6cf61bf » Brandon Casey
2008-01-16 close_lock_file(): new function in the lockfile API
17 if (lock_file_list->fd >= 0)
18 close(lock_file_list->fd);
691f1a28 » raalkml
2009-04-29 replace direct calls to unlink(2) with unlink_or_warn
19 unlink_or_warn(lock_file_list->filename);
4723ee99 » dscho
2007-11-13 Close files opened by lock_file() before unlinking.
20 }
021b6e45 » Junio C Hamano
2006-06-06 Make index file locking code reusable to others.
21 lock_file_list = lock_file_list->next;
22 }
23 }
24
25 static void remove_lock_file_on_signal(int signo)
26 {
27 remove_lock_file();
4a16d072 » peff
2009-01-22 chain kill signals for cleanup functions
28 sigchain_pop(signo);
021b6e45 » Junio C Hamano
2006-06-06 Make index file locking code reusable to others.
29 raise(signo);
30 }
31
5d5a7a67 » Bradford C. Smith
2007-07-26 fully resolve symlinks when creating lockfiles
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 */
38 static 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
80 static 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 » sprohaska
2007-11-25 Use is_absolute_path() in diff-lib.c, lockfile.c, setup.c, trace.c
99 if (is_absolute_path(link)) {
5d5a7a67 » Bradford C. Smith
2007-07-26 fully resolve symlinks when creating lockfiles
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 » felipec
2009-05-01 Fix a bunch of pointer declarations (codestyle)
112 char *r = (char *)last_path_elm(p);
5d5a7a67 » Bradford C. Smith
2007-07-26 fully resolve symlinks when creating lockfiles
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 » gitster
2008-10-17 Enhance hold_lock_file_for_{update,append}() API
125 static int lock_file(struct lock_file *lk, const char *path, int flags)
021b6e45 » Junio C Hamano
2006-06-06 Make index file locking code reusable to others.
126 {
acd3b9ec » gitster
2008-10-17 Enhance hold_lock_file_for_{update,append}() API
127 if (strlen(path) >= sizeof(lk->filename))
128 return -1;
5d5a7a67 » Bradford C. Smith
2007-07-26 fully resolve symlinks when creating lockfiles
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 » gitster
2008-10-17 Enhance hold_lock_file_for_{update,append}() API
134 if (!(flags & LOCK_NODEREF))
135 resolve_symlink(lk->filename, sizeof(lk->filename)-5);
5d5a7a67 » Bradford C. Smith
2007-07-26 fully resolve symlinks when creating lockfiles
136 strcat(lk->filename, ".lock");
4723ee99 » dscho
2007-11-13 Close files opened by lock_file() before unlinking.
137 lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
138 if (0 <= lk->fd) {
9a4cbdca » Sven Verdoolaege
2007-07-13 lockfile.c: schedule remove_lock_file only once.
139 if (!lock_file_list) {
57b235a4 » peff
2009-01-22 refactor signal handling for cleanup functions
140 sigchain_push_common(remove_lock_file_on_signal);
9a4cbdca » Sven Verdoolaege
2007-07-13 lockfile.c: schedule remove_lock_file only once.
141 atexit(remove_lock_file);
142 }
5e635e39 » Junio C Hamano
2007-04-21 lockfile: record the primary process.
143 lk->owner = getpid();
1084b845 » Junio C Hamano
2007-01-02 Fix infinite loop when deleting multiple packed refs.
144 if (!lk->on_list) {
138086a7 » Junio C Hamano
2006-06-09 shared repository - add a few missing calls to adjust_shared_perm().
145 lk->next = lock_file_list;
146 lock_file_list = lk;
1084b845 » Junio C Hamano
2007-01-02 Fix infinite loop when deleting multiple packed refs.
147 lk->on_list = 1;
148 }
138086a7 » Junio C Hamano
2006-06-09 shared repository - add a few missing calls to adjust_shared_perm().
149 if (adjust_shared_perm(lk->filename))
150 return error("cannot fix permission bits on %s",
151 lk->filename);
021b6e45 » Junio C Hamano
2006-06-06 Make index file locking code reusable to others.
152 }
1084b845 » Junio C Hamano
2007-01-02 Fix infinite loop when deleting multiple packed refs.
153 else
154 lk->filename[0] = 0;
4723ee99 » dscho
2007-11-13 Close files opened by lock_file() before unlinking.
155 return lk->fd;
021b6e45 » Junio C Hamano
2006-06-06 Make index file locking code reusable to others.
156 }
157
1b018fd9 » vmiklos
2009-09-27 git branch -D: give a better error message when lockfile creation fails
158 static char *unable_to_lock_message(const char *path, int err)
e43a6fd3 » moy
2009-02-19 More friendly message when locking the index fails.
159 {
1b018fd9 » vmiklos
2009-09-27 git branch -D: give a better error message when lockfile creation fails
160 struct strbuf buf = STRBUF_INIT;
161
bdfd739d » johnflux
2009-03-04 Make the 'lock file' exists error more informative
162 if (err == EEXIST) {
1b018fd9 » vmiklos
2009-09-27 git branch -D: give a better error message when lockfile creation fails
163 strbuf_addf(&buf, "Unable to create '%s.lock': %s.\n\n"
e43a6fd3 » moy
2009-02-19 More friendly message when locking the index fails.
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 » carlosmn
2011-03-17 Name make_*_path functions more accurately
167 absolute_path(path), strerror(err));
1b018fd9 » vmiklos
2009-09-27 git branch -D: give a better error message when lockfile creation fails
168 } else
a8c37a0e » moy
2010-01-07 lockfile: show absolute filename in unable_to_lock_message
169 strbuf_addf(&buf, "Unable to create '%s.lock': %s",
e2a57aac » carlosmn
2011-03-17 Name make_*_path functions more accurately
170 absolute_path(path), strerror(err));
1b018fd9 » vmiklos
2009-09-27 git branch -D: give a better error message when lockfile creation fails
171 return strbuf_detach(&buf, NULL);
172 }
173
174 int 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
182 NORETURN void unable_to_lock_index_die(const char *path, int err)
183 {
184 die("%s", unable_to_lock_message(path, err));
e43a6fd3 » moy
2009-02-19 More friendly message when locking the index fails.
185 }
186
acd3b9ec » gitster
2008-10-17 Enhance hold_lock_file_for_{update,append}() API
187 int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
40aaae88 » Junio C Hamano
2006-08-12 Better error message when we are unable to lock the index file
188 {
acd3b9ec » gitster
2008-10-17 Enhance hold_lock_file_for_{update,append}() API
189 int fd = lock_file(lk, path, flags);
190 if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
e43a6fd3 » moy
2009-02-19 More friendly message when locking the index fails.
191 unable_to_lock_index_die(path, errno);
40aaae88 » Junio C Hamano
2006-08-12 Better error message when we are unable to lock the index file
192 return fd;
193 }
194
acd3b9ec » gitster
2008-10-17 Enhance hold_lock_file_for_{update,append}() API
195 int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
ea3cd5c7 » Daniel Barkalow
2008-04-17 Add a lockfile function to append to a file
196 {
197 int fd, orig_fd;
198
acd3b9ec » gitster
2008-10-17 Enhance hold_lock_file_for_{update,append}() API
199 fd = lock_file(lk, path, flags);
ea3cd5c7 » Daniel Barkalow
2008-04-17 Add a lockfile function to append to a file
200 if (fd < 0) {
acd3b9ec » gitster
2008-10-17 Enhance hold_lock_file_for_{update,append}() API
201 if (flags & LOCK_DIE_ON_ERROR)
bdfd739d » johnflux
2009-03-04 Make the 'lock file' exists error more informative
202 unable_to_lock_index_die(path, errno);
ea3cd5c7 » Daniel Barkalow
2008-04-17 Add a lockfile function to append to a file
203 return fd;
204 }
205
206 orig_fd = open(path, O_RDONLY);
207 if (orig_fd < 0) {
208 if (errno != ENOENT) {
acd3b9ec » gitster
2008-10-17 Enhance hold_lock_file_for_{update,append}() API
209 if (flags & LOCK_DIE_ON_ERROR)
ea3cd5c7 » Daniel Barkalow
2008-04-17 Add a lockfile function to append to a file
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 » gitster
2008-10-17 Enhance hold_lock_file_for_{update,append}() API
215 if (flags & LOCK_DIE_ON_ERROR)
ea3cd5c7 » Daniel Barkalow
2008-04-17 Add a lockfile function to append to a file
216 exit(128);
217 close(fd);
218 return -1;
219 }
220 return fd;
221 }
222
d6cf61bf » Brandon Casey
2008-01-16 close_lock_file(): new function in the lockfile API
223 int close_lock_file(struct lock_file *lk)
224 {
225 int fd = lk->fd;
226 lk->fd = -1;
227 return close(fd);
228 }
229
021b6e45 » Junio C Hamano
2006-06-06 Make index file locking code reusable to others.
230 int commit_lock_file(struct lock_file *lk)
231 {
232 char result_file[PATH_MAX];
d6cf61bf » Brandon Casey
2008-01-16 close_lock_file(): new function in the lockfile API
233 size_t i;
234 if (lk->fd >= 0 && close_lock_file(lk))
235 return -1;
021b6e45 » Junio C Hamano
2006-06-06 Make index file locking code reusable to others.
236 strcpy(result_file, lk->filename);
237 i = strlen(result_file) - 5; /* .lock */
238 result_file[i] = 0;
d6cf61bf » Brandon Casey
2008-01-16 close_lock_file(): new function in the lockfile API
239 if (rename(lk->filename, result_file))
240 return -1;
021b6e45 » Junio C Hamano
2006-06-06 Make index file locking code reusable to others.
241 lk->filename[0] = 0;
d6cf61bf » Brandon Casey
2008-01-16 close_lock_file(): new function in the lockfile API
242 return 0;
021b6e45 » Junio C Hamano
2006-06-06 Make index file locking code reusable to others.
243 }
244
30ca07a2 » Junio C Hamano
2007-03-31 _GIT_INDEX_OUTPUT: allow plumbing to output to an alternative index f…
245 int hold_locked_index(struct lock_file *lk, int die_on_error)
246 {
acd3b9ec » gitster
2008-10-17 Enhance hold_lock_file_for_{update,append}() API
247 return hold_lock_file_for_update(lk, get_index_file(),
248 die_on_error
249 ? LOCK_DIE_ON_ERROR
250 : 0);
30ca07a2 » Junio C Hamano
2007-03-31 _GIT_INDEX_OUTPUT: allow plumbing to output to an alternative index f…
251 }
252
5e7f56ac » Junio C Hamano
2007-03-31 git-read-tree --index-output=<file>
253 void set_alternate_index_output(const char *name)
254 {
255 alternate_index_output = name;
256 }
257
30ca07a2 » Junio C Hamano
2007-03-31 _GIT_INDEX_OUTPUT: allow plumbing to output to an alternative index f…
258 int commit_locked_index(struct lock_file *lk)
259 {
5e7f56ac » Junio C Hamano
2007-03-31 git-read-tree --index-output=<file>
260 if (alternate_index_output) {
d6cf61bf » Brandon Casey
2008-01-16 close_lock_file(): new function in the lockfile API
261 if (lk->fd >= 0 && close_lock_file(lk))
262 return -1;
263 if (rename(lk->filename, alternate_index_output))
264 return -1;
30ca07a2 » Junio C Hamano
2007-03-31 _GIT_INDEX_OUTPUT: allow plumbing to output to an alternative index f…
265 lk->filename[0] = 0;
d6cf61bf » Brandon Casey
2008-01-16 close_lock_file(): new function in the lockfile API
266 return 0;
30ca07a2 » Junio C Hamano
2007-03-31 _GIT_INDEX_OUTPUT: allow plumbing to output to an alternative index f…
267 }
268 else
269 return commit_lock_file(lk);
270 }
271
021b6e45 » Junio C Hamano
2006-06-06 Make index file locking code reusable to others.
272 void rollback_lock_file(struct lock_file *lk)
273 {
4723ee99 » dscho
2007-11-13 Close files opened by lock_file() before unlinking.
274 if (lk->filename[0]) {
d6cf61bf » Brandon Casey
2008-01-16 close_lock_file(): new function in the lockfile API
275 if (lk->fd >= 0)
276 close(lk->fd);
691f1a28 » raalkml
2009-04-29 replace direct calls to unlink(2) with unlink_or_warn
277 unlink_or_warn(lk->filename);
4723ee99 » dscho
2007-11-13 Close files opened by lock_file() before unlinking.
278 }
021b6e45 » Junio C Hamano
2006-06-06 Make index file locking code reusable to others.
279 lk->filename[0] = 0;
280 }
Something went wrong with that request. Please try again.