1 #include "git-compat-util.h"
6 * Do not use this for inspecting *tracked* content. When path is a
7 * symlink to a directory, we do not want to say it is a directory when
8 * dealing with tracked content in the working tree.
10 int is_directory(const char *path
)
13 return (!stat(path
, &st
) && S_ISDIR(st
.st_mode
));
16 /* removes the last path component from 'path' except if 'path' is root */
17 static void strip_last_component(struct strbuf
*path
)
19 size_t offset
= offset_1st_component(path
->buf
);
20 size_t len
= path
->len
;
22 /* Find start of the last component */
23 while (offset
< len
&& !is_dir_sep(path
->buf
[len
- 1]))
25 /* Skip sequences of multiple path-separators */
26 while (offset
< len
&& is_dir_sep(path
->buf
[len
- 1]))
29 strbuf_setlen(path
, len
);
32 /* get (and remove) the next component in 'remaining' and place it in 'next' */
33 static void get_next_component(struct strbuf
*next
, struct strbuf
*remaining
)
40 /* look for the next component */
41 /* Skip sequences of multiple path-separators */
42 for (start
= remaining
->buf
; is_dir_sep(*start
); start
++)
44 /* Find end of the path component */
45 for (end
= start
; *end
&& !is_dir_sep(*end
); end
++)
48 strbuf_add(next
, start
, end
- start
);
49 /* remove the component from 'remaining' */
50 strbuf_remove(remaining
, 0, end
- remaining
->buf
);
53 /* copies root part from remaining to resolved, canonicalizing it on the way */
54 static void get_root_part(struct strbuf
*resolved
, struct strbuf
*remaining
)
56 int offset
= offset_1st_component(remaining
->buf
);
58 strbuf_reset(resolved
);
59 strbuf_add(resolved
, remaining
->buf
, offset
);
60 #ifdef GIT_WINDOWS_NATIVE
61 convert_slashes(resolved
->buf
);
63 strbuf_remove(remaining
, 0, offset
);
66 /* We allow "recursive" symbolic links. Only within reason, though. */
68 #define MAXSYMLINKS 32
72 * If set, any number of trailing components may be missing; otherwise, only one
75 #define REALPATH_MANY_MISSING (1 << 0)
76 /* Should we die if there's an error? */
77 #define REALPATH_DIE_ON_ERROR (1 << 1)
79 static char *strbuf_realpath_1(struct strbuf
*resolved
, const char *path
,
82 struct strbuf remaining
= STRBUF_INIT
;
83 struct strbuf next
= STRBUF_INIT
;
84 struct strbuf symlink
= STRBUF_INIT
;
90 if (flags
& REALPATH_DIE_ON_ERROR
)
91 die("The empty string is not a valid path");
96 strbuf_addstr(&remaining
, path
);
97 get_root_part(resolved
, &remaining
);
100 /* relative path; can use CWD as the initial resolved path */
101 if (strbuf_getcwd(resolved
)) {
102 if (flags
& REALPATH_DIE_ON_ERROR
)
103 die_errno("unable to get current working directory");
109 /* Iterate over the remaining path components */
110 while (remaining
.len
> 0) {
111 get_next_component(&next
, &remaining
);
114 continue; /* empty component */
115 } else if (next
.len
== 1 && !strcmp(next
.buf
, ".")) {
116 continue; /* '.' component */
117 } else if (next
.len
== 2 && !strcmp(next
.buf
, "..")) {
118 /* '..' component; strip the last path component */
119 strip_last_component(resolved
);
123 /* 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
);
128 if (lstat(resolved
->buf
, &st
)) {
129 /* error out unless this was the last component */
130 if (errno
!= ENOENT
||
131 (!(flags
& REALPATH_MANY_MISSING
) && remaining
.len
)) {
132 if (flags
& REALPATH_DIE_ON_ERROR
)
133 die_errno("Invalid path '%s'",
138 } else if (S_ISLNK(st
.st_mode
)) {
140 strbuf_reset(&symlink
);
142 if (num_symlinks
++ > MAXSYMLINKS
) {
145 if (flags
& REALPATH_DIE_ON_ERROR
)
146 die("More than %d nested symlinks "
147 "on path '%s'", MAXSYMLINKS
, path
);
152 len
= strbuf_readlink(&symlink
, resolved
->buf
,
155 if (flags
& REALPATH_DIE_ON_ERROR
)
156 die_errno("Invalid symlink '%s'",
162 if (is_absolute_path(symlink
.buf
)) {
163 /* absolute symlink; set resolved to root */
164 get_root_part(resolved
, &symlink
);
168 * strip off the last component since it will
169 * be replaced with the contents of the symlink
171 strip_last_component(resolved
);
175 * if there are still remaining components to resolve
176 * then append them to symlink
179 strbuf_addch(&symlink
, '/');
180 strbuf_addbuf(&symlink
, &remaining
);
184 * use the symlink as the remaining components that
185 * need to be resolved
187 strbuf_swap(&symlink
, &remaining
);
191 retval
= resolved
->buf
;
194 strbuf_release(&remaining
);
195 strbuf_release(&next
);
196 strbuf_release(&symlink
);
199 strbuf_reset(resolved
);
205 * Return the real path (i.e., absolute path, with symlinks resolved
206 * and extra slashes removed) equivalent to the specified path. (If
207 * you want an absolute path but don't mind links, use
208 * absolute_path().) Places the resolved realpath in the provided strbuf.
210 * The directory part of path (i.e., everything up to the last
211 * dir_sep) must denote a valid, existing directory, but the last
212 * component need not exist. If die_on_error is set, then die with an
213 * informative error message if there is a problem. Otherwise, return
214 * NULL on errors (without generating any output).
216 char *strbuf_realpath(struct strbuf
*resolved
, const char *path
,
219 return strbuf_realpath_1(resolved
, path
,
220 die_on_error
? REALPATH_DIE_ON_ERROR
: 0);
224 * Just like strbuf_realpath, but allows an arbitrary number of path
225 * components to be missing.
227 char *strbuf_realpath_forgiving(struct strbuf
*resolved
, const char *path
,
230 return strbuf_realpath_1(resolved
, path
,
231 ((die_on_error
? REALPATH_DIE_ON_ERROR
: 0) |
232 REALPATH_MANY_MISSING
));
235 char *real_pathdup(const char *path
, int die_on_error
)
237 struct strbuf realpath
= STRBUF_INIT
;
240 if (strbuf_realpath(&realpath
, path
, die_on_error
))
241 retval
= strbuf_detach(&realpath
, NULL
);
243 strbuf_release(&realpath
);
249 * Use this to get an absolute path from a relative one. If you want
250 * to resolve links, you should use strbuf_realpath.
252 const char *absolute_path(const char *path
)
254 static struct strbuf sb
= STRBUF_INIT
;
256 strbuf_add_absolute_path(&sb
, path
);
260 char *absolute_pathdup(const char *path
)
262 struct strbuf sb
= STRBUF_INIT
;
263 strbuf_add_absolute_path(&sb
, path
);
264 return strbuf_detach(&sb
, NULL
);
267 char *prefix_filename(const char *pfx
, const char *arg
)
269 struct strbuf path
= STRBUF_INIT
;
270 size_t pfx_len
= pfx
? strlen(pfx
) : 0;
273 ; /* nothing to prefix */
274 else if (is_absolute_path(arg
))
277 strbuf_add(&path
, pfx
, pfx_len
);
279 strbuf_addstr(&path
, arg
);
280 #ifdef GIT_WINDOWS_NATIVE
281 convert_slashes(path
.buf
+ pfx_len
);
283 return strbuf_detach(&path
, NULL
);
286 char *prefix_filename_except_for_dash(const char *pfx
, const char *arg
)
288 if (!strcmp(arg
, "-"))
290 return prefix_filename(pfx
, arg
);