Skip to content

Commit f655651

Browse files
committed
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()
2 parents 51eeaea + 9610dec commit f655651

15 files changed

+191
-178
lines changed

Documentation/technical/api-strbuf.txt

+10
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,16 @@ same behaviour as well.
307307
use it unless you need the correct position in the file
308308
descriptor.
309309

310+
`strbuf_getcwd`::
311+
312+
Set the buffer to the path of the current working directory.
313+
314+
`strbuf_add_absolute_path`
315+
316+
Add a path to a buffer, converting a relative path to an
317+
absolute one in the process. Symbolic links are not
318+
resolved.
319+
310320
`stripspace`::
311321

312322
Strip whitespace from a buffer. The second parameter controls if

abspath.c

+34-90
Original file line numberDiff line numberDiff line change
@@ -33,24 +33,22 @@ int is_directory(const char *path)
3333
*/
3434
static const char *real_path_internal(const char *path, int die_on_error)
3535
{
36-
static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
36+
static struct strbuf sb = STRBUF_INIT;
3737
char *retval = NULL;
3838

3939
/*
4040
* If we have to temporarily chdir(), store the original CWD
4141
* here so that we can chdir() back to it at the end of the
4242
* function:
4343
*/
44-
char cwd[1024] = "";
45-
46-
int buf_index = 1;
44+
struct strbuf cwd = STRBUF_INIT;
4745

4846
int depth = MAXDEPTH;
4947
char *last_elem = NULL;
5048
struct stat st;
5149

5250
/* We've already done it */
53-
if (path == buf || path == next_buf)
51+
if (path == sb.buf)
5452
return path;
5553

5654
if (!*path) {
@@ -60,90 +58,74 @@ static const char *real_path_internal(const char *path, int die_on_error)
6058
goto error_out;
6159
}
6260

63-
if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX) {
64-
if (die_on_error)
65-
die("Too long path: %.*s", 60, path);
66-
else
67-
goto error_out;
68-
}
61+
strbuf_reset(&sb);
62+
strbuf_addstr(&sb, path);
6963

