#ifndef LSFS_DISK_CONTROLLER_H #define LSFS_DISK_CONTROLLER_H #include #include #include #include #include #include #include #include typedef struct struct_partition_control partition_control; typedef struct struct_table_entry table_entry; typedef struct struct_partition_control partition_control; typedef struct File_System_Control_Information FSCI; typedef struct meta_information_format mif; typedef struct tag_record tag_record; typedef struct lsfs_file lsfs_file; typedef uint64_t lsfs_sector_offset; typedef lsfs_sector_offset lsfs_file_id; //typedef uint64_t sector_index; static FILE* disk; static partition_control p_control; int create_file_system(); //lsfs_sector_offset lsfs_disk_create_tag(char* tag_name, bool is_filename); lsfs_sector_offset lsfs_disk_create_file(char* filename, lsfs_file_id* tags, void* file_data); int lsfs_disk_getattr(lsfs_file* find_file, const char *path); //int lsfs_disk_untag_file(lsfs_file_id file_id, lsfs_file_id file_id); //int lsfs_disk_tag_file(lsfs_file_id file_id, lsfs_file_id file_id); //int lsfs_disk_delete_tag(lsfs_file_id file_id); int lsfs_disk_delete_file(lsfs_file_id file_id); int get_free_sectors(int num_sectors_needed, lsfs_sector_offset* output_array); int lsfs_disk_read_data_from_file(lsfs_file* file, int buffer_size, void* buffer_for_data); int lsfs_disk_write_data_to_file(lsfs_file* file, int data_length, char *data); //int lsfs_disk_rename_tag(lsfs_file_id file_id, char* new_filename); int lsfs_disk_rename_file(lsfs_file* file, const char* new_filename); int lsfs_disk_load_disk(); int write_data_to_disk(lsfs_sector_offset at_sector, uint32_t file_block_size, void* data_to_write); int read_data_from_disk(lsfs_sector_offset index, uint32_t file_block_size, void* data_buffer); int write_data_to_disk_off(lsfs_sector_offset index, void* data_to_write, int offset); int save_modified_file_information(lsfs_file* file); #define SECTOR_SIZE 512 #define DEFAULT_FILE_SIZE 4 // This is in sectors #define DEFAULT_MASTER_TABLE_SIZE 64 #define DEFAULT_TAG_TABLE_SIZE 64 // correspond to 262144 bytes in sectors - 16384 files pr. default. (minus one, the last is a pointer to a table more ) #define MAX_MASTER_TAGS 57825 #define MAX_TAGS_IN_TAG_TABLE 16384 #define MAX_TAGS_FOR_A_FILE 32 #define NUM_DATA_POINTERS 28 //#define MAX_NUM_TWO_LEVEL_DATA 94 // First Mib of a file. //#define MAX_NUM_THREE_LEVEL_DATA 94 // First Mib of a file. typedef struct struct_partition_control{ FSCI* fsci; table_entry* master_table; } __attribute__((packed)) partition_control; typedef struct File_System_Control_Information { uint64_t offset_on_disk; uint64_t next_partition; uint64_t maximum_sectors_on_partition; uint64_t maximum_sectors_on_disk; uint64_t sectors_size_on_disk; uint64_t next_free_sector; uint64_t number_of_mtt; uint64_t master_tag_records[16]; } __attribute__((packed)) FSCI; typedef struct struct_table_entry { char filename[256]; lsfs_file_id file_id; uint64_t file_size; mif* ext_file_data; uint32_t file_block_size; // This tells how many block there are allocated for the specific file. eg. we read this amount of bloks for the file. struct { uint32_t is_filename : 1; } control_bits; lsfs_sector_offset data_pointer[NUM_DATA_POINTERS] } __attribute__((packed)) table_entry; typedef struct meta_information_format { char filename[246]; // remeber that the 246 bytes has to be a /0 terminator.. uint32_t owner_id; lsfs_file_id tags[32]; uint64_t file_size; uint32_t control_bits; /* not pressent - Permission key table 64 bytes sha-265 pr. key*/ uint64_t creation_date; uint64_t last_modification_data; uint64_t last_access_date; /* * 256 first pointers in direct mapping to data * 94 next pointers is a pointer * 94 next pointers to pointers to data */ lsfs_sector_offset one_level_pointer_data[NUM_DATA_POINTERS]; lsfs_sector_offset two_level_pointer_data[94]; lsfs_sector_offset three_level_pointer_data[94]; } __attribute__((packed)) mif; typedef struct tag_record { /* SIZE 16 bytes */ lsfs_file_id mif_record; struct { uint64_t is_filename : 1; } control_bits; } __attribute__((packed)) tag_record; typedef struct lsfs_file { lsfs_file_id file_id; lsfs_sector_offset table_entry_pointer; char* filename; uint32_t owner_id; uint64_t size; uint64_t creation_date; uint64_t access_time; uint64_t modification_time; uint32_t file_block_size; lsfs_sector_offset *data; } lsfs_file; int lsfs_disk_getattr(lsfs_file* find_file, const char* path) { int i = 0; int found = 0; while((p_control.master_table[i].filename[0]) != 0 && !found) { if(strcmp( (path + 1 ), p_control.master_table[i].filename ) == 0) { time_t current_time; time ( ¤t_time ); find_file->file_id = p_control.master_table[i].file_id; find_file->table_entry_pointer = i; find_file->filename = p_control.master_table[i].filename; find_file->owner_id = getuid(); find_file->size = p_control.master_table[i].file_size; // p_control.master_table[i].data_pointer[0]; //; find_file->creation_date = (uint64_t) current_time; find_file->access_time = (uint64_t) current_time; find_file->modification_time = (uint64_t) current_time; find_file->data = p_control.master_table[i].data_pointer; find_file->file_block_size = 1; // TODO: should be loaded from disk. found = 1; } i++; } return found; } int lsfs_disk_read_data_from_file(lsfs_file *file, int buffer_size, void* buffer_for_data) { // TODO some offset, to tell where in the file we want to write int return_val = 0; for (int i = 0; i < NUM_DATA_POINTERS; ++i) { if(file->data[i] == 0) { break; } return_val += read_data_from_disk(file->data[i], file->file_block_size, buffer_for_data + (SECTOR_SIZE * i)); } //time_t current_time; //time ( ¤t_time ); //mif_record->last_access_date = (uint64_t) current_time; //write_data_to_disk(file_id, mif_record); //free(mif_record); return return_val; } static inline time_t lsfs_disk_update_timestamps(lsfs_file *file) { return file->modification_time = file->access_time = time(NULL); } #define lsfs_num_sectors_for_size(x) (((x)+SECTOR_SIZE-1)&~(SECTOR_SIZE-1)) int lsfs_disk_write_data_to_file(lsfs_file *file, int data_length, char *data) { int written; int amount_written = data_length; lsfs_sector_offset current_sector = file->size / SECTOR_SIZE; unsigned int offset_in_sector = file->size % SECTOR_SIZE; char *tmp_buffer = calloc(file->file_block_size, SECTOR_SIZE); assert(tmp_buffer); read_data_from_disk(file->data[current_sector], file->file_block_size, tmp_buffer); memcpy(tmp_buffer + offset_in_sector, data, SECTOR_SIZE-offset_in_sector); data_length -= SECTOR_SIZE-offset_in_sector; if (data_length < 0) { data_length = 0; } for (;;) { assert(current_sector <= NUM_DATA_POINTERS); written = written + write_data_to_disk(p_control.master_table[file->file_id].data_pointer[current_sector], 4, tmp_buffer); if (data_length <= 0) break; data += SECTOR_SIZE; if (data_length >= SECTOR_SIZE) { memcpy(tmp_buffer, data, SECTOR_SIZE); data_length -= SECTOR_SIZE; } else { memset(tmp_buffer, 0, SECTOR_SIZE); memcpy(tmp_buffer, data, data_length); data_length = 0; } } amount_written -= data_length; free(tmp_buffer); //lsfs_disk_update_timestamps(&mif_record); file->size += amount_written; // update file size save_modified_file_information(file); //write_data_to_disk(file->file_id, 4, &p_control.master_table[file->file_id]); return amount_written; } time_t lsfs_disk_truncate_file(lsfs_file *file, off_t offset) { //mif file_mif; //read_data_from_disk(file_id, &file_mif); time_t result = lsfs_disk_update_timestamps(file); file->size = (int) offset; // p_control.master_table[i].data_pointer[0]; //; save_modified_file_information(file); //write_data_to_disk(file->file_id, 4, NULL); return result; } // int lsfs_disk_rename_tag(lsfs_file_id file_id, char* new_filename) { // for (int i = 0; i < MAX_MASTER_TAGS; ++i) // { // if(p_control.master_table[i].file_id == file_id) { // memset(p_control.master_table[i].filename, 0, sizeof(p_control.master_table[i].filename)); // sprintf(p_control.master_table[i].filename, "%s", new_filename); // break; // } // } // // free the sectors including the tag table // // Save the changes to disk // fseek ( disk , (p_control.fsci->master_tag_records[0] * SECTOR_SIZE) , SEEK_SET ); // fwrite(p_control.master_table, 1, sizeof(table_entry) * DEFAULT_MASTER_TABLE_SIZE, disk); // return 1; // } int lsfs_disk_rename_file(lsfs_file* file, const char* new_filename) { memset(file->filename, 0, 256); sprintf(file->filename, "%s", new_filename); time_t current_time; time ( ¤t_time ); file->access_time = (uint64_t) current_time; file->modification_time = (uint64_t) current_time; save_modified_file_information(file); return 1; } int lsfs_disk_delete_file(lsfs_file_id file_id) { mif* mif_record = calloc(1, SECTOR_SIZE); read_data_from_disk(file_id, 1, mif_record); for (int i = 0; i < MAX_TAGS_FOR_A_FILE; ++i) { if(mif_record->tags[i] == 0) { break; } //lsfs_disk_untag_file(mif_record->tags[i], file_id); } // TODO Delete/free all data sectors. // Delete/free the mif record sector. free(mif_record); return 1; } /*int lsfs_disk_delete_tag(lsfs_file_id file_id) { tag_record* tag_table = calloc(64, SECTOR_SIZE); read_data_from_disk(file_id, tag_table); for (int i = 0; i < MAX_TAGS_IN_TAG_TABLE; ++i) { if(tag_table[i].mif_record == 0) { break; } lsfs_disk_untag_file(file_id, tag_table[i].mif_record); } int truncate_table = 0; for (int i = 0; i < MAX_MASTER_TAGS; ++i) { if(p_control.master_table[i].file_id == file_id) { p_control.master_table[i] = p_control.master_table[i+1]; truncate_table = 1; printf("Tag deleted from master table - TagID: %lu\n", file_id); } else if (truncate_table) { p_control.master_table[i] = p_control.master_table[i+1]; if (p_control.master_table[i+1].file_id == 0) { break; } } } // free the sectors including the tag table // Save the changes to disk fseek ( disk , (p_control.fsci->master_tag_records[0] * SECTOR_SIZE) , SEEK_SET ); fwrite(p_control.master_table, 1, sizeof(table_entry) * DEFAULT_MASTER_TABLE_SIZE, disk); free(tag_table); return 1; }*/ /*int lsfs_disk_tag_file(lsfs_file_id file_id, lsfs_file_id file_id) { mif* mif_record = calloc(1, SECTOR_SIZE); read_data_from_disk(file_id, mif_record); for (int i = 0; i < MAX_TAGS_FOR_A_FILE; ++i) { if(mif_record->tags[i] == 0) { mif_record->tags[i] = file_id; break; } } write_data_to_disk(file_id, mif_record); free(mif_record); tag_record* tag_table = calloc(64, SECTOR_SIZE); read_data_from_disk(file_id, tag_table); for (int i = 0; i < MAX_TAGS_IN_TAG_TABLE; ++i) { if(tag_table[i].mif_record == 0) { tag_table[i].mif_record = file_id; printf("file tagged - TagID: %lu - FileID: %lu \n", tag_table[i].mif_record, file_id); break; } } write_data_to_disk(file_id, tag_table); free(tag_table); return 1; } */ /*int lsfs_disk_untag_file(lsfs_file_id file_id, lsfs_file_id file_id) { mif* mif_record = calloc(1, SECTOR_SIZE); read_data_from_disk(file_id, mif_record); int truncate_table = 0; for (int i = 0; i < MAX_TAGS_FOR_A_FILE; ++i) { if(mif_record->tags[i] == file_id) { mif_record->tags[i] = mif_record->tags[i+1]; truncate_table = 1; printf("file untagged - TagID: %lu - FileID: %lu \n", file_id, file_id); } else if (truncate_table) { mif_record->tags[i] = mif_record->tags[i+1]; if (mif_record->tags[i+1] == 0) { break; } } } time_t current_time; time ( ¤t_time ); mif_record->last_modification_data = (uint64_t) current_time; mif_record->last_access_date = (uint64_t) current_time; write_data_to_disk(file_id, mif_record); free(mif_record); tag_record* tag_table = calloc(64, SECTOR_SIZE); read_data_from_disk(file_id, tag_table); truncate_table = 0; for (int i = 0; i < MAX_TAGS_IN_TAG_TABLE; ++i) { if(tag_table[i].mif_record == file_id) { tag_table[i].mif_record = tag_table[i+1].mif_record; truncate_table = 1; printf("file untagged - TagID: %lu - FileID: %lu \n", tag_table[i].mif_record, file_id); } else if (truncate_table) { tag_table[i].mif_record = tag_table[i+1].mif_record; if (tag_table[i+1].mif_record == 0) { break; } } } write_data_to_disk(file_id, tag_table); free(tag_table); return 1; }*/ /*lsfs_file_id lsfs_disk_create_tag(char* tag_name, bool is_filename) { // Return ID of new tag, oterwise return 0 lsfs_file_id* free_sectors; // Returns an array, with the sector numbers that is assignt to you free_sectors = calloc(DEFAULT_TAG_TABLE_SIZE, sizeof(lsfs_file_id)); get_free_sectors(DEFAULT_TAG_TABLE_SIZE, free_sectors); // has to be freed // Insert tag in the master tag, table an set the pointer to the first of the tag table int index_in_mtt = 0; while(p_control.master_table[index_in_mtt].file_id != 0) { //TODO also have to count if we enter next data section. index_in_mtt++; } p_control.master_table[index_in_mtt].file_id = free_sectors[0]; printf("%lu\n", free_sectors[0]); sprintf(p_control.master_table[index_in_mtt].filename, "%s", tag_name); p_control.master_table[index_in_mtt].control_bits.is_filename = is_filename; tag_record new_tag[DEFAULT_TAG_TABLE_SIZE]; memset(new_tag, 0, (DEFAULT_TAG_TABLE_SIZE * sizeof(tag_record))); //printf("Sector number: %lu, is assignt to you \n", (*free_sectors)); //char* data = "red_file_1\nred_file_2\n"; //char* sector_to_write = write_mechanism_new_buffer(data); fseek ( disk , (p_control.fsci->master_tag_records[0] * SECTOR_SIZE) , SEEK_SET ); fwrite(p_control.master_table, 1, sizeof(table_entry) * DEFAULT_MASTER_TABLE_SIZE, disk); fseek ( disk , ((*free_sectors) * SECTOR_SIZE) , SEEK_SET ); fwrite(new_tag, 1, DEFAULT_TAG_TABLE_SIZE * sizeof(tag_record), disk); //free(sector_to_write); int return_value = free_sectors[0]; free(free_sectors); return return_value; } */ int get_free_sectors(int num_sectors_needed, lsfs_sector_offset* output_array) { /* * TODO - WARNING * This has to be a much better algoritm, to pick free sctors. * We have to keep some bookeeping of what is free. * Also if more sctors are claimed, we want them to be sequtive. * This is just a naiv counter, just added more sectors to the file. */ if (num_sectors_needed > 1) { for (int i = 0; i < num_sectors_needed; ++i) { output_array[i] = p_control.fsci->next_free_sector; p_control.fsci->next_free_sector++; } } else { output_array[0] = p_control.fsci->next_free_sector; p_control.fsci->next_free_sector++; } printf("Sector %lu is assignt\n", output_array[0]); write_data_to_disk(0, 4, p_control.fsci); return p_control.fsci->next_free_sector; } int create_file_system() { //char* sector_to_write; // make default File System Control information (FSCI) // first integer says how many pointers we got // to master tag tables // Second and forward is the pointers to the master Tag Tables // we need the first number to allocate memory at one go. int* zero_buffer; FSCI fsci; fsci.offset_on_disk = 1; fsci.maximum_sectors_on_partition = 1048576; // Max 4GiB fsci.next_free_sector = 257; fsci.number_of_mtt = 1; memset(fsci.master_tag_records, 0, 128); fsci.master_tag_records[0] = 1; fseek ( disk , 0, SEEK_SET ); fwrite(&fsci, 1, sizeof(fsci), disk); zero_buffer = calloc(1, (4096 - sizeof(fsci))); fwrite(zero_buffer, 1, (4096 - sizeof(fsci)), disk); free(zero_buffer); /* MASTER TAG TABLE */ table_entry master_table[DEFAULT_MASTER_TABLE_SIZE]; memset(master_table, 0, (DEFAULT_MASTER_TABLE_SIZE * sizeof(table_entry))); fwrite(&master_table, 1, sizeof(master_table), disk); zero_buffer = calloc(1, 16); fwrite(zero_buffer, 1, 16, disk); free(zero_buffer); return 0; } int lsfs_disk_load_disk() { // First we find the Mater Table. fseek ( disk , 24 * SECTOR_SIZE, SEEK_SET ); fread(p_control.master_table, 1, sizeof(table_entry) * DEFAULT_MASTER_TABLE_SIZE , disk); // Now we can finde the FSCI data //fseek ( disk , 0, SEEK_SET ); //fread(p_control.fsci, 1, sizeof(FSCI), disk); return 1; } lsfs_file_id lsfs_disk_create_file(char* filename, lsfs_file_id* tags, void* file_data) { // create space for mif mif new_file_data; lsfs_file_id return_id; memset(new_file_data.filename, 0, sizeof(new_file_data.filename)); sprintf(new_file_data.filename, "%s", filename); // remeber that the 260 bytes has to be a /0 terminator. // 260 because it pads to a full sector. printf("%s\n", new_file_data.filename); new_file_data.owner_id = getuid(); lsfs_file_id* index_to_mif_data; index_to_mif_data = calloc(1, sizeof(lsfs_file_id)); get_free_sectors(1, index_to_mif_data); // has to be freed memset(new_file_data.tags, 0, (32 * sizeof(lsfs_file_id))); new_file_data.file_size = 0; time_t current_time; time ( ¤t_time ); new_file_data.creation_date = (uint64_t) current_time; new_file_data.last_modification_data = (uint64_t) current_time; new_file_data.last_access_date = (uint64_t) current_time; new_file_data.control_bits = 0; memset(new_file_data.one_level_pointer_data, 0, (256 * sizeof(lsfs_sector_offset))); memset(new_file_data.two_level_pointer_data, 0, (94 * sizeof(lsfs_sector_offset))); memset(new_file_data.three_level_pointer_data, 0, (94 * sizeof(lsfs_sector_offset))); get_free_sectors(1, new_file_data.one_level_pointer_data); int actual_file_size = 0; new_file_data.file_size = actual_file_size; fseek ( disk , index_to_mif_data[0] * SECTOR_SIZE, SEEK_SET ); fwrite(&new_file_data, 1, SECTOR_SIZE, disk); printf("MIF written at sector: %lu\n", index_to_mif_data[0]); printf("DATA written at sector: %lu\n", new_file_data.one_level_pointer_data[0]); int i = 0; if (tags != NULL) { while(tags[i] != 0) { printf("A tag is found \n"); //lsfs_disk_tag_file(tags[i], index_to_mif_data[0]); new_file_data.tags[i] = tags[i]; i++; } } return_id = index_to_mif_data[0]; free(index_to_mif_data); return return_id; } int save_modified_file_information(lsfs_file* file) { // Write the file struct into the table_entry, such that we can save the data correct. p_control.master_table[file->table_entry_pointer].file_id = file->file_id; memcpy(p_control.master_table[file->table_entry_pointer].filename, file->filename, 256); p_control.master_table[file->table_entry_pointer].file_size = file->size; // p_control.master_table[i].data_pointer[0]; //; //p_control.master_table[i].data_pointer = find_file->data; write_data_to_disk(file->table_entry_pointer, file->file_block_size, &p_control.master_table[file->table_entry_pointer]); return 0; } int write_data_to_disk(lsfs_sector_offset index, uint32_t file_block_size, void* data_to_write) { fseek ( disk, (index * SECTOR_SIZE), SEEK_SET ); // SEEK_SET start offset at index 0 and move 1 * SECTOR_SIZE, and write here. int written = fwrite(data_to_write, 1, (4 * SECTOR_SIZE), disk); return written; } int write_data_to_disk_off(lsfs_sector_offset index, void* data_to_write, int offset) { fseek ( disk, (index * SECTOR_SIZE) + offset, SEEK_SET ); // SEEK_SET start offset at index 0 and move 1 * SECTOR_SIZE, and write here. int written = fwrite(data_to_write, 1, (4 * SECTOR_SIZE), disk); return written; } int read_data_from_disk(lsfs_sector_offset index, uint32_t file_block_size, void* data_buffer) { fseek ( disk, (index * SECTOR_SIZE ), SEEK_SET ); // SEEK_SET start offset at index 0 and move 1 * SECTOR_SIZE, and write here. int read = fread(data_buffer, 1, (file_block_size * SECTOR_SIZE), disk); return read; } #endif