ext: Properly follow relative symlinks
This commit is contained in:
parent
af4fb9a387
commit
fe637af458
|
@ -339,15 +339,28 @@ static uint32_t *create_alloc_map(struct ext2_file_handle *fd,
|
||||||
return alloc_map;
|
return alloc_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool symlink_to_inode(struct ext2_inode *inode, struct ext2_file_handle *fd) {
|
static bool symlink_to_inode(struct ext2_inode *inode, struct ext2_file_handle *fd,
|
||||||
|
const char *cwd, size_t cwd_len) {
|
||||||
// I cannot find whether this is 0-terminated or not, so I'm gonna take the
|
// I cannot find whether this is 0-terminated or not, so I'm gonna take the
|
||||||
// safe route here and assume it is not.
|
// safe route here and assume it is not.
|
||||||
if (inode->i_size < 59) {
|
if (inode->i_size < 59) {
|
||||||
struct ext2_dir_entry dir;
|
struct ext2_dir_entry dir;
|
||||||
char *symlink = (char *)inode->i_blocks;
|
char *symlink = (char *)inode->i_blocks;
|
||||||
symlink[59] = 0;
|
symlink[59] = 0;
|
||||||
if (!ext2_parse_dirent(&dir, fd, symlink))
|
|
||||||
|
char *abs = ext_mem_alloc(4096);
|
||||||
|
char *cwd_copy = ext_mem_alloc(cwd_len + 1);
|
||||||
|
memcpy(cwd_copy, cwd, cwd_len);
|
||||||
|
get_absolute_path(abs, symlink, cwd_copy);
|
||||||
|
|
||||||
|
pmm_free(cwd_copy, cwd_len + 1);
|
||||||
|
|
||||||
|
if (!ext2_parse_dirent(&dir, fd, abs)) {
|
||||||
|
pmm_free(abs, 4096);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
pmm_free(abs, 4096);
|
||||||
|
|
||||||
ext2_get_inode(inode, fd, dir.inode);
|
ext2_get_inode(inode, fd, dir.inode);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -367,10 +380,15 @@ static bool ext2_parse_dirent(struct ext2_dir_entry *dir, struct ext2_file_handl
|
||||||
|
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
|
const char *cwd = path;
|
||||||
|
size_t cwd_len = 0;
|
||||||
|
|
||||||
next:
|
next:
|
||||||
memset(token, 0, 256);
|
memset(token, 0, 256);
|
||||||
|
|
||||||
for (size_t i = 0; i < 255 && *path != '/' && *path != '\0'; i++, path++)
|
size_t next_cwd_len = cwd_len;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 255 && *path != '/' && *path != '\0'; i++, path++, next_cwd_len++)
|
||||||
token[i] = *path;
|
token[i] = *path;
|
||||||
|
|
||||||
if (*path == '\0')
|
if (*path == '\0')
|
||||||
|
@ -404,7 +422,7 @@ next:
|
||||||
ext2_get_inode(¤t_inode, fd, dir->inode);
|
ext2_get_inode(¤t_inode, fd, dir->inode);
|
||||||
while ((current_inode.i_mode & FMT_MASK) != S_IFDIR) {
|
while ((current_inode.i_mode & FMT_MASK) != S_IFDIR) {
|
||||||
if ((current_inode.i_mode & FMT_MASK) == S_IFLNK) {
|
if ((current_inode.i_mode & FMT_MASK) == S_IFLNK) {
|
||||||
if (!symlink_to_inode(¤t_inode, fd)) {
|
if (!symlink_to_inode(¤t_inode, fd, cwd, cwd_len)) {
|
||||||
ret = false;
|
ret = false;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -415,6 +433,7 @@ next:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pmm_free(alloc_map, current_inode.i_blocks_count * sizeof(uint32_t));
|
pmm_free(alloc_map, current_inode.i_blocks_count * sizeof(uint32_t));
|
||||||
|
cwd_len = next_cwd_len;
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -471,7 +490,18 @@ struct file_handle *ext2_open(struct volume *part, const char *path) {
|
||||||
|
|
||||||
struct ext2_dir_entry entry;
|
struct ext2_dir_entry entry;
|
||||||
|
|
||||||
|
size_t cwd_len = 0;
|
||||||
|
char *cwd = ext_mem_alloc(4096);
|
||||||
|
for (int i = strlen(path) - 1; i > 0; i--) {
|
||||||
|
if (path[i] == '/' || path[i] == 0) {
|
||||||
|
cwd_len = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memcpy(cwd, path, cwd_len);
|
||||||
|
|
||||||
if (!ext2_parse_dirent(&entry, ret, path)) {
|
if (!ext2_parse_dirent(&entry, ret, path)) {
|
||||||
|
pmm_free(cwd, 4096);
|
||||||
pmm_free(ret, sizeof(struct ext2_file_handle));
|
pmm_free(ret, sizeof(struct ext2_file_handle));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -480,17 +510,21 @@ struct file_handle *ext2_open(struct volume *part, const char *path) {
|
||||||
|
|
||||||
while ((ret->inode.i_mode & FMT_MASK) != S_IFREG) {
|
while ((ret->inode.i_mode & FMT_MASK) != S_IFREG) {
|
||||||
if ((ret->inode.i_mode & FMT_MASK) == S_IFLNK) {
|
if ((ret->inode.i_mode & FMT_MASK) == S_IFLNK) {
|
||||||
if (!symlink_to_inode(&ret->inode, ret)) {
|
if (!symlink_to_inode(&ret->inode, ret, cwd, cwd_len)) {
|
||||||
|
pmm_free(cwd, 4096);
|
||||||
pmm_free(ret, sizeof(struct ext2_file_handle));
|
pmm_free(ret, sizeof(struct ext2_file_handle));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
print("ext2: Entity is not regular file nor symlink\n");
|
print("ext2: Entity is not regular file nor symlink\n");
|
||||||
|
pmm_free(cwd, 4096);
|
||||||
pmm_free(ret, sizeof(struct ext2_file_handle));
|
pmm_free(ret, sizeof(struct ext2_file_handle));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pmm_free(cwd, 4096);
|
||||||
|
|
||||||
ret->size = ret->inode.i_size;
|
ret->size = ret->inode.i_size;
|
||||||
|
|
||||||
ret->alloc_map = create_alloc_map(ret, &ret->inode);
|
ret->alloc_map = create_alloc_map(ret, &ret->inode);
|
||||||
|
|
|
@ -37,6 +37,8 @@ extern bool quiet, serial, editor_enabled;
|
||||||
|
|
||||||
bool parse_resolution(size_t *width, size_t *height, size_t *bpp, const char *buf);
|
bool parse_resolution(size_t *width, size_t *height, size_t *bpp, const char *buf);
|
||||||
|
|
||||||
|
void get_absolute_path(char *path_ptr, const char *path, const char *pwd);
|
||||||
|
|
||||||
uint32_t get_crc32(void *_stream, size_t len);
|
uint32_t get_crc32(void *_stream, size_t len);
|
||||||
|
|
||||||
uint32_t oct2bin(uint8_t *str, uint32_t max);
|
uint32_t oct2bin(uint8_t *str, uint32_t max);
|
||||||
|
|
|
@ -41,3 +41,69 @@ uint64_t strtoui(const char *s, const char **end, int base) {
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void get_absolute_path(char *path_ptr, const char *path, const char *pwd) {
|
||||||
|
char *orig_ptr = path_ptr;
|
||||||
|
|
||||||
|
if (!*path) {
|
||||||
|
strcpy(path_ptr, pwd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*path != '/') {
|
||||||
|
strcpy(path_ptr, pwd);
|
||||||
|
path_ptr += strlen(path_ptr);
|
||||||
|
} else {
|
||||||
|
*path_ptr = '/';
|
||||||
|
path_ptr++;
|
||||||
|
path++;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto first_run;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
switch (*path) {
|
||||||
|
case '/':
|
||||||
|
path++;
|
||||||
|
first_run:
|
||||||
|
if (*path == '/') continue;
|
||||||
|
if ((!strncmp(path, ".\0", 2))
|
||||||
|
|| (!strncmp(path, "./\0", 3))) {
|
||||||
|
goto term;
|
||||||
|
}
|
||||||
|
if ((!strncmp(path, "..\0", 3))
|
||||||
|
|| (!strncmp(path, "../\0", 4))) {
|
||||||
|
while (*path_ptr != '/') path_ptr--;
|
||||||
|
if (path_ptr == orig_ptr) path_ptr++;
|
||||||
|
goto term;
|
||||||
|
}
|
||||||
|
if (!strncmp(path, "../", 3)) {
|
||||||
|
while (*path_ptr != '/') path_ptr--;
|
||||||
|
if (path_ptr == orig_ptr) path_ptr++;
|
||||||
|
path += 2;
|
||||||
|
*path_ptr = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strncmp(path, "./", 2)) {
|
||||||
|
path += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (((path_ptr - 1) != orig_ptr) && (*(path_ptr - 1) != '/')) {
|
||||||
|
*path_ptr = '/';
|
||||||
|
path_ptr++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case '\0':
|
||||||
|
term:
|
||||||
|
if ((*(path_ptr - 1) == '/') && ((path_ptr - 1) != orig_ptr))
|
||||||
|
path_ptr--;
|
||||||
|
*path_ptr = 0;
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
*path_ptr = *path;
|
||||||
|
path++;
|
||||||
|
path_ptr++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue