home *** CD-ROM | disk | FTP | other *** search
- /*
- * METALBASE 5.1
- *
- * Released January 1st, 1993 by Huan-Ti [ t-richj@microsoft.com ]
- *
- */
-
- #include <mbase.h>
- #include "internal.h" /* Because we do some non-standard record moving */
-
-
- /*
- * PROTOTYPES -----------------------------------------------------------------
- *
- */
-
- void main XARGS( (int, char **) );
- mb_err convert XARGS( (relation *, relation *) );
- void finalize XARGS( (char *, char *) );
-
- #ifndef MSDOS
- int rename XARGS( (char *, char *) );
- #endif
-
-
- /*
- * ROUTINES -------------------------------------------------------------------
- *
- */
-
- relation *rel;
- relation *new;
-
- char tempname[128];
-
- void
- main (argc, argv)
- int argc;
- char **argv;
- {
- char *str;
- bool fDone = FALSE;
-
- for (--argc,++argv; argc; --argc,++argv)
- {
- if (*(str = *argv) == '-')
- {
- fprintf (stderr, "option %s unrecognized.\n", 1+str);
- continue;
- }
-
- fDone = TRUE;
-
- if ((rel = mb_old (str, 0)) == RNULL)
- {
- fprintf (stderr, "%s: %s.\n", str, mb_error);
- continue;
- }
-
- if (rel->ver >= verLOWEST)
- {
- fprintf (stderr, "%s is in a compatible format.\n", str);
- MB_RemoveRelation (rel);
- continue;
- }
-
- if ((new = mb_new ()) == RNULL)
- {
- fprintf (stderr, "%s.\n", mb_error);
- mb_die();
- continue;
- }
-
- strcpy (tempname, str);
- if (! strncmp (&tempname[strlen(tempname)-4], ".rel", 4))
- {
- tempname[strlen(tempname)-4] = 0;
- }
- strcat (tempname, ".tmp");
-
- if (convert (new, rel) == MB_OKAY)
- {
- MB_RemoveRelation (rel);
- finalize (tempname, str); /* Removes original and renames new */
- }
- else
- {
- MB_RemoveRelation (rel);
- fprintf (stderr, "%s.\n", mb_error);
- }
-
- mb_rmv (new); /* Free any memory used by mb_new() */
- }
-
- if (! fDone)
- {
- fprintf (stderr, "format: mbconv oldrelation [oldrelation...]\n");
- mb_exit (1);
- }
-
- mb_exit (0);
- }
-
- mb_err
- convert (new, rel)
- relation *new, *rel;
- {
- long nexts, numrec, arg;
- char desc[128], t2[5];
- char *ptr;
- int i, j, len;
-
- /*
- * The format for the relation header is something like this:
- *
- * offset for offset for
- * pre-4.1 ver post-4.0 ver field
- * ------------- -------------- --------------------------------
- * 0 0 1-char: signature for MB version
- * ...
- * 2 6 4-char: pointer to fields
- * 6 10 4-char: pointer to indices
- * 10 14 4-char: pointer to record zero
- * 14 (POS_NUMREC) 18 4-char: number of records
- * 18 22 4-char: next serial value
- * 22 26 2-char: number of fields
- * 24 28 2-char: number of indices
- * 26 (POS_INDICES) 30 4*nIdx: top-of-index array
- *
- */
-
- if (rel->ver == verMINIMUM)
- lseek (rel->fhRel, POS_OLDNUMREC, 0);
- else
- lseek (rel->fhRel, POS_NUMREC, 0);
-
- readx (rel->fhRel, &numrec, 4);
- readx (rel->fhRel, &nexts, 4);
-
- /*
- * First, the fields...
- *
- */
-
- for (i = 0; i < rel->nFld; i++)
- {
- switch (rel->fldType[i])
- {
- case T_SERIAL: arg = nexts; break;
- case T_CHAR: arg = rel->cbLen[i]; break;
- case T_BYTE: arg = rel->cbLen[i]; break;
- default: arg = 0L; break;
- }
-
- if (mb_addfield (new, rel->fldName[i], rel->fldType[i], arg) != MB_OKAY)
- {
- Error (mb_errno);
- }
- }
-
- /*
- * Next, the indices...
- *
- */
-
- for (i = 0; i < rel->nIdx; i++)
- {
- desc[0] = 0;
-
- for (j = 0; j < rel->nIdxFld[i]; j++)
- {
- sprintf (t2, "%d", rel->idxFld[i][j]);
-
- if (j != 0)
- strcat (desc, ",");
- strcat (desc, t2);
- }
-
- if (mb_addindex (new, rel->idxName[i], rel->fDups[i], desc) != MB_OKAY)
- {
- Error (mb_errno);
- }
- }
-
- /*
- * Now create it, and open the resulting file...
- *
- */
-
- if (mb_create (new, tempname, 0) != MB_OKAY)
- {
- Error_2 (mb_errno);
- }
-
- if ((new->fhRel = openx (tempname, OPENMODE)) <= 0)
- {
- Error_2 (MB_NO_READ);
- }
-
- /*
- * The number of records is reset to zero inside the new relation, so since
- * we read it from the rel relation earlier, write it out where it needs to
- * be (see why I had to include internal.h?). Oh, and grab a buffer big
- * enough to move an entire record, with indices intact...
- *
- */
-
- lseek (new->fhRel, POS_NUMREC, 0);
- writx (new->fhRel, &numrec, 4);
-
- len = (int)(rel->cbRecord + cbINDEX * rel->nIdx);
-
- if ((ptr = (char *)malloc (len +1)) == NULL)
- {
- Error_3 (MB_NO_MEMORY);
- }
-
- /*
- * Great. Problem is, the new header is bigger than older versions... so
- * read each record, and write it out at the new place in the new relation.
- * Record numbers are offsets relative to ->recz, so they won't have to change
- * this way.
- *
- * We also have to initialize the top-of-index pointers, which aren't set
- * by mb_create() (obviously).
- *
- */
-
- if (rel->ver == verMINIMUM)
- lseek (rel->fhRel, POS_OLDINDICES, 0);
- else
- lseek (rel->fhRel, POS_INDICES, 0);
-
- lseek (new->fhRel, POS_INDICES, 0);
-
- for (i = 0; i < rel->nIdx; i++)
- {
- readx (rel->fhRel, &arg, 4);
- writx (new->fhRel, &arg, 4);
- }
-
-
- lseek (rel->fhRel, rel->posRecZ, 0); /* posRecZ was set by mb_old() */
- lseek (new->fhRel, new->posRecZ, 0); /* posRecZ was set by mb_create() */
-
- for (arg = 0L; arg < numrec; arg++) /* arg == which record we're moving */
- {
- if ((readx (rel->fhRel, ptr, len)) != len)
- {
- free (ptr);
- Error_3 (MB_CORRUPT);
- }
- if ((writx (new->fhRel, ptr, len)) != len)
- {
- free (ptr);
- Error_3 (MB_DISKFULL);
- }
- }
-
- free (ptr);
- SetError (MB_OKAY);
-
- lblERROR_3:
- close (new->fhRel);
-
- lblERROR_2:
- if (mb_errno != MB_OKAY)
- {
- unlink (tempname);
- }
-
- lblERROR:
- return mb_errno;
- }
-
- #ifndef MSDOS
- int
- rename (new, rel)
- char *new,*rel;
- {
- if (link (rel, new) != 0) return -1;
- if (unlink (rel) != 0) return -2;
- return 0;
- }
- #endif
-
- void
- finalize (newname, oldname)
- char *newname,*oldname;
- {
- long sizea, sizeb;
- int fh;
-
- /*
- * If we got here, convert() already closed all file pointers, so we can
- * do this safely. First come the sanity checks--make sure we can open
- * and read/write both files, and make sure the new file is larger than
- * the original (if it isn't, we didn't finish converting, regardless of
- * what convert() said).
- *
- */
-
- if (strncmp (&oldname[strlen(oldname)-4], ".rel", 4))
- {
- strcat (oldname, ".rel");
- }
-
- if ((fh = openx (oldname, OPENMODE)) < 0)
- {
- fprintf (stderr, "mb_conv: could not open %s.\n", oldname);
- return;
- }
- sizea = lseek (fh, 0L, 2); /* Find the filesize */
- close (fh);
-
- if ((fh = openx (newname, OPENMODE)) < 0)
- {
- fprintf (stderr, "mb_conv: could not open %s.\n", newname);
- return;
- }
- sizeb = lseek (fh, 0L, 2); /* Find the filesize */
- close (fh);
-
- if (sizea > sizeb)
- {
- fprintf (stderr, "mb_conv: could not finish conversion!\n");
- return;
- }
-
- /*
- * Fine--looks like we converted it just dandy. So delete the original
- * file, and rename our temporary one so it looks like the old one. Note that
- * rename() for DOS doesn't exist with almost any *nix compiler, so I use my
- * own if MSDOS isn't defined.
- *
- */
-
- printf ("mb_conv: %s converted successfully.\n", oldname);
-
- unlink (oldname);
- if (rename (newname, oldname) != 0)
- {
- fprintf (stderr, "But, the rename didn't work.\n");
- fprintf (stderr, "Rename %s to %s yourself.\n", newname, oldname);
- }
- }
-
-