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