1/* 2 * Copyright (c) 2005, Junio C Hamano 3 */ 4 5#include "cache.h" 6#include "lockfile.h" 7 8/* 9 * path = absolute or relative path name 10 * 11 * Remove the last path name element from path (leaving the preceding 12 * "/", if any). If path is empty or the root directory ("/"), set 13 * path to the empty string. 14 */ 15static void trim_last_path_component(struct strbuf *path) 16{ 17 int i = path->len; 18 19 /* back up past trailing slashes, if any */ 20 while (i && path->buf[i - 1] == '/') 21 i--; 22 23 /* 24 * then go backwards until a slash, or the beginning of the 25 * string 26 */ 27 while (i && path->buf[i - 1] != '/') 28 i--; 29 30 strbuf_setlen(path, i); 31} 32 33 34/* We allow "recursive" symbolic links. Only within reason, though */ 35#define MAXDEPTH 5 36 37/* 38 * path contains a path that might be a symlink. 39 * 40 * If path is a symlink, attempt to overwrite it with a path to the 41 * real file or directory (which may or may not exist), following a 42 * chain of symlinks if necessary. Otherwise, leave path unmodified. 43 * 44 * This is a best-effort routine. If an error occurs, path will 45 * either be left unmodified or will name a different symlink in a 46 * symlink chain that started with the original path. 47 */ 48static void resolve_symlink(struct strbuf *path) 49{ 50 int depth = MAXDEPTH; 51 static struct strbuf link = STRBUF_INIT; 52 53 while (depth--) { 54 if (strbuf_readlink(&link, path->buf, path->len) < 0) 55 break; 56 57 if (is_absolute_path(link.buf)) 58 /* absolute path simply replaces p */ 59 strbuf_reset(path); 60 else 61 /* 62 * link is a relative path, so replace the 63 * last element of p with it. 64 */ 65 trim_last_path_component(path); 66 67 strbuf_addbuf(path, &link); 68 } 69 strbuf_reset(&link); 70} 71 72/* Make sure errno contains a meaningful value on error */ 73static int lock_file(struct lock_file *lk, const char *path, int flags) 74{ 75 int fd; 76 struct strbuf filename = STRBUF_INIT; 77 78 strbuf_addstr(&filename, path); 79 if (!(flags & LOCK_NO_DEREF)) 80 resolve_symlink(&filename); 81 82 strbuf_addstr(&filename, LOCK_SUFFIX); 83 fd = create_tempfile(&lk->tempfile, filename.buf); 84 strbuf_release(&filename); 85 return fd; 86} 87 88/* 89 * Constants defining the gaps between attempts to lock a file. The 90 * first backoff period is approximately INITIAL_BACKOFF_MS 91 * milliseconds. The longest backoff period is approximately 92 * (BACKOFF_MAX_MULTIPLIER * INITIAL_BACKOFF_MS) milliseconds. 93 */ 94#define INITIAL_BACKOFF_MS 1L 95#define BACKOFF_MAX_MULTIPLIER 1000 96 97/* 98 * Try locking path, retrying with quadratic backoff for at least 99 * timeout_ms milliseconds. If timeout_ms is 0, try locking the file 100 * exactly once. If timeout_ms is -1, try indefinitely. 101 */ 102static int lock_file_timeout(struct lock_file *lk, const char *path, 103 int flags, long timeout_ms) 104{ 105 int n = 1; 106 int multiplier = 1; 107 long remaining_ms = 0; 108 static int random_initialized = 0; 109 110 if (timeout_ms == 0) 111 return lock_file(lk, path, flags); 112 113 if (!random_initialized) { 114 srand((unsigned int)getpid()); 115 random_initialized = 1; 116 } 117 118 if (timeout_ms > 0) 119 remaining_ms = timeout_ms; 120 121 while (1) { 122 long backoff_ms, wait_ms; 123 int fd; 124 125 fd = lock_file(lk, path, flags); 126 127 if (fd >= 0) 128 return fd; /* success */ 129 else if (errno != EEXIST) 130 return -1; /* failure other than lock held */ 131 else if (timeout_ms > 0 && remaining_ms <= 0) 132 return -1; /* failure due to timeout */ 133 134 backoff_ms = multiplier * INITIAL_BACKOFF_MS; 135 /* back off for between 0.75*backoff_ms and 1.25*backoff_ms */ 136 wait_ms = (750 + rand() % 500) * backoff_ms / 1000; 137 sleep_millisec(wait_ms); 138 remaining_ms -= wait_ms; 139 140 /* Recursion: (n+1)^2 = n^2 + 2n + 1 */ 141 multiplier += 2*n + 1; 142 if (multiplier > BACKOFF_MAX_MULTIPLIER) 143 multiplier = BACKOFF_MAX_MULTIPLIER; 144 else 145 n++; 146 } 147} 148 149void unable_to_lock_message(const char *path, int err, struct strbuf *buf) 150{ 151 if (err == EEXIST) { 152 strbuf_addf(buf, "Unable to create '%s.lock': %s.\n\n" 153 "If no other git process is currently running, this probably means a\n" 154 "git process crashed in this repository earlier. Make sure no other git\n" 155 "process is running and remove the file manually to continue.", 156 absolute_path(path), strerror(err)); 157 } else 158 strbuf_addf(buf, "Unable to create '%s.lock': %s", 159 absolute_path(path), strerror(err)); 160} 161 162NORETURN void unable_to_lock_die(const char *path, int err) 163{ 164 struct strbuf buf = STRBUF_INIT; 165 166 unable_to_lock_message(path, err, &buf); 167 die("%s", buf.buf); 168} 169 170/* This should return a meaningful errno on failure */ 171int hold_lock_file_for_update_timeout(struct lock_file *lk, const char *path, 172 int flags, long timeout_ms) 173{ 174 int fd = lock_file_timeout(lk, path, flags, timeout_ms); 175 if (fd < 0 && (flags & LOCK_DIE_ON_ERROR)) 176 unable_to_lock_die(path, errno); 177 return fd; 178} 179 180char *get_locked_file_path(struct lock_file *lk) 181{ 182 struct strbuf ret = STRBUF_INIT; 183 184 strbuf_addstr(&ret, get_tempfile_path(&lk->tempfile)); 185 if (ret.len <= LOCK_SUFFIX_LEN || 186 strcmp(ret.buf + ret.len - LOCK_SUFFIX_LEN, LOCK_SUFFIX)) 187 die("BUG: get_locked_file_path() called for malformed lock object"); 188 /* remove ".lock": */ 189 strbuf_setlen(&ret, ret.len - LOCK_SUFFIX_LEN); 190 return strbuf_detach(&ret, NULL); 191} 192 193int commit_lock_file(struct lock_file *lk) 194{ 195 char *result_path = get_locked_file_path(lk); 196 197 if (commit_lock_file_to(lk, result_path)) { 198 int save_errno = errno; 199 free(result_path); 200 errno = save_errno; 201 return -1; 202 } 203 free(result_path); 204 return 0; 205}