@ -10,6 +10,8 @@
# include <time.h>
# include <unistd.h>
# include "lsfs_string.h"
typedef struct Directory_Table Directory_Table ;
typedef struct struct_table_entry struct_table_entry ;
typedef struct struct_partition_control partition_control ;
@ -18,6 +20,7 @@ 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 enum Table_Entry_Kind Table_Entry_Kind ;
typedef uint64_t lsfs_sector_offset ;
typedef lsfs_sector_offset lsfs_file_id ;
@ -27,17 +30,13 @@ 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_create_entry ( const char * path , Table_Entry_Kind entry_kind ) ;
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_table ( ) ;
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 ) ;
@ -45,20 +44,19 @@ int read_data_from_disk(lsfs_sector_offset index, uint32_t file_block_size, void
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 NUMBER_OF_MBR_PARTITIONS 4
# 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 DEFAULT_TABLE_SIZE 10
# 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 enum Table_Entry_Kind
{
// These are specific values since, is has to corrospond to the implementation in assembly
ENTRY_EMPTY = 0 ,
ENTRY_FILE = 1 ,
ENTRY_DIRECTORY = 2 ,
} Table_Entry_Kind ;
typedef struct Partition_Entry
{
@ -101,13 +99,15 @@ typedef struct Directory_Table
typedef struct File_System_Control_Information
{
char filesyste_information [ 256 ] ;
uint64_t offset_on_disk ;
uint64_t master_table_index ;
uint64_t this_partition_offset_on_disk ;
uint64_t next_free_sector ;
uint64_t next_uniqe_id ; // both files and directories gets this.
uint64_t next_sector_reuse_pointer ;
uint64_t last_sector_index_on_partition ;
uint64_t maximum_sectors_on_disk ;
uint64_t sectors_size_on_disk ;
uint64_t not_used [ 26 ] ;
uint64_t not_used [ 24 ] ;
} __attribute__ ( ( packed ) ) FSCI ;
@ -120,15 +120,15 @@ typedef struct struct_partition_control
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 ;
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 ;
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
@ -153,6 +153,7 @@ typedef struct tag_record {
typedef struct lsfs_file {
lsfs_file_id file_id ;
lsfs_sector_offset table_entry_pointer ;
Table_Entry_Kind entry_kind ;
char * filename ;
uint32_t owner_id ;
uint64_t size ;
@ -173,6 +174,7 @@ int lsfs_disk_getattr(lsfs_file* find_file, const char* path) {
time ( & current_time ) ;
find_file - > file_id = p_control . master_table . entries [ i ] . file_id ;
find_file - > entry_kind = p_control . master_table . entries [ i ] . entry_kind ;
find_file - > table_entry_pointer = i ;
find_file - > filename = p_control . master_table . entries [ i ] . filename ;
find_file - > owner_id = getuid ( ) ;
@ -277,23 +279,6 @@ time_t lsfs_disk_truncate_file(lsfs_file *file, off_t offset) {
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.entries[i].file_id == file_id) {
// memset(p_control.master_table.entries[i].filename, 0, sizeof(p_control.master_table.entries[i].filename));
// sprintf(p_control.master_table.entries[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 ) ;
@ -314,13 +299,7 @@ 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.
@ -328,189 +307,44 @@ int lsfs_disk_delete_file(lsfs_file_id file_id) {
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 . entries [ i ] . file_id = = file_id ) {
p_control . master_table . entries [ 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 . entries [ 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 ) ;
int get_free_sectors_table ( ) {
// We need DEFAULT_TABLE_SIZE sectors straight contigious for a table
// Otherwise the file system cannot make a new table.
// We return the offset where the table is starting.
// If we cannot assing DEFAULT_TABLE_SIZE sectors, we report errror.
int return_index = p_control . fsci . next_free_sector ;
for ( int i = 0 ; i < MAX_TAGS_FOR_A_FILE ; + + i )
if ( ( p_control . fsci . next_free_sector + DEFAULT_TABLE_SIZE ) > p_control . fsci . last_sector_index_on_partition )
{
if ( mif_record - > tags [ i ] = = 0 ) {
mif_record - > tags [ i ] = file_id ;
break ;
}
// We don't have space, report error
return - EINVAL ;
}
write_data_to_disk ( file_id , mif_record ) ;
free ( mif_record ) ;
p_control . fsci . next_free_sector + = DEFAULT_TABLE_SIZE ;
tag_record * tag_table = calloc ( 64 , SECTOR_SIZE ) ;
read_data_from_disk ( file_id , tag_table ) ;
fseek ( disk , ( p_control . fsci . this_partition_offset_on_disk ) * SECTOR_SIZE , SEEK_SET ) ;
fwrite ( & p_control . fsci , 1 , SECTOR_SIZE , disk ) ;
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 ;
return return_index ;
}
*/
/*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 ;
int get_free_sectors ( int num_sectors_needed , lsfs_sector_offset * output_array ) {
for ( int i = 0 ; i < MAX_TAGS_FOR_A_FILE ; + + i )
if ( ( p_control . fsci . next_free_sector + num_sectors_needed ) > p_control . fsci . last_sector_index_on_partition )
{
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 ;
}
}
// We cannot assign what we want.
return - EINVAL ;
}
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 )
for ( int i = 0 ; i < num_sectors_needed ; + + 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 + + ;
output_array [ i ] = p_control . fsci . next_free_sector ;
p_control . fsci . next_free_sector + = DEFAULT_FILE_SIZE ;
}
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 , ( p_control . fsci . this_partition_offset_on_disk ) * SECTOR_SIZE , SEEK_SET ) ;
fwrite ( & p_control . fsci , 1 , SECTOR_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 ;
return 0 ;
}
int create_file_system ( ) {
@ -522,7 +356,7 @@ int create_file_system() {
// we need the first number to allocate memory at one go.
int * zero_buffer ;
FSCI fsci ;
fsci . offset_on_disk = 1 ;
fsci . this_partition_ offset_on_disk = 1 ;
//fsci.maximum_sectors_on_partition = 1048576; // Max 4GiB
fsci . next_free_sector = 257 ;
@ -533,8 +367,8 @@ int create_file_system() {
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 ) ) ) ;
table_entry master_table [ DEFAULT_TABLE_SIZE ] ;
memset ( master_table , 0 , ( DEFAULT_TABLE_SIZE * sizeof ( table_entry ) ) ) ;
fwrite ( & master_table , 1 , sizeof ( master_table ) , disk ) ;
zero_buffer = calloc ( 1 , 16 ) ;
@ -561,10 +395,12 @@ int lsfs_disk_load_disk() {
// First we find the File system control information.
fseek ( disk , mbr . partitions [ i ] . LBA_abs_first_sector * SECTOR_SIZE , SEEK_SET ) ;
fread ( & p_control . fsci , 1 , SECTOR_SIZE , disk ) ;
//printf("next free sector: %d\n", p_control.fsci.next_free_sector);
//printf("next free ID: %d\n", p_control.fsci.next_uniqe_id);
// next we find the Mater Table.
fseek ( disk , ( mbr . partitions [ i ] . LBA_abs_first_sector + 1 ) * SECTOR_SIZE , SEEK_SET ) ;
fread ( & p_control . master_table , 1 , 10 * SECTOR_SIZE , disk ) ;
fread ( & p_control . master_table , 1 , DEFAULT_TABLE_SIZE * SECTOR_SIZE , disk ) ;
return 1 ;
}
@ -573,62 +409,92 @@ int lsfs_disk_load_disk() {
}
lsfs_file_id lsfs_disk_create_file ( char * filename , lsfs_file_id * tags , void * file_data ) {
int lsfs_disk_create_entry ( const char * path , Table_Entry_Kind entry_kind )
{
// create space for mif
mif new_file_data ;
lsfs_file_id return_id ;
lsfs_string_array split_path = lsfs_string_split_c ( path , ' / ' , false ) ;
lsfs_string filename = split_path . strings [ split_path . length - 1 ] ;
// Start from the master table
int free_index = - 1 ; // -1 is no index found.
Directory_Table * dir_table = & p_control . master_table ;
lsfs_sector_offset table_disk_position = p_control . fsci . master_table_index ;
for ( int i = 0 ; i < split_path . length ; + + i )
{
for ( int j = 0 ; j < DEFAULT_TABLE_SIZE ; + + j )
{
if ( i = = ( split_path . length - 1 ) )
{
// Find free index and be sure that there dosent exist a file with the same name.
if ( dir_table - > entries [ j ] . entry_kind = = ENTRY_EMPTY )
{
// Set the free index, continue to see if the filename exist.
// if not -1, we have found a better index.
if ( free_index = = - 1 )
{
printf ( " Index found for file: %d \n " , j ) ;
free_index = j ;
}
}
else if ( strcmp ( dir_table - > entries [ j ] . filename , split_path . strings [ 0 ] . chars ) = = 0 )
{
// Abort mission, we have a file with the same name.
return - EINVAL ;
}
}
else
{
if ( strcmp ( dir_table - > entries [ j ] . filename , split_path . strings [ 0 ] . chars ) = = 0 )
{
// We have found the next directory to traverse.
;
}
}
}
}
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
if ( free_index = = - 1 )
{
// The table is full, and we cannot create an entry
return - EINVAL ;
}
memset ( new_file_data . tags , 0 , ( 32 * sizeof ( lsfs_file_id ) ) ) ;
new_file_data . file_size = 0 ;
// Find the entry for the file in the table structure:
dir_table - > entries [ free_index ] . file_id = p_control . fsci . next_uniqe_id ;
p_control . fsci . next_uniqe_id + + ;
sprintf ( dir_table - > entries [ free_index ] . filename , " %s " , filename . chars ) ;
dir_table - > entries [ free_index ] . entry_kind = entry_kind ;
if ( entry_kind = = ENTRY_DIRECTORY )
{
dir_table - > entries [ free_index ] . data_pointer [ 0 ] = get_free_sectors_table ( ) ;
dir_table - > entries [ free_index ] . file_size = 5120 ;
}
else if ( entry_kind = = ENTRY_FILE )
{
// We assign one data pointer consiting of DEFAULT_FILE_SIZE sectors
get_free_sectors_table ( 1 , dir_table - > entries [ free_index ] . data_pointer ) ;
}
else
{
return - EINVAL ;
}
/*
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 . entries [ i ] . data_pointer ;
find_file - > owner_id = getuid ( ) ;
new_file_data . owner_id = getuid ( ) ;
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 ) ;
fseek ( disk , ( table_disk_position + free_index ) * SECTOR_SIZE , SEEK_SET ) ;
fwrite ( & dir_table - > entries [ free_index ] , 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 ;
return 0 ;
}
int save_modified_file_information ( lsfs_file * file ) {