int db_dirdelete(struct db_i *dbip, struct directory *dp) { struct directory *findp; struct directory **headp; RT_CK_DBI(dbip); RT_CK_DIR(dp); headp = &(dbip->dbi_Head[db_dirhash(dp->d_namep)]); if (dp->d_flags & RT_DIR_INMEM) { if (dp->d_un.ptr != NULL) bu_free(dp->d_un.ptr, "db_dirdelete() inmem ptr"); } if (*headp == dp) { RT_DIR_FREE_NAMEP(dp); /* frees d_namep */ *headp = dp->d_forw; /* Put 'dp' back on the freelist */ dp->d_forw = rt_uniresource.re_directory_hd; rt_uniresource.re_directory_hd = dp; return 0; } for (findp = *headp; findp != RT_DIR_NULL; findp = findp->d_forw) { if (findp->d_forw != dp) continue; RT_DIR_FREE_NAMEP(dp); /* frees d_namep */ findp->d_forw = dp->d_forw; /* Put 'dp' back on the freelist */ dp->d_forw = rt_uniresource.re_directory_hd; rt_uniresource.re_directory_hd = dp; return 0; } return -1; }
int db_rename(struct db_i *dbip, struct directory *dp, const char *newname) { struct directory *findp; struct directory **headp; RT_CK_DBI(dbip); RT_CK_DIR(dp); /* Remove from linked list */ headp = &(dbip->dbi_Head[db_dirhash(dp->d_namep)]); if (*headp == dp) { /* Was first on list, dequeue */ *headp = dp->d_forw; } else { for (findp = *headp; findp != RT_DIR_NULL; findp = findp->d_forw) { if (findp->d_forw != dp) continue; /* Dequeue */ findp->d_forw = dp->d_forw; goto out; } return -1; /* ERROR: can't find */ } out: /* Effect new name */ RT_DIR_FREE_NAMEP(dp); /* frees d_namep */ RT_DIR_SET_NAMEP(dp, newname); /* sets d_namep */ /* Add to new linked list */ headp = &(dbip->dbi_Head[db_dirhash(newname)]); dp->d_forw = *headp; *headp = dp; return 0; }
void db_close(register struct db_i *dbip) { register int i; register struct directory *dp, *nextdp; if (!dbip) return; RT_CK_DBI(dbip); if (RT_G_DEBUG&DEBUG_DB) bu_log("db_close(%s) %p uses=%d\n", dbip->dbi_filename, (void *)dbip, dbip->dbi_uses); bu_semaphore_acquire(BU_SEM_LISTS); if ((--dbip->dbi_uses) > 0) { bu_semaphore_release(BU_SEM_LISTS); /* others are still using this database */ return; } bu_semaphore_release(BU_SEM_LISTS); /* ready to free the database -- use count is now zero */ /* free up any mapped files */ if (dbip->dbi_mf) { /* * We're using an instance of a memory mapped file. * We have two choices: * Either dissociate from the memory mapped file * by clearing dbi_mf->apbuf, or * keeping our already-scanned dbip ready for * further use, with our dbi_uses counter at 0. * For speed of re-open, at the price of some address space, * the second choice is taken. */ bu_close_mapped_file(dbip->dbi_mf); bu_free_mapped_files(0); dbip->dbi_mf = (struct bu_mapped_file *)NULL; } /* try to ensure/encourage that the file is written out */ db_sync(dbip); if (dbip->dbi_fp) { fclose(dbip->dbi_fp); } if (dbip->dbi_title) bu_free(dbip->dbi_title, "dbi_title"); if (dbip->dbi_filename) bu_free(dbip->dbi_filename, "dbi_filename"); db_free_anim(dbip); rt_color_free(); /* Free MaterHead list */ /* Release map of database holes */ rt_mempurge(&(dbip->dbi_freep)); rt_memclose(); dbip->dbi_inmem = NULL; /* sanity */ bu_ptbl_free(&dbip->dbi_clients); /* Free all directory entries */ for (i = 0; i < RT_DBNHASH; i++) { for (dp = dbip->dbi_Head[i]; dp != RT_DIR_NULL;) { RT_CK_DIR(dp); nextdp = dp->d_forw; RT_DIR_FREE_NAMEP(dp); /* frees d_namep */ if ((dp->d_flags & RT_DIR_INMEM) && (dp->d_un.ptr != NULL)) { bu_free(dp->d_un.ptr, "db_close d_un.ptr"); dp->d_un.ptr = NULL; dp->d_len = 0; } /* Put 'dp' back on the freelist */ dp->d_forw = rt_uniresource.re_directory_hd; rt_uniresource.re_directory_hd = dp; /* null'ing the forward pointer here is a huge * memory leak as it causes the loss of all * nodes on the freelist except the first. * (so don't do it) */ dp = nextdp; } dbip->dbi_Head[i] = RT_DIR_NULL; /* sanity*/ } if (dbip->dbi_filepath != NULL) { bu_free_argv(2, dbip->dbi_filepath); dbip->dbi_filepath = NULL; /* sanity */ } bu_free((char *)dbip, "struct db_i"); }