You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
64 lines
1.3 KiB
64 lines
1.3 KiB
#include "cache.h" |
|
|
|
struct pathname { |
|
int len; |
|
char path[PATH_MAX]; |
|
}; |
|
|
|
/* Return matching pathname prefix length, or zero if not matching */ |
|
static inline int match_pathname(int len, const char *name, struct pathname *match) |
|
{ |
|
int match_len = match->len; |
|
return (len > match_len && |
|
name[match_len] == '/' && |
|
!memcmp(name, match->path, match_len)) ? match_len : 0; |
|
} |
|
|
|
static inline void set_pathname(int len, const char *name, struct pathname *match) |
|
{ |
|
if (len < PATH_MAX) { |
|
match->len = len; |
|
memcpy(match->path, name, len); |
|
match->path[len] = 0; |
|
} |
|
} |
|
|
|
int has_symlink_leading_path(int len, const char *name) |
|
{ |
|
static struct pathname link, nonlink; |
|
char path[PATH_MAX]; |
|
struct stat st; |
|
char *sp; |
|
int known_dir; |
|
|
|
/* |
|
* See if the last known symlink cache matches. |
|
*/ |
|
if (match_pathname(len, name, &link)) |
|
return 1; |
|
|
|
/* |
|
* Get rid of the last known directory part |
|
*/ |
|
known_dir = match_pathname(len, name, &nonlink); |
|
|
|
while ((sp = strchr(name + known_dir + 1, '/')) != NULL) { |
|
int thislen = sp - name ; |
|
memcpy(path, name, thislen); |
|
path[thislen] = 0; |
|
|
|
if (lstat(path, &st)) |
|
return 0; |
|
if (S_ISDIR(st.st_mode)) { |
|
set_pathname(thislen, path, &nonlink); |
|
known_dir = thislen; |
|
continue; |
|
} |
|
if (S_ISLNK(st.st_mode)) { |
|
set_pathname(thislen, path, &link); |
|
return 1; |
|
} |
|
break; |
|
} |
|
return 0; |
|
}
|
|
|