/* Make sure errno contains a meaningful value on error */ static int lock_file(struct lock_file *lk, const char *path, int flags) { size_t pathlen = strlen(path); if (!lock_file_list) { /* One-time initialization */ sigchain_push_common(remove_lock_files_on_signal); atexit(remove_lock_files_on_exit); } if (lk->active) die("BUG: cannot lock_file(\"%s\") using active struct lock_file", path); if (!lk->on_list) { /* Initialize *lk and add it to lock_file_list: */ lk->fd = -1; lk->fp = NULL; lk->active = 0; lk->owner = 0; strbuf_init(&lk->filename, pathlen + LOCK_SUFFIX_LEN); lk->next = lock_file_list; lock_file_list = lk; lk->on_list = 1; } else if (lk->filename.len) { /* This shouldn't happen, but better safe than sorry. */ die("BUG: lock_file(\"%s\") called with improperly-reset lock_file object", path); } if (flags & LOCK_NO_DEREF) { strbuf_add_absolute_path(&lk->filename, path); } else { struct strbuf resolved_path = STRBUF_INIT; strbuf_add(&resolved_path, path, pathlen); resolve_symlink(&resolved_path); strbuf_add_absolute_path(&lk->filename, resolved_path.buf); strbuf_release(&resolved_path); } strbuf_addstr(&lk->filename, LOCK_SUFFIX); lk->fd = open(lk->filename.buf, O_RDWR | O_CREAT | O_EXCL, 0666); if (lk->fd < 0) { strbuf_reset(&lk->filename); return -1; } lk->owner = getpid(); lk->active = 1; if (adjust_shared_perm(lk->filename.buf)) { int save_errno = errno; error("cannot fix permission bits on %s", lk->filename.buf); rollback_lock_file(lk); errno = save_errno; return -1; } return lk->fd; }
static void add_path(struct strbuf *out, const char *path) { if (path && *path) { strbuf_add_absolute_path(out, path); strbuf_addch(out, PATH_SEP); } }
void register_tempfile(struct tempfile *tempfile, const char *path) { prepare_tempfile_object(tempfile); strbuf_add_absolute_path(&tempfile->filename, path); tempfile->owner = getpid(); tempfile->active = 1; }
/* Make sure errno contains a meaningful value on error */ int create_tempfile(struct tempfile *tempfile, const char *path) { prepare_tempfile_object(tempfile); strbuf_add_absolute_path(&tempfile->filename, path); tempfile->fd = open(tempfile->filename.buf, O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC, 0666); if (O_CLOEXEC && tempfile->fd < 0 && errno == EINVAL) /* Try again w/o O_CLOEXEC: the kernel might not support it */ tempfile->fd = open(tempfile->filename.buf, O_RDWR | O_CREAT | O_EXCL, 0666); if (tempfile->fd < 0) { strbuf_reset(&tempfile->filename); return -1; } tempfile->owner = getpid(); tempfile->active = 1; if (adjust_shared_perm(tempfile->filename.buf)) { int save_errno = errno; error("cannot fix permission bits on %s", tempfile->filename.buf); delete_tempfile(tempfile); errno = save_errno; return -1; } return tempfile->fd; }
/* * Use this to get an absolute path from a relative one. If you want * to resolve links, you should use real_path. */ const char *absolute_path(const char *path) { static struct strbuf sb = STRBUF_INIT; strbuf_reset(&sb); strbuf_add_absolute_path(&sb, path); return sb.buf; }
static struct worktree *get_linked_worktree(const char *id) { struct worktree *worktree = NULL; struct strbuf path = STRBUF_INIT; struct strbuf worktree_path = STRBUF_INIT; if (!id) die("Missing linked worktree name"); strbuf_git_common_path(&path, the_repository, "worktrees/%s/gitdir", id); if (strbuf_read_file(&worktree_path, path.buf, 0) <= 0) /* invalid gitdir file */ goto done; strbuf_rtrim(&worktree_path); if (!strbuf_strip_suffix(&worktree_path, "/.git")) { strbuf_reset(&worktree_path); strbuf_add_absolute_path(&worktree_path, "."); strbuf_strip_suffix(&worktree_path, "/."); } strbuf_reset(&path); strbuf_addf(&path, "%s/worktrees/%s/HEAD", get_git_common_dir(), id); worktree = xcalloc(1, sizeof(*worktree)); worktree->path = strbuf_detach(&worktree_path, NULL); worktree->id = xstrdup(id); add_head_info(worktree); done: strbuf_release(&path); strbuf_release(&worktree_path); return worktree; }
/** * get the main worktree */ static struct worktree *get_main_worktree(void) { struct worktree *worktree = NULL; struct strbuf path = STRBUF_INIT; struct strbuf worktree_path = STRBUF_INIT; struct strbuf head_ref = STRBUF_INIT; int is_bare = 0; int is_detached = 0; strbuf_add_absolute_path(&worktree_path, get_git_common_dir()); is_bare = !strbuf_strip_suffix(&worktree_path, "/.git"); if (is_bare) strbuf_strip_suffix(&worktree_path, "/."); strbuf_addf(&path, "%s/HEAD", get_git_common_dir()); worktree = xcalloc(1, sizeof(*worktree)); worktree->path = strbuf_detach(&worktree_path, NULL); worktree->is_bare = is_bare; worktree->is_detached = is_detached; if (!parse_ref(path.buf, &head_ref, &is_detached)) add_head_info(&head_ref, worktree); strbuf_release(&path); strbuf_release(&worktree_path); strbuf_release(&head_ref); return worktree; }
static struct worktree *get_linked_worktree(const char *id) { struct worktree *worktree = NULL; struct strbuf path = STRBUF_INIT; struct strbuf worktree_path = STRBUF_INIT; struct strbuf head_ref = STRBUF_INIT; int is_detached = 0; if (!id) die("Missing linked worktree name"); strbuf_git_common_path(&path, "worktrees/%s/gitdir", id); if (strbuf_read_file(&worktree_path, path.buf, 0) <= 0) /* invalid gitdir file */ goto done; strbuf_rtrim(&worktree_path); if (!strbuf_strip_suffix(&worktree_path, "/.git")) { strbuf_reset(&worktree_path); strbuf_add_absolute_path(&worktree_path, "."); strbuf_strip_suffix(&worktree_path, "/."); } strbuf_reset(&path); strbuf_addf(&path, "%s/worktrees/%s/HEAD", get_git_common_dir(), id); if (parse_ref(path.buf, &head_ref, &is_detached) < 0) goto done; worktree = xmalloc(sizeof(struct worktree)); worktree->path = strbuf_detach(&worktree_path, NULL); worktree->id = xstrdup(id); worktree->is_bare = 0; worktree->head_ref = NULL; worktree->is_detached = is_detached; worktree->is_current = 0; add_head_info(&head_ref, worktree); worktree->lock_reason = NULL; worktree->lock_reason_valid = 0; done: strbuf_release(&path); strbuf_release(&worktree_path); strbuf_release(&head_ref); return worktree; }
/* Make sure errno contains a meaningful value on error */ int create_tempfile(struct tempfile *tempfile, const char *path) { prepare_tempfile_object(tempfile); strbuf_add_absolute_path(&tempfile->filename, path); tempfile->fd = open(tempfile->filename.buf, O_RDWR | O_CREAT | O_EXCL, 0666); if (tempfile->fd < 0) { strbuf_reset(&tempfile->filename); return -1; } tempfile->owner = getpid(); tempfile->active = 1; if (adjust_shared_perm(tempfile->filename.buf)) { int save_errno = errno; error("cannot fix permission bits on %s", tempfile->filename.buf); delete_tempfile(tempfile); errno = save_errno; return -1; } return tempfile->fd; }
/** * get the main worktree */ static struct worktree *get_main_worktree(void) { struct worktree *worktree = NULL; struct strbuf path = STRBUF_INIT; struct strbuf worktree_path = STRBUF_INIT; struct strbuf head_ref = STRBUF_INIT; int is_bare = 0; int is_detached = 0; strbuf_add_absolute_path(&worktree_path, get_git_common_dir()); is_bare = !strbuf_strip_suffix(&worktree_path, "/.git"); if (is_bare) strbuf_strip_suffix(&worktree_path, "/."); strbuf_addf(&path, "%s/HEAD", get_git_common_dir()); if (parse_ref(path.buf, &head_ref, &is_detached) < 0) goto done; worktree = xmalloc(sizeof(struct worktree)); worktree->path = strbuf_detach(&worktree_path, NULL); worktree->id = NULL; worktree->is_bare = is_bare; worktree->head_ref = NULL; worktree->is_detached = is_detached; worktree->is_current = 0; add_head_info(&head_ref, worktree); worktree->lock_reason = NULL; worktree->lock_reason_valid = 0; done: strbuf_release(&path); strbuf_release(&worktree_path); strbuf_release(&head_ref); return worktree; }