int open_file (const char *path, struct fuse_file_info *info) { file_entry file; if (get_file_entry(path, &file) != 0) { return -ENOENT; } return 0; }
int get_attribute(const char *path, struct stat *stat) { memset(stat, 0, sizeof(struct stat)); if (strcmp(path, "/") == 0) { stat->st_mode = S_IFDIR | 0755; stat->st_nlink = 2; } else { file_entry file; if (get_file_entry(path, &file) != 0) { return -ENOENT; } stat->st_mode = file.mode; stat->st_nlink = 1; stat->st_size = file.size; stat->st_mtime = file.created; } return 0; }
struct dir_table_entry* get_dir_entries(struct file_descriptor dir) { struct dir_table_entry* dir_info = get_file_entry( dir ); char* buff = (char*)malloc( dir_info->file_size ); if(!read_file( (void*)buff , dir , 0 , dir_info->file_size)) { //printf("error reading directory entries\ncall to read_file failed"); return NULL; }else{ return (struct dir_table_entry*)buff; } }
int read(const char *path, char *buf, size_t buf_size, off_t offset, struct fuse_file_info *info) { file_entry file; cluster_t clustert = 0; off_t clusteroffset = 0; size_t size = 0; if (get_file_entry(path, &file) != 0) { return -ENOENT; } if (offset < file.size) { if (offset + buf_size > file.size) { size = file.size - offset; } else { size = buf_size; } size_t sum = 0; clustert = get_cluster_by_offset(file.cluster, offset); char *tmp = (char*)malloc(CLUSTER_SIZE); size_t current = 0; while (sum < size) { clusteroffset = offset % CLUSTER_SIZE; if (sum + CLUSTER_SIZE < size) { current = CLUSTER_SIZE - cluster_offset; } else { current = size - sum - cluster_offset; } lseek(image, data_offset + clustert * CLUSTER_SIZE + cluster_offset, SEEK_SET); read(image, tmp, current); memcpy(buf + sum, tmp, current); offset += current; sum += current; clustert = getnextcl(clustert); } free(tmp); } return size; }
Status DB::add_file_entry(const char* fname, PageId start_page_num) { #ifdef DEBUG cout << "Adding a file entry: " << fname << " : " << start_page_num << endl; #endif // Is the info kosher? if ( strlen(fname) >= MAX_NAME ) return MINIBASE_FIRST_ERROR( DBMGR, FILE_NAME_TOO_LONG ); if ((start_page_num < 0) || (start_page_num >= (int) num_pages) ) return MINIBASE_FIRST_ERROR( DBMGR, BAD_PAGE_NO ); // Does the file already exist? PageId tmp; if ( get_file_entry(fname,tmp) == OK ) return MINIBASE_FIRST_ERROR( DBMGR, DUPLICATE_ENTRY ); char *pg = 0; Status status; directory_page* dp = 0; bool found = false; unsigned free_slot = 0; PageId hpid, nexthpid = 0; do { hpid = nexthpid; // Pin the header page. status = MINIBASE_BM->pinPage( hpid, (Page*&)pg ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); // This complication is because the first page has a different // structure from that of subsequent pages. dp = (hpid == 0)? &((first_page*)pg)->dir : (directory_page*)pg; nexthpid = dp->next_page; unsigned entry = 0; while ( (entry < dp->num_entries) && (dp->entries[entry].pagenum != INVALID_PAGE)) ++entry; if ( entry < dp->num_entries ) { free_slot = entry; found = true; } else if ( nexthpid != INVALID_PAGE ) { // We only unpin if we're going to continue looping. status = MINIBASE_BM->unpinPage( hpid ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); } } while ( nexthpid != INVALID_PAGE && !found ); // Have to add a new header page if possible. if ( !found ) { status = allocate_page( nexthpid ); if ( status != OK ) { MINIBASE_BM->unpinPage( hpid ); return status; } // Set the next-page pointer on the previous directory page. dp->next_page = nexthpid; status = MINIBASE_BM->unpinPage( hpid, true /*dirty*/ ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); // Pin the newly-allocated directory page. hpid = nexthpid; status = MINIBASE_BM->pinPage( hpid, (Page*&)pg, true /*empty*/ ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); dp = (directory_page*)pg; init_dir_page( dp, sizeof(directory_page) ); free_slot = 0; } // At this point, "hpid" has the page id of the header page with the free // slot; "pg" points to the pinned page; "dp" has the directory_page // pointer; "free_slot" is the entry number in the directory where we're // going to put the new file entry. dp->entries[free_slot].pagenum = start_page_num; strcpy( dp->entries[free_slot].fname, fname ); status = MINIBASE_BM->unpinPage( hpid, true /*dirty*/ ); if ( status != OK ) status = MINIBASE_CHAIN_ERROR( DBMGR, status ); return status; }
int main(int argc , char** argv) { fp = fopen( FS_FILENAME , "r+b"); fs_info= get_fs_info( fp ); if( argc > 1) { if( strcmp( argv[1] , "init" )==0 ) { fs_init( argv[2] , FS_SIZE ); return 0; }else if( strcmp( argv[1] , "print_fats" )==0 ) { print_fat_entries( strtol(argv[2] , NULL , 10) ); return 0; }else if( strcmp( argv[1] , "neat_test" )==0 ) { //add an entry into the root dir table struct dir_table_entry temp; strcpy(temp.name , "neat.txt"); temp.file_size = 0; temp.allocated = 1; temp.starting_cluster = allocate_fat_block(); fseek( fp , fs_info->data_start , SEEK_SET); fwrite( &temp , 1 , sizeof(struct dir_table_entry) , fp); //modify root table entry struct dir_table_entry temp_root; fseek( fp , sizeof(struct boot_sec) , SEEK_SET); fread( &temp_root , sizeof(struct dir_table_entry) , 1 , fp ); temp_root.file_size = (int)sizeof(struct dir_table_entry); //printf( "read name: %s\n" , temp_root.name); //printf( "read size: %d\n" , temp_root.file_size); fseek( fp , sizeof(struct boot_sec) , SEEK_SET); fwrite( &temp_root , 1 , sizeof(struct dir_table_entry), fp ); //read the data struct file_descriptor root_fd; root_fd.pointer = (int)sizeof(struct boot_sec); struct dir_table_entry* root_entry = get_file_entry( root_fd ); //printf( "name: %s\n" , root_entry->name ); //printf( "size: %d\n" , root_entry->file_size ); //read root dir entries struct dir_table_entry* root_entries = get_dir_entries( root_fd ); //printf("root entry filename: %s\n" , root_entries->name ); //printf("root entry starting_cluster: %d\n" , root_entries->starting_cluster ); //printf("root entry allocated: %d\n" , root_entries->allocated ); fclose( fp ); return 0; }else if( strcmp( argv[1] , "neat_write_test")== 0 ) { struct file_descriptor temp_fd; temp_fd.pointer = fs_info->data_start; struct dir_table_entry* temp_entry = get_file_entry( temp_fd ); temp_entry->file_size = 0; fseek(fp , temp_fd.pointer , SEEK_SET); fwrite( temp_entry , 1 , sizeof( struct dir_table_entry ) , fp); char mssg[2000]; memset( mssg , 'a' , sizeof( mssg )/2 ); memset( mssg + sizeof( mssg )/2 , 'b' , sizeof( mssg )/2 ); write_file( mssg , temp_fd , 0 , (int)sizeof( mssg ) ); }else if( strcmp( argv[1] , "neat_read_test") == 0 ) { struct file_descriptor temp_fd; temp_fd.pointer = fs_info->data_start; char* buff = (char*)malloc( strtol(argv[2] , NULL , 10) ); read_file( buff , temp_fd , 0 , strtol(argv[2] , NULL , 10) ); //printf("message: %s\n" , buff); }else if( strcmp( argv[1] , "misc_test") == 0 ) { /* struct file_descriptor temp_fd; temp_fd.pointer = sizeof(struct boot_sec); int index = find_file_index( temp_fd , "neat.txt" ); temp_fd.pointer = index; struct dir_table_entry* file_entry = get_file_entry( temp_fd ); //printf("index: %d\n" , index); //printf("filename: %s\n" , file_entry->name ); */ char** dirs = split_string( argv[2] , "/" ); int i; printf("arg_count: %d\n", arg_count ); for( i = 0 ; i < arg_count ; i++) { printf("dirs[%d]: %s\n" , i , dirs[i] ); } }else if( strcmp( argv[1] , "delete_test") == 0 ) { struct file_descriptor temp_fd; temp_fd.pointer = fs_info->data_start; //printf(" delete result: %d\n" ,delete_file( temp_fd ) ); }else if( strcmp( argv[1] , "delete") == 0 ) { struct file_descriptor* fd = open_file( argv[2] ); delete_file( *fd ); }else if( strcmp( argv[1] , "open_test") == 0 ) { printf("opening file %s ...\n" , argv[2] ); struct file_descriptor* fd = open_file( argv[2] ); printf(" pointer: %d\n" , (*fd).pointer ); struct dir_table_entry* temp = get_file_entry( *fd ); printf( " filename: %s\n" , temp->name ); printf( " fileseize: %d\n" , temp->file_size ); }else if( strcmp( argv[1] , "create") == 0 ) { if(argc >= 3) { create_file( argv[2] , strtol(argv[3] , NULL , 10) ); }else{ printf("not enough arguments\n"); } }else if( strcmp( argv[1] , "ls") == 0 ) { //printf("\nprinting dir contents...\n"); struct file_descriptor* fd = open_file( argv[2] ); struct dir_table_entry* items = get_dir_entries( *fd ); struct dir_table_entry* entry = get_file_entry( *fd ); int i; for( i = 0 ; i < entry->file_size/((int)sizeof(struct dir_table_entry)) ; i ++) { if( items[ i ].allocated ) { printf(" %s\n", items[ i ].name ); } } }else if( strcmp( argv[1] , "write") == 0 ) { printf("argc: %d\n" , argc); if( argc < 4) { printf("invalid number of arguments\nexiting...\n"); return 0; } struct file_descriptor* file = open_file( argv[2] ); if( file!=NULL ) { char buff[ strtol(argv[3] , NULL , 10) ]; memset( buff , 'a' , strtol(argv[3] , NULL , 10) ); write_file( buff , *file , 0 , strtol(argv[3] , NULL , 10) ); }else{ printf("error opening file for writing\n"); } }else if( strcmp( argv[1] , "read") == 0 ) { printf("argc: %d\n" , argc); if( argc < 4) { printf("invalid number of arguments\nexiting...\n"); return 0; } struct file_descriptor* file = open_file( argv[2] ); if( file!=NULL ) { char buff[ strtol(argv[3] , NULL , 10) + 1 ]; read_file( buff , *file , 0 , strtol(argv[3] , NULL , 10) ); buff[ strtol(argv[3] , NULL , 10) ] = '\0'; printf("read: %s\n" , buff); }else{ printf("error opening file for writing\n"); } } } fclose(fp); return 0; }
int find_file_index( struct file_descriptor fd , char* filename) { struct dir_table_entry* file_info = get_file_entry(fd); //printf("finding file %s in %s...\n" , filename , file_info->name ); struct dir_table_entry entry; struct fat_entry cur_fat_entry; int cur_cluster_start; int i; int j = 0; fseek( fp , fd.pointer , SEEK_SET ); fread( &entry , 1 , sizeof( struct dir_table_entry ) , fp ); //printf("strcmp: %d\n" , strcmp( entry.name , "root") ); fseek( fp , fs_info->fat_start + (entry.starting_cluster * sizeof(struct fat_entry ) ) , SEEK_SET ); fread( &cur_fat_entry , 1 , sizeof( struct fat_entry ) , fp ); cur_cluster_start = cur_fat_entry.cluster; int dir_max_entries = entry.file_size / sizeof( struct dir_table_entry ); int offset; //printf("CLUSTER_SIZE / sizeof(struct dir_table_entry ): %d\n" , CLUSTER_SIZE / (int)sizeof(struct dir_table_entry ) ); for( i = 0 ; i < dir_max_entries ; i++ ) { offset = ( CLUSTER_SIZE * cur_cluster_start ) + ( j * (int)sizeof(struct dir_table_entry ) ); ////printf("offset: %d\n" , offset ); ////printf("j: %d\n" , j ); fseek( fp , fs_info->data_start + offset , SEEK_SET); fread( &entry , 1 , sizeof(struct dir_table_entry ) , fp); ////printf("entry %d: %s \n" , i , entry.name); if( strcmp( entry.name , filename) == 0 ) { return fs_info->data_start + ( CLUSTER_SIZE * cur_cluster_start ) + ( j * sizeof(struct dir_table_entry ) ); } j++; if( j == ( CLUSTER_SIZE / (int)sizeof(struct dir_table_entry ) ) && i!= dir_max_entries ) { fseek( fp , fs_info->fat_start + ( cur_fat_entry.next * sizeof(struct fat_entry) ) , SEEK_SET ); fread( &cur_fat_entry , 1 , sizeof(struct fat_entry) , fp); cur_cluster_start = cur_fat_entry.cluster; j = 0; } } return -1; }
struct file_descriptor* open_file( char* path ) { printf("opening file %s ...\n" , path); int i; if( (strlen(path) == 1) && path[0]=='/' ) { i = 1; }else{ i = 0; } char** dirs = split_string( path , "/" ); printf(" arg_count: %d\n" , arg_count); int k; for( k = 0 ; k < arg_count ; k++) { printf( " dirs[%d]: %s\n" , k , dirs[k] ); } int entry_count = 0 , j = 0; struct dir_table_entry* cur_entries; struct file_descriptor cur_fd; struct dir_table_entry* cur_file_entry; //get root directory file descriptor cur_fd.pointer = sizeof( struct boot_sec ); int found_file = 0; while( i < arg_count && !found_file ) { cur_entries = get_dir_entries( cur_fd ); cur_file_entry = get_file_entry( cur_fd ); //printf("\nretrieved file %s \n" , cur_file_entry->name ); entry_count = cur_file_entry->file_size / (int)sizeof( struct dir_table_entry ); //printf("entry_count: %d\n" , entry_count); for( j = 0 ; j < entry_count ; j++ ) { //printf("printing entry[%d]...\n" , j); cur_file_entry = cur_entries + j; //printf(" name: %s\n" , cur_file_entry->name ); if( cur_file_entry->allocated ) { //printf(" looking for file %s...\n" , *(dirs + i) ); if( strcmp( cur_file_entry->name , *(dirs + i) ) == 0 ) { if( i == (arg_count -1)) found_file = 1; //printf( " found file!\n"); cur_fd.pointer = find_file_index( cur_fd , cur_file_entry->name ); //printf(" %s fd pointer: %d\n" , cur_file_entry->name , cur_fd.pointer ); /* struct file_descriptor* ret = (struct file_descriptor*)malloc( sizeof(struct file_descriptor) ); memcpy( ret , &cur_fd , sizeof( struct file_descriptor ) ); return ret; */ } } } i++; } if( !found_file ) printf("file not found!\n"); struct file_descriptor* ret = (struct file_descriptor*)malloc( sizeof(struct file_descriptor) ); memcpy( ret , &cur_fd , sizeof( struct file_descriptor ) ); return ret; }
struct file_descriptor create_file( char* path , int attr) { printf("\ncreating file %s ...\n" , path); char* path_cpy = (char *)malloc( strlen( path ) + 1); char* path_cpy_2 = (char *)malloc( strlen( path ) + 1); memcpy( path_cpy , path , strlen( path ) + 1 ); int q; memcpy( path_cpy_2 , path , strlen( path ) + 1 ); //printf(" path_cpy: %s\n" , path_cpy ); //printf(" path: %s\n" , path ); //printf("printing path_cpy_2\n"); path_cpy_2[ strlen(path_cpy_2) ] = '\0'; for(q = 0 ; q < strlen(path_cpy_2) + 1 ; q++) { printf(" path[%d]: %c\n", q , path[q] ); } char** dirs = split_string( path_cpy_2 , "/" ); int k; //arg_count++; /*printf(" arg_count: %d\n" , arg_count); for( k = 0 ; k < arg_count - 1 ; k++) { printf( " dirs[%d]: %s\n" , k , dirs[k] ); } */ char* file_name = (char*)malloc( strlen( dirs[ arg_count - 1 ] ) ); memcpy( file_name , dirs[ arg_count - 1 ] , strlen( dirs[ arg_count - 1 ] ) ); //printf(" file to create: %s\n" , file_name); if(arg_count > 1) { int null_index = (int)(strlen(path_cpy) - strlen(file_name) ); printf(" null index: %d\n" , null_index ); path_cpy[ null_index ] = '\0'; }else { path_cpy = (char*)malloc(2); path_cpy[0] = '/'; path_cpy[1] = '\0'; } //printf( " path_cpy after null: %s\n", path_cpy ); //open the directory that will contain the new file struct file_descriptor* fd = open_file( path_cpy ); //retrieve the directory information struct dir_table_entry* file_entry = get_file_entry( *fd ); //create and populate the new dir table entry struct dir_table_entry new_file_entry; strcpy( new_file_entry.name , file_name ); new_file_entry.attribute = attr; new_file_entry.starting_cluster = allocate_fat_block(); new_file_entry.file_size = 0; new_file_entry.allocated = 1; //append this file entry to the directory file fd write_file( &new_file_entry , *fd , file_entry->file_size , sizeof( struct dir_table_entry ) ); }