static void test_Delete_Tree(TestBatch *batch) { Folder *folder = (Folder*)RAMFolder_new(NULL); FileHandle *fh; bool_t result; // Create tree to be deleted. Folder_MkDir(folder, &foo); Folder_MkDir(folder, &foo_bar); Folder_MkDir(folder, &foo_bar_baz); fh = Folder_Open_FileHandle(folder, &foo_bar_baz_boffo, FH_CREATE | FH_WRITE_ONLY); DECREF(fh); // Create bystanders. Folder_MkDir(folder, &bar); fh = Folder_Open_FileHandle(folder, &baz, FH_CREATE | FH_WRITE_ONLY); DECREF(fh); result = Folder_Delete_Tree(folder, &foo); TEST_TRUE(batch, result, "Delete_Tree() succeeded"); TEST_FALSE(batch, Folder_Exists(folder, &foo), "Tree really gone"); TEST_TRUE(batch, Folder_Exists(folder, &bar), "local dir with same name as nested dir left intact"); TEST_TRUE(batch, Folder_Exists(folder, &baz), "local file with same name as nested dir left intact"); // Kill off the bystanders. result = Folder_Delete_Tree(folder, &bar); TEST_TRUE(batch, result, "Delete_Tree() on empty dir"); result = Folder_Delete_Tree(folder, &baz); TEST_TRUE(batch, result, "Delete_Tree() on file"); // Create new tree to be deleted. Folder_MkDir(folder, &foo); Folder_MkDir(folder, &foo_bar); Folder_MkDir(folder, &foo_bar_baz); fh = Folder_Open_FileHandle(folder, &foo_bar_baz_boffo, FH_CREATE | FH_WRITE_ONLY); DECREF(fh); // Remove tree in subdir. result = Folder_Delete_Tree(folder, &foo_bar); TEST_TRUE(batch, result, "Delete_Tree() of subdir succeeded"); TEST_FALSE(batch, Folder_Exists(folder, &foo_bar), "subdir really gone"); TEST_TRUE(batch, Folder_Exists(folder, &foo), "enclosing dir left intact"); DECREF(folder); }
bool_t Folder_delete_tree(Folder *self, const CharBuf *path) { Folder *enclosing_folder = Folder_Enclosing_Folder(self, path); // Don't allow Folder to delete itself. if (!path || !CB_Get_Size(path)) { return false; } if (enclosing_folder) { ZombieCharBuf *local = IxFileNames_local_part(path, ZCB_BLANK()); if (Folder_Local_Is_Directory(enclosing_folder, (CharBuf*)local)) { Folder *inner_folder = Folder_Local_Find_Folder(enclosing_folder, (CharBuf*)local); DirHandle *dh = Folder_Local_Open_Dir(inner_folder); if (dh) { VArray *files = VA_new(20); VArray *dirs = VA_new(20); CharBuf *entry = DH_Get_Entry(dh); while (DH_Next(dh)) { VA_Push(files, (Obj*)CB_Clone(entry)); if (DH_Entry_Is_Dir(dh) && !DH_Entry_Is_Symlink(dh)) { VA_Push(dirs, (Obj*)CB_Clone(entry)); } } for (uint32_t i = 0, max = VA_Get_Size(dirs); i < max; i++) { CharBuf *name = (CharBuf*)VA_Fetch(files, i); bool_t success = Folder_Delete_Tree(inner_folder, name); if (!success && Folder_Local_Exists(inner_folder, name)) { break; } } for (uint32_t i = 0, max = VA_Get_Size(files); i < max; i++) { CharBuf *name = (CharBuf*)VA_Fetch(files, i); bool_t success = Folder_Local_Delete(inner_folder, name); if (!success && Folder_Local_Exists(inner_folder, name)) { break; } } DECREF(dirs); DECREF(files); DECREF(dh); } } return Folder_Local_Delete(enclosing_folder, (CharBuf*)local); } else { // Return failure if the entry wasn't there in the first place. return false; } }
void SegWriter_Prep_Seg_Dir_IMP(SegWriter *self) { SegWriterIVARS *const ivars = SegWriter_IVARS(self); Folder *folder = SegWriter_Get_Folder(self); String *seg_name = Seg_Get_Name(ivars->segment); // Clear stale segment files from crashed indexing sessions. if (Folder_Exists(folder, seg_name)) { bool result = Folder_Delete_Tree(folder, seg_name); if (!result) { THROW(ERR, "Couldn't completely remove '%o'", seg_name); } } // Create the segment directory. bool result = Folder_MkDir(folder, seg_name); if (!result) { RETHROW(INCREF(Err_get_error())); } }