THIS IS A TEST INSTANCE ONLY! REPOSITORIES CAN BE DELETED AT ANY TIME!

Browse Source

Merge branch 'rs/strbuf-getcwd'

Reduce the use of fixed sized buffer passed to getcwd() calls
by introducing xgetcwd() helper.

* rs/strbuf-getcwd:
  use strbuf_add_absolute_path() to add absolute paths
  abspath: convert absolute_path() to strbuf
  use xgetcwd() to set $GIT_DIR
  use xgetcwd() to get the current directory or die
  wrapper: add xgetcwd()
  abspath: convert real_path_internal() to strbuf
  abspath: use strbuf_getcwd() to remember original working directory
  setup: convert setup_git_directory_gently_1 et al. to strbuf
  unix-sockets: use strbuf_getcwd()
  strbuf: add strbuf_getcwd()
tags/v2.2.0-rc0
Junio C Hamano 5 years ago
parent
commit
f655651e09
15 changed files with 191 additions and 178 deletions
  1. +10
    -0
      Documentation/technical/api-strbuf.txt
  2. +34
    -90
      abspath.c
  3. +11
    -13
      builtin/init-db.c
  4. +3
    -3
      builtin/rev-parse.c
  5. +8
    -4
      dir.c
  6. +1
    -5
      exec_cmd.c
  7. +1
    -0
      git-compat-util.h
  8. +7
    -6
      git.c
  9. +47
    -46
      setup.c
  10. +1
    -1
      sha1_file.c
  11. +46
    -0
      strbuf.c
  12. +3
    -0
      strbuf.h
  13. +4
    -3
      trace.c
  14. +7
    -7
      unix-socket.c
  15. +8
    -0
      wrapper.c

+ 10
- 0
Documentation/technical/api-strbuf.txt View File

@@ -307,6 +307,16 @@ same behaviour as well.
use it unless you need the correct position in the file
descriptor.

`strbuf_getcwd`::

Set the buffer to the path of the current working directory.

`strbuf_add_absolute_path`

Add a path to a buffer, converting a relative path to an
absolute one in the process. Symbolic links are not
resolved.

`stripspace`::

Strip whitespace from a buffer. The second parameter controls if

+ 34
- 90
abspath.c View File

@@ -33,7 +33,7 @@ int is_directory(const char *path)
*/
static const char *real_path_internal(const char *path, int die_on_error)
{
static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
static struct strbuf sb = STRBUF_INIT;
char *retval = NULL;

/*
@@ -41,16 +41,14 @@ static const char *real_path_internal(const char *path, int die_on_error)
* here so that we can chdir() back to it at the end of the
* function:
*/
char cwd[1024] = "";

int buf_index = 1;
struct strbuf cwd = STRBUF_INIT;

int depth = MAXDEPTH;
char *last_elem = NULL;
struct stat st;

/* We've already done it */
if (path == buf || path == next_buf)
if (path == sb.buf)
return path;

if (!*path) {
@@ -60,41 +58,38 @@ static const char *real_path_internal(const char *path, int die_on_error)
goto error_out;
}

if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX) {
if (die_on_error)
die("Too long path: %.*s", 60, path);
else
goto error_out;
}
strbuf_reset(&sb);
strbuf_addstr(&sb, path);

