lockfile.con commit t3418: non-interactive rebase --continue with rerere enabled (0f62fba)
   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
 160/*
 161 * Constants defining the gaps between attempts to lock a file. The
 162 * first backoff period is approximately INITIAL_BACKOFF_MS
 163 * milliseconds. The longest backoff period is approximately
 164 * (BACKOFF_MAX_MULTIPLIER * INITIAL_BACKOFF_MS) milliseconds.
 165 */
 166#define INITIAL_BACKOFF_MS 1L
 167#define BACKOFF_MAX_MULTIPLIER 1000
 168
 169/*
 170 * Try locking path, retrying with quadratic backoff for at least
 171 * timeout_ms milliseconds. If timeout_ms is 0, try locking the file
 172 * exactly once. If timeout_ms is -1, try indefinitely.
 173 */
 174static int lock_file_timeout(struct lock_file *lk, const char *path,
 175                             int flags, long timeout_ms)
 176{
 177        int n = 1;
 178        int multiplier = 1;
 179        long remaining_ms = 0;
 180        static int random_initialized = 0;
 181
 182        if (timeout_ms == 0)
 183                return lock_file(lk, path, flags);
 184
 185        if (!random_initialized) {
 186                srand((unsigned int)getpid());
 187                random_initialized = 1;
 188        }
 189
 190        if (timeout_ms > 0)
 191                remaining_ms = timeout_ms;
 192
 193        while (1) {
 194                long backoff_ms, wait_ms;
 195                int fd;
 196
 197                fd = lock_file(lk, path, flags);
 198
 199                if (fd >= 0)
 200                        return fd; /* success */
 201                else if (errno != EEXIST)
 202                        return -1; /* failure other than lock held */
 203                else if (timeout_ms > 0 && remaining_ms <= 0)
 204                        return -1; /* failure due to timeout */
 205
 206                backoff_ms = multiplier * INITIAL_BACKOFF_MS;
 207                /* back off for between 0.75*backoff_ms and 1.25*backoff_ms */
 208                wait_ms = (750 + rand() % 500) * backoff_ms / 1000;
 209                sleep_millisec(wait_ms);
 210                remaining_ms -= wait_ms;
 211
 212                /* Recursion: (n+1)^2 = n^2 + 2n + 1 */
 213                multiplier += 2*n + 1;
 214                if (multiplier > BACKOFF_MAX_MULTIPLIER)
 215                        multiplier = BACKOFF_MAX_MULTIPLIER;
 216                else
 217                        n++;
 218        }
 219}
 220
 221void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
 222{
 223        if (err == EEXIST) {
 224                strbuf_addf(buf, "Unable to create '%s.lock': %s.\n\n"
 225                    "If no other git process is currently running, this probably means a\n"
 226                    "git process crashed in this repository earlier. Make sure no other git\n"
 227                    "process is running and remove the file manually to continue.",
 228                            absolute_path(path), strerror(err));
 229        } else
 230                strbuf_addf(buf, "Unable to create '%s.lock': %s",
 231                            absolute_path(path), strerror(err));
 232}
 233
 234NORETURN void unable_to_lock_die(const char *path, int err)
 235{
 236        struct strbuf buf = STRBUF_INIT;
 237
 238        unable_to_lock_message(path, err, &buf);
 239        die("%s", buf.buf);
 240}
 241
 242/* This should return a meaningful errno on failure */
 243int hold_lock_file_for_update_timeout(struct lock_file *lk, const char *path,
 244                                      int flags, long timeout_ms)
 245{
 246        int fd = lock_file_timeout(lk, path, flags, timeout_ms);
 247        if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
 248                unable_to_lock_die(path, errno);
 249        return fd;
 250}
 251
 252int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
 253{
 254        int fd, orig_fd;
 255
 256        fd = lock_file(lk, path, flags);
 257        if (fd < 0) {
 258                if (flags & LOCK_DIE_ON_ERROR)
 259                        unable_to_lock_die(path, errno);
 260                return fd;
 261        }
 262
 263        orig_fd = open(path, O_RDONLY);
 264        if (orig_fd < 0) {
 265                if (errno != ENOENT) {
 266                        int save_errno = errno;
 267
 268                        if (flags & LOCK_DIE_ON_ERROR)
 269                                die("cannot open '%s' for copying", path);
 270                        rollback_lock_file(lk);
 271                        error("cannot open '%s' for copying", path);
 272                        errno = save_errno;
 273                        return -1;
 274                }
 275        } else if (copy_fd(orig_fd, fd)) {
 276                int save_errno = errno;
 277
 278                if (flags & LOCK_DIE_ON_ERROR)
 279                        die("failed to prepare '%s' for appending", path);
 280                close(orig_fd);
 281                rollback_lock_file(lk);
 282                errno = save_errno;
 283                return -1;
 284        } else {
 285                close(orig_fd);
 286        }
 287        return fd;
 288}
 289
 290FILE *fdopen_lock_file(struct lock_file *lk, const char *mode)
 291{
 292        if (!lk->active)
 293                die("BUG: fdopen_lock_file() called for unlocked object");
 294        if (lk->fp)
 295                die("BUG: fdopen_lock_file() called twice for file '%s'", lk->filename.buf);
 296
 297        lk->fp = fdopen(lk->fd, mode);
 298        return lk->fp;
 299}
 300
 301char *get_locked_file_path(struct lock_file *lk)
 302{
 303        if (!lk->active)
 304                die("BUG: get_locked_file_path() called for unlocked object");
 305        if (lk->filename.len <= LOCK_SUFFIX_LEN)
 306                die("BUG: get_locked_file_path() called for malformed lock object");
 307        return xmemdupz(lk->filename.buf, lk->filename.len - LOCK_SUFFIX_LEN);
 308}
 309
 310int close_lock_file(struct lock_file *lk)
 311{
 312        int fd = lk->fd;
 313        FILE *fp = lk->fp;
 314        int err;
 315
 316        if (fd < 0)
 317                return 0;
 318
 319        lk->fd = -1;
 320        if (fp) {
 321                lk->fp = NULL;
 322
 323                /*
 324                 * Note: no short-circuiting here; we want to fclose()
 325                 * in any case!
 326                 */
 327                err = ferror(fp) | fclose(fp);
 328        } else {
 329                err = close(fd);
 330        }
 331
 332        if (err) {
 333                int save_errno = errno;
 334                rollback_lock_file(lk);
 335                errno = save_errno;
 336                return -1;
 337        }
 338
 339        return 0;
 340}
 341
 342int reopen_lock_file(struct lock_file *lk)
 343{
 344        if (0 <= lk->fd)
 345                die(_("BUG: reopen a lockfile that is still open"));
 346        if (!lk->active)
 347                die(_("BUG: reopen a lockfile that has been committed"));
 348        lk->fd = open(lk->filename.buf, O_WRONLY);
 349        return lk->fd;
 350}
 351
 352int commit_lock_file_to(struct lock_file *lk, const char *path)
 353{
 354        if (!lk->active)
 355                die("BUG: attempt to commit unlocked object to \"%s\"", path);
 356
 357        if (close_lock_file(lk))
 358                return -1;
 359
 360        if (rename(lk->filename.buf, path)) {
 361                int save_errno = errno;
 362                rollback_lock_file(lk);
 363                errno = save_errno;
 364                return -1;
 365        }
 366
 367        lk->active = 0;
 368        strbuf_reset(&lk->filename);
 369        return 0;
 370}
 371
 372int commit_lock_file(struct lock_file *lk)
 373{
 374        static struct strbuf result_file = STRBUF_INIT;
 375        int err;
 376
 377        if (!lk->active)
 378                die("BUG: attempt to commit unlocked object");
 379
 380        if (lk->filename.len <= LOCK_SUFFIX_LEN ||
 381            strcmp(lk->filename.buf + lk->filename.len - LOCK_SUFFIX_LEN, LOCK_SUFFIX))
 382                die("BUG: lockfile filename corrupt");
 383
 384        /* remove ".lock": */
 385        strbuf_add(&result_file, lk->filename.buf,
 386                   lk->filename.len - LOCK_SUFFIX_LEN);
 387        err = commit_lock_file_to(lk, result_file.buf);
 388        strbuf_reset(&result_file);
 389        return err;
 390}
 391
 392void rollback_lock_file(struct lock_file *lk)
 393{
 394        if (!lk->active)
 395                return;
 396
 397        if (!close_lock_file(lk)) {
 398                unlink_or_warn(lk->filename.buf);
 399                lk->active = 0;
 400                strbuf_reset(&lk->filename);
 401        }
 402}