lockfile.con commit untracked cache: make a wrapper around {open,read,close}dir() (cf7c614)
   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        if (flags & LOCK_NO_DEREF) {
 132                strbuf_add_absolute_path(&lk->filename, path);
 133        } else {
 134                struct strbuf resolved_path = STRBUF_INIT;
 135
 136                strbuf_add(&resolved_path, path, pathlen);
 137                resolve_symlink(&resolved_path);
 138                strbuf_add_absolute_path(&lk->filename, resolved_path.buf);
 139                strbuf_release(&resolved_path);
 140        }
 141
 142        strbuf_addstr(&lk->filename, LOCK_SUFFIX);
 143        lk->fd = open(lk->filename.buf, O_RDWR | O_CREAT | O_EXCL, 0666);
 144        if (lk->fd < 0) {
 145                strbuf_reset(&lk->filename);
 146                return -1;
 147        }
 148        lk->owner = getpid();
 149        lk->active = 1;
 150        if (adjust_shared_perm(lk->filename.buf)) {
 151                int save_errno = errno;
 152                error("cannot fix permission bits on %s", lk->filename.buf);
 153                rollback_lock_file(lk);
 154                errno = save_errno;
 155                return -1;
 156        }
 157        return lk->fd;
 158}
 159
 160void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
 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                            absolute_path(path), strerror(err));
 168        } else
 169                strbuf_addf(buf, "Unable to create '%s.lock': %s",
 170                            absolute_path(path), strerror(err));
 171}
 172
 173NORETURN void unable_to_lock_die(const char *path, int err)
 174{
 175        struct strbuf buf = STRBUF_INIT;
 176
 177        unable_to_lock_message(path, err, &buf);
 178        die("%s", buf.buf);
 179}
 180
 181/* This should return a meaningful errno on failure */
 182int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
 183{
 184        int fd = lock_file(lk, path, flags);
 185        if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
 186                unable_to_lock_die(path, errno);
 187        return fd;
 188}
 189
 190int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
 191{
 192        int fd, orig_fd;
 193
 194        fd = lock_file(lk, path, flags);
 195        if (fd < 0) {
 196                if (flags & LOCK_DIE_ON_ERROR)
 197                        unable_to_lock_die(path, errno);
 198                return fd;
 199        }
 200
 201        orig_fd = open(path, O_RDONLY);
 202        if (orig_fd < 0) {
 203                if (errno != ENOENT) {
 204                        int save_errno = errno;
 205
 206                        if (flags & LOCK_DIE_ON_ERROR)
 207                                die("cannot open '%s' for copying", path);
 208                        rollback_lock_file(lk);
 209                        error("cannot open '%s' for copying", path);
 210                        errno = save_errno;
 211                        return -1;
 212                }
 213        } else if (copy_fd(orig_fd, fd)) {
 214                int save_errno = errno;
 215
 216                if (flags & LOCK_DIE_ON_ERROR)
 217                        exit(128);
 218                close(orig_fd);
 219                rollback_lock_file(lk);
 220                errno = save_errno;
 221                return -1;
 222        } else {
 223                close(orig_fd);
 224        }
 225        return fd;
 226}
 227
 228FILE *fdopen_lock_file(struct lock_file *lk, const char *mode)
 229{
 230        if (!lk->active)
 231                die("BUG: fdopen_lock_file() called for unlocked object");
 232        if (lk->fp)
 233                die("BUG: fdopen_lock_file() called twice for file '%s'", lk->filename.buf);
 234
 235        lk->fp = fdopen(lk->fd, mode);
 236        return lk->fp;
 237}
 238
 239char *get_locked_file_path(struct lock_file *lk)
 240{
 241        if (!lk->active)
 242                die("BUG: get_locked_file_path() called for unlocked object");
 243        if (lk->filename.len <= LOCK_SUFFIX_LEN)
 244                die("BUG: get_locked_file_path() called for malformed lock object");
 245        return xmemdupz(lk->filename.buf, lk->filename.len - LOCK_SUFFIX_LEN);
 246}
 247
 248int close_lock_file(struct lock_file *lk)
 249{
 250        int fd = lk->fd;
 251        FILE *fp = lk->fp;
 252        int err;
 253
 254        if (fd < 0)
 255                return 0;
 256
 257        lk->fd = -1;
 258        if (fp) {
 259                lk->fp = NULL;
 260
 261                /*
 262                 * Note: no short-circuiting here; we want to fclose()
 263                 * in any case!
 264                 */
 265                err = ferror(fp) | fclose(fp);
 266        } else {
 267                err = close(fd);
 268        }
 269
 270        if (err) {
 271                int save_errno = errno;
 272                rollback_lock_file(lk);
 273                errno = save_errno;
 274                return -1;
 275        }
 276
 277        return 0;
 278}
 279
 280int reopen_lock_file(struct lock_file *lk)
 281{
 282        if (0 <= lk->fd)
 283                die(_("BUG: reopen a lockfile that is still open"));
 284        if (!lk->active)
 285                die(_("BUG: reopen a lockfile that has been committed"));
 286        lk->fd = open(lk->filename.buf, O_WRONLY);
 287        return lk->fd;
 288}
 289
 290int commit_lock_file_to(struct lock_file *lk, const char *path)
 291{
 292        if (!lk->active)
 293                die("BUG: attempt to commit unlocked object to \"%s\"", path);
 294
 295        if (close_lock_file(lk))
 296                return -1;
 297
 298        if (rename(lk->filename.buf, path)) {
 299                int save_errno = errno;
 300                rollback_lock_file(lk);
 301                errno = save_errno;
 302                return -1;
 303        }
 304
 305        lk->active = 0;
 306        strbuf_reset(&lk->filename);
 307        return 0;
 308}
 309
 310int commit_lock_file(struct lock_file *lk)
 311{
 312        static struct strbuf result_file = STRBUF_INIT;
 313        int err;
 314
 315        if (!lk->active)
 316                die("BUG: attempt to commit unlocked object");
 317
 318        if (lk->filename.len <= LOCK_SUFFIX_LEN ||
 319            strcmp(lk->filename.buf + lk->filename.len - LOCK_SUFFIX_LEN, LOCK_SUFFIX))
 320                die("BUG: lockfile filename corrupt");
 321
 322        /* remove ".lock": */
 323        strbuf_add(&result_file, lk->filename.buf,
 324                   lk->filename.len - LOCK_SUFFIX_LEN);
 325        err = commit_lock_file_to(lk, result_file.buf);
 326        strbuf_reset(&result_file);
 327        return err;
 328}
 329
 330void rollback_lock_file(struct lock_file *lk)
 331{
 332        if (!lk->active)
 333                return;
 334
 335        if (!close_lock_file(lk)) {
 336                unlink_or_warn(lk->filename.buf);
 337                lk->active = 0;
 338                strbuf_reset(&lk->filename);
 339        }
 340}