1/* 2 * Copyright (c) 2005, Junio C Hamano 3 */ 4#include"cache.h" 5#include"sigchain.h" 6 7/* 8 * File write-locks as used by Git. 9 * 10 * For an overview of how to use the lockfile API, please see 11 * 12 * Documentation/technical/api-lockfile.txt 13 * 14 * This module keeps track of all locked files in lock_file_list for 15 * use at cleanup. This list and the lock_file objects that comprise 16 * it must be kept in self-consistent states at all time, because the 17 * program can be interrupted any time by a signal, in which case the 18 * signal handler will walk through the list attempting to clean up 19 * any open lock files. 20 * 21 * A lockfile is owned by the process that created it. The lock_file 22 * object has an "owner" field that records its owner. This field is 23 * used to prevent a forked process from closing a lockfile created by 24 * its parent. 25 * 26 * The possible states of a lock_file object are as follows: 27 * 28 * - Uninitialized. In this state the object's on_list field must be 29 * zero but the rest of its contents need not be initialized. As 30 * soon as the object is used in any way, it is irrevocably 31 * registered in the lock_file_list, and on_list is set. 32 * 33 * - Locked, lockfile open (after hold_lock_file_for_update(), 34 * hold_lock_file_for_append(), or reopen_lock_file()). In this 35 * state: 36 * - the lockfile exists 37 * - active is set 38 * - filename holds the filename of the lockfile 39 * - fd holds a file descriptor open for writing to the lockfile 40 * - owner holds the PID of the process that locked the file 41 * 42 * - Locked, lockfile closed (after successful close_lock_file()). 43 * Same as the previous state, except that the lockfile is closed 44 * and fd is -1. 45 * 46 * - Unlocked (after commit_lock_file(), rollback_lock_file(), a 47 * failed attempt to lock, or a failed close_lock_file()). In this 48 * state: 49 * - active is unset 50 * - filename is empty (usually, though there are transitory 51 * states in which this condition doesn't hold). Client code should 52 * *not* rely on the filename being empty in this state. 53 * - fd is -1 54 * - the object is left registered in the lock_file_list, and 55 * on_list is set. 56 */ 57 58static struct lock_file *volatile lock_file_list; 59 60static voidremove_lock_file(void) 61{ 62 pid_t me =getpid(); 63 64while(lock_file_list) { 65if(lock_file_list->owner == me) 66rollback_lock_file(lock_file_list); 67 lock_file_list = lock_file_list->next; 68} 69} 70 71static voidremove_lock_file_on_signal(int signo) 72{ 73remove_lock_file(); 74sigchain_pop(signo); 75raise(signo); 76} 77 78/* 79 * p = absolute or relative path name 80 * 81 * Return a pointer into p showing the beginning of the last path name 82 * element. If p is empty or the root directory ("/"), just return p. 83 */ 84static char*last_path_elm(char*p) 85{ 86/* r starts pointing to null at the end of the string */ 87char*r =strchr(p,'\0'); 88 89if(r == p) 90return p;/* just return empty string */ 91 92 r--;/* back up to last non-null character */ 93 94/* back up past trailing slashes, if any */ 95while(r > p && *r =='/') 96 r--; 97 98/* 99 * then go backwards until I hit a slash, or the beginning of 100 * the string 101 */ 102while(r > p && *(r-1) !='/') 103 r--; 104return r; 105} 106 107 108/* We allow "recursive" symbolic links. Only within reason, though */ 109#define MAXDEPTH 5 110 111/* 112 * path contains a path that might be a symlink. 113 * 114 * If path is a symlink, attempt to overwrite it with a path to the 115 * real file or directory (which may or may not exist), following a 116 * chain of symlinks if necessary. Otherwise, leave path unmodified. 117 * 118 * This is a best-effort routine. If an error occurs, path will 119 * either be left unmodified or will name a different symlink in a 120 * symlink chain that started with the original path. 121 */ 122static voidresolve_symlink(struct strbuf *path) 123{ 124int depth = MAXDEPTH; 125static struct strbuf link = STRBUF_INIT; 126 127while(depth--) { 128if(strbuf_readlink(&link, path->buf, path->len) <0) 129break; 130 131if(is_absolute_path(link.buf)) 132/* absolute path simply replaces p */ 133strbuf_reset(path); 134else{ 135/* 136 * link is a relative path, so replace the 137 * last element of p with it. 138 */ 139char*r =last_path_elm(path->buf); 140strbuf_setlen(path, r - path->buf); 141} 142 143strbuf_addbuf(path, &link); 144} 145strbuf_reset(&link); 146} 147 148/* Make sure errno contains a meaningful value on error */ 149static intlock_file(struct lock_file *lk,const char*path,int flags) 150{ 151size_t pathlen =strlen(path); 152 153if(!lock_file_list) { 154/* One-time initialization */ 155sigchain_push_common(remove_lock_file_on_signal); 156atexit(remove_lock_file); 157} 158 159if(lk->active) 160die("BUG: cannot lock_file(\"%s\") using active struct lock_file", 161 path); 162if(!lk->on_list) { 163/* Initialize *lk and add it to lock_file_list: */ 164 lk->fd = -1; 165 lk->active =0; 166 lk->owner =0; 167strbuf_init(&lk->filename, pathlen + LOCK_SUFFIX_LEN); 168 lk->next = lock_file_list; 169 lock_file_list = lk; 170 lk->on_list =1; 171}else if(lk->filename.len) { 172/* This shouldn't happen, but better safe than sorry. */ 173die("BUG: lock_file(\"%s\") called with improperly-reset lock_file object", 174 path); 175} 176 177strbuf_add(&lk->filename, path, pathlen); 178if(!(flags & LOCK_NODEREF)) 179resolve_symlink(&lk->filename); 180strbuf_addstr(&lk->filename, LOCK_SUFFIX); 181 lk->fd =open(lk->filename.buf, O_RDWR | O_CREAT | O_EXCL,0666); 182if(lk->fd <0) { 183strbuf_reset(&lk->filename); 184return-1; 185} 186 lk->owner =getpid(); 187 lk->active =1; 188if(adjust_shared_perm(lk->filename.buf)) { 189int save_errno = errno; 190error("cannot fix permission bits on%s", lk->filename.buf); 191rollback_lock_file(lk); 192 errno = save_errno; 193return-1; 194} 195return lk->fd; 196} 197 198voidunable_to_lock_message(const char*path,int err,struct strbuf *buf) 199{ 200if(err == EEXIST) { 201strbuf_addf(buf,"Unable to create '%s.lock':%s.\n\n" 202"If no other git process is currently running, this probably means a\n" 203"git process crashed in this repository earlier. Make sure no other git\n" 204"process is running and remove the file manually to continue.", 205absolute_path(path),strerror(err)); 206}else 207strbuf_addf(buf,"Unable to create '%s.lock':%s", 208absolute_path(path),strerror(err)); 209} 210 211intunable_to_lock_error(const char*path,int err) 212{ 213struct strbuf buf = STRBUF_INIT; 214 215unable_to_lock_message(path, err, &buf); 216error("%s", buf.buf); 217strbuf_release(&buf); 218return-1; 219} 220 221NORETURN voidunable_to_lock_die(const char*path,int err) 222{ 223struct strbuf buf = STRBUF_INIT; 224 225unable_to_lock_message(path, err, &buf); 226die("%s", buf.buf); 227} 228 229/* This should return a meaningful errno on failure */ 230inthold_lock_file_for_update(struct lock_file *lk,const char*path,int flags) 231{ 232int fd =lock_file(lk, path, flags); 233if(fd <0&& (flags & LOCK_DIE_ON_ERROR)) 234unable_to_lock_die(path, errno); 235return fd; 236} 237 238inthold_lock_file_for_append(struct lock_file *lk,const char*path,int flags) 239{ 240int fd, orig_fd; 241 242 fd =lock_file(lk, path, flags); 243if(fd <0) { 244if(flags & LOCK_DIE_ON_ERROR) 245unable_to_lock_die(path, errno); 246return fd; 247} 248 249 orig_fd =open(path, O_RDONLY); 250if(orig_fd <0) { 251if(errno != ENOENT) { 252if(flags & LOCK_DIE_ON_ERROR) 253die("cannot open '%s' for copying", path); 254rollback_lock_file(lk); 255returnerror("cannot open '%s' for copying", path); 256} 257}else if(copy_fd(orig_fd, fd)) { 258if(flags & LOCK_DIE_ON_ERROR) 259exit(128); 260rollback_lock_file(lk); 261return-1; 262} 263return fd; 264} 265 266intclose_lock_file(struct lock_file *lk) 267{ 268int fd = lk->fd; 269 270if(fd <0) 271return0; 272 273 lk->fd = -1; 274if(close(fd)) { 275int save_errno = errno; 276rollback_lock_file(lk); 277 errno = save_errno; 278return-1; 279} 280return0; 281} 282 283intreopen_lock_file(struct lock_file *lk) 284{ 285if(0<= lk->fd) 286die(_("BUG: reopen a lockfile that is still open")); 287if(!lk->active) 288die(_("BUG: reopen a lockfile that has been committed")); 289 lk->fd =open(lk->filename.buf, O_WRONLY); 290return lk->fd; 291} 292 293intcommit_lock_file(struct lock_file *lk) 294{ 295static struct strbuf result_file = STRBUF_INIT; 296int err; 297 298if(!lk->active) 299die("BUG: attempt to commit unlocked object"); 300 301if(close_lock_file(lk)) 302return-1; 303 304/* remove ".lock": */ 305strbuf_add(&result_file, lk->filename.buf, 306 lk->filename.len - LOCK_SUFFIX_LEN); 307 err =rename(lk->filename.buf, result_file.buf); 308strbuf_reset(&result_file); 309if(err) { 310int save_errno = errno; 311rollback_lock_file(lk); 312 errno = save_errno; 313return-1; 314} 315 316 lk->active =0; 317strbuf_reset(&lk->filename); 318return0; 319} 320 321inthold_locked_index(struct lock_file *lk,int die_on_error) 322{ 323returnhold_lock_file_for_update(lk,get_index_file(), 324 die_on_error 325? LOCK_DIE_ON_ERROR 326:0); 327} 328 329voidrollback_lock_file(struct lock_file *lk) 330{ 331if(!lk->active) 332return; 333 334if(!close_lock_file(lk)) { 335unlink_or_warn(lk->filename.buf); 336 lk->active =0; 337strbuf_reset(&lk->filename); 338} 339}