BRL-CAD
db_corrupt.c
Go to the documentation of this file.
1 /* D B _ C O R R U P T . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2011-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @file librt/db_corrupt.c
21  *
22  * Routines to detect whether a geometry database file seems to be
23  * corrupt or invalid due to flipped endian encoding.
24  *
25  */
26 
27 #include "common.h"
28 
29 
30 #include "vmath.h"
31 #include "raytrace.h"
32 #include "db.h"
33 
34 #include "./librt_private.h"
35 
36 
37 struct counter {
38  size_t found;
39  size_t fixed;
40 };
41 
42 
43 static int
44 db_corrupt_handler(struct db_i *dbip, const char *name, off_t offset, size_t size, int UNUSED(type), void *data)
45 {
46  struct counter *cnt = (struct counter *)data;
47  struct bu_external ext;
48  union record *rp = NULL;
49  mat_t diskmat = MAT_INIT_ZERO;
50  size_t nodecount;
51  size_t j;
52  int ret;
53 
54  RT_CK_DBI(dbip);
55 
56  /* get into position */
57  ret = bu_fseek(dbip->dbi_fp, offset, 0);
58  if (ret) {
59  bu_log("Database seek failure, unable to seek [%s]\n", name);
60  return 0;
61  }
62 
63  /* set up our buffer */
64  BU_EXTERNAL_INIT(&ext);
65  ext.ext_nbytes = size * sizeof(union record);
66  ext.ext_buf = (uint8_t *)bu_calloc(ext.ext_nbytes, 1, "db_corrupt");
67 
68  /* read into the buffer */
69  j = (size_t)fread(ext.ext_buf, 1, ext.ext_nbytes, dbip->dbi_fp);
70  if (j != ext.ext_nbytes) {
71  bu_log("Database read failure, unable to read [%s]\n", name);
72  bu_free_external(&ext);
73  return 0;
74  }
75 
76  rp = (union record *)ext.ext_buf;
77  if (rp[0].u_id != ID_COMB) {
78  /* skip non-combination */
79  bu_free_external(&ext);
80  return 0;
81  }
82 
83  /* iterate over combination members, looking for bad matrices */
84  nodecount = ext.ext_nbytes/sizeof(union record) - 1;
85  for (j = 0; j < nodecount; j++) {
86 
87  /* try without flipping */
88  flip_mat_dbmat(diskmat, rp[j+1].M.m_mat, 0);
89  if ((bn_mat_ck(name, diskmat) < 0)
90  || fabs(diskmat[0]) > 1 || fabs(diskmat[1]) > 1 || fabs(diskmat[2]) > 1
91  || fabs(diskmat[4]) > 1 || fabs(diskmat[5]) > 1 || fabs(diskmat[6]) > 1
92  || fabs(diskmat[8]) > 1 || fabs(diskmat[9]) > 1 || fabs(diskmat[10]) > 1) {
93  /* corruption detected */
94  cnt->found++;
95 
96  /* invalid, so try flipped */
97  flip_mat_dbmat(diskmat, rp[j+1].M.m_mat, 1);
98  if ((bn_mat_ck(name, diskmat) < 0)
99  || fabs(diskmat[0]) > 1 || fabs(diskmat[1]) > 1 || fabs(diskmat[2]) > 1
100  || fabs(diskmat[4]) > 1 || fabs(diskmat[5]) > 1 || fabs(diskmat[6]) > 1
101  || fabs(diskmat[8]) > 1 || fabs(diskmat[9]) > 1 || fabs(diskmat[10]) > 1)
102  {
103  bu_log("WARNING: Invalid matrix detected within %s\n", name);
104  } else {
105  /* flipping helped */
106  cnt->fixed++;
107  }
108 
109  break;
110  }
111  }
112 
113  bu_free_external(&ext);
114 
115  return 0;
116 }
117 
118 
119 int
120 rt_db_flip_endian(struct db_i *dbip)
121 {
122  struct counter cnt = {0, 0};
123  char *v4flip;
124 
125  RT_CK_DBI(dbip);
126 
127  /* does not apply to v5 geometry database */
128  if (db_version(dbip) > 4)
129  return 0;
130 
131  /* provide the user some means to override this automatic behavior */
132  v4flip = getenv("LIBRT_V4FLIP");
133  if (v4flip)
134  return bu_str_true(v4flip);
135 
136  /* iterate over all database objects looking for signs of
137  * corruption keeping a tally of whether flipping the record fixed
138  * the problem.
139  */
140  db_scan(dbip, db_corrupt_handler, 0, &cnt);
141 
142  /* it has to help more than it hurts */
143  if (cnt.found > 0 && (double)cnt.fixed > ((double)cnt.found / 2.0)) {
144  if (cnt.fixed != cnt.found)
145  bu_log("%zu of %zu objects were NOT fixed by flipping endian interpretation. Manual inspection and repair required.\n", cnt.found - cnt.fixed, cnt.found);
146  return 1;
147  }
148 
149  return 0;
150 }
151 
152 
153 /*
154  * Local Variables:
155  * tab-width: 8
156  * mode: C
157  * indent-tabs-mode: t
158  * c-file-style: "stroustrup"
159  * End:
160  * ex: shiftwidth=4 tabstop=8
161  */
Definition: raytrace.h:800
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
Definition: clone.c:90
int bu_fseek(FILE *stream, off_t offset, int origin)
Definition: file.c:330
size_t fixed
Definition: db_corrupt.c:39
int db_version(struct db_i *dbip)
Definition: db5_scan.c:414
void bu_free_external(struct bu_external *ep)
Header file for the BRL-CAD common definitions.
void flip_mat_dbmat(fastf_t *ff, const dbfloat_t *dbp, int flip)
Definition: db_flip.c:107
if(share_geom)
Definition: nmg_mod.c:3829
COMPLEX data[64]
Definition: fftest.c:34
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
int rt_db_flip_endian(struct db_i *dbip)
Definition: db_corrupt.c:120
uint8_t * ext_buf
Definition: parse.h:216
#define UNUSED(parameter)
Definition: common.h:239
int bn_mat_ck(const char *title, const mat_t m)
Definition: mat.c:1058
FILE * dbi_fp
PRIVATE: object hash table.
Definition: raytrace.h:815
#define RT_CK_DBI(_p)
Definition: raytrace.h:829
size_t found
Definition: db_corrupt.c:38
#define BU_EXTERNAL_INIT(_p)
Definition: parse.h:229
int db_scan(struct db_i *, int(*handler)(struct db_i *, const char *name, off_t addr, size_t nrec, int flags, void *client_data), int do_old_matter, void *client_data)
int bu_str_true(const char *str)
Definition: booleanize.c:32
size_t ext_nbytes
Definition: parse.h:210
#define M
Definition: msr.c:52