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