home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c004 / 1.ddi / CTINIT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-04-18  |  19.5 KB  |  960 lines

  1. /*
  2.  *    common utility routines
  3.  *
  4.  *    This program is the CONFIDENTIAL and PROPRIETARY property 
  5.  *    of FairCom(R) Corporation. Any unauthorized use, reproduction or
  6.  *    transfer of this program is strictly prohibited.
  7.  *
  8.  *      Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989 FairCom Corporation
  9.  *    (Subject to limited distribution and
  10.  *     restricted disclosure only.)
  11.  *    *** ALL RIGHTS RESERVED ***
  12.  *
  13.  *    4006 West Broadway
  14.  *    Columbia, MO 65203
  15.  *
  16.  *
  17.  *    c-tree(R)    Version 4.3
  18.  *            Release C
  19.  *            February 7, 1989 17:30
  20.  *
  21.  */
  22.  
  23. /*
  24.  * **** Remove the following define statement
  25.  */
  26.  
  27. #define NO_SPARSE
  28.  
  29. /*
  30.  * **** to allow sparse files on file extension.
  31.  */
  32.  
  33.  
  34. #include "ctstdr.h"        /* standard i/o header         */
  35. #include "ctoptn.h"        /* c-tree configuration options */
  36. #include "cterrc.h"        /* c-tree error codes        */
  37. #include "ctstrc.h"        /* c-tree data structures    */
  38. #include "ctgvar.h"        /* c-tree global variables    */
  39.  
  40. #ifdef KEYTEST
  41. #undef KEYTEST
  42. #endif
  43. #ifndef VARLKEYS
  44. #define KEYTEST
  45. #endif
  46. #ifndef FLOATKEY
  47. #ifndef KEYTEST
  48. #define KEYTEST
  49. #endif
  50. #endif
  51.  
  52.  
  53. #ifdef CTSERVER
  54. #include "ctcomm.h"
  55.  
  56. extern TEXT   *srvmsg,*srvdat;
  57. extern UCOUNT  srvsiz;
  58. extern MESSAGE omsg;
  59.  
  60. #ifndef NO_SPARSE
  61. #define NO_SPARSE
  62. #endif
  63.  
  64. #endif
  65.  
  66. RNDFILE mbopen();
  67. COUNT   mbclos(),ctio(),mbsave();
  68. VOID    terr();
  69.  
  70. /*
  71.  * see if update on read only file
  72.  */
  73.  
  74. chkredf(     ctnum)
  75. FAST CTFILE *ctnum;
  76. {
  77. #ifdef CTSERVER
  78.     ctnum  = ctnum->hmem;
  79. #else
  80.     ctnum -= ctnum->kmem;
  81. #endif
  82.     if (ctnum->flmode & READFIL)
  83.         return(uerr_cod = REDF_ERR);
  84.     else
  85.         return(NO_ERROR);
  86. }
  87.  
  88. /*
  89. ** find available ct file control blocks
  90. */
  91.  
  92. POINTER SERIALNUM(datno)
  93. PFAST COUNT      datno;
  94. {
  95. #ifdef FPUTFGET
  96.     COUNT         redhdr();
  97. #endif
  98.     CTFILE      *tstfnm();
  99.     FAST CTFILE *dnum;
  100.  
  101.     uerr_cod = 0;
  102.     if ((dnum = tstfnm(datno)) == NULL) /* then error condition */
  103.         return(DRNZERO);
  104.  
  105. #ifdef FPUTFGET
  106.     if ((dnum->flmode & SHARED) && redhdr(dnum)) /* then error */
  107.         return(DRNZERO);
  108. #endif
  109.     return(dnum->sernum);
  110. }
  111.  
  112.  
  113. #ifdef CTSERVER
  114.  
  115. COUNT avlfil;
  116.  
  117. COUNT getctf()
  118. {
  119.     FAST CTFILE *ctnum;
  120.  
  121.     if (avlfil <= 0)
  122.         return(-1);
  123.  
  124.     for (ctnum = ct_key; ctnum < ct_key + ct_mxfil; ctnum++)
  125.         if (ctnum->chnacs == 'n') {
  126.             avlfil--;
  127.             ctnum->chnacs = 'c';
  128.             ctnum->hmem   = ctnum;
  129.             ctnum->xmem   = NULL;
  130.             return((COUNT) (ctnum - ct_key));
  131.         }
  132.  
  133.     terr(997);
  134. }
  135.  
  136. COUNT getctm(blocks,btnum)
  137. COUNT         blocks;
  138. CTFILE           *btnum;
  139. {
  140.     FAST CTFILE *ctnum;
  141.     CTFILE        *ltnum;
  142.     FAST COUNT   i;
  143.     COUNT         j;
  144.  
  145.     if (blocks > avlfil)
  146.         return(-1);
  147.  
  148.     ltnum = btnum;
  149.     for (i = j = 0, ctnum = ct_key; i++ < ct_mxfil && j < blocks; ctnum++) {
  150.         if (ctnum->chnacs == 'n') {
  151.             ctnum->hmem   = btnum;
  152.             ltnum->xmem   = ctnum;
  153.             ltnum          = ctnum;
  154.             ctnum->chnacs = 'c';
  155.             j++;
  156.         }
  157.     }
  158.  
  159.     if (j < blocks)
  160.         terr(998);
  161.  
  162.     ltnum->xmem = NULL;
  163.     avlfil       -= blocks;
  164.  
  165.     return(0);
  166. }
  167.  
  168. VOID retctf(filno)
  169. COUNT        filno;
  170. {
  171.     FAST CTFILE *ctnum;
  172.  
  173.     ctnum = ct_key + filno;
  174.     do {
  175.         ctnum->chnacs = 'n';
  176.         ctnum         = ctnum->xmem;
  177.         avlfil++;
  178.     } while (ctnum != (CTFILE *) NULL);
  179. }
  180.  
  181. #else
  182.  
  183. COUNT STPUSR()
  184. {
  185.     return(uerr_cod = NO_ERROR);
  186. }
  187. COUNT TRANSACTION(mode)
  188. COUNT          mode;
  189. {
  190.     return(uerr_cod = NO_ERROR);
  191. }
  192.  
  193. #endif
  194.  
  195. /* --------------------------------------------------------------------
  196.    routine to initialize buffer space and status variables
  197.  */
  198.  
  199. COUNT INTREE(bufs,fils,sect)
  200.  
  201. COUNT bufs,fils,sect;
  202.  
  203. {
  204.     FAST COUNT i;
  205.     TREEBUFF  *buf;
  206.     CTFILE    *ctnum;
  207.     COUNT      valsiz;
  208.     TEXT      *buforg,*valoff;
  209.  
  210.     TEXT      *mballc();
  211.     COUNT       uerr();
  212.  
  213.     /*   
  214.      *    be sure that one and only one of each mutually 
  215.      *    exclusive choice has been selected and compose
  216.      *    version byte for header records.
  217.      */
  218.  
  219.  
  220. #ifndef LOW_HIGH
  221. #ifdef UNIFRMAT
  222.     ct_ver = (LH_VER | CT_V4E);
  223. #else
  224.     ct_ver = (HL_VER | CT_V4E);
  225. #endif
  226. #ifndef HIGH_LOW
  227.     terr(200);
  228. #endif
  229. #else
  230.     ct_ver = (LH_VER | CT_V4E);
  231. #ifdef  HIGH_LOW
  232.     terr(201);
  233. #endif
  234. #endif
  235.  
  236. /* ******************** */
  237.  
  238. #ifndef NOTFORCE
  239. #ifndef FPUTFGET
  240. #ifndef FPUTONLY
  241.     terr(202);
  242. #endif
  243. #endif
  244. #endif
  245.  
  246. #ifdef  NOTFORCE
  247. #ifdef  FPUTFGET
  248.     terr(203);
  249. #endif
  250. #ifdef  FPUTONLY
  251.     terr(203);
  252. #endif
  253. #else
  254. #ifdef  FPUTFGET
  255. #ifdef  FPUTONLY
  256.     terr(203);
  257. #endif
  258. #endif
  259. #endif
  260.  
  261.  
  262. /* ******************** */
  263.  
  264.     uerr_cod = 0;
  265.     if (bufs < 3 || sect < 1 || fils < 0)
  266.         return(uerr(SPRM_ERR));
  267.     if (ct_key != NULL)
  268.         return(uerr(IINT_ERR));
  269.  
  270.     if ((ct_btree = (TREEBUFF *) mballc(bufs,sizeof(TREEBUFF))) == NULL)
  271.         return(uerr(SPAC_ERR));
  272.     if ((ct_key = (CTFILE *) mballc(fils,sizeof(CTFILE))) == NULL) {
  273.         mbfree(ct_btree);
  274.         return(uerr(SPAC_ERR));
  275.     }
  276.     ct_dat = ct_key;
  277.     ct_vat = ct_key;
  278.  
  279.     valsiz = sect * SECSIZ + MAXLEN + sizeof(POINTER);
  280.     if ((ct_origin = (TEXT *) mballc(bufs,valsiz)) == NULL) {
  281.         mbfree(ct_key);
  282.         ct_key = NULL;
  283.         mbfree(ct_btree);
  284.         return(uerr(SPAC_ERR));
  285.     }
  286.     valoff = (buforg = ct_origin) + STATUS;
  287.  
  288.     ct_mxbuf = bufs;
  289. #ifdef CTSERVER
  290.     ct_mxfil = avlfil = fils;
  291. #else
  292.     ct_mxfil = fils;
  293. #endif
  294.     ct_ndsec = sect;
  295.     ct_lacs = ct_lfil = ct_numvfil = ct_npath[0] = 0;
  296.  
  297.     for (i = 0,buf = ct_btree; i++ < ct_mxbuf; buf++) {
  298.         buf->keyid = -1;
  299.         buf->update = 'n';
  300.         buf->nodacs = 0;
  301.         buf->nodorg = buforg;
  302.         buf->ct_kyval = valoff;
  303.         buforg += valsiz;
  304.         valoff += valsiz;
  305.     }
  306.  
  307.     for (i = 0,ctnum = ct_key; i++ < ct_mxfil; ctnum++) {
  308.         ctnum->usecnt = 0;
  309.         ctnum->chnacs = 'n';
  310.     }
  311.  
  312.     return(NO_ERROR);
  313. }
  314.  
  315.  
  316. /* ------------------------------------------------------------------
  317.    extend file size
  318. */
  319.  
  320. POINTER extfil(ctnum,rsize)
  321. PFAST CTFILE  *ctnum;
  322. unsigned int         rsize;
  323.  
  324. {    /* extfil assumes that (in multi-user system) header is locked */
  325.     POINTER retval,oldval;
  326. #ifdef NO_SPARSE
  327.     POINTER    oldphy;
  328.     FAST COUNT i;
  329. #endif
  330.  
  331.     COUNT   uerr();
  332.  
  333. #ifdef CTSERVER
  334.     omsg.mseqn     = 0;
  335.     ctnum           = ctnum->hmem;
  336. #else
  337.     ctnum         -= ctnum->kmem;
  338. #endif
  339.  
  340.     retval         = (oldval = ctnum->numrec) + 1;
  341.     ctnum->numrec += rsize;
  342. #ifdef NO_SPARSE
  343.     oldphy           = ctnum->phyrec;
  344. #endif
  345.     if (oldval > ctnum->numrec) {
  346.         uerr(FULL_ERR);
  347.         return(DRNZERO);
  348.     } else if (ctnum->numrec <= ctnum->phyrec)
  349.         return(retval);
  350.     else if (ctnum->extsiz <= rsize) {
  351.         ctnum->phyrec = ctnum->numrec;
  352.         return(retval);
  353.     } else { /* extend file by chunk and save directory contents */
  354.         if (ctnum->phyrec < (ctnum->extsiz - 1))
  355.             ctnum->phyrec  = ctnum->extsiz - 1;
  356.         else
  357.             ctnum->phyrec += ctnum->extsiz;
  358.  
  359.         if (ctnum->phyrec < ctnum->numrec) {
  360.             /* overflow */
  361.             ctnum->phyrec = ctnum->numrec;
  362.             return(retval);
  363.         }
  364. #ifdef NO_SPARSE
  365.         for (i = 0; i < CTBUFSIZ; i++)
  366.             ct_buf[i] = DELFLG;
  367.         for (i = (ctnum->phyrec - oldphy++) / CTBUFSIZ; i-- > 0; ) {
  368.             if (ctio(CTWRITE,ctnum,oldphy,ct_buf,CTBUFSIZ))
  369.                 break;
  370.             oldphy += CTBUFSIZ;
  371.         }
  372.         if (i = ctnum->phyrec - oldphy + 1) {
  373.             if (uerr_cod || ctio(CTWRITE,ctnum,oldphy,ct_buf,i)) {
  374.                 /* couldn't extend by a chunk */
  375.                 uerr_cod = 0;
  376.                 ctnum->phyrec = ctnum->numrec;
  377.                 return(retval);
  378.             }
  379.         }
  380. #else /* sparse */
  381.         ct_buf[0] = DELFLG;
  382.         if (ctnum->clstyp == DAT_CLOSE) /* fill-in delete flags */
  383.             for (oldval = retval; oldval < ctnum->phyrec;
  384.                 oldval += ctnum->reclen)
  385.                 if (ctio(CTWRITE,ctnum,oldval,ct_buf,1))
  386.                     break;
  387.         if (uerr_cod || ctio(CTWRITE,ctnum,ctnum->phyrec,ct_buf,1)) {
  388.             /* couldn't extend by a chunk */
  389.             uerr_cod = 0;
  390.             ctnum->phyrec = ctnum->numrec;
  391.             return(retval);
  392.         }
  393. #endif
  394.         if (mbsave(ctnum))
  395.             return(DRNZERO);
  396.         return(retval);
  397.     }
  398. }
  399.  
  400.  
  401. /* --------------------------------------------------------------------
  402.    utility to test for valid file number and determine if file
  403.    corresponding to ctnum has been activated. returns NULL ptr if error.
  404.  */
  405.  
  406. CTFILE *tstfnm(filno)
  407. COUNT          filno;
  408.  
  409. {
  410.     FAST CTFILE *retval,*ctnum;
  411.     COUNT        nomemb;
  412.  
  413.     COUNT        uerr();
  414.     UCOUNT         inrfil();
  415.  
  416.     uerr_cod = NO_ERROR;
  417. #ifndef CTSERVER
  418.     if (ct_mxfil == 0) {
  419.         uerr(FINT_ERR);
  420.         return(NULL);
  421.     } else
  422. #endif
  423.     if (filno < 0 || ct_mxfil <= filno) { /* filno out of range */
  424.         uerr(FNUM_ERR);
  425.         return(NULL);
  426.     } else
  427.         retval = ct_key + filno;
  428.  
  429.     switch (retval->chnacs) {
  430. case 'n':
  431.         uerr_cod = FACS_ERR;
  432.         return(NULL);
  433. case 'y':
  434.         retval->usecnt = inrfil(retval);
  435.         return(retval);
  436. case 'v':
  437. case 'w':
  438. #ifdef CTSERVER
  439.         ctnum           = retval->hmem;
  440. #else
  441.         ctnum          = retval - retval->kmem;
  442. #endif
  443.         nomemb         = ctnum->nmem;
  444.         ctnum->usecnt  = 0;
  445. #ifdef CT_ANSI
  446.         if ((ctnum->fd = mbopen(ctnum,ctnum->flmode)) ==
  447.             (RNDFILE) NULL) {
  448. #else
  449.         if ((ctnum->fd = mbopen(ctnum,ctnum->flmode)) < 0) {
  450. #endif
  451.             uerr_cod = VRTO_ERR;
  452.             return(NULL);
  453.         } else {
  454.             ctnum->usecnt = inrfil(retval);
  455. #ifdef CTSERVER
  456.             for (filno = 0; filno++ <= nomemb; ctnum = ctnum->xmem)
  457. #else
  458.             for (filno = 0; filno++ <= nomemb; ctnum++)
  459. #endif
  460.                 ctnum->chnacs = ctnum->chnacs == 'w' ? 'm' : 'y';
  461.             return(retval);
  462.         }
  463. default:
  464.         terr(222);
  465.     }
  466. }
  467.  
  468.  
  469. /* ------------------------------------------------------------ */
  470.  
  471. COUNT vtclose()
  472.  
  473. {
  474.     FAST CTFILE *ctnum;
  475.     CTFILE      *fndnum;
  476.     FAST COUNT   i;
  477.     UCOUNT       lstusd;
  478.  
  479.     COUNT CLSFIL();
  480.  
  481.     for (i = 0, ctnum = ct_key, fndnum = NULL, lstusd = MAXAGE;
  482.         i++ < ct_mxfil; ctnum++)
  483.         if (ctnum->usecnt && ctnum->usecnt <= lstusd &&
  484.             ctnum->chnacs == 'y' && ctnum->kmem < 1 &&
  485.             !(ctnum->flmode & PERMANENT) && !ctnum->lokcnt)
  486.             lstusd = (fndnum = ctnum)->usecnt;
  487.  
  488.     if ((ctnum = fndnum) == NULL)
  489.         return(NO);
  490.     else {
  491.         if (CLSFIL(ctnum->filnum,ctnum->flmode))
  492.                 return(NO);
  493.  
  494.         ctnum->usecnt = 0;
  495. #ifdef CTSERVER
  496.         for (i = 0; i++ <= fndnum->nmem; ctnum = ctnum->xmem)
  497. #else
  498.         for (i = 0; i++ <= fndnum->nmem; ctnum++)
  499. #endif
  500.             ctnum->chnacs = ctnum->chnacs == 'm' ? 'w' : 'v';
  501.         return(YES);
  502.     }
  503. }
  504.  
  505. /* ---------------------------------------------------------------- */
  506.  
  507. UCOUNT inrfil(ctnum)
  508. PFAST CTFILE *ctnum;
  509.  
  510. {
  511.     CTFILE      *calnum;
  512.     FAST COUNT   i;
  513.     UCOUNT       minage;
  514.  
  515. #ifdef CTSERVER
  516.     ctnum  = (calnum = ctnum)->hmem;
  517. #else
  518.     ctnum -= (calnum = ctnum)->kmem;
  519. #endif
  520.     if (ctnum->flmode & PERMANENT) /* not a virtual file */
  521.         return(0);
  522.     else if (++ct_lfil)        /* then file age did not rollover */
  523.         return(calnum->usecnt = ct_lfil);
  524.  
  525.     for (i = 0, ctnum = ct_key, minage = MAXAGE; i++ < ct_mxfil; ctnum++)
  526.         if (ctnum->usecnt && ctnum->usecnt <= minage &&
  527.             ctnum->kmem < 1)
  528.             minage = ctnum->usecnt;
  529.  
  530.     ct_lfil = MAXAGE - (--minage);
  531.     for (i = 0, ctnum = ct_key; i++ < ct_mxfil; ctnum++)
  532.         if (ctnum->usecnt)
  533.             ctnum->usecnt -= minage;
  534.     return(calnum->usecnt = ++ct_lfil);
  535. }
  536.  
  537. /* --------------------------------------------------------------------
  538.    test to see if update flag is set. if not, set it.
  539.  */
  540.  
  541. COUNT  tstupd(ctnum)
  542. PFAST CTFILE *ctnum;
  543.  
  544. {
  545. #ifdef NOTFORCE
  546.  
  547.     COUNT wrthdr();
  548.  
  549. #ifdef CTSERVER
  550.     ctnum  = ctnum->hmem;
  551. #else
  552.     ctnum -= ctnum->kmem;
  553. #endif
  554.     if (!(ctnum->updflg)) {
  555.         ctnum->updflg = UPDATED;
  556.         if (wrthdr(ctnum))
  557.             return(uerr_cod);
  558.     }
  559. #endif
  560.     return(NO_ERROR);
  561. }
  562.  
  563. #ifdef UNIFRMAT
  564.  
  565. VOID revwrd(tp,wrdcnt)
  566. PFAST TEXT *tp;
  567. PFAST COUNT    wrdcnt;
  568. {    /* assumes that revbyt alraedy called */
  569.     TEXT ch1,ch2;
  570.  
  571.     while (wrdcnt-- > 0) {
  572.         ch1      = *tp++;
  573.         ch2      = *tp++;
  574.         *(tp - 2) = *tp;
  575.         *tp++      = ch1;
  576.         *(tp - 2) = *tp;
  577.         *tp++      = ch2;
  578.     }
  579. }
  580.  
  581. VOID revhdr(ctnum)
  582. PFAST CTFILE *ctnum;
  583. {
  584.     revbyt(ctnum,8);
  585.     revbyt(&ctnum->nument,22);
  586.     revwrd(&ctnum->nument,7);
  587. }
  588.  
  589. #endif
  590.  
  591. /* --------------------------------------------------------------------
  592.    read file header record
  593. */
  594.  
  595. COUNT  redhdr(ctnum)
  596. PFAST CTFILE *ctnum;
  597. {
  598.     FAST COUNT    i;
  599.     COUNT        nomemb;
  600.     POINTER        recbyt;
  601. #ifdef CTSERVER
  602.     CTFILE           *mtnum;
  603.     COUNT        uerr();
  604.  
  605.     mtnum = ctnum;
  606. #endif
  607.  
  608.     if (ctio(CTREAD,ctnum,recbyt = DRNZERO,ctnum,HDRSIZ))
  609.         return(uerr_cod);
  610. #ifdef UNIFRMAT
  611.     revhdr(ctnum);
  612. #endif
  613.     if (ctnum->clstyp == IDX_CLOSE) {
  614.         nomemb = ctnum->nmem;
  615. #ifdef CTSERVER
  616.         if (getctm(nomemb,ctnum) < 0)
  617.             return(uerr(SNMC_ERR));
  618. #endif
  619.         for (i = 1; i <= nomemb; i++) {
  620.             recbyt += HDRSIZ;
  621. #ifdef CTSERVER
  622.             mtnum = mtnum->xmem;
  623.             if (ctio(CTREAD,ctnum,recbyt,mtnum,HDRSIZ))
  624. #else
  625.             if (ctio(CTREAD,ctnum,recbyt,ctnum + i,HDRSIZ))
  626. #endif
  627.                 return(uerr_cod);
  628. #ifdef UNIFRMAT
  629. #ifdef CTSERVER
  630.             revhdr(mtnum);
  631. #else
  632.             revhdr(ctnum + i);
  633. #endif
  634. #endif
  635.         }
  636.     }
  637.     return(NO_ERROR);
  638. }
  639.  
  640.  
  641. /* --------------------------------------------------------------------
  642.    write file header record
  643.  */
  644.  
  645. COUNT  wrthdr(ctnum)
  646. PFAST CTFILE *ctnum;
  647. {
  648.     FAST COUNT    i;
  649.     COUNT        nomemb;
  650.     POINTER        recbyt;
  651. #ifdef CTSERVER
  652.     FAST CTFILE    *mtnum;
  653.  
  654.     mtnum  = ctnum  = ctnum->hmem;
  655. #else
  656.     ctnum -= ctnum->kmem;
  657. #endif
  658.     nomemb = ctnum->nmem;
  659.     for (i = 0,recbyt = 0; i <= nomemb; i++,recbyt += HDRSIZ) {
  660. #ifdef UNIFRMAT
  661. #ifdef CTSERVER
  662.         cpybuf(ct_buf,mtnum,HDRSIZ);
  663. #else
  664.         cpybuf(ct_buf,ctnum + i,HDRSIZ);
  665. #endif
  666.         revhdr(ct_buf);
  667.         if (ctio(CTWRITE,ctnum,recbyt,ct_buf,HDRSIZ))
  668.             return(uerr_cod);
  669. #else
  670. #ifdef CTSERVER
  671.         if (ctio(CTWRITE,ctnum,recbyt,mtnum,HDRSIZ))
  672. #else
  673.         if (ctio(CTWRITE,ctnum,recbyt,ctnum + i,HDRSIZ))
  674. #endif
  675.             return(uerr_cod);
  676. #endif
  677. #ifdef CTSERVER
  678.         mtnum = mtnum->xmem;
  679. #endif
  680.     }
  681.  
  682.     return(NO_ERROR);
  683. }
  684.  
  685.  
  686. COUNT OPNFIL(filno,filnam,filmod)
  687. COUNT         filno;          /* data number temporary assigned to file */
  688. TEXT          *filnam;      /* pointer to file name */
  689. COUNT              filmod; /* EXCLUSIVE/SHARED   VIRTUAL/PERMANENT */
  690. {
  691.     FAST CTFILE *ctnum,*knum;
  692.     COUNT        opnflg;
  693. #ifdef KEYTEST
  694.     COUNT         i;
  695. #endif
  696.     COUNT        wrthdr(),redhdr(),uerr();
  697.  
  698.     uerr_cod = opnflg = NO;
  699.     ctnum = ct_key + filno;
  700.     if (filno < 0 || ct_mxfil <= filno)
  701.         uerr_cod = FNUM_ERR;
  702. #ifdef CTSERVER
  703.     else if (ctnum->chnacs != 'c')
  704.         terr(996);
  705. #else
  706.     else if (ctnum->chnacs != 'n')
  707.         uerr_cod = FUSE_ERR;
  708. #endif
  709.     else {
  710.         if ((filmod & NONEXCLUSIVE) == NONEXCLUSIVE)
  711.             /* set READFIL flag if SHARED & READFIL both on */
  712.             filmod &= ~SHARED;
  713.         strcpy(ctnum->flname,filnam);
  714.         ctnum->usecnt = 0;
  715. #ifdef CT_ANSI
  716.         if ((ctnum->fd = mbopen(ctnum,filmod)) == (RNDFILE) NULL)
  717. #else
  718.         if ((ctnum->fd = mbopen(ctnum,filmod)) < 0)
  719. #endif
  720.             /* does not exist */
  721.             uerr_cod = FNOP_ERR;
  722.         else {
  723.             opnflg = YES;
  724.             if (redhdr(ctnum))
  725.             /* no further action */ ;
  726.             else if (ctnum->clstyp < DAT_CLOSE ||
  727.               ctnum->clstyp > VAT_CLOSE)
  728.             uerr_cod = FUNK_ERR;
  729.             else if (ctnum->recsiz > (ct_ndsec * SECSIZ))
  730.             uerr_cod = KSIZ_ERR;
  731.             else if (ctnum->verson != ct_ver)
  732.             uerr_cod = FVER_ERR;
  733.             else if (ctnum->length > MAXLEN)
  734.             uerr_cod = KLEN_ERR;
  735.             else if (ctnum->updflg == COMPACT)
  736.             uerr_cod = FCMP_ERR;
  737.             else if (ctnum->nmem > MAXMEMB || ctnum->kmem > 0)
  738.             uerr_cod = KMEM_ERR;
  739.             else if (ctnum->updflg || (ctnum->clstyp != IDX_CLOSE &&
  740.              ctnum->nmem > 0))
  741.             uerr_cod = FCRP_ERR;
  742. #ifndef VARLDATA
  743.             else if (ctnum->clstyp == VAT_CLOSE)
  744.             uerr_cod = FTYP_ERR;
  745. #endif
  746.  
  747. #ifdef KEYTEST
  748. #ifdef CTSERVER
  749.             else for (knum = ctnum, i = 0; i <= ctnum->nmem; i++,
  750.               knum = knum->xmem) {
  751. #else
  752.             else for (knum = ctnum, i = 0; i <= ctnum->nmem; i++,
  753.               knum++) {
  754. #endif
  755. #ifndef VARLKEYS
  756.                 if (knum->ktype & COL_BOTH)
  757.                 uerr_cod = KTYP_ERR;
  758. #endif
  759. #ifndef FLOATKEY
  760.                 if (knum->ktype == SFLOATKEY ||
  761.                  knum->ktype == DFLOATKEY)
  762.                 uerr_cod = KTYP_ERR;
  763. #endif
  764.             }
  765. #endif
  766.         }
  767.     }
  768.  
  769.     if (uerr_cod) {
  770.         if (opnflg)
  771.             mbclos(ctnum,COMPLETE);
  772.         return(uerr_cod);
  773.     } else {
  774.         if (ctnum->clstyp == VAT_CLOSE)
  775.             filmod |= VLENGTH;
  776.         if (ctnum->flmode != filmod) {
  777.             if (!((ctnum->flmode = filmod) & READFIL) &&
  778.                 wrthdr(ctnum)) {
  779.                 opnflg = uerr_cod;
  780.                 mbclos(ctnum,COMPLETE);
  781.                 return(uerr(opnflg));
  782.             }
  783.         }
  784.         ctnum->filnum = filno;
  785.         ctnum->usecnt = inrfil(ctnum);
  786.         ctnum->srlpos = 0;
  787. #ifdef CTSERVER
  788.         for (knum = ctnum, filno = 0; filno <= ctnum->nmem; filno++,
  789.             knum = knum->xmem) {
  790.             if (knum->chnacs != 'c')
  791.                 terr(994);
  792.             knum->filnum = (COUNT) (knum - ct_key);
  793.             if (filno != 0)
  794. #ifdef CT_ANSI
  795.                 knum->fd = (RNDFILE) NULL;
  796. #else
  797.                 knum->fd = -1;
  798. #endif
  799. #else
  800.         for (knum = ctnum; filno <= (ctnum->filnum + ctnum->nmem); 
  801.             filno++,knum++) {
  802.             if (knum->chnacs != 'n' && knum->chnacs != 'm') {
  803.                 mbclos(ctnum,COMPLETE);
  804.                 return(uerr(FUSE_ERR));
  805.             }
  806.             knum->filnum = filno;
  807.             if (filno > ctnum->filnum)
  808. #ifdef CT_ANSI
  809.                 knum->fd = (RNDFILE) NULL;
  810. #else
  811.                 knum->fd = -1;
  812. #endif
  813. #endif
  814.             knum->chnacs = 'y';
  815.             knum->retelm = knum->lokcnt = 0;
  816.             knum->retnod = NODEZERO;
  817.         }
  818.         return(NO_ERROR);
  819.     }
  820. }
  821.  
  822. /* --------------------------------------------------------------------
  823.    write node contained in buffer to disk file. returns non-zero value if
  824.    error.
  825.  */
  826.  
  827. COUNT wrtnod(   buffer)
  828. PFAST TREEBUFF *buffer;     /* pointer to buffer containing node to be 
  829.                        written to disk */
  830. {
  831.     FAST KEYFILE *knum; /* key number pointer */
  832.     COUNT membno;
  833.  
  834. /* set file pointer & member # */
  835.  
  836.     membno = (knum = ct_key + buffer->keyid)->kmem;
  837.     if (membno > 0)
  838. #ifdef CTSERVER
  839.         knum  = knum->hmem;
  840. #else
  841.         knum -= membno;
  842. #endif
  843.  
  844. /* check member number */
  845.  
  846.     if (buffer->bmem != membno)
  847.         terr(230);
  848.  
  849. /* move node status info to i/o buffer */
  850.  
  851.     cpybuf(buffer->nodorg,&buffer->sucesr,STATUS);
  852.  
  853. #ifdef UNIFRMAT
  854.     revbyt(buffer->nodorg,6);
  855.     revwrd(buffer->nodorg,2);
  856. #endif
  857.  
  858. /* write node to disk */
  859.  
  860.     if (ctio(CTWRITE,knum,buffer->nodeid,buffer->nodorg,knum->recsiz))
  861.         return(uerr_cod);
  862.  
  863.     buffer->update = 'n';
  864.  
  865. #ifdef FPUTFGET
  866.  
  867. /* clobber buffer status information so that subsequent calls to getnod
  868.    will not think that buffer contains a valid node
  869.  */
  870.     if (knum->flmode & SHARED) {
  871.         buffer->keyid  = -1;
  872.         buffer->nodeid = -1;
  873.     }
  874. #endif
  875.  
  876.     return(NO_ERROR);
  877. }
  878.  
  879.  
  880. /* --------------------------------------------------------------------
  881.    routine to close files
  882.  */
  883.  
  884. COUNT CLSFIL(filno,filmod)
  885. COUNT filno;
  886. COUNT filmod;    /* COMPLETE or PARTIAL */ 
  887. {
  888.     FAST COUNT     i;
  889.     FAST CTFILE   *ctnum;
  890.     FAST TREEBUFF *buf;
  891.     CTFILE        *knum;
  892.     COUNT          lowi,hghi;
  893.  
  894.     COUNT wrthdr(),wrtnod(),uerr();
  895.  
  896.     uerr_cod = 0;
  897.     ctnum = ct_key + filno;
  898.     if (filno < 0 || ct_mxfil <= filno)
  899.         return(uerr(FNUM_ERR));
  900.     else if (ctnum->chnacs == 'n')
  901.         return(uerr(FACS_ERR));
  902.     else if (ctnum->kmem > 0)
  903.         return(uerr(KMEM_ERR));
  904.     else if (ctnum->chnacs == 'v') {
  905. #ifdef CTSERVER
  906.         for (i = 0, knum = ctnum; i++ <= ctnum->nmem; knum = knum->xmem)
  907. #else
  908.         for (i = 0, knum = ctnum; i++ <= ctnum->nmem; knum++)
  909. #endif
  910.         knum->chnacs = 'n';
  911.         return(NO_ERROR);
  912.     }
  913.  
  914.  
  915.     if (ctnum->clstyp != DAT_CLOSE) {
  916. #ifdef CTSERVER
  917. #ifdef EXTRABFR
  918.         if clsxbuf(filno))
  919.         return(uerr_cod);
  920. #endif
  921.         for (i = 0, buf = ct_btree; i < ct_mxbuf; i++, buf++) {
  922.         if (buf->keyid >= 0 && (ct_key + buf->keyid)->hmem == ctnum) {
  923. #else
  924.         lowi = ctnum->filnum;
  925.         hghi = lowi + ctnum->nmem;
  926.         for (i = 0, buf = ct_btree; i < ct_mxbuf; i++, buf++) {
  927.         if (buf->keyid >= lowi && buf->keyid <= hghi) {
  928. #endif
  929.             if (buf->update == 'y') {
  930.                 if (ctnum->updflg) {
  931.                     if (wrtnod(buf))
  932.                         return(uerr_cod);
  933.                 } else
  934.                     terr(206);
  935.             }
  936.             buf->keyid = -1;
  937.         }
  938.         }
  939.     }
  940.  
  941. #ifdef CTSERVER
  942.     for (i = 0,knum = ctnum; i++ <= ctnum->nmem; knum = knum->xmem)
  943. #else
  944.     for (i = 0,knum = ctnum; i++ <= ctnum->nmem; knum++)
  945. #endif
  946.         if (knum->chnacs != 'm') knum->chnacs = 'n';
  947.  
  948.     if (ctnum->updflg) {
  949.         ctnum->updflg = NO;
  950.         if (wrthdr(ctnum))
  951.             return(uerr_cod);
  952.     }
  953.     
  954.     if (mbclos(ctnum,filmod) < 0)
  955.         return(uerr(FCLS_ERR));
  956.     return(NO_ERROR);
  957. }
  958.  
  959. /* end of ctinit.c */
  960.