home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 311_01 / db_main.c < prev    next >
C/C++ Source or Header  |  1990-04-22  |  48KB  |  1,936 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /*                                                                          */
  4. /*      db_main.c  v1.3  (c) 1987-1990  Ken Harris                          */
  5. /*                                                                          */
  6. /*                                                                          */
  7. /****************************************************************************/
  8. /*                                                                          */
  9. /*      This software is made available on an AS-IS basis. Unrestricted     */
  10. /*      use is granted provided that the copyright notice remains intact.   */
  11. /*      The author makes no warranties expressed or implied.                */
  12. /*                                                                          */
  13. /****************************************************************************/
  14.  
  15. #include "dblib.h"
  16.  
  17. static char  *copyright = "db V1.3 (c) 1987-1990 Ken Harris";
  18.  
  19. int    db_error     = 0;
  20. ulong  db_match_blk = 0;
  21. ushort db_match_rec = 0;
  22. ulong  db_add_blk   = 0;
  23. ushort db_add_rec   = 0;
  24.  
  25. /*
  26.  *      db_create  -  Create a New Data File 
  27.  */
  28.  
  29. DATA_FILE db_create(path, fname, options)
  30.  char *path, *fname, *options;               
  31. {
  32.         BUFFER db_alloc_buf();
  33.         DATA_FILE df;
  34.     FILE_HDR  fhdr;
  35.         char  *fname_dflts(), *calloc();
  36.  
  37.         db_error = 0;
  38.  
  39.         df = (DATA_FILE) calloc(1, sizeof(struct db_data_file));
  40.     if (!df)
  41.     {    db_error = DB_ALLOC_ERROR;
  42.         return(NULL);
  43.     }
  44.  
  45.         df->df_fhdr = db_alloc_buf(DB_FILE_HDR_SIZE);
  46.         fhdr        = (FILE_HDR) df->df_fhdr->buf_data;
  47.     if (db_error) { db_free_df(df); return(NULL); }
  48.  
  49.         df->df_fhdr->buf_cur_size = DB_FILE_HDR_SIZE;
  50.  
  51.         strcpy(df->df_fname, fname_dflts(fname,path));
  52.  
  53.     db_file_options(fhdr, options);
  54.         if (db_error) { db_free_df(df); return(NULL); }
  55.  
  56.         db_fhdr_create(fhdr);
  57.         if (db_error) { db_free_df(df); return(NULL); }
  58.  
  59. #ifdef MSC
  60.     df->df_fd = open(df->df_fname, O_CREAT|O_TRUNC|O_RDWR|O_BINARY, S_IREAD|S_IWRITE);
  61. #endif
  62. #ifdef TURBO 
  63.     df->df_fd = open(df->df_fname, O_CREAT|O_TRUNC|O_RDWR|O_BINARY, S_IREAD|S_IWRITE);
  64. #endif
  65. #ifdef ULTRIX
  66.     df->df_fd = open(df->df_fname, O_CREAT|O_TRUNC|O_RDWR, S_IREAD|S_IWRITE);
  67. #endif
  68. #ifdef SYSV
  69.     df->df_fd = open(df->df_fname, O_CREAT|O_TRUNC|O_RDWR, S_IREAD|S_IWRITE);
  70. #endif
  71.         if (df->df_fd < 0)
  72.         {       db_error = DB_FILE_NOT_CREATED;
  73.                 db_free_df(df);
  74.                 return(NULL);
  75.         }                       
  76.  
  77.         df->df_stat = DB_OPEN;
  78.  
  79.         switch (fhdr->fh_file_type)
  80.         { 
  81. #ifdef IDX
  82.      case DB_INDEX:
  83.              df->df_buf = db_alloc_buf(fhdr->fh_block_size+2*fhdr->fh_rec_size);
  84.          if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  85.  
  86.              df->df_tmp = db_alloc_buf(fhdr->fh_block_size+2*fhdr->fh_rec_size);
  87.          if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  88.  
  89.              df->df_aux = db_alloc_buf(fhdr->fh_block_size+2*fhdr->fh_rec_size);
  90.          if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  91.  
  92.              df->df_buf->buf_size = fhdr->fh_block_size;
  93.              df->df_tmp->buf_size = fhdr->fh_block_size;
  94.              df->df_aux->buf_size = fhdr->fh_block_size;
  95.          break;
  96. #endif
  97.  
  98. #ifdef RAN
  99.       case DB_RANDOM:
  100.              df->df_buf = db_alloc_buf(fhdr->fh_block_size);
  101.          if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  102.  
  103.              df->df_tmp = db_alloc_buf(fhdr->fh_block_size);
  104.          if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  105.  
  106.              while (fhdr->fh_last_block < fhdr->fh_base_size)
  107.              {  db_extend(df, df->df_buf);
  108.             if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  109.  
  110.                 db_put_blk(df, df->df_buf);
  111.              }
  112.          break;
  113. #endif
  114.          
  115. #ifdef SEQ
  116.       case DB_SEQ:
  117.              df->df_buf = db_alloc_buf(fhdr->fh_block_size);
  118.          if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  119.          break;
  120. #endif
  121.  
  122. #ifdef VAR
  123.       case DB_VAR:
  124.              df->df_buf = db_alloc_buf(fhdr->fh_block_size);
  125.          if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  126.          break;
  127. #endif
  128.     }
  129.  
  130.         db_put_blk(df, df->df_fhdr);
  131.          if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  132.  
  133.         return(df);
  134. }
  135.  
  136. /*
  137.  *    db_file_options - parse and setup file options
  138.  */
  139.  
  140. #define OPTION_SIZE     20
  141. #define SUB_OPTION_SIZE 50
  142.  
  143. db_file_options(fh, option_str)
  144.  FILE_HDR  fh;
  145.  char     *option_str;
  146. {
  147.     char  option[OPTION_SIZE], sub_option[SUB_OPTION_SIZE];
  148.     char *c, *o_ptr, *s_ptr;
  149.     int   cnt;
  150.  
  151.     c = option_str;
  152.     while (*c)
  153.     {    while (*c && !isalpha(*c)) c++;
  154.         
  155.         o_ptr  = option;
  156.         s_ptr  = sub_option;
  157.         *o_ptr = *s_ptr = NULL;
  158.  
  159.         for (cnt=0; isalpha(*c); cnt++, c++)
  160.         {    if (cnt < OPTION_SIZE)
  161.             {    if (islower(*c))
  162.                     *o_ptr++ = toupper(*c);
  163.                 else
  164.                     *o_ptr++ = *c;
  165.             }
  166.         }
  167.  
  168.         while (*c && *c != '=' && *c != ',') c++;
  169.  
  170.         if (*c == '=')
  171.         {    c++;
  172.             while (*c && *c <= ' ') c++;
  173.  
  174.             for (cnt=0; *c && *c!=',' && !isspace(*c); cnt++, c++)
  175.             {    if (cnt < SUB_OPTION_SIZE)
  176.                     *s_ptr++ = *c;
  177.             }
  178.  
  179.             while (*c && *c != ',') c++;
  180.         }
  181.  
  182.         *o_ptr++ = NULL;
  183.         *s_ptr++ = NULL;
  184.  
  185.         db_file_1option(fh, option, sub_option);
  186.         if (db_error) return;
  187.     }
  188. }
  189.  
  190. /*
  191.  *    db_file_1option - Process one file option
  192.  */
  193.  
  194. db_file_1option(fh, option, sub_option)
  195.  FILE_HDR  fh;
  196.  char     *option, *sub_option;
  197. {
  198.     if (strcmp(option, "SEQ")==0)
  199.     {    if (fh->fh_file_type == 0)
  200.             fh->fh_file_type = DB_SEQ;
  201.         else
  202.             db_error = DB_FTYPE_ERROR;
  203.     }
  204.     else
  205.     if (strcmp(option, "RAN")==0)
  206.     {    if (fh->fh_file_type == 0)
  207.             fh->fh_file_type = DB_RANDOM;
  208.         else
  209.             db_error = DB_FTYPE_ERROR;
  210.     }
  211.     else
  212.     if (strcmp(option, "IDX")==0)
  213.     {    if (fh->fh_file_type == 0)
  214.             fh->fh_file_type = DB_INDEX;
  215.         else
  216.             db_error = DB_FTYPE_ERROR;
  217.     }
  218.     else
  219.     if (strcmp(option, "VAR")==0)
  220.     {    if (fh->fh_file_type == 0)
  221.             fh->fh_file_type = DB_VAR;
  222.         else
  223.             db_error = DB_FTYPE_ERROR;
  224.     }
  225.     else
  226.     if (strcmp(option, "BLK")==0)
  227.         fh->fh_block_size = atoi(sub_option);
  228.     else
  229.     if (strcmp(option, "REC")==0)
  230.         fh->fh_data_size = atoi(sub_option);
  231.     else
  232.     if (strcmp(option, "BASE")==0)
  233.         fh->fh_base_size = atoi(sub_option);
  234.     else
  235.     if (strcmp(option, "KEY")==0)
  236.         fh->fh_key_size = atoi(sub_option);
  237.     else
  238.     if (strcmp(option, "ATR")==0)
  239.         fh->fh_atr_size = atoi(sub_option);
  240.     else
  241.     if (strcmp(option, "MLINKS")==0)
  242.         fh->fh_mlink_cnt = atoi(sub_option);
  243.     else
  244.     if (strcmp(option, "OLINKS")==0)
  245.         fh->fh_olink_cnt = atoi(sub_option);
  246.     else
  247.     if (strcmp(option, "KLINKS")==0)
  248.         fh->fh_klink_cnt = atoi(sub_option);
  249.     else
  250.     if (strcmp(option, "DUPS")==0)
  251.         fh->fh_file_stat &= ~DB_DUP_ALLOWED;
  252.     else
  253.     if (strcmp(option, "NODUPS")==0)
  254.         fh->fh_file_stat |= DB_DUP_ALLOWED;
  255.     else
  256.         db_error = DB_INVALID_OPTION;
  257. }
  258.  
  259. /*
  260.  *      db_fhdr_create - Check file header data on create
  261.  */
  262.  
  263. void db_fhdr_create(fh)
  264.  FILE_HDR fh;
  265. {       short hdr_size;
  266.  
  267.         db_error = 0;
  268.  
  269.         fh->fh_db_version = DB_VERSION;
  270.  
  271.         if (fh->fh_file_type != DB_SEQ    &&
  272.             fh->fh_file_type != DB_RANDOM &&
  273.             fh->fh_file_type != DB_INDEX  &&
  274.             fh->fh_file_type != DB_VAR)
  275.         {       db_error = DB_INVALID_FHDR;
  276.                 return;
  277.         }
  278.  
  279. #ifndef SEQ
  280.         if (fh->fh_file_type == DB_SEQ)
  281.         {       db_error = DB_UNSUPP_FEATURE;
  282.                 return;
  283.         }
  284. #endif
  285.  
  286. #ifndef RAN
  287.         if (fh->fh_file_type == DB_RANDOM)
  288.         {       db_error = DB_UNSUPP_FEATURE;
  289.                 return;
  290.         }
  291. #endif
  292.  
  293. #ifndef IDX
  294.         if (fh->fh_file_type == DB_INDEX)
  295.         {       db_error = DB_UNSUPP_FEATURE;
  296.                 return;
  297.         }
  298. #endif
  299.  
  300. #ifndef VAR
  301.         if (fh->fh_file_type == DB_VAR)
  302.         {       db_error = DB_UNSUPP_FEATURE;
  303.                 return;
  304.         }
  305. #endif
  306.  
  307.     fh->fh_file_stat &= ~DB_OPEN;
  308.         fh->fh_last_block = 0;
  309.  
  310.         if (!fh->fh_block_size) fh->fh_block_size = 512;
  311.  
  312.         switch (fh->fh_file_type)
  313.         {       
  314. #ifdef SEQ
  315.         case DB_SEQ:
  316.                      hdr_size = 0;
  317.                      if (!fh->fh_ctl_size) fh->fh_ctl_size = 1;
  318.              if (fh->fh_ctl_size & 1) fh->fh_ctl_size++;
  319.                      break;
  320. #endif
  321.  
  322. #ifdef RAN
  323.                 case DB_RANDOM:
  324.                      hdr_size = sizeof(struct db_random_uhdr);
  325.                      if (!fh->fh_base_size)
  326.                      {       db_error = DB_INVALID_FHDR;
  327.                              return;
  328.                      }
  329.                      if (!fh->fh_ctl_size) fh->fh_ctl_size = 1;
  330.                      break;
  331. #endif
  332.  
  333. #ifdef IDX
  334.                 case DB_INDEX:
  335.                      if (!fh->fh_ctl_size) fh->fh_ctl_size = 2;
  336.                      hdr_size = sizeof(struct db_index_hdr) + fh->fh_ctl_size;
  337.                      break;
  338. #endif
  339.  
  340. #ifdef VAR
  341.                 case DB_VAR:
  342.                      hdr_size = 0;
  343.                      if (!fh->fh_ctl_size) fh->fh_ctl_size = sizeof(struct db_var_rec);
  344.              if (!fh->fh_data_size) fh->fh_data_size = 512;
  345.              fh->fh_block_size = fh->fh_ctl_size + fh->fh_data_size;
  346.              fh->fh_vfile_size = DB_FILE_HDR_SIZE;
  347.                      break;
  348. #endif
  349.  
  350.                 default:
  351.                      hdr_size = 0;
  352.                      break;
  353.         }
  354.  
  355.     fh->fh_ctl_size     = fh->fh_ctl_size 
  356.                 + fh->fh_olink_cnt * sizeof(struct db_owner_link)
  357.                 + fh->fh_mlink_cnt * sizeof(struct db_member_link)
  358.                 + fh->fh_klink_cnt * sizeof(struct db_key_link);
  359.  
  360.         fh->fh_rec_size     = fh->fh_ctl_size + fh->fh_data_size;
  361.  
  362.     if (fh->fh_file_type == DB_VAR)
  363.         fh->fh_block_size = fh->fh_rec_size;
  364.     else
  365.     if (fh->fh_file_type == DB_INDEX)
  366.     {    if (fh->fh_block_size < 2 * fh->fh_rec_size + hdr_size)
  367.             fh->fh_block_size = 2 * fh->fh_rec_size + hdr_size;
  368.  
  369.         fh->fh_block_size = ((fh->fh_block_size + 511) / 512) * 512;
  370.     }
  371.     else
  372.     {    if (fh->fh_block_size < fh->fh_rec_size + hdr_size)
  373.             fh->fh_block_size = fh->fh_rec_size + hdr_size;
  374.  
  375.         fh->fh_block_size = ((fh->fh_block_size + 511) / 512) * 512;
  376.     }
  377.  
  378.         fh->fh_rec_cnt      = 0;
  379.         fh->fh_recs_per_blk = (fh->fh_block_size - hdr_size) / fh->fh_rec_size;
  380.         fh->fh_root_ptr     = 0;
  381.         fh->fh_next_avail   = 0;
  382.  
  383.         if (fh->fh_key_size > fh->fh_data_size)
  384.         {       db_error = DB_INVALID_FHDR;
  385.                 return;
  386.         }
  387. }
  388.  
  389. /*
  390.  *      db_open  -  Open a Data File
  391.  */
  392.  
  393. DATA_FILE db_open(path,fname)
  394.  char *path, *fname;
  395. {
  396.         BUFFER   db_alloc_buf();
  397.         DATA_FILE df;
  398.         FILE_HDR fhdr;
  399.         char    *fname_dflts(), *calloc();
  400.         int      cnt;
  401.  
  402.         db_error = 0;
  403.         df = (DATA_FILE) calloc(1, sizeof(struct db_data_file));
  404.     if (!df)
  405.     {    db_error = DB_ALLOC_ERROR;
  406.         return(NULL);
  407.     }
  408.  
  409.         df->df_fhdr = db_alloc_buf(DB_FILE_HDR_SIZE);
  410.         fhdr        = (FILE_HDR) df->df_fhdr->buf_data;
  411.         if (db_error) { db_free_df(df); return(NULL); }
  412.             
  413.         strcpy(df->df_fname, fname_dflts(fname,path));
  414.  
  415. #ifdef MSC
  416.         df->df_fd = open(df->df_fname, O_RDWR|O_BINARY);
  417. #endif
  418. #ifdef TURBO
  419.         df->df_fd = open(df->df_fname, O_RDWR|O_BINARY);
  420. #endif
  421. #ifdef ULTRIX
  422.     df->df_fd = open(df->df_fname, O_RDWR);
  423. #endif
  424. #ifdef SYSV
  425.     df->df_fd = open(df->df_fname, O_RDWR);
  426. #endif
  427.         if (df->df_fd < 0)
  428.         {       db_error = DB_FILE_NOT_FOUND;
  429.                 db_free_df(df);
  430.                 return(NULL);
  431.         }
  432.                 
  433.         df->df_stat = DB_OPEN;
  434.  
  435.         db_get_blk(df, 0L, df->df_fhdr);
  436.         if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  437.         
  438.         switch (fhdr->fh_file_type)
  439.         { 
  440. #ifdef IDX
  441.       case DB_INDEX:
  442.              df->df_buf = db_alloc_buf(fhdr->fh_block_size+2*fhdr->fh_rec_size);
  443.          if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  444.  
  445.              df->df_tmp = db_alloc_buf(fhdr->fh_block_size+2*fhdr->fh_rec_size);
  446.          if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  447.  
  448.              df->df_aux = db_alloc_buf(fhdr->fh_block_size+2*fhdr->fh_rec_size);
  449.          if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  450.  
  451.              df->df_buf->buf_size = fhdr->fh_block_size;
  452.              df->df_tmp->buf_size = fhdr->fh_block_size;
  453.              df->df_aux->buf_size = fhdr->fh_block_size;
  454.          break;
  455. #endif
  456.  
  457. #ifdef RAN
  458.           case DB_RANDOM:
  459.              df->df_buf = db_alloc_buf(fhdr->fh_block_size);
  460.          if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  461.  
  462.              df->df_tmp = db_alloc_buf(fhdr->fh_block_size);
  463.          if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  464.          break;
  465. #endif
  466.  
  467. #ifdef SEQ
  468.           case DB_SEQ:
  469.              df->df_buf = db_alloc_buf(fhdr->fh_block_size);
  470.          if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  471.          break;
  472. #endif
  473.  
  474. #ifdef VAR
  475.       case DB_VAR:
  476.              df->df_buf = db_alloc_buf(fhdr->fh_block_size);
  477.          if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  478.          break;
  479. #endif
  480.     }
  481.  
  482.         db_fhdr_open(fhdr);
  483.          if (db_error) { close(df->df_fd); db_free_df(df); return(NULL); }
  484.  
  485.         return(df);
  486. }
  487.  
  488. /*
  489.  *      db_fhdr_open - Check file header data on open
  490.  */
  491.  
  492. void db_fhdr_open(fh)
  493.  FILE_HDR fh;
  494. {
  495.         db_error = 0;
  496.  
  497.     if (fh->fh_db_version == 12)
  498.         fh->fh_db_version = 13;
  499.         /* Upgrade shouldn't change data (we hope) */
  500.  
  501.         if (fh->fh_db_version != DB_VERSION)
  502.         {       db_error = DB_VERSION_ERROR;
  503.                 return;
  504.         }
  505.  
  506.         if (fh->fh_file_type != DB_SEQ    &&
  507.             fh->fh_file_type != DB_RANDOM &&
  508.             fh->fh_file_type != DB_INDEX  &&
  509.             fh->fh_file_type != DB_VAR)
  510.         {       db_error = DB_INVALID_FHDR;
  511.                 return;
  512.         }
  513.  
  514. #ifndef SEQ
  515.         if (fh->fh_file_type == DB_SEQ)
  516.         {       db_error = DB_UNSUPP_FEATURE;
  517.                 return;
  518.         }
  519. #endif
  520.  
  521. #ifndef RAN
  522.         if (fh->fh_file_type == DB_RANDOM)
  523.         {       db_error = DB_UNSUPP_FEATURE;
  524.                 return;
  525.         }
  526. #endif
  527.  
  528. #ifndef IDX
  529.         if (fh->fh_file_type == DB_INDEX)
  530.         {       db_error = DB_UNSUPP_FEATURE;
  531.                 return;
  532.         }
  533. #endif
  534.  
  535. #ifndef VAR
  536.         if (fh->fh_file_type == DB_VAR)
  537.         {       db_error = DB_UNSUPP_FEATURE;
  538.                 return;
  539.         }
  540. #endif
  541.  
  542.         if (fh->fh_block_size   == 0 ||
  543.             fh->fh_rec_size     == 0 ||
  544.             fh->fh_recs_per_blk == 0)
  545.         {       db_error = DB_INVALID_FHDR;
  546.                 return;
  547.         }
  548.  
  549.         if (fh->fh_rec_size != fh->fh_ctl_size + fh->fh_data_size)
  550.         {       db_error = DB_INVALID_FHDR;
  551.                 return;
  552.         }
  553.  
  554.         if (fh->fh_key_size > fh->fh_data_size)
  555.         {       db_error = DB_INVALID_FHDR;
  556.                 return;
  557.         }
  558.  
  559.         if (fh->fh_file_type == DB_RANDOM &&
  560.             fh->fh_base_size == 0)
  561.         {       db_error = DB_INVALID_FHDR;
  562.                 return;
  563.         }
  564. }
  565.  
  566. /*
  567.  *      db_close  -  close a data set
  568.  */
  569.  
  570. DATA_FILE db_close(df)
  571.  DATA_FILE df;
  572. {
  573.         db_error = 0;
  574.  
  575.         db_check_df(df);
  576.     if (db_error) return(NULL);
  577.  
  578.         db_put_blk(df, df->df_fhdr);
  579.     if (db_error) return(NULL);
  580.  
  581.         close(df->df_fd);
  582.  
  583.         db_free_df(df);
  584.  
  585.         return(NULL);
  586. }
  587.  
  588. /*
  589.  *      db_add  -  Add a new record to a data set
  590.  */
  591.  
  592. ulong db_add(df, user_data, data_size)
  593.  DATA_FILE df;
  594.  char *user_data;
  595.  int data_size;
  596. {
  597.         FILE_HDR fh;
  598.         BUFFER  buf;
  599.         ulong   rec_no;
  600.  
  601.         db_error = 0;
  602.  
  603.         db_check_df(df);
  604.         if (db_error) return(0);
  605.  
  606.         fh  = (FILE_HDR) df->df_fhdr->buf_data;
  607.         buf = (BUFFER) df->df_buf;
  608.  
  609.         switch (fh->fh_file_type)
  610.         {       
  611. #ifdef SEQ
  612.         case DB_SEQ:
  613.                         db_add_seq(df, user_data);
  614.                         break;
  615. #endif
  616.  
  617. #ifdef IDX
  618.                 case DB_INDEX:
  619.                         db_add_idx(df, user_data);
  620.                         break;
  621. #endif
  622.  
  623. #ifdef RAN
  624.                 case DB_RANDOM:
  625.                         db_add_ran(df, user_data);
  626.                         break;
  627. #endif
  628.  
  629. #ifdef VAR
  630.         case DB_VAR:
  631.             db_add_var(df, user_data, data_size);
  632.             break;
  633. #endif
  634.  
  635.                 default:
  636.                         db_error = DB_INVALID_REQUEST;
  637.                         break;
  638.         }
  639.  
  640.         if (db_error) return(0);
  641.  
  642.     if (fh->fh_file_type == DB_VAR)
  643.         rec_no = db_add_blk;
  644.     else
  645.             rec_no = (db_add_blk - 1) * fh->fh_recs_per_blk + db_add_rec;
  646.  
  647.         buf->buf_cur_blk = 0;
  648.         buf->buf_rec_inx = 0;
  649.  
  650.         return(rec_no);
  651. }
  652.  
  653. /*
  654.  *      db_read_first  -  Read First Record in a data set
  655.  */
  656.  
  657. void db_read_first(df, user_data, data_size)
  658.  DATA_FILE df;
  659.  char *user_data;
  660.  int  *data_size;
  661. {
  662.         FILE_HDR  fh;
  663.         BUFFER   buf;
  664.  
  665.         db_error = 0;
  666.  
  667.         db_check_df(df);
  668.         if (db_error) return;
  669.  
  670.         fh  = (FILE_HDR) df->df_fhdr->buf_data;
  671.         buf = (BUFFER) df->df_buf;
  672.  
  673.         if (!fh->fh_rec_cnt)
  674.         {       db_error = DB_END_OF_FILE;
  675.                 return;
  676.         }
  677.  
  678.         switch (fh->fh_file_type)
  679.         {       
  680. #ifdef SEQ
  681.         case DB_SEQ:
  682.                         db_read_first_seq(df, user_data);
  683.                         break;
  684. #endif
  685.  
  686. #ifdef IDX
  687.                 case DB_INDEX:
  688.                         db_read_first_idx(df, fh->fh_root_ptr, user_data);
  689.                         break;
  690. #endif
  691.  
  692. #ifdef RAN
  693.                 case DB_RANDOM:
  694.                         db_read_first_ran(df, user_data);
  695.                         break;
  696. #endif
  697.  
  698. #ifdef VAR
  699.         case DB_VAR:
  700.             db_read_first_var(df, user_data, data_size);
  701.             break;
  702. #endif
  703.  
  704.                 default:
  705.                         db_error = DB_INVALID_REQUEST;
  706.                         break;
  707.         }
  708.  
  709.         if (db_error)
  710.         {       buf->buf_cur_blk  = 0;
  711.                 buf->buf_rec_inx  = 0;
  712.         buf->buf_cur_size = 0;
  713.         }
  714.  
  715.         df->df_prev_blk   = buf->buf_cur_blk;
  716.         df->df_prev_rec   = buf->buf_rec_inx;
  717.     df->df_prev_vsize = buf->buf_cur_size;
  718.  
  719.     return;
  720. }
  721.  
  722. /*
  723.  *      db_read_next  -  Read next record from a data set
  724.  */
  725.  
  726. void db_read_next(df, user_data, data_size)
  727.  DATA_FILE df;
  728.  char *user_data;
  729.  int  *data_size;
  730. {
  731.         FILE_HDR  fh;
  732.         BUFFER   buf;
  733.  
  734.         db_error = 0;
  735.  
  736.         db_check_df(df);
  737.         if (db_error) return;
  738.  
  739.         fh  = (FILE_HDR) df->df_fhdr->buf_data;
  740.         buf = (BUFFER) df->df_buf;
  741.  
  742.         if (!fh->fh_rec_cnt)
  743.         {       db_error = DB_END_OF_FILE;
  744.                 return;
  745.         }
  746.  
  747.         if (!df->df_prev_blk)
  748.         {       db_error = DB_NO_CURRENT_REC;
  749.                 return;
  750.         }
  751.  
  752.         switch (fh->fh_file_type)
  753.         {       
  754. #ifdef SEQ
  755.         case DB_SEQ:
  756.                         db_read_next_seq(df, user_data);
  757.                         break;
  758. #endif
  759.  
  760. #ifdef IDX
  761.                 case DB_INDEX:
  762.                         db_read_next_idx(df, user_data);
  763.                         break;
  764. #endif
  765.                               
  766. #ifdef RAN
  767.                 case DB_RANDOM:
  768.                         db_read_next_ran(df, user_data);
  769.                         break;
  770. #endif
  771.  
  772. #ifdef VAR
  773.         case DB_VAR:
  774.             db_read_next_var(df, user_data, data_size);
  775.             break;
  776. #endif
  777.  
  778.                 default:
  779.                         db_error = DB_INVALID_REQUEST;
  780.                         break;
  781.         }
  782.  
  783.         if (db_error)
  784.         {       buf->buf_cur_blk  = 0;
  785.                 buf->buf_rec_inx  = 0;
  786.         buf->buf_cur_size = 0;
  787.         }
  788.  
  789.         df->df_prev_blk   = buf->buf_cur_blk;
  790.         df->df_prev_rec   = buf->buf_rec_inx;
  791.     df->df_prev_vsize = buf->buf_cur_size;
  792.  
  793.     return;
  794. }
  795.  
  796. /*
  797.  *    db_read_last  -  Read Last Record in a data set
  798.  */
  799.  
  800. void db_read_last(df, user_data, data_size)
  801.  DATA_FILE df;
  802.  char *user_data;
  803.  int  *data_size;
  804. {
  805.         FILE_HDR  fh;
  806.         BUFFER   buf;
  807.  
  808.         db_error = 0;
  809.  
  810.         db_check_df(df);
  811.         if (db_error) return;
  812.  
  813.         fh  = (FILE_HDR) df->df_fhdr->buf_data;
  814.         buf = (BUFFER) df->df_buf;
  815.  
  816.         if (!fh->fh_rec_cnt)
  817.         {       db_error = DB_END_OF_FILE;
  818.                 return;
  819.         }
  820.  
  821.         switch (fh->fh_file_type)
  822.         {       
  823. #ifdef SEQ
  824.         case DB_SEQ:
  825.             db_read_last_seq(df, user_data);
  826.                         break;
  827. #endif
  828.  
  829. #ifdef IDX
  830.                 case DB_INDEX:
  831.             db_read_last_idx(df, fh->fh_root_ptr, user_data);
  832.                         break;
  833. #endif
  834.  
  835. #ifdef RAN
  836.                 case DB_RANDOM:
  837.             db_read_last_ran(df, user_data);
  838.                         break;
  839. #endif
  840.  
  841. #ifdef VAR
  842.                 case DB_VAR:
  843.             db_read_last_var(df, user_data, data_size);
  844.                         break;
  845. #endif
  846.  
  847.                 default:
  848.                         db_error = DB_INVALID_REQUEST;
  849.                         break;
  850.         }
  851.  
  852.         if (db_error)
  853.         {       buf->buf_cur_blk  = 0;
  854.                 buf->buf_rec_inx  = 0;
  855.         buf->buf_cur_size = 0;
  856.         }
  857.  
  858.         df->df_prev_blk   = buf->buf_cur_blk;
  859.         df->df_prev_rec   = buf->buf_rec_inx;
  860.     df->df_prev_vsize = buf->buf_cur_size;
  861.  
  862.     return;
  863. }
  864.  
  865. /*
  866.  *    db_read_prev  -  Read prev record from a data set
  867.  */
  868.  
  869. void db_read_prev(df, user_data, data_size)
  870.  DATA_FILE df;
  871.  char *user_data;
  872.  int  *data_size;
  873. {
  874.         FILE_HDR  fh;
  875.         BUFFER   buf;
  876.  
  877.         db_error = 0;
  878.  
  879.         db_check_df(df);
  880.         if (db_error) return;
  881.  
  882.         fh  = (FILE_HDR) df->df_fhdr->buf_data;
  883.         buf = (BUFFER) df->df_buf;
  884.  
  885.         if (!fh->fh_rec_cnt)
  886.         {       db_error = DB_END_OF_FILE;
  887.                 return;
  888.         }
  889.  
  890.         if (!df->df_prev_blk)
  891.         {       db_error = DB_NO_CURRENT_REC;
  892.                 return;
  893.         }
  894.  
  895.         switch (fh->fh_file_type)
  896.         {       
  897. #ifdef SEQ
  898.         case DB_SEQ:
  899.             db_read_prev_seq(df, user_data);
  900.                         break;
  901. #endif
  902.  
  903. #ifdef IDX
  904.                 case DB_INDEX:
  905.             db_read_prev_idx(df, user_data);
  906.                         break;
  907. #endif
  908.                               
  909. #ifdef RAN
  910.                 case DB_RANDOM:
  911.             db_read_prev_ran(df, user_data);
  912.                         break;
  913. #endif
  914.  
  915. #ifdef VAR
  916.                 case DB_VAR:
  917.             db_read_prev_var(df, user_data, data_size);
  918.                         break;
  919. #endif
  920.  
  921.                 default:
  922.                         db_error = DB_INVALID_REQUEST;
  923.                         break;
  924.         }
  925.  
  926.         if (db_error)
  927.         {       buf->buf_cur_blk  = 0;
  928.                 buf->buf_rec_inx  = 0;
  929.         buf->buf_cur_size = 0;
  930.         }
  931.  
  932.         df->df_prev_blk   = buf->buf_cur_blk;
  933.         df->df_prev_rec   = buf->buf_rec_inx;
  934.     df->df_prev_vsize = buf->buf_cur_size;
  935.  
  936.     return;
  937. }
  938.  
  939. /*
  940.  *      db_find  -  Find a Record
  941.  */
  942.  
  943. void db_find(df, user_data, key, key_size)
  944.  DATA_FILE df;
  945.  char *user_data;
  946.  char *key;
  947.  int   key_size;
  948. {
  949.         FILE_HDR  fh;
  950.         BUFFER   buf;
  951.  
  952.         db_error = 0;
  953.  
  954.         db_check_df(df);
  955.         if (db_error) return;
  956.  
  957.         fh  = (FILE_HDR) df->df_fhdr->buf_data;
  958.         buf = (BUFFER) df->df_buf;
  959.  
  960.         if (!fh->fh_rec_cnt)
  961.         {       db_error = DB_REC_NOT_FOUND;
  962.                 return;
  963.         }
  964.  
  965.         if (!key_size) key_size = fh->fh_key_size;
  966.  
  967.         switch (fh->fh_file_type)
  968.         {
  969. #ifdef IDX
  970.                 case DB_INDEX:
  971.                         db_find_first_idx(df, user_data, key, key_size);
  972.                         break;
  973. #endif
  974.  
  975. #ifdef RAN
  976.                 case DB_RANDOM:
  977.                         db_find_ran(df, user_data, key);
  978.                         break;
  979. #endif
  980.  
  981.                 default:
  982.                         db_error = DB_INVALID_REQUEST;
  983.                         break;
  984.         }
  985.  
  986.         if (db_error)
  987.         {       buf->buf_cur_blk = 0;
  988.                 buf->buf_rec_inx = 0;
  989.         }
  990.  
  991.         df->df_prev_blk = buf->buf_cur_blk;
  992.         df->df_prev_rec = buf->buf_rec_inx;
  993.  
  994.     return;
  995. }
  996.  
  997. /*
  998.  *      db_update  -  Update a record from a data set
  999.  */
  1000.  
  1001. void db_update(df, user_data)
  1002.  DATA_FILE df;
  1003.  char *user_data;
  1004. {
  1005.         FILE_HDR  fh;
  1006.         BUFFER   buf;
  1007.  
  1008.         db_error = 0;
  1009.  
  1010.         db_check_df(df);
  1011.         if (db_error) return;
  1012.  
  1013.         fh  = (FILE_HDR) df->df_fhdr->buf_data;
  1014.         buf = (BUFFER) df->df_buf;
  1015.  
  1016.         if (!buf->buf_cur_blk)
  1017.         {       db_error = DB_NO_CURRENT_REC;
  1018.                 return;
  1019.         }
  1020.  
  1021.         switch (fh->fh_file_type)
  1022.         {       
  1023. #ifdef SEQ
  1024.         case DB_SEQ:
  1025.                         db_update_seq(df, user_data);
  1026.                         break;
  1027. #endif
  1028.  
  1029. #ifdef RAN
  1030.                 case DB_RANDOM:
  1031.                         db_update_ran(df, user_data);
  1032.                         break;
  1033. #endif
  1034.  
  1035. #ifdef IDX
  1036.                 case DB_INDEX:
  1037.                         db_update_idx(df, user_data);
  1038.                         break;
  1039. #endif
  1040.  
  1041. #ifdef VAR
  1042.                 case DB_VAR:
  1043.                         db_update_var(df, user_data);
  1044.                         break;
  1045. #endif
  1046.  
  1047.                 default:
  1048.                         db_error = DB_INVALID_REQUEST;
  1049.                         break;
  1050.         }
  1051.  
  1052.         buf->buf_cur_blk = 0;
  1053.         buf->buf_rec_inx = 0;
  1054.  
  1055.     return;
  1056. }
  1057.  
  1058. /*
  1059.  *      db_delete  -  Delete a record from a data set
  1060.  */
  1061.  
  1062. void db_delete(df)
  1063.  DATA_FILE df;
  1064. {
  1065.         FILE_HDR  fh;
  1066.         BUFFER   buf;
  1067.  
  1068.         db_error = 0;
  1069.  
  1070.         db_check_df(df);
  1071.         if (db_error) return;
  1072.  
  1073.         fh  = (FILE_HDR) df->df_fhdr->buf_data;
  1074.         buf = (BUFFER) df->df_buf;
  1075.  
  1076.         if (!buf->buf_cur_blk)
  1077.         {       db_error = DB_NO_CURRENT_REC;
  1078.                 return;
  1079.         }
  1080.  
  1081.         switch (fh->fh_file_type)
  1082.         {       
  1083. #ifdef SEQ
  1084.         case DB_SEQ:
  1085.                         db_free_rec(df, buf);
  1086.                         if (db_error) return;
  1087.  
  1088.                         if (fh->fh_rec_cnt > 0) fh->fh_rec_cnt--;
  1089.                         db_put_blk(df, df->df_fhdr);
  1090.                         break;
  1091. #endif
  1092.  
  1093. #ifdef IDX
  1094.                 case DB_INDEX:
  1095.                         db_delete_idx(df);
  1096.                         break;
  1097. #endif
  1098.  
  1099. #ifdef RAN
  1100.                 case DB_RANDOM:
  1101.                         db_delete_ran(df);
  1102.                         break;
  1103. #endif
  1104.  
  1105. #ifdef VAR
  1106.         case DB_VAR:
  1107.             db_delete_var(df);
  1108.             break;
  1109. #endif
  1110.  
  1111.                 default:
  1112.                         db_error = DB_INVALID_REQUEST;
  1113.                         break;
  1114.         }
  1115.  
  1116.         buf->buf_cur_blk = 0;
  1117.         buf->buf_rec_inx = 0;
  1118.  
  1119.     return;
  1120. }
  1121.  
  1122. /*
  1123.  *      db_get_rec_no  -  Get relative record number
  1124.  */
  1125.  
  1126. ulong db_get_rec_no(df)
  1127.  DATA_FILE df;
  1128. {
  1129.         FILE_HDR  fh;
  1130.         BUFFER   buf;
  1131.  
  1132.         db_error = 0;
  1133.  
  1134.         db_check_df(df);
  1135.         if (db_error) return(0);
  1136.  
  1137.         fh  = (FILE_HDR) df->df_fhdr->buf_data;
  1138.         buf = df->df_buf;
  1139.  
  1140.         if (!buf->buf_cur_blk)
  1141.         {       db_error = DB_NO_CURRENT_REC;
  1142.                 return(0);
  1143.         }
  1144.  
  1145.     if (fh->fh_file_type == DB_VAR)
  1146.         return(buf->buf_cur_blk + buf->buf_rec_inx);
  1147.     else
  1148.             return((long)(buf->buf_cur_blk - 1) * fh->fh_recs_per_blk
  1149.                                                     + buf->buf_rec_inx);
  1150. }
  1151.  
  1152. /*
  1153.  *      db_read_direct  -  Read a record by number
  1154.  */                                               
  1155.  
  1156. void db_read_direct(df, rec_no, user_data, data_size)
  1157.  DATA_FILE     df;
  1158.  ulong    rec_no;
  1159.  char  *user_data;
  1160.  int   *data_size;
  1161. {
  1162.         FILE_HDR    fh;
  1163.         BUFFER      buf;
  1164.         INDEX_HDR   ihdr;
  1165.         RANDOM_HDR  rhdr;
  1166.         RANDOM_REC  rrec;
  1167.         SEQ_REC     seq;
  1168.     VAR_REC     vrec;
  1169.         ulong       blk;
  1170.         ushort      rec;
  1171.         char       *rbuf;
  1172.  
  1173.         db_error = 0;
  1174.                                        
  1175.         db_check_df(df);
  1176.     if (db_error) return;
  1177.  
  1178.         fh  = (FILE_HDR) df->df_fhdr->buf_data;
  1179.         buf = df->df_buf;
  1180.  
  1181.         buf->buf_cur_blk = 0;
  1182.         buf->buf_rec_inx = 0;
  1183.  
  1184.     if (fh->fh_file_type == DB_VAR)
  1185.     {    rec = 0;
  1186.         blk = rec_no;
  1187.     }
  1188.     else
  1189.         {    blk = rec_no / fh->fh_recs_per_blk;
  1190.             rec = rec_no % fh->fh_recs_per_blk;
  1191.  
  1192.                if (rec == 0)
  1193.                     rec = fh->fh_recs_per_blk;
  1194.             else
  1195.                        blk++;
  1196.     }
  1197.  
  1198.         db_get_blk(df, blk, buf);
  1199.     if (db_error) return;
  1200.  
  1201.         switch (fh->fh_file_type)
  1202.         {       
  1203. #ifdef SEQ
  1204.         case DB_SEQ:
  1205.                         rbuf = buf->buf_data + (rec-1) * fh->fh_rec_size;
  1206.                         seq  = (SEQ_REC) rbuf;
  1207.                         
  1208.                         if (seq->seq_stat != DB_INUSE)
  1209.                         {       db_error = DB_DELETED_REC;
  1210.                 return;
  1211.                         }
  1212.                         break;
  1213. #endif
  1214.  
  1215. #ifdef IDX
  1216.                 case DB_INDEX:
  1217.                         ihdr = (INDEX_HDR) buf->buf_data;
  1218.                         
  1219.                         if (ihdr->idx_stat != DB_INUSE)
  1220.                         {       db_error = DB_DELETED_REC;
  1221.                 return;
  1222.                         }
  1223.  
  1224.                         if (rec > ihdr->idx_rec_cnt)
  1225.                         {       db_error = DB_DELETED_REC;
  1226.                 return;
  1227.                         }
  1228.  
  1229.                         rbuf = buf->buf_data + sizeof(struct db_index_hdr)
  1230.                                                 + (rec - 1) * fh->fh_rec_size;
  1231.                         break;
  1232. #endif
  1233.  
  1234. #ifdef RAN
  1235.                 case DB_RANDOM:
  1236.                         rhdr = (RANDOM_HDR) buf->buf_data;
  1237.                         
  1238.                         if (rhdr->ran_stat != DB_INUSE)
  1239.                         {       db_error = DB_DELETED_REC;
  1240.                 return;
  1241.                         }
  1242.  
  1243.                         if (rec > rhdr->ran_rec_cnt)
  1244.                         {       db_error = DB_DELETED_REC;
  1245.                 return;
  1246.                         }
  1247.  
  1248.                         rbuf = buf->buf_data + sizeof(struct db_random_uhdr)
  1249.                                                 + (rec - 1) * fh->fh_rec_size;
  1250.  
  1251.                         rrec = (RANDOM_REC) rbuf;
  1252.                         if (rrec->ran_stat != DB_INUSE)
  1253.                         {       db_error = DB_DELETED_REC;
  1254.                 return;
  1255.                         }
  1256.                         break;
  1257. #endif
  1258.  
  1259. #ifdef VAR
  1260.         case DB_VAR:
  1261.             db_var_chk_csum(buf);
  1262.             if (db_error) return;
  1263.  
  1264.             vrec = (VAR_REC)(buf->buf_data + buf->buf_rec_inx);
  1265.  
  1266.             if (vrec->var_stat != DB_INUSE)
  1267.                         {       db_error = DB_DELETED_REC;
  1268.                 return;
  1269.                         }
  1270.             *data_size = vrec->var_dsize;
  1271.             buf->buf_cur_size = vrec->var_dsize
  1272.                           + sizeof(struct db_var_rec);
  1273.             break;
  1274. #endif
  1275.  
  1276.                 default:
  1277.                         db_error = DB_INVALID_REQUEST;
  1278.             return;
  1279.         }
  1280.     if (fh->fh_file_type == DB_VAR)
  1281.         memcpy(user_data, vrec->var_data, vrec->var_dsize);
  1282.     else
  1283.             memcpy(user_data, rbuf + fh->fh_ctl_size, fh->fh_data_size);
  1284.  
  1285.         df->df_prev_blk   = buf->buf_cur_blk = blk;
  1286.         df->df_prev_rec   = buf->buf_rec_inx = rec;
  1287.     df->df_prev_vsize = buf->buf_cur_size;
  1288.  
  1289.     return;
  1290. }
  1291.  
  1292. /*
  1293.  *      db_reorg  -  Reorganize a File
  1294.  */
  1295.  
  1296. void db_reorg(df)
  1297.  DATA_FILE df;
  1298. {
  1299.         FILE_HDR  fh;
  1300.         BUFFER   buf;
  1301.  
  1302.         db_error = 0;
  1303.  
  1304.         db_check_df(df);
  1305.         if (db_error) return;
  1306.  
  1307.         fh  = (FILE_HDR) df->df_fhdr->buf_data;
  1308.         buf = (BUFFER) df->df_buf;
  1309.  
  1310.         switch (fh->fh_file_type)
  1311.         {
  1312. #ifdef VAR
  1313.          case DB_VAR:
  1314.             db_reorg_var(df);
  1315.             break;
  1316. #endif
  1317.  
  1318.                 default:
  1319.                         db_error = DB_INVALID_REQUEST;
  1320.                         break;
  1321.         }
  1322.  
  1323.         buf->buf_cur_blk = 0;
  1324.         buf->buf_rec_inx = 0;
  1325.  
  1326.     return;
  1327. }
  1328.  
  1329. /*
  1330.  *      db_read_atr  - Read Data File Attribute Block
  1331.  */
  1332.  
  1333. void db_read_atr(df, user_data)
  1334.  DATA_FILE df;
  1335.  char  *user_data;
  1336. {        
  1337.         FILE_HDR fh;
  1338.     char    *atr_data;
  1339.  
  1340.  
  1341.         db_error = 0;
  1342.  
  1343.         db_check_df(df);
  1344.         if (db_error) return;
  1345.  
  1346.         fh = (FILE_HDR) df->df_fhdr->buf_data;
  1347.  
  1348.     atr_data = ((char *)fh) + DB_ATR_OFFSET;
  1349.         memcpy(user_data, atr_data, fh->fh_atr_size);
  1350.  
  1351.     return;
  1352. }
  1353.  
  1354. /*
  1355.  *      db_update_atr  - Update Data File Attribute Block
  1356.  */
  1357.  
  1358. void db_update_atr(df, user_data)
  1359.  DATA_FILE df;
  1360.  char  *user_data;
  1361. {
  1362.         FILE_HDR fh;
  1363.     char    *atr_data;
  1364.  
  1365.         db_error = 0;
  1366.  
  1367.         db_check_df(df);
  1368.         if (db_error) return;
  1369.  
  1370.         fh = (FILE_HDR) df->df_fhdr->buf_data;
  1371.  
  1372.     atr_data = ((char *)fh) + DB_ATR_OFFSET;
  1373.         memcpy(atr_data, user_data, fh->fh_atr_size);
  1374.  
  1375.         db_put_blk(df, df->df_fhdr);
  1376.  
  1377.     return;
  1378. }
  1379.  
  1380. /*
  1381.  *      db_check_df  -  Common checks on Data File Validity
  1382.  */                                                       
  1383.  
  1384. void db_check_df(df)
  1385.  DATA_FILE df;
  1386. {
  1387.         FILE_HDR fh;
  1388.  
  1389.         db_error = 0;
  1390.  
  1391.         if (!df)
  1392.         {       db_error = DB_FILE_NOT_OPEN;
  1393.                 return;
  1394.         }
  1395.  
  1396.         if (!df->df_stat & DB_OPEN)
  1397.         {       db_error = DB_FILE_NOT_OPEN;
  1398.                 return;
  1399.         }
  1400.  
  1401.         if (!df->df_fhdr || !df->df_buf)
  1402.         {       db_error = DB_BUFFER_ERROR;
  1403.                 return;
  1404.         }
  1405.  
  1406.         fh = (FILE_HDR) df->df_fhdr->buf_data;
  1407.  
  1408.         if (fh->fh_file_type == DB_INDEX)
  1409.                 if (!df->df_tmp || !df->df_aux)
  1410.                 {       db_error = DB_BUFFER_ERROR;
  1411.                         return;
  1412.                 }
  1413. }
  1414.  
  1415. /*
  1416.  *      db_extend  -  Extend a data set by 1 Block
  1417.  */
  1418.  
  1419. void db_extend(df, buf)
  1420.  DATA_FILE df;
  1421.  BUFFER   buf;
  1422. {
  1423.         FILE_HDR  fhdr;
  1424.         long       rec;
  1425.         char        *c;
  1426.         FREE_REC   fre;
  1427.         RANDOM_HDR ran;
  1428.         SEQ_REC    seq;
  1429.         int        cnt;
  1430.  
  1431.  
  1432.         fhdr                = (FILE_HDR) df->df_fhdr->buf_data;
  1433.         buf                 = df->df_buf;
  1434.         fhdr->fh_last_block = fhdr->fh_last_block + 1;
  1435.         buf->buf_cur_blk    = fhdr->fh_last_block;
  1436.         buf->buf_cur_size   = fhdr->fh_block_size;
  1437.  
  1438.         memset(buf->buf_data, 0, buf->buf_cur_size);
  1439.  
  1440.         switch(fhdr->fh_file_type)
  1441.         {       
  1442. #ifdef SEQ
  1443.         case DB_SEQ:     
  1444.                         rec = buf->buf_cur_blk * fhdr->fh_recs_per_blk;
  1445.                         c   = buf->buf_data + (fhdr->fh_recs_per_blk - 1)
  1446.                                                         * fhdr->fh_rec_size;
  1447.  
  1448.                         for (cnt=0; cnt < fhdr->fh_recs_per_blk; cnt++)
  1449.                         {       fre                 = (FREE_REC) c;
  1450.                                 fre->fre_stat       = DB_FREE;
  1451.                                 fre->fre_next       = fhdr->fh_next_avail;
  1452.                                 fhdr->fh_next_avail = rec--;
  1453.                                 c                  -= fhdr->fh_rec_size;
  1454.                         }
  1455.                         break;
  1456. #endif
  1457.  
  1458. #ifdef RAN
  1459.                 case DB_RANDOM:
  1460.                         c = buf->buf_data + sizeof(struct db_random_uhdr);
  1461.                         for (cnt=0; cnt < fhdr->fh_recs_per_blk; cnt++)
  1462.                         {       *c  = DB_FREE;
  1463.                                  c += fhdr->fh_rec_size;
  1464.                         }
  1465.                         if (buf->buf_cur_blk <= fhdr->fh_base_size)
  1466.                         {       ran = (RANDOM_HDR) buf->buf_data;
  1467.                                 ran->ran_stat    = DB_INUSE;
  1468.                                 ran->ran_next    = 0;
  1469.                                 ran->ran_rec_cnt = 0;
  1470.                         }
  1471.                         else
  1472.                         {       fre = (FREE_REC) buf->buf_data;
  1473.                                 fre->fre_stat = DB_FREE;
  1474.                                 fre->fre_next = fhdr->fh_next_avail;
  1475.                                 fhdr->fh_next_avail = buf->buf_cur_blk;
  1476.                         }
  1477.                         break;
  1478. #endif
  1479.  
  1480. #ifdef IDX
  1481.                 case DB_INDEX:
  1482.                         fre = (FREE_REC) buf->buf_data;
  1483.                         fre->fre_stat = DB_FREE;               
  1484.                         fre->fre_next = fhdr->fh_next_avail;
  1485.                         fhdr->fh_next_avail = buf->buf_cur_blk;
  1486.                         break;
  1487. #endif
  1488.         }
  1489.  
  1490.         db_put_blk(df,df->df_buf);
  1491.         db_put_blk(df,df->df_fhdr);
  1492. }
  1493.  
  1494. /*
  1495.  *      db_get_next_avail  -  Get Next Available Block
  1496.  */
  1497.  
  1498. void db_get_next_avail(df, buf)
  1499.  DATA_FILE df;
  1500.  BUFFER  buf;
  1501. {
  1502.         FILE_HDR     fh;
  1503.         FREE_REC    fre;
  1504.         RANDOM_HDR rhdr;
  1505.         INDEX_HDR  ihdr;
  1506.         ulong       blk;
  1507.         ushort      rec;
  1508.         char      *rbuf;
  1509.  
  1510.         db_error = 0;
  1511.  
  1512.         fh  = (FILE_HDR) df->df_fhdr->buf_data;
  1513.  
  1514.         if (!fh->fh_next_avail)
  1515.         {       db_extend(df, buf);
  1516.                 if (db_error) return;
  1517.         }
  1518.  
  1519.         if (fh->fh_file_type == DB_SEQ)
  1520.         {       blk = fh->fh_next_avail / fh->fh_recs_per_blk;
  1521.                 rec = fh->fh_next_avail % fh->fh_recs_per_blk;
  1522.  
  1523.                 if (rec==0)
  1524.                         rec = fh->fh_recs_per_blk;
  1525.                 else
  1526.                         blk++;
  1527.         }
  1528.         else
  1529.         {       blk = fh->fh_next_avail;
  1530.                 rec = 1;
  1531.         }
  1532.  
  1533.         db_get_blk(df, blk, buf);
  1534.         if (db_error) return;
  1535.  
  1536.         buf->buf_rec_inx = rec;
  1537.         rbuf = buf->buf_data + (rec - 1) * fh->fh_rec_size;
  1538.  
  1539.         fre = (FREE_REC) rbuf;
  1540.         if (fre->fre_stat != DB_FREE)
  1541.         {       db_error = DB_INVALID_FREE;
  1542.                 return;
  1543.         }
  1544.  
  1545.         fre->fre_stat     = DB_INUSE;
  1546.         fh->fh_next_avail = fre->fre_next;
  1547.  
  1548.         if (fh->fh_file_type == DB_INDEX)
  1549.                 if (!fh->fh_root_ptr)
  1550.                         fh->fh_root_ptr = blk;
  1551.  
  1552.         switch (fh->fh_file_type)
  1553.         {       
  1554. #ifdef SEQ
  1555.         case DB_SEQ:
  1556.                         break;
  1557. #endif
  1558.  
  1559. #ifdef RAN
  1560.                 case DB_RANDOM:
  1561.                         rhdr = (RANDOM_HDR) rbuf;
  1562.                         rhdr->ran_next = 0;
  1563.                         rhdr->ran_rec_cnt = 0;
  1564.                         break;
  1565. #endif
  1566.  
  1567. #ifdef IDX
  1568.                 case DB_INDEX:
  1569.                         ihdr = (INDEX_HDR) rbuf;
  1570.                         ihdr->idx_parent = 0;
  1571.                         ihdr->idx_rec_cnt = 0;
  1572.                         break;
  1573. #endif
  1574.         }
  1575. }
  1576.  
  1577. /*
  1578.  *      db_free_rec  -  Free a deleted record
  1579.  */
  1580.  
  1581. void db_free_rec(df, buf)
  1582.  DATA_FILE df;
  1583.  BUFFER   buf;
  1584. {
  1585.         FILE_HDR  fh;
  1586.         FREE_REC fre;
  1587.     VAR_REC  var;
  1588.  
  1589.         db_error = 0;
  1590.  
  1591.         fh = (FILE_HDR) df->df_fhdr->buf_data;
  1592.  
  1593.         switch (fh->fh_file_type)
  1594.         {       
  1595. #ifdef SEQ
  1596.         case DB_SEQ:
  1597.                         fre = (FREE_REC) (buf->buf_data 
  1598.                                 + (buf->buf_rec_inx - 1) * fh->fh_rec_size);
  1599.                         memset(fre, 0, fh->fh_rec_size);
  1600.                         fre->fre_stat     = DB_FREE;
  1601.                         fre->fre_next     = fh->fh_next_avail;
  1602.                         fh->fh_next_avail = (long) (buf->buf_cur_blk - 1)
  1603.                                   * fh->fh_recs_per_blk + buf->buf_rec_inx;
  1604.                         break;
  1605. #endif
  1606.  
  1607. #ifdef RAN
  1608.                 case DB_RANDOM:
  1609.                         fre = (FREE_REC) buf->buf_data;
  1610.                         fre->fre_stat     = DB_FREE;
  1611.                         fre->fre_next     = fh->fh_next_avail;
  1612.                         fh->fh_next_avail = buf->buf_cur_blk;
  1613.                         break;                               
  1614. #endif
  1615.  
  1616. #ifdef IDX
  1617.                 case DB_INDEX:
  1618.                         fre = (FREE_REC) buf->buf_data;
  1619.                         memset(fre, 0, fh->fh_block_size);
  1620.                         fre->fre_stat     = DB_FREE;
  1621.                         fre->fre_next     = fh->fh_next_avail;
  1622.                         fh->fh_next_avail = buf->buf_cur_blk;
  1623.                         break;                               
  1624. #endif
  1625.  
  1626. #ifdef VAR
  1627.         case DB_VAR:
  1628.             var           = (VAR_REC) buf->buf_data;
  1629.             var->var_stat = DB_FREE;
  1630.             memset(var->var_data, 0 , var->var_dsize);
  1631.             break;
  1632. #endif
  1633.         }
  1634.         db_put_blk(df, buf);
  1635.         if (db_error) return;
  1636. }
  1637.  
  1638. /*
  1639.  *      db_get_blk  -  Get a Block from a Data File
  1640.  */
  1641.  
  1642. void db_get_blk(df,blk,buf)
  1643.  DATA_FILE df;         
  1644.  long     blk;
  1645.  BUFFER   buf;
  1646. {
  1647.         FILE_HDR  fhdr;
  1648.     VAR_REC   var;
  1649.         long psn, lseek();
  1650.         short cnt;          
  1651.                                 
  1652.         db_error = 0;
  1653.  
  1654.         if (!df)
  1655.         {       db_error = DB_FILE_NOT_OPEN;
  1656.                 return;
  1657.         }
  1658.  
  1659.         if (!df->df_stat & DB_OPEN)
  1660.         {       db_error = DB_FILE_NOT_OPEN;
  1661.                 return;
  1662.         }
  1663.         
  1664.         if (!buf)
  1665.         {       db_error = DB_BUFFER_ERROR;
  1666.                 return;
  1667.         }
  1668.  
  1669.         fhdr = (FILE_HDR) df->df_fhdr->buf_data;
  1670.                       
  1671.         if (blk == 0)
  1672.         {       psn = 0;
  1673.         cnt = buf->buf_size;
  1674.     }
  1675.         else
  1676.     if (fhdr->fh_file_type == DB_VAR)
  1677.     {    psn  = blk;
  1678.         if (psn >= DB_FILE_HDR_SIZE)
  1679.             cnt = buf->buf_size;
  1680.         else
  1681.         {    cnt = buf->buf_size - (DB_FILE_HDR_SIZE - psn);
  1682.             psn = DB_FILE_HDR_SIZE;
  1683.             blk = DB_FILE_HDR_SIZE;
  1684.             if (cnt <= 0)
  1685.             {    db_error = DB_INVALID_BLOCK;
  1686.                 return;
  1687.             }
  1688.         }
  1689.     }
  1690.     else
  1691.         {       psn = DB_FILE_HDR_SIZE + (blk-1) * (long)fhdr->fh_block_size;
  1692.         cnt = buf->buf_size;
  1693.     }
  1694.  
  1695.         buf->buf_cur_blk  = 0;
  1696.         buf->buf_cur_size = 0;
  1697.     buf->buf_rec_inx  = 0;
  1698.  
  1699.         if (lseek(df->df_fd, psn, 0) < 0)
  1700.         {       db_error = DB_INVALID_BLOCK;
  1701.                 return;
  1702.         }
  1703.  
  1704.         cnt = read(df->df_fd, buf->buf_data, cnt);
  1705.         if (cnt < 0)
  1706.         {       db_error = DB_READ_ERROR;
  1707.                 return;
  1708.         }
  1709.  
  1710.         if (cnt == 0)
  1711.         {       db_error = DB_END_OF_FILE;
  1712.                 return;
  1713.         }            
  1714.  
  1715.         buf->buf_cur_blk  = blk;
  1716.         buf->buf_cur_size = cnt;
  1717.     
  1718. }
  1719.  
  1720. /*
  1721.  *      db_put_blk  -  Put a Block out to a Data File
  1722.  */
  1723.  
  1724. void db_put_blk(df,buf)
  1725.  DATA_FILE df;         
  1726.  BUFFER   buf;
  1727. {
  1728.         FILE_HDR  fhdr;
  1729.     VAR_REC   var;
  1730.         long psn, lseek();
  1731.     int  cnt;
  1732.                                 
  1733.         db_error = 0;
  1734.  
  1735.         if (!df)
  1736.         {       db_error = DB_FILE_NOT_OPEN;
  1737.                 return;
  1738.         }
  1739.  
  1740.         if (!df->df_stat & DB_OPEN)
  1741.         {       db_error = DB_FILE_NOT_OPEN;
  1742.                 return;
  1743.         }
  1744.         
  1745.         if (!buf)
  1746.         {       db_error = DB_BUFFER_ERROR;
  1747.                 return;
  1748.         }
  1749.  
  1750.         if (buf->buf_cur_size == 0)
  1751.         {       db_error = DB_INVALID_BLK_SIZE;
  1752.                 return;
  1753.         }
  1754.  
  1755.         fhdr = (FILE_HDR) df->df_fhdr->buf_data;
  1756.  
  1757.         if (buf->buf_cur_blk == 0)
  1758.                 psn = 0;
  1759.         else
  1760.     if (fhdr->fh_file_type == DB_VAR)
  1761.     {    psn  = buf->buf_cur_blk;
  1762.         if (psn < DB_FILE_HDR_SIZE)
  1763.         {    db_error = DB_INVALID_BLOCK;
  1764.             return;
  1765.         }
  1766.     }
  1767.     else
  1768.                 psn  = DB_FILE_HDR_SIZE
  1769.                      + (buf->buf_cur_blk - 1) * (long)fhdr->fh_block_size;
  1770.  
  1771.         if (lseek(df->df_fd, psn, 0) < 0)
  1772.         {       db_error = DB_INVALID_BLOCK;
  1773.                 return;
  1774.         }
  1775.  
  1776.         cnt = write(df->df_fd, buf->buf_data, buf->buf_cur_size);
  1777.         if (cnt != buf->buf_cur_size)
  1778.         {       db_error = DB_WRITE_ERROR;
  1779.                 return;
  1780.         }
  1781. }
  1782.  
  1783. /*
  1784.  *      db_alloc_buf  -  Get a Buffer
  1785.  */
  1786.  
  1787. BUFFER db_alloc_buf(size)
  1788.  int size;
  1789. {
  1790.         BUFFER  buf;
  1791.         char   *calloc();
  1792.  
  1793.         buf = (BUFFER) calloc(1, sizeof(struct db_data_buf));
  1794.     if (!buf)
  1795.     {    db_error = DB_ALLOC_ERROR;
  1796.         return(NULL);
  1797.     }
  1798.  
  1799.         if (size)
  1800.         {       buf->buf_size  = size;
  1801.                 buf->buf_data  = (char *) calloc(1, size);
  1802.  
  1803.         if (!buf->buf_data)
  1804.         {    db_error = DB_ALLOC_ERROR;
  1805.             free(buf);
  1806.             return(NULL);
  1807.         }
  1808.         }
  1809.  
  1810.         return(buf);
  1811. }
  1812.  
  1813.  
  1814.  
  1815. /*
  1816.  *      db_free_buf  -  Free a Buffer
  1817.  */
  1818.  
  1819. BUFFER db_free_buf(buf)
  1820.  BUFFER buf;
  1821. {      
  1822.         BUFFER prev,next;
  1823.  
  1824.     if (!buf) return(NULL);
  1825.  
  1826.         prev = buf->buf_prev;
  1827.         next = buf->buf_next;
  1828.  
  1829.         if (prev) prev->buf_next = buf->buf_next;
  1830.  
  1831.         if (next) next->buf_prev = buf->buf_prev;
  1832.  
  1833.         if (buf->buf_data) free(buf->buf_data);
  1834.  
  1835.         free(buf);
  1836.         
  1837.         return(next);
  1838. }
  1839.  
  1840. /*
  1841.  *      db_free_df  -  Free all dynamic structures for a Data File
  1842.  */
  1843.  
  1844. void db_free_df(df)
  1845.  DATA_FILE df;
  1846. {
  1847.         if (!df) return;
  1848.  
  1849.         if (df->df_fhdr)
  1850.                 db_free_buf(df->df_fhdr);
  1851.  
  1852.         while (df->df_buf)
  1853.                 df->df_buf = db_free_buf(df->df_buf);
  1854.  
  1855.         if (df->df_tmp)
  1856.                 db_free_buf(df->df_tmp);
  1857.  
  1858.         if (df->df_aux)
  1859.                 db_free_buf(df->df_aux);
  1860.  
  1861.     free(df);
  1862.  
  1863.     return;
  1864. }
  1865.  
  1866. /*
  1867.  *      db_error_msg  -  Return pointer to error message text
  1868.  */
  1869.  
  1870. static char *db_error_msgs[] =
  1871. {"DB-No error",               /*  0 */
  1872.  "DB-Data File Not Found",     /*  1 */
  1873.  "DB-Read Error",              /*  2 */
  1874.  "DB-End Of File",             /*  3 */
  1875.  "DB-Write Error",             /*  4 */
  1876.  "DB-Data File Not Created",   /*  5 */
  1877.  "DB-Data File Not Open",      /*  6 */
  1878.  "DB-Invalid Block",           /*  7 */
  1879.  "DB-Buffer Error",            /*  8 */
  1880.  "DB-No Current Record",       /*  9 */
  1881.  "DB-Record Deleted",          /* 10 */
  1882.  "DB-Free List Error",         /* 11 */
  1883.  "DB-Invalid Block Size",      /* 12 */
  1884.  "DB-Index File Corrupted",    /* 13 */
  1885.  "DB-Record Not Found",        /* 14 */
  1886.  "DB-Duplicate Key",           /* 15 */
  1887.  "DB-Invalid Request",         /* 16 */
  1888.  "DB-Random File Corrupted",   /* 17 */
  1889.  "DB-Invalid File Header",     /* 18 */
  1890.  "DB-File Version Mismatch",   /* 19 */
  1891.  "DB-Invalid Link Descriptor", /* 20 */
  1892.  "DB-Linked List Corrupted",   /* 21 */
  1893.  "DB-Invalid File Type",       /* 22 */
  1894.  "DB-Invalid File Option",     /* 23 */
  1895.  "DB-Can't Allocate Memory",   /* 24 */
  1896.  "DB-Var File Rec Size Error", /* 25 */
  1897.  "DB-Var File Check Sum Error",/* 26 */
  1898.  "DB-Feature Unavailable",     /* 27 */
  1899.  "DB-Invalid Dictionary",      /* 28 */
  1900.  "DB-Invalid Name",            /* 29 */
  1901.  "DB-Invalid Error #",         /* 30 */
  1902.  ""};
  1903.  
  1904. char *db_error_msg(error)
  1905.  int error;
  1906. {
  1907.     if (error < 0 || error > DB_LAST_ERROR)
  1908.         error = DB_INVALID_ERROR;
  1909.  
  1910.         return(db_error_msgs[error]);
  1911. }
  1912.  
  1913. /*
  1914.  *        memcpy - copy a block of memory taking care not to overlap
  1915.  */
  1916.  
  1917. void *memcpy(dst, src, cnt)
  1918.  char *dst, *src;
  1919.  int   cnt;
  1920. {
  1921.     char *s, *d;
  1922.  
  1923.     if (dst > src  &&  dst < src+cnt)
  1924.     {    s = src + cnt - 1;
  1925.         d = dst + cnt - 1;
  1926.         while (cnt--) *d-- = *s--;
  1927.     }
  1928.     else
  1929.     {    s = src;
  1930.         d = dst;
  1931.         while (cnt--) *d++ = *s++;
  1932.     }
  1933.     return(dst);
  1934. }
  1935.                  
  1936.