add truncate

This commit is contained in:
ІО-23 Шмуляр Олег 2025-04-26 22:12:26 +03:00
parent 3b3ce23df0
commit 3ee64e5b5d
3 changed files with 108 additions and 1 deletions

View File

@ -60,5 +60,6 @@ int fs_seek(void *d);
int fs_read(void *d);
int fs_write(void *d);
int fs_close(void *d);
int fs_truncate(void *d);
int fs_allow_write(void *d);
int fs_prohibit_write(void *d);

View File

@ -19,7 +19,7 @@ static const struct CliCommandEntry cmd[] = {
{"ls", 0, NULL, fs_ls},
{"ln", 2, (enum CliArgType[]) {STR, STR}, fs_ln},
{"rm", 1, (enum CliArgType[]) {STR}, fs_rm},
//{"truncate", 2, (enum CliArgType[]) {STR, INT}, fs_truncate},
{"truncate", 2, (enum CliArgType[]) {STR, INT}, fs_truncate},
{"open", 1, (enum CliArgType[]) {STR}, fs_open},
{"seek", 2, (enum CliArgType[]) {INT, INT}, fs_seek},
{"read", 2, (enum CliArgType[]) {INT, INT}, fs_read},

106
src/fs.c
View File

@ -902,6 +902,112 @@ int fs_write(void *d)
return 0;
}
int fs_truncate(void *d)
{
char *fname = *((char **) d);
int size = *((int *) ((char **) d+1));
if (size < 0) {
pr_err("file size can not be negative\n");
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;
}
file_inode_ptr = r[2];
free(r);
}
struct fs_inode f;
read_block(read_inode_ptr(file_inode_ptr), (void *) &f);
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);
} else {
pr("Decreasing file size of '%s': %d -> %d\n", fname, f.size, size);
f.size = size;
// cleanup
int new_block_amount = f.size / FS_BLOCK_SIZE;
if (f.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;
}
}
write_block(read_inode_ptr(file_inode_ptr), (void *) &f);
// look through inode extension blocks
struct fs_inode_extension ext;
unsigned int next_ext = f.next_extension;
unsigned int curr_ext;
while (next_ext) {
read_block(next_ext, (void *) &ext);
for (int i = 0; i < BLOCK_ADDRESSES_PER_INODE_EXTENSION; i++, blocks_seen++) {
if ((blocks_seen > new_block_amount) && (ext.blocks[i])) {
mark_free(ext.blocks[i]);
ext.blocks[i] = 0;
}
}
write_block(next_ext, (void *) &ext);
next_ext = ext.next_extension;
}
// look through inode extensions themselves
int required_extensions = (f.size - BLOCK_ADDRESSES_PER_INODE) / BLOCK_ADDRESSES_PER_INODE_EXTENSION;
if ((f.size - BLOCK_ADDRESSES_PER_INODE) % BLOCK_ADDRESSES_PER_INODE_EXTENSION)
required_extensions++;
next_ext = f.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);
}
// seek to last required extension
for (int i = 0; i < required_extensions; i++) {
if (!next_ext)
return 0;
curr_ext = next_ext;
read_block(next_ext, (void *) &ext);
next_ext = ext.next_extension;
}
// remove next_extension ptr
ext.next_extension = 0;
write_block(curr_ext, (void *) &ext);
// erase all extensions after this one
while (next_ext) {
mark_free(next_ext);
read_block(next_ext, (void *) &ext);
next_ext = ext.next_extension;
}
}
return 0;
}
int fs_close(void *d)
{
int fd = *((int *) d);