home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / c / cbase.zoo / btree101.zoo / btfix.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-20  |  6.2 KB  |  271 lines

  1. /*    Copyright (c) 1989 Citadel    */
  2. /*       All Rights Reserved        */
  3.  
  4. /* #ident    "@(#)btfix.c    1.4 - 90/06/20" */
  5.  
  6. #include <blkio.h>
  7. #include <errno.h>
  8. /*#include <stddef.h>*/
  9. #include <stdio.h>
  10. /*#include <stdlib.h>*/
  11. /*#include <string.h>*/
  12.  
  13. /* local headers */
  14. #include "btree_.h"
  15.  
  16. #ifndef min
  17. #define min(a,b)    ((a) < (b) ? (a) : (b))
  18. #endif
  19.  
  20. /*man---------------------------------------------------------------------------
  21. NAME
  22.      btfix - fix a corrupt btree file
  23.  
  24. SYNOPSIS
  25.      int btfix(filename, m, keysize, fldc, fldv)
  26.      const char *filename;
  27.      int m;
  28.      size_t keysize;
  29.      int fldc;
  30.      const btfield_t fldv[];
  31.  
  32. DESCRIPTION
  33.      The btfix function reconstructs a corrupt btree.  The parameters
  34.      are the same as for btcreate.  It may be specified that the
  35.      degree of the btree and the key size be read from the header by
  36.      passing a value of zero for m and keysize, respectively.  These
  37.      parameters are provided for cases where the header is corrupt.
  38.  
  39.      btfix will fail if one or more of the following is true:
  40.  
  41.      [EINVAL]       filename is the NULL pointer.
  42.      [EINVAL]       fldc is less than 1.
  43.      [EINVAL]       fldv is the NULL pointer.
  44.      [EINVAL]       fldv contains an invalid field
  45.                     definition.
  46.      [ENOENT]       The named btree file does not exist.
  47.      [BTEEOF]       Incomplete file header.
  48.      [BTEMFILE]     Too many open btrees.  The maximum
  49.                     is defined as BTOPEN_MAX in btree.h.
  50.  
  51. SEE ALSO
  52.      btcreate.
  53.  
  54. DIAGNOSTICS
  55.      Upon successful completion, a value of 0 is returned.  Otherwise,
  56.      a value of -1 is returned, and errno set to indicate the error.
  57.  
  58. NOTES
  59.      It is recommended that a backup copy of the corrupted file be
  60.      made before calling a reconstruction routine such as btfix.
  61.  
  62.      btfix uses a temporary file to reconstruct the btree.  If
  63.      security is important, a call should be added to set the
  64.      permissions of the temporary file (e.g., chmod in UNIX) before
  65.      data is written to it.  This has not been included because such a
  66.      call is not portable.
  67.  
  68. ------------------------------------------------------------------------------*/
  69. int btfix(filename, m, keysize, fldc, fldv)
  70. const char *filename;
  71. int m;
  72. size_t keysize;
  73. int fldc;
  74. const btfield_t fldv[];
  75. {
  76.     int terrno = 0;            /* tmp errno */
  77.     bthdr_t bthdr;            /* btree header */
  78.     char tmpbtname[L_tmpnam + 1];    /* temporary btree file name */
  79.     btree_t *btp = NULL;        /* btree */
  80.     btree_t btree;            /* used for bt_blksize */
  81.     BLKFILE *bp = NULL;        /* block file */
  82.     btnode_t *btnp = NULL;        /* btree node */
  83.     bpos_t bn = 0;            /* block number */
  84.     int k = 0;            /* counter */
  85.     void *buf = NULL;
  86.  
  87.     /* validate arguments */
  88.     if (filename == NULL) {
  89.         errno = EINVAL;
  90.         return -1;
  91.     }
  92.  
  93.     /* open original btree file */
  94.     bp = bopen(filename, "r", sizeof(bthdr_t), (size_t)1, (size_t)0);
  95.     if (bp == NULL) {
  96.         if (errno != ENOENT) BTEPRINT;
  97.         return -1;
  98.     }
  99.     if (lockb(bp, B_RDLCK, (bpos_t)0, (bpos_t)0) == -1) {    /* read lock */
  100.         terrno = errno;
  101.         bclose(bp);
  102.         errno = terrno;
  103.         return -1;
  104.     }
  105.  
  106.     /* read header and set block size */
  107.     if (bgeth(bp, &bthdr) == -1) {
  108.         BTEPRINT;
  109.         if (errno == BEEOF) errno = BTEEOF;
  110.         terrno = errno;
  111.         bclose(bp);
  112.         errno = terrno;
  113.         return -1;
  114.     }
  115.     if (m == 0) {
  116.         m = bthdr.m;
  117.     }
  118.     if (keysize == 0) {
  119.         keysize = bthdr.keysize;
  120.     }
  121.     btree.bthdr.m = m;        /* set block size */
  122.     btree.bthdr.keysize = keysize;
  123.     if (bsetvbuf(bp, NULL, bt_blksize(&btree), (size_t)0) == -1) {
  124.         BTEPRINT;
  125.         terrno = errno;
  126.         bclose(bp);
  127.         errno = terrno;
  128.         return -1;
  129.     }
  130.  
  131.     /* create temporary btree */
  132.     tmpnam(tmpbtname);
  133.     if (btcreate(tmpbtname, m, keysize, fldc, fldv) == -1){
  134.         BTEPRINT;
  135.         terrno = errno;
  136.         bclose(bp);
  137.         errno = terrno;
  138.         return -1;
  139.     }
  140.     /*
  141.     If security is important, insert a call here
  142.     to set the permissions of file tmpbtname.  In UNIX, for
  143.     example,
  144.     #include <sys/types.h>
  145.     #include <sys/stat.h>
  146.     if (chmod(tmpbtname, S_IRUSR | S_IWUSR) == -1) {
  147.         BTEPRINT;
  148.         terrno = errno;
  149.         bclose(bp);
  150.         errno = terrno;
  151.         return -1;
  152.     }
  153.     */
  154.     btp = btopen(tmpbtname, "r+", fldc, fldv);
  155.     if (btp == NULL) {
  156.         BTEPRINT;
  157.         terrno = errno;
  158.         bclose(bp);
  159.         errno = terrno;
  160.         return -1;
  161.     }
  162.  
  163.     /* create in-core btree node */
  164.     btnp = bt_ndalloc(btp);
  165.     if (btnp == NULL) {
  166.         BTEPRINT;
  167.         terrno = errno;
  168.         bclose(bp);
  169.         btclose(btp);
  170.         errno = terrno;
  171.         return -1;
  172.     }
  173.  
  174.     /* create buffer for reading blocks */
  175.     buf = calloc((size_t)1, bt_blksize(&btree));
  176.     if (buf == NULL) {
  177.         BTEPRINT;
  178.         terrno = errno;
  179.         bclose(bp);
  180.         errno = terrno;
  181.         return -1;
  182.     }
  183.  
  184.     /* write lock temporary btree */
  185.     if (btlock(btp, BT_WRLCK) == -1) {
  186.         terrno = errno;
  187.         bclose(bp);
  188.         free(buf);
  189.         btclose(btp);
  190.         bt_ndfree(btnp);
  191.         errno = terrno;
  192.         return -1;
  193.     }
  194.  
  195.     /* main loop */
  196.     for (bn = 1; ; ++bn) {
  197.         if (bgetb(bp, bn, buf) == -1) {
  198.             if (errno == BEEOF) {
  199.                 break;
  200.             }
  201.             BTEPRINT;
  202.             terrno = errno;
  203.             bclose(bp);
  204.             free(buf);
  205.             btclose(btp);
  206.             bt_ndfree(btnp);
  207.             errno = terrno;
  208.             return -1;
  209.         }
  210.         bt_fltocr(btp, btnp, buf);    /* copy to in-memory node */
  211.         if ((btnp->n != 0) && bt_ndleaf(btnp)) {
  212.             for (k = 1; k <= min(btnp->n, bt_ndmax(btp)); ++k) {
  213.                 if (btinsert(btp, bt_kykeyp(btp, btnp, k)) == -1) {
  214.                     if (errno != BTEDUP) {
  215.                         BTEPRINT;
  216.                         terrno = errno;
  217.                         bclose(bp);
  218.                         free(buf);
  219.                         btclose(btp);
  220.                         bt_ndfree(btnp);
  221.                         errno = terrno;
  222.                         return -1;
  223.                     }
  224.                 }
  225.             }
  226.         }
  227.     }
  228.  
  229.     /* free memory */
  230.     free(buf);
  231.     bt_ndfree(btnp);
  232.  
  233.     /* close and remove original btree file */
  234.     if (bclose(bp) == -1) {
  235.         BTEPRINT;
  236.         terrno = errno;
  237.         btclose(btp);
  238.         errno = terrno;
  239.         return -1;
  240.     }
  241.     if (remove(filename) != 0) {
  242.         BTEPRINT;
  243.         terrno = errno;
  244.         btclose(btp);
  245.         errno = terrno;
  246.         return -1;
  247.     }
  248.  
  249.     /* move temporary file to filename */
  250.     if (rename(tmpbtname, filename) != 0) {
  251.         BTEPRINT;
  252.         terrno = errno;
  253.         btclose(btp);
  254.         errno = terrno;
  255.         return -1;
  256.     }
  257.  
  258.     /* close and remove temporary file */
  259.     if (btclose(btp) == -1) {
  260.         BTEPRINT;
  261.         return -1;
  262.     }
  263.     if (remove(tmpbtname) != 0) {
  264.         BTEPRINT;
  265.         return -1;
  266.     }
  267.  
  268.     errno = 0;
  269.     return 0;
  270. }
  271.