7064
while (depth--) {
71-
if (!is_directory(buf)) {
72-
char *last_slash = find_last_dir_sep(buf);
65+
if (!is_directory(sb.buf)) {
66+
char *last_slash = find_last_dir_sep(sb.buf);
7367
if (last_slash) {
7468
last_elem = xstrdup(last_slash + 1);
75-
last_slash[1] = '\0';
69+
strbuf_setlen(&sb, last_slash - sb.buf + 1);
7670
} else {
77-
last_elem = xstrdup(buf);
78-
*buf = '\0';
71+
last_elem = xmemdupz(sb.buf, sb.len);
72+
strbuf_reset(&sb);
7973
}
8074
}
8175

82-
if (*buf) {
83-
if (!*cwd && !getcwd(cwd, sizeof(cwd))) {
76+
if (sb.len) {
77+
if (!cwd.len && strbuf_getcwd(&cwd)) {
8478
if (die_on_error)
8579
die_errno("Could not get current working directory");
8680
else
8781
goto error_out;
8882
}
8983

90-
if (chdir(buf)) {
84+
if (chdir(sb.buf)) {
9185
if (die_on_error)
92-
die_errno("Could not switch to '%s'", buf);
86+
die_errno("Could not switch to '%s'",
87+
sb.buf);
9388
else
9489
goto error_out;
9590
}
9691
}
97-
if (!getcwd(buf, PATH_MAX)) {
92+
if (strbuf_getcwd(&sb)) {
9893
if (die_on_error)
9994
die_errno("Could not get current working directory");
10095
else
10196
goto error_out;
10297
}
10398

10499
if (last_elem) {
105-
size_t len = strlen(buf);
106-
if (len + strlen(last_elem) + 2 > PATH_MAX) {
107-
if (die_on_error)
108-
die("Too long path name: '%s/%s'",
109-
buf, last_elem);
110-
else
111-
goto error_out;
112-
}
113-
if (len && !is_dir_sep(buf[len - 1]))
114-
buf[len++] = '/';
115-
strcpy(buf + len, last_elem);
100+
if (sb.len && !is_dir_sep(sb.buf[sb.len - 1]))
101+
strbuf_addch(&sb, '/');
102+
strbuf_addstr(&sb, last_elem);
116103
free(last_elem);
117104
last_elem = NULL;
118105
}
119106

120-
if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
121-
ssize_t len = readlink(buf, next_buf, PATH_MAX);
107+
if (!lstat(sb.buf, &st) && S_ISLNK(st.st_mode)) {
108+
struct strbuf next_sb = STRBUF_INIT;
109+
ssize_t len = strbuf_readlink(&next_sb, sb.buf, 0);
122110
if (len < 0) {
123111
if (die_on_error)
124-
die_errno("Invalid symlink '%s'", buf);
125-
else
126-
goto error_out;
127-
}
128-
if (PATH_MAX <= len) {
129-
if (die_on_error)
130-
die("symbolic link too long: %s", buf);
112+
die_errno("Invalid symlink '%s'",
113+
sb.buf);
131114
else
132115
goto error_out;
133116
}
134-
next_buf[len] = '\0';
135-
buf = next_buf;
136-
buf_index = 1 - buf_index;
137-
next_buf = bufs[buf_index];
117+
strbuf_swap(&sb, &next_sb);
118+
strbuf_release(&next_sb);
138119
} else
139120
break;
140121
}
141122

142-
retval = buf;
123+
retval = sb.buf;
143124
error_out:
144125
free(last_elem);
145-
if (*cwd && chdir(cwd))
146-
die_errno("Could not change back to '%s'", cwd);
126+
if (cwd.len && chdir(cwd.buf))
127+
die_errno("Could not change back to '%s'", cwd.buf);
128+
strbuf_release(&cwd);
147129

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

161-
static const char *get_pwd_cwd(void)
162-
{
163-
static char cwd[PATH_MAX + 1];
164-
char *pwd;
165-
struct stat cwd_stat, pwd_stat;
166-
if (getcwd(cwd, PATH_MAX) == NULL)
167-
return NULL;
168-
pwd = getenv("PWD");
169-
if (pwd && strcmp(pwd, cwd)) {
170-
stat(cwd, &cwd_stat);
171-
if ((cwd_stat.st_dev || cwd_stat.st_ino) &&
172-
!stat(pwd, &pwd_stat) &&
173-
pwd_stat.st_dev == cwd_stat.st_dev &&
174-
pwd_stat.st_ino == cwd_stat.st_ino) {
175-
strlcpy(cwd, pwd, PATH_MAX);
176-
}
177-
}
178-
return cwd;
179-
}
180-
181143
/*
182144
* Use this to get an absolute path from a relative one. If you want
183145
* to resolve links, you should use real_path.
184-
*
185-
* If the path is already absolute, then return path. As the user is
186-
* never meant to free the return value, we're safe.
187146
*/
188147
const char *absolute_path(const char *path)
189148
{
190-
static char buf[PATH_MAX + 1];
191-
192-
if (!*path) {
193-
die("The empty string is not a valid path");
194-
} else if (is_absolute_path(path)) {
195-
if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
196-
die("Too long path: %.*s", 60, path);
197-
} else {
198-
size_t len;
199-
const char *fmt;
200-
const char *cwd = get_pwd_cwd();
201-
if (!cwd)
202-
die_errno("Cannot determine the current working directory");
203-
len = strlen(cwd);
204-
fmt = (len > 0 && is_dir_sep(cwd[len - 1])) ? "%s%s" : "%s/%s";
205-
if (snprintf(buf, PATH_MAX, fmt, cwd, path) >= PATH_MAX)
206-
die("Too long path: %.*s", 60, path);
207-
}
208-
return buf;
149+
static struct strbuf sb = STRBUF_INIT;
150+
strbuf_reset(&sb);
151+
strbuf_add_absolute_path(&sb, path);
152+
return sb.buf;
209153
}
210154

211155
/*

builtin/init-db.c

+11-13
Original file line numberDiff line numberDiff line change
@@ -426,18 +426,20 @@ int init_db(const char *template_dir, unsigned int flags)
426426

427427
static int guess_repository_type(const char *git_dir)
428428
{
429-
char cwd[PATH_MAX];
430429
const char *slash;
430+
char *cwd;
431+
int cwd_is_git_dir;
431432

432433
/*
433434
* "GIT_DIR=. git init" is always bare.
434435
* "GIT_DIR=`pwd` git init" too.
435436
*/
436437
if (!strcmp(".", git_dir))
437438
return 1;
438-
if (!getcwd(cwd, sizeof(cwd)))
439-
die_errno(_("cannot tell cwd"));
440-
if (!strcmp(git_dir, cwd))
439+
cwd = xgetcwd();
440+
cwd_is_git_dir = !strcmp(git_dir, cwd);
441+
free(cwd);
442+
if (cwd_is_git_dir)
441443
return 1;
442444
/*
443445
* "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)
535537
usage(init_db_usage[0]);
536538
}
537539
if (is_bare_repository_cfg == 1) {
538-
static char git_dir[PATH_MAX+1];
539-
540-
setenv(GIT_DIR_ENVIRONMENT,
541-
getcwd(git_dir, sizeof(git_dir)), argc > 0);
540+
char *cwd = xgetcwd();
541+
setenv(GIT_DIR_ENVIRONMENT, cwd, argc > 0);
542+
free(cwd);
542543
}
543544

544545
if (init_shared_repository != -1)
@@ -572,11 +573,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
572573
git_work_tree_cfg = xstrdup(real_path(rel));
573574
free(rel);
574575
}
575-
if (!git_work_tree_cfg) {
576-
git_work_tree_cfg = xcalloc(PATH_MAX, 1);
577-
if (!getcwd(git_work_tree_cfg, PATH_MAX))
578-
die_errno (_("Cannot access current working directory"));
579-
}
576+
if (!git_work_tree_cfg)
577+
git_work_tree_cfg = xgetcwd();
580578
if (work_tree)
581579
set_git_work_tree(work_tree);
582580
else

builtin/rev-parse.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
736736
}
737737
if (!strcmp(arg, "--git-dir")) {
738738
const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
739-
static char cwd[PATH_MAX];
739+
char *cwd;
740740
int len;
741741
if (gitdir) {
742742
puts(gitdir);
@@ -746,10 +746,10 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
746746
puts(".git");
747747
continue;
748748
}
749-
if (!getcwd(cwd, PATH_MAX))
750-
die_errno("unable to get current working directory");
749+
cwd = xgetcwd();
751750
len = strlen(cwd);
752751
printf("%s%s.git\n", cwd, len && cwd[len-1] != '/' ? "/" : "");
752+
free(cwd);
753753
continue;
754754
}
755755
if (!strcmp(arg, "--resolve-git-dir")) {

dir.c

+8-4
Original file line numberDiff line numberDiff line change
@@ -1507,12 +1507,16 @@ int dir_inside_of(const char *subdir, const char *dir)
15071507

15081508
int is_inside_dir(const char *dir)
15091509
{
1510-
char cwd[PATH_MAX];
1510+
char *cwd;
1511+
int rc;
1512+
15111513
if (!dir)
15121514
return 0;
1513-
if (!getcwd(cwd, sizeof(cwd)))
1514-
die_errno("can't find the current directory");
1515-
return dir_inside_of(cwd, dir) >= 0;
1515+
1516+
cwd = xgetcwd();
1517+
rc = (dir_inside_of(cwd, dir) >= 0);
1518+
free(cwd);
1519+
return rc;
15161520
}
15171521

15181522
int is_empty_dir(const char *path)

exec_cmd.c

+1-5
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,7 @@ const char *git_exec_path(void)
8686
static void add_path(struct strbuf *out, const char *path)
8787
{
8888
if (path && *path) {
89-
if (is_absolute_path(path))
90-
strbuf_addstr(out, path);
91-
else
92-
strbuf_addstr(out, absolute_path(path));
93-
89+
strbuf_add_absolute_path(out, path);
9490
strbuf_addch(out, PATH_SEP);
9591
}
9692
}

git-compat-util.h

+1
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,7 @@ extern int xmkstemp(char *template);
607607
extern int xmkstemp_mode(char *template, int mode);
608608
extern int odb_mkstemp(char *template, size_t limit, const char *pattern);
609609
extern int odb_pack_keep(char *name, size_t namesz, const unsigned char *sha1);
610+
extern char *xgetcwd(void);
610611

611612
static inline size_t xsize_t(off_t len)
612613
{

git.c

+7-6
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const char git_more_info_string[] =
2020

2121
static struct startup_info git_startup_info;
2222
static int use_pager = -1;
23-
static char orig_cwd[PATH_MAX];
23+
static char *orig_cwd;
2424
static const char *env_names[] = {
2525
GIT_DIR_ENVIRONMENT,
2626
GIT_WORK_TREE_ENVIRONMENT,
@@ -36,8 +36,7 @@ static void save_env(void)
3636
if (saved_environment)
3737
return;
3838
saved_environment = 1;
39-
if (!getcwd(orig_cwd, sizeof(orig_cwd)))
40-
die_errno("cannot getcwd");
39+
orig_cwd = xgetcwd();
4140
for (i = 0; i < ARRAY_SIZE(env_names); i++) {
4241
orig_env[i] = getenv(env_names[i]);
4342
if (orig_env[i])
@@ -48,8 +47,9 @@ static void save_env(void)
4847
static void restore_env(void)
4948
{
5049
int i;
51-
if (*orig_cwd && chdir(orig_cwd))
50+
if (orig_cwd && chdir(orig_cwd))
5251
die_errno("could not move to %s", orig_cwd);
52+
free(orig_cwd);
5353
for (i = 0; i < ARRAY_SIZE(env_names); i++) {
5454
if (orig_env[i])
5555
setenv(env_names[i], orig_env[i], 1);
@@ -161,9 +161,10 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
161161
if (envchanged)
162162
*envchanged = 1;
163163
} else if (!strcmp(cmd, "--bare")) {
164-
static char git_dir[PATH_MAX+1];
164+
char *cwd = xgetcwd();
165165
is_bare_repository_cfg = 1;
166-
setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 0);
166+
setenv(GIT_DIR_ENVIRONMENT, cwd, 0);
167+
free(cwd);
167168
setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1);
168169
if (envchanged)
169170
*envchanged = 1;

0 commit comments

Comments
 (0)