2  * Copyright (c) 2005, Junio C Hamano
 
   7 static struct lock_file *lock_file_list;
 
   8 static const char *alternate_index_output;
 
  10 static void remove_lock_file(void)
 
  14         while (lock_file_list) {
 
  15                 if (lock_file_list->owner == me &&
 
  16                     lock_file_list->filename[0]) {
 
  17                         if (lock_file_list->fd >= 0)
 
  18                                 close(lock_file_list->fd);
 
  19                         unlink(lock_file_list->filename);
 
  21                 lock_file_list = lock_file_list->next;
 
  25 static void remove_lock_file_on_signal(int signo)
 
  33  * p = absolute or relative path name
 
  35  * Return a pointer into p showing the beginning of the last path name
 
  36  * element.  If p is empty or the root directory ("/"), just return p.
 
  38 static char *last_path_elm(char *p)
 
  40         /* r starts pointing to null at the end of the string */
 
  41         char *r = strchr(p, '\0');
 
  44                 return p; /* just return empty string */
 
  46         r--; /* back up to last non-null character */
 
  48         /* back up past trailing slashes, if any */
 
  49         while (r > p && *r == '/')
 
  53          * then go backwards until I hit a slash, or the beginning of
 
  56         while (r > p && *(r-1) != '/')
 
  62 /* We allow "recursive" symbolic links. Only within reason, though */
 
  66  * p = path that may be a symlink
 
  69  * If p is a symlink, attempt to overwrite p with a path to the real
 
  70  * file or directory (which may or may not exist), following a chain of
 
  71  * symlinks if necessary.  Otherwise, leave p unmodified.
 
  73  * This is a best-effort routine.  If an error occurs, p will either be
 
  74  * left unmodified or will name a different symlink in a symlink chain
 
  75  * that started with p's initial contents.
 
  80 static char *resolve_symlink(char *p, size_t s)
 
  86                 int link_len = readlink(p, link, sizeof(link));
 
  88                         /* not a symlink anymore */
 
  91                 else if (link_len < sizeof(link))
 
  92                         /* readlink() never null-terminates */
 
  93                         link[link_len] = '\0';
 
  95                         warning("%s: symlink too long", p);
 
  99                 if (is_absolute_path(link)) {
 
 100                         /* absolute path simply replaces p */
 
 104                                 warning("%s: symlink too long", p);
 
 109                          * link is a relative path, so I must replace the
 
 110                          * last element of p with it.
 
 112                         char *r = (char*)last_path_elm(p);
 
 113                         if (r - p + link_len < s)
 
 116                                 warning("%s: symlink too long", p);
 
 125 static int lock_file(struct lock_file *lk, const char *path, int flags)
 
 127         if (strlen(path) >= sizeof(lk->filename))
 
 129         strcpy(lk->filename, path);
 
 131          * subtract 5 from size to make sure there's room for adding
 
 132          * ".lock" for the lock file name
 
 134         if (!(flags & LOCK_NODEREF))
 
 135                 resolve_symlink(lk->filename, sizeof(lk->filename)-5);
 
 136         strcat(lk->filename, ".lock");
 
 137         lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
 
 139                 if (!lock_file_list) {
 
 140                         sigchain_push_common(remove_lock_file_on_signal);
 
 141                         atexit(remove_lock_file);
 
 143                 lk->owner = getpid();
 
 145                         lk->next = lock_file_list;
 
 149                 if (adjust_shared_perm(lk->filename))
 
 150                         return error("cannot fix permission bits on %s",
 
 159 NORETURN void unable_to_lock_index_die(const char *path, int err)
 
 162                 die("Unable to create '%s.lock': %s.\n\n"
 
 163                     "If no other git process is currently running, this probably means a\n"
 
 164                     "git process crashed in this repository earlier. Make sure no other git\n"
 
 165                     "process is running and remove the file manually to continue.",
 
 166                     path, strerror(err));
 
 168                 die("Unable to create '%s.lock': %s", path, strerror(err));
 
 172 int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
 
 174         int fd = lock_file(lk, path, flags);
 
 175         if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
 
 176                 unable_to_lock_index_die(path, errno);
 
 180 int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
 
 184         fd = lock_file(lk, path, flags);
 
 186                 if (flags & LOCK_DIE_ON_ERROR)
 
 187                         unable_to_lock_index_die(path, errno);
 
 191         orig_fd = open(path, O_RDONLY);
 
 193                 if (errno != ENOENT) {
 
 194                         if (flags & LOCK_DIE_ON_ERROR)
 
 195                                 die("cannot open '%s' for copying", path);
 
 197                         return error("cannot open '%s' for copying", path);
 
 199         } else if (copy_fd(orig_fd, fd)) {
 
 200                 if (flags & LOCK_DIE_ON_ERROR)
 
 208 int close_lock_file(struct lock_file *lk)
 
 215 int commit_lock_file(struct lock_file *lk)
 
 217         char result_file[PATH_MAX];
 
 219         if (lk->fd >= 0 && close_lock_file(lk))
 
 221         strcpy(result_file, lk->filename);
 
 222         i = strlen(result_file) - 5; /* .lock */
 
 224         if (rename(lk->filename, result_file))
 
 230 int hold_locked_index(struct lock_file *lk, int die_on_error)
 
 232         return hold_lock_file_for_update(lk, get_index_file(),
 
 238 void set_alternate_index_output(const char *name)
 
 240         alternate_index_output = name;
 
 243 int commit_locked_index(struct lock_file *lk)
 
 245         if (alternate_index_output) {
 
 246                 if (lk->fd >= 0 && close_lock_file(lk))
 
 248                 if (rename(lk->filename, alternate_index_output))
 
 254                 return commit_lock_file(lk);
 
 257 void rollback_lock_file(struct lock_file *lk)
 
 259         if (lk->filename[0]) {
 
 262                 unlink(lk->filename);