1/* 2 * Copyright (c) 2005, Junio C Hamano 3 */ 4#include"cache.h" 5 6static struct lock_file *lock_file_list; 7static const char*alternate_index_output; 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]) { 16close(lock_file_list->fd); 17unlink(lock_file_list->filename); 18} 19 lock_file_list = lock_file_list->next; 20} 21} 22 23static voidremove_lock_file_on_signal(int signo) 24{ 25remove_lock_file(); 26signal(SIGINT, SIG_DFL); 27raise(signo); 28} 29 30/* 31 * p = absolute or relative path name 32 * 33 * Return a pointer into p showing the beginning of the last path name 34 * element. If p is empty or the root directory ("/"), just return p. 35 */ 36static char*last_path_elm(char*p) 37{ 38/* r starts pointing to null at the end of the string */ 39char*r =strchr(p,'\0'); 40 41if(r == p) 42return p;/* just return empty string */ 43 44 r--;/* back up to last non-null character */ 45 46/* back up past trailing slashes, if any */ 47while(r > p && *r =='/') 48 r--; 49 50/* 51 * then go backwards until I hit a slash, or the beginning of 52 * the string 53 */ 54while(r > p && *(r-1) !='/') 55 r--; 56return r; 57} 58 59 60/* We allow "recursive" symbolic links. Only within reason, though */ 61#define MAXDEPTH 5 62 63/* 64 * p = path that may be a symlink 65 * s = full size of p 66 * 67 * If p is a symlink, attempt to overwrite p with a path to the real 68 * file or directory (which may or may not exist), following a chain of 69 * symlinks if necessary. Otherwise, leave p unmodified. 70 * 71 * This is a best-effort routine. If an error occurs, p will either be 72 * left unmodified or will name a different symlink in a symlink chain 73 * that started with p's initial contents. 74 * 75 * Always returns p. 76 */ 77 78static char*resolve_symlink(char*p,size_t s) 79{ 80int depth = MAXDEPTH; 81 82while(depth--) { 83char link[PATH_MAX]; 84int link_len =readlink(p, link,sizeof(link)); 85if(link_len <0) { 86/* not a symlink anymore */ 87return p; 88} 89else if(link_len <sizeof(link)) 90/* readlink() never null-terminates */ 91 link[link_len] ='\0'; 92else{ 93warning("%s: symlink too long", p); 94return p; 95} 96 97if(is_absolute_path(link)) { 98/* absolute path simply replaces p */ 99if(link_len < s) 100strcpy(p, link); 101else{ 102warning("%s: symlink too long", p); 103return p; 104} 105}else{ 106/* 107 * link is a relative path, so I must replace the 108 * last element of p with it. 109 */ 110char*r = (char*)last_path_elm(p); 111if(r - p + link_len < s) 112strcpy(r, link); 113else{ 114warning("%s: symlink too long", p); 115return p; 116} 117} 118} 119return p; 120} 121 122 123static intlock_file(struct lock_file *lk,const char*path) 124{ 125if(strlen(path) >=sizeof(lk->filename))return-1; 126strcpy(lk->filename, path); 127/* 128 * subtract 5 from size to make sure there's room for adding 129 * ".lock" for the lock file name 130 */ 131resolve_symlink(lk->filename,sizeof(lk->filename)-5); 132strcat(lk->filename,".lock"); 133 lk->fd =open(lk->filename, O_RDWR | O_CREAT | O_EXCL,0666); 134if(0<= lk->fd) { 135if(!lock_file_list) { 136signal(SIGINT, remove_lock_file_on_signal); 137atexit(remove_lock_file); 138} 139 lk->owner =getpid(); 140if(!lk->on_list) { 141 lk->next = lock_file_list; 142 lock_file_list = lk; 143 lk->on_list =1; 144} 145if(adjust_shared_perm(lk->filename)) 146returnerror("cannot fix permission bits on%s", 147 lk->filename); 148} 149else 150 lk->filename[0] =0; 151return lk->fd; 152} 153 154inthold_lock_file_for_update(struct lock_file *lk,const char*path,int die_on_error) 155{ 156int fd =lock_file(lk, path); 157if(fd <0&& die_on_error) 158die("unable to create '%s.lock':%s", path,strerror(errno)); 159return fd; 160} 161 162intcommit_lock_file(struct lock_file *lk) 163{ 164char result_file[PATH_MAX]; 165int i; 166close(lk->fd); 167strcpy(result_file, lk->filename); 168 i =strlen(result_file) -5;/* .lock */ 169 result_file[i] =0; 170 i =rename(lk->filename, result_file); 171 lk->filename[0] =0; 172return i; 173} 174 175inthold_locked_index(struct lock_file *lk,int die_on_error) 176{ 177returnhold_lock_file_for_update(lk,get_index_file(), die_on_error); 178} 179 180voidset_alternate_index_output(const char*name) 181{ 182 alternate_index_output = name; 183} 184 185intcommit_locked_index(struct lock_file *lk) 186{ 187if(alternate_index_output) { 188int result =rename(lk->filename, alternate_index_output); 189 lk->filename[0] =0; 190return result; 191} 192else 193returncommit_lock_file(lk); 194} 195 196voidrollback_lock_file(struct lock_file *lk) 197{ 198if(lk->filename[0]) { 199close(lk->fd); 200unlink(lk->filename); 201} 202 lk->filename[0] =0; 203}