home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / CONTRIB / MBASE / MBASE50.TAR / mbase / src / mbconv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-25  |  7.3 KB  |  311 lines

  1. /*
  2.  * METALBASE 5.0
  3.  *
  4.  * Released October 1st, 1992 by Huan-Ti [ richid@owlnet.rice.edu ]
  5.  *                                       [ t-richj@microsoft.com ]
  6.  */
  7.  
  8. #include "mbase.h"
  9. #include "internal.h"  /* Because we do some non-standard record moving */
  10.  
  11. #ifdef LONGARGS
  12.    void   main       (int,        char **);
  13.    mb_err convert    (relation *, relation *);
  14.    void   finalize   (char *,     char *);
  15.    int    renamefile (char *,     char *);
  16. #else
  17.    void   main();
  18.    mb_err convert();
  19.    void   finalize();
  20.    int    renamefile();
  21. #endif
  22.  
  23. relation *old;
  24. relation *new;
  25.  
  26. char    tempname[128];
  27.  
  28. void
  29. main  (argc, argv)
  30. int    argc;
  31. char **argv;
  32. {
  33.    char *str;
  34.    int   done = 0;
  35.  
  36.    for (--argc,++argv; argc; --argc,++argv)
  37.       {
  38.       if (*(str = *argv) == '-')
  39.          {
  40.          fprintf (stderr, "mbconv: option %s unrecognized.%s", 1+str, SNGCR);
  41.          continue;
  42.          }
  43.  
  44.       done = 1;
  45.  
  46.       if ((old = mb_old (str, 0)) == RNULL)
  47.          {
  48.          fprintf (stderr, "mbconv: %s: %s.%s", str, mb_error, SNGCR);
  49.          continue;
  50.          }
  51.  
  52.       if (old->ver == verCURRENT)
  53.          {
  54.          fprintf (stderr, "mbconv: %s is already in 5.0 format.%s", str,SNGCR);
  55.          MB_RemoveRelation (old);
  56.          continue;
  57.          }
  58.  
  59.       if ((new = mb_new ()) == RNULL)
  60.          {
  61.          fprintf (stderr, "mbconv: %s.%s", mb_error, SNGCR);
  62.          mb_die();
  63.          continue;
  64.          }
  65.  
  66.       strcpy (tempname, str);
  67.       if (! strncmp (&tempname[strlen(tempname)-4], ".rel", 4))
  68.          {
  69.          tempname[strlen(tempname)-4] = 0;
  70.          }
  71.       strcat (tempname, ".tmp");
  72.  
  73.       if (convert (new, old) == MB_OKAY)
  74.          {
  75.          finalize (tempname, str);  /* Removes original and renames new */
  76.          }
  77.       else
  78.          {
  79.          fprintf (stderr, "mbconv: %s.%s", mb_error, SNGCR);
  80.          }
  81.  
  82.                    /* BECAUSE WE USED MB_NEW(), FREE IT. DON'T DO THIS */
  83.       free (new);  /* WITH ANY OTHER RELATION!!!  mb_die() won't free  */
  84.                    /* the memory for a relation made with mb_new().    */
  85.  
  86.       MB_RemoveRelation (old);  /* Maybe it's still open, maybe not. */
  87.       }
  88.  
  89.    if (! done)
  90.       {
  91.       fprintf (stderr, "format: mbconv oldrelation [oldrelation...]%s", SNGCR);
  92.       mb_exit (1);
  93.       }
  94.  
  95.    mb_exit (0);
  96. }
  97.  
  98. mb_err
  99. convert  (new,  old)
  100. relation *new, *old;
  101. {
  102.    long    nexts, numrec, arg;
  103.    char    desc[128], temp[5], t2[5];
  104.    char   *ptr;
  105.    int     i, j, n, len;
  106.  
  107.    lseek (old->relcode, 12L +POS_FIELDPTR(old->ver), 0);
  108.    readx (old->relcode, &numrec, 4);
  109.    readx (old->relcode, &nexts,  4);
  110.  
  111. /*
  112.  * First, the fields...
  113.  *
  114.  */
  115.  
  116.    for (i = 0; i < old->num_f; i++)
  117.       {
  118.       arg = 0L;
  119.  
  120.       if (old->type[i] == T_SERIAL)    arg = nexts;
  121.       else
  122.          if (old->type[i] == T_CHAR)   arg = old->siz[i];
  123.  
  124.       if (mb_addfield (new, old->name[i], old->type[i], arg) != MB_OKAY)
  125.          return mb_errno;
  126.       }
  127.  
  128. /*
  129.  * Next, the indices...
  130.  *
  131.  */
  132.  
  133.    for (i = 0; i < old->num_i; i++)
  134.       {
  135.       desc[0] = 0;
  136.       strzcpy (temp, old->idxs[i], 3);
  137.       n = atoi (temp);
  138.  
  139.       for (j = 0; j < n; j++)
  140.          {
  141.          strzcpy (temp, &old->idxs[i][3+ j*3], 3);
  142.          sprintf (t2, "%d", (int)atoi (temp));
  143.  
  144.          if (j != 0)  strcat (desc, ",");
  145.          strcat (desc, t2);
  146.          }
  147.  
  148.       if (mb_addindex (new, old->iname[i], old->itype[i], desc) != MB_OKAY)
  149.          return mb_errno;
  150.       }
  151.  
  152. /*
  153.  * Now create it, and open the resulting file...
  154.  *
  155.  */
  156.  
  157.    if (mb_create (new, tempname, 0) != MB_OKAY)
  158.       {
  159.       unlink (tempname);
  160.       return mb_errno;
  161.       }
  162.  
  163.    if ((new->relcode = openx (tempname, OPENMODE)) <= 0)
  164.       {
  165.       unlink (tempname);
  166.       baderr (MB_NO_READ);
  167.       }
  168.  
  169. /*
  170.  * The number of records is reset to zero inside the new relation, so since
  171.  * we read it from the old relation earlier, write it out where it needs to
  172.  * be (see why I had to include internal.h?).  Oh, and grab a buffer big
  173.  * enough to move an entire record, with indices intact...
  174.  *
  175.  */
  176.  
  177.    lseek (new->relcode, 12L +POS_FIELDPTR(verCURRENT), 0);
  178.    writx (new->relcode, &numrec, 4);
  179.  
  180.    len = (int)(old->rec_len +13L*(old->num_i));
  181.  
  182.    if ((ptr = (char *)malloc (len +1)) == NULL)
  183.       {
  184.       close (new->relcode);
  185.       unlink (tempname);
  186.       baderr (MB_NO_MEMORY);
  187.       }
  188.  
  189. /*
  190.  * Great.  Problem is, the new header is bigger than older versions... so
  191.  * read each record, and write it out at the new place in the new relation.
  192.  * Record numbers are offsets relative to ->recz, so they won't have to change
  193.  * this way.
  194.  *
  195.  * We also have to initialize the top-of-index pointers, which aren't set
  196.  * by mb_create() (obviously).
  197.  *
  198.  */
  199.  
  200.    lseek (old->relcode, 24+ POS_FIELDPTR(old->ver),   0);
  201.    lseek (new->relcode, 24+ POS_FIELDPTR(verCURRENT), 0);
  202.  
  203.    for (i = 0; i < old->num_i; i++)
  204.       {
  205.       readx (old->relcode, &arg, 4);
  206.       writx (new->relcode, &arg, 4);
  207.       }
  208.  
  209.  
  210.    lseek (old->relcode, old->recz, 0);
  211.    lseek (new->relcode, new->recz, 0);
  212.  
  213.    for (arg = 0L; arg < numrec; arg++)  /* arg == which number we're moving */
  214.       {
  215.       if ((readx (old->relcode, ptr, len)) != len)
  216.          {
  217.          free (ptr);
  218.          close (new->relcode);
  219.          unlink (tempname);
  220.          baderr (MB_CORRUPT);
  221.          }
  222.       if ((writx (new->relcode, ptr, len)) != len)
  223.          {
  224.          free (ptr);
  225.          close (new->relcode);
  226.          unlink (tempname);
  227.          baderr (MB_DISKFULL);
  228.          }
  229.       }
  230.  
  231.    free (ptr);
  232.    close (new->relcode);     /* Close this filehandle.  */
  233.    MB_RemoveRelation (old);  /* Unnecessary now.        */
  234.    baderr (MB_OKAY);
  235. }
  236.  
  237. int
  238. renamefile (new, old)
  239. char       *new,*old;
  240. {
  241. #ifdef MSDOS
  242.    return rename(old,new);
  243. #else
  244.    if (link (old, new) != 0)  return -1;
  245.    if (unlink (old) != 0)     return -2;
  246.    return 0;
  247. #endif
  248. }
  249.  
  250. void
  251. finalize (newname, oldname)
  252. char     *newname,*oldname;
  253. {
  254.    long  sizea, sizeb;
  255.    int   fh;
  256.  
  257. /*
  258.  * If we got here, convert() already closed all file pointers, so we can
  259.  * do this safely.  First come the sanity checks--make sure we can open
  260.  * and read/write both files, and make sure the new file is larger than
  261.  * the original (if it isn't, we didn't finish converting, regardless of
  262.  * what convert() said).
  263.  *
  264.  */
  265.  
  266.    if (strncmp (&oldname[strlen(oldname)-4], ".rel", 4))
  267.       {
  268.       strcat (oldname, ".rel");
  269.       }
  270.  
  271.    if ((fh = openx (oldname, OPENMODE)) < 0)
  272.       {
  273.       fprintf (stderr, "mb_conv: could not open %s.%s", oldname, SNGCR);
  274.       return;
  275.       }
  276.    sizea = lseek (fh, 0L, 2);  /* Find the filesize */
  277.    close (fh);
  278.  
  279.    if ((fh = openx (newname, OPENMODE)) < 0)
  280.       {
  281.       fprintf (stderr, "mb_conv: could not open %s.%s", oldname, SNGCR);
  282.       return;
  283.       }
  284.    sizeb = lseek (fh, 0L, 2);  /* Find the filesize */
  285.    close (fh);
  286.  
  287.    if (sizea >= sizeb)
  288.       {
  289.       fprintf (stderr, "mb_conv: could not finish conversion!%s", SNGCR);
  290.       return;
  291.       }
  292.  
  293. /*
  294.  * Fine--looks like we converted it just dandy.  So delete the original
  295.  * file, and rename our temporary one so it looks like the old one.  Note that
  296.  * rename() for DOS doesn't exist with almost any *nix compiler, so I use my
  297.  * own renamefile(); args work like *nix MV would (new=first, old=second).
  298.  *
  299.  */
  300.  
  301.    printf ("mb_conv: %s converted to 5.0 successfully.%s", oldname, SNGCR);
  302.  
  303.    unlink (oldname);
  304.    if (renamefile (oldname, newname) != 0)
  305.       {
  306.       fprintf (stderr, "But, the rename didn't work.%s", SNGCR);
  307.       fprintf (stderr, "Rename %s to %s yourself.%s", newname, oldname, SNGCR);
  308.       }
  309. }
  310.  
  311.