home *** CD-ROM | disk | FTP | other *** search
- /* DBF.c
- *
- * DBF.Com -- dBASE III / FoxBASE+ Database structure lister
- *
- * Copyright (c) 1988, by Matrix Software Systems
- * All rights reserved
- *
- * This program will list the structure of any dBASE III /FoxBASE +
- * database file in a format similar to "List Structure." It is similar
- * to another PD program (ListStru.COM) except that this version handles
- * wildcards, comes complete with source code (for use with Turbo C),
- * and is about one-half the size.
- *
- *
- * This program is provided on an "as-is" basis. No warranty, expressed
- * or implied, covers this program. Matrix Software Systems disclaims
- * all conditions and warranties, whether express or implied with regard
- * to this program, including all implied conditions or warranties of
- * merchantibility and fitness for a particular purpose.
- *
- * This program is NOT public domain. It may be freely distributed as
- * long as the following conditions are met:
- *
- * 1. Any and all copies must include the above copyright notice.
- * 2. The software must be distributed in its original ARC format
- * which contains the files DBF.COM, DBF.C, and READ.ME.
- * 3. No fee may be charged for any copy, aside from a possible small
- * duplication and handling fee. (I sincerely doubt you could sell
- * this if you wanted to...)
- *
- *
- * To compile the source code, you will need Turbo C (V1.0).
- *
- * tcc -Ic:\tc\include -Lc:\tc\lib -K -O -Z -d -f- -mt dbf.c
- * exe2bin dbf.exe dbf.com
- *
- */
-
- #include <stdio.h>
- #include <fcntl.h>
- #include <io.h>
- #include <errno.h>
- #include <dir.h>
- #include <string.h>
-
-
- /* A few typedefs from Amigaland. Makes porting code a hell of a lot easier */
- #define VOID void
- typedef unsigned char UBYTE;
- typedef unsigned short UWORD;
- typedef unsigned long ULONG;
- typedef char BYTE;
- typedef short WORD;
- typedef char *STRPTR;
-
-
- STRPTR usagemessage[] = {
- "DBF.Com -- Copyright (c) 1988, by Matrix Software Systems",
- " -- All Rights Reserved --",
- " ",
- "List dBASE III / FoxBASE+ database file structures",
- "Usage: DBF <filename.ext> [<filename.ext>...]",
- " Filenames may include path and/or wildcards (* and ?)",
- " If no extension is specified, '.DBF' is assumed.",
- " ",
- "Please send comments/requests to the following locations:",
- " CompuServe: 75126,2223",
- " BIX: dlove",
- ""
- };
-
- /* dBASE III database header size and offset information */
- #define SIZEOF_DBF_HEADER 32
- #define HOFF_VERSION 0
- #define HOFF_UPDATE_DAY 3
- #define HOFF_UPDATE_MONTH 2
- #define HOFF_UPDATE_YEAR 1
- #define HOFF_RECORDS 4
- #define HOFF_HEADER_SIZE 8
- #define HOFF_RECORD_SIZE 10
-
- #define hdr_version(x) ( (WORD)*(x) )
- #define hdr_update_day(x) ( (WORD)*(x+HOFF_UPDATE_DAY) )
- #define hdr_update_month(x) ( (WORD)*(x+HOFF_UPDATE_MONTH) )
- #define hdr_update_year(x) ( (WORD)*(x+HOFF_UPDATE_YEAR)+1900)
- #define hdr_records(x) (*((ULONG *)(x+HOFF_RECORDS)))
- #define hdr_size(x) (*((UWORD *)(x+HOFF_HEADER_SIZE)))
- #define hdr_rsize(x) (*((UWORD *)(x+HOFF_RECORD_SIZE)))
- #define num_fields(x) ((hdr_size(x)-32)>>5)
-
-
- /* dBASE field header size and offset information */
- #define SIZEOF_DBF_FIELD 32
- #define FOFF_TYPE 11
- #define FOFF_LENGTH 16
- #define FOFF_DECIMAL 17
-
- #define fld_name(x) (x)
- #define fld_type(x) (x[FOFF_TYPE])
- #define fld_length(x) ((UWORD)x[FOFF_LENGTH])
- #define fld_decimal(x) ((UWORD)x[FOFF_DECIMAL])
-
-
-
-
- /* Prototypes */
- WORD main(int, char**);
- STRPTR fixname(STRPTR,struct ffblk *);
- WORD liststru(STRPTR);
- VOID usage(void);
-
-
- WORD
- main(argc,argv)
- WORD argc;
- char *argv[];
- {
- static char filename[256];
- static struct ffblk ffblk;
- register STRPTR st;
-
- if (argc < 2) { /* Show usage if no argument given */
- usage();
- } else {
- while(--argc) {
- strcpy(filename,*(++argv));
-
- /* Assume the extension .dbf unless otherwise specified */
- for (st = filename; *st != '\0' && *st != '.'; st++);
- if (*st == '\0')
- strcpy(st,".dbf");
-
- /* Now check for a matching file. If no match is found, assume
- * the argument is a directory name, append "\\*.dbf" and attempt
- * to match a file there. If there are still no matches found,
- * print a warning message and skip to the next arg. */
-
- if (findfirst(filename,&ffblk,0)) {
- sprintf(filename,"%s%s",*argv,"\\*.dbf");
- if (findfirst(filename,&ffblk,0)) {
- printf("Could not locate %s.",*argv);
- continue;
- }
- }
-
- /* If we get here, findfirst() found a matching file. So fix the
- * filename to eliminate any wildcards and attempt to process it.
- * Loop until all matches have been handled. */
- do {
- liststru(fixname(filename,&ffblk));
- } while (!findnext(&ffblk));
- }
- }
- }
-
-
- STRPTR
- fixname(filename,ffblk)
- STRPTR filename;
- struct ffblk *ffblk;
- {
- static char drive[MAXDRIVE];
- static char dir[MAXDIR];
- static char file[MAXFILE];
- static char ext[MAXEXT];
-
- /* Tear the filename apart to get the drive and directory */
- fnsplit(filename,drive,dir,file,ext);
-
- /* Then reassemble it with the correct filename */
- sprintf(filename,"%s%s%s",drive,dir,ffblk->ff_name);
-
- /* For convenience, return a pointer to the fixed filename */
- return(filename);
- }
-
-
- WORD
- liststru(filename)
- STRPTR filename;
- {
- static char header[SIZEOF_DBF_HEADER];
- static char field[SIZEOF_DBF_FIELD];
- register int fp;
- register int size,i;
- register STRPTR format,type;
-
- printf("Structure for database : %s\n",filename);
-
- /* Attempt to open the file (Note that O_BINARY MUST be present!) */
- fp = open(filename,O_RDONLY|O_BINARY|O_DENYNONE);
- if (fp) {
- /* Attempt to read the database header */
- size = read(fp,&header[0],SIZEOF_DBF_HEADER);
- if (size == SIZEOF_DBF_HEADER) {
-
- /* Got it, so print out the header information */
- /* Uncomment the next line to check the dbf version #. For dBASE III
- and FoxBASE + files it will be 3 (or 83 if there is an associated
- .dbt file) */
- /* printf("Version #%d\n",hdr_version(header)); */
-
- printf("Number of data records : %10ld\n",hdr_records(header));
- printf("Date of last update : %02d-%02d-%4d\n",
- hdr_update_month(header),hdr_update_day(header),
- hdr_update_year(header));
- printf("Field Field name Type Width Dec\n");
- printf("----- ---------- ---- ----- ---\n");
-
- /* Finally, print out each field */
- for (i = 1; i <= num_fields(header); i++) {
- size = read(fp,&field[0],SIZEOF_DBF_FIELD);
- if (size == SIZEOF_DBF_FIELD) {
- format = "%-9s %5d\n";
- printf("%5d %-10s ",i,fld_name(field));
- switch(fld_type(field)) {
- case 'C':
- type = "Character";break;
- case 'D':
- type = "Date";break;
- case 'L':
- type = "Logical";break;
- case 'M':
- type = "Memo";break;
- case 'N':
- type = "Numeric";
- format = "%-9s %5d %3d\n";break;
- default:
- /* Egads! A goto! */
- goto error;
- }
- printf(format,type,fld_length(field),fld_decimal(field));
- } else
- /* Oh No! Another one! */
- goto error;
- }
- /* Finally, print out the total record size. Notice that this is one
- * byte larger than the sum of the individual field length printed
- * above. dBASE adds one byte to the beginning of every record
- * for internal use (deletion state). */
-
- printf("** Total ** %5d\n",hdr_rsize(header));
- } else {
- error:
- puts("Database file corrupt!");
- }
- close(fp);
- } else
- printf("Couldn't open database : %s\n",filename);
- }
-
-
- void usage()
- {
- register STRPTR *st;
- for(st = usagemessage; **st; st++)
- puts(*st);
- }