char* _dir_find_entry_name(minifile_t inode, int inode_id) { int i, x; block_t dir_data_block; char* buff; for (i = 0; i < inode->u.data.num_data_blocks; i++) { dir_data_block = _retrieve_block(_inode_get_data_block_id(inode, i)); // Go through the listing for (x = 0; x < MAX_DIR_DATA_BLOCK_ENTRIES; x++) { if (dir_data_block->type.dir_data_block.entries[x].inode_block_id != 0) { if (dir_data_block->type.dir_data_block.entries[x].inode_block_id == inode_id) { _release_block(dir_data_block); _release_block((block_t) inode); buff = (char*) malloc(sizeof(char) * (strlen(dir_data_block->type.dir_data_block.entries[x].name) + 1)); strcpy(buff, dir_data_block->type.dir_data_block.entries[x].name); return buff; } } } _release_block(dir_data_block); } _release_block((block_t) inode); return NULL; }
int _dir_remove_entry(minifile_t dir, int inode_block_id) { int i, x; block_t dir_data_block; minifile_t inode = (minifile_t) _retrieve_block(inode_block_id); for (i = 0; i < dir->u.data.num_data_blocks; i++) { dir_data_block = _retrieve_block(_inode_get_data_block_id(dir, i)); // Go through the listing for (x = 0; x < MAX_DIR_DATA_BLOCK_ENTRIES; x++) { if (dir_data_block->type.dir_data_block.entries[x].inode_block_id == inode_block_id) { dir_data_block->type.dir_data_block.entries[x].inode_block_id = 0; inode->u.data.size--; _commit_block((block_t) dir_data_block); _commit_block(inode); _release_block((block_t) dir_data_block); _release_block((block_t) inode); return 0; } } _release_block(dir_data_block); } _release_block((block_t) inode); return -1; }
int _dir_find_entry(minifile_t inode, char* filename) { int i, x; block_t dir_data_block; for (i = 0; i < inode->u.data.num_data_blocks; i++) { dir_data_block = _retrieve_block(_inode_get_data_block_id(inode, i)); // Go through the listing for (x = 0; x < MAX_DIR_DATA_BLOCK_ENTRIES; x++) { if (dir_data_block->type.dir_data_block.entries[x].inode_block_id != 0) { if ( strcmp(dir_data_block->type.dir_data_block.entries[x].name, filename) == 0) { _release_block(dir_data_block); _release_block((block_t) inode); return dir_data_block->type.dir_data_block.entries[x].inode_block_id; } } } _release_block(dir_data_block); } _release_block((block_t) inode); return -1; }
int _inode_get_data_block_id(minifile_t inode, int block_num) { int indir_block_id; block_t indir_block; int blocks_seen; int block_id; if (inode->u.data.num_data_blocks == 0) { // Add the first data block. // Other than this, if they specify a nonexistent block, we return -1 block_id = _inode_add_new_data_block(inode); } if (block_num < 11) { return inode->u.data.data_block_ids[block_num]; } indir_block_id = inode->u.data.indir_block_id; blocks_seen = 11; while (indir_block_id != 0) { indir_block = _retrieve_block(indir_block_id); if ((block_num - blocks_seen) < MAX_INDIR_BLOCK_ENTRIES -1) // nearly positive we need +1 after blocknum, write it out - say we have 12 data blocks in groups of two. If we saw 9 blocks, we'd really have seen 8 and be on the wrong block, but 10-9 = 1 < 2... { block_id = indir_block->type.indir_block.entries[(block_num-11) % MAX_INDIR_BLOCK_ENTRIES]; _release_block(indir_block); return block_id; } indir_block_id = indir_block->type.indir_block.entries[MAX_INDIR_BLOCK_ENTRIES]; _release_block(indir_block); blocks_seen += MAX_INDIR_BLOCK_ENTRIES -1; } return -1; }
/* This gets the current data block, and creates a new one (and indir block) if it * sees that the current ones are full. */ int _inode_find_curr_data_block_id(minifile_t inode) { int num_data_blocks = inode->u.data.num_data_blocks; int size = inode->u.data.size; block_t indir_block; int block_id; int threshold_size; /* todo - put this back after we have creating files/dirs working if (inode->u.data.block_type != BLOCK_TYPE_DIRECTORY) { return 0; } */ // Determine what the size of the inode really means if (inode->u.data.block_type == BLOCK_TYPE_DIRECTORY) { threshold_size = MAX_DIR_DATA_BLOCK_ENTRIES; if (size >= 11) size -= 11; } else { threshold_size = DISK_BLOCK_SIZE; if (size >= 11*DISK_BLOCK_SIZE) size -= 11*DISK_BLOCK_SIZE; } // If no block yet if (num_data_blocks == 0) { return _inode_add_new_data_block(inode); } // If we're out of blocks, get a new one and return it if (size > 0 && size % threshold_size == 0) { return _inode_add_new_data_block(inode); } // Otherwise, find the latest data block if (num_data_blocks <= 11) { return inode->u.data.data_block_ids[num_data_blocks-1]; } else { indir_block = _retrieve_block(inode->u.data.latest_indir_block_id); block_id = indir_block->type.indir_block.entries[((num_data_blocks-12) % MAX_INDIR_BLOCK_ENTRIES)]; _release_block(indir_block); return block_id; } }
void _big_xdebug_write(unsigned EAX, void* *ECX) { // ECX IS BLOCK TABLE // EAX IS BYTE COUNT if (EAX) { void* *EBX = ECX; unsigned count = EAX; L1: void *p = *EBX; *EBX = 0; unsigned n = PAGE_SIZE; if (count <= n) n = count; _xdebug_normal(p, n); count -= n; ++EBX; _release_block(p); if (count) goto L1; return; } void *a = (void *)EAX; void **c = ECX; __asm { mov EAX,a mov ECX,c xchg [ECX],EAX mov a,EAX } if (a) _release_block(a); }
int _pop_free_data_block() { block_t block; int block_id; superblock_t superblock = (superblock_t) _retrieve_block(0); block = _retrieve_block(superblock->u.data.first_free_data_block_id); block_id = block->block_id; superblock->u.data.first_free_data_block_id = block->type.free_data_block.next_free_data_block_id; _release_block(block); _commit_block((block_t) superblock); return block_id; }
int _pop_free_inode() { block_t block; int block_id; superblock_t superblock = (superblock_t) _retrieve_block(0); if (superblock == NULL) return -1; block = _retrieve_block(superblock->u.data.first_free_inode_id); block_id = block->block_id; superblock->u.data.first_free_inode_id = block->type.free_inode.next_free_inode_id; _release_block(block); _commit_block((block_t) superblock); return block_id; }
// todo - make it search for an empty spot int _dir_add_entry(minifile_t inode, int inode_block_id, char* name) { block_t dir_data_block; int dir_size = inode->u.data.size; int next_idx = dir_size % MAX_DIR_DATA_BLOCK_ENTRIES; int found_block_id; int curr_data_block; if (inode == NULL) { return -1; } // todo - ensure file isn't already in directory found_block_id = _dir_find_entry(inode, name); if (found_block_id != -1) { return found_block_id; } // Get the block - it is guaranteed to have room curr_data_block = _inode_find_curr_data_block_id(inode); dir_data_block = _retrieve_block(curr_data_block); // Add ourselves to the block dir_data_block->type.dir_data_block.entries[next_idx].inode_block_id = inode_block_id; strcpy(dir_data_block->type.dir_data_block.entries[next_idx].name, name); // todo - may need to account for endianness & use packing // Update the inode's size inode->u.data.size++; // Close & save the block dir_data_block->is_dirty = 1; _release_block(dir_data_block); // Release the inode too _commit_block((block_t) inode); return 0; }
int _inode_add_new_data_block(minifile_t inode) { int num_data_blocks = inode->u.data.num_data_blocks; int new_block_id; int new_indir_block_id; block_t indir_block; // Check if we need to add a normal block if (num_data_blocks < 11) { new_block_id = _pop_free_data_block(); inode->u.data.data_block_ids[num_data_blocks] = new_block_id; } // Check if we need to create our first indirection block else if (num_data_blocks == 11) { // Get the new block IDs new_indir_block_id = _pop_free_data_block(); new_block_id = _pop_free_data_block(); // Setup the indirection block indir_block = _retrieve_block(new_indir_block_id); indir_block->type.indir_block.entries[0] = new_block_id; indir_block->type.indir_block.entries[MAX_INDIR_BLOCK_ENTRIES] = 0; // we check this eventually // Close & save the indirection block indir_block->is_dirty = 1; _release_block(indir_block); // Update the inode inode->u.data.indir_block_id = new_indir_block_id; inode->u.data.latest_indir_block_id = new_indir_block_id; } // Check if we need to update the indirection current blocks else if (num_data_blocks > 11) { // Check if we need to create a new indirection block as well if ((num_data_blocks-11) % MAX_INDIR_BLOCK_ENTRIES == 0) { // We could make this just make the indir block, and remove the code from // the else and put it below, which would look cleaner; however, it would // also be slower. // Get the new data blocks new_indir_block_id = _pop_free_data_block(); new_block_id = _pop_free_data_block(); // Setup the indirection block indir_block = _retrieve_block(new_indir_block_id); indir_block->type.indir_block.entries[0] = new_block_id; indir_block->type.indir_block.entries[MAX_INDIR_BLOCK_ENTRIES] = 0; // we check this eventually // Close & save the indirection block indir_block->is_dirty = 1; _release_block(indir_block); // Open up the old indirection block and update it indir_block = _retrieve_block(inode->u.data.latest_indir_block_id); indir_block->type.indir_block.entries[MAX_INDIR_BLOCK_ENTRIES] = new_indir_block_id; // we check this eventually // Close and save the old indirection block indir_block->is_dirty = 1; _commit_block(indir_block); _release_block(indir_block); // Update the inode inode->u.data.latest_indir_block_id = new_indir_block_id; } // Otherwise, just add a new data block to the current indirection block else { // Get the new data block new_block_id = _pop_free_data_block(); // Open up the indirection block and update it indir_block = _retrieve_block(inode->u.data.latest_indir_block_id); indir_block->type.indir_block.entries[((num_data_blocks-11) % MAX_INDIR_BLOCK_ENTRIES)] = new_block_id; // no need for +1, the math works // Close and save the indirection block indir_block->is_dirty = 1; _release_block(indir_block); } } // Update & commit the inode inode->u.data.num_data_blocks++; _commit_block((block_t) inode); return new_block_id; }
/* Given a path, find the inode it refers to (either file or dir) */ int _find_path_inode(char* path) { int i, x; minifile_t inode; block_t data_block; char** path_parts; int path_part_ct = 0; int found_inode = 1; minithread_t running = minithread_self(); superblock_t superblock; int block_id; int path_parts_size = _find_path_len(path); if (strcmp(path, "/") == 0) { superblock = (superblock_t) _retrieve_block(0); block_id = superblock->u.data.root_dir_block_id; return block_id; } // Split up path by "/"s path_parts = _parse_path(path, path_parts_size); // Is this a relative or absolute path? if (path[0] == '/') { /* TODO: MUST PUT THIS BACK IN superblock = (superblock_t) _retrieve_block(0); inode = (minifile_t) _retrieve_block(superblock->u.data.root_dir_block_id); */ inode = (minifile_t) _retrieve_block(1); path_part_ct++; } else { inode = (minifile_t) _retrieve_block(running->dir_block_id); } while (found_inode == 1 && path_part_ct < path_parts_size) { found_inode = 0; // Go through all the data blocks for (i = 0; i < inode->u.data.num_data_blocks; i++) { if (found_inode == 1) break; data_block = _retrieve_block(_inode_get_data_block_id(inode, i)); // Go through the listing for (x = 0; x < MAX_DIR_DATA_BLOCK_ENTRIES; x++) { if (data_block->type.dir_data_block.entries[x].inode_block_id == 0) { continue; } if (strcmp(data_block->type.dir_data_block.entries[x].name, path_parts[path_part_ct]) == 0) { // We found it block_id = data_block->type.dir_data_block.entries[x].inode_block_id; _release_block((block_t) inode); inode = (minifile_t) _retrieve_block(data_block->type.dir_data_block.entries[x].inode_block_id); found_inode = 1; path_part_ct++; break; } } } } _release_block((block_t) inode); if (found_inode == 1) { return block_id; } return -1; }