1/* 2 * Copyright (c) 2005, Junio C Hamano 3 */ 4#include"cache.h" 5#include"sigchain.h" 6 7static struct lock_file *lock_file_list; 8 9static voidremove_lock_file(void) 10{ 11 pid_t me =getpid(); 12 13while(lock_file_list) { 14if(lock_file_list->owner == me && 15 lock_file_list->filename[0]) { 16if(lock_file_list->fd >=0) 17close(lock_file_list->fd); 18unlink_or_warn(lock_file_list->filename); 19} 20 lock_file_list = lock_file_list->next; 21} 22} 23 24static voidremove_lock_file_on_signal(int signo) 25{ 26remove_lock_file(); 27sigchain_pop(signo); 28raise(signo); 29} 30 31/* 32 * p = absolute or relative path name 33 * 34 * Return a pointer into p showing the beginning of the last path name 35 * element. If p is empty or the root directory ("/"), just return p. 36 */ 37static char*last_path_elm(char*p) 38{ 39/* r starts pointing to null at the end of the string */ 40char*r =strchr(p,'\0'); 41 42if(r == p) 43return p;/* just return empty string */ 44 45 r--;/* back up to last non-null character */ 46 47/* back up past trailing slashes, if any */ 48while(r > p && *r =='/') 49 r--; 50 51/* 52 * then go backwards until I hit a slash, or the beginning of 53 * the string 54 */ 55while(r > p && *(r-1) !='/') 56 r--; 57return r; 58} 59 60 61/* We allow "recursive" symbolic links. Only within reason, though */ 62#define MAXDEPTH 5 63 64/* 65 * p = path that may be a symlink 66 * s = full size of p 67 * 68 * If p is a symlink, attempt to overwrite p with a path to the real 69 * file or directory (which may or may not exist), following a chain of 70 * symlinks if necessary. Otherwise, leave p unmodified. 71 * 72 * This is a best-effort routine. If an error occurs, p will either be 73 * left unmodified or will name a different symlink in a symlink chain 74 * that started with p's initial contents. 75 * 76 * Always returns p. 77 */ 78 79static char*resolve_symlink(char*p,size_t s) 80{ 81int depth = MAXDEPTH; 82 83while(depth--) { 84char link[PATH_MAX]; 85int link_len =readlink(p, link,sizeof(link)); 86if(link_len <0) { 87/* not a symlink anymore */ 88return p; 89} 90else if(link_len <sizeof(link)) 91/* readlink() never null-terminates */ 92 link[link_len] ='\0'; 93else{ 94warning("%s: symlink too long", p); 95return p; 96} 97 98if(is_absolute_path(link)) { 99/* absolute path simply replaces p */ 100if(link_len < s) 101strcpy(p, link); 102else{ 103warning("%s: symlink too long", p); 104return p; 105} 106}else{ 107/* 108 * link is a relative path, so I must replace the 109 * last element of p with it. 110 */ 111char*r = (char*)last_path_elm(p); 112if(r - p + link_len < s) 113strcpy(r, link); 114else{ 115warning("%s: symlink too long", p); 116return p; 117} 118} 119} 120return p; 121} 122 123/* Make sure errno contains a meaningful value on error */ 124static intlock_file(struct lock_file *lk,const char*path,int flags) 125{ 126/* 127 * subtract 5 from size to make sure there's room for adding 128 * ".lock" for the lock file name 129 */ 130static const size_t max_path_len =sizeof(lk->filename) -5; 131 132if(strlen(path) >= max_path_len) { 133 errno = ENAMETOOLONG; 134return-1; 135} 136strcpy(lk->filename, path); 137if(!(flags & LOCK_NODEREF)) 138resolve_symlink(lk->filename, max_path_len); 139strcat(lk->filename,".lock"); 140 lk->fd =open(lk->filename, O_RDWR | O_CREAT | O_EXCL,0666); 141if(0<= lk->fd) { 142if(!lock_file_list) { 143sigchain_push_common(remove_lock_file_on_signal); 144atexit(remove_lock_file); 145} 146 lk->owner =getpid(); 147if(!lk->on_list) { 148 lk->next = lock_file_list; 149 lock_file_list = lk; 150 lk->on_list =1; 151} 152if(adjust_shared_perm(lk->filename)) { 153int save_errno = errno; 154error("cannot fix permission bits on%s", 155 lk->filename); 156rollback_lock_file(lk); 157 errno = save_errno; 158return-1; 159} 160} 161else 162 lk->filename[0] =0; 163return lk->fd; 164} 165 166voidunable_to_lock_message(const char*path,int err,struct strbuf *buf) 167{ 168if(err == EEXIST) { 169strbuf_addf(buf,"Unable to create '%s.lock':%s.\n\n" 170"If no other git process is currently running, this probably means a\n" 171"git process crashed in this repository earlier. Make sure no other git\n" 172"process is running and remove the file manually to continue.", 173absolute_path(path),strerror(err)); 174}else 175strbuf_addf(buf,"Unable to create '%s.lock':%s", 176absolute_path(path),strerror(err)); 177} 178 179intunable_to_lock_error(const char*path,int err) 180{ 181struct strbuf buf = STRBUF_INIT; 182 183unable_to_lock_message(path, err, &buf); 184error("%s", buf.buf); 185strbuf_release(&buf); 186return-1; 187} 188 189NORETURN voidunable_to_lock_die(const char*path,int err) 190{ 191struct strbuf buf = STRBUF_INIT; 192 193unable_to_lock_message(path, err, &buf); 194die("%s", buf.buf); 195} 196 197/* This should return a meaningful errno on failure */ 198inthold_lock_file_for_update(struct lock_file *lk,const char*path,int flags) 199{ 200int fd =lock_file(lk, path, flags); 201if(fd <0&& (flags & LOCK_DIE_ON_ERROR)) 202unable_to_lock_die(path, errno); 203return fd; 204} 205 206inthold_lock_file_for_append(struct lock_file *lk,const char*path,int flags) 207{ 208int fd, orig_fd; 209 210 fd =lock_file(lk, path, flags); 211if(fd <0) { 212if(flags & LOCK_DIE_ON_ERROR) 213unable_to_lock_die(path, errno); 214return fd; 215} 216 217 orig_fd =open(path, O_RDONLY); 218if(orig_fd <0) { 219if(errno != ENOENT) { 220if(flags & LOCK_DIE_ON_ERROR) 221die("cannot open '%s' for copying", path); 222rollback_lock_file(lk); 223returnerror("cannot open '%s' for copying", path); 224} 225}else if(copy_fd(orig_fd, fd)) { 226if(flags & LOCK_DIE_ON_ERROR) 227exit(128); 228rollback_lock_file(lk); 229return-1; 230} 231return fd; 232} 233 234intclose_lock_file(struct lock_file *lk) 235{ 236int fd = lk->fd; 237 238if(fd <0) 239return0; 240 241 lk->fd = -1; 242returnclose(fd); 243} 244 245intreopen_lock_file(struct lock_file *lk) 246{ 247if(0<= lk->fd) 248die(_("BUG: reopen a lockfile that is still open")); 249if(!lk->filename[0]) 250die(_("BUG: reopen a lockfile that has been committed")); 251 lk->fd =open(lk->filename, O_WRONLY); 252return lk->fd; 253} 254 255intcommit_lock_file(struct lock_file *lk) 256{ 257char result_file[PATH_MAX]; 258size_t i; 259if(close_lock_file(lk)) 260return-1; 261strcpy(result_file, lk->filename); 262 i =strlen(result_file) -5;/* .lock */ 263 result_file[i] =0; 264if(rename(lk->filename, result_file)) 265return-1; 266 lk->filename[0] =0; 267return0; 268} 269 270inthold_locked_index(struct lock_file *lk,int die_on_error) 271{ 272returnhold_lock_file_for_update(lk,get_index_file(), 273 die_on_error 274? LOCK_DIE_ON_ERROR 275:0); 276} 277 278voidrollback_lock_file(struct lock_file *lk) 279{ 280if(!lk->filename[0]) 281return; 282 283close_lock_file(lk); 284unlink_or_warn(lk->filename); 285 lk->filename[0] =0; 286}