home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / EXTRAS / UUCODE / UUPC / TEST / UPC12ES4.ZIP / RNEWS / hdbm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-07  |  5.2 KB  |  236 lines

  1. /* hdbm.c
  2.  *
  3.  * simple history database manager for UUPC news
  4.  *
  5.  * Author:  Kai Uwe Rommel <rommel@ars.muc.de>
  6.  * Created: Sun Aug 15 1993
  7.  */
  8.  
  9. static char *rcsid = "$Id: hdbm.c 1.2 1993/11/06 17:54:55 rhg Exp $";
  10. static char *rcsrev = "$Revision: 1.2 $";
  11.  
  12. /* $Log: hdbm.c $
  13.  * Revision 1.2  1993/11/06  17:54:55  rhg
  14.  * Drive Drew nuts by submitting cosmetic changes mixed in with bug fixes
  15.  *
  16.  * Revision 1.1  1993/09/05  10:56:49  rommel
  17.  * Initial revision
  18.  * */
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <io.h>
  24. #include <fcntl.h>
  25.  
  26. #include "hdbm.h"
  27. #include "idx.h"
  28.  
  29. datum nullitem = {NULL, 0};
  30.  
  31. DBM *dbm_open(char *name, int flags, int mode)
  32. {
  33.   DBM *db;
  34.   char filename[_MAX_PATH];
  35.  
  36.   if ((db = (DBM *) malloc(sizeof(DBM))) == NULL)
  37.     return NULL;
  38.  
  39.   strcpy(filename, name);
  40.   strcat(filename, DBM_EXT_DBF);
  41.  
  42.   if ((db -> dbffile = open(filename, flags | O_BINARY, mode)) == -1)
  43.     return NULL;
  44.  
  45.   strcpy(filename, name);
  46.   strcat(filename, DBM_EXT_IDX);
  47.  
  48.   if ((db -> idxfile = open(filename, flags | O_BINARY, mode)) == -1)
  49.     return close(db -> dbffile), NULL;
  50.  
  51.   if ((db -> idx = idx_init(db -> idxfile)) == NULL)
  52.     return close(db -> dbffile), close(db -> idxfile), NULL;
  53.  
  54.   db -> magic = DBM_MAGIC;
  55.  
  56.   return db;
  57. }
  58.  
  59. void dbm_close(DBM *db)
  60. {
  61.   if (db == NULL || db -> magic != DBM_MAGIC)
  62.     return;
  63.  
  64.   idx_exit(db -> idx);
  65.  
  66.   close(db -> idxfile);
  67.   close(db -> dbffile);
  68.  
  69.   free(db);
  70. }
  71.  
  72. #ifdef __TURBOC__
  73. #pragma argsused
  74. #elif _MSC_VER >= 700
  75. #pragma warning(disable:4100)   /* suppress unref'ed formal param. warnings */
  76. #endif
  77.  
  78. int dbm_store(DBM *db, datum key, datum val, int flag)
  79. {
  80.   char buffer[BUFSIZ];
  81.   long offset;
  82.   int size;
  83.  
  84.   if (db == NULL || db -> magic != DBM_MAGIC)
  85.     return -1;
  86.  
  87.   if ((offset = lseek(db -> dbffile, 0, SEEK_END)) == -1L)
  88.     return -1;
  89.  
  90.   memcpy(buffer, key.dptr, key.dsize);
  91.   size = key.dsize;
  92.   buffer[size - 1] = ' '; /* replace zero */
  93.   memcpy(buffer + size, val.dptr, val.dsize);
  94.   size += val.dsize;
  95.   buffer[size - 1] = '\n';
  96.  
  97.   if (idx_addkey(db -> idx, key.dptr, offset, size) == -1)
  98.     return -1;
  99.  
  100.   if (write(db -> dbffile, buffer, size) != size)
  101.     return -1;
  102.  
  103.   return 0;
  104. }
  105.  
  106. #if _MSC_VER >= 700
  107. #pragma warning(default:4100)   /* restore unref'ed formal param. warnings */
  108. #endif
  109.  
  110. int dbm_delete(DBM *db, datum key)
  111. {
  112.   char buffer[BUFSIZ];
  113.   long offset;
  114.   int size;
  115.  
  116.   if (db == NULL || db -> magic != DBM_MAGIC)
  117.     return -1;
  118.  
  119.   if (idx_delkey(db -> idx, key.dptr, &offset, &size) != -1)
  120.   {
  121.     if ((offset = lseek(db -> dbffile, offset, SEEK_SET)) == -1L)
  122.       return -1;
  123.  
  124.     memset(buffer, ' ', size - 1);
  125.     buffer[size - 1] = '\n';
  126.  
  127.     if (write(db -> dbffile, buffer, size) != size)
  128.       return -1;
  129.   }
  130.  
  131.   return 0;
  132. }
  133.  
  134. datum dbm_fetch(DBM *db, datum key)
  135. {
  136.   datum val = nullitem;
  137.   long offset;
  138.   int size;
  139.  
  140.   if (db == NULL || db -> magic != DBM_MAGIC)
  141.     return nullitem;
  142.  
  143.   if (db -> stream && strcmp(key.dptr, db -> buffer) == 0)
  144.   {
  145.     val.dptr = db -> value;
  146.     val.dsize = strlen(val.dptr) + 1;
  147.   }
  148.   else if (idx_getkey(db -> idx, key.dptr, &offset, &size) != -1)
  149.   {
  150.     if ((offset = lseek(db -> dbffile, offset, SEEK_SET)) == -1L)
  151.       return nullitem;
  152.  
  153.     if (read(db -> dbffile, db -> buffer, size) != size)
  154.       return nullitem;
  155.  
  156.     db -> buffer[size - 1] = 0; /* delete \n */
  157.  
  158.     val.dptr = strchr(db -> buffer, ' ') + 1;
  159.     val.dsize = strlen(val.dptr) + 1;
  160.   }
  161.  
  162.   return val;
  163. }
  164.  
  165. /* Accessing the database sequentially is not as easy as the records
  166.  * are of variable length to save space and make it look like a text
  167.  * file. So we just put a stream on top of it and read it this way. */
  168.  
  169. datum dbm_firstkey(DBM *db)
  170. {
  171.   datum val = nullitem;
  172.   char *ptr;
  173.   int handle;
  174.  
  175.   if (db == NULL || db -> magic != DBM_MAGIC)
  176.     return nullitem;
  177.  
  178.   if (lseek(db -> dbffile, 0, SEEK_SET) == -1L)
  179.     return nullitem;
  180.  
  181.   if ((handle = dup(db -> dbffile)) == -1)
  182.     return nullitem;
  183.  
  184.   if ((db -> stream = fdopen(handle, "rb")) == NULL)
  185.     return nullitem;
  186.  
  187.   do /* skip blanked out records */
  188.   {
  189.     if (fgets(db -> buffer, sizeof(db -> buffer), db -> stream) == NULL)
  190.       return nullitem;
  191.   } while (db -> buffer[0] == ' ');
  192.  
  193.   if ((ptr = strchr(db -> buffer, ' ')) == NULL)
  194.     return nullitem;
  195.  
  196.   db -> buffer[strlen(db -> buffer) - 1] = 0; /* delete \n */
  197.  
  198.   *ptr = 0;
  199.   db -> value = ptr + 1;
  200.  
  201.   val.dptr = db -> buffer;
  202.   val.dsize = strlen(db -> buffer) + 1;
  203.  
  204.   return val;
  205. }
  206.  
  207. datum dbm_nextkey(DBM *db)
  208. {
  209.   datum val = nullitem;
  210.   char *ptr;
  211.  
  212.   if (db == NULL || db -> magic != DBM_MAGIC || db -> stream == NULL)
  213.     return nullitem;
  214.  
  215.   do /* skip blanked out records */
  216.   {
  217.     if (fgets(db -> buffer, sizeof(db -> buffer), db -> stream) == NULL)
  218.       return fclose(db -> stream), (db -> stream = NULL), nullitem;
  219.   } while (db -> buffer[0] == ' ');
  220.  
  221.   if ((ptr = strchr(db -> buffer, ' ')) == NULL)
  222.     return nullitem;
  223.  
  224.   db -> buffer[strlen(db -> buffer) - 1] = 0; /* delete \n */
  225.  
  226.   *ptr = 0;
  227.   db -> value = ptr + 1;
  228.  
  229.   val.dptr = db -> buffer;
  230.   val.dsize = strlen(db -> buffer) + 1;
  231.  
  232.   return val;
  233. }
  234.  
  235. /* end of hdbm.c */
  236.