home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************/
- /* */
- /* */
- /* db_main.c (c) 1987 Ken Harris */
- /* */
- /* */
- /****************************************************************************/
- /* */
- /* This software is made available on an AS-IS basis. Unrestricted */
- /* use is granted provided that the copywrite notice remains intack. */
- /* The author makes no warranties expressed or implied. */
- /* */
- /****************************************************************************/
-
- #include <stdio.h>
- #ifdef MSC
- #include <fcntl.h>
- #include <sys\types.h>
- #include <sys\stat.h>
- #endif
- #include "db.h"
-
- static char *copyright = "db V1.2 (c) 1987 Ken Harris";
-
- int db_error = 0;
- ulong db_match_blk = 0;
- ushort db_match_rec = 0;
- ulong db_add_blk = 0;
- ushort db_add_rec = 0;
-
- /*
- * db_create - Create a New Data Set
- */
-
- DATA_SET db_create(path, fname, fhdr)
- char *path, *fname;
- FILE_HDR fhdr;
- {
- BUFFER db_alloc_buf();
- DATA_SET ds;
- char *fname_dflts(), *calloc();
-
- db_error = 0;
-
- db_fhdr_create(fhdr);
- if (db_error) return(NULL);
-
- ds = (DATA_SET) calloc(1, sizeof(struct db_data_set));
-
- strcpy(ds->ds_fname, fname_dflts(fname,path));
-
- #ifdef MSC
- ds->ds_fd = open(ds->ds_fname, O_CREAT|O_TRUNC|O_RDWR|O_BINARY, S_IREAD|S_IWRITE);
- #endif
- #ifdef CI86
- ds->ds_fd = creat(ds->ds_fname, BUPDATE);
- #endif
- if (ds->ds_fd < 0)
- { db_error = DB_FILE_NOT_CREATED;
- db_free_ds(ds);
- return(NULL);
- }
-
- ds->ds_stat = DB_OPEN;
-
- ds->ds_fhdr = db_alloc_buf(0);
- ds->ds_fhdr->buf_size = sizeof(struct db_file_hdr);
- ds->ds_fhdr->buf_data = (char*) fhdr;
- ds->ds_fhdr->buf_cur_size = sizeof(struct db_file_hdr);
-
- if (fhdr->fh_file_type == DB_INDEX)
- { ds->ds_buf = db_alloc_buf(fhdr->fh_block_size + 2 * fhdr->fh_rec_size);
- ds->ds_tmp = db_alloc_buf(fhdr->fh_block_size + 2 * fhdr->fh_rec_size);
- ds->ds_aux = db_alloc_buf(fhdr->fh_block_size + 2 * fhdr->fh_rec_size);
- ds->ds_buf->buf_size = fhdr->fh_block_size;
- ds->ds_tmp->buf_size = fhdr->fh_block_size;
- ds->ds_aux->buf_size = fhdr->fh_block_size;
- }
- else
- if (fhdr->fh_file_type == DB_RANDOM)
- { ds->ds_buf = db_alloc_buf(fhdr->fh_block_size);
- ds->ds_tmp = db_alloc_buf(fhdr->fh_block_size);
- while (fhdr->fh_last_block < fhdr->fh_base_size)
- { db_extend(ds, ds->ds_buf);
- if (db_error) return(NULL);
-
- db_put_blk(ds, ds->ds_buf);
- }
- }
- else
- ds->ds_buf = db_alloc_buf(fhdr->fh_block_size);
-
- db_put_blk(ds, ds->ds_fhdr);
- if (db_error)
- { db_free_ds(ds);
- return(NULL);
- }
-
- return(ds);
- }
-
- /*
- * db_fhdr_create - Check file header data on create
- */
-
- void db_fhdr_create(fh)
- FILE_HDR fh;
- { short hdr_size;
-
- db_error = 0;
-
- fh->fh_db_version = DB_VERSION;
-
- if (fh->fh_file_type != DB_SEQ &&
- fh->fh_file_type != DB_RANDOM &&
- fh->fh_file_type != DB_INDEX)
- { db_error = DB_INVALID_FHDR;
- return;
- }
-
- fh->fh_file_stat &= ~DB_OPEN;
- fh->fh_last_block = 0;
-
- if (!fh->fh_block_size) fh->fh_block_size = 512;
-
- switch (fh->fh_file_type)
- { case DB_SEQ:
- hdr_size = 0;
- if (!fh->fh_ctl_size) fh->fh_ctl_size = 1;
- break;
-
- case DB_RANDOM:
- hdr_size = sizeof(struct db_random_hdr);
- if (!fh->fh_base_size)
- { db_error = DB_INVALID_FHDR;
- return;
- }
- if (!fh->fh_ctl_size) fh->fh_ctl_size = 1;
- break;
-
- case DB_INDEX:
- hdr_size = sizeof(struct db_index_hdr);
- if (!fh->fh_ctl_size) fh->fh_ctl_size = 2;
- break;
-
- default:
- hdr_size = 0;
- break;
- }
-
- fh->fh_rec_size = fh->fh_ctl_size + fh->fh_data_size;
-
- if (fh->fh_block_size < fh->fh_rec_size + hdr_size)
- fh->fh_block_size = fh->fh_rec_size + hdr_size;
-
- fh->fh_block_size = ((fh->fh_block_size + 511) / 512) * 512;
-
- fh->fh_rec_cnt = 0;
- fh->fh_recs_per_blk = (fh->fh_block_size - hdr_size) / fh->fh_rec_size;
- fh->fh_root_ptr = 0;
- fh->fh_next_avail = 0;
-
- if (fh->fh_key_size > fh->fh_data_size)
- { db_error = DB_INVALID_FHDR;
- return;
- }
- }
-
- /*
- * db_open - Open a Data Set
- */
-
- DATA_SET db_open(path,fname)
- char *path, *fname;
- {
- BUFFER db_alloc_buf();
- DATA_SET ds;
- FILE_HDR fhdr;
- char *fname_dflts(), *calloc();
- int cnt;
-
- db_error = 0;
- ds = (DATA_SET) calloc(1, sizeof(struct db_data_set));
- strcpy(ds->ds_fname, fname_dflts(fname,path));
-
- #ifdef MSC
- ds->ds_fd = open(ds->ds_fname, O_RDWR|O_BINARY);
- #endif
- #ifdef CI86
- ds->ds_fd = open(ds->ds_fname, BUPDATE);
- #endif
- if (ds->ds_fd < 0)
- { db_error = DB_FILE_NOT_FOUND;
- db_free_ds(ds);
- return(NULL);
- }
-
- ds->ds_stat = DB_OPEN;
-
- ds->ds_fhdr = db_alloc_buf(sizeof(struct db_file_hdr));
- fhdr = (FILE_HDR) ds->ds_fhdr->buf_data;
-
- db_get_blk(ds, 0L, ds->ds_fhdr);
- if (db_error)
- { db_free_ds(ds);
- return(NULL);
- }
-
- db_fhdr_open(fhdr);
- if (db_error) return(NULL);
-
- if (fhdr->fh_file_type == DB_INDEX)
- { ds->ds_buf = db_alloc_buf(fhdr->fh_block_size + 2 * fhdr->fh_rec_size);
- ds->ds_tmp = db_alloc_buf(fhdr->fh_block_size + 2 * fhdr->fh_rec_size);
- ds->ds_aux = db_alloc_buf(fhdr->fh_block_size + 2 * fhdr->fh_rec_size);
- ds->ds_buf->buf_size = fhdr->fh_block_size;
- ds->ds_tmp->buf_size = fhdr->fh_block_size;
- ds->ds_aux->buf_size = fhdr->fh_block_size;
- }
- else
- if (fhdr->fh_file_type == DB_RANDOM)
- { ds->ds_buf = db_alloc_buf(fhdr->fh_block_size);
- ds->ds_tmp = db_alloc_buf(fhdr->fh_block_size);
- }
- else
- ds->ds_buf = db_alloc_buf(fhdr->fh_block_size);
-
- return(ds);
- }
-
- /*
- * db_fhdr_open - Check file header data on open
- */
-
- void db_fhdr_open(fh)
- FILE_HDR fh;
- {
- db_error = 0;
-
- if (fh->fh_db_version != DB_VERSION)
- { db_error = DB_VERSION_ERROR;
- return;
- }
-
- if (fh->fh_file_type != DB_SEQ &&
- fh->fh_file_type != DB_RANDOM &&
- fh->fh_file_type != DB_INDEX)
- { db_error = DB_INVALID_FHDR;
- return;
- }
-
- if (fh->fh_block_size == 0 ||
- fh->fh_rec_size == 0 ||
- fh->fh_recs_per_blk == 0)
- { db_error = DB_INVALID_FHDR;
- return;
- }
-
- if (fh->fh_rec_size != fh->fh_ctl_size + fh->fh_data_size)
- { db_error = DB_INVALID_FHDR;
- return;
- }
-
- if (fh->fh_key_size > fh->fh_data_size)
- { db_error = DB_INVALID_FHDR;
- return;
- }
-
- if (fh->fh_file_type == DB_RANDOM &&
- fh->fh_base_size == 0)
- { db_error = DB_INVALID_FHDR;
- return;
- }
- }
-
- /*
- * db_close - close a data set
- */
-
- DATA_SET db_close(ds)
- DATA_SET ds;
- {
- db_error = 0;
-
- db_check_ds(ds);
- if (db_error) return(NULL);
-
- db_put_blk(ds, ds->ds_fhdr);
- if (db_error) return(NULL);
-
- close(ds->ds_fd);
-
- db_free_ds(ds);
-
- return(NULL);
- }
-
- /*
- * db_add - Add a new record to a data set
- */
-
- ulong db_add(ds, user_data)
- DATA_SET ds;
- char *user_data;
- {
- FILE_HDR fh;
- BUFFER buf;
- ulong rec_no;
-
- db_error = 0;
-
- db_check_ds(ds);
- if (db_error) return(0);
-
- fh = (FILE_HDR) ds->ds_fhdr->buf_data;
- buf = (BUFFER) ds->ds_buf;
-
- switch (fh->fh_file_type)
- { case DB_SEQ:
- db_add_seq(ds, user_data);
- break;
-
- case DB_INDEX:
- db_add_idx(ds, user_data);
- break;
-
- case DB_RANDOM:
- db_add_ran(ds, user_data);
- break;
-
- default:
- db_error = DB_INVALID_REQUEST;
- break;
- }
-
- if (db_error) return(0);
-
- rec_no = (db_add_blk - 1) * fh->fh_recs_per_blk + db_add_rec;
-
- buf->buf_cur_blk = 0;
- buf->buf_rec_inx = 0;
-
- return(rec_no);
- }
-
- /*
- * db_read_first - Read First Record in a data set
- */
-
- void db_read_first(ds, user_data)
- DATA_SET ds;
- char *user_data;
- {
- FILE_HDR fh;
- BUFFER buf;
-
- db_error = 0;
-
- db_check_ds(ds);
- if (db_error) return;
-
- fh = (FILE_HDR) ds->ds_fhdr->buf_data;
- buf = (BUFFER) ds->ds_buf;
-
- if (!fh->fh_rec_cnt)
- { db_error = DB_END_OF_FILE;
- return;
- }
-
- switch (fh->fh_file_type)
- { case DB_SEQ:
- db_read_first_seq(ds, user_data);
- break;
-
- case DB_INDEX:
- db_read_first_idx(ds, fh->fh_root_ptr, user_data);
- break;
-
- case DB_RANDOM:
- db_read_first_ran(ds, user_data);
- break;
-
- default:
- db_error = DB_INVALID_REQUEST;
- break;
- }
-
- if (db_error)
- { buf->buf_cur_blk = 0;
- buf->buf_rec_inx = 0;
- }
-
- ds->ds_prev_blk = buf->buf_cur_blk;
- ds->ds_prev_rec = buf->buf_rec_inx;
-
- return;
- }
-
- /*
- * db_read_next - Read next record from a data set
- */
-
- void db_read_next(ds, user_data)
- DATA_SET ds;
- char *user_data;
- {
- FILE_HDR fh;
- BUFFER buf;
-
- db_error = 0;
-
- db_check_ds(ds);
- if (db_error) return;
-
- fh = (FILE_HDR) ds->ds_fhdr->buf_data;
- buf = (BUFFER) ds->ds_buf;
-
- if (!fh->fh_rec_cnt)
- { db_error = DB_END_OF_FILE;
- return;
- }
-
- if (!ds->ds_prev_blk)
- { db_error = DB_NO_CURRENT_REC;
- return;
- }
-
- switch (fh->fh_file_type)
- { case DB_SEQ:
- db_read_next_seq(ds, user_data);
- break;
-
- case DB_INDEX:
- db_read_next_idx(ds, user_data);
- break;
-
- case DB_RANDOM:
- db_read_next_ran(ds, user_data);
- break;
-
- default:
- db_error = DB_INVALID_REQUEST;
- break;
- }
-
- if (db_error)
- { buf->buf_cur_blk = 0;
- buf->buf_rec_inx = 0;
- }
-
- ds->ds_prev_blk = buf->buf_cur_blk;
- ds->ds_prev_rec = buf->buf_rec_inx;
-
- return;
- }
-
- /*
- * db_read_last - Read Last Record in a data set
- */
-
- void db_read_last(ds, user_data)
- DATA_SET ds;
- char *user_data;
- {
- FILE_HDR fh;
- BUFFER buf;
-
- db_error = 0;
-
- db_check_ds(ds);
- if (db_error) return;
-
- fh = (FILE_HDR) ds->ds_fhdr->buf_data;
- buf = (BUFFER) ds->ds_buf;
-
- if (!fh->fh_rec_cnt)
- { db_error = DB_END_OF_FILE;
- return;
- }
-
- switch (fh->fh_file_type)
- { case DB_SEQ:
- db_read_last_seq(ds, user_data);
- break;
-
- case DB_INDEX:
- db_read_last_idx(ds, fh->fh_root_ptr, user_data);
- break;
-
- case DB_RANDOM:
- db_read_last_ran(ds, user_data);
- break;
-
- default:
- db_error = DB_INVALID_REQUEST;
- break;
- }
-
- if (db_error)
- { buf->buf_cur_blk = 0;
- buf->buf_rec_inx = 0;
- }
-
- ds->ds_prev_blk = buf->buf_cur_blk;
- ds->ds_prev_rec = buf->buf_rec_inx;
-
- return;
- }
-
- /*
- * db_read_prev - Read prev record from a data set
- */
-
- void db_read_prev(ds, user_data)
- DATA_SET ds;
- char *user_data;
- {
- FILE_HDR fh;
- BUFFER buf;
-
- db_error = 0;
-
- db_check_ds(ds);
- if (db_error) return;
-
- fh = (FILE_HDR) ds->ds_fhdr->buf_data;
- buf = (BUFFER) ds->ds_buf;
-
- if (!fh->fh_rec_cnt)
- { db_error = DB_END_OF_FILE;
- return;
- }
-
- if (!ds->ds_prev_blk)
- { db_error = DB_NO_CURRENT_REC;
- return;
- }
-
- switch (fh->fh_file_type)
- { case DB_SEQ:
- db_read_prev_seq(ds, user_data);
- break;
-
- case DB_INDEX:
- db_read_prev_idx(ds, user_data);
- break;
-
- case DB_RANDOM:
- db_read_prev_ran(ds, user_data);
- break;
-
- default:
- db_error = DB_INVALID_REQUEST;
- break;
- }
-
- if (db_error)
- { buf->buf_cur_blk = 0;
- buf->buf_rec_inx = 0;
- }
-
- ds->ds_prev_blk = buf->buf_cur_blk;
- ds->ds_prev_rec = buf->buf_rec_inx;
-
- return;
- }
-
- /*
- * db_find - Find a Record
- */
-
- void db_find(ds, user_data, key, key_size)
- DATA_SET ds;
- char *user_data;
- char *key;
- int key_size;
- {
- FILE_HDR fh;
- BUFFER buf;
-
- db_error = 0;
-
- db_check_ds(ds);
- if (db_error) return;
-
- fh = (FILE_HDR) ds->ds_fhdr->buf_data;
- buf = (BUFFER) ds->ds_buf;
-
- if (!fh->fh_rec_cnt)
- { db_error = DB_REC_NOT_FOUND;
- return;
- }
-
- if (!key_size) key_size = fh->fh_key_size;
-
- switch (fh->fh_file_type)
- { case DB_INDEX:
- db_find_first_idx(ds, user_data, key, key_size);
- break;
-
- case DB_RANDOM:
- db_find_ran(ds, user_data, key);
- break;
-
- default:
- db_error = DB_INVALID_REQUEST;
- break;
- }
-
- if (db_error)
- { buf->buf_cur_blk = 0;
- buf->buf_rec_inx = 0;
- }
-
- ds->ds_prev_blk = buf->buf_cur_blk;
- ds->ds_prev_rec = buf->buf_rec_inx;
-
- return;
- }
-
- /*
- * db_update - Update a record from a data set
- */
-
- void db_update(ds, user_data)
- DATA_SET ds;
- char *user_data;
- {
- FILE_HDR fh;
- BUFFER buf;
-
- db_error = 0;
-
- db_check_ds(ds);
- if (db_error) return;
-
- fh = (FILE_HDR) ds->ds_fhdr->buf_data;
- buf = (BUFFER) ds->ds_buf;
-
- if (!buf->buf_cur_blk || !buf->buf_rec_inx)
- { db_error = DB_NO_CURRENT_REC;
- return;
- }
-
- switch (fh->fh_file_type)
- { case DB_SEQ:
- db_update_seq(ds, user_data);
- break;
-
- case DB_RANDOM:
- db_update_ran(ds, user_data);
- break;
-
- case DB_INDEX:
- db_update_idx(ds, user_data);
- break;
-
- default:
- db_error = DB_INVALID_REQUEST;
- break;
- }
-
- buf->buf_cur_blk = 0;
- buf->buf_rec_inx = 0;
-
- return;
- }
-
- /*
- * db_delete - Delete a record from a data set
- */
-
- void db_delete(ds)
- DATA_SET ds;
- {
- FILE_HDR fh;
- BUFFER buf;
-
- db_error = 0;
-
- db_check_ds(ds);
- if (db_error) return;
-
- fh = (FILE_HDR) ds->ds_fhdr->buf_data;
- buf = (BUFFER) ds->ds_buf;
-
- if (!buf->buf_cur_blk || !buf->buf_rec_inx)
- { db_error = DB_NO_CURRENT_REC;
- return;
- }
-
- switch (fh->fh_file_type)
- { case DB_SEQ:
- db_free_rec(ds, buf);
- if (db_error) return;
-
- if (fh->fh_rec_cnt > 0) fh->fh_rec_cnt--;
- db_put_blk(ds, ds->ds_fhdr);
- break;
-
- case DB_INDEX:
- db_delete_idx(ds);
- break;
-
- case DB_RANDOM:
- db_delete_ran(ds);
- break;
-
- default:
- db_error = DB_INVALID_REQUEST;
- break;
- }
-
- buf->buf_cur_blk = 0;
- buf->buf_rec_inx = 0;
-
- return;
- }
-
- /*
- * db_get_rec_no - Get relative record number
- */
-
- ulong db_get_rec_no(ds)
- DATA_SET ds;
- {
- FILE_HDR fh;
- BUFFER buf;
-
- db_error = 0;
-
- db_check_ds(ds);
- if (db_error) return(0);
-
- fh = (FILE_HDR) ds->ds_fhdr->buf_data;
- buf = ds->ds_buf;
-
- if (!buf->buf_cur_blk || !buf->buf_rec_inx)
- { db_error = DB_NO_CURRENT_REC;
- return(0);
- }
-
- return((long)(buf->buf_cur_blk - 1) * fh->fh_recs_per_blk
- + buf->buf_rec_inx);
- }
-
- /*
- * db_read_direct - Read a record by number
- */
-
- void db_read_direct(ds, rec_no, user_data)
- DATA_SET ds;
- ulong rec_no;
- char *user_data;
- {
- FILE_HDR fh;
- BUFFER buf;
- INDEX_HDR ihdr;
- RANDOM_HDR rhdr;
- RANDOM_REC rrec;
- SEQ_REC seq;
- ulong blk;
- ushort rec;
- char *rbuf;
-
- db_error = 0;
-
- db_check_ds(ds);
- if (db_error) return;
-
- fh = (FILE_HDR) ds->ds_fhdr->buf_data;
- buf = ds->ds_buf;
-
- buf->buf_cur_blk = 0;
- buf->buf_rec_inx = 0;
-
- blk = rec_no / fh->fh_recs_per_blk;
- rec = rec_no % fh->fh_recs_per_blk;
-
- if (rec == 0)
- rec = fh->fh_recs_per_blk;
- else
- blk++;
-
- db_get_blk(ds, blk, buf);
- if (db_error) return;
-
- switch (fh->fh_file_type)
- { case DB_SEQ:
- rbuf = buf->buf_data + (rec-1) * fh->fh_rec_size;
- seq = (SEQ_REC) rbuf;
-
- if (seq->seq_stat != DB_INUSE)
- { db_error = DB_DELETED_REC;
- return;
- }
- break;
-
- case DB_INDEX:
- ihdr = (INDEX_HDR) buf->buf_data;
-
- if (ihdr->idx_stat != DB_INUSE)
- { db_error = DB_DELETED_REC;
- return;
- }
-
- if (rec > ihdr->idx_rec_cnt)
- { db_error = DB_DELETED_REC;
- return;
- }
-
- rbuf = buf->buf_data + sizeof(struct db_index_hdr)
- + (rec - 1) * fh->fh_rec_size;
- break;
-
- case DB_RANDOM:
- rhdr = (RANDOM_HDR) buf->buf_data;
-
- if (rhdr->ran_stat != DB_INUSE)
- { db_error = DB_DELETED_REC;
- return;
- }
-
- if (rec > rhdr->ran_rec_cnt)
- { db_error = DB_DELETED_REC;
- return;
- }
-
- rbuf = buf->buf_data + sizeof(struct db_random_hdr)
- + (rec - 1) * fh->fh_rec_size;
-
- rrec = (RANDOM_REC) rbuf;
- if (rrec->ran_stat != DB_INUSE)
- { db_error = DB_DELETED_REC;
- return;
- }
-
- break;
-
- default:
- db_error = DB_INVALID_REQUEST;
- return;
- }
- memcpy(user_data, rbuf + fh->fh_ctl_size, fh->fh_data_size);
-
- ds->ds_prev_blk = buf->buf_cur_blk = blk;
- ds->ds_prev_rec = buf->buf_rec_inx = rec;
-
- return;
- }
-
- /*
- * db_read_atr - Read Data Set Attribute Block
- */
-
- void db_read_atr(ds, user_data)
- DATA_SET ds;
- char *user_data;
- {
- FILE_HDR fh;
-
- db_error = 0;
-
- db_check_ds(ds);
- if (db_error) return;
-
- fh = (FILE_HDR) ds->ds_fhdr->buf_data;
-
- memcpy(user_data, fh->fh_user_data, fh->fh_atr_size);
-
- return;
- }
-
- /*
- * db_update_atr - Update Data Set Attribute Block
- */
-
- void db_update_atr(ds, user_data)
- DATA_SET ds;
- char *user_data;
- {
- FILE_HDR fh;
-
- db_error = 0;
-
- db_check_ds(ds);
- if (db_error) return;
-
- fh = (FILE_HDR) ds->ds_fhdr->buf_data;
-
- memcpy(fh->fh_user_data, user_data, fh->fh_atr_size);
-
- db_put_blk(ds, ds->ds_fhdr);
-
- return;
- }
-
- /*
- * db_check_ds - Common checks on Data Set Validity
- */
-
- void db_check_ds(ds)
- DATA_SET ds;
- {
- FILE_HDR fh;
-
- db_error = 0;
-
- if (!ds)
- { db_error = DB_FILE_NOT_OPEN;
- return;
- }
-
- if (!ds->ds_stat & DB_OPEN)
- { db_error = DB_FILE_NOT_OPEN;
- return;
- }
-
- if (!ds->ds_fhdr || !ds->ds_buf)
- { db_error = DB_BUFFER_ERROR;
- return;
- }
-
- fh = (FILE_HDR) ds->ds_fhdr->buf_data;
-
- if (fh->fh_file_type == DB_INDEX)
- if (!ds->ds_tmp || !ds->ds_aux)
- { db_error = DB_BUFFER_ERROR;
- return;
- }
- }
-
- /*
- * db_extend - Extend a data set by 1 Block
- */
-
- void db_extend(ds, buf)
- DATA_SET ds;
- BUFFER buf;
- {
- FILE_HDR fhdr;
- long rec;
- char *c;
- FREE_REC fre;
- RANDOM_HDR ran;
- SEQ_REC seq;
- int cnt;
-
-
- fhdr = (FILE_HDR) ds->ds_fhdr->buf_data;
- buf = ds->ds_buf;
- fhdr->fh_last_block = fhdr->fh_last_block + 1;
- buf->buf_cur_blk = fhdr->fh_last_block;
- buf->buf_cur_size = fhdr->fh_block_size;
-
- memset(buf->buf_data, 0, buf->buf_cur_size);
-
- switch(fhdr->fh_file_type)
- { case DB_SEQ:
- rec = buf->buf_cur_blk * fhdr->fh_recs_per_blk;
- c = buf->buf_data + (fhdr->fh_recs_per_blk - 1)
- * fhdr->fh_rec_size;
-
- for (cnt=0; cnt < fhdr->fh_recs_per_blk; cnt++)
- { fre = (FREE_REC) c;
- fre->fre_stat = DB_FREE;
- fre->fre_next = fhdr->fh_next_avail;
- fhdr->fh_next_avail = rec--;
- c -= fhdr->fh_rec_size;
- }
- break;
-
- case DB_RANDOM:
- c = buf->buf_data + sizeof(struct db_random_hdr);
- for (cnt=0; cnt < fhdr->fh_recs_per_blk; cnt++)
- { *c = DB_FREE;
- c += fhdr->fh_rec_size;
- }
- if (buf->buf_cur_blk <= fhdr->fh_base_size)
- { ran = (RANDOM_HDR) buf->buf_data;
- ran->ran_stat = DB_INUSE;
- ran->ran_next = 0;
- ran->ran_rec_cnt = 0;
- }
- else
- { fre = (FREE_REC) buf->buf_data;
- fre->fre_stat = DB_FREE;
- fre->fre_next = fhdr->fh_next_avail;
- fhdr->fh_next_avail = buf->buf_cur_blk;
- }
- break;
-
- case DB_INDEX:
- fre = (FREE_REC) buf->buf_data;
- fre->fre_stat = DB_FREE;
- fre->fre_next = fhdr->fh_next_avail;
- fhdr->fh_next_avail = buf->buf_cur_blk;
- break;
- }
-
- db_put_blk(ds,ds->ds_buf);
- db_put_blk(ds,ds->ds_fhdr);
- }
-
- /*
- * db_get_next_avail - Get Next Available Block
- */
-
- void db_get_next_avail(ds, buf)
- DATA_SET ds;
- BUFFER buf;
- {
- FILE_HDR fh;
- FREE_REC fre;
- RANDOM_HDR rhdr;
- INDEX_HDR ihdr;
- ulong blk;
- ushort rec;
- char *rbuf;
-
- db_error = 0;
-
- fh = (FILE_HDR) ds->ds_fhdr->buf_data;
-
- if (!fh->fh_next_avail)
- { db_extend(ds, buf);
- if (db_error) return;
- }
-
- if (fh->fh_file_type == DB_SEQ)
- { blk = fh->fh_next_avail / fh->fh_recs_per_blk;
- rec = fh->fh_next_avail % fh->fh_recs_per_blk;
-
- if (rec==0)
- rec = fh->fh_recs_per_blk;
- else
- blk++;
- }
- else
- { blk = fh->fh_next_avail;
- rec = 1;
- }
-
- db_get_blk(ds, blk, buf);
- if (db_error) return;
-
- buf->buf_rec_inx = rec;
- rbuf = buf->buf_data + (rec - 1) * fh->fh_rec_size;
-
- fre = (FREE_REC) rbuf;
- if (fre->fre_stat != DB_FREE)
- { db_error = DB_INVALID_FREE;
- return;
- }
-
- fre->fre_stat = DB_INUSE;
- fh->fh_next_avail = fre->fre_next;
-
- if (fh->fh_file_type == DB_INDEX)
- if (!fh->fh_root_ptr)
- fh->fh_root_ptr = blk;
-
- switch (fh->fh_file_type)
- { case DB_SEQ:
- break;
-
- case DB_RANDOM:
- rhdr = (RANDOM_HDR) rbuf;
- rhdr->ran_next = 0;
- rhdr->ran_rec_cnt = 0;
- break;
-
- case DB_INDEX:
- ihdr = (INDEX_HDR) rbuf;
- ihdr->idx_parent = 0;
- ihdr->idx_rec_cnt = 0;
- break;
- }
- }
-
- /*
- * db_free_rec - Free a deleted record
- */
-
- void db_free_rec(ds, buf)
- DATA_SET ds;
- BUFFER buf;
- {
- FILE_HDR fh;
- FREE_REC fre;
-
- db_error = 0;
-
- fh = (FILE_HDR) ds->ds_fhdr->buf_data;
-
- switch (fh->fh_file_type)
- { case DB_SEQ:
- fre = (FREE_REC) (buf->buf_data
- + (buf->buf_rec_inx - 1) * fh->fh_rec_size);
- memset(fre, 0, fh->fh_rec_size);
- fre->fre_stat = DB_FREE;
- fre->fre_next = fh->fh_next_avail;
- fh->fh_next_avail = (long) (buf->buf_cur_blk - 1)
- * fh->fh_recs_per_blk + buf->buf_rec_inx;
- break;
-
- case DB_RANDOM:
- fre = (FREE_REC) buf->buf_data;
- fre->fre_stat = DB_FREE;
- fre->fre_next = fh->fh_next_avail;
- fh->fh_next_avail = buf->buf_cur_blk;
- break;
-
- case DB_INDEX:
- fre = (FREE_REC) buf->buf_data;
- memset(fre, 0, fh->fh_block_size);
- fre->fre_stat = DB_FREE;
- fre->fre_next = fh->fh_next_avail;
- fh->fh_next_avail = buf->buf_cur_blk;
- break;
- }
- db_put_blk(ds, buf);
- if (db_error) return;
- }
-
- /*
- * db_get_blk - Get a Block from a Data Set
- */
-
- void db_get_blk(ds,blk,buf)
- DATA_SET ds;
- long blk;
- BUFFER buf;
- {
- FILE_HDR fhdr;
- long psn, lseek();
- int cnt;
-
- db_error = 0;
-
- if (!ds)
- { db_error = DB_FILE_NOT_OPEN;
- return;
- }
-
- if (!ds->ds_stat & DB_OPEN)
- { db_error = DB_FILE_NOT_OPEN;
- return;
- }
-
- if (!buf)
- { db_error = DB_BUFFER_ERROR;
- return;
- }
-
- fhdr = (FILE_HDR) ds->ds_fhdr->buf_data;
-
- if (blk == 0)
- psn = 0;
- else
- psn = sizeof(struct db_file_hdr)
- + (blk-1) * fhdr->fh_block_size;
-
- buf->buf_cur_blk = 0;
- buf->buf_cur_size = 0;
-
- if (lseek(ds->ds_fd, psn, 0) < 0)
- { db_error = DB_INVALID_BLOCK;
- return;
- }
-
- cnt = read(ds->ds_fd, buf->buf_data, buf->buf_size);
- if (cnt < 0)
- { db_error = DB_READ_ERROR;
- return;
- }
-
- if (cnt == 0)
- { db_error = DB_END_OF_FILE;
- return;
- }
-
- buf->buf_cur_blk = blk;
- buf->buf_cur_size = cnt;
- }
-
- /*
- * db_put_blk - Put a Block out to a Data Set
- */
-
- void db_put_blk(ds,buf)
- DATA_SET ds;
- BUFFER buf;
- {
- FILE_HDR fhdr;
- long psn, lseek();
- int cnt;
-
- db_error = 0;
-
- if (!ds)
- { db_error = DB_FILE_NOT_OPEN;
- return;
- }
-
- if (!ds->ds_stat & DB_OPEN)
- { db_error = DB_FILE_NOT_OPEN;
- return;
- }
-
- if (!buf)
- { db_error = DB_BUFFER_ERROR;
- return;
- }
-
- if (buf->buf_cur_size == 0)
- { db_error = DB_INVALID_BLK_SIZE;
- return;
- }
-
- fhdr = (FILE_HDR) ds->ds_fhdr->buf_data;
-
- if (buf->buf_cur_blk == 0)
- psn = 0;
- else
- psn = sizeof(struct db_file_hdr)
- + (buf->buf_cur_blk - 1) * fhdr->fh_block_size;
-
- if (lseek(ds->ds_fd, psn, 0) < 0)
- { db_error = DB_INVALID_BLOCK;
- return;
- }
-
- cnt = write(ds->ds_fd, buf->buf_data, buf->buf_cur_size);
- if (cnt != buf->buf_cur_size)
- { db_error = DB_WRITE_ERROR;
- return;
- }
- }
-
- /*
- * db_alloc_buf - Get a Buffer
- */
-
- BUFFER db_alloc_buf(size)
- int size;
- {
- BUFFER buf;
- char *calloc();
-
- buf = (BUFFER) calloc(1, sizeof(struct db_data_buf));
-
- if (size)
- { buf->buf_size = size;
- buf->buf_data = (char *) calloc(1, size);
- }
-
- return(buf);
- }
-
-
-
- /*
- * db_free_buf - Free a Buffer
- */
-
- BUFFER db_free_buf(buf)
- BUFFER buf;
- {
- BUFFER prev,next;
-
- if (!buf) return(NULL);
-
- if (!buf->buf_data) return(NULL);
-
- prev = buf->buf_prev;
- next = buf->buf_next;
-
- if (prev) prev->buf_next = buf->buf_next;
-
- if (next) next->buf_prev = buf->buf_prev;
-
- free(buf->buf_data);
- free(buf);
-
- return(next);
- }
-
- /*
- * db_free_ds - Free all dynamic structures for a Data Set
- */
-
- void db_free_ds(ds)
- DATA_SET ds;
- {
- if (!ds) return;
-
- if (ds->ds_fhdr)
- db_free_buf(ds->ds_fhdr);
-
- while (ds->ds_buf)
- ds->ds_buf = db_free_buf(ds->ds_buf);
-
- if (ds->ds_tmp)
- db_free_buf(ds->ds_tmp);
-
- if (ds->ds_aux)
- db_free_buf(ds->ds_aux);
-
- return;
- }
-
- /*
- * db_error_msg - Return pointer to error message text
- */
-
- static char *db_error_msgs[] =
- {"",
- "DB-Data Set Not Found", /* 1 */
- "DB-Read Error", /* 2 */
- "DB-End Of File", /* 3 */
- "DB-Write Error", /* 4 */
- "DB-Data Set Not Created", /* 5 */
- "DB-Data Set Not Open", /* 6 */
- "DB-Invalid Block", /* 7 */
- "DB-Buffer Error", /* 8 */
- "DB-No Current Record", /* 9 */
- "DB-Record Deleted", /* 10 */
- "DB-Free List Error", /* 11 */
- "DB-Invalid Block Size", /* 12 */
- "DB-Index File Corrupted", /* 13 */
- "DB-Record Not Found", /* 14 */
- "DB-Duplicate Key", /* 15 */
- "DB-Invalid Request", /* 16 */
- "DB-Random File Corrupted", /* 17 */
- "DB-Invalid File Header", /* 18 */
- "DB-File Version Mismatch", /* 19 */
- ""};
-
- char *db_error_msg(error)
- int error;
- {
- return(db_error_msgs[error]);
- }
-
- /*
- * memcpy - copy a block of memory taking care not to overlap
- */
-
- memcpy(dst, src, cnt)
- char *dst, *src;
- int cnt;
- {
- char *s, *d;
-
- if (dst > src && dst < src+cnt)
- { s = src + cnt - 1;
- d = dst + cnt - 1;
- while (cnt--) *d-- = *s--;
- }
- else
- while (cnt--) *dst++ = *src++;
- }
-