diff --git a/src/fs.c b/src/fs.c index 6bf3e41..8bca2b9 100644 --- a/src/fs.c +++ b/src/fs.c @@ -24,6 +24,7 @@ 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_symlink(int symlink_inode_ptr, char *path); static int read_block(unsigned int block_no, void *data) @@ -953,21 +954,22 @@ static void resolve_path(struct resolved_path * const rp, const char * const ori if (path[i] != '/') { next_fname[next_fname_ptr] = path[i]; next_fname_ptr++; - continue; } - // path[i] == '/', trying to change current directory + if ((path[i] != '/') && (i+1 < path_len)) + continue; if (!next_fname_ptr) 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; + if (i+1 < path_len) { + pr_warn("parent '%s' does not exist\n", next_fname); + rp->parent_inode_ptr = -1; + } + + rp->target_inode_ptr = -1; break; } @@ -975,83 +977,110 @@ static void resolve_path(struct resolved_path * const rp, const char * const ori read_block(read_inode_ptr(res), &d); if (d.ftype == SYMLINK) { - char symlink_path[FS_MAX_PATH_LEN+1]; - int symlink_path_len = read_symlink(res, symlink_path); + if (i+1 < path_len) { + 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; - break; - } + 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, "/"); - return; - } + 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; - if (symlink_path[0] == '/') { - res = 0; - memmove(&(path[symlink_path_len]), &(path[i+1]), path_len-i-1); - path[symlink_path_len-1] = '/'; - memcpy(path, &(symlink_path[1]), symlink_path_len-1); - path_len = symlink_path_len + path_len - i + 1; - i = -1; - strcpy(next_fname, "/"); + 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 { - memmove(&(path[symlink_path_len+1]), &(path[i+1]), path_len-i-1); - path[symlink_path_len] = '/'; - memcpy(path, symlink_path, symlink_path_len); - path_len = symlink_path_len + path_len - i + 2; - i = -1; + if (!(params & FOLLOW_LAST_SYMLINK)) { + rp->target_inode_ptr = res; + strcpy(rp->parent_fname, current_fname); + strcpy(rp->target_fname, next_fname); + 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) { - pr_warn("'%s' is a regular file\n", next_fname); - rp->parent_inode_ptr = -1; - break; + 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) { - pr("Found directory '%s'\n", next_fname); - current_inode_ptr = res; - rp->parent_inode_ptr = res; + 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); + } } - 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); - if (res < 0) { - pr_warn("target fname '%s' does not exist\n", next_fname); - rp->target_inode_ptr = -1; - } - - struct fs_inode i; - read_block(res, &i); - - if (i.ftype == SYMLINK && (params & FOLLOW_LAST_SYMLINK)) - struct - /* - rp->target_inode_ptr = res; - strcpy(rp->target_fname, next_fname); - */ - } else { - rp->target_inode_ptr = res; - strcpy(rp->target_fname, next_fname); - } - } - - return; }