home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / c / kafsrt20.zip / KAFS.C < prev    next >
C/C++ Source or Header  |  1993-05-28  |  17KB  |  554 lines

  1. /****************************************************************
  2.  * KAFS.C
  3.  *
  4.  *    Keyed Access File Definitions
  5.  *
  6.  * Keyed Access File System Version 2.0
  7.  *
  8.  * 2.0  Revised to contain keys and data in a single file.
  9.  *      Key Access Files (KAF) are self contained.
  10.  * 9/23/92 - Added 'filecommit' function in KAFS.
  11.  * 2.1  11/11/92 - Qualified rec value for delete, read_rec, write_rec
  12.  *
  13.  ****************************************************************/
  14. #include <dos.h>
  15. #include <fcntl.h>
  16. #include <stdio.h>
  17. #include <math.h>
  18. #include <sys\stat.h>
  19.  
  20.  
  21. /**********************************************************
  22.  *    Key Access files definitions
  23.  **********************************************************/
  24.  
  25. #define TRUE 1
  26. #define FALSE 0
  27.  
  28. #define OK 0
  29. #define SOF -1        /* Start of File */
  30. #define FCLOSED -1
  31. #define ERR -1
  32. #define NOTFOUND -2
  33. #define FILEFULL -3
  34. #define KAEOF -4            /* Reached End Of File on Sequential Read */
  35.  
  36. /**
  37.  ** KEY ACCESS ERROR CODES - Value held in kaerror global Variable
  38.  **
  39.  1 - File Already Open
  40.  2 - Not a valid KAFSII file
  41.  3 - Error Attempting to Open Data File
  42.  4 - File Not Open
  43.  5 - Seek Error on Data File
  44.  6 - Read Error on Data File
  45.  7 - Write Error on Data File
  46.  8 - Error Reading Hash Index Block
  47.  9 - Error Writing Hash Index Block
  48. 10 - Invalid Channel Number 
  49. 11 - Passed Key Argument exceeds keysize
  50. 12 - File Name too Long or Invalid
  51. 13 - Rec exceeds file's extent
  52. **
  53. **/
  54.  
  55.  
  56.  
  57. #define HBLOCKSIZE 1024
  58. #define KEYSTART 128    /* Start of File's Key Blocks */
  59. #define KEYFILES 16     /* Number of key files allowed */
  60. #define MAXRECSIZE 512  /* Maximum Record Size allowed */
  61. #define MAXKEYSIZE 40   /* Maximum Key Size allowed */
  62.  
  63. /* ------------- File Definition Structure (Allow 256 Bytes) --------- */
  64. struct fildef {
  65.    char signature[7];   /* KAFSII */
  66.    char filename[16];   /* User's File Name */
  67.    int keysize;         /* Size of Key Field */
  68.    int recsize;         /* Size of a Record */
  69.    long records;        /* Number of Records */
  70.    int kpb;             /* Keys per Block */
  71.    long hblocks;         /* Hash blocks (calculated) */
  72.    long dbeg;           /* File Position for Data Beginning */
  73.    };
  74.  
  75. /* ------------- File Table Definition ---------------- */
  76. struct ft {
  77.   int handle;    /* Data File's handle */
  78.   int keysize;   /* Size of the key field */
  79.   int recsize;   /* Size of record */
  80.   char fname[16];/* Filename (User's) */
  81.   long records;  /* File defined max records */
  82.   long hblocks;   /* Hash blocks (calculated) */
  83.   int kpb;       /* Keys per block (calculated) */
  84.   long dbeg;     /* File position for beginning of Data */
  85. };
  86.  
  87.  
  88. /*********************************************************************
  89.  * Function Prototypes
  90.  *********************************************************************/
  91.  
  92. int ka_open(int, char *);
  93. void ka_close_all(void);
  94. void ka_close(int);
  95. int read_key(int, char *, void *);
  96. int read_rec(int, void *);
  97. int read_xrec(int, void *);
  98. int write_key(int, char *, void *);
  99. int write_rec(int, void *);
  100. int write_upd(int, void *);
  101. int rdelete(int, long);
  102. int read_seq(int, void *);
  103. int read_hblk(int, long);
  104. int write_hblk(int, long);
  105. long khash(char *, long);
  106.  
  107. void filecommit(int);
  108.  
  109. char hbuf[HBLOCKSIZE];  /* Define the Hash Buffer */
  110. long rec;               /* Global Record Number */
  111. int kaerror = 0;        /* Global Error Code */
  112. char *kaversion = "V2.01 - 11/11/92";    /* Version 2.0 */
  113. char key[MAXKEYSIZE+1]; /* Global Key 40 chars max */
  114.  
  115. /* Define the file table structure */
  116. struct ft ftbl[KEYFILES+1]=
  117. {-1,0,0,"",0,0,0,0,
  118. -1,0,0,"",0,0,0,0,
  119. -1,0,0,"",0,0,0,0,
  120. -1,0,0,"",0,0,0,0,
  121. -1,0,0,"",0,0,0,0,
  122. -1,0,0,"",0,0,0,0,
  123. -1,0,0,"",0,0,0,0,
  124. -1,0,0,"",0,0,0,0,
  125. -1,0,0,"",0,0,0,0,
  126. -1,0,0,"",0,0,0,0,
  127. -1,0,0,"",0,0,0,0,
  128. -1,0,0,"",0,0,0,0,
  129. -1,0,0,"",0,0,0,0,
  130. -1,0,0,"",0,0,0,0,
  131. -1,0,0,"",0,0,0,0,
  132. -1,0,0,"",0,0,0,0};
  133.  
  134. struct fildef fdef;        /* File Definition structure */
  135.  
  136.  
  137. /********************************************************************
  138.  * KA_OPEN - Open a keyed access file.
  139.  *
  140.  * All Keyed Access files have the extension 'KAF'.
  141.  *
  142.  ********************************************************************/
  143. ka_open(int fn, char * fname)
  144. {
  145.  unsigned mode;
  146.  char buffer[256]; /* Used to build filename & read in file defs */
  147.  
  148.  if(strlen(fname)>76)  /* Validate filename parameter */
  149.    {
  150.    kaerror = 12;  /* Filename too Long */
  151.    return(ERR);
  152.    }
  153.  
  154.  if(fn <0 || fn >= KEYFILES)  /* Validate filenumber */
  155.    {
  156.    kaerror = 10;  /* Invalid Channel Number */
  157.    return(ERR);
  158.    }
  159.  
  160.  if(ftbl[fn].handle != -1)
  161.    {
  162.    kaerror = 1;
  163.    return(ERR);  /* File already Open */
  164.    }
  165.  
  166.  strcpy(buffer, fname);  /* Build the KAF filename */
  167.  strcat(buffer, ".KAF");
  168.  
  169.  /*
  170.   * Set the mode for opening or for Creating a new file
  171.   */
  172.  mode = O_RDWR | O_BINARY | O_DENYNONE;
  173.  
  174.  ftbl[fn].handle = open(buffer, mode ,S_IREAD | S_IWRITE);
  175.  if(ftbl[fn].handle==ERR)
  176.    {
  177.    kaerror = 3;  /* Unable to Open File */
  178.    return(ERR);
  179.    }
  180.  
  181.  /*
  182.   * Read the File's Definition and set the file table values
  183.   */
  184.  if(read(ftbl[fn].handle, &fdef, sizeof(fdef))==ERR ||
  185.      strcmp(fdef.signature, "KAFSII"))
  186.       {
  187.       kaerror = 2;  /* Not a KAFSII file */
  188.       return(ERR);
  189.       }
  190.  
  191.  ftbl[fn].keysize = fdef.keysize;  /* size of key */
  192.  ftbl[fn].recsize = fdef.recsize;  /* Record size */
  193.  ftbl[fn].records = fdef.records;
  194.  ftbl[fn].kpb = fdef.kpb;           /* Keys per Block */
  195.  ftbl[fn].hblocks =fdef.hblocks; /* Number of hash Blocks */
  196.  ftbl[fn].dbeg = fdef.dbeg;      /* Start of Data Pointer */
  197.  strcpy(ftbl[fn].fname, fdef.filename);
  198.  return(OK);
  199. }
  200.  
  201. /** --------  Close Files -------- */
  202. void ka_close_all(void)
  203. {
  204.    int i;
  205.    for(i=0;i<KEYFILES;i++) ka_close(i);
  206. }
  207. void ka_close(int fn)
  208. {
  209.  if(ftbl[fn].handle > -1) close(ftbl[fn].handle);
  210.  ftbl[fn].handle = -1;
  211. }
  212.  
  213. /** -----------------------------------------------------------------
  214.  ** READ_KEY - Read a key access file by key.
  215.  **    This function hashes the key to find the record if Rec = SOF
  216.  **    If Rec != SOF reads for key at rec + 1
  217.  ** ----------------------------------------------------------------- */
  218. read_key(int fn, char *keyarg, void *buffer)
  219. {
  220.  long hblk;
  221.  long startblock;  /* Starting point for search */
  222.  int brec;       /* Record number in Block  */
  223.  char *hp;
  224.  
  225.  key[0]=0;      /* Blank Key for Return */
  226.  if(ftbl[fn].handle == FCLOSED || fn < 0 || fn >= KEYFILES)
  227.    {
  228.    kaerror = 4;  /* File not open */
  229.    return(ERR);
  230.    }
  231.  
  232.  if(rec==SOF)
  233.    {
  234.    hblk = khash(keyarg, ftbl[fn].hblocks);  /* Get the Hashed Block */
  235.    rec = hblk * ftbl[fn].kpb;   /* Calculate record number at beginning */
  236.    }
  237.    else
  238.       {
  239.       rec++;
  240.       if(rec > ftbl[fn].records) rec = 0;  /* Wrap At EOF */
  241.       hblk = (long)rec/ftbl[fn].kpb;             /* Or block based on rec */
  242.       }
  243.   
  244.  if(read_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR);
  245.  startblock = hblk;               /* Save for wrap-arounds */
  246.  brec = rec - (hblk * ftbl[fn].kpb);
  247.  hp = hbuf + (brec * ftbl[fn].keysize);  /* point to Record in Buffer */
  248.  while(TRUE)
  249.    {
  250.     if(*hp == 0) return(NOTFOUND);
  251.     if(!strcmp(hp,keyarg))
  252.       {
  253.       strcpy(key,hp);   /* copy the key */
  254.       return(read_xrec(fn, buffer)); /* FOUND */
  255.       }
  256.     rec++;                    /* Bump the record number */
  257.     brec++;                   /* Bump the block record number */
  258.     hp += ftbl[fn].keysize;   /* Move the Pointer to the next key */
  259.     if(brec>=ftbl[fn].kpb)
  260.       {
  261.      hblk++;
  262.      if(hblk >= ftbl[fn].hblocks) hblk=0;  /* Wrap around at EOF */
  263.      if(hblk == startblock) return(NOTFOUND);  /* Oops We wrapped around */
  264.      if(read_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR);  /* Read Nxt Blk */
  265.      hp = hbuf;               /* Point to beginning of block */
  266.      brec = 0;
  267.      rec = hblk * ftbl[fn].kpb;  /* Calculate Record # */
  268.       }
  269.    }
  270. }
  271.  
  272. /** -----------------------------------------------------------------
  273.  ** READ_REC - External Access to Read a key access file by Record Number.
  274.  **   This function reads only the Data portion of a record.
  275.  **   Returns the key for the record in global key.
  276.  **
  277.  ** 2.0 Modified to Add Data Offset 
  278.  ** ----------------------------------------------------------------- */
  279. read_rec(int fn, void *buffer)
  280. {
  281.    long hblk;  /* Hash Block number */
  282.    int brec;
  283.    char *kp;
  284.  
  285.    if(read_xrec(fn, buffer)==ERR) return(ERR); /* Get Data First */
  286.  
  287.    hblk = (long)rec / ftbl[fn].kpb;   /* get the hash index block no. */
  288.    if(read_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR);
  289.    brec = rec-(hblk * ftbl[fn].kpb); /* Rec # offset into this block */
  290.    kp = hbuf + (brec * ftbl[fn].keysize);  /* point to the record */
  291.    strcpy(key,kp);  /* Copy in the Key */
  292.    return(OK);
  293. }
  294. /** -----------------------------------------------------------------
  295.  ** READ_XREC - Internal Access to Read a key access file by Record Number.
  296.  **   This function reads only the Data portion of a record.
  297.  ** ----------------------------------------------------------------- */
  298. read_xrec(int fn, void *buffer)
  299. {
  300.    long fpos;
  301.  
  302.    if(ftbl[fn].handle == FCLOSED || fn < 0 || fn >= KEYFILES)
  303.     {
  304.     kaerror = 4;  /* File not open */
  305.     return(ERR);
  306.     }
  307.  
  308.    if(rec > ftbl[fn].records || rec < 0)
  309.       {
  310.       kaerror = 13;  /* Beyond File Limit */
  311.       return(ERR);
  312.       }
  313.    fpos = ((long)rec * ftbl[fn].recsize) + ftbl[fn].dbeg;
  314.    if(lseek(ftbl[fn].handle,fpos,0)==ERR)
  315.       {
  316.       kaerror = 5;  /* Seek Error on Data File */
  317.       return(ERR);
  318.       }
  319.  
  320.    if(read(ftbl[fn].handle, buffer,(unsigned)ftbl[fn].recsize)==ERR)
  321.       {
  322.       kaerror = 6;  /* Read Error on Data File */
  323.       return(ERR);
  324.       }
  325.       return(OK);
  326. }
  327.  
  328. /** -----------------------------------------------------------------
  329.  ** WRITE_KEY - Write a new record to a key access file by key.
  330.  **    This function hashes the key to find the record.
  331.  ** ----------------------------------------------------------------- */
  332. write_key(int fn, char *keyarg, void *buffer)
  333. {
  334.  long hblk;
  335.  long startblock;  /* Starting point for search */
  336.  int brec;       /* Record number in Block  */
  337.  char *hp;
  338.  
  339.    if(ftbl[fn].handle == FCLOSED || fn < 0 || fn >= KEYFILES)
  340.     {
  341.     kaerror = 4;  /* File not open */
  342.     return(ERR);
  343.     }
  344.  
  345.  if(strlen(keyarg)>ftbl[fn].keysize-1)
  346.    {
  347.    kaerror = 11;  /* key too big */
  348.    return(ERR);
  349.    }
  350.  
  351.  hblk = khash(keyarg, ftbl[fn].hblocks);  /* Get the Hashed Block */
  352.  if(read_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR);
  353.  hp = hbuf;   /* Point to beginning of Buffer */
  354.  rec = hblk * ftbl[fn].kpb;   /* Calculate record number */
  355.  startblock = hblk;               /* Save for wrap-arounds */
  356.  brec = 0;
  357.  while(1)
  358.    {
  359.     if(*hp < 02)  /* Found an Empty Slot, empty (00) or deleted (01) */
  360.       {
  361.        if(write_rec(fn, buffer)==ERR) return(ERR);  /* Write the Data */
  362.        strcpy(hp,keyarg);   /* Copy in the Key */
  363.        if(write_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR);
  364.           else return(OK);
  365.       }
  366.     rec++;                    /* Bump the record number */
  367.     brec++;                   /* Bump the block record number */
  368.     hp += ftbl[fn].keysize;   /* Move the Pointer to the next key */
  369.     if(brec>=ftbl[fn].kpb)
  370.       {
  371.      hblk++;
  372.      if(hblk >= ftbl[fn].hblocks) hblk=0;  /* Wrap around at EOF */
  373.      if(hblk == startblock) return(FILEFULL);  /* Oops We wrapped around */
  374.      if(read_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR);  /* Read Nxt Blk */
  375.      hp = hbuf;               /* Point to beginning of block */
  376.      brec = 0;
  377.      rec = hblk * ftbl[fn].kpb;  /* Calculate Record # */
  378.       }
  379.    }
  380. }
  381.  
  382. /** -----------------------------------------------------------------
  383.  ** WRITE_REC - Write a record to a key access file by Record #.
  384.  **    This function only writes the Data Portion of a record
  385.  **
  386.  ** 2.0 Modified to add data beginning offset
  387.  **
  388.  ** ----------------------------------------------------------------- */
  389. write_rec(int fn, void *buffer)
  390. {
  391.    int fh;
  392.    long fpos;
  393.  
  394.    if(ftbl[fn].handle == FCLOSED || fn < 0 || fn >= KEYFILES)
  395.     {
  396.     kaerror = 4;  /* File not open */
  397.     return(ERR);
  398.     }
  399.  
  400.    if(rec > ftbl[fn].records || rec < 0)
  401.       {
  402.       kaerror = 13;  /* Beyond File Limit */
  403.       return(ERR);
  404.       }
  405.  
  406.    fh = ftbl[fn].handle;   /* Set file handle */
  407.    fpos = ((long)rec * ftbl[fn].recsize) + ftbl[fn].dbeg;
  408.  
  409.    if(lseek(fh,fpos,0)==ERR)
  410.       {
  411.       kaerror = 5;  /* Seek Error */
  412.       return(ERR);
  413.       }
  414.    if(write(fh, buffer,(unsigned)ftbl[fn].recsize)==ERR)
  415.       {
  416.       kaerror = 7;  /* Write Error */
  417.       return(ERR);
  418.       }
  419.    return(OK);
  420. }
  421. write_upd(int fn, void *buffer)
  422. {
  423.    return(write_rec(fn, buffer));
  424. }
  425.  
  426. /** -----------------------------------------------------------------
  427.  ** RDELETE - Delete a record in a key access file by record number.
  428.  **    The record must have previously been read and rec # obtained
  429.  ** ----------------------------------------------------------------- */
  430. rdelete(int fn, long delrec)
  431. {
  432.    long hblk;
  433.    int brec;
  434.    char * hp;
  435.  
  436.    if(ftbl[fn].handle == FCLOSED || fn < 0 || fn >= KEYFILES)
  437.     {
  438.     kaerror = 4;  /* File not open */
  439.     return(ERR);
  440.     }
  441.  
  442.    if(rec > ftbl[fn].records || rec < 0)
  443.       {
  444.       kaerror = 13;  /* Beyond File Limit */
  445.       return(ERR);
  446.       }
  447.  
  448.    rec = delrec;
  449.    hblk = (long)delrec / ftbl[fn].kpb;   /* get the hash index block no. */
  450.    if(read_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR); /* read it */
  451.    brec = rec-(hblk * ftbl[fn].kpb); /* Rec # offset into this block */
  452.    hp = hbuf + (brec * ftbl[fn].keysize);  /* point to the record */
  453.    *hp = 01;  /* Delete the Record */
  454.    if(write_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR); /* Write it */
  455.    return(OK);
  456. }
  457.  
  458. /** -----------------------------------------------------------------
  459.  ** READ_SEQ - Read sequential.  Reads next record based on rec.
  460.  **  Esentially reads rec+1 for next available record.
  461.  ** ----------------------------------------------------------------- */
  462. read_seq(int fn, void *buffer)
  463. {
  464.   long hblk;
  465.   int brec;
  466.   char *hp;
  467.  
  468.    if(ftbl[fn].handle == FCLOSED || fn < 0 || fn >= KEYFILES)
  469.     {
  470.     kaerror = 4;  /* File not open */
  471.     return(ERR);
  472.     }
  473.  
  474.   key[0]=0;   /* Null the key */
  475. while(TRUE)
  476. {
  477.   if(rec+1 > ftbl[fn].records) return(KAEOF); /* End of file */
  478.   rec++;            /* increment record */
  479.   hblk = rec / ftbl[fn].kpb;   /* get the hash index block no. */
  480.   if(read_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR);
  481.   brec = rec-(hblk * ftbl[fn].kpb); /* Rec # offset into this block */
  482.   hp = hbuf + (brec * ftbl[fn].keysize);  /* point to the record */
  483.   if(*hp > 2)
  484.    {
  485.     strcpy(key, hp);  /* Copy the key into the key storage */
  486.     return(read_xrec(fn, buffer));  /* Read the record & return */
  487.    }
  488.   if(*hp == 0)   /* NO more recs this block */
  489.    {
  490.      hblk++;
  491.      if(hblk >= ftbl[fn].hblocks) return(KAEOF);  /* At EOF */
  492.      rec = (hblk * ftbl[fn].kpb)-1;  /* Get beginning rec number -1 */
  493.    }
  494.  }
  495. }
  496.  
  497. /** -----------------------------------------------------------------
  498.  ** READ_HBLK - Read Hash Block to Hash Block Buffer
  499.  **
  500.  ** 2.0 Modified to add key offset
  501.  ** ----------------------------------------------------------------- */
  502. read_hblk(int fh, long blkno)
  503. {
  504.  kaerror = 8;
  505.  if(lseek(fh, ((long)blkno * HBLOCKSIZE)+KEYSTART, 0)==ERR) return(ERR);
  506.  return(read(fh, hbuf, (unsigned)HBLOCKSIZE));
  507. }
  508.  
  509. /** -----------------------------------------------------------------
  510.  ** WRITE_HBLK - Write Hash Block from Hash Block Buffer
  511.  **
  512.  ** 2.0 Modified to add key offset
  513.  ** ----------------------------------------------------------------- */
  514. write_hblk(int fh, long blkno)
  515. {
  516.  kaerror = 9;
  517.  if(lseek(fh, ((long)blkno * HBLOCKSIZE)+KEYSTART, 0)==ERR) return(ERR);
  518.  return(write(fh, hbuf, (unsigned)HBLOCKSIZE));
  519. }
  520.  
  521. /** ------------------------------------------------------------------
  522.  ** KHASH - Hash a key and return the hash block number
  523.  ** ------------------------------------------------------------------ */
  524. long khash(char *hkey, long blocks)
  525. {
  526.  char *hp;
  527.  double hc;
  528.  long val;
  529.  
  530.  hc = (double)blocks-1;
  531.  hp = hkey;  /* Point to key for Hashing */
  532.  while (*hp) hc += *hp++ - 32;
  533.  val = (long)fmod(hc, (double)blocks);
  534.  return(val);
  535. }
  536.  
  537. /**************************************************************************
  538.  * FILECOMMIT - Commit a file's changes etc to disk.  Flush.
  539.  *************************************************************************/
  540. void filecommit(int fnum)
  541. {
  542.    union REGS regs;
  543.    int rc, ec;
  544.  
  545.    regs.h.ah = 0x68;  /* Call to Flush */
  546.    regs.x.bx = ftbl[fnum].handle;  /* Give the file's handle */
  547.  
  548.    intdos(®s, ®s);
  549.    rc = regs.x.cflag;
  550.    if(rc != 0) ec = _doserrno;
  551.  
  552. }
  553.  
  554.