path.c: make get_pathname() return strbuf instead of static buffer
We've been avoiding PATH_MAX whenever possible. This patch makes get_pathname() return a strbuf and updates the callers to take advantage of this. The code is simplified as we no longer need to worry about buffer overflow. vsnpath() behavior is changed slightly: previously it always clears the buffer before writing, now it just appends. Fortunately this is a static function and all of its callers prepare the buffer properly: git_path() gets the buffer from get_pathname() which resets the buffer, the remaining call sites start with STRBUF_INIT'd buffer. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Nguyễn Thái Ngọc Duy committed
Nov 30, 2014 at 15:24 UTC
4ef9caf5431dbbd23f240a25b69a989aeb9840a4
1 file changed
+51
-69
path.c
+51
-69
@@ -16,11 +16,15 @@ static int get_st_mode_bits(const char *path, int *mode)
16
17
static char bad_path[] = "/bad-path/";
18
19
-static char *get_pathname(void)
19
+static struct strbuf *get_pathname(void)
20
{
21
- static char pathname_array[4][PATH_MAX];
21
+ static struct strbuf pathname_array[4] = {
22
+ STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
23
+ };
24
static int index;
23
- return pathname_array[3 & ++index];
25
+ struct strbuf *sb = &pathname_array[3 & ++index];
26
+ strbuf_reset(sb);
27
+ return sb;
28
}
29
30
static char *cleanup_path(char *path)
@@ -34,6 +38,13 @@ static char *cleanup_path(char *path)
38
return path;
39
}
40
41
+static void strbuf_cleanup_path(struct strbuf *sb)
42
+{
43
+ char *path = cleanup_path(sb->buf);
44
+ if (path > sb->buf)
45
+ strbuf_remove(sb, 0, path - sb->buf);
46
+}
47
+
48
char *mksnpath(char *buf, size_t n, const char *fmt, ...)
49
{
50
va_list args;
@@ -49,85 +60,70 @@ char *mksnpath(char *buf, size_t n, const char *fmt, ...)
60
return cleanup_path(buf);
61
}
62
52
-static char *vsnpath(char *buf, size_t n, const char *fmt, va_list args)
63
+static void vsnpath(struct strbuf *buf, const char *fmt, va_list args)
64
{
65
const char *git_dir = get_git_dir();
55
- size_t len;
56
-
57
- len = strlen(git_dir);
58
- if (n < len + 1)
59
- goto bad;
60
- memcpy(buf, git_dir, len);
61
- if (len && !is_dir_sep(git_dir[len-1]))
62
- buf[len++] = '/';
63
- len += vsnprintf(buf + len, n - len, fmt, args);
64
- if (len >= n)
65
- goto bad;
66
- return cleanup_path(buf);
67
-bad:
68
- strlcpy(buf, bad_path, n);
69
- return buf;
66
+ strbuf_addstr(buf, git_dir);
67
+ if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
68
+ strbuf_addch(buf, '/');
69
+ strbuf_vaddf(buf, fmt, args);
70
+ strbuf_cleanup_path(buf);
71
}
72
73
char *git_snpath(char *buf, size_t n, const char *fmt, ...)
74
{
74
- char *ret;
75
+ struct strbuf sb = STRBUF_INIT;
76
va_list args;
77
va_start(args, fmt);
77
- ret = vsnpath(buf, n, fmt, args);
78
+ vsnpath(&sb, fmt, args);
79
va_end(args);
79
- return ret;
80
+ if (sb.len >= n)
81
+ strlcpy(buf, bad_path, n);
82
+ else
83
+ memcpy(buf, sb.buf, sb.len + 1);
84
+ strbuf_release(&sb);
85
+ return buf;
86
}
87
88
char *git_pathdup(const char *fmt, ...)
89
{
84
- char path[PATH_MAX], *ret;
90
+ struct strbuf path = STRBUF_INIT;
91
va_list args;
92
va_start(args, fmt);
87
- ret = vsnpath(path, sizeof(path), fmt, args);
93
+ vsnpath(&path, fmt, args);
94
va_end(args);
89
- return xstrdup(ret);
95
+ return strbuf_detach(&path, NULL);
96
}
97
98
char *mkpathdup(const char *fmt, ...)
99
{
94
- char *path;
100
struct strbuf sb = STRBUF_INIT;
101
va_list args;
97
-
102
va_start(args, fmt);
103
strbuf_vaddf(&sb, fmt, args);
104
va_end(args);
101
- path = xstrdup(cleanup_path(sb.buf));
102
-
103
- strbuf_release(&sb);
104
- return path;
105
+ strbuf_cleanup_path(&sb);
106
+ return strbuf_detach(&sb, NULL);
107
}
108
109
char *mkpath(const char *fmt, ...)
110
{
111
va_list args;
110
- unsigned len;
111
- char *pathname = get_pathname();
112
-
112
+ struct strbuf *pathname = get_pathname();
113
va_start(args, fmt);
114
- len = vsnprintf(pathname, PATH_MAX, fmt, args);
114
+ strbuf_vaddf(pathname, fmt, args);
115
va_end(args);
116
- if (len >= PATH_MAX)
117
- return bad_path;
118
- return cleanup_path(pathname);
116
+ return cleanup_path(pathname->buf);
117
}
118
119
char *git_path(const char *fmt, ...)
120
{
123
- char *pathname = get_pathname();
121
+ struct strbuf *pathname = get_pathname();
122
va_list args;
125
- char *ret;
126
-
123
va_start(args, fmt);
128
- ret = vsnpath(pathname, PATH_MAX, fmt, args);
124
+ vsnpath(pathname, fmt, args);
125
va_end(args);
130
- return ret;
126
+ return pathname->buf;
127
}
128
129
void home_config_paths(char **global, char **xdg, char *file)
@@ -160,41 +156,27 @@ void home_config_paths(char **global, char **xdg, char *file)
156
157
char *git_path_submodule(const char *path, const char *fmt, ...)
158
{
163
- char *pathname = get_pathname();
164
- struct strbuf buf = STRBUF_INIT;
159
+ struct strbuf *buf = get_pathname();
160
const char *git_dir;
161
va_list args;
167
- unsigned len;
168
-
169
- len = strlen(path);
170
- if (len > PATH_MAX-100)
171
- return bad_path;
162
173
- strbuf_addstr(&buf, path);
174
- if (len && path[len-1] != '/')
175
- strbuf_addch(&buf, '/');
176
- strbuf_addstr(&buf, ".git");
163
+ strbuf_addstr(buf, path);
164
+ if (buf->len && buf->buf[buf->len - 1] != '/')
165
+ strbuf_addch(buf, '/');
166
+ strbuf_addstr(buf, ".git");
167
178
- git_dir = read_gitfile(buf.buf);
168
+ git_dir = read_gitfile(buf->buf);
169
if (git_dir) {
180
- strbuf_reset(&buf);
181
- strbuf_addstr(&buf, git_dir);
170
+ strbuf_reset(buf);
171
+ strbuf_addstr(buf, git_dir);
172
}
183
- strbuf_addch(&buf, '/');
184
-
185
- if (buf.len >= PATH_MAX)
186
- return bad_path;
187
- memcpy(pathname, buf.buf, buf.len + 1);
188
-
189
- strbuf_release(&buf);
190
- len = strlen(pathname);
173
+ strbuf_addch(buf, '/');
174
175
va_start(args, fmt);
193
- len += vsnprintf(pathname + len, PATH_MAX - len, fmt, args);
176
+ strbuf_vaddf(buf, fmt, args);
177
va_end(args);
195
- if (len >= PATH_MAX)
196
- return bad_path;
197
- return cleanup_path(pathname);
178
+ strbuf_cleanup_path(buf);
179
+ return buf->buf;
180
}
181
182
int validate_headref(const char *path)