+ return r;
+}
+
+static void write_indx (Records p, int sysno, void *buf, int itemsize)
+{
+ int pos = (sysno-1)*itemsize;
+
+ bf_write (p->index_BFile, 1+pos/128, pos%128, itemsize, buf);
+}
+
+static void rec_release_blocks (Records p, int sysno)
+{
+ struct record_index_entry entry;
+ int freeblock, freenext;
+ int dst_type;
+
+ if (read_indx (p, sysno, &entry, sizeof(entry), 1) != 1)
+ return ;
+ p->head.total_bytes -= entry.size;
+ freeblock = entry.next;
+ assert (freeblock > 0);
+ dst_type = freeblock & 7;
+ assert (dst_type < REC_BLOCK_TYPES);
+ freeblock = freeblock / 8;
+ while (freeblock)
+ {
+ if (bf_read (p->data_BFile[dst_type], freeblock, 0, sizeof(freenext),
+ &freenext) != 1)
+ {
+ logf (LOG_FATAL|LOG_ERRNO, "read in rec_del_single");
+ exit (1);
+ }
+ if (bf_write (p->data_BFile[dst_type], freeblock, 0, sizeof(freenext),
+ &p->head.block_free[dst_type]))
+ {
+ logf (LOG_FATAL|LOG_ERRNO, "write in rec_del_single");
+ exit (1);
+ }
+ p->head.block_free[dst_type] = freeblock;
+ freeblock = freenext;
+ p->head.block_used[dst_type]--;
+ }
+}
+
+static void rec_delete_single (Records p, Record rec)
+{
+ struct record_index_entry entry;
+
+ rec_release_blocks (p, rec->sysno);
+
+ entry.next = p->head.index_free;
+ entry.size = 0;
+ p->head.index_free = rec->sysno;
+ write_indx (p, rec->sysno, &entry, sizeof(entry));
+}
+
+
+static void rec_write_single (Records p, Record rec)
+{
+ int i, size = 0;
+ char *cptr;
+ int dst_type = 0;
+ int no_written = 0;
+ int block_prev = -1, block_free;
+ struct record_index_entry entry;
+
+ for (i = 0; i < REC_NO_INFO; i++)
+ if (!rec->info[i])
+ size += sizeof(*rec->size);
+ else
+ size += sizeof(*rec->size) + rec->size[i];
+
+ for (i = 1; i<REC_BLOCK_TYPES; i++)
+ if (size >= p->head.block_move[i])
+ dst_type = i;
+
+ rec_tmp_expand (p, size, dst_type);
+
+ cptr = p->tmp_buf + sizeof(int); /* a hack! */
+ for (i = 0; i < REC_NO_INFO; i++)
+ {
+ memcpy (cptr, &rec->size[i], sizeof(*rec->size));
+ cptr += sizeof(*rec->size);
+ if (rec->info[i])
+ {
+ memcpy (cptr, rec->info[i], rec->size[i]);
+ cptr += rec->size[i];
+ }
+ }
+ cptr = p->tmp_buf;
+ while (no_written < size)
+ {
+ block_free = p->head.block_free[dst_type];
+ if (block_free)
+ {
+ if (bf_read (p->data_BFile[dst_type],
+ block_free, 0, sizeof(*p->head.block_free),
+ &p->head.block_free[dst_type]) != 1)
+ {
+ logf (LOG_FATAL|LOG_ERRNO, "read in %s at free block %d",
+ p->data_fname[dst_type], block_free);
+ }
+ }
+ else
+ block_free = p->head.block_last[dst_type]++;
+ if (block_prev == -1)
+ {
+ entry.next = block_free*8 + dst_type;
+ entry.size = size;
+ p->head.total_bytes += size;
+ write_indx (p, rec->sysno, &entry, sizeof(entry));
+ }
+ else
+ {
+ memcpy (cptr, &block_free, sizeof(int));
+ bf_write (p->data_BFile[dst_type], block_prev, 0, 0, cptr);
+ cptr = p->tmp_buf + no_written;
+ }
+ block_prev = block_free;
+ no_written += p->head.block_size[dst_type] - sizeof(int);
+ p->head.block_used[dst_type]++;
+ }
+ assert (block_prev != -1);
+ block_free = 0;
+ memcpy (cptr, &block_free, sizeof(int));
+ bf_write (p->data_BFile[dst_type], block_prev, 0,
+ sizeof(int) + (p->tmp_buf+size) - cptr, cptr);
+}
+
+static void rec_update_single (Records p, Record rec)
+{
+ rec_release_blocks (p, rec->sysno);
+ rec_write_single (p, rec);
+}
+
+Records rec_open (int rw)
+{
+ Records p;
+ int i, r;
+
+ p = xmalloc (sizeof(*p));
+ p->rw = rw;
+ p->tmp_size = 1024;
+ p->tmp_buf = xmalloc (p->tmp_size);
+ p->index_fname = "recindex";
+ p->index_BFile = bf_open (p->index_fname, 128, rw);
+ if (p->index_BFile == NULL)