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); 156 errno = save_errno; 157return-1; 158} 159} 160else 161 lk->filename[0] =0; 162return lk->fd; 163} 164 165voidunable_to_lock_message(const char*path,int err,struct strbuf *buf) 166{ 167if(err == EEXIST) { 168strbuf_addf(buf,"Unable to create '%s.lock':%s.\n\n" 169"If no other git process is currently running, this probably means a\n" 170"git process crashed in this repository earlier. Make sure no other git\n" 171"process is running and remove the file manually to continue.", 172absolute_path(path),strerror(err)); 173}else 174strbuf_addf(buf,"Unable to create '%s.lock':%s", 175absolute_path(path),strerror(err)); 176} 177 178intunable_to_lock_error(const char*path,int err) 179{ 180struct strbuf buf = STRBUF_INIT; 181 182unable_to_lock_message(path, err, &buf); 183error("%s", buf.buf); 184strbuf_release(&buf); 185return-1; 186} 187 188NORETURN voidunable_to_lock_index_die(const char*path,int err) 189{ 190struct strbuf buf = STRBUF_INIT; 191 192unable_to_lock_message(path, err, &buf); 193die("%s", buf.buf); 194} 195 196/* This should return a meaningful errno on failure */ 197inthold_lock_file_for_update(struct lock_file *lk,const char*path,int flags) 198{ 199int fd =lock_file(lk, path, flags); 200if(fd <0&& (flags & LOCK_DIE_ON_ERROR)) 201unable_to_lock_index_die(path, errno); 202return fd; 203} 204 205inthold_lock_file_for_append(struct lock_file *lk,const char*path,int flags) 206{ 207int fd, orig_fd; 208 209 fd =lock_file(lk, path, flags); 210if(fd <0) { 211if(flags & LOCK_DIE_ON_ERROR) 212unable_to_lock_index_die(path, errno); 213return fd; 214} 215 216 orig_fd =open(path, O_RDONLY); 217if(orig_fd <0) { 218if(errno != ENOENT) { 219if(flags & LOCK_DIE_ON_ERROR) 220die("cannot open '%s' for copying", path); 221close(fd); 222returnerror("cannot open '%s' for copying", path); 223} 224}else if(copy_fd(orig_fd, fd)) { 225if(flags & LOCK_DIE_ON_ERROR) 226exit(128); 227close(fd); 228return-1; 229} 230return fd; 231} 232 233intclose_lock_file(struct lock_file *lk) 234{ 235int fd = lk->fd; 236 lk->fd = -1; 237returnclose(fd); 238} 239 240intreopen_lock_file(struct lock_file *lk) 241{ 242if(0<= lk->fd) 243die(_("BUG: reopen a lockfile that is still open")); 244if(!lk->filename[0]) 245die(_("BUG: reopen a lockfile that has been committed")); 246 lk->fd =open(lk->filename, O_WRONLY); 247return lk->fd; 248} 249 250intcommit_lock_file(struct lock_file *lk) 251{ 252char result_file[PATH_MAX]; 253size_t i; 254if(lk->fd >=0&&close_lock_file(lk)) 255return-1; 256strcpy(result_file, lk->filename); 257 i =strlen(result_file) -5;/* .lock */ 258 result_file[i] =0; 259if(rename(lk->filename, result_file)) 260return-1; 261 lk->filename[0] =0; 262return0; 263} 264 265inthold_locked_index(struct lock_file *lk,int die_on_error) 266{ 267returnhold_lock_file_for_update(lk,get_index_file(), 268 die_on_error 269? LOCK_DIE_ON_ERROR 270:0); 271} 272 273voidrollback_lock_file(struct lock_file *lk) 274{ 275if(lk->filename[0]) { 276if(lk->fd >=0) 277close(lk->fd); 278unlink_or_warn(lk->filename); 279} 280 lk->filename[0] =0; 281}