real_path: resolve symlinks by hand
[git] / abspath.c
1 #include "cache.h"
2
3 /*
4  * Do not use this for inspecting *tracked* content.  When path is a
5  * symlink to a directory, we do not want to say it is a directory when
6  * dealing with tracked content in the working tree.
7  */
8 int is_directory(const char *path)
9 {
10         struct stat st;
11         return (!stat(path, &st) && S_ISDIR(st.st_mode));
12 }
13
14 /* removes the last path component from 'path' except if 'path' is root */
15 static void strip_last_component(struct strbuf *path)
16 {
17         size_t offset = offset_1st_component(path->buf);
18         size_t len = path->len;
19
20         /* Find start of the last component */
21         while (offset < len && !is_dir_sep(path->buf[len - 1]))
22                 len--;
23         /* Skip sequences of multiple path-separators */
24         while (offset < len && is_dir_sep(path->buf[len - 1]))
25                 len--;
26
27         strbuf_setlen(path, len);
28 }
29
30 /* get (and remove) the next component in 'remaining' and place it in 'next' */
31 static void get_next_component(struct strbuf *next, struct strbuf *remaining)
32 {
33         char *start = NULL;
34         char *end = NULL;
35
36         strbuf_reset(next);
37
38         /* look for the next component */
39         /* Skip sequences of multiple path-separators */
40         for (start = remaining->buf; is_dir_sep(*start); start++)
41                 ; /* nothing */
42         /* Find end of the path component */
43         for (end = start; *end && !is_dir_sep(*end); end++)
44                 ; /* nothing */
45
46         strbuf_add(next, start, end - start);
47         /* remove the component from 'remaining' */
48         strbuf_remove(remaining, 0, end - remaining->buf);
49 }
50
51 /* We allow "recursive" symbolic links. Only within reason, though. */
52 #define MAXSYMLINKS 5
53
54 /*
55  * Return the real path (i.e., absolute path, with symlinks resolved
56  * and extra slashes removed) equivalent to the specified path.  (If
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.
60  *
61  * The directory part of path (i.e., everything up to the last
62  * dir_sep) must denote a valid, existing directory, but the last
63  * component need not exist.  If die_on_error is set, then die with an
64  * informative error message if there is a problem.  Otherwise, return
65  * 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  */
70 static const char *real_path_internal(const char *path, int die_on_error)
71 {
72         static struct strbuf resolved = STRBUF_INIT;
73         struct strbuf remaining = STRBUF_INIT;
74         struct strbuf next = STRBUF_INIT;
75         struct strbuf symlink = STRBUF_INIT;
76         char *retval = NULL;
77         int num_symlinks = 0;
78         struct stat st;
79
80         /* We've already done it */
81         if (path == resolved.buf)
82                 return path;
83
84         if (!*path) {
85                 if (die_on_error)
86                         die("The empty string is not a valid path");
87                 else
88                         goto error_out;
89         }
90
91         strbuf_reset(&resolved);
92
93         if (is_absolute_path(path)) {
94                 /* absolute path; start with only root as being resolved */
95                 int offset = offset_1st_component(path);
96                 strbuf_add(&resolved, path, offset);
97                 strbuf_addstr(&remaining, path + offset);
98         } else {
99                 /* relative path; can use CWD as the initial resolved path */
100                 if (strbuf_getcwd(&resolved)) {
101                         if (die_on_error)
102                                 die_errno("unable to get current working directory");
103                         else
104                                 goto error_out;
105                 }
106                 strbuf_addstr(&remaining, path);
107         }
108
109         /* Iterate over the remaining path components */
110         while (remaining.len > 0) {
111                 get_next_component(&next, &remaining);
112
113                 if (next.len == 0) {
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);
120                         continue;
121                 }
122
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);
127
128                 if (lstat(resolved.buf, &st)) {
129                         /* error out unless this was the last component */
130                         if (errno != ENOENT || remaining.len) {
131                                 if (die_on_error)
132                                         die_errno("Invalid path '%s'",
133                                                   resolved.buf);
134                                 else
135                                         goto error_out;
136                         }
137                 } else if (S_ISLNK(st.st_mode)) {
138                         ssize_t len;
139                         strbuf_reset(&symlink);
140
141                         if (num_symlinks++ > MAXSYMLINKS) {
142                                 if (die_on_error)
143                                         die("More than %d nested symlinks "
144                                             "on path '%s'", MAXSYMLINKS, path);
145                                 else
146                                         goto error_out;
147                         }
148
149                         len = strbuf_readlink(&symlink, resolved.buf,
150                                               st.st_size);
151                         if (len < 0) {
152                                 if (die_on_error)
153                                         die_errno("Invalid symlink '%s'",
154                                                   resolved.buf);
155                                 else
156                                         goto error_out;
157                         }
158
159                         if (is_absolute_path(symlink.buf)) {
160                                 /* absolute symlink; set resolved to root */
161                                 int offset = offset_1st_component(symlink.buf);
162                                 strbuf_reset(&resolved);
163                                 strbuf_add(&resolved, symlink.buf, offset);
164                                 strbuf_remove(&symlink, 0, offset);
165                         } else {
166                                 /*
167                                  * relative symlink
168                                  * strip off the last component since it will
169                                  * be replaced with the contents of the symlink
170                                  */
171                                 strip_last_component(&resolved);
172                         }
173
174                         /*
175                          * if there are still remaining components to resolve
176                          * then append them to symlink
177                          */
178                         if (remaining.len) {
179                                 strbuf_addch(&symlink, '/');
180                                 strbuf_addbuf(&symlink, &remaining);
181                         }
182
183                         /*
184                          * use the symlink as the remaining components that
185                          * need to be resloved
186                          */
187                         strbuf_swap(&symlink, &remaining);
188                 }
189         }
190
191         retval = resolved.buf;
192
193 error_out:
194         strbuf_release(&remaining);
195         strbuf_release(&next);
196         strbuf_release(&symlink);
197
198         return retval;
199 }
200
201 const char *real_path(const char *path)
202 {
203         return real_path_internal(path, 1);
204 }
205
206 const char *real_path_if_valid(const char *path)
207 {
208         return real_path_internal(path, 0);
209 }
210
211 /*
212  * Use this to get an absolute path from a relative one. If you want
213  * to resolve links, you should use real_path.
214  */
215 const char *absolute_path(const char *path)
216 {
217         static struct strbuf sb = STRBUF_INIT;
218         strbuf_reset(&sb);
219         strbuf_add_absolute_path(&sb, path);
220         return sb.buf;
221 }
222
223 /*
224  * Unlike prefix_path, this should be used if the named file does
225  * not have to interact with index entry; i.e. name of a random file
226  * on the filesystem.
227  */
228 const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
229 {
230         static struct strbuf path = STRBUF_INIT;
231 #ifndef GIT_WINDOWS_NATIVE
232         if (!pfx_len || is_absolute_path(arg))
233                 return arg;
234         strbuf_reset(&path);
235         strbuf_add(&path, pfx, pfx_len);
236         strbuf_addstr(&path, arg);
237 #else
238         /* don't add prefix to absolute paths, but still replace '\' by '/' */
239         strbuf_reset(&path);
240         if (is_absolute_path(arg))
241                 pfx_len = 0;
242         else if (pfx_len)
243                 strbuf_add(&path, pfx, pfx_len);
244         strbuf_addstr(&path, arg);
245         convert_slashes(path.buf + pfx_len);
246 #endif
247         return path.buf;
248 }