GnuCOBOL  2.0
A free COBOL compiler
ischeck.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003 Trevor van Bremen
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 2.1,
7  * or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; see the file COPYING.LIB. If
16  * not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor
17  * Boston, MA 02110-1301 USA
18  */
19 
20 #include "isinternal.h"
21 
22 static char *gpsdatarow; /* Buffer to hold rows read */
23 static char *gpsdatamap[2]; /* Bitmap of 'used' data rows */
24 static char *gpsindexmap[2]; /* Bitmap of 'used' index nodes */
25 static char *cvbnodetmp;
26 static off_t gtlastuseddata; /* Last row USED in data file */
27 static off_t gtdatasize; /* # Rows in data file */
28 static off_t gtindexsize; /* # Nodes in index file */
29 static int girebuilddatafree; /* If set, we need to rebuild data free list */
30 static int girebuildindexfree; /* If set, we need to rebuild index free list */
31 static int girebuildkey[MAXSUBS]; /* For any are SET, we need to rebuild that key */
32 
33 static int
34 ibittestandset (char *psmap, off_t tbit)
35 {
36  tbit--;
37  switch (tbit % 8) {
38  case 0:
39  if (psmap[tbit / 8] & 0x80) {
40  return 1;
41  }
42  psmap[tbit / 8] |= 0x80;
43  break;
44  case 1:
45  if (psmap[tbit / 8] & 0x40) {
46  return 1;
47  }
48  psmap[tbit / 8] |= 0x40;
49  break;
50  case 2:
51  if (psmap[tbit / 8] & 0x20) {
52  return 1;
53  }
54  psmap[tbit / 8] |= 0x20;
55  break;
56  case 3:
57  if (psmap[tbit / 8] & 0x10) {
58  return 1;
59  }
60  psmap[tbit / 8] |= 0x10;
61  break;
62  case 4:
63  if (psmap[tbit / 8] & 0x08) {
64  return 1;
65  }
66  psmap[tbit / 8] |= 0x08;
67  break;
68  case 5:
69  if (psmap[tbit / 8] & 0x04) {
70  return 1;
71  }
72  psmap[tbit / 8] |= 0x04;
73  break;
74  case 6:
75  if (psmap[tbit / 8] & 0x02) {
76  return 1;
77  }
78  psmap[tbit / 8] |= 0x02;
79  break;
80  case 7:
81  if (psmap[tbit / 8] & 0x01) {
82  return 1;
83  }
84  psmap[tbit / 8] |= 0x01;
85  break;
86  }
87  return 0;
88 }
89 
90 static int
91 ibittestandreset (char *psmap, off_t tbit)
92 {
93  tbit--;
94  switch (tbit % 8) {
95  case 0:
96  if (!(psmap[tbit / 8] & 0x80)) {
97  return 1;
98  }
99  psmap[tbit / 8] ^= 0x80;
100  break;
101  case 1:
102  if (!(psmap[tbit / 8] & 0x40)) {
103  return 1;
104  }
105  psmap[tbit / 8] ^= 0x40;
106  break;
107  case 2:
108  if (!(psmap[tbit / 8] & 0x20)) {
109  return 1;
110  }
111  psmap[tbit / 8] ^= 0x20;
112  break;
113  case 3:
114  if (!(psmap[tbit / 8] & 0x10)) {
115  return 1;
116  }
117  psmap[tbit / 8] ^= 0x10;
118  break;
119  case 4:
120  if (!(psmap[tbit / 8] & 0x08)) {
121  return 1;
122  }
123  psmap[tbit / 8] ^= 0x08;
124  break;
125  case 5:
126  if (!(psmap[tbit / 8] & 0x04)) {
127  return 1;
128  }
129  psmap[tbit / 8] ^= 0x04;
130  break;
131  case 6:
132  if (!(psmap[tbit / 8] & 0x02)) {
133  return 1;
134  }
135  psmap[tbit / 8] ^= 0x02;
136  break;
137  case 7:
138  if (!(psmap[tbit / 8] & 0x01)) {
139  return 1;
140  }
141  psmap[tbit / 8] ^= 0x01;
142  break;
143  }
144  return 0;
145 }
146 
147 static int
148 ipreamble (ihandle)
149 {
150  struct DICTINFO *psvbptr;
151  struct stat sstat;
152 
153  psvbptr = psvbfile[ihandle];
154  printf ("Table node size: %d bytes\n", psvbptr->inodesize);
155  girebuilddatafree = 0;
156  girebuildindexfree = 0;
157  gtlastuseddata = 0;
158  gpsdatarow = pvvbmalloc ((size_t)psvbptr->imaxrowlength);
159  if (!gpsdatarow) {
160  printf ("Unable to allocate data row buffer!\n");
161  return -1;
162  }
163  if (fstat (svbfile[psvbptr->idatahandle].ihandle, &sstat)) {
164  printf ("Unable to get data status!\n");
165  return -1;
166  }
167  if (psvbptr->iopenmode & ISVARLEN) {
168  gtdatasize =
169  (off_t) (sstat.st_size + psvbptr->iminrowlength + INTSIZE +
170  QUADSIZE) / (psvbptr->iminrowlength + INTSIZE +
171  QUADSIZE + 1);
172  } else {
173  gtdatasize = (off_t) (sstat.st_size +
174  psvbptr->iminrowlength) / (psvbptr->iminrowlength + 1);
175  }
176  gpsdatamap[0] = pvvbmalloc ((size_t)((gtdatasize + 7) / 8));
177  if (gpsdatamap[0] == NULL) {
178  printf ("Unable to allocate node map!\n");
179  return -1;
180  }
181  gpsdatamap[1] = pvvbmalloc ((size_t)((gtdatasize + 7) / 8));
182  if (gpsdatamap[1] == NULL) {
183  printf ("Unable to allocate node map!\n");
184  return -1;
185  }
186 
187  if (fstat (svbfile[psvbptr->iindexhandle].ihandle, &sstat)) {
188  printf ("Unable to get index status!\n");
189  return -1;
190  }
191  gtindexsize = (off_t)(sstat.st_size + psvbptr->inodesize -
192  1) / psvbptr->inodesize;
193  gpsindexmap[0] = pvvbmalloc ((size_t)((gtindexsize + 7) / 8));
194  if (gpsindexmap[0] == NULL) {
195  printf ("Unable to allocate node map!\n");
196  return -1;
197  }
198  gpsindexmap[1] = pvvbmalloc ((size_t)((gtindexsize + 7) / 8));
199  if (gpsindexmap[1] == NULL) {
200  printf ("Unable to allocate node map!\n");
201  return -1;
202  }
204  if (cvbnodetmp == NULL) {
205  printf ("Unable to allocate buffer!\n");
206  return -1;
207  }
208  switch (gtindexsize % 8) {
209  case 1:
210  *(gpsindexmap[0] + ((gtindexsize - 1) / 8)) = 0x7f;
211  break;
212  case 2:
213  *(gpsindexmap[0] + ((gtindexsize - 1) / 8)) = 0x3f;
214  break;
215  case 3:
216  *(gpsindexmap[0] + ((gtindexsize - 1) / 8)) = 0x1f;
217  break;
218  case 4:
219  *(gpsindexmap[0] + ((gtindexsize - 1) / 8)) = 0x0f;
220  break;
221  case 5:
222  *(gpsindexmap[0] + ((gtindexsize - 1) / 8)) = 0x07;
223  break;
224  case 6:
225  *(gpsindexmap[0] + ((gtindexsize - 1) / 8)) = 0x03;
226  break;
227  case 7:
228  *(gpsindexmap[0] + ((gtindexsize - 1) / 8)) = 0x01;
229  break;
230  }
231  ibittestandset (gpsindexmap[0], 1); /* Dictionary node! */
232 
233  return 0;
234 }
235 
236 static int
237 idatacheck (int ihandle)
238 {
239  off_t tloop;
240  int ideleted;
241 
242  /* Mark the entries used by *LIVE* data rows */
243  for (tloop = 1; tloop <= gtdatasize; tloop++) {
244  if (ivbdataread (ihandle, gpsdatarow, &ideleted, tloop)) {
245  continue; /* A data file read error! Leave it as free! */
246  }
247  if (!ideleted) {
248  gtlastuseddata = tloop;
249  /* MAYBE we could add index verification here */
250  /* That'd be in SUPER THOROUGH mode only! */
251  ibittestandset (gpsdatamap[0], tloop);
252  }
253  /* BUG - We also need to set gpsindexmap [1] for those node(s) */
254  /* BUG - that were at least partially consumed by VARLEN data! */
255  }
256  return 0;
257 }
258 
259 static int
260 idatafreecheck (int ihandle)
261 {
262  struct DICTINFO *psvbptr;
263  off_t tfreehead, tfreerow, tholdhead, tloop;
264  int iloop, iresult;
265 
266  psvbptr = psvbfile[ihandle];
267  girebuilddatafree = 1;
268  /* Mark the entries used by the free data list */
269  tholdhead = inl_ldquad (psvbptr->sdictnode.cdatafree);
270  inl_stquad (0, psvbptr->sdictnode.cdatafree);
271  tfreehead = tholdhead;
272  memcpy (gpsdatamap[1], gpsdatamap[0], (int)((gtdatasize + 7) / 8));
273  memcpy (gpsindexmap[1], gpsindexmap[0], (int)((gtindexsize + 7) / 8));
274  while (tfreehead) {
275  /* If the freelist node is > index.EOF, it must be bullshit! */
276  if (tfreehead > gtindexsize) {
277  return 0;
278  }
279  iresult = ivbblockread (ihandle, 1, tfreehead, cvbnodetmp);
280  if (iresult) {
281  return 0;
282  }
283  /*
284  * If the node has the WRONG signature, then we've got
285  * a corrupt data free list. We'll rebuild it later!
286  */
287 /* C-ISAM is not 100% C-ISAM compatible */
288 #if ISAMMODE == 1
289  if (cvbnodetmp[psvbptr->inodesize - 2] != 0x7f) {
290  return 0;
291  }
292 #endif
293  if (cvbnodetmp[psvbptr->inodesize - 3] != -1) {
294  return 0;
295  }
296  if (inl_ldint (cvbnodetmp) > (psvbptr->inodesize - 3)) {
297  return 0;
298  }
299  /*
300  * If the node is already 'used' then we have a corrupt
301  * data free list (circular reference).
302  * We'll rebuild the free list later
303  */
304  if (ibittestandset (gpsindexmap[1], tfreehead)) {
305  return 0;
306  }
307  for (iloop = INTSIZE + QUADSIZE; iloop < inl_ldint (cvbnodetmp); iloop += QUADSIZE) {
308  tfreerow = inl_ldquad (cvbnodetmp + iloop);
309  /*
310  * If the row is NOT deleted, then the free
311  * list is screwed so we ignore it and rebuild it
312  * later.
313  */
314  if (ibittestandset (gpsdatamap[1], tfreerow)) {
315  return 0;
316  }
317  }
318  tfreehead = inl_ldquad (cvbnodetmp + INTSIZE);
319  }
320  /* Set the few bits between the last row used and EOF to 'used' */
321  for (tloop = gtlastuseddata + 1; tloop <= ((gtdatasize + 7) / 8) * 8; tloop++) {
322  ibittestandset (gpsdatamap[1], tloop);
323  }
324  for (tloop = 0; tloop < (gtdatasize + 7) / 8; tloop++) {
325  if (gpsdatamap[1][tloop] != -1) {
326  return 0;
327  }
328  }
329  /* Seems the data file is 'intact' so we'll keep the allocation lists! */
330  memcpy (gpsdatamap[0], gpsdatamap[1], (int)((gtdatasize + 7) / 8));
331  memcpy (gpsindexmap[0], gpsindexmap[1], (int)((gtindexsize + 7) / 8));
332  inl_stquad (tholdhead, psvbptr->sdictnode.cdatafree);
333  girebuilddatafree = 0;
334 
335  return 0;
336 }
337 
338 static int
339 iindexfreecheck (int ihandle)
340 {
341  struct DICTINFO *psvbptr;
342  off_t tfreehead, tfreenode, tholdhead;
343  int iloop, iresult;
344 
345  psvbptr = psvbfile[ihandle];
346  /* Mark the entries used by the free data list */
347  girebuildindexfree = 1;
348  tfreehead = inl_ldquad (psvbptr->sdictnode.cnodefree);
349  tholdhead = tfreehead;
350  inl_stquad (0, psvbptr->sdictnode.cnodefree);
351  memcpy (gpsindexmap[1], gpsindexmap[0], (int)((gtindexsize + 7) / 8));
352  while (tfreehead) {
353  /* If the freelist node is > index.EOF, it must be bullshit! */
354  if (tfreehead > inl_ldquad (psvbptr->sdictnode.cnodecount)) {
355  return 0;
356  }
357  if (tfreehead > gtindexsize) {
358  return 0;
359  }
360  iresult = ivbblockread (ihandle, 1, tfreehead, cvbnodetmp);
361  if (iresult) {
362  return 0;
363  }
364  /*
365  * If the node has the WRONG signature, then we've got
366  * a corrupt data free list. We'll rebuild it later!
367  */
368 /* C-ISAM is not 100% C-ISAM compatible */
369 #if ISAMMODE == 1
370  if (cvbnodetmp[psvbptr->inodesize - 2] != 0x7f) {
371  return 0;
372  }
373 #endif
374  if (cvbnodetmp[psvbptr->inodesize - 3] != -2) {
375  return 0;
376  }
377  if (inl_ldint (cvbnodetmp) > (psvbptr->inodesize - 3)) {
378  return 0;
379  }
380  /*
381  * If the node is already 'used' then we have a corrupt
382  * index free list (circular reference).
383  * We'll rebuild the free list later
384  */
385  if (ibittestandset (gpsindexmap[1], tfreehead)) {
386  return 0;
387  }
388  for (iloop = INTSIZE + QUADSIZE; iloop < inl_ldint (cvbnodetmp); iloop += QUADSIZE) {
389  tfreenode = inl_ldquad (cvbnodetmp + iloop);
390  /*
391  * If the row is NOT deleted, then the free
392  * list is screwed so we ignore it and rebuild it
393  * later.
394  */
395  if (ibittestandset (gpsindexmap[1], tfreenode)) {
396  return 0;
397  }
398  }
399  tfreehead = inl_ldquad (cvbnodetmp + INTSIZE);
400  }
401  /* Seems the index free list is 'intact' so we'll keep the allocation lists! */
402  memcpy (gpsindexmap[0], gpsindexmap[1], (int)((gtindexsize + 7) / 8));
403  inl_stquad (tholdhead, psvbptr->sdictnode.cnodefree);
404  girebuildindexfree = 0;
405 
406  return 0;
407 }
408 
409 static int
410 icheckkeydesc (int ihandle)
411 {
412  struct DICTINFO *psvbptr;
413  off_t tnode;
414 
415  psvbptr = psvbfile[ihandle];
416  tnode = inl_ldquad (psvbptr->sdictnode.cnodekeydesc);
417  while (tnode) {
418  if (tnode > gtindexsize) {
419  return 1;
420  }
421  if (ibittestandset (gpsindexmap[0], tnode)) {
422  return 1;
423  }
424  if (ivbblockread (ihandle, 1, tnode, cvbnodetmp)) {
425  return 1;
426  }
427  if (cvbnodetmp[psvbptr->inodesize - 3] != -1) {
428  return 1;
429  }
430  if (cvbnodetmp[psvbptr->inodesize - 2] != 0x7e) {
431  return 1;
432  }
433  if (cvbnodetmp[psvbptr->inodesize - 1] != 0) {
434  return 1;
435  }
436  tnode = inl_ldquad (cvbnodetmp + INTSIZE);
437  }
438  return 0;
439 }
440 
441 static int
442 ichecktree (int ihandle, int ikey, off_t tnode, int ilevel)
443 {
444  int iloop;
445  struct VBTREE stree;
446 
447  memset (&stree, 0, sizeof (stree));
448  if (tnode > gtindexsize) {
449  return 1;
450  }
451  if (ibittestandset (gpsindexmap[1], tnode)) {
452  return 1;
453  }
454  stree.ttransnumber = -1;
455  if (ivbnodeload (ihandle, ikey, &stree, tnode, ilevel)) {
456  return 1;
457  }
458  for (iloop = 0; iloop < stree.ikeysinnode; iloop++) {
459  if (stree.pskeylist[iloop]->iisdummy) {
460  continue;
461  }
462  if (iloop > 0
463  && ivbkeycompare (ihandle, ikey, 0, stree.pskeylist[iloop - 1]->ckey,
464  stree.pskeylist[iloop]->ckey) > 0) {
465  printf ("Index is out of order!\n");
466  vvbkeyallfree (ihandle, ikey, &stree);
467  return 1;
468  }
469  if (iloop > 0
470  && ivbkeycompare (ihandle, ikey, 0, stree.pskeylist[iloop - 1]->ckey,
471  stree.pskeylist[iloop]->ckey) == 0
472  && stree.pskeylist[iloop - 1]->tdupnumber >=
473  stree.pskeylist[iloop]->tdupnumber) {
474  printf ("Index is out of order!\n");
475  vvbkeyallfree (ihandle, ikey, &stree);
476  return 1;
477  }
478  if (stree.ilevel) {
479  if (ichecktree (ihandle, ikey, stree.pskeylist[iloop]->trownode,
480  stree.ilevel)) {
481  vvbkeyallfree (ihandle, ikey, &stree);
482  return 1;
483  }
484  } else {
485  if (ibittestandreset (gpsdatamap[1], stree.pskeylist[iloop]->trownode)) {
486  vvbkeyallfree (ihandle, ikey, &stree);
487  printf ("Bad data row pointer!\n");
488  return 1;
489  }
490  }
491  }
492  vvbkeyallfree (ihandle, ikey, &stree);
493  return 0;
494 }
495 
496 static int
497 icheckkey (int ihandle, int ikey)
498 {
499  struct DICTINFO *psvbptr;
500  off_t tloop;
501 
502  psvbptr = psvbfile[ihandle];
503  memcpy (gpsdatamap[1], gpsdatamap[0], (int)((gtdatasize + 7) / 8));
504  memcpy (gpsindexmap[1], gpsindexmap[0], (int)((gtindexsize + 7) / 8));
505  if (ivbblockread (ihandle, 1, psvbptr->pskeydesc[ikey]->k_rootnode, cvbnodetmp)) {
506  return 1;
507  }
508  if (ichecktree (ihandle, ikey, psvbptr->pskeydesc[ikey]->k_rootnode,
509  cvbnodetmp[psvbptr->inodesize - 2] + 1)) {
510  return 1;
511  }
512  for (tloop = 0; tloop < (gtdatasize + 7) / 8; tloop++) {
513  if (gpsdatamap[1][tloop]) {
514  return 1;
515  }
516  }
517  memcpy (gpsindexmap[0], gpsindexmap[1], (int)((gtindexsize + 7) / 8));
518  return 0;
519 }
520 
521 static int
522 iindexcheck (int ihandle)
523 {
524  struct DICTINFO *psvbptr;
525  int ikey, iloop, ipart;
526 
527  for (iloop = 0; iloop < MAXSUBS; iloop++) {
528  girebuildkey[iloop] = 0;
529  }
530  /* If the keydesc node(s) are bad, we QUIT this table altogether */
531  if (icheckkeydesc (ihandle)) {
532  printf ("Corrupted Key Descriptor node(s)! Can't continue!\n");
533  return -1;
534  }
535  psvbptr = psvbfile[ihandle];
536  for (ikey = 0; ikey < psvbptr->inkeys; ikey++) {
537  printf ("Index %d: ", ikey + 1);
538  printf ("%s ",
539  psvbptr->pskeydesc[ikey]->
540  k_flags & ISDUPS ? "ISDUPS" : "ISNODUPS");
541  printf ("%s",
542  psvbptr->pskeydesc[ikey]->
543  k_flags & DCOMPRESS ? "DCOMPRESS " : "");
544  printf ("%s",
545  psvbptr->pskeydesc[ikey]->
546  k_flags & LCOMPRESS ? "LCOMPRESS " : "");
547  printf ("%s\n",
548  psvbptr->pskeydesc[ikey]->
549  k_flags & TCOMPRESS ? "TCOMPRESS" : "");
550  for (ipart = 0; ipart < psvbptr->pskeydesc[ikey]->k_nparts; ipart++) {
551  printf (" Part %d: ", ipart + 1);
552  printf ("%d,",
553  psvbptr->pskeydesc[ikey]->k_part[ipart].kp_start);
554  printf ("%d,",
555  psvbptr->pskeydesc[ikey]->k_part[ipart].kp_leng);
556  switch (psvbptr->pskeydesc[ikey]->k_part[ipart].
557  kp_type & ~ISDESC) {
558  case CHARTYPE:
559  printf ("CHARTYPE");
560  break;
561  case INTTYPE:
562  printf ("INTTYPE");
563  break;
564  case LONGTYPE:
565  printf ("LONGTYPE");
566  break;
567  case DOUBLETYPE:
568  printf ("DOUBLETYPE");
569  break;
570  case FLOATTYPE:
571  printf ("FLOATTYPE");
572  break;
573  case QUADTYPE:
574  printf ("QUADTYPE");
575  break;
576  default:
577  printf ("UNKNOWN TYPE");
578  break;
579  }
580  if (psvbptr->pskeydesc[ikey]->k_part[ipart].kp_type & ISDESC) {
581  printf (" ISDESC\n");
582  } else {
583  printf ("\n");
584  }
585  }
586  /* If the index is screwed, write out an EMPTY root node and */
587  /* flag the index for a complete reconstruction later on */
588  if (icheckkey (ihandle, ikey)) {
589  memset (cvbnodetmp, 0, VB_NODE_MAX);
590  inl_stint (2, cvbnodetmp);
591  ivbblockwrite (ihandle, 1,
592  psvbptr->pskeydesc[ikey]->k_rootnode,
593  cvbnodetmp);
595  psvbptr->pskeydesc[ikey]->k_rootnode);
596  vvbtreeallfree (ihandle, ikey, psvbptr->pstree[ikey]);
597  psvbptr->pstree[ikey] = NULL;
598  girebuildkey[ikey] = 1;
599  }
600  }
601  return 0;
602 }
603 
604 static void
605 vrebuildindexfree (int ihandle)
606 {
607  struct DICTINFO *psvbptr;
608  off_t tloop;
609 
610  psvbptr = psvbfile[ihandle];
611  printf ("Rebuilding index free list\n");
612  if (gtindexsize > inl_ldquad (psvbptr->sdictnode.cnodecount)) {
614  }
615  for (tloop = 1; tloop <= gtindexsize; tloop++) {
616  if (ibittestandset (gpsindexmap[0], tloop)) {
617  continue;
618  }
619  iserrno = ivbnodefree (ihandle, tloop);
620  if (iserrno) {
621  printf ("Error %d rebuilding index free list!\n", iserrno);
622  return;
623  }
624  }
625  return;
626 }
627 
628 static void
629 vrebuilddatafree (int ihandle)
630 {
631  off_t tloop;
632 
633  printf ("Rebuilding data free list\n");
634  for (tloop = 1; tloop <= gtlastuseddata; tloop++) {
635  if (ibittestandset (gpsdatamap[0], tloop)) {
636  continue;
637  }
638  iserrno = ivbdatafree (ihandle, tloop + 1);
639  if (iserrno) {
640  printf ("Error %d rebuilding data free list!\n", iserrno);
641  return;
642  }
643  }
644  return;
645 }
646 
647 static void
648 vaddkeyforrow (int ihandle, int ikey, off_t trownumber)
649 {
650  struct DICTINFO *psvbptr;
651  struct VBKEY *psKey;
652  off_t tdupnumber;
653  int iresult;
654  unsigned char ckeyvalue[VB_MAX_KEYLEN];
655 
656  psvbptr = psvbfile[ihandle];
657  if (psvbptr->pskeydesc[ikey]->k_nparts == 0) {
658  return;
659  }
660  vvbmakekey (psvbptr->pskeydesc[ikey], gpsdatarow, ckeyvalue);
661  iresult = ivbkeysearch (ihandle, ISGREAT, ikey, 0, ckeyvalue, 0);
662  tdupnumber = 0;
663  if (iresult >= 0 && !ivbkeyload (ihandle, ikey, ISPREV, 0, &psKey)
664  && !memcmp (psKey->ckey, ckeyvalue,
665  psvbptr->pskeydesc[ikey]->k_len)) {
666  iserrno = EDUPL;
667  if (psvbptr->pskeydesc[ikey]->k_flags & ISDUPS) {
668  tdupnumber = psKey->tdupnumber + 1;
669  } else {
670  printf ("Error! Duplicate entry in key %d\n", ikey);
671  return;
672  }
673  iresult = ivbkeysearch (ihandle, ISGTEQ, ikey, 0, ckeyvalue, tdupnumber);
674  }
675 
676  ivbkeyinsert (ihandle, NULL, ikey, ckeyvalue, trownumber, tdupnumber,
677  NULL);
678  return;
679 }
680 
681 static void
682 vrebuildkeys (int ihandle)
683 {
684  off_t trownumber;
685  int ideleted, ikey;
686 
687  /* Mark the entries used by *LIVE* data rows */
688  for (trownumber = 1; trownumber <= gtdatasize; trownumber++) {
689  if (ivbdataread (ihandle, gpsdatarow, &ideleted, trownumber)) {
690  continue; /* A data file read error! Leave it as free! */
691  }
692  if (!ideleted) {
693  for (ikey = 0; ikey < MAXSUBS; ikey++) {
694  if (girebuildkey[ikey]) {
695  vaddkeyforrow (ihandle, ikey, trownumber);
696  }
697  }
698  }
699  }
700  return;
701 }
702 
703 static void
704 ipostamble (int ihandle)
705 {
706  off_t tloop;
707  int ikeycounttorebuild = 0, iloop;
708 
709  for (tloop = 0; tloop < (gtindexsize + 7) / 8; tloop++) {
710  if (gpsindexmap[0][tloop] != -1) {
711  girebuildindexfree = 1;
712  }
713  }
714 
715  if (girebuildindexfree) {
716  vrebuildindexfree (ihandle);
717  }
718  if (girebuilddatafree) {
719  vrebuilddatafree (ihandle);
720  }
721  for (iloop = 0; iloop < MAXSUBS; iloop++)
722  if (girebuildkey[iloop]) {
723  if (!ikeycounttorebuild) {
724  printf ("Rebuilding keys: ");
725  }
726  printf ("%d ", iloop + 1);
727  ikeycounttorebuild++;
728  }
729  if (ikeycounttorebuild) {
730  vrebuildkeys (ihandle);
731  printf ("\n");
732  }
733  inl_stquad (gtlastuseddata, psvbfile[ihandle]->sdictnode.cdatacount);
734  /* Other stuff here */
737 
738  vvbfree (gpsdatamap[0]);
739  vvbfree (gpsdatamap[1]);
740  vvbfree (gpsindexmap[0]);
741  vvbfree (gpsindexmap[1]);
742 }
743 
744 static void
745 vprocess (int ihandle)
746 {
747  if (ipreamble (ihandle)) {
748  return;
749  }
750  if (idatacheck (ihandle)) {
751  return;
752  }
753  if (iindexcheck (ihandle)) {
754  return;
755  }
756  if (idatafreecheck (ihandle)) {
757  return;
758  }
759  if (iindexfreecheck (ihandle)) {
760  return;
761  }
762  ipostamble (ihandle);
763 }
764 
765 int
766 ischeck (const char *pcfile)
767 {
768  int ihandle;
769 
770  ihandle = isopen (pcfile, ISINOUT + ISEXCLLOCK);
771  if (ihandle < 0 && iserrno == EROWSIZE) {
772  printf ("Recovery of ISVARLEN files not possible\n");
773  printf ("File %s contains variable length rows!\n", pcfile);
774  isfullclose (ihandle);
775  return -1;
776  }
777  /* if (ihandle < 0 && iserrno == EROWSIZE) */
778  /* ihandle = isopen (ppcargv [iloop], ISINOUT+ISVARLEN+ISEXCLLOCK); */
779  if (ihandle < 0) {
780  printf ("Error %d opening %s\n", iserrno, pcfile);
781  return -1;
782  }
783 
784  printf ("Processing: %s\n", pcfile);
785  ivbenter (ihandle, 1, 0);
786  vprocess (ihandle);
787  psvbfile[ihandle]->iisdictlocked |= 0x06;
788  ivbexit (ihandle);
789 
790  isfullclose (ihandle);
791  return 0;
792 }
static int ipreamble(ihandle)
Definition: ischeck.c:148
int inkeys
Definition: isinternal.h:400
struct VBFILE svbfile[128 *3]
Definition: vblowlevel.c:24
static int inl_ldint(void *pclocation)
Definition: isinternal.h:170
static int ichecktree(int ihandle, int ikey, off_t tnode, int ilevel)
Definition: ischeck.c:442
int isfullclose(const int ihandle)
Definition: isopen.c:209
int ivbdatafree(const int ihandle, const off_t trownumber)
Definition: vbindexio.c:150
static off_t gtindexsize
Definition: ischeck.c:28
int ischeck(const char *pcfile)
Definition: ischeck.c:766
static off_t gtlastuseddata
Definition: ischeck.c:26
static char * gpsindexmap[2]
Definition: ischeck.c:24
int ivbkeysearch(const int ihandle, const int imode, const int ikeynumber, int ilength, unsigned char *pckeyvalue, off_t tdupnumber)
Definition: vbkeysio.c:372
int ivbblockread(const int ihandle, const int iisindex, const off_t tblocknumber, char *cbuffer)
Definition: vblowlevel.c:137
unsigned char ckey[1]
Definition: isinternal.h:334
static char * gpsdatamap[2]
Definition: ischeck.c:23
int ivbkeycompare(const int ihandle, const int ikeynumber, int ilength, unsigned char *pckey1, unsigned char *pckey2)
Definition: vbkeysio.c:230
int ihandle
Definition: isinternal.h:456
static off_t gtdatasize
Definition: ischeck.c:27
static int girebuilddatafree
Definition: ischeck.c:29
int ivbenter(const int ihandle, const unsigned int imodifying, const unsigned int ispecial)
Definition: vblocking.c:178
unsigned char iisdummy
Definition: isinternal.h:332
int ivbkeyload(const int ihandle, const int ikeynumber, const int imode, const int isetcurr, struct VBKEY **ppskey)
Definition: vbkeysio.c:503
char cnodekeydesc[8]
Definition: isinternal.h:370
void vvbfree(void *mptr)
Definition: vbmemio.c:59
int ivbnodeload(const int ihandle, const int ikeynumber, struct VBTREE *pstree, const off_t tnodenumber, const int iprevlvl)
Definition: vbnodememio.c:285
static int iindexfreecheck(int ihandle)
Definition: ischeck.c:339
#define VB_NODE_MAX
Definition: isinternal.h:288
static void vrebuilddatafree(int ihandle)
Definition: ischeck.c:629
static void inl_stint(int ivalue, void *pclocation)
Definition: isinternal.h:190
unsigned char iisdictlocked
Definition: isinternal.h:427
static void ipostamble(int ihandle)
Definition: ischeck.c:704
int isopen(const char *pcfilename, int imode)
Definition: isopen.c:270
EC ARGUMENT EC EC BOUND EC BOUND EC BOUND EC BOUND TABLE EC DATA EC DATA EC DATA PTR NULL
Definition: exception.def:95
off_t ttransnumber
Definition: isinternal.h:344
void vvbkeyallfree(const int ihandle, const int ikeynumber, struct VBTREE *pstree)
Definition: vbmemio.c:143
static int ibittestandset(char *psmap, off_t tbit)
Definition: ischeck.c:34
static int girebuildindexfree
Definition: ischeck.c:30
struct DICTNODE sdictnode
Definition: isinternal.h:444
off_t trownode
Definition: isinternal.h:328
char cnodecount[8]
Definition: isinternal.h:376
static int idatacheck(int ihandle)
Definition: ischeck.c:237
static int idatafreecheck(int ihandle)
Definition: ischeck.c:260
static void vrebuildkeys(int ihandle)
Definition: ischeck.c:682
static int icheckkey(int ihandle, int ikey)
Definition: ischeck.c:497
void vvbmakekey(const struct keydesc *pskeydesc, char *pcrow_buffer, unsigned char *pckeyvalue)
Definition: vbkeysio.c:212
int ivbdataread(const int ihandle, char *pcbuffer, int *pideletedrow, const off_t trownumber)
Definition: vbdataio.c:493
void * pvvbmalloc(const size_t size)
Definition: vbmemio.c:45
unsigned int ikeysinnode
Definition: isinternal.h:346
struct DICTINFO * psvbfile[128+1]
Definition: vblowlevel.c:23
#define QUADSIZE
Definition: isinternal.h:108
char cnodefree[8]
Definition: isinternal.h:374
off_t tdupnumber
Definition: isinternal.h:329
int ivbnodefree(const int ihandle, const off_t tnodenumber)
Definition: vbindexio.c:67
int ivbkeyinsert(const int ihandle, struct VBTREE *pstree, const int ikeynumber, unsigned char *pckeyvalue, off_t trownode, off_t tdupnumber, struct VBTREE *pschild)
Definition: vbkeysio.c:727
char cdatafree[8]
Definition: isinternal.h:373
int ivbexit(const int ihandle)
Definition: vblocking.c:290
int ivbblockwrite(const int ihandle, const int iisindex, const off_t tblocknumber, const char *cbuffer)
Definition: vblowlevel.c:167
void vvbtreeallfree(const int ihandle, const int ikeynumber, struct VBTREE *pstree)
Definition: vbmemio.c:105
static int iindexcheck(int ihandle)
Definition: ischeck.c:522
struct VBKEY * pskeylist[512]
Definition: isinternal.h:352
static void inl_stquad(off_t tvalue, void *pclocation)
Definition: isinternal.h:260
static int girebuildkey[32]
Definition: ischeck.c:31
unsigned int ilevel
Definition: isinternal.h:345
static int icheckkeydesc(int ihandle)
Definition: ischeck.c:410
struct VBTREE * pstree[32]
Definition: isinternal.h:446
static void vrebuildindexfree(int ihandle)
Definition: ischeck.c:605
static char * cvbnodetmp
Definition: ischeck.c:25
struct keydesc * pskeydesc[32]
Definition: isinternal.h:445
static int ibittestandreset(char *psmap, off_t tbit)
Definition: ischeck.c:91
static off_t inl_ldquad(void *pclocation)
Definition: isinternal.h:238
static void vprocess(int ihandle)
Definition: ischeck.c:745
off_t trownumber
Definition: isinternal.h:416
static void vaddkeyforrow(int ihandle, int ikey, off_t trownumber)
Definition: ischeck.c:648
int iserrno
Definition: vbmemio.c:27
int inodesize
Definition: isinternal.h:402
#define MAXSUBS
Definition: isinternal.h:119
static char * gpsdatarow
Definition: ischeck.c:22