/* @(#) scandb.c @(#) By Peter de Jong @(#) Scans a Progress database and checks the dbkey of each database block. @(#) Version 2.1 @(#) Feel free to distribute this program but use at your own risk. @(#) This program will open the database file(s) Read-Only. # Please send comments to pjo@progress.com. # # Oct 12 1996 - Initial programming - V1.0 # Jan 29 1997 - Implemented Variable blocksize for V8.2 databases - V1.1 # May 4 1997 - Major rewrite for Multi-Volume databases - V2.0 # May 21 1997 - Write error messages to standard error - V2.1 # Jun 27 1997 - Minor adjustment testing arguments for GPF on NT - V2.2 # Tested OS DB version ######################################### 4/96 AIX 8.1 4/96 HPUX 8.0 4/96 HPUX 8.2 4/96 HPUX 7.3 4/96 SCO/5 8.1 5/96 SCO/Unixw 8.1 # Todo: # Testing + Testing on all platforms. */ #include #include long lseek(); void syserr(msg) char *msg; { extern int errno, sys_nerr; extern char *sys_errlist[]; fflush(stdout); fprintf(stderr, "\nERROR: %s (%d", msg, errno); if (errno > 0 && errno < sys_nerr) fprintf(stderr, "; %s)\n", sys_errlist[errno]); else fprintf(stderr,")\n"); exit(1); } long int dbkey=0, rdbkey=0, blocknum=0, dbwater=0, dbkeyerr=0, recinblock; short int blocksize, mv, verbose=0; main( int argc, char *argv[]) { FILE *fpdb, *fpdb2, *fopen(), *fplock; char dbname[70], lockfile[70], extname[70], extype; short int dbversion, readmaster=1; long int dbblocks, readint, extpos, extsize; if (argc == 1) /* Geen optie meegegeven: error */ { fprintf(stderr,"%s: Usage: %s [-v(erbose)].\n",argv[0],argv[0]); exit(1); } if (argc > 3) /* Te veel opties: error */ { fprintf(stderr,"%s: Too many options.\n",argv[0]); exit(1); } strcpy(dbname,argv[1]); strcat(dbname,".db"); if (( fpdb = fopen(dbname, "rb" )) == NULL) { fprintf(stderr,"%s: Could not find or open file: %s\n",argv[0],dbname); exit(1); } if (argc == 3) /* NT cannot stand cmp of null pointers */ { if ( ! strcmp(argv[2],"-v")) { verbose = 1; } } printf("\n Progress Database DBKEY scan. Version 2.1 by Peter de Jong.\n\n"); strcpy(lockfile,argv[1]); strcat(lockfile,".lk"); if (( fplock = fopen(lockfile,"r")) != NULL) { printf("WARNING: The lockfile %s exists!\n\n",lockfile); fclose(fplock); } printf(" Database name: %s\n",dbname); if (fseek(fpdb, 16, 0) == -1) syserr("fseek"); if (fread(&dbversion, 1, 2, fpdb) != 2) syserr("fread"); printf(" Database version number: %d\n",dbversion); /* Blockgrootte bepalen */ blocksize = ( dbversion / 1024 ) * 1024; printf(" Database blocksize: %d\n",blocksize); if (blocksize < 8192) { recinblock = 32; } else { recinblock = 64; } /* Multi-Volume bepalen */ if (fseek(fpdb, 140, 0) == -1) syserr("fseek"); if (fread(&readint, 1, 4, fpdb) != 4) syserr("fread"); printf(" Multi Volume database: "); if ( readint > 0 ) { /**************** MULTI VOLUME ***********************/ mv = 1; printf("Yes\n"); extpos = blocksize; /* Offset eerste extent info */ for (;;) { /* Lees extent type */ if (fseek(fpdb, extpos + 8, 0) == -1) syserr("fseek"); if (fread(&extype, 1, 1, fpdb) != 1) syserr("fread"); if ( extype == 37 | extype == 5 ) /* Fixed of variabel data extent */ { if (fseek(fpdb, extpos + 9, 0) == -1) syserr("fseek"); if (fread(&extname, 1, 70, fpdb) != 70) syserr("fread"); if (( fpdb2 = fopen(extname, "rb" )) == NULL) { printf("%s: Could not find or open file %s\n",argv[0],extname); syserr("fopen"); } /* Het eerste extent is nu open, nu de info eruit lezen */ if ( readmaster ) { readmaster = 0; if (fseek(fpdb2, 24 + blocksize, 0) == -1) syserr("fseek"); if (fread(&dbblocks, 1, 4, fpdb2) != 4) syserr("fread"); printf(" Total allocated blocks: %d\n",dbblocks); if (fseek(fpdb2, 48 + blocksize, 0) == -1) syserr("fseek"); if (fread(&dbwater, 1, 4, fpdb2) != 4) syserr("fread"); printf(" Database blocks used: %d\n",dbwater); printf("\nScanning the database and checking the dbkey of each block, please wait...\n"); fflush(stdout); } /* readmaster */ /* Lees aantal blokken wat dit extent groot is */ if (fseek(fpdb, extpos, 0) == -1) syserr("fseek"); if (fread(&extsize, 1, 4, fpdb) != 4) syserr("fread"); if (verbose) printf("\n"); printf("Scanning database extent: %s\n",extname); /* Laat de user weten */ switch (extype) { case 37: /* Fixed data extent */ printf("Blocks in Fixed Extent: %d",extsize); break; case 5: /* Variabel data extent */ printf("Variable Extent"); break; default: /* Unknown data extent */ printf("Blocks in unknown extent type %d: %d",extype,extsize); break; } if ( extsize == 0 ) /* variabel extent */ { extsize = -1; } printf(" Please wait ...\n"); /* Scan het extent */ dbkey = readdbkey(blocknum,extsize,fpdb2); } else break; /* Geen data extents meer */ extpos += 72; /* Positie voor de volgende extent naam */ } } else { /* mv = no */ /**************** SINGLE VOLUME ********************/ printf("No\n"); if (fseek(fpdb, 24, 0) == -1) syserr("fseek"); if (fread(&dbblocks, 1, 4, fpdb) != 4) syserr("fread"); printf(" Total allocated blocks: %d\n",dbblocks); if (fseek(fpdb, 48, 0) == -1) syserr("fseek"); if (fread(&dbwater, 1, 4, fpdb) != 4) syserr("fread"); printf(" Database blocks used: %d\n",dbwater); printf("\nScanning the database and checking the dbkey of each block, please wait...\n"); dbkey = readdbkey(blocknum,dbwater,fpdb); } printf("\nDone, %d error(s) reported.\n",dbkeyerr); /* Sluiten & Sluiten */ fclose(fpdb); if (dbkeyerr) { return(1); } else { return(0); } } /* main */ readdbkey( long blocknum, long toblock, FILE *fp) { /* mv start met tweede blok */ if (mv) { blocknum = 1; } else { blocknum = 0; } /* Bereken aantal blokken in extent */ toblock = toblock / ( blocksize / 1024 ); while ( blocknum != toblock ) { dbkey = dbkey + recinblock; /* volgende dbkey */ /* Gaan we over de high water mark? */ if ((dbkey / recinblock) > dbwater) { printf("\nAbove High Water Mark %d.\n", dbwater); break; } /* Lees dbkey */ if (fseek(fp, blocknum * blocksize, 0) == -1) syserr("fseek"); if (fread(&rdbkey, 1, 4, fp) != 4) syserr("fread"); /* checkit */ if (verbose) printf("rdbkey: %10d",rdbkey); if (dbkey != rdbkey) { if (verbose) printf("\n"); fprintf(stderr, "ERROR: Wrong dbkey in database block %d. Read %d but should be %d.\n", blocknum, rdbkey, dbkey); dbkeyerr++; } else { if (verbose) printf(" Ok\r"); } blocknum++; if (verbose) printf("blocknum: %10d dbkey: %10d ",blocknum,dbkey); } return (dbkey); } /* EOF */