home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume43 / dbf / part01 / dbf_head.c next >
C/C++ Source or Header  |  1994-06-27  |  6KB  |  277 lines

  1. /*
  2.  * Copyright (c) 1991, 1992, 1993 Brad Eacker,
  3.  *              (Music, Intuition, Software, and Computers)
  4.  * All Rights Reserved
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <fcntl.h>
  9.  
  10. #include "dbf.h"
  11.  
  12. /*
  13.  * get the header info from the file
  14.  *    basic header info & field descriptions
  15.  */
  16. dbhead_t *
  17. get_dbf_head(fd)
  18. int fd;
  19. {
  20.     dbhead_t *dbh;
  21.     struct dbf_dhead  dbhead;
  22.     dbfield_t *dbf, *cur_f;
  23.     int ret, nfields, offset;
  24.  
  25.     if ((dbh = (dbhead_t *)malloc(sizeof(dbhead_t))) == NULL)
  26.         return NULL;
  27.     if (lseek(fd, 0, 0) < 0)
  28.         return NULL;
  29.     if ((ret = read(fd, &dbhead, sizeof(dbhead))) < 0)
  30.         return NULL;
  31.  
  32.     /* build in core info */
  33.     dbh->db_fd = fd;
  34.     dbh->db_dbt = dbhead.dbh_dbt;
  35.     dbh->db_records = get_long(dbhead.dbh_records);
  36.     dbh->db_hlen = get_short(dbhead.dbh_hlen);
  37.     dbh->db_rlen = get_short(dbhead.dbh_rlen);
  38.  
  39.     db_set_date(dbh->db_date, dbhead.dbh_date[DBH_DATE_YEAR] + 1900,
  40.         dbhead.dbh_date[DBH_DATE_MONTH],
  41.         dbhead.dbh_date[DBH_DATE_DAY]);
  42.  
  43.     dbh->db_nfields = nfields = (dbh->db_hlen - sizeof(struct dbf_dhead)) /
  44.                 sizeof(struct dbf_dfield);
  45.  
  46.     /* get all the field info */
  47.     dbf = (dbfield_t *)malloc(sizeof(dbfield_t) * nfields);
  48.  
  49.     offset = 1;
  50.     for (cur_f = dbf; cur_f < &dbf[nfields] ; cur_f++) {
  51.         if (get_dbf_field(dbh, cur_f) < 0) {
  52.             free_dbf_head(dbh);
  53.             return NULL;
  54.         }
  55.         cur_f->db_foffset = offset;
  56.         offset += cur_f->db_flen;
  57.     }
  58.     dbh->db_fields = dbf;
  59.  
  60.     return dbh;
  61. }
  62.  
  63. /*
  64.  * free up the header info built above
  65.  */
  66. free_dbf_head(dbh)
  67. dbhead_t *dbh;
  68. {
  69.     dbfield_t *dbf, *cur_f;
  70.     int nfields;
  71.     u_char *fp;
  72.  
  73.     dbf = dbh->db_fields;
  74.     nfields = dbh->db_nfields;
  75.     for (cur_f = dbf; cur_f < &dbf[nfields]; cur_f++) {
  76.         if (cur_f->db_format) {
  77.             free(cur_f->db_format);
  78.         }
  79.     }
  80.  
  81.     free(dbf);
  82.     free(dbh);
  83. }
  84.  
  85. /*
  86.  * put out the header info
  87.  */
  88. put_dbf_head(dbh)
  89. dbhead_t *dbh;
  90. {
  91.     int fd = dbh->db_fd;
  92.     struct dbf_dhead  dbhead;
  93.     int    ret;
  94.  
  95.     bzero(&dbhead, sizeof dbhead);
  96.  
  97.     /* build on disk info */
  98.     dbhead.dbh_dbt = dbh->db_dbt;
  99.     put_long(dbhead.dbh_records, dbh->db_records);
  100.     put_short(dbhead.dbh_hlen, dbh->db_hlen);
  101.     put_short(dbhead.dbh_rlen, dbh->db_rlen);
  102.  
  103.     /* put the date spec'd into the on disk header */
  104.     dbhead.dbh_date[DBH_DATE_YEAR] =(u_char)(db_date_year(dbh->db_date) -
  105.                         1900);
  106.     dbhead.dbh_date[DBH_DATE_MONTH]=(u_char)(db_date_month(dbh->db_date));
  107.     dbhead.dbh_date[DBH_DATE_DAY] =(u_char)(db_date_day(dbh->db_date));
  108.  
  109.     if (lseek(fd, 0, 0) < 0)
  110.         return -1;
  111.     if ((ret = write(fd, &dbhead, sizeof(dbhead))) < 0)
  112.         return -1;
  113. }
  114.  
  115. /*
  116.  * get a field off the disk from the current file offset
  117.  */
  118. get_dbf_field(dbh, dbf)
  119. dbhead_t *dbh;
  120. dbfield_t *dbf;
  121. {
  122.     struct dbf_dfield    dbfield;
  123.     unsigned char    *scp, *dcp;
  124.     unsigned char    format[100];
  125.     int ret;
  126.  
  127.     if ((ret = read(dbh->db_fd, &dbfield, sizeof(dbfield))) < 0) {
  128.         return ret;
  129.     }
  130.  
  131.     /* build the field name */
  132.     copy_crimp(dbf->db_fname, dbfield.dbf_name, DBF_NAMELEN);
  133.  
  134.     dbf->db_type = dbfield.dbf_type;
  135.     switch (dbf->db_type) {
  136.         case 'N':
  137.         dbf->db_flen = dbfield.dbf_flen[0];
  138.         dbf->db_fdc = dbfield.dbf_flen[1];
  139.         break;
  140.         default:
  141.             dbf->db_flen = get_short(dbfield.dbf_flen);
  142.     }
  143.  
  144.     if ((dbf->db_format = get_dbf_f_fmt(dbf)) == NULL) {
  145.         return 1;
  146.     }
  147.  
  148.     return 0;
  149. }
  150.  
  151. /*
  152.  * put a field out on the disk at the current file offset
  153.  */
  154. put_dbf_field(dbh, dbf)
  155. dbhead_t *dbh;
  156. dbfield_t *dbf;
  157. {
  158.     struct dbf_dfield    dbfield;
  159.     unsigned char        *scp, *dcp;
  160.     int            c_left = DBF_NAMELEN;
  161.     int            ret;
  162.  
  163.     bzero(&dbfield, sizeof dbfield);
  164.  
  165.     /* build the on disk field info */
  166.     scp = dbf->db_fname; dcp = dbfield.dbf_name;
  167.  
  168.     strncpy(dbfield.dbf_name, dbf->db_fname, DBF_NAMELEN);
  169.  
  170.     dbfield.dbf_type = dbf->db_type;
  171.     switch (dbf->db_type) {
  172.         case 'N':        
  173.         dbfield.dbf_flen[0] = dbf->db_flen;
  174.         dbfield.dbf_flen[1] = dbf->db_fdc;
  175.         break;
  176.         default:
  177.             put_short(dbfield.dbf_flen, dbf->db_flen);
  178.     }
  179.  
  180.     /* now write it out to disk */
  181.     if ((ret = write(dbh->db_fd, &dbfield, sizeof(dbfield))) < 0) {
  182.         return ret;
  183.     }
  184.     return 1;
  185. }
  186.  
  187. /*
  188.  * put out all the info at the top of the file...
  189.  */
  190. static char end_stuff[2] = {0x0d, 0};
  191.  
  192. put_dbf_info(dbh)
  193. dbhead_t *dbh;
  194. {
  195.     dbfield_t    *dbf, *cur_f;
  196.     u_char        *cp;
  197.     int        fcnt;
  198.  
  199.     if (cp = db_cur_date(NULL)) {
  200.         strncpy(dbh->db_date, cp, 8);
  201.         free(cp);
  202.     }
  203.     put_dbf_head(dbh);
  204.     dbf = dbh->db_fields;
  205.     for (fcnt = dbh->db_nfields; fcnt > 0; fcnt--, dbf++)
  206.         put_dbf_field(dbh, dbf);
  207.     write(dbh->db_fd, end_stuff, 2);
  208. }
  209.  
  210. u_char *
  211. get_dbf_f_fmt(dbf)
  212. dbfield_t *dbf;
  213. {
  214.     u_char format[100];
  215.  
  216.     /* build the field format for printf */
  217.     switch (dbf->db_type) {
  218.        case 'C':
  219.         sprintf(format, "%%-%ds", dbf->db_flen);
  220.         break;
  221.        case 'N':
  222.        case 'L':
  223.        case 'D':
  224.         sprintf(format, "%%%ds", dbf->db_flen);
  225.         break;
  226.        case 'M':
  227.         strcpy(format, "%s");
  228.         break;
  229.     }
  230.     return (u_char *)strdup(format);
  231. }
  232.  
  233. dbhead_t *
  234. dbf_open(dp, o_flags)
  235. u_char *dp;
  236. int    o_flags;
  237. {
  238.     int fd;
  239.     u_char *cp;
  240.     dbhead_t *dbh;
  241.  
  242.     cp = dp;
  243.     if ((fd = open(cp, o_flags)) < 0) {
  244.         cp = (u_char *)malloc(256);
  245.         strcpy(cp, dp); strcat(cp, ".dbf");
  246.         if ((fd = open(cp, o_flags)) < 0) {
  247.             perror("open");
  248.             return NULL;
  249.         }
  250.     }
  251.  
  252.     if ((dbh = get_dbf_head(fd)) ==     0) {
  253.         fprintf(stderr, "Unable to get header\n");
  254.         return NULL;
  255.     }
  256.     dbh->db_name = cp;
  257.     dbh->db_cur_rec = 0;
  258.     
  259.     return dbh;
  260. }
  261.  
  262. dbf_head_info(dbh)
  263. dbhead_t *dbh;
  264. {
  265.     int    nfields;
  266.     dbfield_t *dbf, *cur_f;
  267.  
  268.     nfields = dbh->db_nfields;
  269.     printf("# fields: %d, record len: %d, total records %d\n",
  270.         nfields, dbh->db_rlen, dbh->db_records);
  271.     dbf = dbh->db_fields;
  272.     for (cur_f = dbf; cur_f < &dbf[nfields] ; cur_f++) {
  273.         printf("# %s, %c, %d, %d\n", cur_f->db_fname,
  274.             cur_f->db_type, cur_f->db_flen, cur_f->db_fdc);
  275.     }
  276. }
  277.