Compare commits
2 Commits
4e37240971
...
72a02047d5
Author | SHA1 | Date |
---|---|---|
|
72a02047d5 | |
|
585492b6d7 |
249
src/fs.c
249
src/fs.c
|
@ -1002,33 +1002,45 @@ static void resolve_path(struct resolved_path *rp, char *path, unsigned int para
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int find_free_fd(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < FS_MAX_OPEN_FD; i++)
|
||||||
|
if (!fs_file_descriptions[i].inode)
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int fs_open(void *d)
|
int fs_open(void *d)
|
||||||
{
|
{
|
||||||
char *fname = *((char **) d);
|
char *path = *((char **) d);
|
||||||
|
|
||||||
// find file inode
|
struct resolved_path rp;
|
||||||
struct fs_file_description fd;
|
resolve_path(&rp, path, FOLLOW_LAST_SYMLINK);
|
||||||
{
|
|
||||||
int *r = find_filename_in_directory(fs_cwd_inode_ptr, fname);
|
|
||||||
if (!r) {
|
|
||||||
pr_err("no such file: '%s'\n", fname);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fd.inode = read_inode_ptr(r[2]);
|
if (rp.target_inode_ptr < 0) {
|
||||||
free(r);
|
pr_err("no such file: '%s'\n", path);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
fd.rw_offset = 0;
|
|
||||||
|
|
||||||
// find free file descriptor
|
int free_fd = find_free_fd();
|
||||||
int free_fd;
|
if (free_fd < 0) {
|
||||||
for (free_fd = 0; (free_fd < FS_MAX_OPEN_FD) && (fs_file_descriptions[free_fd].inode); free_fd++);
|
|
||||||
if (free_fd == FS_MAX_OPEN_FD) {
|
|
||||||
pr_err("no free file descriptor found\n");
|
pr_err("no free file descriptor found\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&(fs_file_descriptions[free_fd]), &fd, sizeof(struct fs_file_description));
|
{
|
||||||
|
struct fs_inode i;
|
||||||
|
read_block(read_inode_ptr(rp.target_inode_ptr), &i);
|
||||||
|
|
||||||
|
if (i.ftype == DIRECTORY) {
|
||||||
|
pr_err("can't open '%s': file is a directory\n", rp.target_fname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs_file_descriptions[free_fd].inode = read_inode_ptr(rp.target_inode_ptr);
|
||||||
|
fs_file_descriptions[free_fd].rw_offset = 0;
|
||||||
|
|
||||||
pr_stdout("%d\n", free_fd);
|
pr_stdout("%d\n", free_fd);
|
||||||
|
|
||||||
|
@ -1332,7 +1344,7 @@ int fs_write(void *d)
|
||||||
|
|
||||||
int fs_truncate(void *d)
|
int fs_truncate(void *d)
|
||||||
{
|
{
|
||||||
char *fname = *((char **) d);
|
char *path = *((char **) d);
|
||||||
int size = *((int *) ((char **) d+1));
|
int size = *((int *) ((char **) d+1));
|
||||||
|
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
|
@ -1340,52 +1352,48 @@ int fs_truncate(void *d)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int file_inode_ptr;
|
struct resolved_path rp;
|
||||||
{
|
resolve_path(&rp, path, FOLLOW_LAST_SYMLINK);
|
||||||
int *r = find_filename_in_directory(fs_cwd_inode_ptr, fname);
|
|
||||||
if (r == NULL) {
|
|
||||||
pr_err("no such file: '%s'\n", fname);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
file_inode_ptr = r[2];
|
if (rp.target_inode_ptr < 0) {
|
||||||
free(r);
|
pr_err("no such file: '%s'\n", path);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fs_inode f;
|
struct fs_inode inode;
|
||||||
read_block(read_inode_ptr(file_inode_ptr), (void *) &f);
|
read_block(read_inode_ptr(rp.target_inode_ptr), &inode);
|
||||||
|
|
||||||
if (size > f.size) {
|
if (size > inode.size) {
|
||||||
pr("Increasing file size of '%s': %d -> %d\n", fname, f.size, size);
|
pr("Increasing file size of '%s': %d -> %d\n", rp.target_fname, inode.size, size);
|
||||||
f.size = size;
|
inode.size = size;
|
||||||
write_block(read_inode_ptr(file_inode_ptr), (void *) &f);
|
write_block(read_inode_ptr(rp.target_inode_ptr), &inode);
|
||||||
} else {
|
} else {
|
||||||
pr("Decreasing file size of '%s': %d -> %d\n", fname, f.size, size);
|
pr("Decreasing file size of '%s': %d -> %d\n", rp.target_fname, inode.size, size);
|
||||||
f.size = size;
|
inode.size = size;
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
int new_block_amount = f.size / FS_BLOCK_SIZE;
|
int new_block_amount = inode.size / FS_BLOCK_SIZE;
|
||||||
if (f.size % FS_BLOCK_SIZE)
|
if (inode.size % FS_BLOCK_SIZE)
|
||||||
new_block_amount++;
|
new_block_amount++;
|
||||||
|
|
||||||
int blocks_seen = 0;
|
int blocks_seen = 0;
|
||||||
|
|
||||||
// look through base inode blocks
|
// look through base inode blocks
|
||||||
for (int i = 0; i < BLOCK_ADDRESSES_PER_INODE; i++, blocks_seen++) {
|
for (int i = 0; i < BLOCK_ADDRESSES_PER_INODE; i++, blocks_seen++) {
|
||||||
if ((blocks_seen >= new_block_amount) && (f.blocks[i])) {
|
if ((blocks_seen >= new_block_amount) && (inode.blocks[i])) {
|
||||||
mark_free(f.blocks[i]);
|
mark_free(inode.blocks[i]);
|
||||||
f.blocks[i] = 0;
|
inode.blocks[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write_block(read_inode_ptr(file_inode_ptr), (void *) &f);
|
write_block(read_inode_ptr(rp.target_inode_ptr), &inode);
|
||||||
|
|
||||||
// look through inode extension blocks
|
// look through inode extension blocks
|
||||||
struct fs_inode_extension ext;
|
struct fs_inode_extension ext;
|
||||||
unsigned int next_ext = f.next_extension;
|
unsigned int next_ext = inode.next_extension;
|
||||||
unsigned int curr_ext;
|
unsigned int curr_ext;
|
||||||
|
|
||||||
while (next_ext) {
|
while (next_ext) {
|
||||||
read_block(next_ext, (void *) &ext);
|
read_block(next_ext, &ext);
|
||||||
|
|
||||||
for (int i = 0; i < BLOCK_ADDRESSES_PER_INODE_EXTENSION; i++, blocks_seen++) {
|
for (int i = 0; i < BLOCK_ADDRESSES_PER_INODE_EXTENSION; i++, blocks_seen++) {
|
||||||
if ((blocks_seen >= new_block_amount) && (ext.blocks[i])) {
|
if ((blocks_seen >= new_block_amount) && (ext.blocks[i])) {
|
||||||
|
@ -1394,25 +1402,25 @@ int fs_truncate(void *d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
write_block(next_ext, (void *) &ext);
|
write_block(next_ext, &ext);
|
||||||
next_ext = ext.next_extension;
|
next_ext = ext.next_extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
// look through inode extensions themselves
|
// look through inode extensions themselves
|
||||||
int required_blocks_after_base_inode = (int) f.size - (int) BLOCK_ADDRESSES_PER_INODE;
|
int required_blocks_after_base_inode = (int) inode.size - (int) BLOCK_ADDRESSES_PER_INODE;
|
||||||
int required_extensions = required_blocks_after_base_inode >= 0
|
int required_extensions = required_blocks_after_base_inode >= 0
|
||||||
? required_blocks_after_base_inode / BLOCK_ADDRESSES_PER_INODE_EXTENSION
|
? required_blocks_after_base_inode / BLOCK_ADDRESSES_PER_INODE_EXTENSION
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
if ((f.size - BLOCK_ADDRESSES_PER_INODE) % BLOCK_ADDRESSES_PER_INODE_EXTENSION)
|
if ((inode.size - BLOCK_ADDRESSES_PER_INODE) % BLOCK_ADDRESSES_PER_INODE_EXTENSION)
|
||||||
required_extensions++;
|
required_extensions++;
|
||||||
|
|
||||||
next_ext = f.next_extension;
|
next_ext = inode.next_extension;
|
||||||
|
|
||||||
if (!required_extensions) {
|
if (!required_extensions) {
|
||||||
// zero base inode next_extension ptr
|
// zero base inode next_extension ptr
|
||||||
f.next_extension = 0;
|
inode.next_extension = 0;
|
||||||
write_block(read_inode_ptr(file_inode_ptr), (void *) &f);
|
write_block(read_inode_ptr(rp.target_inode_ptr), &inode);
|
||||||
} else {
|
} else {
|
||||||
// seek to last required extension
|
// seek to last required extension
|
||||||
for (int i = 0; i < required_extensions; i++) {
|
for (int i = 0; i < required_extensions; i++) {
|
||||||
|
@ -1420,19 +1428,19 @@ int fs_truncate(void *d)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
curr_ext = next_ext;
|
curr_ext = next_ext;
|
||||||
read_block(curr_ext, (void *) &ext);
|
read_block(curr_ext, &ext);
|
||||||
next_ext = ext.next_extension;
|
next_ext = ext.next_extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove next_extension ptr
|
// remove next_extension ptr
|
||||||
ext.next_extension = 0;
|
ext.next_extension = 0;
|
||||||
write_block(curr_ext, (void *) &ext);
|
write_block(curr_ext, &ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
// erase all remaining extensions
|
// erase all remaining extensions
|
||||||
while (next_ext) {
|
while (next_ext) {
|
||||||
mark_free(next_ext);
|
mark_free(next_ext);
|
||||||
read_block(next_ext, (void *) &ext);
|
read_block(next_ext, &ext);
|
||||||
next_ext = ext.next_extension;
|
next_ext = ext.next_extension;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1546,108 +1554,63 @@ int fs_create(void *d)
|
||||||
|
|
||||||
int fs_ln(void *d)
|
int fs_ln(void *d)
|
||||||
{
|
{
|
||||||
if (used_file_fd <= 0) {
|
char *prev_path = ((char **) d)[0];
|
||||||
pr_err("no storage device\n");
|
char *new_path = ((char **)d)[1];
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *existing_fname = ((char **) d)[0];
|
|
||||||
char *new_fname = ((char **)d)[1];
|
|
||||||
int new_fname_len = strlen(new_fname);
|
|
||||||
|
|
||||||
|
char new_fname[FS_MAX_FNAME_LEN+1];
|
||||||
{
|
{
|
||||||
// check if duplicate filename exists in current directory
|
int new_fname_len = extract_basename(new_path, new_fname);
|
||||||
int *r = find_filename_in_directory(fs_cwd_inode_ptr, new_fname);
|
if (new_fname_len > FS_MAX_FNAME_LEN) {
|
||||||
if (r) {
|
pr_err("new filename too long (%d > %d)\n", new_fname_len, FS_MAX_FNAME_LEN);
|
||||||
free(r);
|
|
||||||
pr_err("filename '%s' already exists\n", new_fname);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct resolved_path prev_rp, new_rp;
|
||||||
|
|
||||||
if (new_fname_len > FS_MAX_FNAME_LEN) {
|
resolve_path(&prev_rp, prev_path, 0);
|
||||||
pr_err("new filename too long (%d > %d)\n", new_fname_len, FS_MAX_FNAME_LEN);
|
if (prev_rp.target_inode_ptr < 0) {
|
||||||
|
pr_err("no such file: '%s'\n", prev_path);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr("Making hard link '%s' -> '%s'\n", new_fname, existing_fname);
|
{
|
||||||
|
struct fs_inode prev_i;
|
||||||
|
read_block(read_inode_ptr(prev_rp.target_inode_ptr), &prev_i);
|
||||||
|
|
||||||
// find original file name
|
if (prev_i.ftype == DIRECTORY) {
|
||||||
unsigned int original_inode_ptr = 0;
|
pr_err("refusing to create hard link for directory\n");
|
||||||
|
return 0;
|
||||||
int dir_inode = read_inode_ptr(fs_cwd_inode_ptr);
|
|
||||||
|
|
||||||
struct fs_inode dir;
|
|
||||||
read_block(dir_inode, (void *) &dir);
|
|
||||||
|
|
||||||
// list entries from base inode
|
|
||||||
for (int i = 0; i < BLOCK_ADDRESSES_PER_INODE; i++) {
|
|
||||||
struct fs_directory_record recs[DIRECTORY_RECORDS_PER_BLOCK];
|
|
||||||
|
|
||||||
if (dir.blocks[i]) {
|
|
||||||
read_block(dir.blocks[i], (void *) &recs);
|
|
||||||
|
|
||||||
for (int k = 0; k < DIRECTORY_RECORDS_PER_BLOCK; k++) {
|
|
||||||
if (!recs[k].inode_no)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!strcmp(existing_fname, recs[k].fname)) {
|
|
||||||
original_inode_ptr = recs[k].inode_no;
|
|
||||||
goto original_inode_ptr_found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// list entries from inode extensions
|
resolve_path(&new_rp, new_path, 1);
|
||||||
struct fs_inode_extension ext;
|
if (new_rp.parent_inode_ptr < 0) {
|
||||||
unsigned int next_ext = dir.next_extension;
|
pr_err("failed to create hard link: no such directory: '%s'\n", new_path);
|
||||||
|
return 0;
|
||||||
while (next_ext) {
|
} else if (new_rp.target_inode_ptr >= 0) {
|
||||||
read_block(next_ext, (void *) &ext);
|
pr_err("file already exists: '%s'\n", new_rp.target_fname);
|
||||||
next_ext = ext.next_extension;
|
return 0;
|
||||||
|
|
||||||
for (int i = 0; i < BLOCK_ADDRESSES_PER_INODE_EXTENSION; i++) {
|
|
||||||
struct fs_directory_record recs[DIRECTORY_RECORDS_PER_BLOCK];
|
|
||||||
|
|
||||||
if (dir.blocks[i]) {
|
|
||||||
read_block(ext.blocks[i], (void *) &recs);
|
|
||||||
|
|
||||||
for (int k = 0; k < DIRECTORY_RECORDS_PER_BLOCK; k++) {
|
|
||||||
if (!recs[k].inode_no)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!strcmp(existing_fname, recs[k].fname)) {
|
|
||||||
original_inode_ptr = recs[k].inode_no;
|
|
||||||
goto original_inode_ptr_found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_err("no such file '%s'\n", existing_fname);
|
pr("Making hard link '%s' -> '%s'\n", new_path, prev_path);
|
||||||
return 0;
|
|
||||||
|
|
||||||
original_inode_ptr_found:
|
if (fs_add_fname_to_directory(new_rp.parent_inode_ptr, prev_rp.target_inode_ptr, new_fname) < 0) {
|
||||||
pr("Original inode_ptr found (%d)\n", original_inode_ptr);
|
pr_err("failed to add filename to directory '%s' (inode_ptr=%d)\n",
|
||||||
|
new_rp.parent_fname, new_rp.parent_inode_ptr);
|
||||||
// register new filename with the same inode_ptr
|
|
||||||
if (fs_add_fname_to_directory(fs_cwd_inode_ptr, original_inode_ptr, new_fname) < 0) {
|
|
||||||
pr_err("failed to register filename in directory '%s'\n", fs_cwd);
|
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
pr("Registered new filename in directory '%s'\n", fs_cwd);
|
pr("Added new filename to directory '%s' (inode_ptr=%d)\n",
|
||||||
|
new_rp.parent_fname, new_rp.parent_inode_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update ref_count in file inode
|
// update ref_count in file inode
|
||||||
struct fs_inode f;
|
struct fs_inode i;
|
||||||
read_block(read_inode_ptr(original_inode_ptr), (void *) &f);
|
read_block(read_inode_ptr(prev_rp.target_inode_ptr), &i);
|
||||||
f.ref_count++;
|
i.ref_count++;
|
||||||
write_block(read_inode_ptr(original_inode_ptr), (void *) &f);
|
write_block(read_inode_ptr(prev_rp.target_inode_ptr), &i);
|
||||||
|
|
||||||
pr("Updated inode ref_count (%d -> %d)\n", f.ref_count-1, f.ref_count);
|
pr("Updated inode ref_count (%d -> %d)\n", i.ref_count-1, i.ref_count);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1677,7 +1640,9 @@ static int extract_basename(char *path, char *name)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(name, &(path[lsp+1]));
|
// allow the usage of NULL ptr to discard basename string
|
||||||
|
if (name)
|
||||||
|
strcpy(name, &(path[lsp+1]));
|
||||||
|
|
||||||
return fname_len;
|
return fname_len;
|
||||||
}
|
}
|
||||||
|
@ -2188,23 +2153,25 @@ int fs_la(void *d)
|
||||||
|
|
||||||
int fs_stat(void *d)
|
int fs_stat(void *d)
|
||||||
{
|
{
|
||||||
char *fname = *((char **) d);
|
char *path = *((char **) d);
|
||||||
|
|
||||||
int file_inode_ptr = find_fname_in_directory(fs_cwd_inode_ptr, fname);
|
struct resolved_path rp;
|
||||||
if (file_inode_ptr < 0) {
|
resolve_path(&rp, path, 0);
|
||||||
pr_err("no such file: '%s'\n", fname);
|
|
||||||
|
if (rp.target_inode_ptr < 0) {
|
||||||
|
pr_err("no such file: '%s'\n", path);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fs_inode f;
|
struct fs_inode i;
|
||||||
read_block(read_inode_ptr(file_inode_ptr), (void *) &f);
|
read_block(read_inode_ptr(rp.target_inode_ptr), &i);
|
||||||
|
|
||||||
if (f.ftype == DIRECTORY) {
|
if (i.ftype == DIRECTORY) {
|
||||||
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=dir\n",
|
||||||
file_inode_ptr, read_inode_ptr(file_inode_ptr), f.ref_count, f.size);
|
rp.target_inode_ptr, read_inode_ptr(rp.target_inode_ptr), i.ref_count, i.size);
|
||||||
} else {
|
} else {
|
||||||
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=reg\n",
|
||||||
file_inode_ptr, read_inode_ptr(file_inode_ptr), f.ref_count, f.size);
|
rp.target_inode_ptr, read_inode_ptr(rp.target_inode_ptr), i.ref_count, i.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue