lockfile.con commit Merge branch 'jk/more-push-completion' (0d9cb2d)
   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 void remove_lock_file(void)
  10{
  11        pid_t me = getpid();
  12
  13        while (lock_file_list) {
  14                if (lock_file_list->owner == me &&
  15                    lock_file_list->filename[0]) {
  16                        if (lock_file_list->fd >= 0)
  17                                close(lock_file_list->fd);
  18                        unlink_or_warn(lock_file_list->filename);
  19                }
  20                lock_file_list = lock_file_list->next;
  21        }
  22}
  23
  24static void remove_lock_file_on_signal(int signo)
  25{
  26        remove_lock_file();
  27        sigchain_pop(signo);
  28        raise(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 */
  40        char *r = strchr(p, '\0');
  41
  42        if (r == p)
  43                return p; /* just return empty string */
  44
  45        r--; /* back up to last non-null character */
  46
  47        /* back up past trailing slashes, if any */
  48        while (r > p && *r == '/')
  49                r--;
  50
  51        /*
  52         * then go backwards until I hit a slash, or the beginning of
  53         * the string
  54         */
  55        while (r > p && *(r-1) != '/')
  56                r--;
  57        return 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{
  81        int depth = MAXDEPTH;
  82
  83        while (depth--) {
  84                char link[PATH_MAX];
  85                int link_len = readlink(p, link, sizeof(link));
  86                if (link_len < 0) {
  87                        /* not a symlink anymore */
  88                        return p;
  89                }
  90                else if (link_len < sizeof(link))
  91                        /* readlink() never null-terminates */
  92                        link[link_len] = '\0';
  93                else {
  94                        warning("%s: symlink too long", p);
  95                        return p;
  96                }
  97
  98                if (is_absolute_path(link)) {
  99                        /* absolute path simply replaces p */
 100                        if (link_len < s)
 101                                strcpy(p, link);
 102                        else {
 103                                warning("%s: symlink too long", p);
 104                                return p;
 105                        }
 106                } else {
 107                        /*
 108                         * link is a relative path, so I must replace the
 109                         * last element of p with it.
 110                         */
 111                        char *r = (char *)last_path_elm(p);
 112                        if (r - p + link_len < s)
 113                                strcpy(r, link);
 114                        else {
 115                                warning("%s: symlink too long", p);
 116                                return p;
 117                        }
 118                }
 119        }
 120        return p;
 121}
 122
 123/* Make sure errno contains a meaningful value on error */
 124static int lock_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         */
 130        static const size_t max_path_len = sizeof(lk->filename) - 5;
 131
 132        if (strlen(path) >= max_path_len) {
 133                errno = ENAMETOOLONG;
 134                return -1;
 135        }
 136        strcpy(lk->filename, path);
 137        if (!(flags & LOCK_NODEREF))
 138                resolve_symlink(lk->filename, max_path_len);
 139        strcat(lk->filename, ".lock");
 140        lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
 141        if (0 <= lk->fd) {
 142                if (!lock_file_list) {
 143                        sigchain_push_common(remove_lock_file_on_signal);
 144                        atexit(remove_lock_file);
 145                }
 146                lk->owner = getpid();
 147                if (!lk->on_list) {
 148                        lk->next = lock_file_list;
 149                        lock_file_list = lk;
 150                        lk->on_list = 1;
 151                }
 152                if (adjust_shared_perm(lk->filename)) {
 153                        int save_errno = errno;
 154                        error("cannot fix permission bits on %s",
 155                              lk->filename);
 156                        errno = save_errno;
 157                        return -1;
 158                }
 159        }
 160        else
 161                lk->filename[0] = 0;
 162        return lk->fd;
 163}
 164
 165void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
 166{
 167        if (err == EEXIST) {
 168                strbuf_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.",
 172                            absolute_path(path), strerror(err));
 173        } else
 174                strbuf_addf(buf, "Unable to create '%s.lock': %s",
 175                            absolute_path(path), strerror(err));
 176}
 177
 178int unable_to_lock_error(const char *path, int err)
 179{
 180        struct strbuf buf = STRBUF_INIT;
 181
 182        unable_to_lock_message(path, err, &buf);
 183        error("%s", buf.buf);
 184        strbuf_release(&buf);
 185        return -1;
 186}
 187
 188NORETURN void unable_to_lock_index_die(const char *path, int err)
 189{
 190        struct strbuf buf = STRBUF_INIT;
 191
 192        unable_to_lock_message(path, err, &buf);
 193        die("%s", buf.buf);
 194}
 195
 196/* This should return a meaningful errno on failure */
 197int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
 198{
 199        int fd = lock_file(lk, path, flags);
 200        if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
 201                unable_to_lock_index_die(path, errno);
 202        return fd;
 203}
 204
 205int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
 206{
 207        int fd, orig_fd;
 208
 209        fd = lock_file(lk, path, flags);
 210        if (fd < 0) {
 211                if (flags & LOCK_DIE_ON_ERROR)
 212                        unable_to_lock_index_die(path, errno);
 213                return fd;
 214        }
 215
 216        orig_fd = open(path, O_RDONLY);
 217        if (orig_fd < 0) {
 218                if (errno != ENOENT) {
 219                        if (flags & LOCK_DIE_ON_ERROR)
 220                                die("cannot open '%s' for copying", path);
 221                        close(fd);
 222                        return error("cannot open '%s' for copying", path);
 223                }
 224        } else if (copy_fd(orig_fd, fd)) {
 225                if (flags & LOCK_DIE_ON_ERROR)
 226                        exit(128);
 227                close(fd);
 228                return -1;
 229        }
 230        return fd;
 231}
 232
 233int close_lock_file(struct lock_file *lk)
 234{
 235        int fd = lk->fd;
 236        lk->fd = -1;
 237        return close(fd);
 238}
 239
 240int commit_lock_file(struct lock_file *lk)
 241{
 242        char result_file[PATH_MAX];
 243        size_t i;
 244        if (lk->fd >= 0 && close_lock_file(lk))
 245                return -1;
 246        strcpy(result_file, lk->filename);
 247        i = strlen(result_file) - 5; /* .lock */
 248        result_file[i] = 0;
 249        if (rename(lk->filename, result_file))
 250                return -1;
 251        lk->filename[0] = 0;
 252        return 0;
 253}
 254
 255int hold_locked_index(struct lock_file *lk, int die_on_error)
 256{
 257        return hold_lock_file_for_update(lk, get_index_file(),
 258                                         die_on_error
 259                                         ? LOCK_DIE_ON_ERROR
 260                                         : 0);
 261}
 262
 263void rollback_lock_file(struct lock_file *lk)
 264{
 265        if (lk->filename[0]) {
 266                if (lk->fd >= 0)
 267                        close(lk->fd);
 268                unlink_or_warn(lk->filename);
 269        }
 270        lk->filename[0] = 0;
 271}