#include #include #include #include #include "common.h" #include "debug.h" #include "string.h" #include "collection.h" #include "function.h" #include "array.h" #include "set.h" #include "file.h" #include "filepath.h" #include "holemanager.h" enum { DEBUG_HOLEMANAGER = false, HOLEMANAGER_DUMPFILE_PERM = 0755L }; struct HoleManager { Set *holes; char *holefile; bool isdirty; }; static collection_do_ret holemanager_dump_holes_each(void *p, void *arg) { int result; char *filename = (char *)p; Biobuf *biohole = (Biobuf *)arg; assert_valid(filename); assert(strlen(filename) > 0); assert_valid(biohole); result = Bprint(biohole, "%s\n", filename); if(result == Beof) { WARNING(DEBUG_HOLEMANAGER, "holemanager_dump_holes_each failed to write to file"); } // NOISE(DEBUG_HOLEMANAGER, "holemanager_dump_holes_each dumping %s", filename); return COLLECTION_DO_CONTINUE; } static void holemanager_dump_holes(HoleManager *self) { int result; Biobuf *biohole; assert_valid(self); biohole = Bopen(self->holefile, OWRITE); if(biohole == nil) { WARNING(DEBUG_HOLEMANAGER, "holemanager_dump_holes unable to open dump file"); return; } set_do(self->holes, holemanager_dump_holes_each, biohole); result = Bterm(biohole); NOISE(DEBUG_HOLEMANAGER, "holemanager_dump_holes total: %ud Bterm returns %d", set_size(self->holes), result); NOISE(DEBUG_HOLEMANAGER, "holemanager_dump_holes unsetting dirty bit"); self->isdirty = false; } static void holemanager_read_holes(HoleManager *self) { int result; int fd; char *filename; Biobuf biohole; assert_valid(self); fd = file_open(self->holefile, OREAD); if(!fd_isopen(fd)) { NOISE(DEBUG_HOLEMANAGER, "holemanager_read_holes unable to open hole file %s for reading", self->holefile); return; } result = Binit(&biohole, fd, OREAD); NOISE(DEBUG_HOLEMANAGER, "holemanager_read_holes Binit returns %s", result); while((filename = Brdstr(&biohole, '\n', 1)) != nil) { NOISE(DEBUG_HOLEMANAGER, "holemanager_read_holes reading filename: %s len: %d", filename, strlen(filename)); set_add(self->holes, filename); } result = Bterm(&biohole); file_close(fd); NOISE(DEBUG_HOLEMANAGER, "holemanager_dump_holes Bterm returns %d", result); self->isdirty = false; } HoleManager *holemanager_new(char *holefile) { HoleManager *result = (HoleManager *)emalloc_fs(sizeof(*result)); result->holes = set_new(string_isequal, string_hash); result->isdirty = false; if(holefile != nil) { result->holefile = filepath_make_absolute_cstr(holefile); holemanager_read_holes(result); } else { result->holefile = estrdup_fs("/tmp/holes"); } NOISE(DEBUG_HOLEMANAGER, "holemanager_new holefile: %s", result->holefile); return result; } void holemanager_free(HoleManager *self) { if(self == nil) { return; } free(self->holefile); set_free_with(self->holes, free); free(self); } void holemanager_add(HoleManager *self, char *holepath) { assert_valid(self); assert_valid(holepath); NOISE(DEBUG_HOLEMANAGER, "holemanager_add adding hole: %s", holepath); set_add(self->holes, estrdup_fs(holepath)); NOISE(DEBUG_HOLEMANAGER, "holemanager_add setting dirty bit"); self->isdirty = true; holemanager_dump_holes(self); } bool holemanager_includes(HoleManager *self, char *holepath) { bool result; assert_valid(self); assert_valid(holepath); result = set_includes(self->holes, holepath); NOISE(DEBUG_HOLEMANAGER, "holemanager_includes path: %s result: %d", holepath, result); return result; } void holemanager_remove(HoleManager *self, char *holepath) { bool result; assert_valid(self); assert_valid(holepath); result = set_remove(self->holes, holepath); NOISE(DEBUG_HOLEMANAGER, "holemanager_remove removing: %s with result: %d", holepath, result); self->isdirty = true; NOISE(DEBUG_HOLEMANAGER, "holemanager_add setting dirty bit"); holemanager_dump_holes(self); }