HIDDEN void txt_free(void *cp) { struct txt_specific *tp = (struct txt_specific *)cp; bu_vls_free(&tp->tx_name); if (tp->tx_binunifp) rt_binunif_free(tp->tx_binunifp); if (tp->tx_mp) bu_close_mapped_file(tp->tx_mp); tp->tx_binunifp = (struct rt_binunif_internal *)NULL; /* sanity */ tp->tx_mp = (struct bu_mapped_file *)NULL; /* sanity */ BU_PUT(cp, struct txt_specific); }
/* * T X T _ F R E E */ HIDDEN void txt_free(char *cp) { struct txt_specific *tp = (struct txt_specific *)cp; bu_vls_free(&tp->tx_name); if (tp->tx_binunifp) rt_binunif_free( tp->tx_binunifp ); if (tp->tx_mp) bu_close_mapped_file( tp->tx_mp ); tp->tx_binunifp = GENPTR_NULL; /* sanity */ tp->tx_mp = GENPTR_NULL; /* sanity */ bu_free( cp, "txt_specific" ); }
/* * E X T _ S E T U P * * Returns 0 on failure, 1 on success. */ HIDDEN int ext_setup(register struct region *rp, struct bu_vls *matparm, char **dpp, struct mfuncs *mf_p, struct rt_i *rtip, struct mfuncs **headp) /* parameter string */ /* pointer to user data pointer */ { struct bu_mapped_file *parameter_file; struct bu_vls parameter_data; char *filename; int status; RT_CHECK_RTI(rtip); BU_CK_VLS( matparm ); RT_CK_REGION(rp); filename = bu_vls_addr(matparm); parameter_file = bu_open_mapped_file( filename, (char *)NULL ); if (!parameter_file) { bu_log("cannot open external shader file \"%s\"\n", filename); bu_bomb("ext_setup()\n"); } bu_vls_init(¶meter_data); bu_vls_strncpy( ¶meter_data, (char *)parameter_file->buf, parameter_file->buflen ); if (rdebug&RDEBUG_SHADE ) { bu_log("ext_setup(%s): {%s}\n", filename, bu_vls_addr(¶meter_data)); } bu_close_mapped_file( parameter_file ); status = sh_stk_setup(rp, ¶meter_data, dpp, mf_p, rtip, headp); bu_vls_free( ¶meter_data ); return status; }
int rt_mk_binunif(struct rt_wdb *wdbp, const char *obj_name, const char *file_name, unsigned int minor_type, size_t max_count) { int ret; struct stat st; size_t num_items = 0; size_t obj_length = 0; size_t item_length = 0; unsigned int major_type = DB5_MAJORTYPE_BINARY_UNIF; struct directory *dp = NULL; struct bu_mapped_file *bu_fd = NULL; struct rt_binunif_internal *bip = NULL; struct bu_external body; struct bu_external bin_ext; struct rt_db_internal intern; item_length = db5_type_sizeof_h_binu(minor_type); if (item_length == 0) { bu_log("Unrecognized minor type (%d)!\n", minor_type); return -1; } if (bu_stat(file_name, &st)) { bu_log("Cannot stat input file (%s)", file_name); return -1; } bu_fd = bu_open_mapped_file(file_name, NULL); if (bu_fd == NULL) { bu_log("Cannot open input file (%s) for reading", file_name); return -1; } /* create the rt_binunif internal form */ BU_ALLOC(bip, struct rt_binunif_internal); bip->magic = RT_BINUNIF_INTERNAL_MAGIC; bip->type = minor_type; num_items = (size_t)(st.st_size / item_length); /* maybe only a partial file read */ if (max_count > 0 && max_count < num_items) { num_items = max_count; } obj_length = num_items * item_length; if (obj_length < 1) { obj_length = 1; } /* just copy the bytes */ bip->count = (long)num_items; bip->u.int8 = (char *)bu_malloc(obj_length, "binary uniform object"); memcpy(bip->u.int8, bu_fd->buf, obj_length); bu_close_mapped_file(bu_fd); /* create the rt_internal form */ RT_DB_INTERNAL_INIT(&intern); intern.idb_major_type = major_type; intern.idb_minor_type = minor_type; intern.idb_ptr = (genptr_t)bip; intern.idb_meth = &rt_functab[ID_BINUNIF]; /* create body portion of external form */ ret = -1; if (intern.idb_meth->ft_export5) { ret = intern.idb_meth->ft_export5(&body, &intern, 1.0, wdbp->dbip, wdbp->wdb_resp); } if (ret != 0) { bu_log("Error while attempting to export %s\n", obj_name); rt_db_free_internal(&intern); return -1; } /* create entire external form */ db5_export_object3(&bin_ext, DB5HDR_HFLAGS_DLI_APPLICATION_DATA_OBJECT, obj_name, 0, NULL, &body, intern.idb_major_type, intern.idb_minor_type, DB5_ZZZ_UNCOMPRESSED, DB5_ZZZ_UNCOMPRESSED); rt_db_free_internal(&intern); bu_free_external(&body); /* make sure the database directory is initialized */ if (wdbp->dbip->dbi_eof == RT_DIR_PHONY_ADDR) { ret = db_dirbuild(wdbp->dbip); if (ret) { return -1; } } /* add this (phony until written) object to the directory */ if ((dp=db_diradd5(wdbp->dbip, obj_name, RT_DIR_PHONY_ADDR, major_type, minor_type, 0, 0, NULL)) == RT_DIR_NULL) { bu_log("Error while attempting to add new name (%s) to the database", obj_name); bu_free_external(&bin_ext); return -1; } /* and write it to the database */ if (db_put_external5(&bin_ext, dp, wdbp->dbip)) { bu_log("Error while adding new binary object (%s) to the database", obj_name); bu_free_external(&bin_ext); return -1; } bu_free_external(&bin_ext); return 0; }
struct db_i * db_open(const char *name, const char *mode) { register struct db_i *dbip = DBI_NULL; register int i; char **argv; if (name == NULL) return DBI_NULL; if (RT_G_DEBUG & DEBUG_DB) { bu_log("db_open(%s, %s)\n", name, mode); } if (mode && mode[0] == 'r' && mode[1] == '\0') { /* Read-only mode */ struct bu_mapped_file *mfp; mfp = bu_open_mapped_file(name, "db_i"); if (mfp == NULL) { if (RT_G_DEBUG & DEBUG_DB) { bu_log("db_open(%s) FAILED, unable to open as a mapped file\n", name); } return DBI_NULL; } /* Is this a re-use of a previously mapped file? */ if (mfp->apbuf) { dbip = (struct db_i *)mfp->apbuf; RT_CK_DBI(dbip); dbip->dbi_uses++; /* * decrement the mapped file reference counter by 1, * references are already counted in dbip->dbi_uses */ bu_close_mapped_file(mfp); if (RT_G_DEBUG & DEBUG_DB) { bu_log("db_open(%s) dbip=%p: reused previously mapped file\n", name, (void *)dbip); } return dbip; } BU_ALLOC(dbip, struct db_i); dbip->dbi_mf = mfp; dbip->dbi_eof = (off_t)mfp->buflen; dbip->dbi_inmem = mfp->buf; dbip->dbi_mf->apbuf = (void *)dbip; /* Do this too, so we can seek around on the file */ if ((dbip->dbi_fp = fopen(name, "rb")) == NULL) { if (RT_G_DEBUG & DEBUG_DB) { bu_log("db_open(%s) FAILED, unable to open file for reading\n", name); } bu_free((char *)dbip, "struct db_i"); return DBI_NULL; } dbip->dbi_read_only = 1; } else { /* Read-write mode */ BU_ALLOC(dbip, struct db_i); dbip->dbi_eof = (off_t)-1L; if ((dbip->dbi_fp = fopen(name, "r+b")) == NULL) { if (RT_G_DEBUG & DEBUG_DB) { bu_log("db_open(%s) FAILED, unable to open file for reading/writing\n", name); } bu_free((char *)dbip, "struct db_i"); return DBI_NULL; } dbip->dbi_read_only = 0; } /* Initialize fields */ for (i = 0; i < RT_DBNHASH; i++) dbip->dbi_Head[i] = RT_DIR_NULL; dbip->dbi_local2base = 1.0; /* mm */ dbip->dbi_base2local = 1.0; dbip->dbi_title = (char *)0; dbip->dbi_uses = 1; /* FIXME: At some point, expand argv search paths with * getenv("BRLCAD_FILE_PATH") paths */ /* intentionally acquiring dynamic memory here since we set * dbip->dbi_filepath to argv. arg values and array memory are * released during db_close. */ argv = (char **)bu_malloc(3 * sizeof(char *), "dbi_filepath[3]"); argv[0] = bu_strdup("."); argv[1] = bu_dirname(name); argv[2] = NULL; dbip->dbi_filepath = argv; #if !defined(_WIN32) || defined(__CYGWIN__) /* If not a full path */ if (argv[1][0] != '/') { struct bu_vls fullpath = BU_VLS_INIT_ZERO; bu_free((void *)argv[1], "db_open: argv[1]"); argv[1] = getcwd((char *)NULL, (size_t)MAXPATHLEN); /* Something went wrong and we didn't get the CWD. So, * free up any memory allocated here and return DBI_NULL */ if (argv[1] == NULL) { if (dbip->dbi_mf) { bu_close_mapped_file(dbip->dbi_mf); bu_free_mapped_files(0); dbip->dbi_mf = (struct bu_mapped_file *)NULL; } if (dbip->dbi_fp) { fclose(dbip->dbi_fp); } bu_free((void *)argv[0], "db_open: argv[0]"); bu_free((void *)argv, "db_open: argv"); bu_free((char *)dbip, "struct db_i"); return DBI_NULL; } bu_vls_printf(&fullpath, "%s/%s", argv[1], name); dbip->dbi_filename = bu_strdup(bu_vls_addr(&fullpath)); bu_vls_free(&fullpath); } else { /* Record the filename and file path */ dbip->dbi_filename = bu_strdup(name); } #else /* Record the filename and file path */ dbip->dbi_filename = bu_strdup(name); #endif bu_ptbl_init(&dbip->dbi_clients, 128, "dbi_clients[]"); dbip->dbi_magic = DBI_MAGIC; /* Now it's valid */ /* determine version */ dbip->dbi_version = 0; /* make db_version() calculate */ dbip->dbi_version = db_version(dbip); if (dbip->dbi_version < 5) { if (rt_db_flip_endian(dbip)) { if (dbip->dbi_version > 0) dbip->dbi_version *= -1; dbip->dbi_read_only = 1; bu_log("WARNING: Binary-incompatible v4 geometry database detected.\n"); bu_log(" Endianness flipped. Converting to READ ONLY.\n"); } } if (RT_G_DEBUG & DEBUG_DB) { bu_log("db_open(%s) dbip=%p version=%d\n", dbip->dbi_filename, (void *)dbip, dbip->dbi_version); } return dbip; }
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"); }
/* T R E E T H E R M _ S E T U P * * This routine is called (at prep time) * once for each region which uses this shader. * Any shader-specific initialization should be done here. */ HIDDEN int tthrm_setup(register struct region *rp, struct bu_vls *matparm, genptr_t *dpp, const struct mfuncs *UNUSED(mfp), struct rt_i *rtip) /* pointer to reg_udata in *rp */ /* New since 4.4 release */ { register struct tthrm_specific *tthrm_sp; struct bu_mapped_file *tt_file; char *tt_data; long cyl_tot = 0; long tseg; float *fp; float fv[4]; double min_temp; double max_temp; point_t center; point_t pt; vect_t dir; static const double inv_nodes = 1.0/8.0; int node; int i; int long_size = 0; size_t file_size_long; size_t file_size_int; /* check the arguments */ RT_CHECK_RTI(rtip); BU_CK_VLS(matparm); RT_CK_REGION(rp); if (rdebug&RDEBUG_SHADE) bu_log("tthrm_setup(Region:\"%s\", tthrm(%s))\n", rp->reg_name, bu_vls_addr(matparm)); /* Get memory for the shader parameters and shader-specific data */ BU_GET(tthrm_sp, struct tthrm_specific); *dpp = tthrm_sp; tthrm_sp->magic = tthrm_MAGIC; tthrm_sp->tt_name[0] = '\0'; tthrm_sp->tt_min_temp = tthrm_sp->tt_max_temp = 0.0; if (rdebug&RDEBUG_SHADE) bu_log("Parsing: (%s)\n", bu_vls_addr(matparm)); if (bu_struct_parse(matparm, tthrm_parse, (char *)tthrm_sp) < 0) { bu_bomb(__FILE__); } if (tthrm_sp->tt_name[0] == '\0') { bu_log("Must specify file for tthrm shader on %s (got \"%s\"\n", rp->reg_name, bu_vls_addr(matparm)); bu_bomb(__FILE__); } tt_file = bu_open_mapped_file(tthrm_sp->tt_name, (char *)NULL); if (!tt_file) { bu_log("Error mapping \"%s\"\n", tthrm_sp->tt_name); bu_bomb("shader tthrm: can't get thermal data"); } tt_data = tt_file->buf; if (rdebug&RDEBUG_SHADE) bu_log("tthrm_setup() data: %p total\n", (void *)tt_data); /* Compute how big the file should be, so that we can guess * at the size of the integer at the front of the file */ file_size_int = sizeof(int) + *((int *)tt_data) * (sizeof(short) + sizeof(float) * 4 * NUM_NODES); file_size_long = sizeof(long) + *((long *)tt_data) * (sizeof(short) + sizeof(float) * 4 * NUM_NODES); switch (sizeof(long)) { case 8: if (tt_file->buflen == file_size_long) { /* 64bit data on 64bit host */ long_size = sizeof(long); tthrm_sp->tt_max_seg = cyl_tot = *((long *)tt_data); } else if (tt_file->buflen == file_size_int) { /* 32bit data on 32bit host */ long_size = sizeof(int); tthrm_sp->tt_max_seg = cyl_tot = *((int *)tt_data); } break; case 4: if (tt_file->buflen == file_size_long) { /* 32bit data on 32bit host */ long_size = sizeof(long); tthrm_sp->tt_max_seg = cyl_tot = *((long *)tt_data); } else if (tt_file->buflen == (file_size_long+4)) { /* 64bit data on 32bit host */ cyl_tot = *((int *)tt_data); if (cyl_tot != 0) { bu_log("%s:%d thermal data written on 64bit machine with more that 2^32 segs\n", __FILE__, __LINE__); bu_bomb(""); } long_size = sizeof(long) + 4; tthrm_sp->tt_max_seg = cyl_tot = ((int *)tt_data)[1]; } break; default: bu_log("a long int is %d bytes on this machine\n", sizeof(long)); bu_bomb("I can only handle 4 or 8 byte longs\n"); break; } if (rdebug&RDEBUG_SHADE) bu_log("cyl_tot = %ld\n", cyl_tot); tthrm_sp->tt_segs = (struct thrm_seg *) bu_calloc(cyl_tot, sizeof(struct thrm_seg), "thermal segs"); min_temp = MAX_FASTF; max_temp = -MAX_FASTF; #define CYL_DATA(_n) ((float *) (&tt_data[ \ long_size + \ (_n) * (sizeof(short) + sizeof(float) * 4 * NUM_NODES) + \ sizeof(short) \ ])) for (tseg = 0; tseg < cyl_tot; tseg++) { /* compute centerpoint, min/max temperature values */ fp = CYL_DATA(tseg); VSETALL(center, 0.0); for (node=0; node < NUM_NODES; node++, fp+=4) { /* this is necessary to assure that all float * values are aligned on 4-byte boundaries */ memcpy(fv, fp, sizeof(float)*4); if (rdebug&RDEBUG_SHADE) bu_log("tthrm_setup() node %d (%g %g %g) %g\n", node, fv[0], fv[1], fv[2], fv[3]); /* make sure we don't have any "infinity" values */ for (i=0; i < 4; i++) { if (fv[i] > MAX_FASTF || fv[i] < -MAX_FASTF) { bu_log("%s:%d seg %ld node %d coord %d out of bounds: %g\n", __FILE__, __LINE__, tseg, node, i, fv[i]); bu_bomb("choke, gasp, *croak*\n"); } } /* copy the values to the segment list, converting * from Meters to Millimeters in the process */ VSCALE(tthrm_sp->tt_segs[tseg].node[node], fv, 1000.0); tthrm_sp->tt_segs[tseg].temperature[node] = fv[3]; VADD2(center, center, fv); if (fv[3] > max_temp) max_temp = fv[3]; if (fv[3] < min_temp) min_temp = fv[3]; } VSCALE(center, center, 1000.0); VSCALE(tthrm_sp->tt_segs[tseg].pt, center, inv_nodes); if (rdebug&RDEBUG_SHADE) { bu_log("Center: (%g %g %g) (now in mm, not m)\n", V3ARGS(tthrm_sp->tt_segs[tseg].pt)); } /* compute vectors from center pt for each node */ fp = CYL_DATA(tseg); for (node=0; node < NUM_NODES; node++, fp+=4) { /* this is necessary to assure that all float * values are aligned on 4-byte boundaries */ memcpy(fv, fp, sizeof(float)*4); VSCALE(pt, fv, 1000.0); VSUB2(tthrm_sp->tt_segs[tseg].vect[node], pt, tthrm_sp->tt_segs[tseg].pt ); } /* compute a direction vector for the thermal segment */ VCROSS(dir, tthrm_sp->tt_segs[tseg].vect[0], tthrm_sp->tt_segs[tseg].vect[2]); VUNITIZE(dir); VMOVE(tthrm_sp->tt_segs[tseg].dir, dir); tthrm_sp->tt_segs[tseg].magic = THRM_SEG_MAGIC; } bu_close_mapped_file(tt_file); if (ZERO(tthrm_sp->tt_min_temp) && EQUAL(tthrm_sp->tt_max_temp, SMALL_FASTF)) { tthrm_sp->tt_min_temp = min_temp; tthrm_sp->tt_max_temp = max_temp; bu_log("computed temp min/max on %s: %g/%g\n", rp->reg_name, min_temp, max_temp); } else { min_temp =tthrm_sp->tt_min_temp; max_temp = tthrm_sp->tt_max_temp; bu_log("taking user specified on %s: min/max %g/%g\n", rp->reg_name, min_temp, max_temp); } if (!EQUAL(max_temp, min_temp)) { tthrm_sp->tt_temp_scale = 1.0 / (max_temp - min_temp); } else { /* min and max are equal, maybe zero */ if (ZERO(max_temp)) tthrm_sp->tt_temp_scale = 0.0; else tthrm_sp->tt_temp_scale = 255.0/max_temp; } /* The shader needs to operate in a coordinate system which stays * fixed on the region when the region is moved (as in animation) * we need to get a matrix to perform the appropriate transform(s). * * Shading is done in "region coordinates": */ db_region_mat(tthrm_sp->tthrm_m_to_sh, rtip->rti_dbip, rp->reg_name, &rt_uniresource); if (rdebug&RDEBUG_SHADE) { bu_log("min_temp: %17.14e max_temp %17.14e temp_scale: %17.14e\n", tthrm_sp->tt_min_temp, tthrm_sp->tt_max_temp, tthrm_sp->tt_temp_scale); bu_log("tthrm_setup(%s, %s)done\n", rp->reg_name, bu_vls_addr(matparm)); tthrm_print(rp, *dpp); } return 1; }
int rt_mk_binunif(struct rt_wdb *wdbp, const char *obj_name, const char *file_name, unsigned int minor_type, long max_count) { struct stat st; unsigned int major_type=DB5_MAJORTYPE_BINARY_UNIF; #if defined(_WIN32) && !defined(__CYGWIN__) __int64 num_items=-1; __int64 obj_length=-1; #else long long num_items=-1; long long obj_length=-1; #endif int item_length=0; struct bu_mapped_file *bu_fd; struct rt_binunif_internal *bip; struct rt_db_internal intern; struct bu_external body; struct bu_external bin_ext; struct directory *dp; if ( (item_length=db5_type_sizeof_h_binu( minor_type ) ) <= 0 ) { bu_log( "Unrecognized minor type!!!\n" ); return -1; } if ( stat( file_name, &st ) ) { bu_log( "Cannot stat input file(%s)", file_name ); return -1; } if ( (bu_fd=bu_open_mapped_file( file_name, NULL)) == NULL ) { bu_log( "Cannot open input file(%s) for reading", file_name ); return -1; } /* create the rt_binunif internal form */ BU_GETSTRUCT( bip, rt_binunif_internal ); bip->magic = RT_BINUNIF_INTERNAL_MAGIC; bip->type = minor_type; num_items = (long)(st.st_size / item_length); /* maybe only a partial file read */ if (max_count > 0 && max_count < num_items) { num_items = max_count; } obj_length = num_items * item_length; if (obj_length > __LONG_MAX__) { bu_log("Unable to create binary objects larger than %ld bytes\n", __LONG_MAX__); return -1; } /* just copy the bytes */ bip->count = num_items; bip->u.int8 = (char *)bu_malloc( obj_length, "binary uniform object" ); memcpy(bip->u.int8, bu_fd->buf, obj_length); bu_close_mapped_file( bu_fd ); /* create the rt_internal form */ RT_INIT_DB_INTERNAL( &intern ); intern.idb_major_type = major_type; intern.idb_minor_type = minor_type; intern.idb_ptr = (genptr_t)bip; intern.idb_meth = &rt_functab[ID_BINUNIF]; /* create body portion of external form */ if ( intern.idb_meth->ft_export5( &body, &intern, 1.0, wdbp->dbip, wdbp->wdb_resp, intern.idb_minor_type ) ) { bu_log( "Error while attemptimg to export %s\n", obj_name ); rt_db_free_internal( &intern, wdbp->wdb_resp ); return -1; } /* create entire external form */ db5_export_object3( &bin_ext, DB5HDR_HFLAGS_DLI_APPLICATION_DATA_OBJECT, obj_name, 0, NULL, &body, intern.idb_major_type, intern.idb_minor_type, DB5_ZZZ_UNCOMPRESSED, DB5_ZZZ_UNCOMPRESSED ); rt_db_free_internal( &intern, wdbp->wdb_resp ); bu_free_external( &body ); /* add this object to the directory */ if ( (dp=db_diradd5( wdbp->dbip, obj_name, -1, major_type, minor_type, 0, 0, NULL )) == DIR_NULL ) { bu_log( "Error while attemptimg to add new name (%s) to the database", obj_name ); bu_free_external( &bin_ext ); return -1; } /* and write it to the database */ if ( db_put_external5( &bin_ext, dp, wdbp->dbip ) ) { bu_log( "Error while adding new binary object (%s) to the database", obj_name ); bu_free_external( &bin_ext ); return -1; } bu_free_external( &bin_ext ); return 0; }