home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / CBASE101.ZIP / BLKIO112.ZIP / BOPS.C < prev    next >
Text File  |  1990-06-20  |  14KB  |  592 lines

  1. /*    Copyright (c) 1989 Citadel    */
  2. /*       All Rights Reserved        */
  3.  
  4. /* #ident    "@(#)bops.c    1.4 - 90/06/20" */
  5.  
  6. /* ansi headers */
  7. #include <errno.h>
  8. /*#include <stddef.h>*/
  9. /*#include <stdlib.h>*/
  10. /*#include <string.h>*/
  11.  
  12. /* non-ansi headers */
  13. #include <bool.h>
  14.  
  15. /* local headers */
  16. #include "blkio_.h"
  17.  
  18. /*man---------------------------------------------------------------------------
  19. NAME
  20.      b_alloc - allocate memory for block file
  21.  
  22. SYNOPSIS
  23.      #include "blkio_.h"
  24.  
  25.      int b_alloc(bp)
  26.      BLKFILE *bp;
  27.  
  28. DESCRIPTION
  29.      The b_alloc function allocates the memory needed by bp.  The
  30.      memory is initialized to all zeros.  A call to b_alloc should
  31.      normally be followed by a call to b_initlist to construct the
  32.      linked list for LRU replacement.
  33.  
  34.      b_alloc will fail if one or more of the following is true:
  35.  
  36.      [EINVAL]       bp is not a valid BLKFILE pointer.
  37.      [ENOMEM]       Enough memory is not available for
  38.                     allocation by the calling process.
  39.      [BENOPEN]      bp is not open.
  40.  
  41. SEE ALSO
  42.      b_free, b_initlist.
  43.  
  44. DIAGNOSTICS
  45.      Upon successful completion, a value of 0 is returned.  Otherwise,
  46.      a value of -1 is returned, and errno set to indicate the error.
  47.  
  48. ------------------------------------------------------------------------------*/
  49. int b_alloc(bp)
  50. BLKFILE *bp;
  51. {
  52. #ifdef DEBUG
  53.     /* validate arguments */
  54.     if (!b_valid(bp)) {
  55.         BEPRINT;
  56.         errno = EINVAL;
  57.         return -1;
  58.     }
  59.  
  60.     /* check if not open */
  61.     if (!(bp->flags & BIOOPEN)) {
  62.         BEPRINT;
  63.         errno = BENOPEN;
  64.         return -1;
  65.     }
  66.  
  67.     /* check for memory leak */
  68.     if (bp->blockp != NULL || bp->blkbuf != NULL && !(bp->flags & BIOUSRBUF)) {
  69.         BEPRINT;
  70.         errno = BEPANIC;
  71.         return -1;
  72.     }
  73. #endif
  74.     /* check if not buffered */
  75.     if (bp->bufcnt == 0) {
  76.         errno = 0;
  77.         return 0;
  78.     }
  79.  
  80.     /* allocate buffer storage (one extra block structure for header) */
  81.     bp->blockp = (block_t *)calloc(bp->bufcnt + 1, sizeof(block_t));
  82.     if (bp->blockp == NULL) {
  83.         BEPRINT;
  84.         errno = ENOMEM;
  85.         return -1;
  86.     }
  87.     if (!(bp->flags & BIOUSRBUF)) {
  88.         bp->blkbuf = calloc((size_t)1, bp->hdrsize + bp->bufcnt * bp->blksize);
  89.         if (bp->blkbuf == NULL) {
  90.             BEPRINT;
  91.             free(bp->blockp);
  92.             bp->blockp = NULL;
  93.             errno = ENOMEM;
  94.             return -1;
  95.         }
  96.     }
  97.  
  98.     errno = 0;
  99.     return 0;
  100. }
  101.  
  102. /*man---------------------------------------------------------------------------
  103. NAME
  104.      b_blockp - pointer to block structure
  105.  
  106. SYNOPSIS
  107.      #include "blkio_.h"
  108.  
  109.      block_t *b_blockp(bp, i)
  110.      BLKFILE *bp;
  111.      size_t i;
  112.  
  113. DESCRIPTION
  114.      b_blockp returns a pointer to the ith block structure in the
  115.      buffer list of block file bp.  If bp is not a valid open block
  116.      file or i is not in the range [0..bp->bufcnt] the results are
  117.      undefined.  b_blockp is a macro.
  118.  
  119. ------------------------------------------------------------------------------*/
  120. /* b_blockp is defined in blkio_.h */
  121.  
  122. /*man---------------------------------------------------------------------------
  123. NAME
  124.      b_blkbuf - pointer to block buffer
  125.  
  126. SYNOPSIS
  127.      #include "blkio_.h"
  128.  
  129.      void *b_blkbuf(bp, i)
  130.      BLKFILE *bp;
  131.      size_t i;
  132.  
  133. DESCRIPTION
  134.      b_blkbuf returns a pointer to the ith buffer in the buffer list
  135.      of block file bp.  A value of zero for i indicates the header
  136.      buffer.  If bp is not a valid BLKFILE pointer to an open file or
  137.      i is not in the range [0..bp->bufcnt] the results are undefined.
  138.      b_blkbuf is a macro.
  139.  
  140. ------------------------------------------------------------------------------*/
  141. /* b_blkbuf is defined in blkio_.h */
  142.  
  143. /*man---------------------------------------------------------------------------
  144. NAME
  145.      b_free - free memory allocated for block file
  146.  
  147. SYNOPSIS
  148.      #include "blkio_.h"
  149.  
  150.      void b_free(bp)
  151.      BLKFILE *bp;
  152.  
  153. DESCRIPTION
  154.      The b_free function frees all memory allocated for block file bp.
  155.      If bp has a user-supplied buffer storage area, it is disconnected
  156.      from bp but is not freed.  On return from b_free, bp->blockp and
  157.      bp->blkbuf will be NULL.
  158.  
  159. SEE ALSO
  160.      b_alloc.
  161.  
  162. ------------------------------------------------------------------------------*/
  163. void b_free(bp)
  164. BLKFILE *bp;
  165. {
  166. #ifdef DEBUG
  167.     /* validate arguments */
  168.     if (!b_valid(bp)) {
  169.         BEPRINT;
  170.         return;
  171.     }
  172. #endif
  173.     /* free memory */
  174.     if (!(bp->flags & BIOUSRBUF)) {        /* if not user-supplied buf */
  175.         if (bp->blkbuf != NULL) {        /* free buffer */
  176.             free(bp->blkbuf);
  177.         }
  178.     }
  179.     bp->blkbuf = NULL;            /* disconnect buffer */
  180.     if (bp->blockp != NULL) {
  181.         free(bp->blockp);
  182.         bp->blockp = NULL;
  183.     }
  184.  
  185.     return;
  186. }
  187.  
  188. /*man---------------------------------------------------------------------------
  189. NAME
  190.      b_get - get block from block file
  191.  
  192. SYNOPSIS
  193.      #include "blkio_.h"
  194.  
  195.      int b_get(bp, i)
  196.      BLKFILE *bp;
  197.      size_t i;
  198.  
  199. DESCRIPTION
  200.      The b_get function reads a block from block file bp into the ith
  201.      buffer for that block file.  b_get reads the block identified by
  202.      the block number field of the block structure associated with
  203.      buffer i (i.e., b_blockp(bp, i)->bn); the zeroth buffer is
  204.      always used for the header.  The read flag is set and all others
  205.      cleared for buffer i.
  206.  
  207.      b_get will fail if one or more of the following is true:
  208.  
  209.      [EINVAL]       bp is not a valid BLKFILE pointer.
  210.      [EINVAL]       i is not in the range [0..bp->bufcnt].
  211.      [BEEOF]        End of file occured before end of block.
  212.      [BENBUF]       bp is not buffered.
  213.  
  214. SEE ALSO
  215.      b_put.
  216.  
  217. DIAGNOSTICS
  218.      Upon successful completion, a value of 0 is returned.  Otherwise,
  219.      a value of -1 is returned, and errno set to indicate the error.
  220.  
  221. ------------------------------------------------------------------------------*/
  222. int b_get(bp, i)
  223. BLKFILE *bp;
  224. size_t i;
  225. {
  226. #ifdef DEBUG
  227.     /* validate arguments */
  228.     if (!b_valid(bp)) {
  229.         BEPRINT;
  230.         errno = EINVAL;
  231.         return -1;
  232.     }
  233.  
  234.     /* check if not open */
  235.     if (!(bp->flags & BIOOPEN)) {
  236.         BEPRINT;
  237.         errno = BENOPEN;
  238.         return -1;
  239.     }
  240.  
  241.     /* check if file is not buffered */
  242.     if (bp->bufcnt == 0) {
  243.         BEPRINT;
  244.         errno = BENBUF;
  245.         return -1;
  246.     }
  247.  
  248.     /* validate arguments */
  249.     if (i > bp->bufcnt) {
  250.         BEPRINT;
  251.         errno = EINVAL;
  252.         return -1;
  253.     }
  254.  
  255.     /* check if block number set */
  256.     if ((b_blockp(bp, i)->bn == 0) && (i != 0)) {
  257.         BEPRINT;
  258.         errno = BEPANIC;
  259.         return -1;
  260.     }
  261.  
  262.     /* check if block needs to be written to disk */
  263.     if (b_blockp(bp, i)->flags & BLKWRITE) {
  264.         BEPRINT;
  265.         errno = BEPANIC;
  266.         return -1;
  267.     }
  268. #endif
  269.     /* read block from file */
  270.     if (i == 0) {
  271.         if (b_ugetf(bp, (bpos_t)0, (size_t)0, b_blkbuf(bp, (size_t)0), bp->hdrsize) == -1) {
  272.             BEPRINT;
  273.             return -1;
  274.         }
  275.     } else {
  276.         if (b_ugetf(bp, b_blockp(bp, i)->bn, (size_t)0, b_blkbuf(bp, i), bp->blksize) == -1) {
  277.             BEPRINT;
  278.             return -1;
  279.         }
  280.     }
  281.  
  282.     /* set read flag and clear all others */
  283.     b_blockp(bp, i)->flags = BLKREAD;
  284.  
  285.     errno = 0;
  286.     return 0;
  287. }
  288.  
  289. /*man---------------------------------------------------------------------------
  290. NAME
  291.      b_initlist - build linked list
  292.  
  293. SYNOPSIS
  294.      #include "blkio_.h"
  295.  
  296.      int b_initlist(bp)
  297.      BLKFILE *bp;
  298.  
  299. DESCRIPTION
  300.      The b_initlist function builds the linked list of buffers for
  301.      block file bp.  The buffer contents are deleted in the process.
  302.      A call to b_initlist should normally follow a call to b_alloc.
  303.  
  304.      b_initlist will fail if one or more of the following is true:
  305.  
  306.      [EINVAL]       bp is not a valid block file.
  307.  
  308. SEE ALSO
  309.      b_alloc.
  310.  
  311. DIAGNOSTICS
  312.      Upon successful completion, a value of 0 is returned.  Otherwise,
  313.      a value of -1 is returned, and errno set to indicate the error.
  314.  
  315. ------------------------------------------------------------------------------*/
  316. int b_initlist(bp)
  317. BLKFILE *bp;
  318. {
  319.     size_t i = 0;
  320.  
  321. #ifdef DEBUG
  322.     /* validate arguments */
  323.     if (!b_valid(bp)) {
  324.         BEPRINT;
  325.         errno = EINVAL;
  326.         return -1;
  327.     }
  328.  
  329.     /* check if not open */
  330.     if (!(bp->flags & BIOOPEN)) {
  331.         BEPRINT;
  332.         errno = BENOPEN;
  333.         return -1;
  334.     }
  335. #endif
  336.     /* initialize head and tail of list */
  337.     bp->most = 0;
  338.     bp->least = 0;
  339.  
  340.     /* check if not buffered */
  341.     if (bp->bufcnt == 0) {
  342.         errno = 0;
  343.         return 0;
  344.     }
  345.  
  346.     /* initialize linked list */
  347.     bp->most = bp->bufcnt;
  348.     bp->least = 1;
  349.     for (i = 1; i <= bp->bufcnt; ++i) {
  350.         b_blockp(bp, i)->bn = 0;
  351.         b_blockp(bp, i)->flags = 0;
  352.         b_blockp(bp, i)->more = i + 1;
  353.         b_blockp(bp, i)->less = i - 1;
  354.     }
  355.     b_blockp(bp, bp->most)->more = 0;
  356.     b_blockp(bp, bp->least)->less = 0;
  357.  
  358.     /* initialize block structure for header */
  359.     b_blockp(bp, (size_t)0)->bn = 0;
  360.     b_blockp(bp, (size_t)0)->flags = 0;
  361.     b_blockp(bp, (size_t)0)->more = 0;
  362.     b_blockp(bp, (size_t)0)->less = 0;
  363.  
  364.     /* scrub buffer storage area */
  365.     memset(bp->blkbuf, 0, bp->hdrsize + bp->bufcnt * bp->blksize);
  366.  
  367.     errno = 0;
  368.     return 0;
  369. }
  370.  
  371. /*man---------------------------------------------------------------------------
  372. NAME
  373.      b_mkmru - make most recently used block
  374.  
  375. SYNOPSIS
  376.      #include "blkio_.h"
  377.  
  378.      int b_mkmru(bp, i)
  379.      BLKFILE *bp;
  380.      size_t i;
  381.  
  382. DESCRIPTION
  383.      The b_mkmru function moves the ith block in the buffer list to
  384.      the most recently used end of the buffer list.
  385.  
  386.      b_mkmru will fail if one or more of the following is true:
  387.  
  388.      [EINVAL]       bp is not a valid block file.
  389.      [EINVAL]       i is not in the range [1..bp->bufcnt].
  390.      [BENBUF]       bp is not buffered.
  391.  
  392. DIAGNOSTICS
  393.      Upon successful completion, a value of 0 is returned.  Otherwise,
  394.      a value of -1 is returned, and errno set to indicate the error.
  395.  
  396. ------------------------------------------------------------------------------*/
  397. int b_mkmru(bp, i)
  398. BLKFILE *bp;
  399. size_t   i;
  400. {
  401.     size_t more = 0;
  402.     size_t less = 0;
  403.  
  404. #ifdef DEBUG
  405.     /* validate arguments */
  406.     if (!b_valid(bp)) {
  407.         BEPRINT;
  408.         errno = EINVAL;
  409.         return -1;
  410.     }
  411.  
  412.     /* check if not open */
  413.     if (!(bp->flags & BIOOPEN)) {
  414.         BEPRINT;
  415.         errno = BENOPEN;
  416.         return -1;
  417.     }
  418.  
  419.     /* check if file is not buffered */
  420.     if (bp->bufcnt == 0) {
  421.         BEPRINT;
  422.         errno = BENBUF;
  423.         return -1;
  424.     }
  425.  
  426.     /* validate arguments */
  427.     if (i < 1 || i > bp->bufcnt) {
  428.         BEPRINT;
  429.         errno = EINVAL;
  430.         return -1;
  431.     }
  432. #endif
  433.     /* check block addresses */
  434.     more = b_blockp(bp, i)->more;
  435.     less = b_blockp(bp, i)->less;
  436.     if (more > bp->bufcnt || less > bp->bufcnt) {
  437.         BEPRINT;
  438.         errno = BEPANIC;
  439.         return -1;
  440.     }
  441.  
  442.     /* check if already most recently used */
  443.     if (more == 0) {
  444.         errno = 0;
  445.         return 0;
  446.     }
  447.  
  448.     /* remove block i from linked list */
  449.     b_blockp(bp, more)->less = less;
  450.     if (less != 0) {
  451.         b_blockp(bp, less)->more = more;
  452.     } else {
  453.         bp->least = more;
  454.     }
  455.  
  456.     /* connect ith block as most recently used */
  457.     b_blockp(bp, i)->more = 0;
  458.     b_blockp(bp, i)->less = bp->most;
  459.     b_blockp(bp, bp->most)->more = i;
  460.     bp->most = i;
  461.  
  462.     errno = 0;
  463.     return 0;
  464. }
  465.  
  466. /*man---------------------------------------------------------------------------
  467. NAME
  468.      b_put - put block into block file
  469.  
  470. SYNOPSIS
  471.      #include "blkio_.h"
  472.  
  473.      int b_put(bp, i)
  474.      BLKFILE *bp;
  475.      size_t i;
  476.  
  477. DESCRIPTION
  478.      The b_put function writes a block from the ith buffer of block
  479.      file bp to the file.  b_put writes to the block identified by
  480.      the block number field of the block structure associated with
  481.      buffer i (i.e., b_blockp(bp, i)->bn); the zeroth buffer is
  482.      always used for the header.  If the write flag is not set,
  483.      nothing is written.  After writing, the write flag is cleared.
  484.  
  485.      b_put will fail if one or more of the following is true:
  486.  
  487.      [EINVAL]       bp is not a valid block file.
  488.      [EINVAL]       i is not in the range [0..bp->bufcnt].
  489.      [BENBUF]       bp is not buffered.
  490.  
  491. SEE ALSO
  492.      b_get.
  493.  
  494. DIAGNOSTICS
  495.      Upon successful completion, a value of 0 is returned.  Otherwise,
  496.      a value of -1 is returned, and errno set to indicate the error.
  497.  
  498. ------------------------------------------------------------------------------*/
  499. int b_put(bp, i)
  500. BLKFILE *bp;
  501. size_t i;
  502. {
  503. #ifdef DEBUG
  504.     /* validate arguments */
  505.     if (!b_valid(bp)) {
  506.         BEPRINT;
  507.         errno = EINVAL;
  508.         return -1;
  509.     }
  510.  
  511.     /* check if not open */
  512.     if (!(bp->flags & BIOOPEN)) {
  513.         BEPRINT;
  514.         errno = BENOPEN;
  515.         return -1;
  516.     }
  517.  
  518.     /* check if file is not buffered */
  519.     if (bp->bufcnt == 0) {
  520.         BEPRINT;
  521.         errno = BENBUF;
  522.         return -1;
  523.     }
  524.  
  525.     /* validate arguments */
  526.     if (i > bp->bufcnt) {
  527.         BEPRINT;
  528.         errno = EINVAL;
  529.         return -1;
  530.     }
  531. #endif
  532.     /* check if block doesn't need to be written to disk */
  533.     if (!(b_blockp(bp, i)->flags & BLKWRITE)) {
  534.         errno = 0;
  535.         return 0;
  536.     }
  537.  
  538.     /* check for inconsistent read flag setting */
  539.     if (!(b_blockp(bp, i)->flags & BLKREAD)) {
  540.         BEPRINT;
  541.         errno = BEPANIC;
  542.         return 0;
  543.     }
  544.  
  545.     /* write block to disk */
  546.     if (i == 0) {
  547.         if (b_uputf(bp, (bpos_t)0, (size_t)0, b_blkbuf(bp, (size_t)0), bp->hdrsize) == -1) {
  548.             BEPRINT;
  549.             return -1;
  550.         }
  551.     } else {
  552.         if (b_uputf(bp, b_blockp(bp, i)->bn, (size_t)0, b_blkbuf(bp, i), bp->blksize) == -1) {
  553.             BEPRINT;
  554.             return -1;
  555.         }
  556.     }
  557.  
  558.     /* clear all but read flag */
  559.     b_blockp(bp, i)->flags = BLKREAD;
  560.  
  561.     errno = 0;
  562.     return 0;
  563. }
  564.  
  565. /*man---------------------------------------------------------------------------
  566. NAME
  567.      b_valid - validate block file pointer
  568.  
  569. SYNOPSIS
  570.      #include "blkio_.h"
  571.  
  572.      bool b_valid(bp)
  573.      BLKFILE *bp;
  574.  
  575. DESCRIPTION
  576.      The b_valid function determines if bp is a valid BLKFILE pointer.
  577.      If valid, the TRUE is returned.  If not, then FALSE is returned.
  578.  
  579. ------------------------------------------------------------------------------*/
  580. bool b_valid(bp)
  581. const BLKFILE *bp;
  582. {
  583.     if (bp < biob || bp > (biob + BOPEN_MAX - 1)) {
  584.         return FALSE;
  585.     }
  586.     if (((char *)bp - (char *)biob) % sizeof(*biob) != 0) {
  587.         return FALSE;
  588.     }
  589.  
  590.     return TRUE;
  591. }
  592.