while (depth--) {
if (!is_directory(buf)) {
char *last_slash = find_last_dir_sep(buf);
if (!is_directory(sb.buf)) {
char *last_slash = find_last_dir_sep(sb.buf);
if (last_slash) {
last_elem = xstrdup(last_slash + 1);
last_slash[1] = '\0';
strbuf_setlen(&sb, last_slash - sb.buf + 1);
} else {
last_elem = xstrdup(buf);
*buf = '\0';
last_elem = xmemdupz(sb.buf, sb.len);
strbuf_reset(&sb);
}
}

if (*buf) {
if (!*cwd && !getcwd(cwd, sizeof(cwd))) {
if (sb.len) {
if (!cwd.len && strbuf_getcwd(&cwd)) {
if (die_on_error)
die_errno("Could not get current working directory");
else
goto error_out;
}

if (chdir(buf)) {
if (chdir(sb.buf)) {
if (die_on_error)
die_errno("Could not switch to '%s'", buf);
die_errno("Could not switch to '%s'",
sb.buf);
else
goto error_out;
}
}
if (!getcwd(buf, PATH_MAX)) {
if (strbuf_getcwd(&sb)) {
if (die_on_error)
die_errno("Could not get current working directory");
else
@@ -102,48 +97,35 @@ static const char *real_path_internal(const char *path, int die_on_error)
}

if (last_elem) {
size_t len = strlen(buf);
if (len + strlen(last_elem) + 2 > PATH_MAX) {
if (die_on_error)
die("Too long path name: '%s/%s'",
buf, last_elem);
else
goto error_out;
}
if (len && !is_dir_sep(buf[len - 1]))
buf[len++] = '/';
strcpy(buf + len, last_elem);
if (sb.len && !is_dir_sep(sb.buf[sb.len - 1]))
strbuf_addch(&sb, '/');
strbuf_addstr(&sb, last_elem);
free(last_elem);
last_elem = NULL;
}

if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
ssize_t len = readlink(buf, next_buf, PATH_MAX);
if (!lstat(sb.buf, &st) && S_ISLNK(st.st_mode)) {
struct strbuf next_sb = STRBUF_INIT;
ssize_t len = strbuf_readlink(&next_sb, sb.buf, 0);
if (len < 0) {
if (die_on_error)
die_errno("Invalid symlink '%s'", buf);
else
goto error_out;
}
if (PATH_MAX <= len) {
if (die_on_error)
die("symbolic link too long: %s", buf);
die_errno("Invalid symlink '%s'",
sb.buf);
else
goto error_out;
}
next_buf[len] = '\0';
buf = next_buf;
buf_index = 1 - buf_index;
next_buf = bufs[buf_index];
strbuf_swap(&sb, &next_sb);
strbuf_release(&next_sb);
} else
break;
}

retval = buf;
retval = sb.buf;
error_out:
free(last_elem);
if (*cwd && chdir(cwd))
die_errno("Could not change back to '%s'", cwd);
if (cwd.len && chdir(cwd.buf))
die_errno("Could not change back to '%s'", cwd.buf);
strbuf_release(&cwd);

return retval;
}
@@ -158,54 +140,16 @@ const char *real_path_if_valid(const char *path)
return real_path_internal(path, 0);
}

static const char *get_pwd_cwd(void)
{
static char cwd[PATH_MAX + 1];
char *pwd;
struct stat cwd_stat, pwd_stat;
if (getcwd(cwd, PATH_MAX) == NULL)
return NULL;
pwd = getenv("PWD");
if (pwd && strcmp(pwd, cwd)) {
stat(cwd, &cwd_stat);
if ((cwd_stat.st_dev || cwd_stat.st_ino) &&
!stat(pwd, &pwd_stat) &&
pwd_stat.st_dev == cwd_stat.st_dev &&
pwd_stat.st_ino == cwd_stat.st_ino) {
strlcpy(cwd, pwd, PATH_MAX);
}
}
return cwd;
}

/*
* Use this to get an absolute path from a relative one. If you want
* to resolve links, you should use real_path.
*
* If the path is already absolute, then return path. As the user is
* never meant to free the return value, we're safe.
*/
const char *absolute_path(const char *path)
{
static char buf[PATH_MAX + 1];

if (!*path) {
die("The empty string is not a valid path");
} else if (is_absolute_path(path)) {
if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
die("Too long path: %.*s", 60, path);
} else {
size_t len;
const char *fmt;
const char *cwd = get_pwd_cwd();
if (!cwd)
die_errno("Cannot determine the current working directory");
len = strlen(cwd);
fmt = (len > 0 && is_dir_sep(cwd[len - 1])) ? "%s%s" : "%s/%s";
if (snprintf(buf, PATH_MAX, fmt, cwd, path) >= PATH_MAX)
die("Too long path: %.*s", 60, path);
}
return buf;
static struct strbuf sb = STRBUF_INIT;
strbuf_reset(&sb);
strbuf_add_absolute_path(&sb, path);
return sb.buf;
}

/*

+ 11
- 13
builtin/init-db.c View File

@@ -426,8 +426,9 @@ int init_db(const char *template_dir, unsigned int flags)

static int guess_repository_type(const char *git_dir)
{
char cwd[PATH_MAX];
const char *slash;
char *cwd;
int cwd_is_git_dir;

/*
* "GIT_DIR=. git init" is always bare.
@@ -435,9 +436,10 @@ static int guess_repository_type(const char *git_dir)
*/
if (!strcmp(".", git_dir))
return 1;
if (!getcwd(cwd, sizeof(cwd)))
die_errno(_("cannot tell cwd"));
if (!strcmp(git_dir, cwd))
cwd = xgetcwd();
cwd_is_git_dir = !strcmp(git_dir, cwd);
free(cwd);
if (cwd_is_git_dir)
return 1;
/*
* "GIT_DIR=.git or GIT_DIR=something/.git is usually not.
@@ -535,10 +537,9 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
usage(init_db_usage[0]);
}
if (is_bare_repository_cfg == 1) {
static char git_dir[PATH_MAX+1];

setenv(GIT_DIR_ENVIRONMENT,
getcwd(git_dir, sizeof(git_dir)), argc > 0);
char *cwd = xgetcwd();
setenv(GIT_DIR_ENVIRONMENT, cwd, argc > 0);
free(cwd);
}

if (init_shared_repository != -1)
@@ -572,11 +573,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
git_work_tree_cfg = xstrdup(real_path(rel));
free(rel);
}
if (!git_work_tree_cfg) {
git_work_tree_cfg = xcalloc(PATH_MAX, 1);
if (!getcwd(git_work_tree_cfg, PATH_MAX))
die_errno (_("Cannot access current working directory"));
}
if (!git_work_tree_cfg)
git_work_tree_cfg = xgetcwd();
if (work_tree)
set_git_work_tree(work_tree);
else

+ 3
- 3
builtin/rev-parse.c View File

@@ -736,7 +736,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
}
if (!strcmp(arg, "--git-dir")) {
const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
static char cwd[PATH_MAX];
char *cwd;
int len;
if (gitdir) {
puts(gitdir);
@@ -746,10 +746,10 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
puts(".git");
continue;
}
if (!getcwd(cwd, PATH_MAX))
die_errno("unable to get current working directory");
cwd = xgetcwd();
len = strlen(cwd);
printf("%s%s.git\n", cwd, len && cwd[len-1] != '/' ? "/" : "");
free(cwd);
continue;
}
if (!strcmp(arg, "--resolve-git-dir")) {

+ 8
- 4
dir.c View File

@@ -1507,12 +1507,16 @@ int dir_inside_of(const char *subdir, const char *dir)

int is_inside_dir(const char *dir)
{
char cwd[PATH_MAX];
char *cwd;
int rc;

if (!dir)
return 0;
if (!getcwd(cwd, sizeof(cwd)))
die_errno("can't find the current directory");
return dir_inside_of(cwd, dir) >= 0;

cwd = xgetcwd();
rc = (dir_inside_of(cwd, dir) >= 0);
free(cwd);
return rc;
}

int is_empty_dir(const char *path)

+ 1
- 5
exec_cmd.c View File

@@ -86,11 +86,7 @@ const char *git_exec_path(void)
static void add_path(struct strbuf *out, const char *path)
{
if (path && *path) {
if (is_absolute_path(path))
strbuf_addstr(out, path);
else
strbuf_addstr(out, absolute_path(path));

strbuf_add_absolute_path(out, path);
strbuf_addch(out, PATH_SEP);
}
}

+ 1
- 0
git-compat-util.h View File

@@ -607,6 +607,7 @@ extern int xmkstemp(char *template);
extern int xmkstemp_mode(char *template, int mode);
extern int odb_mkstemp(char *template, size_t limit, const char *pattern);
extern int odb_pack_keep(char *name, size_t namesz, const unsigned char *sha1);
extern char *xgetcwd(void);

static inline size_t xsize_t(off_t len)
{

+ 7
- 6
git.c View File

@@ -20,7 +20,7 @@ const char git_more_info_string[] =

static struct startup_info git_startup_info;
static int use_pager = -1;
static char orig_cwd[PATH_MAX];
static char *orig_cwd;
static const char *env_names[] = {
GIT_DIR_ENVIRONMENT,
GIT_WORK_TREE_ENVIRONMENT,
@@ -36,8 +36,7 @@ static void save_env(void)
if (saved_environment)
return;
saved_environment = 1;
if (!getcwd(orig_cwd, sizeof(orig_cwd)))
die_errno("cannot getcwd");
orig_cwd = xgetcwd();
for (i = 0; i < ARRAY_SIZE(env_names); i++) {
orig_env[i] = getenv(env_names[i]);
if (orig_env[i])
@@ -48,8 +47,9 @@ static void save_env(void)
static void restore_env(void)
{
int i;
if (*orig_cwd && chdir(orig_cwd))
if (orig_cwd && chdir(orig_cwd))
die_errno("could not move to %s", orig_cwd);
free(orig_cwd);
for (i = 0; i < ARRAY_SIZE(env_names); i++) {
if (orig_env[i])
setenv(env_names[i], orig_env[i], 1);
@@ -161,9 +161,10 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
if (envchanged)
*envchanged = 1;
} else if (!strcmp(cmd, "--bare")) {
static char git_dir[PATH_MAX+1];
char *cwd = xgetcwd();
is_bare_repository_cfg = 1;
setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 0);
setenv(GIT_DIR_ENVIRONMENT, cwd, 0);
free(cwd);
setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1);
if (envchanged)
*envchanged = 1;

+ 47
- 46
setup.c View File

@@ -387,7 +387,7 @@ const char *read_gitfile(const char *path)
}

static const char *setup_explicit_git_dir(const char *gitdirenv,
char *cwd, int len,
struct strbuf *cwd,
int *nongit_ok)
{
const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
@@ -434,16 +434,16 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
if (is_absolute_path(git_work_tree_cfg))
set_git_work_tree(git_work_tree_cfg);
else {
char core_worktree[PATH_MAX];
char *core_worktree;
if (chdir(gitdirenv))
die_errno("Could not chdir to '%s'", gitdirenv);
if (chdir(git_work_tree_cfg))
die_errno("Could not chdir to '%s'", git_work_tree_cfg);
if (!getcwd(core_worktree, PATH_MAX))
die_errno("Could not get directory '%s'", git_work_tree_cfg);
if (chdir(cwd))
core_worktree = xgetcwd();
if (chdir(cwd->buf))
die_errno("Could not come back to cwd");
set_git_work_tree(core_worktree);
free(core_worktree);
}
}
else if (!git_env_bool(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, 1)) {
@@ -459,21 +459,20 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
worktree = get_git_work_tree();

/* both get_git_work_tree() and cwd are already normalized */
if (!strcmp(cwd, worktree)) { /* cwd == worktree */
if (!strcmp(cwd->buf, worktree)) { /* cwd == worktree */
set_git_dir(gitdirenv);
free(gitfile);
return NULL;
}

offset = dir_inside_of(cwd, worktree);
offset = dir_inside_of(cwd->buf, worktree);
if (offset >= 0) { /* cwd inside worktree? */
set_git_dir(real_path(gitdirenv));
if (chdir(worktree))
die_errno("Could not chdir to '%s'", worktree);
cwd[len++] = '/';
cwd[len] = '\0';
strbuf_addch(cwd, '/');
free(gitfile);
return cwd + offset;
return cwd->buf + offset;
}

/* cwd outside worktree */
@@ -483,7 +482,7 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
}

static const char *setup_discovered_git_dir(const char *gitdir,
char *cwd, int offset, int len,
struct strbuf *cwd, int offset,
int *nongit_ok)
{
if (check_repository_format_gently(gitdir, nongit_ok))
@@ -491,17 +490,17 @@ static const char *setup_discovered_git_dir(const char *gitdir,

/* --work-tree is set without --git-dir; use discovered one */
if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
if (offset != len && !is_absolute_path(gitdir))
if (offset != cwd->len && !is_absolute_path(gitdir))
gitdir = xstrdup(real_path(gitdir));
if (chdir(cwd))
if (chdir(cwd->buf))
die_errno("Could not come back to cwd");
return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok);
return setup_explicit_git_dir(gitdir, cwd, nongit_ok);
}

/* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */
if (is_bare_repository_cfg > 0) {
set_git_dir(offset == len ? gitdir : real_path(gitdir));
if (chdir(cwd))
set_git_dir(offset == cwd->len ? gitdir : real_path(gitdir));
if (chdir(cwd->buf))
die_errno("Could not come back to cwd");
return NULL;
}
@@ -512,18 +511,18 @@ static const char *setup_discovered_git_dir(const char *gitdir,
set_git_dir(gitdir);
inside_git_dir = 0;
inside_work_tree = 1;
if (offset == len)
if (offset == cwd->len)
return NULL;

/* Make "offset" point to past the '/', and add a '/' at the end */
offset++;
cwd[len++] = '/';
cwd[len] = 0;
return cwd + offset;
strbuf_addch(cwd, '/');
return cwd->buf + offset;
}

/* #16.1, #17.1, #20.1, #21.1, #22.1 (see t1510) */
static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongit_ok)
static const char *setup_bare_git_dir(struct strbuf *cwd, int offset,
int *nongit_ok)
{
int root_len;

@@ -536,20 +535,20 @@ static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongi
if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
const char *gitdir;

gitdir = offset == len ? "." : xmemdupz(cwd, offset);
if (chdir(cwd))
gitdir = offset == cwd->len ? "." : xmemdupz(cwd->buf, offset);
if (chdir(cwd->buf))
die_errno("Could not come back to cwd");
return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok);
return setup_explicit_git_dir(gitdir, cwd, nongit_ok);
}

inside_git_dir = 1;
inside_work_tree = 0;
if (offset != len) {
if (chdir(cwd))
if (offset != cwd->len) {
if (chdir(cwd->buf))
die_errno("Cannot come back to cwd");
root_len = offset_1st_component(cwd);
cwd[offset > root_len ? offset : root_len] = '\0';
set_git_dir(cwd);
root_len = offset_1st_component(cwd->buf);
strbuf_setlen(cwd, offset > root_len ? offset : root_len);
set_git_dir(cwd->buf);
}
else
set_git_dir(".");
@@ -617,10 +616,10 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
{
const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT);
struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
static char cwd[PATH_MAX + 1];
static struct strbuf cwd = STRBUF_INIT;
const char *gitdirenv, *ret;
char *gitfile;
int len, offset, offset_parent, ceil_offset = -1;
int offset, offset_parent, ceil_offset = -1;
dev_t current_device = 0;
int one_filesystem = 1;

@@ -641,9 +640,9 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
if (nongit_ok)
*nongit_ok = 0;

if (!getcwd(cwd, sizeof(cwd) - 1))
if (strbuf_getcwd(&cwd))
die_errno("Unable to read current working directory");
offset = len = strlen(cwd);
offset = cwd.len;

/*
* If GIT_DIR is set explicitly, we're not going
@@ -652,7 +651,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
*/
gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
if (gitdirenv)
return setup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok);
return setup_explicit_git_dir(gitdirenv, &cwd, nongit_ok);

if (env_ceiling_dirs) {
int empty_entry_found = 0;
@@ -660,11 +659,11 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
string_list_split(&ceiling_dirs, env_ceiling_dirs, PATH_SEP, -1);
filter_string_list(&ceiling_dirs, 0,
canonicalize_ceiling_entry, &empty_entry_found);
ceil_offset = longest_ancestor_length(cwd, &ceiling_dirs);
ceil_offset = longest_ancestor_length(cwd.buf, &ceiling_dirs);
string_list_clear(&ceiling_dirs, 0);
}

if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
if (ceil_offset < 0 && has_dos_drive_prefix(cwd.buf))
ceil_offset = 1;

/*
@@ -692,7 +691,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)

if (gitdirenv) {
ret = setup_discovered_git_dir(gitdirenv,
cwd, offset, len,
&cwd, offset,
nongit_ok);
free(gitfile);
return ret;
@@ -700,29 +699,31 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
free(gitfile);

if (is_git_directory("."))
return setup_bare_git_dir(cwd, offset, len, nongit_ok);
return setup_bare_git_dir(&cwd, offset, nongit_ok);

offset_parent = offset;
while (--offset_parent > ceil_offset && cwd[offset_parent] != '/');
while (--offset_parent > ceil_offset && cwd.buf[offset_parent] != '/');
if (offset_parent <= ceil_offset)
return setup_nongit(cwd, nongit_ok);
return setup_nongit(cwd.buf, nongit_ok);
if (one_filesystem) {
dev_t parent_device = get_device_or_die("..", cwd, offset);
dev_t parent_device = get_device_or_die("..", cwd.buf,
offset);
if (parent_device != current_device) {
if (nongit_ok) {
if (chdir(cwd))
if (chdir(cwd.buf))
die_errno("Cannot come back to cwd");
*nongit_ok = 1;
return NULL;
}
cwd[offset] = '\0';
strbuf_setlen(&cwd, offset);
die("Not a git repository (or any parent up to mount point %s)\n"
"Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).", cwd);
"Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).",
cwd.buf);
}
}
if (chdir("..")) {
cwd[offset] = '\0';
die_errno("Cannot change to '%s/..'", cwd);
strbuf_setlen(&cwd, offset);
die_errno("Cannot change to '%s/..'", cwd.buf);
}
offset = offset_parent;
}

+ 1
- 1
sha1_file.c View File

@@ -350,7 +350,7 @@ static void link_alt_odb_entries(const char *alt, int len, int sep,
return;
}

strbuf_addstr(&objdirbuf, absolute_path(get_object_directory()));
strbuf_add_absolute_path(&objdirbuf, get_object_directory());
normalize_path_copy(objdirbuf.buf, objdirbuf.buf);

alt_copy = xmemdupz(alt, len);

+ 46
- 0
strbuf.c View File

@@ -406,6 +406,27 @@ int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
return -1;
}

int strbuf_getcwd(struct strbuf *sb)
{
size_t oldalloc = sb->alloc;
size_t guessed_len = 128;

for (;; guessed_len *= 2) {
strbuf_grow(sb, guessed_len);
if (getcwd(sb->buf, sb->alloc)) {
strbuf_setlen(sb, strlen(sb->buf));
return 0;
}
if (errno != ERANGE)
break;
}
if (oldalloc == 0)
strbuf_release(sb);
else
strbuf_reset(sb);
return -1;
}

int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
{
int ch;
@@ -555,6 +576,31 @@ void strbuf_humanise_bytes(struct strbuf *buf, off_t bytes)
}
}

void strbuf_add_absolute_path(struct strbuf *sb, const char *path)
{
if (!*path)
die("The empty string is not a valid path");
if (!is_absolute_path(path)) {
struct stat cwd_stat, pwd_stat;
size_t orig_len = sb->len;
char *cwd = xgetcwd();
char *pwd = getenv("PWD");
if (pwd && strcmp(pwd, cwd) &&
!stat(cwd, &cwd_stat) &&
(cwd_stat.st_dev || cwd_stat.st_ino) &&
!stat(pwd, &pwd_stat) &&
pwd_stat.st_dev == cwd_stat.st_dev &&
pwd_stat.st_ino == cwd_stat.st_ino)
strbuf_addstr(sb, pwd);
else
strbuf_addstr(sb, cwd);
if (sb->len > orig_len && !is_dir_sep(sb->buf[sb->len - 1]))
strbuf_addch(sb, '/');
free(cwd);
}
strbuf_addstr(sb, path);
}

int printf_ln(const char *fmt, ...)
{
int ret;

+ 3
- 0
strbuf.h View File

@@ -174,6 +174,7 @@ extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint);
extern int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint);
extern int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint);
extern int strbuf_getcwd(struct strbuf *sb);

extern int strbuf_getwholeline(struct strbuf *, FILE *, int);
extern int strbuf_getline(struct strbuf *, FILE *, int);
@@ -189,6 +190,8 @@ extern void strbuf_addstr_urlencode(struct strbuf *, const char *,
int reserved);
extern void strbuf_humanise_bytes(struct strbuf *buf, off_t bytes);

extern void strbuf_add_absolute_path(struct strbuf *sb, const char *path);

__attribute__((format (printf,1,2)))
extern int printf_ln(const char *fmt, ...);
__attribute__((format (printf,2,3)))

+ 4
- 3
trace.c View File

@@ -298,13 +298,12 @@ void trace_repo_setup(const char *prefix)
{
static struct trace_key key = TRACE_KEY_INIT(SETUP);
const char *git_work_tree;
char cwd[PATH_MAX];
char *cwd;

if (!trace_want(&key))
return;

if (!getcwd(cwd, PATH_MAX))
die("Unable to get current working directory");
cwd = xgetcwd();

if (!(git_work_tree = get_git_work_tree()))
git_work_tree = "(null)";
@@ -316,6 +315,8 @@ void trace_repo_setup(const char *prefix)
trace_printf_key(&key, "setup: worktree: %s\n", quote_crnl(git_work_tree));
trace_printf_key(&key, "setup: cwd: %s\n", quote_crnl(cwd));
trace_printf_key(&key, "setup: prefix: %s\n", quote_crnl(prefix));

free(cwd);
}

int trace_want(struct trace_key *key)

+ 7
- 7
unix-socket.c View File

@@ -18,12 +18,12 @@ static int chdir_len(const char *orig, int len)
}

struct unix_sockaddr_context {
char orig_dir[PATH_MAX];
char *orig_dir;
};

static void unix_sockaddr_cleanup(struct unix_sockaddr_context *ctx)
{
if (!ctx->orig_dir[0])
if (!ctx->orig_dir)
return;
/*
* If we fail, we can't just return an error, since we have
@@ -32,6 +32,7 @@ static void unix_sockaddr_cleanup(struct unix_sockaddr_context *ctx)
*/
if (chdir(ctx->orig_dir) < 0)
die("unable to restore original working directory");
free(ctx->orig_dir);
}

static int unix_sockaddr_init(struct sockaddr_un *sa, const char *path,
@@ -39,10 +40,11 @@ static int unix_sockaddr_init(struct sockaddr_un *sa, const char *path,
{
int size = strlen(path) + 1;

ctx->orig_dir[0] = '\0';
ctx->orig_dir = NULL;
if (size > sizeof(sa->sun_path)) {
const char *slash = find_last_dir_sep(path);
const char *dir;
struct strbuf cwd = STRBUF_INIT;

if (!slash) {
errno = ENAMETOOLONG;
@@ -56,11 +58,9 @@ static int unix_sockaddr_init(struct sockaddr_un *sa, const char *path,
errno = ENAMETOOLONG;
return -1;
}

if (!getcwd(ctx->orig_dir, sizeof(ctx->orig_dir))) {
errno = ENAMETOOLONG;
if (strbuf_getcwd(&cwd))
return -1;
}
ctx->orig_dir = strbuf_detach(&cwd, NULL);
if (chdir_len(dir, slash - dir) < 0)
return -1;
}

+ 8
- 0
wrapper.c View File

@@ -493,3 +493,11 @@ struct passwd *xgetpwuid_self(void)
errno ? strerror(errno) : _("no such user"));
return pw;
}

char *xgetcwd(void)
{
struct strbuf sb = STRBUF_INIT;
if (strbuf_getcwd(&sb))
die_errno(_("unable to get current working directory"));
return strbuf_detach(&sb, NULL);
}

Loading…
Cancel
Save