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 */ 8int is_directory(const char *path) 9{ 10 struct stat st; 11 return (!stat(path, &st) && S_ISDIR(st.st_mode)); 12} 13 14/* We allow "recursive" symbolic links. Only within reason, though. */ 15#define MAXDEPTH 5 16 17/* 18 * Return the real path (i.e., absolute path, with symlinks resolved 19 * and extra slashes removed) equivalent to the specified path. (If 20 * you want an absolute path but don't mind links, use 21 * absolute_path().) The return value is a pointer to a static 22 * buffer. 23 * 24 * The input and all intermediate paths must be shorter than MAX_PATH. 25 * The directory part of path (i.e., everything up to the last 26 * dir_sep) must denote a valid, existing directory, but the last 27 * component need not exist. If die_on_error is set, then die with an 28 * informative error message if there is a problem. Otherwise, return 29 * NULL on errors (without generating any output). 30 * 31 * If path is our buffer, then return path, as it's already what the 32 * user wants. 33 */ 34static const char *real_path_internal(const char *path, int die_on_error) 35{ 36 static struct strbuf sb = STRBUF_INIT; 37 char *retval = NULL; 38 39 /* 40 * If we have to temporarily chdir(), store the original CWD 41 * here so that we can chdir() back to it at the end of the 42 * function: 43 */ 44 struct strbuf cwd = STRBUF_INIT; 45 46 int depth = MAXDEPTH; 47 char *last_elem = NULL; 48 struct stat st; 49 50 /* We've already done it */ 51 if (path == sb.buf) 52 return path; 53 54 if (!*path) { 55 if (die_on_error) 56 die("The empty string is not a valid path"); 57 else 58 goto error_out; 59 } 60 61 strbuf_reset(&sb); 62 strbuf_addstr(&sb, path); 63 64 while (depth--) { 65 if (!is_directory(sb.buf)) { 66 char *last_slash = find_last_dir_sep(sb.buf); 67 if (last_slash) { 68 last_elem = xstrdup(last_slash + 1); 69 strbuf_setlen(&sb, last_slash - sb.buf + 1); 70 } else { 71 last_elem = xmemdupz(sb.buf, sb.len); 72 strbuf_reset(&sb); 73 } 74 } 75 76 if (sb.len) { 77 if (!cwd.len && strbuf_getcwd(&cwd)) { 78 if (die_on_error) 79 die_errno("Could not get current working directory"); 80 else 81 goto error_out; 82 } 83 84 if (chdir(sb.buf)) { 85 if (die_on_error) 86 die_errno("Could not switch to '%s'", 87 sb.buf); 88 else 89 goto error_out; 90 } 91 } 92 if (strbuf_getcwd(&sb)) { 93 if (die_on_error) 94 die_errno("Could not get current working directory"); 95 else 96 goto error_out; 97 } 98 99 if (last_elem) { 100 if (sb.len && !is_dir_sep(sb.buf[sb.len - 1])) 101 strbuf_addch(&sb, '/'); 102 strbuf_addstr(&sb, last_elem); 103 free(last_elem); 104 last_elem = NULL; 105 } 106 107 if (!lstat(sb.buf, &st) && S_ISLNK(st.st_mode)) { 108 struct strbuf next_sb = STRBUF_INIT; 109 ssize_t len = strbuf_readlink(&next_sb, sb.buf, 0); 110 if (len < 0) { 111 if (die_on_error) 112 die_errno("Invalid symlink '%s'", 113 sb.buf); 114 else 115 goto error_out; 116 } 117 strbuf_swap(&sb, &next_sb); 118 strbuf_release(&next_sb); 119 } else 120 break; 121 } 122 123 retval = sb.buf; 124error_out: 125 free(last_elem); 126 if (cwd.len && chdir(cwd.buf)) 127 die_errno("Could not change back to '%s'", cwd.buf); 128 strbuf_release(&cwd); 129 130 return retval; 131} 132 133const char *real_path(const char *path) 134{ 135 return real_path_internal(path, 1); 136} 137 138const char *real_path_if_valid(const char *path) 139{ 140 return real_path_internal(path, 0); 141} 142 143/* 144 * Use this to get an absolute path from a relative one. If you want 145 * to resolve links, you should use real_path. 146 */ 147const char *absolute_path(const char *path) 148{ 149 static struct strbuf sb = STRBUF_INIT; 150 strbuf_reset(&sb); 151 strbuf_add_absolute_path(&sb, path); 152 return sb.buf; 153} 154 155/* 156 * Unlike prefix_path, this should be used if the named file does 157 * not have to interact with index entry; i.e. name of a random file 158 * on the filesystem. 159 */ 160const char *prefix_filename(const char *pfx, int pfx_len, const char *arg) 161{ 162 static struct strbuf path = STRBUF_INIT; 163#ifndef GIT_WINDOWS_NATIVE 164 if (!pfx_len || is_absolute_path(arg)) 165 return arg; 166 strbuf_reset(&path); 167 strbuf_add(&path, pfx, pfx_len); 168 strbuf_addstr(&path, arg); 169#else 170 char *p; 171 /* don't add prefix to absolute paths, but still replace '\' by '/' */ 172 strbuf_reset(&path); 173 if (is_absolute_path(arg)) 174 pfx_len = 0; 175 else if (pfx_len) 176 strbuf_add(&path, pfx, pfx_len); 177 strbuf_addstr(&path, arg); 178 for (p = path.buf + pfx_len; *p; p++) 179 if (*p == '\\') 180 *p = '/'; 181#endif 182 return path.buf; 183}