コード例 #1
0
ファイル: node.c プロジェクト: Distrotech/cdrkit
/*
 * NAME:	node->compact()
 * DESCRIPTION:	clean up a node, removing deleted records
 */
void n_compact(node *np)
{
  unsigned char *ptr;
  int offset, nrecs, i;

  offset = 0x00e;
  ptr    = np->data + offset;
  nrecs  = 0;

  for (i = 0; i < (int)np->nd.ndNRecs; ++i)
    {
      unsigned char *rec;
      int reclen;

      rec    = HFS_NODEREC(*np, i);
      reclen = np->roff[i + 1] - np->roff[i];

      if (HFS_RECKEYLEN(rec) > 0)
	{
	  np->roff[nrecs++] = offset;
	  offset += reclen;

	  if (ptr == rec)
	    ptr += reclen;
	  else
	    {
	      while (reclen--)
		*ptr++ = *rec++;
	    }
	}
    }

  np->roff[nrecs] = offset;
  np->nd.ndNRecs  = nrecs;
}
コード例 #2
0
ファイル: node.c プロジェクト: tycho/pearpc
/*
 * NAME:	node->search()
 * DESCRIPTION:	locate a record in a node, or the record it should follow
 */
int n_search(node *np, const byte *pkey)
{
  const btree *bt = np->bt;
  byte key1[HFS_MAX_KEYLEN], key2[HFS_MAX_KEYLEN];
  int i, comp = -1;

  bt->keyunpack(pkey, key2);

  for (i = np->nd.ndNRecs; i--; )
    {
      const byte *rec;

      rec = HFS_NODEREC(*np, i);

      if (HFS_RECKEYLEN(rec) == 0)
	continue;  /* deleted record */

      bt->keyunpack(rec, key1);
      comp = bt->keycompare(key1, key2);

      if (comp <= 0)
	break;
    }

  np->rnum = i;

  return comp == 0;
}
コード例 #3
0
ファイル: node.c プロジェクト: Distrotech/cdrkit
/*
 * NAME:	node->index()
 * DESCRIPTION:	create an index record from a key and node pointer
 */
void n_index(btree *bt, unsigned char *key, unsigned long nnum, 
             unsigned char *record, int *reclen)
{
  if (bt == &bt->f.vol->cat)
    {
      /* force the key length to be 0x25 */

      HFS_RECKEYLEN(record) = 0x25;
      memset(record + 1, 0, 0x25);
      memcpy(record + 1, key + 1, HFS_RECKEYLEN(key));
    }
  else
    memcpy(record, key, HFS_RECKEYSKIP(key));

  d_putl(HFS_RECDATA(record), nnum);

  if (reclen)
    *reclen = HFS_RECKEYSKIP(record) + 4;
}
コード例 #4
0
ファイル: node.c プロジェクト: Distrotech/cdrkit
/*
 * NAME:	node->merge()
 * DESCRIPTION:	combine two nodes into a single node
 */
int n_merge(node *right, node *left, unsigned char *record, int *flag)
{
  int i, offset;

  /* copy records and offsets */

  memcpy(HFS_NODEREC(*left, left->nd.ndNRecs), HFS_NODEREC(*right, 0),
	 right->roff[right->nd.ndNRecs] - right->roff[0]);

  offset = left->roff[left->nd.ndNRecs] - right->roff[0];

  for (i = 1; i <= (int)right->nd.ndNRecs; ++i)
    left->roff[++left->nd.ndNRecs] = offset + right->roff[i];

  /* update link pointers */

  left->nd.ndFLink = right->nd.ndFLink;

  if (bt_putnode(left) < 0)
    return -1;

  if (right->bt->hdr.bthLNode == right->nnum)
    {
      right->bt->hdr.bthLNode = left->nnum;
      right->bt->flags |= HFS_UPDATE_BTHDR;
    }

  if (right->nd.ndFLink)
    {
      node n;

      n.bt   = right->bt;
      n.nnum = right->nd.ndFLink;

      if (bt_getnode(&n) < 0)
	return -1;

      n.nd.ndBLink = left->nnum;

      if (bt_putnode(&n) < 0)
	return -1;
    }

  n_free(right);

  HFS_RECKEYLEN(record) = 0;
  *flag = 1;

  return 0;
}
コード例 #5
0
ファイル: node.c プロジェクト: tycho/pearpc
/*
 * NAME:	node->index()
 * DESCRIPTION:	create an index record from a key and node pointer
 */
void n_index(const node *np, byte *record, unsigned int *reclen)
{
  const byte *key = HFS_NODEREC(*np, 0);

  if (np->bt == &np->bt->f.vol->cat)
    {
      /* force the key length to be 0x25 */

      HFS_SETKEYLEN(record, 0x25);
      memset(record + 1, 0, 0x25);
      memcpy(record + 1, key + 1, HFS_RECKEYLEN(key));
    }
  else
    memcpy(record, key, HFS_RECKEYSKIP(key));

  d_putul(HFS_RECDATA(record), np->nnum);

  if (reclen)
    *reclen = HFS_RECKEYSKIP(record) + 4;
}
コード例 #6
0
ファイル: node.c プロジェクト: tycho/pearpc
/*
 * NAME:	compact()
 * DESCRIPTION:	clean up a node, removing deleted records
 */
static
void compact(node *np)
{
  byte *ptr;
  int offset, nrecs, i;

  offset = 0x00e;
  ptr    = np->data + offset;
  nrecs  = 0;

  for (i = 0; i < np->nd.ndNRecs; ++i)
    {
      const byte *rec;
      int reclen;

      rec    = HFS_NODEREC(*np, i);
      reclen = HFS_RECLEN(*np, i);

      if (HFS_RECKEYLEN(rec) > 0)
	{
	  np->roff[nrecs++] = offset;
	  offset += reclen;

	  if (ptr == rec)
	    ptr += reclen;
	  else
	    {
	      while (reclen--)
		*ptr++ = *rec++;
	    }
	}
    }

  np->roff[nrecs] = offset;
  np->nd.ndNRecs  = nrecs;
}
コード例 #7
0
ファイル: node.c プロジェクト: Distrotech/cdrkit
/*
 * NAME:	node->delete()
 * DESCRIPTION:	remove a record from a node
 */
int n_delete(node *np, unsigned char *record, int *flag)
{
  node left;
  unsigned char *rec;

  rec = HFS_NODEREC(*np, np->rnum);

  HFS_RECKEYLEN(rec) = 0;
  n_compact(np);

  /* see if we can merge with our left sibling */

  left.bt   = np->bt;
  left.nnum = np->nd.ndBLink;

  if (left.nnum > 0)
    {
      if (bt_getnode(&left) < 0)
	return -1;

      if ((int)(np->nd.ndNRecs + left.nd.ndNRecs) <= HFS_MAXRECS &&
	  (int)(np->roff[np->nd.ndNRecs] - np->roff[0] +
	  2 * np->nd.ndNRecs) <= (int)NODESPACE(left))
	return n_merge(np, &left, record, flag);
    }

  if (np->rnum == 0)
    {
      /* special case: first record changed; update parent record key */

      n_index(np->bt, HFS_NODEREC(*np, 0), np->nnum, record, 0);
      *flag = 1;
    }

  return bt_putnode(np);
}
コード例 #8
0
ファイル: node.c プロジェクト: Distrotech/cdrkit
/*
 * NAME:	node->search()
 * DESCRIPTION:	locate a record in a node, or the record it should follow
 */
int n_search(node *np, unsigned char *key)
{
  btree *bt = np->bt;
  int i, comp = -1;

  for (i = np->nd.ndNRecs; i--; )
    {
      unsigned char *rec;

      rec = HFS_NODEREC(*np, i);

      if (HFS_RECKEYLEN(rec) == 0)
	continue;  /* deleted record */

      comp = bt->compare(rec, key);

      if (comp <= 0)
	break;
    }

  np->rnum = i;

  return comp == 0;
}
コード例 #9
0
ファイル: node.c プロジェクト: Distrotech/cdrkit
/*
 * NAME:	node->split()
 * DESCRIPTION:	divide a node into two and insert a record
 */
