]>
git.ipfire.org Git - thirdparty/git.git/blob - lockfile.c
2 * Copyright (c) 2005, Junio C Hamano
5 #include "git-compat-util.h"
11 * path = absolute or relative path name
13 * Remove the last path name element from path (leaving the preceding
14 * "/", if any). If path is empty or the root directory ("/"), set
15 * path to the empty string.
17 static void trim_last_path_component(struct strbuf
*path
)
21 /* back up past trailing slashes, if any */
22 while (i
&& path
->buf
[i
- 1] == '/')
26 * then go backwards until a slash, or the beginning of the
29 while (i
&& path
->buf
[i
- 1] != '/')
32 strbuf_setlen(path
, i
);
36 /* We allow "recursive" symbolic links. Only within reason, though */
40 * path contains a path that might be a symlink.
42 * If path is a symlink, attempt to overwrite it with a path to the
43 * real file or directory (which may or may not exist), following a
44 * chain of symlinks if necessary. Otherwise, leave path unmodified.
46 * This is a best-effort routine. If an error occurs, path will
47 * either be left unmodified or will name a different symlink in a
48 * symlink chain that started with the original path.
50 static void resolve_symlink(struct strbuf
*path
)
53 static struct strbuf link
= STRBUF_INIT
;
56 if (strbuf_readlink(&link
, path
->buf
, path
->len
) < 0)
59 if (is_absolute_path(link
.buf
))
60 /* absolute path simply replaces p */
64 * link is a relative path, so replace the
65 * last element of p with it.
67 trim_last_path_component(path
);
69 strbuf_addbuf(path
, &link
);
74 /* Make sure errno contains a meaningful value on error */
75 static int lock_file(struct lock_file
*lk
, const char *path
, int flags
,
78 struct strbuf filename
= STRBUF_INIT
;
80 strbuf_addstr(&filename
, path
);
81 if (!(flags
& LOCK_NO_DEREF
))
82 resolve_symlink(&filename
);
84 strbuf_addstr(&filename
, LOCK_SUFFIX
);
85 lk
->tempfile
= create_tempfile_mode(filename
.buf
, mode
);
86 strbuf_release(&filename
);
87 return lk
->tempfile
? lk
->tempfile
->fd
: -1;
91 * Constants defining the gaps between attempts to lock a file. The
92 * first backoff period is approximately INITIAL_BACKOFF_MS
93 * milliseconds. The longest backoff period is approximately
94 * (BACKOFF_MAX_MULTIPLIER * INITIAL_BACKOFF_MS) milliseconds.
96 #define INITIAL_BACKOFF_MS 1L
97 #define BACKOFF_MAX_MULTIPLIER 1000
100 * Try locking path, retrying with quadratic backoff for at least
101 * timeout_ms milliseconds. If timeout_ms is 0, try locking the file
102 * exactly once. If timeout_ms is -1, try indefinitely.
104 static int lock_file_timeout(struct lock_file
*lk
, const char *path
,
105 int flags
, long timeout_ms
, int mode
)
109 long remaining_ms
= 0;
110 static int random_initialized
= 0;
113 return lock_file(lk
, path
, flags
, mode
);
115 if (!random_initialized
) {
116 srand((unsigned int)getpid());
117 random_initialized
= 1;
121 remaining_ms
= timeout_ms
;
124 long backoff_ms
, wait_ms
;
127 fd
= lock_file(lk
, path
, flags
, mode
);
130 return fd
; /* success */
131 else if (errno
!= EEXIST
)
132 return -1; /* failure other than lock held */
133 else if (timeout_ms
> 0 && remaining_ms
<= 0)
134 return -1; /* failure due to timeout */
136 backoff_ms
= multiplier
* INITIAL_BACKOFF_MS
;
137 /* back off for between 0.75*backoff_ms and 1.25*backoff_ms */
138 wait_ms
= (750 + rand() % 500) * backoff_ms
/ 1000;
139 sleep_millisec(wait_ms
);
140 remaining_ms
-= wait_ms
;
142 /* Recursion: (n+1)^2 = n^2 + 2n + 1 */
143 multiplier
+= 2*n
+ 1;
144 if (multiplier
> BACKOFF_MAX_MULTIPLIER
)
145 multiplier
= BACKOFF_MAX_MULTIPLIER
;
151 void unable_to_lock_message(const char *path
, int err
, struct strbuf
*buf
)
154 strbuf_addf(buf
, _("Unable to create '%s.lock': %s.\n\n"
155 "Another git process seems to be running in this repository, e.g.\n"
156 "an editor opened by 'git commit'. Please make sure all processes\n"
157 "are terminated then try again. If it still fails, a git process\n"
158 "may have crashed in this repository earlier:\n"
159 "remove the file manually to continue."),
160 absolute_path(path
), strerror(err
));
162 strbuf_addf(buf
, _("Unable to create '%s.lock': %s"),
163 absolute_path(path
), strerror(err
));
166 NORETURN
void unable_to_lock_die(const char *path
, int err
)
168 struct strbuf buf
= STRBUF_INIT
;
170 unable_to_lock_message(path
, err
, &buf
);
174 /* This should return a meaningful errno on failure */
175 int hold_lock_file_for_update_timeout_mode(struct lock_file
*lk
,
176 const char *path
, int flags
,
177 long timeout_ms
, int mode
)
179 int fd
= lock_file_timeout(lk
, path
, flags
, timeout_ms
, mode
);
181 if (flags
& LOCK_DIE_ON_ERROR
)
182 unable_to_lock_die(path
, errno
);
183 if (flags
& LOCK_REPORT_ON_ERROR
) {
184 struct strbuf buf
= STRBUF_INIT
;
185 unable_to_lock_message(path
, errno
, &buf
);
186 error("%s", buf
.buf
);
187 strbuf_release(&buf
);
193 char *get_locked_file_path(struct lock_file
*lk
)
195 struct strbuf ret
= STRBUF_INIT
;
197 strbuf_addstr(&ret
, get_tempfile_path(lk
->tempfile
));
198 if (ret
.len
<= LOCK_SUFFIX_LEN
||
199 strcmp(ret
.buf
+ ret
.len
- LOCK_SUFFIX_LEN
, LOCK_SUFFIX
))
200 BUG("get_locked_file_path() called for malformed lock object");
201 /* remove ".lock": */
202 strbuf_setlen(&ret
, ret
.len
- LOCK_SUFFIX_LEN
);
203 return strbuf_detach(&ret
, NULL
);
206 int commit_lock_file(struct lock_file
*lk
)
208 char *result_path
= get_locked_file_path(lk
);
210 if (commit_lock_file_to(lk
, result_path
)) {
211 int save_errno
= errno
;