void fs_remove_file(fs_t* fs, inodeid_t entryid) { fs_inode_t ifile = fs->inode_tab[entryid]; for(int i = 0; i < INODE_NUM_BLKS && ifile.blocks[i] != 0 ; i++) { BMAP_CLR(fs->blk_bmap, ifile.blocks[i]); } BMAP_CLR(fs->inode_bmap, entryid); }
static int cbm_write(struct exfat_dev* dev) { uint32_t allocated_clusters = DIV_ROUND_UP(cbm.get_size(), get_cluster_size()) + DIV_ROUND_UP(uct.get_size(), get_cluster_size()) + DIV_ROUND_UP(rootdir.get_size(), get_cluster_size()); size_t bitmap_size = DIV_ROUND_UP(allocated_clusters, CHAR_BIT); uint8_t* bitmap = malloc(bitmap_size); size_t i; if (bitmap == NULL) { exfat_error("failed to allocate bitmap of %zu bytes", bitmap_size); return 1; } for (i = 0; i < bitmap_size * CHAR_BIT; i++) if (i < allocated_clusters) BMAP_SET(bitmap, i); else BMAP_CLR(bitmap, i); if (exfat_write(dev, bitmap, bitmap_size) < 0) { exfat_error("failed to write bitmap of %zu bytes", bitmap_size); return 1; } free(bitmap); return 0; }
static void free_cluster(struct exfat* ef, cluster_t cluster) { if (CLUSTER_INVALID(cluster)) exfat_bug("freeing invalid cluster 0x%x", cluster); if (cluster - EXFAT_FIRST_DATA_CLUSTER >= ef->cmap.size) exfat_bug("freeing non-existing cluster 0x%x (0x%x)", cluster, ef->cmap.size); BMAP_CLR(ef->cmap.chunk, cluster - EXFAT_FIRST_DATA_CLUSTER); ef->cmap.dirty = true; }
void fs_remove_dir(fs_t* fs, inodeid_t dir) { fs_inode_t idir = fs->inode_tab[dir]; int num = idir.size / sizeof(fs_dentry_t); // numero de entradas num directorio fs_dentry_t page[DIR_PAGE_ENTRIES]; for(int i = 0; i < INODE_NUM_BLKS && idir.blocks[i] != 0; i++){ int num_dir_pg_entries; while(num > 0){ block_read(fs->blocks, idir.blocks[i], (char*)page); for(num_dir_pg_entries = 0; num_dir_pg_entries < DIR_PAGE_ENTRIES && num > 0; i++, num --){ inodeid_t entryid = page[num_dir_pg_entries].inodeid; if (fs->inode_tab[entryid].type == FS_FILE) fs_remove_file(fs, entryid); else fs_remove_dir(fs, entryid); } } } BMAP_CLR(fs->inode_bmap, dir); }
int fs_remove(fs_t* fs, inodeid_t dir, char *name) { //checks if the arguments are valid if (fs == NULL || dir>=ITAB_SIZE || name == NULL) { dprintf("[fs_remove] malformed arguments. \n"); return -1; } if (strlen(name) == 0 || strlen(name)+1 > FS_MAX_FNAME_SZ) { dprintf("[fs_remove] file name size error\n"); return -1; } if (!BMAP_ISSET(fs->inode_bmap, dir)) { dprintf("[fs_remove] inode is not being used.\n"); return -1; } inodeid_t entryid = 0; if (!fsi_dir_search(fs, dir, name, &entryid) == 0) { dprintf("[fs_remove] file/dir does not exist\n"); return -1; } fs_inode_t* idir = &fs->inode_tab[dir]; if (idir->type != FS_DIR) { dprintf("[fs_remove] inode is not a directory. \n"); return -1; } fs_dentry_t page[DIR_PAGE_ENTRIES]; int num_dir_entry = 0, block_num = 0; search_dir_entry(fs, dir, entryid, &num_dir_entry, &block_num, (char*)page); fs_dentry_t last_page[DIR_PAGE_ENTRIES]; // array de entradas do ultimo bloco int last_entry_index = (idir->size % BLOCK_SIZE / sizeof(fs_dentry_t)) -1; block_read(fs->blocks,idir->blocks[idir->size/BLOCK_SIZE],(char *)last_page); fs_dentry_t* last_entry = &last_page[last_entry_index]; // ponteiro p/ última posição ocupada do dir page[num_dir_entry] = *last_entry; // mete a ultima entrada na posição da que vai ser removida block_write(fs->blocks, idir->blocks[block_num], (char*)page); // escreve o bloco (page) no disco idir->size -= sizeof(fs_dentry_t); // diminui o tamanho do directório em uma entrada int i, j; if (last_entry_index == 0) { //se for a primeira entrada do bloco, elimina esse bloco for(i = 0, j = 1; idir->blocks[j] != 0; i++, j++); BMAP_CLR(fs->blk_bmap, idir->blocks[i]); idir->blocks[i] = 0; } fs_inode_t ientry = fs->inode_tab[entryid]; // vai buscar o inode do ficheiro/directorio à tabela de inodes if(ientry.type == FS_FILE) fs_remove_file(fs, entryid); else fs_remove_dir(fs, entryid); BMAP_CLR(fs->inode_bmap, entryid); return 0; }