linux manual impl of get_canonical to handle non-existent paths

This commit is contained in:
insofaras 2016-09-01 20:30:09 +01:00
parent c82dbd8e2c
commit 0ad5165cf2
1 changed files with 34 additions and 15 deletions

View File

@ -499,26 +499,45 @@ Sys_Set_File_List_Sig(system_set_file_list){
internal internal
Sys_Get_Canonical_Sig(system_get_canonical){ Sys_Get_Canonical_Sig(system_get_canonical){
int32_t result = 0; char* path = (char*) alloca(len + 1);
char* write_p = path;
const char* read_p = filename;
char* path = realpath(strndupa(filename, len), NULL); while(read_p < filename + len){
if(path){ if(read_p == filename || read_p[0] == '/'){
size_t path_len = strlen(path); if(read_p[1] == '/'){
if(max >= path_len){ ++read_p;
memcpy(buffer, path, path_len); } else if(read_p[1] == '.'){
result = path_len; if(read_p[2] == '/' || !read_p[2]){
read_p += 2;
} else if(read_p[2] == '.' && (read_p[3] == '/' || !read_p[3])){
while(write_p > path && *--write_p != '/');
read_p += 3;
} else {
*write_p++ = *read_p++;
}
} else {
*write_p++ = *read_p++;
}
} else {
*write_p++ = *read_p++;
} }
#if FRED_INTERNAL }
if(strncmp(filename, path, len) != 0){ if(write_p == path) *write_p++ = '/';
LINUX_FN_DEBUG("[%.*s] -> [%s]", len, filename, path);
} if(max >= (write_p - path)){
#endif memcpy(buffer, path, write_p - path);
free(path);
} else { } else {
LINUX_FN_DEBUG("[%.*s] -> [null]", len, filename); write_p = path;
} }
return result; #if FRED_INTERNAL
if(len != (write_p - path) || memcmp(filename, path, len) != 0){
LINUX_FN_DEBUG("[%.*s] -> [%.*s]", len, filename, (int)(write_p - path), path);
}
#endif
return write_p - path;
} }
internal internal