update fs_stat, fs_open, fs_ln and fs_truncate to operate on paths
This commit is contained in:
parent
4e37240971
commit
585492b6d7
239
src/fs.c
239
src/fs.c
|
@ -1002,33 +1002,35 @@ 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)
|
||||
{
|
||||
char *fname = *((char **) d);
|
||||
char *path = *((char **) d);
|
||||
|
||||
// find file inode
|
||||
struct fs_file_description fd;
|
||||
{
|
||||
int *r = find_filename_in_directory(fs_cwd_inode_ptr, fname);
|
||||
if (!r) {
|
||||
pr_err("no such file: '%s'\n", fname);
|
||||
return 0;
|
||||
}
|
||||
struct resolved_path rp;
|
||||
resolve_path(&rp, path, FOLLOW_LAST_SYMLINK);
|
||||
|
||||
fd.inode = read_inode_ptr(r[2]);
|
||||
free(r);
|
||||
if (rp.target_inode_ptr < 0) {
|
||||
pr_err("no such file: '%s'\n", path);
|
||||
return 0;
|
||||
}
|
||||
fd.rw_offset = 0;
|
||||
|
||||
// find free file descriptor
|
||||
int free_fd;
|
||||
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) {
|
||||
int free_fd = find_free_fd();
|
||||
if (free_fd < 0) {
|
||||
pr_err("no free file descriptor found\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&(fs_file_descriptions[free_fd]), &fd, sizeof(struct fs_file_description));
|
||||
fs_file_descriptions[free_fd].inode = rp.target_inode_ptr;
|
||||
fs_file_descriptions[free_fd].rw_offset = 0;
|
||||
|
||||
pr_stdout("%d\n", free_fd);
|
||||
|
||||
|
@ -1332,7 +1334,7 @@ int fs_write(void *d)
|
|||
|
||||
int fs_truncate(void *d)
|
||||
{
|
||||
char *fname = *((char **) d);
|
||||
char *path = *((char **) d);
|
||||
int size = *((int *) ((char **) d+1));
|
||||
|
||||
if (size < 0) {
|
||||
|
@ -1340,52 +1342,48 @@ int fs_truncate(void *d)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int file_inode_ptr;
|
||||
{
|
||||
int *r = find_filename_in_directory(fs_cwd_inode_ptr, fname);
|
||||
if (r == NULL) {
|
||||
pr_err("no such file: '%s'\n", fname);
|
||||
return 0;
|
||||
}
|
||||
struct resolved_path rp;
|
||||
resolve_path(&rp, path, FOLLOW_LAST_SYMLINK);
|
||||
|
||||
file_inode_ptr = r[2];
|
||||
free(r);
|
||||
if (rp.target_inode_ptr < 0) {
|
||||
pr_err("no such file: '%s'\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct fs_inode f;
|
||||
read_block(read_inode_ptr(file_inode_ptr), (void *) &f);
|
||||
struct fs_inode inode;
|
||||
read_block(read_inode_ptr(rp.target_inode_ptr), &inode);
|
||||
|
||||
if (size > f.size) {
|
||||
pr("Increasing file size of '%s': %d -> %d\n", fname, f.size, size);
|
||||
f.size = size;
|
||||
write_block(read_inode_ptr(file_inode_ptr), (void *) &f);
|
||||
if (size > inode.size) {
|
||||
pr("Increasing file size of '%s': %d -> %d\n", rp.target_fname, inode.size, size);
|
||||
inode.size = size;
|
||||
write_block(read_inode_ptr(rp.target_inode_ptr), &inode);
|
||||
} else {
|
||||
pr("Decreasing file size of '%s': %d -> %d\n", fname, f.size, size);
|
||||
f.size = size;
|
||||
pr("Decreasing file size of '%s': %d -> %d\n", rp.target_fname, inode.size, size);
|
||||
inode.size = size;
|
||||
|
||||
// cleanup
|
||||
int new_block_amount = f.size / FS_BLOCK_SIZE;
|
||||
if (f.size % FS_BLOCK_SIZE)
|
||||
int new_block_amount = inode.size / FS_BLOCK_SIZE;
|
||||
if (inode.size % FS_BLOCK_SIZE)
|
||||
new_block_amount++;
|
||||
|
||||
int blocks_seen = 0;
|
||||
|
||||
// look through base inode blocks
|
||||
for (int i = 0; i < BLOCK_ADDRESSES_PER_INODE; i++, blocks_seen++) {
|
||||
if ((blocks_seen >= new_block_amount) && (f.blocks[i])) {
|
||||
mark_free(f.blocks[i]);
|
||||
f.blocks[i] = 0;
|
||||
if ((blocks_seen >= new_block_amount) && (inode.blocks[i])) {
|
||||
mark_free(inode.blocks[i]);
|
||||
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
|
||||
struct fs_inode_extension ext;
|
||||
unsigned int next_ext = f.next_extension;
|
||||
unsigned int next_ext = inode.next_extension;
|
||||
unsigned int curr_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++) {
|
||||
if ((blocks_seen >= new_block_amount) && (ext.blocks[i])) {
|
||||
|
@ -1394,25 +1392,25 @@ int fs_truncate(void *d)
|
|||
}
|
||||
}
|
||||
|
||||
write_block(next_ext, (void *) &ext);
|
||||
write_block(next_ext, &ext);
|
||||
next_ext = ext.next_extension;
|
||||
}
|
||||
|
||||
// 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
|
||||
? required_blocks_after_base_inode / BLOCK_ADDRESSES_PER_INODE_EXTENSION
|
||||
: 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++;
|
||||
|
||||
next_ext = f.next_extension;
|
||||
next_ext = inode.next_extension;
|
||||
|
||||
if (!required_extensions) {
|
||||
// zero base inode next_extension ptr
|
||||
f.next_extension = 0;
|
||||
write_block(read_inode_ptr(file_inode_ptr), (void *) &f);
|
||||
inode.next_extension = 0;
|
||||
write_block(read_inode_ptr(rp.target_inode_ptr), &inode);
|
||||
} else {
|
||||
// seek to last required extension
|
||||
for (int i = 0; i < required_extensions; i++) {
|
||||
|
@ -1420,19 +1418,19 @@ int fs_truncate(void *d)
|
|||
return 0;
|
||||
|
||||
curr_ext = next_ext;
|
||||
read_block(curr_ext, (void *) &ext);
|
||||
read_block(curr_ext, &ext);
|
||||
next_ext = ext.next_extension;
|
||||
}
|
||||
|
||||
// remove next_extension ptr
|
||||
ext.next_extension = 0;
|
||||
write_block(curr_ext, (void *) &ext);
|
||||
write_block(curr_ext, &ext);
|
||||
}
|
||||
|
||||
// erase all remaining extensions
|
||||
while (next_ext) {
|
||||
mark_free(next_ext);
|
||||
read_block(next_ext, (void *) &ext);
|
||||
read_block(next_ext, &ext);
|
||||
next_ext = ext.next_extension;
|
||||
}
|
||||
}
|
||||
|
@ -1546,108 +1544,63 @@ int fs_create(void *d)
|
|||
|
||||
int fs_ln(void *d)
|
||||
{
|
||||
if (used_file_fd <= 0) {
|
||||
pr_err("no storage device\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *existing_fname = ((char **) d)[0];
|
||||
char *new_fname = ((char **)d)[1];
|
||||
int new_fname_len = strlen(new_fname);
|
||||
char *prev_path = ((char **) d)[0];
|
||||
char *new_path = ((char **)d)[1];
|
||||
|
||||
char new_fname[FS_MAX_FNAME_LEN+1];
|
||||
{
|
||||
// check if duplicate filename exists in current directory
|
||||
int *r = find_filename_in_directory(fs_cwd_inode_ptr, new_fname);
|
||||
if (r) {
|
||||
free(r);
|
||||
pr_err("filename '%s' already exists\n", new_fname);
|
||||
int new_fname_len = extract_basename(new_path, new_fname);
|
||||
if (new_fname_len > FS_MAX_FNAME_LEN) {
|
||||
pr_err("new filename too long (%d > %d)\n", new_fname_len, FS_MAX_FNAME_LEN);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct resolved_path prev_rp, new_rp;
|
||||
|
||||
if (new_fname_len > FS_MAX_FNAME_LEN) {
|
||||
pr_err("new filename too long (%d > %d)\n", new_fname_len, FS_MAX_FNAME_LEN);
|
||||
resolve_path(&prev_rp, prev_path, 0);
|
||||
if (prev_rp.target_inode_ptr < 0) {
|
||||
pr_err("no such file: '%s'\n", prev_path);
|
||||
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
|
||||
unsigned int original_inode_ptr = 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;
|
||||
}
|
||||
}
|
||||
if (prev_i.ftype == DIRECTORY) {
|
||||
pr_err("refusing to create hard link for directory\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// list entries from inode extensions
|
||||
struct fs_inode_extension ext;
|
||||
unsigned int next_ext = dir.next_extension;
|
||||
|
||||
while (next_ext) {
|
||||
read_block(next_ext, (void *) &ext);
|
||||
next_ext = ext.next_extension;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
resolve_path(&new_rp, new_path, 1);
|
||||
if (new_rp.parent_inode_ptr < 0) {
|
||||
pr_err("failed to create hard link: no such directory: '%s'\n", new_path);
|
||||
return 0;
|
||||
} else if (new_rp.target_inode_ptr >= 0) {
|
||||
pr_err("file already exists: '%s'\n", new_rp.target_fname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pr_err("no such file '%s'\n", existing_fname);
|
||||
return 0;
|
||||
pr("Making hard link '%s' -> '%s'\n", new_path, prev_path);
|
||||
|
||||
original_inode_ptr_found:
|
||||
pr("Original inode_ptr found (%d)\n", original_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);
|
||||
if (fs_add_fname_to_directory(new_rp.parent_inode_ptr, prev_rp.target_inode_ptr, new_fname) < 0) {
|
||||
pr_err("failed to add filename to directory '%s' (inode_ptr=%d)\n",
|
||||
new_rp.parent_fname, new_rp.parent_inode_ptr);
|
||||
return 0;
|
||||
} 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
|
||||
struct fs_inode f;
|
||||
read_block(read_inode_ptr(original_inode_ptr), (void *) &f);
|
||||
f.ref_count++;
|
||||
write_block(read_inode_ptr(original_inode_ptr), (void *) &f);
|
||||
struct fs_inode i;
|
||||
read_block(read_inode_ptr(prev_rp.target_inode_ptr), &i);
|
||||
i.ref_count++;
|
||||
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;
|
||||
}
|
||||
|
@ -1677,7 +1630,9 @@ static int extract_basename(char *path, char *name)
|
|||
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;
|
||||
}
|
||||
|
@ -2188,23 +2143,25 @@ int fs_la(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);
|
||||
if (file_inode_ptr < 0) {
|
||||
pr_err("no such file: '%s'\n", fname);
|
||||
struct resolved_path rp;
|
||||
resolve_path(&rp, path, 0);
|
||||
|
||||
if (rp.target_inode_ptr < 0) {
|
||||
pr_err("no such file: '%s'\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct fs_inode f;
|
||||
read_block(read_inode_ptr(file_inode_ptr), (void *) &f);
|
||||
struct fs_inode i;
|
||||
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",
|
||||
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 {
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue