static int
zerofill_record(struct cdb_make *cdbmp, unsigned rpos, unsigned rlen) {
  if (rpos + rlen == cdbmp->cdb_dpos) {
    cdbmp->cdb_dpos = rpos;
    return 0;
  }
  if (lseek(cdbmp->cdb_fd, rpos, SEEK_SET) < 0)
    return -1;
  memset(cdbmp->cdb_buf, 0, sizeof(cdbmp->cdb_buf));
  cdb_pack(rlen - 8, cdbmp->cdb_buf + 4);
  for(;;) {
    rpos = rlen > sizeof(cdbmp->cdb_buf) ? sizeof(cdbmp->cdb_buf) : rlen;
    if (_cdb_make_fullwrite(cdbmp->cdb_fd, cdbmp->cdb_buf, rpos) < 0)
      return -1;
    rlen -= rpos;
    if (!rlen) return 0;
    memset(cdbmp->cdb_buf + 4, 0, 4);
  }
}
Example #2
0
int
cdb_make_put(struct cdb_make *cdbmp,
	     const void *key, unsigned klen,
	     const void *val, unsigned vlen,
	     int flags)
{
  unsigned char rlen[8];
  unsigned hval = cdb_hash(key, klen);
  struct cdb_rl *rl;
  int c, r;

  switch(flags) {
    case CDB_PUT_REPLACE:
    case CDB_PUT_INSERT:
    case CDB_PUT_WARN:
      c = _cdb_make_find(cdbmp, key, klen, hval, &rl);
      if (c < 0)
	return -1;
      if (c) {
	if (flags == CDB_PUT_INSERT)
	  return errno = EEXIST, 1;
	else if (flags == CDB_PUT_REPLACE) {
	  --c;
	  r = 1;
	  break;
	}
	else
	  r = 1;
      }
      /* fall */

    case CDB_PUT_ADD:
      rl = cdbmp->cdb_rec[hval&255];
      if (!rl || rl->cnt >= sizeof(rl->rec)/sizeof(rl->rec[0])) {
 	rl = (struct cdb_rl*)xmalloc(sizeof(struct cdb_rl));
	if (!rl)
	  return errno = ENOMEM, -1;
	rl->cnt = 0;
	rl->next = cdbmp->cdb_rec[hval&255];
	cdbmp->cdb_rec[hval&255] = rl;
      }
      c = rl->cnt;
      r = 0;
      break;

    default:
      return errno = EINVAL, -1;
  }

  if (klen > 0xffffffff - (cdbmp->cdb_dpos + 8) ||
      vlen > 0xffffffff - (cdbmp->cdb_dpos + klen + 8))
    return errno = ENOMEM, -1;
  rl->rec[c].hval = hval;
  rl->rec[c].rpos = cdbmp->cdb_dpos;
  if ((unsigned)c == rl->cnt) {
    ++rl->cnt;
    ++cdbmp->cdb_rcnt;
  }
  cdb_pack(klen, rlen);
  cdb_pack(vlen, rlen + 4);
  if (_cdb_make_write(cdbmp, (const char *)rlen, 8) < 0 ||
      _cdb_make_write(cdbmp, (const char *)key, klen) < 0 ||
      _cdb_make_write(cdbmp, (const char *)val, vlen) < 0)
    return -1;
  return r;
}