7 Commits

4 changed files with 337 additions and 74 deletions
+4 -4
View File
@@ -14,9 +14,9 @@
/* CLI config section */ /* CLI config section */
#define CLI_MAX_LINE_LENGTH 256 #define CLI_MAX_LINE_LENGTH 1024
#define CLI_MAX_ACCEPTED_ARGS 4 #define CLI_MAX_ACCEPTED_ARGS 4
#define CLI_MAX_TOKEN_LENGTH 64 #define CLI_MAX_TOKEN_LENGTH 256
/* FS config section */ /* FS config section */
@@ -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 512 #define FS_MAX_DIRECTORY_DEPTH 2048
#define FS_MAX_SYMLINK_FOLLOWING_DEPTH 1024 #define FS_MAX_SYMLINK_FOLLOWS 1024
#endif #endif
+10 -4
View File
@@ -9,6 +9,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
static const struct CliCommandEntry cmd[] = { static const struct CliCommandEntry cmd[] = {
@@ -208,11 +209,11 @@ abandon_struct:
unsigned int cli_poll_process_next(void) unsigned int cli_poll_process_next(void)
{ {
for ( ;; ) { int echo_commands = !isatty(STDIN_FILENO);
fputs(fs_get_cwd(), stdout);
for ( ;; ) {
if (fs_get_cwd()[0]) { if (fs_get_cwd()[0]) {
printf(" $ "); printf("%s $ ", fs_get_cwd());
} else { } else {
printf("$ "); printf("$ ");
} }
@@ -221,8 +222,13 @@ unsigned int cli_poll_process_next(void)
char *line = NULL; char *line = NULL;
ssize_t result = getline(&line, &buf_size, stdin); ssize_t result = getline(&line, &buf_size, stdin);
if (result == -1) if (result == -1) {
printf("\n");
return 0x1; return 0x1;
}
if (echo_commands)
printf(line);
char **tokenized_line = tokenize_line(line, result); char **tokenized_line = tokenize_line(line, result);
free(line); free(line);
+268 -66
View File
@@ -24,6 +24,7 @@ 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)
@@ -907,18 +908,21 @@ fs_remove_fname_from_directory_finish:
return 0; return 0;
} }
static void resolve_path(struct resolved_path *rp, char *path, unsigned int params) static void resolve_path(struct resolved_path * const rp, const char * const original_path, const 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(path); int path_len = strlen(original_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;
@@ -931,6 +935,8 @@ static void resolve_path(struct resolved_path *rp, char *path, unsigned int para
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;
@@ -950,65 +956,156 @@ static void resolve_path(struct resolved_path *rp, char *path, unsigned int para
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;
} }
// path[i] == '/', trying to change current directory if ((path[i] != '/') && (i+1 < path_len))
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) {
pr_warn("target fname '%s' does not exist\n", next_fname); if (i+1 < path_len) {
rp->target_inode_ptr = -1; pr_warn("parent '%s' does not exist\n", next_fname);
} else { rp->parent_inode_ptr = -1;
rp->target_inode_ptr = res; }
strcpy(rp->target_fname, next_fname);
}
}
return; rp->target_inode_ptr = -1;
break;
}
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;
}
pr("Found symlink '%s', following (-> '%s')\n", next_fname, symlink_path);
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)) {
pr("Stopping at symlink '%s', not following\n", next_fname);
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;
}
pr("Found symlink '%s' at last position, following (-> '%s')\n", next_fname, symlink_path);
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 {
pr("Stopping at regular file '%s'\n", next_fname);
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 {
pr("Stopping at directory '%s'\n", next_fname);
rp->target_inode_ptr = res;
strcpy(rp->parent_fname, current_fname);
strcpy(rp->target_fname, next_fname);
}
}
}
} }
@@ -1631,6 +1728,73 @@ 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];
@@ -2262,15 +2426,29 @@ int fs_la(void *d)
struct fs_inode f_inode; struct fs_inode f_inode;
read_block(read_inode_ptr(recs[k].inode_no), (void *) &f_inode); read_block(read_inode_ptr(recs[k].inode_no), (void *) &f_inode);
if (f_inode.ftype == DIRECTORY) { if (f_inode.ftype == REGULAR) {
pr_stdout("%s (inode_ptr=%d -> inode=%d, ref_count=%d, size=%d, type=reg)\n",
recs[k].fname, recs[k].inode_no, read_inode_ptr(recs[k].inode_no),
f_inode.ref_count, f_inode.size);
} else if (f_inode.ftype == DIRECTORY) {
pr_stdout(COLOR_BLUE "%s" COLOR_RESET pr_stdout(COLOR_BLUE "%s" COLOR_RESET
" (inode_ptr=%d -> inode=%d, ref_count=%d, size=%d, type=dir)\n", " (inode_ptr=%d -> inode=%d, ref_count=%d, size=%d, type=dir)\n",
recs[k].fname, recs[k].inode_no, read_inode_ptr(recs[k].inode_no), recs[k].fname, recs[k].inode_no, read_inode_ptr(recs[k].inode_no),
f_inode.ref_count, f_inode.size); f_inode.ref_count, f_inode.size);
} else { } else if (f_inode.ftype == SYMLINK) {
pr_stdout("%s (inode_ptr=%d -> inode=%d, ref_count=%d, size=%d, type=reg)\n", char l_path[FS_MAX_PATH_LEN+1];
recs[k].fname, recs[k].inode_no, read_inode_ptr(recs[k].inode_no), int l_path_len = read_symlink(recs[k].inode_no, l_path);
f_inode.ref_count, f_inode.size);
if (l_path_len > 0)
pr_stdout(COLOR_CYAN "%s" COLOR_RESET
" (inode_ptr=%d -> inode=%d, ref_count=%d, size=%d, type=lnk, -> '%s')\n",
recs[k].fname, recs[k].inode_no, read_inode_ptr(recs[k].inode_no),
f_inode.ref_count, f_inode.size, l_path);
else
pr_stdout(COLOR_RED "%s" COLOR_RESET
" (inode_ptr=%d -> inode=%d, ref_count=%d, size=%d, type=lnk)\n",
recs[k].fname, recs[k].inode_no, read_inode_ptr(recs[k].inode_no),
f_inode.ref_count, f_inode.size);
} }
} }
} }
@@ -2297,15 +2475,29 @@ int fs_la(void *d)
struct fs_inode f_inode; struct fs_inode f_inode;
read_block(read_inode_ptr(recs[k].inode_no), (void *) &f_inode); read_block(read_inode_ptr(recs[k].inode_no), (void *) &f_inode);
if (f_inode.ftype == DIRECTORY) { if (f_inode.ftype == REGULAR) {
pr_stdout("%s (inode_ptr=%d -> inode=%d, ref_count=%d, size=%d, type=reg)\n",
recs[k].fname, recs[k].inode_no, read_inode_ptr(recs[k].inode_no),
f_inode.ref_count, f_inode.size);
} else if (f_inode.ftype == DIRECTORY) {
pr_stdout(COLOR_BLUE "%s" COLOR_RESET pr_stdout(COLOR_BLUE "%s" COLOR_RESET
" (inode_ptr=%d -> inode=%d, ref_count=%d, size=%d, type=dir)\n", " (inode_ptr=%d -> inode=%d, ref_count=%d, size=%d, type=dir)\n",
recs[k].fname, recs[k].inode_no, read_inode_ptr(recs[k].inode_no), recs[k].fname, recs[k].inode_no, read_inode_ptr(recs[k].inode_no),
f_inode.ref_count, f_inode.size); f_inode.ref_count, f_inode.size);
} else { } else if (f_inode.ftype == SYMLINK) {
pr_stdout("%s (inode_ptr=%d -> inode=%d, ref_count=%d, size=%d, type=reg)\n", char l_path[FS_MAX_PATH_LEN+1];
recs[k].fname, recs[k].inode_no, read_inode_ptr(recs[k].inode_no), int l_path_len = read_symlink(recs[k].inode_no, l_path);
f_inode.ref_count, f_inode.size);
if (l_path_len > 0)
pr_stdout(COLOR_CYAN "%s" COLOR_RESET
" (inode_ptr=%d -> inode=%d, ref_count=%d, size=%d, type=lnk, -> '%s')\n",
recs[k].fname, recs[k].inode_no, read_inode_ptr(recs[k].inode_no),
f_inode.ref_count, f_inode.size, l_path);
else
pr_stdout(COLOR_RED "%s" COLOR_RESET
" (inode_ptr=%d -> inode=%d, ref_count=%d, size=%d, type=lnk)\n",
recs[k].fname, recs[k].inode_no, read_inode_ptr(recs[k].inode_no),
f_inode.ref_count, f_inode.size);
} }
} }
} }
@@ -2329,12 +2521,22 @@ int fs_stat(void *d)
struct fs_inode i; struct fs_inode i;
read_block(read_inode_ptr(rp.target_inode_ptr), &i); read_block(read_inode_ptr(rp.target_inode_ptr), &i);
if (i.ftype == DIRECTORY) { if (i.ftype == REGULAR) {
pr_stdout("inode_ptr=%d -> inode=%d\nref_count=%d\nsize=%d\ntype=dir\n", pr_stdout("inode_ptr=%d -> inode=%d\nref_count=%d\nsize=%d\ntype=regular\n",
rp.target_inode_ptr, read_inode_ptr(rp.target_inode_ptr), i.ref_count, i.size); rp.target_inode_ptr, read_inode_ptr(rp.target_inode_ptr), i.ref_count, i.size);
} else { } else if (i.ftype == DIRECTORY) {
pr_stdout("inode_ptr=%d -> inode=%d\nref_count=%d\nsize=%d\ntype=reg\n", pr_stdout("inode_ptr=%d -> inode=%d\nref_count=%d\nsize=%d\ntype=directory\n",
rp.target_inode_ptr, read_inode_ptr(rp.target_inode_ptr), i.ref_count, i.size); rp.target_inode_ptr, read_inode_ptr(rp.target_inode_ptr), i.ref_count, i.size);
} else if (i.ftype == SYMLINK) {
char l_path[FS_MAX_PATH_LEN+1];
int l_path_len = read_symlink(rp.target_inode_ptr, l_path);
if (l_path_len > 0) {
pr_stdout("inode_ptr=%d -> inode=%d\nref_count=%d\nsize=%d\ntype=symlink\npoints to: %s\n",
rp.target_inode_ptr, read_inode_ptr(rp.target_inode_ptr), i.ref_count, i.size, l_path);
} else {
pr_stdout("inode_ptr=%d -> inode=%d\nref_count=%d\nsize=%d\ntype=symlink\n<broken>\n",
rp.target_inode_ptr, read_inode_ptr(rp.target_inode_ptr), i.ref_count, i.size);
}
} }
return 0; return 0;
+55
View File
@@ -0,0 +1,55 @@
use disk1
mkfs 32
mkdir test1
mkdir test2
la
cd test1
la
create hello1
mkdir inside
symlink ../../test2/ inside/hello3
stat inside/hello3
cd ../test2
la
symlink ../test1/inside hello2
stat hello2
cd /
cd test1/../test2/hello2/../../test2/.././././test1/inside/hello3/./hello2/.
cd ..
create inside/././hello3/.././test1/f7
symlink /test1/f7 ../f1
la
cd ..
la
cd test1
open ../test2/hello2/../../f1
write 0 data
la
close 0
cd /
rm test1
rmdir test1
rm test1/inside/hello3
rmdir test1/inside
rm test1/hello1
rm test1/f7
rmdir test1
cd test2
la
cd hello2
symlink garbage/ttttt ..
cd ..
la
cd ttttt
rm ttttt