lockfile.con commit remote rm/prune: print a message when writing packed-refs fails (2ebb49c)
   1/*
   2 * Copyright (c) 2005, Junio C Hamano
   3 */
   4#include "cache.h"
   5#include "lockfile.h"
   6#include "sigchain.h"
   7
   8static struct lock_file *volatile lock_file_list;
   9
  10static void remove_lock_files(int skip_fclose)
  11{
  12        pid_t me = getpid();
  13
  14        while (lock_file_list) {
  15                if (lock_file_list->owner == me) {
  16                        /* fclose() is not safe to call in a signal handler */
  17                        if (skip_fclose)
  18                                lock_file_list->fp = NULL;
  19                        rollback_lock_file(lock_file_list);
  20                }
  21                lock_file_list = lock_file_list->next;
  22        }
  23}
  24
  25static void remove_lock_files_on_exit(void)
  26{
  27        remove_lock_files(0);
  28}
  29
  30static void remove_lock_files_on_signal(int signo)
  31{
  32        remove_lock_files(1);
  33        sigchain_pop(signo);
  34        raise(signo);
  35}
  36
  37/*
  38 * path = absolute or relative path name
  39 *
  40 * Remove the last path name element from path (leaving the preceding
  41 * "/", if any).  If path is empty or the root directory ("/"), set
  42 * path to the empty string.
  43 */
  44static void trim_last_path_component(struct strbuf *path)
  45{
  46        int i = path->len;
  47
  48        /* back up past trailing slashes, if any */
  49        while (i && path->buf[i - 1] == '/')
  50                i--;
  51
  52        /*
  53         * then go backwards until a slash, or the beginning of the
  54         * string
  55         */
  56        while (i && path->buf[i - 1] != '/')
  57                i--;
  58
  59        strbuf_setlen(path, i);
  60}
  61
  62
  63/* We allow "recursive" symbolic links. Only within reason, though */
  64#define MAXDEPTH 5
  65
  66/*
  67 * path contains a path that might be a symlink.
  68 *
  69 * If path is a symlink, attempt to overwrite it with a path to the
  70 * real file or directory (which may or may not exist), following a
  71 * chain of symlinks if necessary.  Otherwise, leave path unmodified.
  72 *
  73 * This is a best-effort routine.  If an error occurs, path will
  74 * either be left unmodified or will name a different symlink in a
  75 * symlink chain that started with the original path.
  76 */
  77static void resolve_symlink(struct strbuf *path)
  78{
  79        int depth = MAXDEPTH;
  80        static struct strbuf link = STRBUF_INIT;
  81
  82        while (depth--) {
  83                if (strbuf_readlink(&link, path->buf, path->len) < 0)
  84                        break;
  85
  86                if (is_absolute_path(link.buf))
  87                        /* absolute path simply replaces p */
  88                        strbuf_reset(path);
  89                else
  90                        /*
  91                         * link is a relative path, so replace the
  92                         * last element of p with it.
  93                         */
  94                        trim_last_path_component(path);
  95
  96                strbuf_addbuf(path, &link);
  97        }
  98        strbuf_reset(&link);
  99}
 100
 101/* Make sure errno contains a meaningful value on error */
 102static int lock_file(struct lock_file *lk, const char *path, int flags)
 103{
 104        size_t pathlen = strlen(path);
 105
 106        if (!lock_file_list) {
 107                /* One-time initialization */
 108                sigchain_push_common(remove_lock_files_on_signal);
 109                atexit(remove_lock_files_on_exit);
 110        }
 111
 112        if (lk->active)
 113                die("BUG: cannot lock_file(\"%s\") using active struct lock_file",
 114                    path);
 115        if (!lk->on_list) {
 116                /* Initialize *lk and add it to lock_file_list: */
 117                lk->fd = -1;
 118                lk->fp = NULL;
 119                lk->active = 0;
 120                lk->owner = 0;
 121                strbuf_init(&lk->filename, pathlen + LOCK_SUFFIX_LEN);
 122                lk->next = lock_file_list;
 123                lock_file_list = lk;
 124                lk->on_list = 1;
 125        } else if (lk->filename.len) {
 126                /* This shouldn't happen, but better safe than sorry. */
 127                die("BUG: lock_file(\"%s\") called with improperly-reset lock_file object",
 128                    path);
 129        }
 130
 131        strbuf_add(&lk->filename, path, pathlen);
 132        if (!(flags & LOCK_NO_DEREF))
 133                resolve_symlink(&lk->filename);
 134        strbuf_addstr(&lk->filename, LOCK_SUFFIX);
 135        lk->fd = open(lk->filename.buf, O_RDWR | O_CREAT | O_EXCL, 0666);
 136        if (lk->fd < 0) {
 137                strbuf_reset(&lk->filename);
 138                return -1;
 139        }
 140        lk->owner = getpid();
 141        lk->active = 1;
 142        if (adjust_shared_perm(lk->filename.buf)) {
 143                int save_errno = errno;
 144                error("cannot fix permission bits on %s", lk->filename.buf);
 145                rollback_lock_file(lk);
 146                errno = save_errno;
 147                return -1;
 148        }
 149        return lk->fd;
 150}
 151
 152void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
 153{
 154        if (err == EEXIST) {
 155                strbuf_addf(buf, "Unable to create '%s.lock': %s.\n\n"
 156                    "If no other git process is currently running, this probably means a\n"
 157                    "git process crashed in this repository earlier. Make sure no other git\n"
 158                    "process is running and remove the file manually to continue.",
 159                            absolute_path(path), strerror(err));
 160        } else
 161                strbuf_addf(buf, "Unable to create '%s.lock': %s",
 162                            absolute_path(path), strerror(err));
 163}
 164
 165int unable_to_lock_error(const char *path, int err)
 166{
 167        struct strbuf buf = STRBUF_INIT;
 168
 169        unable_to_lock_message(path, err, &buf);
 170        error("%s", buf.buf);
 171        strbuf_release(&buf);
 172        return -1;
 173}
 174
 175NORETURN void unable_to_lock_die(const char *path, int err)
 176{
 177        struct strbuf buf = STRBUF_INIT;
 178
 179        unable_to_lock_message(path, err, &buf);
 180        die("%s", buf.buf);
 181}
 182
 183/* This should return a meaningful errno on failure */
 184int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
 185{
 186        int fd = lock_file(lk, path, flags);
 187        if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
 188                unable_to_lock_die(path, errno);
 189        return fd;
 190}
 191
 192int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
 193{
 194        int fd, orig_fd;
 195
 196        fd = lock_file(lk, path, flags);
 197        if (fd < 0) {
 198                if (flags & LOCK_DIE_ON_ERROR)
 199                        unable_to_lock_die(path, errno);
 200                return fd;
 201        }
 202
 203        orig_fd = open(path, O_RDONLY);
 204        if (orig_fd < 0) {
 205                if (errno != ENOENT) {
 206                        int save_errno = errno;
 207
 208                        if (flags & LOCK_DIE_ON_ERROR)
 209                                die("cannot open '%s' for copying", path);
 210                        rollback_lock_file(lk);
 211                        error("cannot open '%s' for copying", path);
 212                        errno = save_errno;
 213                        return -1;
 214                }
 215        } else if (copy_fd(orig_fd, fd)) {
 216                int save_errno = errno;
 217
 218                if (flags & LOCK_DIE_ON_ERROR)
 219                        exit(128);
 220                close(orig_fd);
 221                rollback_lock_file(lk);
 222                errno = save_errno;
 223                return -1;
 224        } else {
 225                close(orig_fd);
 226        }
 227        return fd;
 228}
 229
 230FILE *fdopen_lock_file(struct lock_file *lk, const char *mode)
 231{
 232        if (!lk->active)
 233                die("BUG: fdopen_lock_file() called for unlocked object");
 234        if (lk->fp)
 235                die("BUG: fdopen_lock_file() called twice for file '%s'", lk->filename.buf);
 236
 237        lk->fp = fdopen(lk->fd, mode);
 238        return lk->fp;
 239}
 240
 241char *get_locked_file_path(struct lock_file *lk)
 242{
 243        if (!lk->active)
 244                die("BUG: get_locked_file_path() called for unlocked object");
 245        if (lk->filename.len <= LOCK_SUFFIX_LEN)
 246                die("BUG: get_locked_file_path() called for malformed lock object");
 247        return xmemdupz(lk->filename.buf, lk->filename.len - LOCK_SUFFIX_LEN);
 248}
 249
 250int close_lock_file(struct lock_file *lk)
 251{
 252        int fd = lk->fd;
 253        FILE *fp = lk->fp;
 254        int err;
 255
 256        if (fd < 0)
 257                return 0;
 258
 259        lk->fd = -1;
 260        if (fp) {
 261                lk->fp = NULL;
 262
 263                /*
 264                 * Note: no short-circuiting here; we want to fclose()
 265                 * in any case!
 266                 */
 267                err = ferror(fp) | fclose(fp);
 268        } else {
 269                err = close(fd);
 270        }
 271
 272        if (err) {
 273                int save_errno = errno;
 274                rollback_lock_file(lk);
 275                errno = save_errno;
 276                return -1;
 277        }
 278
 279        return 0;
 280}
 281
 282int reopen_lock_file(struct lock_file *lk)
 283{
 284        if (0 <= lk->fd)
 285                die(_("BUG: reopen a lockfile that is still open"));
 286        if (!lk->active)
 287                die(_("BUG: reopen a lockfile that has been committed"));
 288        lk->fd = open(lk->filename.buf, O_WRONLY);
 289        return lk->fd;
 290}
 291
 292int commit_lock_file_to(struct lock_file *lk, const char *path)
 293{
 294        if (!lk->active)
 295                die("BUG: attempt to commit unlocked object to \"%s\"", path);
 296
 297        if (close_lock_file(lk))
 298                return -1;
 299
 300        if (rename(lk->filename.buf, path)) {
 301                int save_errno = errno;
 302                rollback_lock_file(lk);
 303                errno = save_errno;
 304                return -1;
 305        }
 306
 307        lk->active = 0;
 308        strbuf_reset(&lk->filename);
 309        return 0;
 310}
 311
 312int commit_lock_file(struct lock_file *lk)
 313{
 314        static struct strbuf result_file = STRBUF_INIT;
 315        int err;
 316
 317        if (!lk->active)
 318                die("BUG: attempt to commit unlocked object");
 319
 320        if (lk->filename.len <= LOCK_SUFFIX_LEN ||
 321            strcmp(lk->filename.buf + lk->filename.len - LOCK_SUFFIX_LEN, LOCK_SUFFIX))
 322                die("BUG: lockfile filename corrupt");
 323
 324        /* remove ".lock": */
 325        strbuf_add(&result_file, lk->filename.buf,
 326                   lk->filename.len - LOCK_SUFFIX_LEN);
 327        err = commit_lock_file_to(lk, result_file.buf);
 328        strbuf_reset(&result_file);
 329        return err;
 330}
 331
 332void rollback_lock_file(struct lock_file *lk)
 333{
 334        if (!lk->active)
 335                return;
 336
 337        if (!close_lock_file(lk)) {
 338                unlink_or_warn(lk->filename.buf);
 339                lk->active = 0;
 340                strbuf_reset(&lk->filename);
 341        }
 342}