@@ -67,19 +67,15 @@ static void get_root_part(struct strbuf *resolved, struct strbuf *remaining)
67
67
#endif
68
68
69
69
/*
70
- * Return the real path (i.e., absolute path, with symlinks resolved
71
- * and extra slashes removed) equivalent to the specified path. (If
72
- * you want an absolute path but don't mind links, use
73
- * absolute_path().) Places the resolved realpath in the provided strbuf.
74
- *
75
- * The directory part of path (i.e., everything up to the last
76
- * dir_sep) must denote a valid, existing directory, but the last
77
- * component need not exist. If die_on_error is set, then die with an
78
- * informative error message if there is a problem. Otherwise, return
79
- * NULL on errors (without generating any output).
70
+ * If set, any number of trailing components may be missing; otherwise, only one
71
+ * may be.
80
72
*/
81
- char * strbuf_realpath (struct strbuf * resolved , const char * path ,
82
- int die_on_error )
73
+ #define REALPATH_MANY_MISSING (1 << 0)
74
+ /* Should we die if there's an error? */
75
+ #define REALPATH_DIE_ON_ERROR (1 << 1)
76
+
77
+ static char * strbuf_realpath_1 (struct strbuf * resolved , const char * path ,
78
+ int flags )
83
79
{
84
80
struct strbuf remaining = STRBUF_INIT ;
85
81
struct strbuf next = STRBUF_INIT ;
@@ -89,7 +85,7 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
89
85
struct stat st ;
90
86
91
87
if (!* path ) {
92
- if (die_on_error )
88
+ if (flags & REALPATH_DIE_ON_ERROR )
93
89
die ("The empty string is not a valid path" );
94
90
else
95
91
goto error_out ;
@@ -101,7 +97,7 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
101
97
if (!resolved -> len ) {
102
98
/* relative path; can use CWD as the initial resolved path */
103
99
if (strbuf_getcwd (resolved )) {
104
- if (die_on_error )
100
+ if (flags & REALPATH_DIE_ON_ERROR )
105
101
die_errno ("unable to get current working directory" );
106
102
else
107
103
goto error_out ;
@@ -129,8 +125,9 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
129
125
130
126
if (lstat (resolved -> buf , & st )) {
131
127
/* error out unless this was the last component */
132
- if (errno != ENOENT || remaining .len ) {
133
- if (die_on_error )
128
+ if (errno != ENOENT ||
129
+ (!(flags & REALPATH_MANY_MISSING ) && remaining .len )) {
130
+ if (flags & REALPATH_DIE_ON_ERROR )
134
131
die_errno ("Invalid path '%s'" ,
135
132
resolved -> buf );
136
133
else
@@ -143,7 +140,7 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
143
140
if (num_symlinks ++ > MAXSYMLINKS ) {
144
141
errno = ELOOP ;
145
142
146
- if (die_on_error )
143
+ if (flags & REALPATH_DIE_ON_ERROR )
147
144
die ("More than %d nested symlinks "
148
145
"on path '%s'" , MAXSYMLINKS , path );
149
146
else
@@ -153,7 +150,7 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
153
150
len = strbuf_readlink (& symlink , resolved -> buf ,
154
151
st .st_size );
155
152
if (len < 0 ) {
156
- if (die_on_error )
153
+ if (flags & REALPATH_DIE_ON_ERROR )
157
154
die_errno ("Invalid symlink '%s'" ,
158
155
resolved -> buf );
159
156
else
@@ -202,6 +199,37 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
202
199
return retval ;
203
200
}
204
201
202
+ /*
203
+ * Return the real path (i.e., absolute path, with symlinks resolved
204
+ * and extra slashes removed) equivalent to the specified path. (If
205
+ * you want an absolute path but don't mind links, use
206
+ * absolute_path().) Places the resolved realpath in the provided strbuf.
207
+ *
208
+ * The directory part of path (i.e., everything up to the last
209
+ * dir_sep) must denote a valid, existing directory, but the last
210
+ * component need not exist. If die_on_error is set, then die with an
211
+ * informative error message if there is a problem. Otherwise, return
212
+ * NULL on errors (without generating any output).
213
+ */
214
+ char * strbuf_realpath (struct strbuf * resolved , const char * path ,
215
+ int die_on_error )
216
+ {
217
+ return strbuf_realpath_1 (resolved , path ,
218
+ die_on_error ? REALPATH_DIE_ON_ERROR : 0 );
219
+ }
220
+
221
+ /*
222
+ * Just like strbuf_realpath, but allows an arbitrary number of path
223
+ * components to be missing.
224
+ */
225
+ char * strbuf_realpath_forgiving (struct strbuf * resolved , const char * path ,
226
+ int die_on_error )
227
+ {
228
+ return strbuf_realpath_1 (resolved , path ,
229
+ ((die_on_error ? REALPATH_DIE_ON_ERROR : 0 ) |
230
+ REALPATH_MANY_MISSING ));
231
+ }
232
+
205
233
char * real_pathdup (const char * path , int die_on_error )
206
234
{
207
235
struct strbuf realpath = STRBUF_INIT ;
0 commit comments