int n_split(node *left, unsigned char *record, int *reclen)
{
  node right;
  int nrecs, i, mid;
  unsigned char *rec;

  right = *left;
  right.nd.ndBLink = left->nnum;

  if (n_new(&right) < 0)
    return -1;

  left->nd.ndFLink = right.nnum;
  nrecs = left->nd.ndNRecs;

  /*
   * Ensure node split leaves enough room for new record.
   * The size calculations used are based on the NODESPACE() macro, but
   * I don't know what the extra 2's and 1's are needed for.
   * John Witford <*****@*****.**>
   */
  n_search(&right, record);
  mid = nrecs/2;
  for(;;)
    {
	if (right.rnum < mid)
	{
	    if (   mid > 0
		&& (int)left->roff[mid] + *reclen + 2 > HFS_BLOCKSZ - 2 * (mid + 1))
	    {
		--mid;
		if (mid > 0)
		    continue;
	    }
	}
	else
	{
	    if (   mid < nrecs
		&& (int)right.roff[nrecs] - (int)right.roff[mid] + (int)left->roff[0] + *reclen + 2 > HFS_BLOCKSZ - 2 * (mid + 1))
	    {
		++mid;
		if (mid < nrecs)
		    continue;
	    }
	}
	break;
    }

  for (i = 0; i < nrecs; ++i)
    {
	if (i < mid)
	    rec = HFS_NODEREC(right, i);
	else
	    rec = HFS_NODEREC(*left, i);

	HFS_RECKEYLEN(rec) = 0;
    }

/* original code ...
  for (i = 0; i < nrecs; ++i)
    {
      if (i < nrecs / 2)
	rec = HFS_NODEREC(right, i);
      else
	rec = HFS_NODEREC(*left, i);

      HFS_RECKEYLEN(rec) = 0;
    }
*/
  n_compact(left);
  n_compact(&right);

  n_search(&right, record);
  if (right.rnum >= 0)
    n_insertx(&right, record, *reclen);
  else
    {
      n_search(left, record);
      n_insertx(left, record, *reclen);
    }

  /* store the new/modified nodes */

  if (bt_putnode(left) < 0 ||
      bt_putnode(&right) < 0)
    return -1;

  /* create an index record for the new node in the parent */

  n_index(right.bt, HFS_NODEREC(right, 0), right.nnum, record, reclen);

  /* update link pointers */

  if (left->bt->hdr.bthLNode == left->nnum)
    {
      left->bt->hdr.bthLNode = right.nnum;
      left->bt->flags |= HFS_UPDATE_BTHDR;
    }

  if (right.nd.ndFLink)
    {
      node n;

      n.bt   = right.bt;
      n.nnum = right.nd.ndFLink;

      if (bt_getnode(&n) < 0)
	return -1;

      n.nd.ndBLink = right.nnum;

      if (bt_putnode(&n) < 0)
	return -1;
    }

  return 0;
}
コード例 #10
0
ファイル: node.c プロジェクト: OS2World/DRV-HFS
/*
 * NAME:	node->split()
 * DESCRIPTION:	divide a node into two and insert a record
 */
int n_split(node *left, unsigned char *record, int *reclen)
{
  node right;
  int nrecs, i;
  unsigned char *rec;

  right = *left;
  right.nd.ndBLink = left->nnum;

  if (n_new(&right) < 0)
    return -1;

  left->nd.ndFLink = right.nnum;
  nrecs = left->nd.ndNRecs;

  for (i = 0; i < nrecs; ++i)
    {
      if (i < nrecs / 2)
	rec = HFS_NODEREC(right, i);
      else
	rec = HFS_NODEREC(*left, i);

      HFS_RECKEYLEN(rec) = 0;
    }

  n_compact(left);
  n_compact(&right);

  n_search(&right, record);
  if (right.rnum >= 0)
    n_insertx(&right, record, *reclen);
  else
    {
      n_search(left, record);
      n_insertx(left, record, *reclen);
    }

  /* store the new/modified nodes */

  if (bt_putnode(left) < 0 ||
      bt_putnode(&right) < 0)
    return -1;

  /* create an index record for the new node in the parent */

  n_index(right.bt, HFS_NODEREC(right, 0), right.nnum, record, reclen);

  /* update link pointers */

  if (left->bt->hdr.bthLNode == left->nnum)
    {
      left->bt->hdr.bthLNode = right.nnum;
      left->bt->flags |= HFS_UPDATE_BTHDR;
    }

  if (right.nd.ndFLink)
    {
      node n;

      n.bt   = right.bt;
      n.nnum = right.nd.ndFLink;

      if (bt_getnode(&n) < 0)
	return -1;

      n.nd.ndBLink = right.nnum;

      if (bt_putnode(&n) < 0)
	return -1;
    }

  return 0;
}