@@ -55,49 +55,41 @@ static void get_next_component(struct strbuf *next, struct strbuf *remaining)
55
55
* Return the real path (i.e., absolute path, with symlinks resolved
56
56
* and extra slashes removed) equivalent to the specified path. (If
57
57
* you want an absolute path but don't mind links, use
58
- * absolute_path().) The return value is a pointer to a static
59
- * buffer.
58
+ * absolute_path().) Places the resolved realpath in the provided strbuf.
60
59
*
61
60
* The directory part of path (i.e., everything up to the last
62
61
* dir_sep) must denote a valid, existing directory, but the last
63
62
* component need not exist. If die_on_error is set, then die with an
64
63
* informative error message if there is a problem. Otherwise, return
65
64
* NULL on errors (without generating any output).
66
- *
67
- * If path is our buffer, then return path, as it's already what the
68
- * user wants.
69
65
*/
70
- static const char * real_path_internal (const char * path , int die_on_error )
66
+ char * strbuf_realpath (struct strbuf * resolved , const char * path ,
67
+ int die_on_error )
71
68
{
72
- static struct strbuf resolved = STRBUF_INIT ;
73
69
struct strbuf remaining = STRBUF_INIT ;
74
70
struct strbuf next = STRBUF_INIT ;
75
71
struct strbuf symlink = STRBUF_INIT ;
76
72
char * retval = NULL ;
77
73
int num_symlinks = 0 ;
78
74
struct stat st ;
79
75
80
- /* We've already done it */
81
- if (path == resolved .buf )
82
- return path ;
83
-
84
76
if (!* path ) {
85
77
if (die_on_error )
86
78
die ("The empty string is not a valid path" );
87
79
else
88
80
goto error_out ;
89
81
}
90
82
91
- strbuf_reset (& resolved );
83
+ strbuf_reset (resolved );
92
84
93
85
if (is_absolute_path (path )) {
94
86
/* absolute path; start with only root as being resolved */
95
87
int offset = offset_1st_component (path );
96
- strbuf_add (& resolved , path , offset );
88
+ strbuf_add (resolved , path , offset );
97
89
strbuf_addstr (& remaining , path + offset );
98
90
} else {
99
91
/* relative path; can use CWD as the initial resolved path */
100
- if (strbuf_getcwd (& resolved )) {
92
+ if (strbuf_getcwd (resolved )) {
101
93
if (die_on_error )
102
94
die_errno ("unable to get current working directory" );
103
95
else
@@ -116,21 +108,21 @@ static const char *real_path_internal(const char *path, int die_on_error)
116
108
continue ; /* '.' component */
117
109
} else if (next .len == 2 && !strcmp (next .buf , ".." )) {
118
110
/* '..' component; strip the last path component */
119
- strip_last_component (& resolved );
111
+ strip_last_component (resolved );
120
112
continue ;
121
113
}
122
114
123
115
/* append the next component and resolve resultant path */
124
- if (!is_dir_sep (resolved . buf [resolved . len - 1 ]))
125
- strbuf_addch (& resolved , '/' );
126
- strbuf_addbuf (& resolved , & next );
116
+ if (!is_dir_sep (resolved -> buf [resolved -> len - 1 ]))
117
+ strbuf_addch (resolved , '/' );
118
+ strbuf_addbuf (resolved , & next );
127
119
128
- if (lstat (resolved . buf , & st )) {
120
+ if (lstat (resolved -> buf , & st )) {
129
121
/* error out unless this was the last component */
130
122
if (errno != ENOENT || remaining .len ) {
131
123
if (die_on_error )
132
124
die_errno ("Invalid path '%s'" ,
133
- resolved . buf );
125
+ resolved -> buf );
134
126
else
135
127
goto error_out ;
136
128
}
@@ -146,29 +138,29 @@ static const char *real_path_internal(const char *path, int die_on_error)
146
138
goto error_out ;
147
139
}
148
140
149
- len = strbuf_readlink (& symlink , resolved . buf ,
141
+ len = strbuf_readlink (& symlink , resolved -> buf ,
150
142
st .st_size );
151
143
if (len < 0 ) {
152
144
if (die_on_error )
153
145
die_errno ("Invalid symlink '%s'" ,
154
- resolved . buf );
146
+ resolved -> buf );
155
147
else
156
148
goto error_out ;
157
149
}
158
150
159
151
if (is_absolute_path (symlink .buf )) {
160
152
/* absolute symlink; set resolved to root */
161
153
int offset = offset_1st_component (symlink .buf );
162
- strbuf_reset (& resolved );
163
- strbuf_add (& resolved , symlink .buf , offset );
154
+ strbuf_reset (resolved );
155
+ strbuf_add (resolved , symlink .buf , offset );
164
156
strbuf_remove (& symlink , 0 , offset );
165
157
} else {
166
158
/*
167
159
* relative symlink
168
160
* strip off the last component since it will
169
161
* be replaced with the contents of the symlink
170
162
*/
171
- strip_last_component (& resolved );
163
+ strip_last_component (resolved );
172
164
}
173
165
174
166
/*
@@ -188,24 +180,29 @@ static const char *real_path_internal(const char *path, int die_on_error)
188
180
}
189
181
}
190
182
191
- retval = resolved . buf ;
183
+ retval = resolved -> buf ;
192
184
193
185
error_out :
194
186
strbuf_release (& remaining );
195
187
strbuf_release (& next );
196
188
strbuf_release (& symlink );
197
189
190
+ if (!retval )
191
+ strbuf_reset (resolved );
192
+
198
193
return retval ;
199
194
}
200
195
201
196
const char * real_path (const char * path )
202
197
{
203
- return real_path_internal (path , 1 );
198
+ static struct strbuf realpath = STRBUF_INIT ;
199
+ return strbuf_realpath (& realpath , path , 1 );
204
200
}
205
201
206
202
const char * real_path_if_valid (const char * path )
207
203
{
208
- return real_path_internal (path , 0 );
204
+ static struct strbuf realpath = STRBUF_INIT ;
205
+ return strbuf_realpath (& realpath , path , 0 );
209
206
}
210
207
211
208
/*
0 commit comments