🌐 AI搜索 & 代理 主页
blob: b0d74cdddee2407de590cb9f725e8e24093d9d35 [file] [log] [blame]
Junio C Hamano021b6e42006-06-06 19:51:491/*
2 * Copyright (c) 2005, Junio C Hamano
3 */
Junio C Hamano021b6e42006-06-06 19:51:494#include "cache.h"
Jeff King4a16d072009-01-22 06:02:355#include "sigchain.h"
Junio C Hamano021b6e42006-06-06 19:51:496
7static struct lock_file *lock_file_list;
Junio C Hamano5e7f56a2007-04-01 06:27:418static const char *alternate_index_output;
Junio C Hamano021b6e42006-06-06 19:51:499
10static void remove_lock_file(void)
11{
Junio C Hamano5e635e32007-04-21 10:11:1012 pid_t me = getpid();
13
Junio C Hamano021b6e42006-06-06 19:51:4914 while (lock_file_list) {
Junio C Hamano5e635e32007-04-21 10:11:1015 if (lock_file_list->owner == me &&
Johannes Schindelin4723ee92007-11-13 20:05:0316 lock_file_list->filename[0]) {
Brandon Caseyd6cf61b2008-01-16 19:05:3217 if (lock_file_list->fd >= 0)
18 close(lock_file_list->fd);
Alex Riesen691f1a22009-04-29 21:22:5619 unlink_or_warn(lock_file_list->filename);
Johannes Schindelin4723ee92007-11-13 20:05:0320 }
Junio C Hamano021b6e42006-06-06 19:51:4921 lock_file_list = lock_file_list->next;
22 }
23}
24
25static void remove_lock_file_on_signal(int signo)
26{
27 remove_lock_file();
Jeff King4a16d072009-01-22 06:02:3528 sigchain_pop(signo);
Junio C Hamano021b6e42006-06-06 19:51:4929 raise(signo);
30}
31
Bradford C. Smith5d5a7a62007-07-26 17:34:1432/*
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
Steffen Prohaskaecf48312007-11-25 22:29:0399 if (is_absolute_path(link)) {
Bradford C. Smith5d5a7a62007-07-26 17:34:14100 /* 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 */
Felipe Contreras4b25d092009-05-01 09:06:36112 char *r = (char *)last_path_elm(p);
Bradford C. Smith5d5a7a62007-07-26 17:34:14113 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
Junio C Hamanoacd3b9e2008-10-17 22:44:39125static int lock_file(struct lock_file *lk, const char *path, int flags)
Junio C Hamano021b6e42006-06-06 19:51:49126{
Junio C Hamanoacd3b9e2008-10-17 22:44:39127 if (strlen(path) >= sizeof(lk->filename))
128 return -1;
Bradford C. Smith5d5a7a62007-07-26 17:34:14129 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 */
Junio C Hamanoacd3b9e2008-10-17 22:44:39134 if (!(flags & LOCK_NODEREF))
135 resolve_symlink(lk->filename, sizeof(lk->filename)-5);
Bradford C. Smith5d5a7a62007-07-26 17:34:14136 strcat(lk->filename, ".lock");
Johannes Schindelin4723ee92007-11-13 20:05:03137 lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
138 if (0 <= lk->fd) {
Sven Verdoolaege9a4cbdc2007-07-13 14:14:50139 if (!lock_file_list) {
Jeff King57b235a2009-01-22 06:03:08140 sigchain_push_common(remove_lock_file_on_signal);
Sven Verdoolaege9a4cbdc2007-07-13 14:14:50141 atexit(remove_lock_file);
142 }
Junio C Hamano5e635e32007-04-21 10:11:10143 lk->owner = getpid();
Junio C Hamano1084b842007-01-02 19:19:05144 if (!lk->on_list) {
Junio C Hamano138086a2006-06-10 05:07:23145 lk->next = lock_file_list;
146 lock_file_list = lk;
Junio C Hamano1084b842007-01-02 19:19:05147 lk->on_list = 1;
148 }
Junio C Hamano138086a2006-06-10 05:07:23149 if (adjust_shared_perm(lk->filename))
150 return error("cannot fix permission bits on %s",
151 lk->filename);
Junio C Hamano021b6e42006-06-06 19:51:49152 }
Junio C Hamano1084b842007-01-02 19:19:05153 else
154 lk->filename[0] = 0;
Johannes Schindelin4723ee92007-11-13 20:05:03155 return lk->fd;
Junio C Hamano021b6e42006-06-06 19:51:49156}
157
Miklos Vajna1b018fd2009-09-26 23:15:09158static char *unable_to_lock_message(const char *path, int err)
Matthieu Moye43a6fd2009-02-19 12:54:18159{
Miklos Vajna1b018fd2009-09-26 23:15:09160 struct strbuf buf = STRBUF_INIT;
161
John Tapsellbdfd7392009-03-04 15:00:44162 if (err == EEXIST) {
Miklos Vajna1b018fd2009-09-26 23:15:09163 strbuf_addf(&buf, "Unable to create '%s.lock': %s.\n\n"
Matthieu Moye43a6fd2009-02-19 12:54:18164 "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.",
Matthieu Moya8c37a02010-01-07 14:54:10167 make_nonrelative_path(path), strerror(err));
Miklos Vajna1b018fd2009-09-26 23:15:09168 } else
Matthieu Moya8c37a02010-01-07 14:54:10169 strbuf_addf(&buf, "Unable to create '%s.lock': %s",
170 make_nonrelative_path(path), strerror(err));
Miklos Vajna1b018fd2009-09-26 23:15:09171 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));
Matthieu Moye43a6fd2009-02-19 12:54:18185}
186
Junio C Hamanoacd3b9e2008-10-17 22:44:39187int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
Junio C Hamano40aaae82006-08-12 08:03:47188{
Junio C Hamanoacd3b9e2008-10-17 22:44:39189 int fd = lock_file(lk, path, flags);
190 if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
Matthieu Moye43a6fd2009-02-19 12:54:18191 unable_to_lock_index_die(path, errno);
Junio C Hamano40aaae82006-08-12 08:03:47192 return fd;
193}
194
Junio C Hamanoacd3b9e2008-10-17 22:44:39195int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
Daniel Barkalowea3cd5c2008-04-17 23:32:26196{
197 int fd, orig_fd;
198
Junio C Hamanoacd3b9e2008-10-17 22:44:39199 fd = lock_file(lk, path, flags);
Daniel Barkalowea3cd5c2008-04-17 23:32:26200 if (fd < 0) {
Junio C Hamanoacd3b9e2008-10-17 22:44:39201 if (flags & LOCK_DIE_ON_ERROR)
John Tapsellbdfd7392009-03-04 15:00:44202 unable_to_lock_index_die(path, errno);
Daniel Barkalowea3cd5c2008-04-17 23:32:26203 return fd;
204 }
205
206 orig_fd = open(path, O_RDONLY);
207 if (orig_fd < 0) {
208 if (errno != ENOENT) {
Junio C Hamanoacd3b9e2008-10-17 22:44:39209 if (flags & LOCK_DIE_ON_ERROR)
Daniel Barkalowea3cd5c2008-04-17 23:32:26210 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)) {
Junio C Hamanoacd3b9e2008-10-17 22:44:39215 if (flags & LOCK_DIE_ON_ERROR)
Daniel Barkalowea3cd5c2008-04-17 23:32:26216 exit(128);
217 close(fd);
218 return -1;
219 }
220 return fd;
221}
222
Brandon Caseyd6cf61b2008-01-16 19:05:32223int close_lock_file(struct lock_file *lk)
224{
225 int fd = lk->fd;
226 lk->fd = -1;
227 return close(fd);
228}
229
Junio C Hamano021b6e42006-06-06 19:51:49230int commit_lock_file(struct lock_file *lk)
231{
232 char result_file[PATH_MAX];
Brandon Caseyd6cf61b2008-01-16 19:05:32233 size_t i;
234 if (lk->fd >= 0 && close_lock_file(lk))
235 return -1;
Junio C Hamano021b6e42006-06-06 19:51:49236 strcpy(result_file, lk->filename);
237 i = strlen(result_file) - 5; /* .lock */
238 result_file[i] = 0;
Brandon Caseyd6cf61b2008-01-16 19:05:32239 if (rename(lk->filename, result_file))
240 return -1;
Junio C Hamano021b6e42006-06-06 19:51:49241 lk->filename[0] = 0;
Brandon Caseyd6cf61b2008-01-16 19:05:32242 return 0;
Junio C Hamano021b6e42006-06-06 19:51:49243}
244
Junio C Hamano30ca07a2007-04-01 06:09:02245int hold_locked_index(struct lock_file *lk, int die_on_error)
246{
Junio C Hamanoacd3b9e2008-10-17 22:44:39247 return hold_lock_file_for_update(lk, get_index_file(),
248 die_on_error
249 ? LOCK_DIE_ON_ERROR
250 : 0);
Junio C Hamano30ca07a2007-04-01 06:09:02251}
252
Junio C Hamano5e7f56a2007-04-01 06:27:41253void set_alternate_index_output(const char *name)
254{
255 alternate_index_output = name;
256}
257
Junio C Hamano30ca07a2007-04-01 06:09:02258int commit_locked_index(struct lock_file *lk)
259{
Junio C Hamano5e7f56a2007-04-01 06:27:41260 if (alternate_index_output) {
Brandon Caseyd6cf61b2008-01-16 19:05:32261 if (lk->fd >= 0 && close_lock_file(lk))
262 return -1;
263 if (rename(lk->filename, alternate_index_output))
264 return -1;
Junio C Hamano30ca07a2007-04-01 06:09:02265 lk->filename[0] = 0;
Brandon Caseyd6cf61b2008-01-16 19:05:32266 return 0;
Junio C Hamano30ca07a2007-04-01 06:09:02267 }
268 else
269 return commit_lock_file(lk);
270}
271
Junio C Hamano021b6e42006-06-06 19:51:49272void rollback_lock_file(struct lock_file *lk)
273{
Johannes Schindelin4723ee92007-11-13 20:05:03274 if (lk->filename[0]) {
Brandon Caseyd6cf61b2008-01-16 19:05:32275 if (lk->fd >= 0)
276 close(lk->fd);
Alex Riesen691f1a22009-04-29 21:22:56277 unlink_or_warn(lk->filename);
Johannes Schindelin4723ee92007-11-13 20:05:03278 }
Junio C Hamano021b6e42006-06-06 19:51:49279 lk->filename[0] = 0;
280}