From 941c51200c9bbcdc0fd60041a1656643f72d1d18 Mon Sep 17 00:00:00 2001 From: hasslesstech Date: Fri, 16 May 2025 14:32:44 +0300 Subject: [PATCH] fix fs_mkdir and fs_cd --- inc/fs.h | 7 +++ src/fs.c | 155 ++++++++++++++++++++++++++++++------------------------- 2 files changed, 91 insertions(+), 71 deletions(-) diff --git a/inc/fs.h b/inc/fs.h index 1219591..797e28e 100644 --- a/inc/fs.h +++ b/inc/fs.h @@ -46,6 +46,13 @@ struct fs_file_description { unsigned int rw_offset; }; +struct resolved_path { + int target_inode_ptr; + int parent_inode_ptr; + char target_fname[FS_MAX_FNAME_LEN+1]; + char parent_fname[FS_MAX_FNAME_LEN+1]; +}; + char *fs_get_cwd(void); int fs_create(void *d); diff --git a/src/fs.c b/src/fs.c index b3bd919..9694568 100644 --- a/src/fs.c +++ b/src/fs.c @@ -23,6 +23,8 @@ static unsigned int fs_cwd_inode_ptr; static struct fs_file_description fs_file_descriptions[FS_MAX_OPEN_FD]; +static int extract_basename(char *path, char *name); + static int read_block(unsigned int block_no, void *data) { @@ -572,12 +574,13 @@ static int find_fname_in_directory(unsigned int dir_inode_ptr, char *fname) int *r = find_filename_in_directory(dir_inode_ptr, fname); int res; - if (r) + if (r) { res = r[2]; - else + free(r); + } else { res = -1; + } - free(r); return res; } @@ -898,23 +901,31 @@ fs_remove_fname_from_directory_finish: return 0; } -static int resolve_directory(char *path) +static void resolve_directory(struct resolved_path *rp, char *path) { + rp->parent_inode_ptr = -1; + rp->target_inode_ptr = -1; + int path_len = strlen(path); if (!path_len) { pr_err("no path specified\n"); - return -1; + return; } + char current_dir_name[FS_MAX_FNAME_LEN+1] = {}; int current_dir_inode_ptr; int i; if (path[0] == '/') { current_dir_inode_ptr = 0; + rp->parent_inode_ptr = 0; + strcpy(current_dir_name, "/"); i = 1; } else { current_dir_inode_ptr = fs_cwd_inode_ptr; + rp->parent_inode_ptr = fs_cwd_inode_ptr; + extract_basename(fs_cwd, current_dir_name); i = 0; } @@ -937,34 +948,53 @@ static int resolve_directory(char *path) continue; { - int *res = find_filename_in_directory(current_dir_inode_ptr, next_dir_name); - if (!res) { - pr_err("directory '%s' does not exist\n", next_dir_name); - return -1; + int res = find_fname_in_directory(current_dir_inode_ptr, next_dir_name); + if (res < 0) { + pr_warn("directory '%s' does not exist\n", next_dir_name); + rp->parent_inode_ptr = -1; + break; } { struct fs_inode d; - read_block(read_inode_ptr(res[2]), &d); + read_block(read_inode_ptr(res), &d); if (d.ftype == REGULAR) { - free(res); - pr_err("'%s' is a regular file\n", next_dir_name); - return -1; + pr_warn("'%s' is a regular file\n", next_dir_name); + rp->parent_inode_ptr = -1; + break; } } pr("Found directory '%s'\n", next_dir_name); - current_dir_inode_ptr = res[2]; - - free(res); + current_dir_inode_ptr = res; + rp->parent_inode_ptr = res; } next_dir_name_ptr = 0; + strcpy(current_dir_name, next_dir_name); memset(next_dir_name, 0, FS_MAX_FNAME_LEN); } - return current_dir_inode_ptr; + if (rp->parent_inode_ptr < 0) { + rp->target_inode_ptr = -1; + return; + } + + strcpy(rp->parent_fname, current_dir_name); + + { + int res = find_fname_in_directory(current_dir_inode_ptr, next_dir_name); + if (res < 0) { + pr_warn("target fname '%s' does not exist\n", next_dir_name); + rp->target_inode_ptr = -1; + } else { + rp->target_inode_ptr = res; + strcpy(rp->target_fname, next_dir_name); + } + } + + return; } @@ -1678,9 +1708,14 @@ int fs_mkdir(void *d) return 0; } - int target_directory_inode_ptr = resolve_directory(dirpath); - if (target_directory_inode_ptr < 0) { - pr_err("failed to resolve path '%s'\n", dirpath); + struct resolved_path rp; + resolve_directory(&rp, dirpath); + if (rp.parent_inode_ptr < 0) { + pr_err("failed to find parent of '%s'\n", dirpath); + return 0; + } else if (rp.target_inode_ptr >= 0) { + pr_err("fname '%s' already exists in directory '%s'\n", + rp.target_fname, rp.parent_fname); return 0; } @@ -1690,48 +1725,32 @@ int fs_mkdir(void *d) return 0; } - int inode_block_ptr = find_free_block(); - if (!inode_block_ptr) { + int target_inode_block = find_free_block(); + if (!target_inode_block) { pr_err("no space left on device\n"); return 0; } - int parent_directory_inode_ptr; - { - char full_directory_path[FS_MAX_PATH_LEN+1]; - strcpy(full_directory_path, fs_cwd); - strcat(full_directory_path, "/"); - strcat(full_directory_path, dirpath); - - char parent_directory_path[FS_MAX_PATH_LEN+1]; - extract_parent_directory_path(full_directory_path, parent_directory_path); - - parent_directory_inode_ptr = resolve_directory(parent_directory_path); - if (parent_directory_inode_ptr < 0) { - pr_err("parent directory ('%s') does not exist\n", parent_directory_path); - return 0; - } - } - struct fs_inode dir; memset(&dir, 0, sizeof(dir)); dir.ftype = DIRECTORY; dir.ref_count = 1; - write_block(inode_block_ptr, &dir); - mark_used(inode_block_ptr); + write_block(target_inode_block, &dir); + mark_used(target_inode_block); - write_inode_ptr(target_inode_ptr, inode_block_ptr); + write_inode_ptr(target_inode_ptr, target_inode_block); - if (fs_add_fname_to_directory(target_directory_inode_ptr, target_inode_ptr, dirname) < 0) { - pr_err("failed to add record '%s' -> %d to directory inode_ptr=%d\n", - dirname, target_inode_ptr, target_directory_inode_ptr); + if (fs_add_fname_to_directory(rp.parent_inode_ptr, target_inode_ptr, dirname) < 0) { + pr_err("failed to add record '%s' -> inode_ptr=%d to directory '%s' (inode_ptr=%d)\n", + dirname, target_inode_ptr, rp.parent_fname, rp.parent_inode_ptr); + return 0; } // add . and .. fs_add_fname_to_directory(target_inode_ptr, target_inode_ptr, "."); - fs_add_fname_to_directory(target_inode_ptr, parent_directory_inode_ptr, ".."); + fs_add_fname_to_directory(target_inode_ptr, rp.parent_inode_ptr, ".."); } @@ -1799,48 +1818,43 @@ static int get_fname_by_inode_ptr(int dir_inode_ptr, int file_inode_ptr, char *n static int build_canonical_dir_path(char *path, int dir_inode_ptr) { - // build directory inode_ptr-based path - //int *dir_inode_ptrs = NULL; + // build directory inode_ptr-based reverse path int dir_inode_ptrs[FS_MAX_DIRECTORY_DEPTH]; int dir_inode_ptrs_len = 1; dir_inode_ptrs[0] = dir_inode_ptr; - int current_dir_inode_ptr = dir_inode_ptr; for ( ; dir_inode_ptrs_len < FS_MAX_DIRECTORY_DEPTH; dir_inode_ptrs_len++) { // check if reached the root dir if (!dir_inode_ptrs[dir_inode_ptrs_len-1]) break; - int *r = find_filename_in_directory(current_dir_inode_ptr, ".."); + int *r = find_filename_in_directory(dir_inode_ptrs[dir_inode_ptrs_len-1], ".."); if (!r) { - pr_err("failed to find parent directory of inode_ptr=%d\n", current_dir_inode_ptr); + pr_err("failed to find parent directory of inode_ptr=%d\n", dir_inode_ptrs[dir_inode_ptrs_len-1]); return -1; } - //realloc(dir_inode_ptrs, sizeof(int) * dir_inode_ptrs_len); dir_inode_ptrs[dir_inode_ptrs_len] = r[2]; free(r); } - // build path based on inode_ptr list + // build string path based on inode_ptr list memset(path, 0, sizeof(FS_MAX_PATH_LEN)); - path[0] = '/'; for (int i = dir_inode_ptrs_len - 2; i >= 0; i--) { char fname[FS_MAX_FNAME_LEN+1]; if (get_fname_by_inode_ptr(dir_inode_ptrs[i+1], dir_inode_ptrs[i], fname) < 0) { pr_err("failed to build canonical path\n"); - //free(dir_inode_ptrs); return -1; } + strcat(path, "/"); strcat(path, fname); } - //free(dir_inode_ptrs); return 0; } @@ -1854,33 +1868,32 @@ int fs_cd(void *d) return 0; } - int new_dir_parent_inode_ptr = resolve_directory(new_dir); - if (new_dir_parent_inode_ptr < 0) { - pr_err("failed to resolve path '%s' from '%s'\n", new_dir, fs_cwd); + struct resolved_path rp; + resolve_directory(&rp, new_dir); + + if (rp.parent_inode_ptr < 0) { + pr_err("failed to find parent of '%s' from '%s'\n", new_dir, fs_cwd); return 0; } - char top_dir_name[FS_MAX_FNAME_LEN+1]; - if (extract_basename(new_dir, top_dir_name) < 0) { - pr_err("failed to extract base name from '%s'\n", new_dir); - return 0; - } - - int new_dir_inode_ptr = find_fname_in_directory(new_dir_parent_inode_ptr, top_dir_name); - if (new_dir_inode_ptr < 0) { - pr_err("no such directory: '%s'\n", top_dir_name); + if (rp.target_inode_ptr < 0) { + pr_err("no fname '%s' in directory '%s'\n", rp.target_fname, rp.parent_fname); return 0; } char canonical_path[FS_MAX_PATH_LEN+1]; - if (build_canonical_dir_path(canonical_path, new_dir_inode_ptr) < 0) { - pr_err("failed to build canonical path to '%s'\n", new_dir); + if (build_canonical_dir_path(canonical_path, rp.target_inode_ptr) < 0) { + pr_err("failed to build canonical path to '%s' (inode_ptr=%d)\n", + new_dir, rp.target_inode_ptr); return 0; } + if (!canonical_path[0]) + canonical_path[0] = '/'; + char *cpp = (char *) canonical_path; fs_chdir(&cpp); - fs_cwd_inode_ptr = new_dir_inode_ptr; + fs_cwd_inode_ptr = rp.target_inode_ptr; return 0; }