Compare commits
No commits in common. "049405989b684ebf5c4c5ae4324b6de5488039c5" and "552e574cde247ee0d36b54d93f961c4346e5d38f" have entirely different histories.
049405989b
...
552e574cde
4
config.h
4
config.h
@ -26,8 +26,8 @@
|
|||||||
#define FS_MAX_PATH_LEN 512
|
#define FS_MAX_PATH_LEN 512
|
||||||
#define FS_MAX_OPEN_FD 32
|
#define FS_MAX_OPEN_FD 32
|
||||||
#define FS_MAX_FNAME_LEN 11
|
#define FS_MAX_FNAME_LEN 11
|
||||||
#define FS_MAX_DIRECTORY_DEPTH 2048
|
#define FS_MAX_DIRECTORY_DEPTH 512
|
||||||
#define FS_MAX_SYMLINK_FOLLOWS 1024
|
#define FS_MAX_SYMLINK_FOLLOWING_DEPTH 1024
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
257
src/fs.c
257
src/fs.c
@ -24,7 +24,6 @@ static unsigned int fs_cwd_inode_ptr;
|
|||||||
static struct fs_file_description fs_file_descriptions[FS_MAX_OPEN_FD];
|
static struct fs_file_description fs_file_descriptions[FS_MAX_OPEN_FD];
|
||||||
|
|
||||||
static int extract_basename(char *path, char *name);
|
static int extract_basename(char *path, char *name);
|
||||||
static int read_symlink(int symlink_inode_ptr, char *path);
|
|
||||||
|
|
||||||
|
|
||||||
static int read_block(unsigned int block_no, void *data)
|
static int read_block(unsigned int block_no, void *data)
|
||||||
@ -908,21 +907,18 @@ fs_remove_fname_from_directory_finish:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void resolve_path(struct resolved_path * const rp, const char * const original_path, const unsigned int params)
|
static void resolve_path(struct resolved_path *rp, char *path, unsigned int params)
|
||||||
{
|
{
|
||||||
rp->parent_inode_ptr = -1;
|
rp->parent_inode_ptr = -1;
|
||||||
rp->target_inode_ptr = -1;
|
rp->target_inode_ptr = -1;
|
||||||
|
|
||||||
int path_len = strlen(original_path);
|
int path_len = strlen(path);
|
||||||
|
|
||||||
if (!path_len) {
|
if (!path_len) {
|
||||||
pr_err("no path specified\n");
|
pr_err("no path specified\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char path[FS_MAX_PATH_LEN+1];
|
|
||||||
strcpy(path, original_path);
|
|
||||||
|
|
||||||
if (!strcmp(path, "/")) {
|
if (!strcmp(path, "/")) {
|
||||||
rp->parent_inode_ptr = 0;
|
rp->parent_inode_ptr = 0;
|
||||||
rp->target_inode_ptr = 0;
|
rp->target_inode_ptr = 0;
|
||||||
@ -935,8 +931,6 @@ static void resolve_path(struct resolved_path * const rp, const char * const ori
|
|||||||
int current_inode_ptr;
|
int current_inode_ptr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
unsigned int symlinks_followed = 0;
|
|
||||||
|
|
||||||
if (path[0] == '/') {
|
if (path[0] == '/') {
|
||||||
current_inode_ptr = 0;
|
current_inode_ptr = 0;
|
||||||
rp->parent_inode_ptr = 0;
|
rp->parent_inode_ptr = 0;
|
||||||
@ -956,149 +950,65 @@ static void resolve_path(struct resolved_path * const rp, const char * const ori
|
|||||||
if (path[i] != '/') {
|
if (path[i] != '/') {
|
||||||
next_fname[next_fname_ptr] = path[i];
|
next_fname[next_fname_ptr] = path[i];
|
||||||
next_fname_ptr++;
|
next_fname_ptr++;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((path[i] != '/') && (i+1 < path_len))
|
// path[i] == '/', trying to change current directory
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!next_fname_ptr)
|
if (!next_fname_ptr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (i+1 == path_len)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
{
|
||||||
|
int res = find_fname_in_directory(current_inode_ptr, next_fname);
|
||||||
|
if (res < 0) {
|
||||||
|
pr_warn("directory '%s' does not exist\n", next_fname);
|
||||||
|
rp->parent_inode_ptr = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
struct fs_inode d;
|
||||||
|
read_block(read_inode_ptr(res), &d);
|
||||||
|
|
||||||
|
if (d.ftype == REGULAR) {
|
||||||
|
pr_warn("'%s' is a regular file\n", next_fname);
|
||||||
|
rp->parent_inode_ptr = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pr("Found directory '%s'\n", next_fname);
|
||||||
|
current_inode_ptr = res;
|
||||||
|
rp->parent_inode_ptr = res;
|
||||||
|
}
|
||||||
|
|
||||||
|
next_fname_ptr = 0;
|
||||||
|
strcpy(current_fname, next_fname);
|
||||||
|
memset(next_fname, 0, FS_MAX_FNAME_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rp->parent_inode_ptr < 0) {
|
||||||
|
rp->target_inode_ptr = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(rp->parent_fname, current_fname);
|
||||||
|
|
||||||
|
{
|
||||||
int res = find_fname_in_directory(current_inode_ptr, next_fname);
|
int res = find_fname_in_directory(current_inode_ptr, next_fname);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
if (i+1 < path_len) {
|
pr_warn("target fname '%s' does not exist\n", next_fname);
|
||||||
pr_warn("parent '%s' does not exist\n", next_fname);
|
|
||||||
rp->parent_inode_ptr = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp->target_inode_ptr = -1;
|
rp->target_inode_ptr = -1;
|
||||||
break;
|
} else {
|
||||||
|
rp->target_inode_ptr = res;
|
||||||
|
strcpy(rp->target_fname, next_fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fs_inode d;
|
|
||||||
read_block(read_inode_ptr(res), &d);
|
|
||||||
|
|
||||||
if (d.ftype == SYMLINK) {
|
|
||||||
if (i+1 < path_len) {
|
|
||||||
symlinks_followed++;
|
|
||||||
if (symlinks_followed > FS_MAX_SYMLINK_FOLLOWS) {
|
|
||||||
pr_err("too many symlink follows\n");
|
|
||||||
rp->parent_inode_ptr = -1;
|
|
||||||
rp->target_inode_ptr = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
char symlink_path[FS_MAX_PATH_LEN+1];
|
|
||||||
int symlink_path_len = read_symlink(res, symlink_path);
|
|
||||||
|
|
||||||
if (symlink_path_len < 0) {
|
|
||||||
pr_warn("broken symlink\n");
|
|
||||||
rp->parent_inode_ptr = -1;
|
|
||||||
rp->target_inode_ptr = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (symlink_path[0] == '/') {
|
|
||||||
memmove(&(path[symlink_path_len]), &(path[i+1]), path_len-i-1);
|
|
||||||
strcpy(path, &(symlink_path[1]));
|
|
||||||
path[symlink_path_len-1] = '/';
|
|
||||||
path_len = symlink_path_len + path_len - i - 1;
|
|
||||||
i = -1;
|
|
||||||
|
|
||||||
next_fname_ptr = 0;
|
|
||||||
strcpy(current_fname, "/");
|
|
||||||
memset(next_fname, 0, FS_MAX_FNAME_LEN);
|
|
||||||
} else {
|
|
||||||
memmove(&(path[symlink_path_len+1]), &(path[i+1]), path_len-i-1);
|
|
||||||
strcpy(path, symlink_path);
|
|
||||||
path[symlink_path_len] = '/';
|
|
||||||
path_len = symlink_path_len + path_len - i;
|
|
||||||
i = -1;
|
|
||||||
|
|
||||||
next_fname_ptr = 0;
|
|
||||||
strcpy(current_fname, next_fname);
|
|
||||||
memset(next_fname, 0, FS_MAX_FNAME_LEN);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!(params & FOLLOW_LAST_SYMLINK)) {
|
|
||||||
rp->target_inode_ptr = res;
|
|
||||||
strcpy(rp->parent_fname, current_fname);
|
|
||||||
strcpy(rp->target_fname, next_fname);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
symlinks_followed++;
|
|
||||||
if (symlinks_followed > FS_MAX_SYMLINK_FOLLOWS) {
|
|
||||||
pr_err("too many symlink follows\n");
|
|
||||||
rp->parent_inode_ptr = -1;
|
|
||||||
rp->target_inode_ptr = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
char symlink_path[FS_MAX_PATH_LEN+1];
|
|
||||||
int symlink_path_len = read_symlink(res, symlink_path);
|
|
||||||
|
|
||||||
if (symlink_path_len < 0) {
|
|
||||||
pr_warn("broken symlink\n");
|
|
||||||
rp->parent_inode_ptr = -1;
|
|
||||||
rp->target_inode_ptr = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(symlink_path, "/")) {
|
|
||||||
rp->parent_inode_ptr = 0;
|
|
||||||
rp->target_inode_ptr = 0;
|
|
||||||
strcpy(rp->parent_fname, "/");
|
|
||||||
strcpy(rp->target_fname, "/");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (symlink_path[0] == '/') {
|
|
||||||
strcpy(path, &(symlink_path[1]));
|
|
||||||
path_len = symlink_path_len - 1;
|
|
||||||
i = -1;
|
|
||||||
|
|
||||||
next_fname_ptr = 0;
|
|
||||||
strcpy(current_fname, "/");
|
|
||||||
memset(next_fname, 0, FS_MAX_FNAME_LEN);
|
|
||||||
} else {
|
|
||||||
strcpy(path, symlink_path);
|
|
||||||
path_len = symlink_path_len;
|
|
||||||
i = -1;
|
|
||||||
|
|
||||||
next_fname_ptr = 0;
|
|
||||||
strcpy(current_fname, next_fname);
|
|
||||||
memset(next_fname, 0, FS_MAX_FNAME_LEN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (d.ftype == REGULAR) {
|
|
||||||
if (i+1 < path_len) {
|
|
||||||
pr_warn("'%s': regular file not in the end of a path\n", next_fname);
|
|
||||||
rp->parent_inode_ptr = -1;
|
|
||||||
rp->target_inode_ptr = -1;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
rp->target_inode_ptr = res;
|
|
||||||
strcpy(rp->parent_fname, current_fname);
|
|
||||||
strcpy(rp->target_fname, next_fname);
|
|
||||||
}
|
|
||||||
} else if (d.ftype == DIRECTORY) {
|
|
||||||
if (i+1 < path_len) {
|
|
||||||
pr("Found directory '%s'\n", next_fname);
|
|
||||||
current_inode_ptr = res;
|
|
||||||
rp->parent_inode_ptr = res;
|
|
||||||
|
|
||||||
next_fname_ptr = 0;
|
|
||||||
strcpy(current_fname, next_fname);
|
|
||||||
memset(next_fname, 0, FS_MAX_FNAME_LEN);
|
|
||||||
} else {
|
|
||||||
rp->target_inode_ptr = res;
|
|
||||||
strcpy(rp->parent_fname, current_fname);
|
|
||||||
strcpy(rp->target_fname, next_fname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1721,73 +1631,6 @@ int fs_ln(void *d)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_symlink(int symlink_inode_ptr, char *path)
|
|
||||||
{
|
|
||||||
struct fs_inode i;
|
|
||||||
read_block(read_inode_ptr(symlink_inode_ptr), &i);
|
|
||||||
|
|
||||||
path[0] = '\0';
|
|
||||||
int bytes_read = 0;
|
|
||||||
|
|
||||||
for (int j = 0; j < BLOCK_ADDRESSES_PER_INODE; j++) {
|
|
||||||
if (!i.blocks[j]) {
|
|
||||||
pr_err("inode size (%d) indicates existing block but it's address is absent in inode, symlink at inode_ptr=%d might be broken\n",
|
|
||||||
i.size, symlink_inode_ptr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char data[FS_BLOCK_SIZE];
|
|
||||||
read_block(i.blocks[j], data);
|
|
||||||
|
|
||||||
if (i.size - bytes_read < FS_BLOCK_SIZE) {
|
|
||||||
memcpy(&(path[bytes_read]), data, i.size - bytes_read);
|
|
||||||
bytes_read = i.size;
|
|
||||||
path[bytes_read] = '\0';
|
|
||||||
} else {
|
|
||||||
memcpy(&(path[bytes_read]), data, FS_BLOCK_SIZE);
|
|
||||||
bytes_read += FS_BLOCK_SIZE;
|
|
||||||
path[bytes_read] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i.size == bytes_read)
|
|
||||||
goto finish_reading;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int next_ext = i.next_extension; ; ) {
|
|
||||||
struct fs_inode_extension ext;
|
|
||||||
read_block(next_ext, &ext);
|
|
||||||
|
|
||||||
for (int j = 0; j < BLOCK_ADDRESSES_PER_INODE_EXTENSION; j++) {
|
|
||||||
if (!ext.blocks[j]) {
|
|
||||||
pr_err("inode size (%d) indicates existing block but it's address is absent in inode extension, symlink at inode_ptr=%d might be broken\n",
|
|
||||||
i.size, symlink_inode_ptr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char data[FS_BLOCK_SIZE];
|
|
||||||
read_block(ext.blocks[j], data);
|
|
||||||
|
|
||||||
if (i.size - bytes_read < FS_BLOCK_SIZE) {
|
|
||||||
memcpy(&(path[bytes_read]), data, i.size - bytes_read);
|
|
||||||
bytes_read = i.size;
|
|
||||||
path[bytes_read] = '\0';
|
|
||||||
} else {
|
|
||||||
memcpy(&(path[bytes_read]), data, FS_BLOCK_SIZE);
|
|
||||||
bytes_read += FS_BLOCK_SIZE;
|
|
||||||
path[bytes_read] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i.size == bytes_read)
|
|
||||||
goto finish_reading;
|
|
||||||
}
|
|
||||||
|
|
||||||
next_ext = ext.next_extension;
|
|
||||||
}
|
|
||||||
|
|
||||||
finish_reading:
|
|
||||||
return bytes_read;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fs_symlink(void *d)
|
int fs_symlink(void *d)
|
||||||
{
|
{
|
||||||
char *target_path = ((char **) d)[0];
|
char *target_path = ((char **) d)[0];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user