lockfile.con commit lock_file(): always initialize and register lock_file object (04e57d4)
   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 (!lock_file_list) {
 133                /* One-time initialization */
 134                sigchain_push_common(remove_lock_file_on_signal);
 135                atexit(remove_lock_file);
 136        }
 137
 138        if (!lk->on_list) {
 139                /* Initialize *lk and add it to lock_file_list: */
 140                lk->fd = -1;
 141                lk->owner = 0;
 142                lk->filename[0] = 0;
 143                lk->next = lock_file_list;
 144                lock_file_list = lk;
 145                lk->on_list = 1;
 146        }
 147
 148        if (strlen(path) >= max_path_len) {
 149                errno = ENAMETOOLONG;
 150                return -1;
 151        }
 152        strcpy(lk->filename, path);
 153        if (!(flags & LOCK_NODEREF))
 154                resolve_symlink(lk->filename, max_path_len);
 155        strcat(lk->filename, ".lock");
 156        lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
 157        if (0 <= lk->fd) {
 158                lk->owner = getpid();
 159                if (adjust_shared_perm(lk->filename)) {
 160                        int save_errno = errno;
 161                        error("cannot fix permission bits on %s",
 162                              lk->filename);
 163                        rollback_lock_file(lk);
 164                        errno = save_errno;
 165                        return -1;
 166                }
 167        }
 168        else
 169                lk->filename[0] = 0;
 170        return lk->fd;
 171}
 172
 173void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
 174{
 175        if (err == EEXIST) {
 176                strbuf_addf(buf, "Unable to create '%s.lock': %s.\n\n"
 177                    "If no other git process is currently running, this probably means a\n"
 178                    "git process crashed in this repository earlier. Make sure no other git\n"
 179                    "process is running and remove the file manually to continue.",
 180                            absolute_path(path), strerror(err));
 181        } else
 182                strbuf_addf(buf, "Unable to create '%s.lock': %s",
 183                            absolute_path(path), strerror(err));
 184}
 185
 186int unable_to_lock_error(const char *path, int err)
 187{
 188        struct strbuf buf = STRBUF_INIT;
 189
 190        unable_to_lock_message(path, err, &buf);
 191        error("%s", buf.buf);
 192        strbuf_release(&buf);
 193        return -1;
 194}
 195
 196NORETURN void unable_to_lock_die(const char *path, int err)
 197{
 198        struct strbuf buf = STRBUF_INIT;
 199
 200        unable_to_lock_message(path, err, &buf);
 201        die("%s", buf.buf);
 202}
 203
 204/* This should return a meaningful errno on failure */
 205int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
 206{
 207        int fd = lock_file(lk, path, flags);
 208        if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
 209                unable_to_lock_die(path, errno);
 210        return fd;
 211}
 212
 213int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
 214{
 215        int fd, orig_fd;
 216
 217        fd = lock_file(lk, path, flags);
 218        if (fd < 0) {
 219                if (flags & LOCK_DIE_ON_ERROR)
 220                        unable_to_lock_die(path, errno);
 221                return fd;
 222        }
 223
 224        orig_fd = open(path, O_RDONLY);
 225        if (orig_fd < 0) {
 226                if (errno != ENOENT) {
 227                        if (flags & LOCK_DIE_ON_ERROR)
 228                                die("cannot open '%s' for copying", path);
 229                        rollback_lock_file(lk);
 230                        return error("cannot open '%s' for copying", path);
 231                }
 232        } else if (copy_fd(orig_fd, fd)) {
 233                if (flags & LOCK_DIE_ON_ERROR)
 234                        exit(128);
 235                rollback_lock_file(lk);
 236                return -1;
 237        }
 238        return fd;
 239}
 240
 241int close_lock_file(struct lock_file *lk)
 242{
 243        int fd = lk->fd;
 244
 245        if (fd < 0)
 246                return 0;
 247
 248        lk->fd = -1;
 249        return close(fd);
 250}
 251
 252int reopen_lock_file(struct lock_file *lk)
 253{
 254        if (0 <= lk->fd)
 255                die(_("BUG: reopen a lockfile that is still open"));
 256        if (!lk->filename[0])
 257                die(_("BUG: reopen a lockfile that has been committed"));
 258        lk->fd = open(lk->filename, O_WRONLY);
 259        return lk->fd;
 260}
 261
 262int commit_lock_file(struct lock_file *lk)
 263{
 264        char result_file[PATH_MAX];
 265        size_t i;
 266        if (close_lock_file(lk))
 267                return -1;
 268        strcpy(result_file, lk->filename);
 269        i = strlen(result_file) - 5; /* .lock */
 270        result_file[i] = 0;
 271        if (rename(lk->filename, result_file))
 272                return -1;
 273        lk->filename[0] = 0;
 274        return 0;
 275}
 276
 277int hold_locked_index(struct lock_file *lk, int die_on_error)
 278{
 279        return hold_lock_file_for_update(lk, get_index_file(),
 280                                         die_on_error
 281                                         ? LOCK_DIE_ON_ERROR
 282                                         : 0);
 283}
 284
 285void rollback_lock_file(struct lock_file *lk)
 286{
 287        if (!lk->filename[0])
 288                return;
 289
 290        close_lock_file(lk);
 291        unlink_or_warn(lk->filename);
 292        lk->filename[0] = 0;
 293}