home *** CD-ROM | disk | FTP | other *** search
/ Jason Aller Floppy Collection / 125.img / PRO-C4.ZIP / BENCH1.ZIP / BENCH / ICTREE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-28  |  42.9 KB  |  1,513 lines

  1. /* ==( io/src/ictree.c )== */
  2.  
  3. /* ----------------------------------------------- */
  4. /* Pro-C  Copyright (C) 1988 - 1990 Vestronix Inc. */
  5. /* Modification to this source is not supported    */
  6. /* by Vestronix Inc.                               */
  7. /*            All Rights Reserved                  */
  8. /* ----------------------------------------------- */
  9. /* Written   SBF  01-Aug-89                        */
  10. /* Modified  VvA  28-Feb-90  see notes below       */
  11. /* ----------------------------------------------- */
  12. /* %W%  (%H% %T%) */
  13.  
  14. /*
  15.  *  Modifications
  16.  *
  17.  *  28-Mar-90  VvA - adjustments for locking modes, transactions
  18.  *  16-Feb-90  VvA - IOGEN version, key segments enabled
  19.  *  20-Aug-89  SBF
  20. */
  21.  
  22. /*
  23.  *   C-TREE I/O calls via general IOGEN.C interface 
  24.  *   (for C-Tree 4.3B and beyond)
  25.  *
  26.  *****************************************************************************
  27.  *                                                                           *
  28.  * *** NOTE *** : For UNIX systems two modifications to C-Tree code are      *
  29.  *                required.  Change calls to creat() to calls to open()      *
  30.  *                with O_RDWR | O_CREAT | O_TRUNC as the second argument.    *
  31.  *                Also, in the function CREIDX() where the other indices     *
  32.  *                ct_num->chnacs are being set to 'm' increment ct_num       *
  33.  *                before entering the loop through all the members.          *
  34.  *                                                                           *
  35.  *****************************************************************************
  36. */
  37.  
  38. # include <stdio.h>
  39. # include <iodef.h>
  40. # include <iomsg.h>
  41. # include <proc.io>
  42. # include <bench.h>
  43. # include <iosup.h>
  44. # include <ctype.h>
  45.  
  46. #ifdef QNX
  47. #include <file_io.h>
  48. #else
  49. #include <fileio.h>
  50. #endif
  51.  
  52. #include <ctport.h>
  53. #include <ctoptn.h>
  54. #include <ctstrc.h>
  55. #include <ctisam.h>
  56. #include <ctifil.h>
  57. #include <cterrc.h>
  58. #include <ctgvar.h>
  59.  
  60. /*
  61.  * Macro definitions
  62. */
  63. #define INDEX_BUFFERS   6              /* These three are the parameters */
  64. #define MAX_FILES_USED  20             /* used for an INTREE() call...   */
  65. #define NUM_INDEX_SECTS 4              /* If you increase MAX_FILES then */
  66.                                        /* increase MAX_FILES_USED...     */
  67. #define RLOCKON        2
  68. #define WLOCKON        1
  69. #define LOCKOFF        0
  70.  
  71.  
  72. /* Function prototypes */
  73. # ifdef ANSI
  74. static int i_addrec(int, char *);
  75. static int i_close_file(int, char *);
  76. static int i_commit(int, char *);
  77. static int i_delrec(int, char *);
  78. static int i_filename(int, char *);
  79. static int i_findkey(int, char *);
  80. static int i_firstkey(int, char *);
  81. static int i_init_file(int, char *);
  82. static int i_lastkey(int, char *);
  83. static int i_lockrec(int, char *);
  84. static int i_login(int, char *);
  85. static int i_logoff(int, char *);
  86. static int i_nextrec(int, char *);
  87. static int i_open_file(int, char *);
  88. static int i_prevrec(int, char *);
  89. static int i_rereadrec(int, char *);
  90. static int i_rollback(int, char *);
  91. static int i_selectinx(int, char *);
  92. static int i_transact(int, char *);
  93. static int i_unlock_rec(int, char *);
  94. static int i_updrec(int, char *);
  95. static int io_xlate(int, int, char *);
  96. static int add_rec(int, char *);
  97. static int cl_ifil(IFIL *);
  98. static int cre_ifil(IFIL *);
  99. static int del_rec(int);
  100. static int frm_key(int, int, char *, char *, long);
  101. static int gte_rec(int, char *, char *);
  102. static int lst_rec(int, char *);
  103. static int nxt_rec(int, char *);
  104. static int opn_ifil(IFIL *);
  105. static int prv_rec(int, char *);
  106. static int rrd_rec(int, char *);
  107. static int rwt_rec(int, char *);
  108. static int create_file(int);
  109. static int get_mode(int);
  110. static int length_check(int);
  111. static int load_keys(int);
  112. static int lockit(int, long, int);
  113. /* externs from C-Tree */
  114. EXTERN COUNT ADDKEY(COUNT, TEXT *, POINTER, COUNT);
  115. EXTERN COUNT CLSFIL(COUNT, COUNT);
  116. EXTERN COUNT CREDAT(COUNT, TEXT *, UCOUNT, UCOUNT, COUNT);
  117. EXTERN COUNT CREIDX(COUNT, TEXT *, COUNT, COUNT, COUNT, COUNT, UCOUNT, COUNT);
  118. EXTERN COUNT CREMEM(COUNT, COUNT, COUNT, COUNT, COUNT);
  119. EXTERN COUNT DELCHK(COUNT, TEXT *, POINTER);
  120. EXTERN POINTER GTEKEY(COUNT, TEXT *, TEXT *);
  121. EXTERN POINTER GTKEY(COUNT, TEXT *, TEXT *);
  122. EXTERN COUNT INTREE(COUNT, COUNT, COUNT);
  123. EXTERN COUNT LOKREC(COUNT, COUNT, POINTER);
  124. EXTERN COUNT LSTKEY(COUNT, TEXT *);
  125. EXTERN POINTER LTKEY(COUNT, TEXT *, TEXT *);
  126. EXTERN POINTER NEWREC(COUNT);
  127. EXTERN COUNT OPNFIL(COUNT, TEXT *, COUNT);
  128. EXTERN COUNT REDREC(COUNT, POINTER, TEXT *);
  129. EXTERN COUNT RETREC(COUNT, POINTER);
  130. EXTERN COUNT WRTREC(COUNT, POINTER, TEXT *);
  131. # else
  132. static int i_addrec();
  133. static int i_close_file();
  134. static int i_commit();
  135. static int i_delrec();
  136. static int i_filename();
  137. static int i_findkey();
  138. static int i_firstkey();
  139. static int i_init_file();
  140. static int i_lastkey();
  141. static int i_lockrec();
  142. static int i_login();
  143. static int i_logoff();
  144. static int i_nextrec();
  145. static int i_open_file();
  146. static int i_prevrec();
  147. static int i_rereadrec();
  148. static int i_rollback();
  149. static int i_selectinx();
  150. static int i_transact();
  151. static int i_unlock_rec();
  152. static int i_updrec();
  153. static int io_xlate();
  154. static int add_rec();
  155. static int cl_ifil();
  156. static int cre_ifil();
  157. static int del_rec();
  158. static int frm_key();
  159. static int gte_rec();
  160. static int lst_rec();
  161. static int nxt_rec();
  162. static int opn_ifil();
  163. static int prv_rec();
  164. static int rrd_rec();
  165. static int rwt_rec();
  166. static int create_file();
  167. static int get_mode();
  168. static int length_check();
  169. static int load_keys();
  170. static int lockit();
  171. /* externs from C-Tree */
  172. EXTERN COUNT ADDKEY();
  173. EXTERN COUNT CLSFIL();
  174. EXTERN COUNT CREDAT();
  175. EXTERN COUNT CREIDX();
  176. EXTERN COUNT CREMEM();
  177. EXTERN COUNT DELCHK();
  178. EXTERN POINTER GTEKEY();
  179. EXTERN POINTER GTKEY();
  180. EXTERN COUNT INTREE();
  181. EXTERN COUNT LOKREC();
  182. EXTERN COUNT LSTKEY();
  183. EXTERN POINTER LTKEY();
  184. EXTERN POINTER NEWREC();
  185. EXTERN COUNT OPNFIL();
  186. EXTERN COUNT REDREC();
  187. EXTERN COUNT RETREC();
  188. EXTERN COUNT WRTREC();
  189. # endif
  190.  
  191. /* EXTERNs */
  192. extern long lseek();
  193. extern char *alloc();
  194.  
  195.  
  196. /*
  197.  * C-TREE specific file descriptor structure
  198.  * (index fd_sys will be in parallel with fd[] structure from iogen)
  199. */
  200. struct cfd_def
  201. {
  202.     long cur_recbyt;                   /* current record offset */
  203.     char *cur_recbuf;                  /* buffer holding current record */
  204.     int lockflag;                      /* locking flag */
  205.     long lockbyt;                      /* offset of locked record */
  206.     char *updbuf;                      /* pointer to buffer used in update */
  207.     IFIL datafile;                     /* C-Tree file info */
  208.     IIDX fdkey[MAX_KEYS];              /* C-Tree index/key info */
  209. };
  210.  
  211.  
  212. static struct cfd_def cfd[MAX_FILES];
  213. static int filno_used[MAX_FILES_USED]; /* keep track of file numbers */
  214.  
  215.  
  216. /*
  217.  *
  218.  * Interface Functions
  219.  *
  220. */
  221.  
  222.  
  223. /*
  224.  *  Sets up File Name extension, Name is passed in buffer.
  225. */
  226. static int i_filename(fd_sys, buffer)
  227. int fd_sys;
  228. char *buffer;
  229. {
  230.     char *f1;                               /* pointer to filename extension */
  231.  
  232.     if ((f1 = strchr(buffer, '.')) != NULL)
  233.         *f1 = '\0';                         /* remove extension from filename */
  234.     return(IOGOOD);
  235. }
  236.  
  237.  
  238. /*
  239.  *  Initialize C-TREE
  240. */
  241. static int i_init_file(fd_sys, buffer)
  242. int fd_sys;
  243. char *buffer;
  244. {
  245.     int i;
  246.  
  247.     INTREE(INDEX_BUFFERS, MAX_FILES_USED, NUM_INDEX_SECTS);
  248.  
  249.     for (i = 0; i < MAX_FILES_USED; i++)
  250.         filno_used[i] = FALSE;                /* no file numbers in use (yet) */
  251.     return(IOGOOD);
  252. }
  253.  
  254. /*
  255.  *  C-TREE file open
  256. */
  257. static int i_open_file(fd_sys, buffer)
  258. int fd_sys;
  259. char *buffer;
  260. {
  261.     int stat;                                             /* status variable */
  262.     char *datname;                            /* filename buffer (with .dat) */
  263.     char *idxname;                            /* filename buffer (with .idx) */
  264.     struct fd_def *fptr = &fd[fd_sys];
  265.     struct cfd_def *cptr = &cfd[fd_sys];
  266.     IFIL *dptr;                                      /* pointer to IFIL info */
  267.  
  268.     cptr->cur_recbyt = 0L;             /* 0L is actually before first record */
  269.     cptr->cur_recbuf = alloc(fptr->rec_len);    /* buffer for current record */
  270.     cptr->lockflag = 0;                                      /* no locks yet */
  271.     cptr->lockbyt = 0L;                
  272.  
  273.     dptr = &cptr->datafile;                        /* pointer to IFIL struct */
  274.     dptr->pfilnam = strsave(fptr->filname);    /* fill IFIL struct with info */
  275.     dptr->dfilno = -1;                               /* no file number (yet) */
  276.     dptr->dreclen = fptr->rec_len;                      /* set record length */
  277.     dptr->dxtdsiz = fptr->rec_len;
  278.     dptr->dfilmod = get_mode(fptr->openmode);    /* get the mode, then the key info */
  279.     dptr->dnumidx = load_keys(fd_sys);
  280.     dptr->ixtdsiz = fptr->rec_len;            
  281.     dptr->ifilmod = get_mode(fptr->openmode);            /* CHECK THIS!!!!!! */
  282.     dptr->ix = cptr->fdkey;                             /* point to key info */
  283.     dptr->rfstfld = NULL;             /* these two are only needed by R-Tree */
  284.     dptr->rlstfld = NULL;
  285.     dptr->tfilno = -1;
  286.  
  287.     datname = alloc(strlen(fptr->filname) + 5);
  288.     idxname = alloc(strlen(fptr->filname) + 5);
  289.     sprintf(datname, "%s.dat", fptr->filname);
  290.     sprintf(idxname, "%s.idx", fptr->filname);
  291.  
  292.      if (fptr->openmode & OUTPUT_FLAG)
  293.     {
  294.         unlink(datname);
  295.         unlink(idxname);
  296.     }
  297.     free(idxname);
  298.     free(datname);
  299.  
  300.     if (stat = opn_ifil(dptr))                                /* open failed */
  301.     {
  302.         if (fptr->openmode & INPUT_FLAG)
  303.             return(io_xlate(fd_sys, stat, "CT OPEN"));
  304.                                              /* create if update/output mode */
  305.         if (create_file(fd_sys) != IOGOOD)
  306.             return(IOERROR);
  307.     }
  308.     else
  309.     {
  310.         if (length_check(fd_sys) != IOGOOD)
  311.         {                                    /* but the length doesn't match */
  312.             errmsg(FileRecLenChg_s, dptr->pfilnam);
  313.             return(IOERROR);
  314.         }
  315.     }
  316.  
  317.     dptr->dfilno = dptr->tfilno;        /* open successful, save file number */
  318.     fptr->exact = 0;                                /* initialize exact flag */
  319.     return(IOGOOD);
  320. }
  321.  
  322. /*
  323.  * Create file(s)
  324. */
  325. static int create_file(fd_sys)
  326. int fd_sys;
  327. {
  328.     IFIL *dptr = &cfd[fd_sys].datafile; /* point to IFIL info */
  329.     int stat;                          /* create status */
  330.  
  331.     if (stat = cre_ifil(dptr))         /* create file */
  332.         return(io_xlate(fd_sys, stat, "CT CREATE 1"));
  333.  
  334.     return(IOGOOD);                    /* s'allright! */
  335. }
  336.  
  337. /*
  338.  * Translate Pro-C mode to C-Tree mode
  339.  * - here FairCom's definitions of SHARED & EXCLUSIVE are used!
  340. */
  341. static int get_mode(mode)
  342. int mode;
  343. {
  344.     if (mode & OUTPUT_FLAG)                      /* output mode is exclusive */
  345.         return(FIXED | EXCLUSIVE | PERMANENT);
  346.     else                                                /* others are shared */
  347.         return(FIXED | SHARED | PERMANENT);
  348. }
  349.  
  350. /*
  351.  * length_check() - check the length of the existing data records
  352.  *                - since C-Tree doesn't have a record length check
  353.  *                  we have to get an int value from byte offset 4
  354.  *                  in the C-Tree data file header
  355. */
  356. extern CTFILE *ct_key;                 /* extern to ctree's wfils info */
  357.  
  358. static int length_check(fd_sys)
  359. int fd_sys;
  360. {
  361.     struct fd_def *fptr = &fd[fd_sys];
  362.     struct cfd_def *cptr = &cfd[fd_sys];
  363.     IFIL *dptr = &cptr->datafile;      /* pointer to IFIL info */
  364.     CTFILE *ct_num;                    /* pointer for current info */
  365.     
  366.     ct_num = ct_key + dptr->tfilno;
  367.  
  368.     if (ct_num->reclen == dptr->dreclen)
  369.         return(IOGOOD);                /* record length OK */
  370.  
  371.     return(IOERROR);                   /* problem checking record length */
  372. }
  373.  
  374. /*
  375.  * Load key information from Pro-C key specifications
  376. */
  377. static int load_keys(fd_sys)
  378. int fd_sys;
  379. {
  380.      int i, datatype, fldix;
  381.     int nkeys = 0;                     /* number of keys */
  382.     int dupkeyflag;                    /* duplicate key flag */
  383.     struct fd_def *fptr = &fd[fd_sys];
  384.     IIDX *kptr = cfd[fd_sys].fdkey;     /* pointer to key info */
  385.     ISEG *sptr;                        /* pointer to segment info */
  386.  
  387.     while (fptr->keys[nkeys].segcount != -1)
  388.     {
  389.         kptr->inumseg = fptr->keys[nkeys].segcount;
  390.         kptr->ikeylen = 0;
  391.         sptr = (ISEG *) alloc(sizeof(ISEG) * fptr->keys[nkeys].segcount);
  392.         kptr->seg = sptr;              /* point to segment info */
  393.         kptr->ikeytyp = 0;             /* set type to 0 (fixed length key) */
  394.         dupkeyflag = 0;                /* initialize flag */
  395.  
  396.         for (i = 0; i < fptr->keys[nkeys].segcount; i++)
  397.         {
  398.             sptr->soffset = fptr->keys[nkeys].segstart[i];
  399.             sptr->slength = fptr->keys[nkeys].seglen[i];
  400.             kptr->ikeylen += fptr->keys[nkeys].seglen[i];       
  401.  
  402.             if (fptr->keys[nkeys].keytype == KEY_DUPLICATE)
  403.                 dupkeyflag++;              /* is it a duplicate? */
  404.  
  405.              fldix = fptr->keys[nkeys].fldindex[i];
  406.              datatype = fptr->flds[fldix].fldtype;
  407.             switch(datatype)             /* set segment mode from Pro-C type */
  408.             {
  409.                 case CHRTYP:
  410.                     sptr->segmode = 0;     /* no transformation */
  411.                     break;
  412.                 case LNGTYP:
  413.                 case INTTYP:
  414.                     sptr->segmode = 1;     /* unsigned integer */
  415.                     break;
  416.                 case FLTTYP:
  417.                 case DBLTYP:
  418.                     sptr->segmode = 9;     /* floating point */
  419.                     break;
  420.                 case DATTYP:
  421.                     if (fptr->flds[fldix].fldlen == 6)
  422.                         sptr->segmode = 0;     /* treat as char */
  423.                     else
  424.                         sptr->segmode = 1;     /* treat as int */
  425.                     break;
  426.             }
  427.             sptr++;                                            /* next segment */
  428.         }
  429.  
  430.         kptr->inulkey = 0;                                    /* zero for now */
  431.         kptr->iempchr = 0;
  432.         if (dupkeyflag)
  433.         {
  434.             kptr->ikeylen += 4;        /* duplicate keys need 4 extra bytes */
  435.             kptr->ikeydup = 1;           
  436.         }    
  437.         else
  438.             kptr->ikeydup = 0;
  439.  
  440.         kptr++;                        /* next key */
  441.         nkeys++;                       /* increment counter */
  442.     }
  443.  
  444.     return(nkeys);                     /* return number of keys loaded */
  445. }
  446.  
  447.  
  448. /*
  449.  *  Close data and/or index files and free the fd_def
  450. */
  451. static int i_close_file(fd_sys, buffer)
  452. int fd_sys;
  453. char *buffer;
  454. {
  455.     int stat;
  456.     struct cfd_def *cptr = &cfd[fd_sys];
  457.  
  458.     if (stat = cl_ifil(&cptr->datafile))
  459.         return(io_xlate(fd_sys, stat, "CT CLOSE"));
  460.  
  461.     free(cptr->cur_recbuf);
  462.     return(IOGOOD);
  463. }
  464.  
  465.  
  466.  
  467. /*
  468.  *  Select an index to perform processing on - already done in IOGEN.C
  469. */
  470. static int i_selectinx(fd_sys, buffer)
  471. int fd_sys;
  472. char *buffer;
  473. {
  474.    return(IOGOOD);
  475. }
  476.  
  477.  
  478. /*
  479.  *  Find a record by key value
  480.  *  The selectinx function has already set fd[fd_sys].exact to EXACT or PART.
  481. */
  482. static int i_findkey(fd_sys, buffer)
  483. int fd_sys;
  484. char *buffer;
  485. {
  486.     int keylen;                        /* length of key */
  487.     int reallen;                       /* length of key without suffix */
  488.     int keyoff;                        /* offset of key within buffer */
  489.     int stat;                          /* status variable */
  490.     char *target;                      /* pointer to target key buffer */
  491.     char *kcmpbuf;                     /* buffer for comparing new key */
  492.     struct fd_def *fptr = &fd[fd_sys]; /* pointer to fd_def */
  493.     struct cfd_def *cptr = &cfd[fd_sys]; /* pointer to cfd_def */
  494.     IIDX *kptr;                        /* pointer to key info */
  495.  
  496.     kptr = &cptr->fdkey[fptr->cur_key];         /* point to current key info */
  497.     keyoff = kptr->seg->soffset;                 /* get offset, length, etc. */
  498.     keylen = kptr->ikeylen;
  499.     reallen = kptr->seg->slength;
  500.  
  501.     target = alloc(keylen);                    /* allocate target key buffer */
  502.     frm_key(fd_sys, fptr->cur_key, buffer, target, 0L);     /* transform key */
  503.  
  504.     stat = gte_rec(fd_sys, target, buffer);          /* get record >= target */
  505.     if (stat)
  506.     {
  507.         free(target);
  508.         return(io_xlate(fd_sys, stat, "CT FIND"));
  509.     }
  510.  
  511.     if (fptr->exact)
  512.     {
  513.         kcmpbuf = alloc(keylen);                /* allocate comparison buffer */
  514.         frm_key(fd_sys, fptr->cur_key, buffer, kcmpbuf, 0L);
  515.                                             /* compare them to see if equal */
  516.         stat = bytecmp(target, kcmpbuf, reallen);
  517.         free(target);
  518.         free(kcmpbuf);
  519.         if (stat)
  520.             return(IONOKEY);                                      /* not equal */
  521.     }
  522.     return(IOGOOD);
  523. }
  524.  
  525.  
  526. /*
  527.  *  Find first record in the file
  528. */
  529. static int i_firstkey(fd_sys, buffer)
  530. int fd_sys;
  531. char *buffer;
  532. {
  533.     int stat;                          /* gte_rec status */
  534.     char *ptr;                         /* pointer to key buffer */
  535.     struct fd_def *fptr = &fd[fd_sys]; /* pointer to the fd_def */
  536.     struct cfd_def *cptr = &cfd[fd_sys]; /* pointer to the cfd_def */
  537.     IFIL *dptr = &cptr->datafile;      /* pointer to IFIL info */
  538.  
  539.     zerorec(buffer, dptr->dreclen);      /* zero buffer and alloc key buffer */
  540.     ptr = alloc(cptr->fdkey[fptr->cur_key].ikeylen);
  541.  
  542.     frm_key(fd_sys, fptr->cur_key, buffer, ptr, 0L);
  543.     stat = gte_rec(fd_sys, ptr, buffer);
  544.     free(ptr);                        /* inquire on null key and free buffer */
  545.     if (stat)
  546.         return(io_xlate(fd_sys, stat, "CT FIRST"));
  547.  
  548.     return(IOGOOD);
  549. }
  550.  
  551.  
  552. /*
  553.  *  Find last record in the file using the current key
  554. */
  555. static int i_lastkey(fd_sys, buffer)
  556. int fd_sys;
  557. char *buffer;
  558. {
  559.     int stat;                          /* status variable */
  560.  
  561.     if (stat = lst_rec(fd_sys, buffer))
  562.     {
  563.         if (stat = INOT_ERR)
  564.             return(IOEOF);
  565.  
  566.         return(io_xlate(fd_sys, stat, "CT LAST"));
  567.     }
  568.  
  569.     return(IOGOOD);
  570. }
  571.  
  572.  
  573. /*
  574.  *  Find next record in the file by current index
  575.  *  The IOGEN function will check for EXACT next match
  576. */
  577. static int i_nextrec(fd_sys, buffer)
  578. int fd_sys;
  579. char *buffer;
  580. {
  581.     int stat;
  582.     long sav_recbyt;
  583.     struct fd_def *fptr = &fd[fd_sys];
  584.     struct cfd_def *cptr = &cfd[fd_sys];
  585.  
  586.     sav_recbyt = cptr->cur_recbyt;             /* save current record offset */
  587.  
  588.     if (stat = nxt_rec(fd_sys, buffer))
  589.     {
  590.         cptr->cur_recbyt = sav_recbyt;       /* restore current record offset */
  591.         if (stat == INOT_ERR)
  592.             return(IOEOF);
  593.         return(io_xlate(fd_sys, stat, "CT NEXT"));
  594.     }
  595.  
  596.     return(IOGOOD);
  597. }
  598.  
  599.  
  600. /*
  601.  *  Find previous record in the file by current index
  602.  *  The IOGEN function will check for EXACT next match
  603. */
  604. static int i_prevrec(fd_sys, buffer)
  605. int fd_sys;
  606. char *buffer;
  607. {
  608.     int stat;
  609.     long sav_recbyt;
  610.     struct fd_def *fptr = &fd[fd_sys];
  611.     struct cfd_def *cptr = &cfd[fd_sys];
  612.  
  613.     sav_recbyt = cptr->cur_recbyt;             /* save current record offset */
  614.  
  615.     if (stat = prv_rec(fd_sys, buffer))
  616.     {
  617.         cptr->cur_recbyt = sav_recbyt;       /* restore current record offset */
  618.         if (stat == INOT_ERR)
  619.             return(IOTOF);
  620.         return(io_xlate(fd_sys, stat, "CT PREV"));
  621.     }
  622.  
  623.     return(IOGOOD);
  624. }
  625.  
  626.  
  627. /*
  628.  *  Re-read/reposition record pointer function - if required
  629. */
  630. static int i_rereadrec(fd_sys, buffer)
  631. int fd_sys;
  632. char *buffer;
  633. {
  634.    return(IOGOOD);
  635. }
  636.  
  637.  
  638. /*
  639.  *  Add a new record - unlocking is handled from IOGEN
  640. */
  641. static int i_addrec(fd_sys, buffer)
  642. int fd_sys;
  643. char *buffer;
  644. {
  645.     int stat;
  646.  
  647.     if (stat = add_rec(fd_sys, buffer))
  648.         return(io_xlate(fd_sys, stat, "CT ADD"));
  649.  
  650.     return(IOGOOD);
  651. }
  652.  
  653.  
  654. /*
  655.  *  Update the current record - unlocking is handled from IOGEN
  656. */
  657. static int i_updrec(fd_sys, buffer)
  658. int fd_sys;
  659. char *buffer;
  660. {
  661.     int stat;
  662.     struct cfd_def *cptr = &cfd[fd_sys];
  663.     IFIL *dptr = &cptr->datafile;
  664.  
  665.     cptr->updbuf = alloc(dptr->dreclen);        /* allocate temporary buffer */
  666.  
  667.     if (stat = rrd_rec(fd_sys, cptr->updbuf))           /* reread the record */
  668.     {
  669.         free(cptr->updbuf);
  670.         return(io_xlate(fd_sys, stat, "CT UPDT1"));
  671.     }
  672.  
  673.     stat = rwt_rec(fd_sys, buffer);
  674.     free(cptr->updbuf);
  675.     if (stat)
  676.         return(io_xlate(fd_sys, stat, "CT UPDT2"));
  677.  
  678.     return(IOGOOD);
  679. }
  680.  
  681.  
  682. /*
  683.  *  Delete the current record.
  684. */
  685. static int i_delrec(fd_sys, buffer)
  686. int fd_sys;
  687. char *buffer;
  688. {
  689.     int stat;
  690.     struct cfd_def *cptr = &cfd[fd_sys];
  691.  
  692.     if (stat = del_rec(fd_sys))
  693.         return(io_xlate(fd_sys, stat, "CT DEL"));
  694.  
  695.     cptr->lockflag = 0;
  696.     cptr->lockbyt = 0L;
  697.     return(IOGOOD);
  698. }
  699.  
  700.  
  701. /*
  702.  *  Lock Record - dummy function since C-Tree locks automatically
  703.  *  - write lock request from lockit() to allow for explicit locking
  704.  *    (will return IOGOOD or NO_ERROR (both 0) if no lock wanted)
  705. */  
  706. static int i_lockrec(fd_sys, buffer)
  707. int fd_sys;
  708. char *buffer;
  709. {
  710.    int stat;
  711.    long recbyt;
  712.  
  713.    recbyt = cfd[fd_sys].cur_recbyt;
  714.    if (lockit(fd_sys, recbyt, WLOCKON))
  715.       return(io_xlate(fd_sys, stat, "CT LOCK"));
  716.    return(IOGOOD);
  717. }
  718.  
  719. /*
  720.  *  Unlock Record
  721.  *  - returns with IOGOOD if no locks used
  722. */
  723. static int i_unlock_rec(fd_sys, buffer)
  724. int fd_sys;
  725. char *buffer;
  726. {
  727.     lockit(fd_sys, cfd[fd_sys].lockbyt, LOCKOFF);
  728.     return(IOGOOD);
  729. }
  730.  
  731. /*
  732.  *  Login
  733. */
  734. static int i_login(fd_sys, buffer)
  735. int fd_sys;
  736. char *buffer;
  737. {
  738.    return(IOGOOD);
  739. }
  740.  
  741. /*
  742.  *  Logoff
  743. */
  744. static int i_logoff(fd_sys, buffer)
  745. int fd_sys;
  746. char *buffer;
  747. {
  748.    return(IOGOOD);
  749. }
  750.  
  751. /*
  752.  *  End (Commit) transaction 
  753. */
  754. static int i_commit(fd_sys, buffer)
  755. int fd_sys;
  756. char *buffer;
  757. {
  758.    return(IOGOOD);
  759. }
  760.  
  761. /*
  762.  *  Rollback transaction
  763. */
  764. static int i_rollback(fd_sys, buffer)
  765. int fd_sys;
  766. char *buffer;
  767. {
  768.    return(IOGOOD);
  769. }
  770.  
  771. /*
  772.  *  Start transaction
  773. */
  774. static int i_transact(fd_sys, buffer)
  775. int fd_sys;
  776. char *buffer;
  777. {
  778.    return(IOGOOD);
  779. }
  780.  
  781.  
  782. /*
  783.  *  This routine translates C-TREE Error codes into PRO-C error codes.
  784.  *  If no PRO-C equivalent, displays the error number.
  785. */
  786. static int io_xlate(fd_sys, ernum, rtnname)
  787. int fd_sys;
  788. int ernum;
  789. char *rtnname;
  790. {
  791.     switch(ernum)
  792.     {
  793.         case KCRAT_ERR:
  794.         case DCRAT_ERR:
  795.             return(IONOLOCK);
  796.         case FNOP_ERR:
  797.             return(IOBADOPEN);
  798.         case IPND_ERR:
  799.         case DLOK_ERR:
  800.             return(IOLOCKED);
  801.         case KDUP_ERR:
  802.             return(IODUP);
  803.         case ICUR_ERR:
  804.         case INOT_ERR:
  805.             return(IONOKEY);
  806.         case FNUM_ERR:
  807.             return(IONOFILE);
  808. #ifndef NO_SERVE
  809.         case ASKY_ERR:
  810.         case ASID_ERR:
  811.             errmsg("C-Tree Server Not Running");
  812.             return(IOERROR);
  813. #endif
  814.     }
  815.  
  816.     if (fd_sys >= 0)
  817.         errmsg(FileDbgError_sdss, "C-TREE", ernum, fd[fd_sys].filname, rtnname);
  818.     else      /* if routines called from generated apps without valid fd_sys */
  819.         errmsg(FileDbgError_sds, "C-TREE", ernum, rtnname);
  820.     return(IOERROR);
  821. }
  822.  
  823.  
  824. /*******************************************************************************
  825. *                                                                              *
  826. * Static functions used by io3 functions                                       *
  827. *                                                                              *
  828. *******************************************************************************/
  829.  
  830. /*
  831.  * lockit() - lock/unlock record
  832. */
  833. static int lockit(fd_sys, recbyt, lkmod)
  834. int fd_sys;
  835. long recbyt;
  836. int lkmod;
  837. {
  838.     int stat;                          /* lock status */
  839.     int lokmod;                        /* C-Tree lock mode */
  840.     struct fd_def *fptr = &fd[fd_sys];
  841.     struct cfd_def *cptr = &cfd[fd_sys];
  842.     IFIL *dptr = &cptr->datafile;      /* pointer to IFIL info */
  843.  
  844.      if (fd[fd_sys].lockmode == NOLOCK)            /* if no locking specified */
  845.         return(NO_ERROR);              /* just return without doing anything */
  846.  
  847.                                        /* get lock mode */
  848.     switch(lkmod)
  849.     {
  850.         case LOCKOFF:
  851.             lokmod = FREE;
  852.             break;
  853.         case WLOCKON:
  854.             lokmod = (fptr->openmode & INPUT_FLAG) ? READREC : ENABLE;
  855.             break;
  856.         case RLOCKON:
  857.             lokmod = READREC;
  858.             break;
  859.         default:
  860.             abort_mess("Invalid lock mode in lockit()...\n");
  861.             exit(-1);
  862.             break;
  863.     }
  864.     
  865.     if (lokmod != FREE)
  866.     {                                  /* when locking */
  867.         if (cptr->lockflag == 1)       /* if there's a lock free it */
  868.             if (stat = LOKREC(dptr->dfilno, FREE, cptr->lockbyt))
  869.                 return(stat);
  870.     }
  871.                                        /* attempt lock/free */
  872.     if (stat = LOKREC(dptr->dfilno, lokmod, recbyt))
  873.         return(stat);
  874.  
  875.     if (lokmod == FREE)                /* free was successful */
  876.     {
  877.         cptr->lockflag = 0;            /* so zero the lock info */
  878.         cptr->lockbyt = 0L;
  879.     }
  880.     else                               /* lock was successful */
  881.     {
  882.         cptr->lockflag = 1;            /* so update lock info */
  883.         cptr->lockbyt = recbyt;
  884.     }
  885.  
  886.     return(NO_ERROR);
  887. }
  888.  
  889. /*******************************************************************************
  890. *                                                                              *
  891. * Replacement high level routines (so we have control over locking)            *
  892. *                                                                              *
  893. *******************************************************************************/
  894. /*
  895.  * add_rec() - add a record and it key values to the appropriate file(s)
  896. */
  897. static int add_rec(fd_sys, recptr)
  898. int fd_sys;
  899. char *recptr;
  900. {
  901.     long recbyt;                       /* byte offset of record */
  902.     struct fd_def *fptr = &fd[fd_sys];
  903.     struct cfd_def *cptr = &cfd[fd_sys];
  904.     IFIL *dptr = &cptr->datafile;      /* pointer to IFIL info */
  905.     IIDX *kptr;                        /* pointer for key info */
  906.     int datno = dptr->dfilno;          /* base data file number (C-Tree) */
  907.     int keyno;                         /* 'file' number for key (C-Tree) */
  908.     int i, j;                          /* counters */
  909.     char *target;                      /* pointer to target key buffer */
  910.     int stat;                          /* status variable */
  911.                                         
  912.     if (!recptr)
  913.         return(DNUL_ERR);              /* null record passed in */
  914.     recbyt = NEWREC(datno);            /* get offset for new record */
  915.     if (!recbyt)
  916.         return(uerr_cod);              /* error getting new record */
  917.     if (lockit(fd_sys, recbyt, WLOCKON))/* lock the new record */
  918.         return(DLOK_ERR);              
  919.     if (WRTREC(datno, recbyt, recptr)) /* write the data out */
  920.         return(uerr_cod);
  921.     for(i = 0; i < dptr->dnumidx; i++) /* add each of the keys to the index */
  922.     {
  923.         kptr = &cptr->fdkey[i];        /* point to key info for this key */
  924.         keyno = datno + i + 1;         /* key's 'file' number */
  925.         target = alloc(kptr->ikeylen);    /* allocate and transform target */
  926.         frm_key(fd_sys, i, recptr, target, recbyt);
  927.         stat = ADDKEY(keyno, target, recbyt, REGADD);
  928.         free(target);                  /* add the key and free the target */
  929.         if (stat)                      /* cleanup if there was an error */
  930.         {
  931.             for(j = i - 1; j >= 0; j--)/* rebuild and delete each key that */
  932.             {                          /* was added up 'til now */
  933.                 kptr = &cptr->fdkey[j];
  934.                 keyno = datno + j + 1;
  935.                 target = alloc(kptr->ikeylen);
  936.                 frm_key(fd_sys, j, recptr, target, 0L);
  937.                 DELCHK(keyno, target, recbyt);
  938.                 free(target);
  939.             }
  940.             RETREC(datno, recbyt);     /* return this record for use */
  941.             return(stat);
  942.         }
  943.     }
  944.     cptr->cur_recbyt = recbyt;         /* update current record offset */
  945.     bytecpy(cptr->cur_recbuf, recptr, dptr->dreclen);
  946.     return(NO_ERROR);
  947. }
  948.  
  949. /*
  950.  * cre_ifil() - create file according to parameters specified in IFIL structure
  951. */
  952. static int cre_ifil(dptr)
  953. IFIL *dptr;
  954. {
  955.     int i, j;                          /* counters */
  956.     IIDX *kptr;                        /* pointer to key info */
  957.     char *datnam, *idxnam;             /* fullnames of data and index files */
  958.     int stat;
  959.  
  960.     kptr = dptr->ix;                   /* dptr->ix is first key */
  961.  
  962.     datnam = alloc(strlen(dptr->pfilnam) + 5);
  963.     idxnam = alloc(strlen(dptr->pfilnam) + 5);
  964.     sprintf(datnam, "%s.dat", dptr->pfilnam);
  965.     sprintf(idxnam, "%s.idx", dptr->pfilnam);
  966.  
  967.                                        /* find consecutive filno's */
  968.     for(i = 0; i < (MAX_FILES_USED - dptr->dnumidx); i++)
  969.     {
  970.         for(j = 0; j <= dptr->dnumidx; j++)
  971.             if (filno_used[i + j] == TRUE)
  972.                 break;
  973.         if (j > dptr->dnumidx)
  974.             break;
  975.     }
  976.     if (i == (MAX_FILES_USED - dptr->dnumidx))
  977.         return(FUSE_ERR);              /* must be out of filno's */
  978.  
  979.     if (stat = CREDAT(i, datnam, dptr->dreclen, dptr->dxtdsiz, dptr->dfilmod))
  980.         return(stat);                  /* error creating datafile */
  981.  
  982.     if (stat = CREIDX(i + 1, idxnam, kptr->ikeylen, kptr->ikeytyp,
  983.         kptr->ikeydup, dptr->dnumidx - 1, dptr->ixtdsiz, dptr->ifilmod))
  984.     {                                  /* error creating the index file */
  985.         CLSFIL(i, dptr->dfilmod);
  986.         unlink(datnam);                /* so close and unlink data file */
  987.         free(datnam);
  988.         free(idxnam);
  989.         return(stat);
  990.     }
  991.  
  992.     for(j = 1; j < dptr->dnumidx; j++) /* add any additional keys */
  993.     {
  994.         kptr++;                        /* point to next one */
  995.         if(stat = CREMEM(i + 1, kptr->ikeylen, kptr->ikeytyp, kptr->ikeydup, j))
  996.             goto create_recover;
  997.     }
  998.  
  999. /*
  1000.  * This wasn't being done at first so we were getting FUSE_ERR (error # 46)
  1001.  * coming back at us...
  1002. */
  1003.     for(j = 0; j <= dptr->dnumidx; j++)/* flag the filno's as used */
  1004.         filno_used[i + j] = TRUE;
  1005.  
  1006.     dptr->tfilno = i;                  /* create successful, save file number */
  1007.     free(datnam);
  1008.     free(idxnam);
  1009.     return(NO_ERROR);
  1010.  
  1011. create_recover:
  1012.     CLSFIL(i, dptr->dfilmod);          /* recover from an error */
  1013.     CLSFIL(i + 1, dptr->ifilmod);       /* by closing and unlinking files */
  1014.     unlink(datnam);
  1015.     unlink(idxnam);
  1016.     free(datnam);
  1017.     free(idxnam);
  1018.     return(stat);                      /* then return the status... */
  1019. }
  1020.  
  1021. /*
  1022.  * cl_ifil() - close file(s)
  1023. */
  1024. static int cl_ifil(dptr)
  1025. IFIL *dptr;
  1026. {
  1027.     int i;                             /* counter */
  1028.  
  1029.     if (dptr->dnumidx > 0)             /* close .idx file */
  1030.         if (CLSFIL(dptr->dfilno + 1, PARTIAL))
  1031.             return(uerr_cod);
  1032.  
  1033.     if (CLSFIL(dptr->dfilno, PARTIAL))
  1034.         return(uerr_cod);              /* close .dat file */
  1035.  
  1036.     for(i = 0; i <= dptr->dnumidx; i++)
  1037.         filno_used[i + dptr->dfilno] = FALSE;
  1038.  
  1039.     return(IOGOOD);
  1040. }
  1041.  
  1042. /*
  1043.  * del_rec() - delete a record
  1044. */
  1045. static int del_rec(fd_sys)
  1046. int fd_sys;
  1047. {
  1048.     int i, stat;
  1049.     char *tmpbufp;                     /* pointer to temporary buffer */
  1050.     char *target;                      /* pointer to target key buffer */
  1051.     struct fd_def *fptr = &fd[fd_sys];
  1052.     struct cfd_def *cptr = &cfd[fd_sys];
  1053.     IFIL *dptr = &cptr->datafile;      /* pointer to IFIL info */
  1054.  
  1055.     tmpbufp = cptr->cur_recbuf;        /* allocate temporary buffer */
  1056.     
  1057.     if (!tmpbufp)
  1058.         return(ICUR_ERR);
  1059.  
  1060.     if (dptr->dnumidx > 0)             /* any indices must be deleted */
  1061.     {
  1062.         for(i = 0; i < dptr->dnumidx; i++)
  1063.         {                              /* allocate target key buffer */
  1064.             target = alloc(cptr->fdkey[i].ikeylen);
  1065.                                        /* transform and delete key */
  1066.             frm_key(fd_sys, i, tmpbufp, target, 0L);
  1067.             stat = DELCHK(dptr->dfilno + i + 1, target, cptr->cur_recbyt);
  1068.             free(target);              /* free target key buffer */
  1069.             if (stat)
  1070.                 return(uerr_cod);
  1071.         }
  1072.     }
  1073.     return(RETREC(dptr->dfilno, cptr->cur_recbyt));
  1074. }
  1075.  
  1076. /*
  1077.  * frm_key() - low level version of C-Tree's frmkey() function
  1078. */
  1079. #ifdef REVBIN
  1080. #undef REVBIN
  1081. #endif
  1082. #ifdef LOW_HIGH
  1083. #define REVBIN
  1084. #endif
  1085. #ifdef HIGH_LOW
  1086. #ifdef UNIFRMAT
  1087. #define REVBIN
  1088. #endif
  1089. #endif
  1090.  
  1091. static int frm_key(fd_sys, keyno, recptr, target, recbyt)
  1092. int fd_sys;
  1093. int keyno;
  1094. char *recptr;
  1095. char *target;
  1096. long recbyt;
  1097. {
  1098.     struct cfd_def *cptr = &cfd[fd_sys];
  1099.     IIDX *kptr = &cptr->fdkey[keyno];
  1100.     ISEG *sptr;
  1101.     int i, j, len, slen, mod;
  1102.     char *recpos;
  1103.  
  1104.     sptr = kptr->seg;
  1105.     for(i = len = 0; i < kptr->inumseg; i++, sptr++)
  1106.     {
  1107.         recpos = recptr + sptr->soffset;
  1108.         len += (slen = sptr->slength);
  1109.         mod = sptr->segmode;
  1110.         mod &= SEGMSK;    
  1111.         switch (mod)
  1112.         {
  1113.             case REGSEG:
  1114.             case SRLSEG:
  1115. #ifndef REVBIN
  1116.             case INTSEG:
  1117. #endif
  1118.                 for(j = 0; j++ < slen; )
  1119.                     *target++ = *recpos++;
  1120.                 break;
  1121. #ifdef REVBIN
  1122.             case INTSEG:
  1123.                 recpos += slen;
  1124.                 for(j = 0; j++ < slen; )
  1125.                     *target++ = *(--recpos);
  1126.                 break;
  1127. #endif
  1128.             case UREGSEG:
  1129.                 for(j = 0; j++ < slen; )
  1130.                     *target++ = toupper(*recpos++);
  1131.                 break;
  1132.             case SGNSEG:
  1133.             case FLTSEG:
  1134. #ifdef REVBIN
  1135.                 target += slen;
  1136.                 for(j = 0; j++ < slen; )
  1137.                     *(--target) = *recpos++;
  1138. #else
  1139.                 bytecpy(target, recpos, slen);
  1140. #endif
  1141.                 if (*target & 0x0080)
  1142.                 {
  1143.                     if (mod == SGNSEG)
  1144.                         *target &= 0x007f;
  1145.                 }
  1146.                 else
  1147.                     *target |= 0x0080;
  1148.                 target += slen;
  1149.                 break;
  1150.             default:
  1151.                 abort_mess("ABORT : Invalid segment mode in frm_key()...\n");
  1152.                 exit(-1);
  1153.                 break;
  1154.         }
  1155.     }
  1156.     slen = len;
  1157.     if (kptr->ikeydup)
  1158.     {
  1159.         recpos = (char *)&recbyt;
  1160.         len += sizeof(long);
  1161. #ifdef LOW_HIGH
  1162.         target += sizeof(long);
  1163.         for(j = 0; j < sizeof(long); j++)
  1164.             *--target = *recpos++;
  1165. #else
  1166.         for(j = 0; j < sizeof(long); j++)
  1167.             *target++ = *recpos++;
  1168. #endif
  1169.     }
  1170.     return(len);
  1171. }
  1172.  
  1173. /*
  1174.  * gte_rec() - read record with greater than or equal key value
  1175. */
  1176. static int gte_rec(fd_sys, target, recptr)
  1177. int fd_sys;
  1178. char *target;
  1179. char *recptr;
  1180. {
  1181.     long recbyt;                       /* byte offset of record */
  1182.     char *keybuf;                      /* pointer to key buffer */
  1183.     struct fd_def *fptr = &fd[fd_sys];
  1184.     struct cfd_def *cptr = &cfd[fd_sys];
  1185.     IFIL *dptr = &cptr->datafile;      /* pointer to IFIL info */
  1186.     IIDX *kptr;                        /* pointer for key info */
  1187.  
  1188.     if (!recptr)                       /* NULL record pointer */
  1189.         return(DNUL_ERR);
  1190.  
  1191.     kptr = &cptr->fdkey[fptr->cur_key];/* point to current key info */
  1192.     keybuf = alloc(kptr->ikeylen);     /* alloc key buffer */
  1193.     recbyt = GTEKEY(fptr->cur_key + dptr->dfilno + 1, target, keybuf);
  1194.  
  1195.     free(keybuf);                      /* get byte offset and free keybuf */
  1196.  
  1197.     if (!recbyt)                       /* match not found means...*/
  1198.     {
  1199.         if (uerr_cod)                  /* error, or... */
  1200.             return(uerr_cod);
  1201.         else                           /* just not there */
  1202.             return(INOT_ERR); 
  1203.     }
  1204.  
  1205.     if (lockit(fd_sys, recbyt, RLOCKON))/* lock the record... */
  1206.         return(DLOK_ERR);
  1207.                                        /* and read it */
  1208.     if (REDREC(dptr->dfilno, recbyt, recptr))
  1209.         return(uerr_cod);
  1210.  
  1211.     cptr->cur_recbyt = recbyt;         /* set current record offset */
  1212.     bytecpy(cptr->cur_recbuf, recptr, dptr->dreclen);
  1213.     return(NO_ERROR);
  1214. }
  1215.  
  1216. /*
  1217.  * lst_rec() - get last record
  1218. */
  1219. static int lst_rec(fd_sys, recptr)
  1220. int fd_sys;
  1221. char *recptr;
  1222. {
  1223.     long recbyt;                       /* byte offset of last record */
  1224.     char *target;                      /* pointer to target key buffer */
  1225.     struct fd_def *fptr = &fd[fd_sys];
  1226.     struct cfd_def *cptr = &cfd[fd_sys];
  1227.     IFIL *dptr = &cptr->datafile;      /* pointer to IFIL info */
  1228.     IIDX *kptr;                        /* pointer to key info */
  1229.  
  1230.     if (!recptr)                       /* NULL record pointer passed in */
  1231.         return(DNUL_ERR);
  1232.  
  1233.     kptr = &cptr->fdkey[fptr->cur_key];/* point to key info */
  1234.     target = alloc(kptr->ikeylen);     /* allocate target key buffer */
  1235.                                        /* find last key value */
  1236.     recbyt = LSTKEY(fptr->cur_key + dptr->dfilno + 1, target);
  1237.     free(target);                      /* free target key buffer */
  1238.  
  1239.     if (!recbyt)
  1240.     {
  1241.         if (uerr_cod)                  /* error getting last key */
  1242.             return(uerr_cod);
  1243.         else
  1244.             return(INOT_ERR);          /* no last key */
  1245.     }
  1246.  
  1247.     if (lockit(fd_sys, recbyt, RLOCKON))/* lock the record */
  1248.         return(DLOK_ERR);
  1249.                                        /* then read the record */
  1250.     if (REDREC(dptr->dfilno, recbyt, recptr))
  1251.         return(uerr_cod);
  1252.  
  1253.     cptr->cur_recbyt = recbyt;         /* update current record pointer */
  1254.     bytecpy(cptr->cur_recbuf, recptr, dptr->dreclen);
  1255.     return(NO_ERROR);
  1256. }
  1257.  
  1258. /*
  1259.  * nxt_rec() - get next record
  1260. */
  1261. static int nxt_rec(fd_sys, recptr)
  1262. int fd_sys;
  1263. char *recptr;
  1264. {
  1265.     long recbyt;                       /* byte offset of next record */
  1266.     char *oldrecp;                     /* pointer to buffer for old record */
  1267.     char *oldkeyp;                     /* pointer to buffer for old key */
  1268.     char *newkeyp;                     /* pointer to buffer for new key */
  1269.     struct fd_def *fptr = &fd[fd_sys];
  1270.     struct cfd_def *cptr = &cfd[fd_sys];
  1271.     IFIL *dptr = &cptr->datafile;      /* pointer to IFIL info */
  1272.     IIDX *kptr;                        /* pointer for key info */
  1273.  
  1274.     if (!recptr)
  1275.         return(DNUL_ERR);              /* NULL record pointer passed in */
  1276.  
  1277.     kptr = &cptr->fdkey[fptr->cur_key];/* point to current key's info */
  1278.  
  1279.     oldrecp = cptr->cur_recbuf;        /* allocate working buffers */
  1280.     oldkeyp = alloc(kptr->ikeylen);
  1281.     newkeyp = alloc(kptr->ikeylen);
  1282.                                        /* reread previous record */
  1283.     if (!oldrecp)
  1284.         return(ICUR_ERR);
  1285.                                        /* transform previous key */
  1286.     frm_key(fd_sys, fptr->cur_key, oldrecp, oldkeyp, cptr->cur_recbyt);
  1287.                                        /* get record > previous */
  1288.     recbyt = GTKEY(dptr->dfilno + fptr->cur_key + 1, oldkeyp, newkeyp);
  1289.  
  1290.     free(newkeyp);                     /* free working buffers */
  1291.     free(oldkeyp);
  1292.  
  1293.     if (!recbyt)                       /* GTKEY failed for some reason */
  1294.     {
  1295.         if (uerr_cod)                  /* error on GTKEY */
  1296.             return(uerr_cod);
  1297.         else                           /* end of file */
  1298.             return(INOT_ERR);
  1299.     }
  1300.  
  1301.     if (lockit(fd_sys, recbyt, RLOCKON))/* lock the record */
  1302.         return(DLOK_ERR);
  1303.                                        /* then read it in */
  1304.     if (REDREC(dptr->dfilno, recbyt, recptr))
  1305.         return(uerr_cod);
  1306.  
  1307.     cptr->cur_recbyt = recbyt;         /* set current record */
  1308.     bytecpy(cptr->cur_recbuf, recptr, dptr->dreclen);
  1309.     return(NO_ERROR);
  1310. }
  1311.  
  1312. /*
  1313.  * opn_ifil() - open file(s) according to parameters specified in IFIL structure
  1314. */
  1315. static int opn_ifil(dptr)
  1316. IFIL *dptr;
  1317. {
  1318.     int i, j;                          /* counters */
  1319.     int stat;                          /* return status */
  1320.     char *fullname;                    /* for expansion of filename */
  1321.  
  1322.                                        /* find consecutive filno's */
  1323.     for(i = 0; i < (MAX_FILES_USED - dptr->dnumidx); i++)
  1324.     {
  1325.         for(j = 0; j <= dptr->dnumidx; j++)
  1326.             if (filno_used[i + j] == TRUE)
  1327.                 break;
  1328.         if (j > dptr->dnumidx)
  1329.             break;
  1330.     }
  1331.     if (i == (MAX_FILES_USED - dptr->dnumidx))
  1332.         return(FUSE_ERR);              /* must be out of filno's */
  1333.  
  1334.                                        /* open data file */
  1335.     fullname = alloc(strlen(dptr->pfilnam) + 5);
  1336.     sprintf(fullname, "%s.dat", dptr->pfilnam);
  1337.     if (stat = OPNFIL(i, fullname, dptr->dfilmod))
  1338.     {
  1339.         free(fullname);
  1340.         return(stat);
  1341.     }
  1342.                                        /* open index file */
  1343.     sprintf(fullname, "%s.idx", dptr->pfilnam);
  1344.     if (stat = OPNFIL(i + 1, fullname, dptr->ifilmod))
  1345.     {
  1346.         CLSFIL(i, dptr->dfilmod);      /* open of index failed so close data */
  1347.         free(fullname);
  1348.         return(stat);
  1349.     }
  1350.  
  1351.     free(fullname);
  1352.     for(j = 0; j <= dptr->dnumidx; j++)
  1353.         filno_used[i + j] = TRUE;      /* opens were succesful, flag filno's */
  1354.  
  1355.     dptr->tfilno = i;                  /* OK! (return it in tfilno) */
  1356.  
  1357.     return(NO_ERROR);
  1358. }
  1359.  
  1360. /*
  1361.  * prv_rec() - get previous record
  1362. */
  1363. static int prv_rec(fd_sys, recptr)
  1364. int fd_sys;
  1365. char *recptr;
  1366. {
  1367.     long recbyt;                       /* byte offset of next record */
  1368.     char *oldrecp;                     /* pointer to buffer for old record */
  1369.     char *oldkeyp;                     /* pointer to buffer for old key */
  1370.     char *newkeyp;                     /* pointer to buffer for new key */
  1371.     struct fd_def *fptr = &fd[fd_sys];
  1372.     struct cfd_def *cptr = &cfd[fd_sys];
  1373.     IFIL *dptr = &cptr->datafile;      /* pointer to IFIL info */
  1374.     IIDX *kptr;                        /* pointer for key info */
  1375.  
  1376.     if (!recptr)
  1377.         return(DNUL_ERR);              /* NULL record pointer passed in */
  1378.  
  1379.     kptr = &cptr->fdkey[fptr->cur_key];/* point to current key's info */
  1380.  
  1381.     oldrecp = cptr->cur_recbuf;        /* allocate working buffers */
  1382.     oldkeyp = alloc(kptr->ikeylen);
  1383.     newkeyp = alloc(kptr->ikeylen);
  1384.                                        /* reread previous record */
  1385.     if (!oldrecp)
  1386.         return(ICUR_ERR);
  1387.                                        /* transform previous key */
  1388.     frm_key(fd_sys, fptr->cur_key, oldrecp, oldkeyp, cptr->cur_recbyt);
  1389.                                        /* get record > previous */
  1390.     recbyt = LTKEY(dptr->dfilno + fptr->cur_key + 1, oldkeyp, newkeyp);
  1391.  
  1392.     free(newkeyp);                     /* free working buffers */
  1393.     free(oldkeyp);
  1394.  
  1395.     if (!recbyt)                       /* LTKEY failed for some reason */
  1396.     {
  1397.         if (uerr_cod)                  /* error on LTKEY */
  1398.             return(uerr_cod);
  1399.         else                           /* end of file */
  1400.             return(INOT_ERR);
  1401.     }
  1402.  
  1403.     if (lockit(fd_sys, recbyt, RLOCKON))/* lock the record */
  1404.         return(DLOK_ERR);
  1405.                                        /* then read it in */
  1406.     if (REDREC(dptr->dfilno, recbyt, recptr))
  1407.         return(uerr_cod);
  1408.  
  1409.     cptr->cur_recbyt = recbyt;         /* set current record */
  1410.     bytecpy(cptr->cur_recbuf, recptr, dptr->dreclen);
  1411.     return(NO_ERROR);
  1412. }
  1413.  
  1414. /*
  1415.  * rrd_rec() - reread current record
  1416. */
  1417. static int rrd_rec(fd_sys, recptr)
  1418. int fd_sys;
  1419. char *recptr;
  1420. {
  1421.     struct cfd_def *cptr = &cfd[fd_sys];
  1422.     long recbyt = cptr->cur_recbyt;    /* byte offset of current record */
  1423.     int datno = cptr->datafile.dfilno; /* datafile number (C-Tree) */
  1424.  
  1425.     if (!recptr)
  1426.         return(DNUL_ERR);              /* Null record pointer passed in */
  1427.  
  1428. /*
  1429.  * This lock is a write lock since rrd_rec() is only used for updates...
  1430. */
  1431.     if (lockit(fd_sys, recbyt, WLOCKON))/* lock the record */
  1432.         return(DLOK_ERR);          
  1433.                                        /* read the record */
  1434.     return(REDREC(datno, recbyt, recptr));
  1435. }
  1436.  
  1437. /*
  1438.  * rwt_rec() - rewrite current record
  1439. */
  1440. static int rwt_rec(fd_sys, recptr)
  1441. int fd_sys;
  1442. char *recptr;
  1443. {
  1444.     struct cfd_def *cptr = &cfd[fd_sys];
  1445.     IFIL *dptr = &cptr->datafile;      /* pointer to IFIL info */
  1446.     int i;                             /* counter */
  1447.     char *target;                      /* target key buffer */
  1448.     int stat;                          /* status variable */
  1449.  
  1450.     if (!recptr)
  1451.         return(DNUL_ERR);              /* null record pointer passed in */
  1452.  
  1453.     for(i = 0; i < dptr->dnumidx; i++) /* update any indices */
  1454.     {
  1455.         /* first we have to delete the old key */
  1456.  
  1457.         target = alloc(cptr->fdkey[i].ikeylen);
  1458.                                        /* transform and delete key */
  1459.         frm_key(fd_sys, i, cptr->updbuf, target, 0L);
  1460.         stat = DELCHK(dptr->dfilno + i + 1, target, cptr->cur_recbyt);
  1461.         free(target);
  1462.         if (stat)
  1463.             return(uerr_cod);          /* error deleting key */
  1464.  
  1465.         /* now we add a new one */
  1466.  
  1467.         target = alloc(cptr->fdkey[i].ikeylen);
  1468.                                        /* transform and add key */
  1469.         frm_key(fd_sys, i, recptr, target, 0L);
  1470.         stat = ADDKEY(dptr->dfilno + i + 1, target, cptr->cur_recbyt, REGADD);
  1471.         free(target);
  1472.         if (stat)
  1473.             return(uerr_cod);          /* error adding key */
  1474.     }
  1475.                                        /* write out the data */
  1476.     if (WRTREC(dptr->dfilno, cptr->cur_recbyt, recptr))
  1477.         return(uerr_cod);
  1478.  
  1479.     return(NO_ERROR);                  /* OK, she be done! */
  1480. }
  1481.  
  1482.  
  1483. /*
  1484.  * Assign section
  1485. */
  1486.  
  1487. void assign_IO_CT(dbnum)
  1488. int dbnum;
  1489. {
  1490.    Fntab[dbnum - 1][0]  = (int(*)())0; /* Empty */
  1491.    Fntab[dbnum - 1][1]  = i_init_file;
  1492.    Fntab[dbnum - 1][2]  = i_open_file;
  1493.    Fntab[dbnum - 1][3]  = i_close_file;
  1494.    Fntab[dbnum - 1][4]  = i_addrec;
  1495.    Fntab[dbnum - 1][5]  = i_delrec;
  1496.    Fntab[dbnum - 1][6]  = i_findkey;
  1497.    Fntab[dbnum - 1][7]  = i_firstkey;
  1498.    Fntab[dbnum - 1][8]  = i_lastkey;
  1499.    Fntab[dbnum - 1][9]  = i_lockrec;
  1500.    Fntab[dbnum - 1][10] = i_nextrec;
  1501.    Fntab[dbnum - 1][11] = i_prevrec;
  1502.    Fntab[dbnum - 1][12] = i_unlock_rec;
  1503.    Fntab[dbnum - 1][13] = i_updrec;
  1504.    Fntab[dbnum - 1][14] = i_commit;
  1505.    Fntab[dbnum - 1][15] = i_login;
  1506.    Fntab[dbnum - 1][16] = i_logoff;
  1507.    Fntab[dbnum - 1][17] = i_rollback;
  1508.    Fntab[dbnum - 1][18] = i_transact;
  1509.    Fntab[dbnum - 1][19] = i_selectinx;
  1510.    Fntab[dbnum - 1][20] = i_rereadrec;
  1511.    Fntab[dbnum - 1][21] = i_filename;
  1512. }
  1513.