3cd57dc3854c22b071619e03c3ccd26981b0c45b
   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;
   8static const char *alternate_index_output;
   9
  10static void remove_lock_file(void)
  11{
  12        pid_t me = getpid();
  13
  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);
  20                }
  21                lock_file_list = lock_file_list->next;
  22        }
  23}
  24
  25static void remove_lock_file_on_signal(int signo)
  26{
  27        remove_lock_file();
  28        sigchain_pop(signo);
  29        raise(signo);
  30}
  31
  32/*
  33 * p = absolute or relative path name
  34 *
  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.
  37 */
  38static char *last_path_elm(char *p)
  39{
  40        /* r starts pointing to null at the end of the string */
  41        char *r = strchr(p, '\0');
  42
  43        if (r == p)
  44                return p; /* just return empty string */
  45
  46        r--; /* back up to last non-null character */
  47
  48        /* back up past trailing slashes, if any */
  49        while (r > p && *r == '/')
  50                r--;
  51
  52        /*
  53         * then go backwards until I hit a slash, or the beginning of
  54         * the string
  55         */
  56        while (r > p && *(r-1) != '/')
  57                r--;
  58        return r;
  59}
  60
  61
  62/* We allow "recursive" symbolic links. Only within reason, though */
  63#define MAXDEPTH 5
  64
  65/*
  66 * p = path that may be a symlink
  67 * s = full size of p
  68 *
  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.
  72 *
  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.
  76 *
  77 * Always returns p.
  78 */
  79
  80static char *resolve_symlink(char *p, size_t s)
  81{
  82        int depth = MAXDEPTH;
  83
  84        while (depth--) {
  85                char link[PATH_MAX];
  86                int link_len = readlink(p, link, sizeof(link));
  87                if (link_len < 0) {
  88                        /* not a symlink anymore */
  89                        return p;
  90                }
  91                else if (link_len < sizeof(link))
  92                        /* readlink() never null-terminates */
  93                        link[link_len] = '\0';
  94                else {
  95                        warning("%s: symlink too long", p);
  96                        return p;
  97                }
  98
  99                if (is_absolute_path(link)) {
 100                        /* absolute path simply replaces p */
 101                        if (link_len < s)
 102                                strcpy(p, link);
 103                        else {
 104                                warning("%s: symlink too long", p);
 105                                return p;
 106                        }
 107                } else {
 108                        /*
 109                         * link is a relative path, so I must replace the
 110                         * last element of p with it.
 111                         */
 112                        char *r = (char*)last_path_elm(p);
 113                        if (r - p + link_len < s)
 114                                strcpy(r, link);
 115                        else {
 116                                warning("%s: symlink too long", p);
 117                                return p;
 118                        }
 119                }
 120        }
 121        return p;
 122}
 123
 124
 125static int lock_file(struct lock_file *lk, const char *path, int flags)
 126{
 127        if (strlen(path) >= sizeof(lk->filename))
 128                return -1;
 129        strcpy(lk->filename, path);
 130        /*
 131         * subtract 5 from size to make sure there's room for adding
 132         * ".lock" for the lock file name
 133         */
 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);
 138        if (0 <= lk->fd) {
 139                if (!lock_file_list) {
 140                        sigchain_push(SIGINT, remove_lock_file_on_signal);
 141                        sigchain_push(SIGHUP, remove_lock_file_on_signal);
 142                        sigchain_push(SIGTERM, remove_lock_file_on_signal);
 143                        sigchain_push(SIGQUIT, remove_lock_file_on_signal);
 144                        sigchain_push(SIGPIPE, remove_lock_file_on_signal);
 145                        atexit(remove_lock_file);
 146                }
 147                lk->owner = getpid();
 148                if (!lk->on_list) {
 149                        lk->next = lock_file_list;
 150                        lock_file_list = lk;
 151                        lk->on_list = 1;
 152                }
 153                if (adjust_shared_perm(lk->filename))
 154                        return error("cannot fix permission bits on %s",
 155                                     lk->filename);
 156        }
 157        else
 158                lk->filename[0] = 0;
 159        return lk->fd;
 160}
 161
 162int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
 163{
 164        int fd = lock_file(lk, path, flags);
 165        if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
 166                die("unable to create '%s.lock': %s", path, strerror(errno));
 167        return fd;
 168}
 169
 170int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
 171{
 172        int fd, orig_fd;
 173
 174        fd = lock_file(lk, path, flags);
 175        if (fd < 0) {
 176                if (flags & LOCK_DIE_ON_ERROR)
 177                        die("unable to create '%s.lock': %s", path, strerror(errno));
 178                return fd;
 179        }
 180
 181        orig_fd = open(path, O_RDONLY);
 182        if (orig_fd < 0) {
 183                if (errno != ENOENT) {
 184                        if (flags & LOCK_DIE_ON_ERROR)
 185                                die("cannot open '%s' for copying", path);
 186                        close(fd);
 187                        return error("cannot open '%s' for copying", path);
 188                }
 189        } else if (copy_fd(orig_fd, fd)) {
 190                if (flags & LOCK_DIE_ON_ERROR)
 191                        exit(128);
 192                close(fd);
 193                return -1;
 194        }
 195        return fd;
 196}
 197
 198int close_lock_file(struct lock_file *lk)
 199{
 200        int fd = lk->fd;
 201        lk->fd = -1;
 202        return close(fd);
 203}
 204
 205int commit_lock_file(struct lock_file *lk)
 206{
 207        char result_file[PATH_MAX];
 208        size_t i;
 209        if (lk->fd >= 0 && close_lock_file(lk))
 210                return -1;
 211        strcpy(result_file, lk->filename);
 212        i = strlen(result_file) - 5; /* .lock */
 213        result_file[i] = 0;
 214        if (rename(lk->filename, result_file))
 215                return -1;
 216        lk->filename[0] = 0;
 217        return 0;
 218}
 219
 220int hold_locked_index(struct lock_file *lk, int die_on_error)
 221{
 222        return hold_lock_file_for_update(lk, get_index_file(),
 223                                         die_on_error
 224                                         ? LOCK_DIE_ON_ERROR
 225                                         : 0);
 226}
 227
 228void set_alternate_index_output(const char *name)
 229{
 230        alternate_index_output = name;
 231}
 232
 233int commit_locked_index(struct lock_file *lk)
 234{
 235        if (alternate_index_output) {
 236                if (lk->fd >= 0 && close_lock_file(lk))
 237                        return -1;
 238                if (rename(lk->filename, alternate_index_output))
 239                        return -1;
 240                lk->filename[0] = 0;
 241                return 0;
 242        }
 243        else
 244                return commit_lock_file(lk);
 245}
 246
 247void rollback_lock_file(struct lock_file *lk)
 248{
 249        if (lk->filename[0]) {
 250                if (lk->fd >= 0)
 251                        close(lk->fd);
 252                unlink(lk->filename);
 253        }
 254        lk->filename[0] = 0;
 255}