You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

603 lines
20 KiB

#ifndef LSFS_DISK_CONTROLLER_H
#define LSFS_DISK_CONTROLLER_H
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <time.h>
#include <unistd.h>
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_id file_id, 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, void* data_buffer);
int write_data_to_disk_off(lsfs_sector_offset index, void* data_to_write, int offset);
#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;
char* filename;
uint32_t owner_id;
uint64_t size;
uint64_t creation_date;
uint64_t access_time;
uint64_t modification_time;
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 ( &current_time );
//find_file = calloc(1, sizeof(lsfs_file));
find_file->file_id = p_control.master_table[i].file_id;
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;
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], buffer_for_data + (SECTOR_SIZE * i));
}
//time_t current_time;
//time ( &current_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 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 = malloc(SECTOR_SIZE);
assert(tmp_buffer);
read_data_from_disk(file->data[current_sector], 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);
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);
p_control.master_table[file->file_id].file_size += amount_written; // update file size
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]; //;
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_id file_id, const char* new_filename) {
mif* mif_record = calloc(1, SECTOR_SIZE);
read_data_from_disk(file_id, mif_record);
memset(mif_record->filename, 0, sizeof(mif_record->filename));
sprintf(mif_record->filename, "%s", new_filename);
time_t current_time;
time ( &current_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, 4, mif_record);
free(mif_record);
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, 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 ( &current_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 ( &current_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 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, 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, (4 * SECTOR_SIZE), disk);
return read;
}
#endif