lockfile.con commit Merge branch 'maint-1.6.0' into maint-1.6.1 (4258c21)
   1/*
   2 * Copyright (c) 2005, Junio C Hamano
   3 */
   4#include "cache.h"
   5
   6static struct lock_file *lock_file_list;
   7static const char *alternate_index_output;
   8
   9static void remove_lock_file(void)
  10{
  11        pid_t me = getpid();
  12
  13        while (lock_file_list) {
  14                if (lock_file_list->owner == me &&
  15                    lock_file_list->filename[0]) {
  16                        if (lock_file_list->fd >= 0)
  17                                close(lock_file_list->fd);
  18                        unlink(lock_file_list->filename);
  19                }
  20                lock_file_list = lock_file_list->next;
  21        }
  22}
  23
  24static void remove_lock_file_on_signal(int signo)
  25{
  26        remove_lock_file();
  27        signal(signo, SIG_DFL);
  28        raise(signo);
  29}
  30
  31/*
  32 * p = absolute or relative path name
  33 *
  34 * Return a pointer into p showing the beginning of the last path name
  35 * element.  If p is empty or the root directory ("/"), just return p.
  36 */
  37static char *last_path_elm(char *p)
  38{
  39        /* r starts pointing to null at the end of the string */
  40        char *r = strchr(p, '\0');
  41
  42        if (r == p)
  43                return p; /* just return empty string */
  44
  45        r--; /* back up to last non-null character */
  46
  47        /* back up past trailing slashes, if any */
  48        while (r > p && *r == '/')
  49                r--;
  50
  51        /*
  52         * then go backwards until I hit a slash, or the beginning of
  53         * the string
  54         */
  55        while (r > p && *(r-1) != '/')
  56                r--;
  57        return r;
  58}
  59
  60
  61/* We allow "recursive" symbolic links. Only within reason, though */
  62#define MAXDEPTH 5
  63
  64/*
  65 * p = path that may be a symlink
  66 * s = full size of p
  67 *
  68 * If p is a symlink, attempt to overwrite p with a path to the real
  69 * file or directory (which may or may not exist), following a chain of
  70 * symlinks if necessary.  Otherwise, leave p unmodified.
  71 *
  72 * This is a best-effort routine.  If an error occurs, p will either be
  73 * left unmodified or will name a different symlink in a symlink chain
  74 * that started with p's initial contents.
  75 *
  76 * Always returns p.
  77 */
  78
  79static char *resolve_symlink(char *p, size_t s)
  80{
  81        int depth = MAXDEPTH;
  82
  83        while (depth--) {
  84                char link[PATH_MAX];
  85                int link_len = readlink(p, link, sizeof(link));
  86                if (link_len < 0) {
  87                        /* not a symlink anymore */
  88                        return p;
  89                }
  90                else if (link_len < sizeof(link))
  91                        /* readlink() never null-terminates */
  92                        link[link_len] = '\0';
  93                else {
  94                        warning("%s: symlink too long", p);
  95                        return p;
  96                }
  97
  98                if (is_absolute_path(link)) {
  99                        /* absolute path simply replaces p */
 100                        if (link_len < s)
 101                                strcpy(p, link);
 102                        else {
 103                                warning("%s: symlink too long", p);
 104                                return p;
 105                        }
 106                } else {
 107                        /*
 108                         * link is a relative path, so I must replace the
 109                         * last element of p with it.
 110                         */
 111                        char *r = (char*)last_path_elm(p);
 112                        if (r - p + link_len < s)
 113                                strcpy(r, link);
 114                        else {
 115                                warning("%s: symlink too long", p);
 116                                return p;
 117                        }
 118                }
 119        }
 120        return p;
 121}
 122
 123
 124static int lock_file(struct lock_file *lk, const char *path, int flags)
 125{
 126        if (strlen(path) >= sizeof(lk->filename))
 127                return -1;
 128        strcpy(lk->filename, path);
 129        /*
 130         * subtract 5 from size to make sure there's room for adding
 131         * ".lock" for the lock file name
 132         */
 133        if (!(flags & LOCK_NODEREF))
 134                resolve_symlink(lk->filename, sizeof(lk->filename)-5);
 135        strcat(lk->filename, ".lock");
 136        lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
 137        if (0 <= lk->fd) {
 138                if (!lock_file_list) {
 139                        signal(SIGINT, remove_lock_file_on_signal);
 140                        signal(SIGHUP, remove_lock_file_on_signal);
 141                        signal(SIGTERM, remove_lock_file_on_signal);
 142                        signal(SIGQUIT, remove_lock_file_on_signal);
 143                        signal(SIGPIPE, remove_lock_file_on_signal);
 144                        atexit(remove_lock_file);
 145                }
 146                lk->owner = getpid();
 147                if (!lk->on_list) {
 148                        lk->next = lock_file_list;
 149                        lock_file_list = lk;
 150                        lk->on_list = 1;
 151                }
 152                if (adjust_shared_perm(lk->filename))
 153                        return error("cannot fix permission bits on %s",
 154                                     lk->filename);
 155        }
 156        else
 157                lk->filename[0] = 0;
 158        return lk->fd;
 159}
 160
 161
 162NORETURN void unable_to_lock_index_die(const char *path, int err)
 163{
 164        if (errno == EEXIST) {
 165                die("Unable to create '%s.lock': %s.\n\n"
 166                    "If no other git process is currently running, this probably means a\n"
 167                    "git process crashed in this repository earlier. Make sure no other git\n"
 168                    "process is running and remove the file manually to continue.",
 169                    path, strerror(err));
 170        } else {
 171                die("Unable to create '%s.lock': %s", path, strerror(err));
 172        }
 173}
 174
 175int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
 176{
 177        int fd = lock_file(lk, path, flags);
 178        if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
 179                unable_to_lock_index_die(path, errno);
 180        return fd;
 181}
 182
 183int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
 184{
 185        int fd, orig_fd;
 186
 187        fd = lock_file(lk, path, flags);
 188        if (fd < 0) {
 189                if (flags & LOCK_DIE_ON_ERROR)
 190                        die("unable to create '%s.lock': %s", path, strerror(errno));
 191                return fd;
 192        }
 193
 194        orig_fd = open(path, O_RDONLY);
 195        if (orig_fd < 0) {
 196                if (errno != ENOENT) {
 197                        if (flags & LOCK_DIE_ON_ERROR)
 198                                die("cannot open '%s' for copying", path);
 199                        close(fd);
 200                        return error("cannot open '%s' for copying", path);
 201                }
 202        } else if (copy_fd(orig_fd, fd)) {
 203                if (flags & LOCK_DIE_ON_ERROR)
 204                        exit(128);
 205                close(fd);
 206                return -1;
 207        }
 208        return fd;
 209}
 210
 211int close_lock_file(struct lock_file *lk)
 212{
 213        int fd = lk->fd;
 214        lk->fd = -1;
 215        return close(fd);
 216}
 217
 218int commit_lock_file(struct lock_file *lk)
 219{
 220        char result_file[PATH_MAX];
 221        size_t i;
 222        if (lk->fd >= 0 && close_lock_file(lk))
 223                return -1;
 224        strcpy(result_file, lk->filename);
 225        i = strlen(result_file) - 5; /* .lock */
 226        result_file[i] = 0;
 227        if (rename(lk->filename, result_file))
 228                return -1;
 229        lk->filename[0] = 0;
 230        return 0;
 231}
 232
 233int hold_locked_index(struct lock_file *lk, int die_on_error)
 234{
 235        return hold_lock_file_for_update(lk, get_index_file(),
 236                                         die_on_error
 237                                         ? LOCK_DIE_ON_ERROR
 238                                         : 0);
 239}
 240
 241void set_alternate_index_output(const char *name)
 242{
 243        alternate_index_output = name;
 244}
 245
 246int commit_locked_index(struct lock_file *lk)
 247{
 248        if (alternate_index_output) {
 249                if (lk->fd >= 0 && close_lock_file(lk))
 250                        return -1;
 251                if (rename(lk->filename, alternate_index_output))
 252                        return -1;
 253                lk->filename[0] = 0;
 254                return 0;
 255        }
 256        else
 257                return commit_lock_file(lk);
 258}
 259
 260void rollback_lock_file(struct lock_file *lk)
 261{
 262        if (lk->filename[0]) {
 263                if (lk->fd >= 0)
 264                        close(lk->fd);
 265                unlink(lk->filename);
 266        }
 267        lk->filename[0] = 0;
 268}