int write_to_file(int child_nbr, inode inode, uint16_t newblock_nbr, uint8_t block[], superblock spb, FILE * ufs) { if (child_nbr >= 1024) { printf("Inode full\n"); return -1; } int blocksize = spb.magic_number; // int j; for(j = 0; j < blocksize; j++)printf("%c",block[j]); int initial_pos = ftell(ufs); if (child_nbr < BLK_PER_IND-4) //No refered position { inode.blocks[child_nbr] = newblock_nbr; inode_write(inode.id, ufs, blocksize, spb.root_inode, inode); fseek(ufs, spb.root_dir * blocksize, SEEK_SET); fseek(ufs, newblock_nbr * blocksize, SEEK_CUR); fwrite(block, sizeof(uint8_t), blocksize, ufs); } else //Refered position { // printf("entrou aqui\n"); int newblock; int block_in_vec = (BLK_PER_IND-4) + ((child_nbr - (BLK_PER_IND-4))/(blocksize/2)); int jump_inside = 0; if ((child_nbr - (BLK_PER_IND-4))%(blocksize/2) == 0)//First position, verify is block is already there { if (inode.blocks[block_in_vec] == 0)//Alloc the block { // printf("Seraaqui?\n"); newblock = frst_free_block(ufs, spb.magic_number, spb.root_dir); // printf("%d<>%d\n",newblock, block_in_vec); inode.blocks[block_in_vec] = newblock; inode_write(inode.id, ufs, blocksize, spb.root_inode, inode); } else newblock = inode.blocks[block_in_vec]; } else { newblock = inode.blocks[block_in_vec]; jump_inside = (child_nbr - (BLK_PER_IND-4))%(blocksize/2) * sizeof(uint16_t); } fseek(ufs, spb.root_dir * blocksize, SEEK_SET); fseek(ufs, newblock * blocksize, SEEK_CUR); if (jump_inside) fseek(ufs, jump_inside, SEEK_CUR); fwrite(&newblock_nbr, sizeof(uint16_t), 1, ufs); fseek(ufs, spb.root_dir * blocksize, SEEK_SET); fseek(ufs, newblock_nbr * blocksize, SEEK_CUR); fwrite(block, sizeof(uint8_t), blocksize, ufs); } fseek(ufs, initial_pos, SEEK_SET); return 0; }
int fs_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { struct inode *ino = (struct inode *)fi->fh; ino->i_mtime = time(NULL); return inode_write(ino, buf, size, offset); }
//****** cnwrite ********************* size_t cnwrite(uint8_t* buf, size_t bytes, int16_t fd) { fd_entry* fde = &fd_tbl[fd]; check(fde->state == FD_WRITE, "File descriptor not in write mode"); uint32_t required_size = fde->cursor + bytes; if(fde->inode.size < required_size) //The data cache and block size may have to be expanded { //Compute new sizes uint32_t required_blocks = (required_size / BLOCK_SIZE) + 1; //Allocate new data cache check(realloc_cache(fde, required_blocks) == 0, "Unable to realloc cache"); fde->inode.size = required_size; //Allocate fs blocks if(fde->inode.blocks < required_blocks) { check(realloc_fs_blocks(&fde->inode, required_blocks) == 0, "Could not allocate fs blocks"); } fde->inode.modified = time(NULL); inode_write(fde->inode_id, &fde->inode); } uint8_t* data_ptr = ((uint8_t*)fde->data)+fde->cursor; memcpy(data_ptr, buf, bytes); fde->cursor += bytes; llwrite(&fde->inode, (block*)fde->data); return bytes; error: return 0; }
//****** cnseek ********************** int8_t cnseek(int16_t fd, uint32_t offset) { fd_entry* fde = &fd_tbl[fd]; uint32_t required_size = fde->cursor + offset; if(fde->inode.size < required_size) //The data cache and block size may have to be expanded { //Compute new sizes uint32_t required_blocks = (required_size / BLOCK_SIZE) + 1; //Allocate new data cache check(realloc_cache(fde, required_blocks) == 0, "Unable to realloc cache"); fde->inode.size = required_size; //Allocate fs blocks if(fde->inode.blocks < required_blocks) { check(realloc_fs_blocks(&fde->inode, required_blocks) == 0, "Could not allocate fs blocks"); } fde->inode.modified = time(NULL); inode_write(fde->inode_id, &fde->inode); } fde->cursor = offset; return 0; error: return -1; }
//******** rmdir ******************** int8_t cnrmdir(const char* name) { char parent_name[512]; char entry_name[256]; dir_entry* entry; inode dir_inode; memset(&dir_inode, 0, sizeof(inode)); strcpy(parent_name, name); strcat(parent_name, "/.."); dir_ptr* parent = cnopendir(parent_name); check(parent != NULL, "Cannot open parent directory"); //Copy the entire directory minus the entry dir_ptr* new_parent = calloc(1,sizeof(dir_ptr)); new_parent->data = calloc(parent->inode_st.blocks, sizeof(block)); dir_entry* new_dir_entry = (dir_entry*)new_parent->data; new_parent->inode_st = parent->inode_st; new_parent->inode_id = parent->inode_id; new_parent->inode_st.size = 0; new_parent->index = 0; while((entry = cnreaddir(parent))) { memcpy(entry_name, entry->name, entry->name_len); entry_name[entry->name_len] = 0; if(strcmp(entry_name, name) == 0) //If this is the directory we want { inode_read(entry->inode, &dir_inode); check(dir_inode.size == 24, "Directory is not empty"); release_block(dir_inode.data0[0]); //Release target directory block release_inode(entry->inode); //Release target inode continue; } new_dir_entry->entry_len = entry->entry_len; new_dir_entry->name_len = entry->name_len; new_dir_entry->file_type = entry->file_type; new_dir_entry->inode = entry->inode; memcpy(new_dir_entry->name, entry->name, entry->name_len); new_parent->inode_st.size += entry->entry_len; new_parent->index += entry->entry_len; new_dir_entry = (dir_entry*)((uint8_t*)new_parent->data+new_parent->index); } inode_write(new_parent->inode_id, &new_parent->inode_st); llwrite(&new_parent->inode_st, new_parent->data); free(new_parent->data); free(new_parent); cnclosedir(parent); return 0; error: if(new_parent != NULL && new_parent->data != NULL) free(new_parent->data); if(new_parent != NULL) free(new_parent); if(parent != NULL) cnclosedir(parent); return -1; }
int inode_append (super_block_t *sb, int index, void *buffer, int len) { // assert (sb != NULL); // assert (index >= 0 && index < INODE_ARRAY_SIZE); // assert (buffer != NULL); // assert (len >= 0); int offset = sb->inodes[index].size; return inode_write (sb, index, offset, buffer, len); }
//******** creat ******************** int8_t cncreat(dir_ptr* dir, const char* name) { stat_st stat_buf; dir_entry* entry; check(cnstat(dir,name,&stat_buf) != 0, "File exists"); //If this file exists //Create parent directory entry entry = (dir_entry*)(((uint8_t*)dir->data)+dir->index); entry->file_type = ITYPE_FILE; entry->inode = reserve_inode(); memcpy(entry->name, name, strlen(name)); entry->name_len = strlen(name); entry->entry_len = entry->name_len + 8; entry->entry_len += (4 - entry->entry_len % 4); //padding out to 32 bits dir->inode_st.size += entry->entry_len; //TODO: handle creat dir block overflow //Write parent dir and inode dir->inode_st.modified = time(NULL); inode_write(dir->inode_id, &dir->inode_st); blk_write(dir->inode_st.data0[0], dir->data); //Write new file inode inode new_file_i; memset(&new_file_i, 0, sizeof(inode)); uint32_t now = time(NULL); new_file_i.modified = now; new_file_i.type = ITYPE_FILE; new_file_i.size = 0; new_file_i.blocks = 0; inode_write(entry->inode, &new_file_i); return 0; error: return -1; }
// Opens a link filetype unsigned int fs_open_link(char * name, char * target_name) { unsigned int folder_inode = current_ttyc()->pwd; int target_inode = fs_indir(target_name, folder_inode); if(target_inode > 0) { int result = fs_open_file(name, folder_inode, O_NEW, EXT2_S_IFLNK); if(result > 0) { inode_read(result, &n); n.data_blocks[0] = target_inode; inode_write(result, &n); result = fs_open_reg_file(target_name, folder_inode, O_RD); inode_read(result, &n); n.links++; inode_write(result, &n); return 1; } else { return result; } } else { return ERR_NO_EXIST; } }
// Changes the permissions of the file unsigned int fs_chmod(char * filename, int perms) { int current_uid = current_ttyc()->uid; int start_inode = current_ttyc()->pwd; int namenode = fs_indir(filename, start_inode); if (namenode) { inode_read(namenode, &n); if (n.uid == current_uid || current_uid == 0) { n.i_file_acl = perms; inode_write(namenode, &n); } else { return ERR_PERMS; } return 1; } else { return ERR_NO_EXIST; } }
// Changes the inode's owner unsigned int fs_chown(char * filename, char * username) { int new_uid = user_exists(username); int current_uid = current_ttyc()->uid; int start_inode = current_ttyc()->pwd; int namenode = fs_indir(filename, start_inode); if (namenode && new_uid != -1) { inode_read(namenode, &n); if (n.uid == current_uid || current_uid == 0) { n.uid = new_uid; inode_write(namenode, &n); } else { return ERR_PERMS; } return 1; } else { return ERR_NO_EXIST; } }
void remove_from_dir(int inode_id, inode parent, FILE *ufs, superblock spb) { uint16_t children[1024] = {0}; inode realoc; int i; int position = -1; int blocksize = spb.magic_number; int last = first_free_child(parent, ufs, spb, blocksize, children); for (i = 0; i < last; i++) { if (children[i] == inode_id) { position = i; } } if (last == -1) last = 1023; else last -= 1; if (position == -1) { printf("Error\n"); return; } // printf("Position %d last %d children %d\n", position, last, children[last]); write_to_dir(position, parent, children[last], spb, ufs); inode_read(parent.id, ufs, spb.magic_number, spb.root_inode, &parent); // printf("last one is %d\n",last); //inode_read(last, ufs, blocksize, spb.root_inode, &realoc); // inode_write(inode_id, ufs, blocksize, uint16_t first_inode_blk, realoc); // write_to_dir(inode_id, parent, last, spb, ufs); write_to_dir(last, parent, 0, spb, ufs); if ((last - (BLK_PER_IND-4))%(blocksize/2) == 0) { // printf("caiu aqui\n"); int block_in_vec = (BLK_PER_IND-4) + ((last - (BLK_PER_IND-4))/(blocksize/2)); inode_read(parent.id, ufs, spb.magic_number, spb.root_inode, &parent); parent.blocks[block_in_vec] = 0; inode_write(parent.id, ufs, blocksize, spb.root_inode, parent); } }
int fs_write (fs_t *fs, int index, int offset, void *buffer, int len) { // assert (fs != NULL); // assert (index >= 0 && index < INODE_ARRAY_SIZE); // assert (buffer != NULL); // assert (offset >= 0); // assert (len >= 0); index_node_t *inode = &fs->super_block->inodes[index]; // assert (inode->in_use == 1); if (offset + len > LOC_LIMIT_DOUBLE_INDIRECT) return -1; int status; if (inode->size < offset + len) { status = inode_expand (fs->super_block, index, offset + len); if (status < 0) return -1; } return inode_write (fs->super_block, index, offset, buffer, len); }
/** * Write to file f. */ int file_write(struct file *f, char *addr, int n) { int r; if(f->writable == 0) return -1; if(f->type == FD_INODE){ // Write a few blocks at a time to avoid exceeding // the maximum log transaction size, including // i-node, indirect block, allocation blocks, // and 2 blocks of slop for non-aligned writes. // this really belongs lower down, since inode_write() // might be writing a device like the console. int max = ((LOGSIZE-1-1-2) / 2) * 512; int i = 0; while(i < n){ int n1 = n - i; if(n1 > max) n1 = max; begin_trans(); inode_lock(f->ip); if ((r = inode_write(f->ip, addr + i, f->off, n1)) > 0) f->off += r; inode_unlock(f->ip); commit_trans(); if(r < 0) break; if(r != n1) KERN_PANIC("short file_write"); i += r; } return i == n ? n : -1; } KERN_PANIC("file_write"); }
void write_root_dir(void) { //Prepare inode inode root_i; memset(&root_i, 0, sizeof(inode)); uint32_t now = time(NULL); root_i.modified = now; root_i.type = ITYPE_DIR; root_i.size = 0; root_i.blocks = 1; root_i.data0[0] = BLOCKID_ROOT_DIR; block* root_dir_block = calloc(1,sizeof(block)); // . (self entry) dir_entry* root_dir_entry = (dir_entry*)root_dir_block; root_dir_entry->inode = 0; root_dir_entry->file_type = ITYPE_DIR; root_dir_entry->name_len = 1; root_dir_entry->entry_len = 12; memcpy(root_dir_entry->name, ".", 1); root_i.size += 12; // .. (parent entry, also itself) root_dir_entry = (dir_entry*)(((char*)root_dir_block) + 12); root_dir_entry->inode = 0; root_dir_entry->file_type = ITYPE_DIR; root_dir_entry->name_len = 2; root_dir_entry->entry_len = 12; memcpy(root_dir_entry->name, "..", 2); root_i.size += 12; inode_write(0, &root_i); blk_write(BLOCKID_ROOT_DIR, root_dir_block); free(root_dir_block); }
// Writes to a file, as simple as unix unsigned int fs_write_file(int inode, char * data, int size) { inode_clear(&n); // Clear the inode to take off the trash inode_read(inode, &n); // Read the current inode. int log_block = n.blocks / 2; block_clear(&b); // Prepare to read the data, clear it. int i = 0; int block_index = n._last_write_offset; log_block_read(&n, &log_block); // Set up the point where we'll write char * block = (char *) &b; // Write until we reach end for (; i < size; i++) { block[block_index] = data[i]; if (block_index == FS_BLOCK_SIZE - 1) { log_block_write(&n, &log_block); log_block++; // Iterate if necessary. log_block_read(&n, &log_block); block_index = 0; } else { block_index++; } } n._last_write_offset = block_index; log_block_write(&n, &log_block); // Save the last bits n.blocks = log_block * 2; // Update the inodes inode_write(inode,&n); fs_bitmaps_write_all(); // Persist the changes in the FS return i; }
// Used to move a file unsigned int fs_mv(char * name, char * newname, int from_inode) { int i1 = fs_open_file(name, from_inode, O_WR | O_RD, EXT2_S_IFREG); if(i1 < 0) { return i1; // If there's an error with the first name then there's nothing to do actually. } int i2 = fs_indir(newname, from_inode); if(i2 == 0) { folder_rem_direntry(i1, n._dir_inode); inode_read(from_inode, &n); int log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; log_block_read(&n, &log_block); add_dir_entry(&n, EXT2_FT_DIR, i1, newname, &log_block); log_block_write(&n, &log_block); n.blocks = log_block * 2; inode_write(from_inode, &n); return 1; } else { inode_read(i2, &n); if(!fs_has_perms(&n, ACTION_READ)) { return ERR_PERMS; } if(!(n.mode & EXT2_S_IFDIR)) { return ERR_INVALID_TYPE; } if (fs_indir(name, i2)) { return ERR_REPEATED; } int log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; log_block_read(&n, &log_block); add_dir_entry(&n, EXT2_FT_DIR, i1, name, &log_block); log_block_write(&n, &log_block); n.blocks = log_block * 2; inode_write(i2, &n); inode_read(i1, &n); folder_rem_direntry(i1, n._dir_inode); inode_read(i1, &n); folder_rem_direntry(n._dir_inode, i1); log_block_read(&n, &log_block); add_dir_entry(&n, EXT2_FT_DIR, i2, "..", &log_block); log_block_write(&n, &log_block); n._dir_inode = i2; inode_write(i1, &n); } return i1; }
//******** mkdir ******************** int8_t cnmkdir(const char* name) { char* name_copy = strdup(name); char name_tok[256]; char entry_name[256]; char* next_name_tok; dir_entry* entry; dir_ptr *dir = calloc(1,sizeof(dir_ptr)); //Directory file in memory (e.g. DIR object from filedef.h) bool last_dir = false; inode_read(cwd->inode_id, &dir->inode_st); //Start at cwd dir->inode_id = cwd->inode_id; next_name_tok = strtok(name_copy, "/"); do { //name_tok is the dir we are searching for or going to create strcpy(name_tok, next_name_tok); //Read the directory file for this inode dir->data = calloc(dir->inode_st.blocks,sizeof(block)); //Memory for all directory file blocks llread(&dir->inode_st, dir->data); //Read the directory file dir->index = 0; next_name_tok = strtok(NULL, "/"); //Read the next token if(next_name_tok == NULL) //This is the last directory in the path { last_dir = true; } //Find the token in this dir while((entry = cnreaddir(dir))) { memcpy(entry_name, entry->name, entry->name_len); entry_name[entry->name_len] = 0; if(strcmp(entry_name, name_tok) == 0) //If this directory already exists { if(last_dir) { return -1; //Directory already exists } else //Read the directory inode { dir->inode_id = entry->inode; inode_read(entry->inode,&dir->inode_st); //Read the next directory's inode free(dir->data); //Forget the directory we just read break; } } } if(last_dir) //Create the directory at the end of the list { //Create parent directory entry entry = (dir_entry*)(((uint8_t*)dir->data)+dir->index); entry->file_type = ITYPE_DIR; entry->inode = reserve_inode(); memcpy(entry->name,name_tok,strlen(name_tok)); entry->name_len = strlen(name_tok); entry->entry_len = entry->name_len + 8; entry->entry_len += (4 - entry->entry_len % 4); //padding out to 32 bits dir->inode_st.size += entry->entry_len; //TODO: handle mkdir block overflow //Write parent dir and inode dir->inode_st.modified = time(NULL); inode_write(dir->inode_id, &dir->inode_st); blk_write(dir->inode_st.data0[0], dir->data); //Write new directory inode inode new_dir_i; memset(&new_dir_i, 0, sizeof(inode)); uint32_t now = time(NULL); new_dir_i.modified = now; new_dir_i.type = ITYPE_DIR; new_dir_i.size = 0; new_dir_i.blocks = 1; new_dir_i.data0[0] = reserve_block(); //Write new directory file block* new_dir_block = calloc(1,sizeof(block)); // . (self entry) dir_entry* new_dir_self_entry = (dir_entry*)new_dir_block; new_dir_self_entry->inode = entry->inode; new_dir_self_entry->file_type = ITYPE_DIR; new_dir_self_entry->name_len = 1; new_dir_self_entry->entry_len = 12; memcpy(new_dir_self_entry->name, ".", 1); new_dir_i.size += 12; // .. (parent entry) dir_entry* new_dir_parent_entry = (dir_entry*)(((uint8_t*)new_dir_block) + 12); new_dir_parent_entry->inode = dir->inode_id; new_dir_parent_entry->file_type = ITYPE_DIR; new_dir_parent_entry->name_len = 2; new_dir_parent_entry->entry_len = 12; memcpy(new_dir_parent_entry->name, "..", 2); new_dir_i.size += 12; //Write new dir and inode inode_write(entry->inode, &new_dir_i); blk_write(new_dir_i.data0[0], new_dir_block); free(new_dir_block); break; } } while(1); free(dir); free(name_copy); return 0; }
// Makes a new directory unsigned int fs_mkdir(char * name, unsigned int parent_inode) { unsigned int inode_id = 0; if ((inode_id = fs_indir(name, parent_inode))) { return 0; } inode_id = bitmap_first_valued(bm_inodes, FS_INODE_BITMAP_SIZE, 0) + 1; if (!parent_inode) { parent_inode = inode_id; } int log_block; if (parent_inode != inode_id) { inode_read(parent_inode, &n); if(!fs_has_perms(&n, ACTION_WRITE)) { return ERR_PERMS; } log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; log_block_read(&n, &log_block); add_dir_entry(&n, EXT2_FT_DIR, inode_id, name, &log_block); log_block_write(&n, &log_block); inode_write(parent_inode, &n); } bitmap_write(bm_inodes, inode_id - 1, 1); inode_clear(&n); if(!fs_done) { n.uid = 0; } else { n.uid = current_ttyc()->uid; } n.mode = EXT2_S_IFDIR; n.size = 0; n.blocks = 0; // Beware! This represents the SECTORS! log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; add_dir_entry(&n, EXT2_FT_DIR, inode_id, ".", &log_block); add_dir_entry(&n, EXT2_FT_DIR, parent_inode, "..", &log_block); log_block_write(&n, &log_block); n.blocks = (log_block) * 2; n.i_file_acl = 511; n._dir_inode = parent_inode; n._last_write_offset = dir_op_offset; inode_write(inode_id, &n); fs_bitmaps_write_all(); return inode_id; }
// Opens a file unsigned int fs_open_file(char * name, unsigned int folder_inode, int mode, int type) { unsigned int inode_id = 0; if(strcmp(name, "/") == 0 && strlen(name) == strlen("/")) { return 1; // root } if(name[0] == 0) { inode_id = current_ttyc()->pwd; } else { inode_id = fs_indir(name, folder_inode); } if (inode_id) { if (mode & O_CREAT) { int _rm_res = fs_rm(inode_id, 0); if(_rm_res < 0) { return _rm_res; } } else if(mode & O_NEW) { inode_read(inode_id, &n); if(n.mode == EXT2_S_IFLNK) { return n.data_blocks[0]; } return inode_id; } else { inode_read(inode_id, &n); int can = 1; if((mode & O_RD) && !fs_has_perms(&n, ACTION_READ)) { can = 0; } if((mode & O_WR) && !fs_has_perms(&n, ACTION_WRITE)) { can = 0; } if(can || !fs_done) { if(n.mode == EXT2_S_IFLNK) { return n.data_blocks[0]; } return inode_id; } else { return ERR_PERMS; } } } else if (!(mode & (O_NEW | O_CREAT))) { return ERR_NO_EXIST; } inode_id = bitmap_first_valued(bm_inodes, FS_INODE_BITMAP_SIZE, 0) + 1; if (!folder_inode) { folder_inode = inode_id; } int log_block; if (folder_inode != inode_id) { inode_read(folder_inode, &n); if(!fs_has_perms(&n, ACTION_WRITE)) { return ERR_PERMS; } log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; log_block_read(&n, &log_block); add_dir_entry(&n, EXT2_FT_DIR, inode_id, name, &log_block); log_block_write(&n, &log_block); inode_write(folder_inode, &n); } bitmap_write(bm_inodes, inode_id - 1, 1); inode_clear(&n); if(!fs_done) { n.uid = 0; } else { n.uid = current_ttyc()->uid; } n.mode = type; n.size = 0; n.blocks = 0; // Beware! This represents the SECTORS! n._last_write_offset = 0; n.i_file_acl = 511; n._dir_inode = folder_inode; inode_write(inode_id, &n); inode_clear(&n); if(n.mode == EXT2_S_IFLNK) { return n.data_blocks[0]; } return inode_id; }
// Removes an inode from the filesystem, documented in header unsigned int fs_rm(unsigned int inode, int inside_recursion) { inode_read(inode, &n); if(!(inode > 1)) { return ERR_PERMS; // Permissions check } if(!fs_has_perms(&n, ACTION_WRITE)) { return ERR_PERMS; // If you can't write you can't delete... } if(n.links > 0) { return ERR_PERMS; // If you can't write you can't delete... } if(n.mode == EXT2_S_IFLNK) { int ptr = n.data_blocks[0]; inode_read(ptr, &n); n.links--; inode_write(ptr, &n); inode_read(inode, &n); } if (!inside_recursion) { // I'm not sure about this, but well... at least it's just a security flaw. inode_read(n._dir_inode, &n); if(!fs_has_perms(&n, ACTION_WRITE)) { return ERR_PERMS; // If you can't write on the parent folder you can't delete } inode_read(inode, &n); } int log_block = n.blocks / 2 + 1; // Logical block top int ph_block = 0; // Go from top to bottom to delete everything. while(log_block > 0) { log_block--; make_ph_block(&n, &ph_block, &log_block); if (n.mode & EXT2_S_IFDIR) { // If it's a directory... then... RECURSION! D: block entries; data_read_block(&entries, ph_block); int off = 0; dir_op_offset = 0; dir_entry * old_dot = NULL; dir_entry * dot = iterate_dir_entry(&entries); // Iterates dir entries while (dot != NULL) { if (dot == NULL) { break; } else { if (dot->name_len > 0 && dot->inode != inode && dot->inode != n._dir_inode) { // If we get an error we don't actually make anything :D, but we might delete other files. int _rm = fs_rm(dot->inode, 1); if(_rm < 0) { data_write_block(&entries, ph_block); bitmap_write(bm_blocks, ph_block - 1, 0); return _rm; } off = dir_op_offset; dot->name_len = 0; dir_op_offset = off; inode_read(inode, &n); } } old_dot = dot; dot = iterate_dir_entry(&entries); } data_write_block(&entries, ph_block); } bitmap_write(bm_blocks, ph_block - 1, 0); // This deletes the stuff actually delete_internal_inodes(log_block); // This deletes the EXT2 ugly but wise indirects. } // Delete the directory entry of the file. if (!inside_recursion) { inode_read(inode, &n); unsigned int folder_inode = n._dir_inode; inode_read(folder_inode, &n); folder_rem_direntry(inode, folder_inode); } bitmap_write(bm_inodes, inode - 1, 0); // Persist the directory liberation. fs_bitmaps_write_all(); // Persist in the FS. return 1; }