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