lockfile.con commit Merge branch 'da/include-compat-util-first-in-c' (211836f)
   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(orig_fd);
 228                close(fd);
 229                return -1;
 230        } else {
 231                close(orig_fd);
 232        }
 233        return fd;
 234}
 235
 236int close_lock_file(struct lock_file *lk)
 237{
 238        int fd = lk->fd;
 239        lk->fd = -1;
 240        return close(fd);
 241}
 242
 243int reopen_lock_file(struct lock_file *lk)
 244{
 245        if (0 <= lk->fd)
 246                die(_("BUG: reopen a lockfile that is still open"));
 247        if (!lk->filename[0])
 248                die(_("BUG: reopen a lockfile that has been committed"));
 249        lk->fd = open(lk->filename, O_WRONLY);
 250        return lk->fd;
 251}
 252
 253int commit_lock_file(struct lock_file *lk)
 254{
 255        char result_file[PATH_MAX];
 256        size_t i;
 257        if (lk->fd >= 0 && close_lock_file(lk))
 258                return -1;
 259        strcpy(result_file, lk->filename);
 260        i = strlen(result_file) - 5; /* .lock */
 261        result_file[i] = 0;
 262        if (rename(lk->filename, result_file))
 263                return -1;
 264        lk->filename[0] = 0;
 265        return 0;
 266}
 267
 268int hold_locked_index(struct lock_file *lk, int die_on_error)
 269{
 270        return hold_lock_file_for_update(lk, get_index_file(),
 271                                         die_on_error
 272                                         ? LOCK_DIE_ON_ERROR
 273                                         : 0);
 274}
 275
 276void rollback_lock_file(struct lock_file *lk)
 277{
 278        if (lk->filename[0]) {
 279                if (lk->fd >= 0)
 280                        close(lk->fd);
 281                unlink_or_warn(lk->filename);
 282        }
 283        lk->filename[0] = 0;
 284}