lockfile.con commit t7501-commit.sh: explicitly check that -F prevents invoking the editor (7eb5bbd)
   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
 161int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
 162{
 163        int fd = lock_file(lk, path, flags);
 164        if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
 165                die("unable to create '%s.lock': %s", path, strerror(errno));
 166        return fd;
 167}
 168
 169int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
 170{
 171        int fd, orig_fd;
 172
 173        fd = lock_file(lk, path, flags);
 174        if (fd < 0) {
 175                if (flags & LOCK_DIE_ON_ERROR)
 176                        die("unable to create '%s.lock': %s", path, strerror(errno));
 177                return fd;
 178        }
 179
 180        orig_fd = open(path, O_RDONLY);
 181        if (orig_fd < 0) {
 182                if (errno != ENOENT) {
 183                        if (flags & LOCK_DIE_ON_ERROR)
 184                                die("cannot open '%s' for copying", path);
 185                        close(fd);
 186                        return error("cannot open '%s' for copying", path);
 187                }
 188        } else if (copy_fd(orig_fd, fd)) {
 189                if (flags & LOCK_DIE_ON_ERROR)
 190                        exit(128);
 191                close(fd);
 192                return -1;
 193        }
 194        return fd;
 195}
 196
 197int close_lock_file(struct lock_file *lk)
 198{
 199        int fd = lk->fd;
 200        lk->fd = -1;
 201        return close(fd);
 202}
 203
 204int commit_lock_file(struct lock_file *lk)
 205{
 206        char result_file[PATH_MAX];
 207        size_t i;
 208        if (lk->fd >= 0 && close_lock_file(lk))
 209                return -1;
 210        strcpy(result_file, lk->filename);
 211        i = strlen(result_file) - 5; /* .lock */
 212        result_file[i] = 0;
 213        if (rename(lk->filename, result_file))
 214                return -1;
 215        lk->filename[0] = 0;
 216        return 0;
 217}
 218
 219int hold_locked_index(struct lock_file *lk, int die_on_error)
 220{
 221        return hold_lock_file_for_update(lk, get_index_file(),
 222                                         die_on_error
 223                                         ? LOCK_DIE_ON_ERROR
 224                                         : 0);
 225}
 226
 227void set_alternate_index_output(const char *name)
 228{
 229        alternate_index_output = name;
 230}
 231
 232int commit_locked_index(struct lock_file *lk)
 233{
 234        if (alternate_index_output) {
 235                if (lk->fd >= 0 && close_lock_file(lk))
 236                        return -1;
 237                if (rename(lk->filename, alternate_index_output))
 238                        return -1;
 239                lk->filename[0] = 0;
 240                return 0;
 241        }
 242        else
 243                return commit_lock_file(lk);
 244}
 245
 246void rollback_lock_file(struct lock_file *lk)
 247{
 248        if (lk->filename[0]) {
 249                if (lk->fd >= 0)
 250                        close(lk->fd);
 251                unlink(lk->filename);
 252        }
 253        lk->filename[0] = 0;
 254}