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