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