示例#1
0
文件: node.c 项目: tycho/pearpc
/*
 * NAME:	node->free()
 * DESCRIPTION:	deallocate and remove a b*-tree node
 */
int n_free(node *np)
{
  btree *bt = np->bt;
  node sib;

  if (bt->hdr.bthFNode == np->nnum)
    bt->hdr.bthFNode = np->nd.ndFLink;

  if (bt->hdr.bthLNode == np->nnum)
    bt->hdr.bthLNode = np->nd.ndBLink;

  if (np->nd.ndFLink > 0)
    {
      if (bt_getnode(&sib, bt, np->nd.ndFLink) == -1)
	goto fail;

      sib.nd.ndBLink = np->nd.ndBLink;

      if (bt_putnode(&sib) == -1)
	goto fail;
    }

  if (np->nd.ndBLink > 0)
    {
      if (bt_getnode(&sib, bt, np->nd.ndBLink) == -1)
	goto fail;

      sib.nd.ndFLink = np->nd.ndFLink;

      if (bt_putnode(&sib) == -1)
	goto fail;
    }

  BMCLR(bt->map, np->nnum);
  ++bt->hdr.bthFree;

  bt->flags |= HFS_BT_UPDATE_HDR;

  return 0;

fail:
  return -1;
}
示例#2
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;
}
示例#3
0
文件: node.c 项目: tycho/pearpc
/*
 * NAME:	node->delete()
 * DESCRIPTION:	remove a record from a node
 */
int n_delete(node *np, byte *record, int *flag)
{
  byte *rec;

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

  HFS_SETKEYLEN(rec, 0);
  compact(np);

  if (np->nd.ndNRecs == 0)
    {
      if (n_free(np) == -1)
	goto fail;

      HFS_SETKEYLEN(record, 0);
      *flag = 1;

      return 0;
    }

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

  if (np->nd.ndBLink > 0)
    {
      node left;

      if (bt_getnode(&left, np->bt, np->nd.ndBLink) == -1)
	goto fail;

      if (np->nd.ndNRecs + left.nd.ndNRecs <= HFS_MAX_NRECS &&
	  NODEUSED(*np) + 2 * np->nd.ndNRecs <= NODEFREE(left))
	return join(&left, np, record, flag);
    }

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

      n_index(np, record, 0);
      *flag = 1;
    }

  return bt_putnode(np);

fail:
  return -1;
}
示例#4
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);
}
示例#5
0
文件: node.c 项目: tycho/pearpc
/*
 * NAME:	split()
 * DESCRIPTION:	divide a node into two and insert a record
 */
static
int split(node *left, byte *record, unsigned int *reclen)
{
  btree *bt = left->bt;
  node n, *right = &n, *side = 0;
  int mark, i;

  /* create a second node by cloning the first */

  *right = *left;

  if (n_new(right) == -1)
    goto fail;

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

  /* divide all records evenly between the two nodes */

  mark = (NODEUSED(*left) + 2 * left->nd.ndNRecs + *reclen + 2) >> 1;

  if (left->rnum == -1)
    {
      side  = left;
      mark -= *reclen + 2;
    }

  for (i = 0; i < left->nd.ndNRecs; ++i)
    {
      node *np;
      byte *rec;

      np  = (mark > 0) ? right : left;
      rec = HFS_NODEREC(*np, i);

      mark -= HFS_RECLEN(*np, i) + 2;

      HFS_SETKEYLEN(rec, 0);

      if (left->rnum == i)
	{
	  side  = (mark > 0) ? left : right;
	  mark -= *reclen + 2;
	}
    }

  compact(left);
  compact(right);

  /* insert the new record and store the modified nodes */

  ASSERT(side);

  n_search(side, record);
  n_insertx(side, record, *reclen);

  if (bt_putnode(left) == -1 ||
      bt_putnode(right) == -1)
    goto fail;

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

  n_index(right, record, reclen);

  /* update link pointers */

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

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

      if (bt_getnode(&sib, right->bt, right->nd.ndFLink) == -1)
	goto fail;

      sib.nd.ndBLink = right->nnum;

      if (bt_putnode(&sib) == -1)
	goto fail;
    }

  return 0;

fail:
  return -1;
}
示例#6
0
/*
 * NAME:	vol->scavenge()
 * DESCRIPTION:	safeguard blocks in the volume bitmap
 */
int v_scavenge(hfsvol *vol)
{
    const block *vbm = vol->vbm;
    node n;
    unsigned int pt, blks;

    if (vbm == 0)
        goto done;

    markexts(vbm, &vol->mdb.drXTExtRec);
    markexts(vbm, &vol->mdb.drCTExtRec);

    vol->flags |= HFS_VOL_UPDATE_VBM;

    /* scavenge the extents overflow file */

    n.bt   = &vol->ext;
    n.nnum = vol->ext.hdr.bthFNode;

    if (n.nnum > 0)
    {
        if (bt_getnode(&n) == -1)
            goto fail;

        n.rnum = 0;

        while (1)
        {
            ExtDataRec data;
            const byte *ptr;

            while (n.rnum >= n.nd.ndNRecs)
            {
                n.nnum = n.nd.ndFLink;
                if (n.nnum == 0)
                    break;

                if (bt_getnode(&n) == -1)
                    goto fail;

                n.rnum = 0;
            }

            if (n.nnum == 0)
                break;

            ptr = HFS_NODEREC(n, n.rnum);
            r_unpackextdata(HFS_RECDATA(ptr), &data);

            markexts(vbm, &data);

            ++n.rnum;
        }
    }

    /* scavenge the catalog file */

    n.bt   = &vol->cat;
    n.nnum = vol->cat.hdr.bthFNode;

    if (n.nnum > 0)
    {
        if (bt_getnode(&n) == -1)
            goto fail;

        n.rnum = 0;

        while (1)
        {
            CatDataRec data;
            const byte *ptr;

            while (n.rnum >= n.nd.ndNRecs)
            {
                n.nnum = n.nd.ndFLink;
                if (n.nnum == 0)
                    break;

                if (bt_getnode(&n) == -1)
                    goto fail;

                n.rnum = 0;
            }

            if (n.nnum == 0)
                break;

            ptr = HFS_NODEREC(n, n.rnum);
            r_unpackcatdata(HFS_RECDATA(ptr), &data);

            if (data.cdrType == cdrFilRec)
            {
                markexts(vbm, &data.u.fil.filExtRec);
                markexts(vbm, &data.u.fil.filRExtRec);
            }

            ++n.rnum;
        }
    }

    for (blks = 0, pt = vol->mdb.drNmAlBlks; pt--; )
    {
        if (! BMTST(vbm, pt))
            ++blks;
    }

    if (vol->mdb.drFreeBks != blks)
    {
        vol->mdb.drFreeBks = blks;
        vol->flags |= HFS_VOL_UPDATE_MDB;
    }

done:
    return 0;

fail:
    return -1;
}
示例#7
0
文件: hfs.c 项目: 3a9LL/panda
/*
 * NAME:	hfs->readdir()
 * DESCRIPTION:	return the next entry in the directory
 */
int hfs_readdir(hfsdir *dir, hfsdirent *ent)
{
  CatKeyRec key;
  CatDataRec data;
  const byte *ptr;

  if (dir->dirid == 0)
    {
      hfsvol *vol;
      char cname[HFS_MAX_FLEN + 1];

      for (vol = hfs_mounts; vol; vol = vol->next)
	{
	  if (vol == dir->vptr)
	    break;
	}

      if (vol == NULL)
	ERROR(ENOENT, "no more entries");

      if (v_getdthread(vol, HFS_CNID_ROOTDIR, &data, NULL) <= 0 ||
	  v_catsearch(vol, HFS_CNID_ROOTPAR, data.u.dthd.thdCName,
                      &data, cname, NULL) <= 0)
	goto fail;

      r_unpackdirent(HFS_CNID_ROOTPAR, cname, &data, ent);

      dir->vptr = vol->next;

      goto done;
    }

  if (dir->n.rnum == -1)
    ERROR(ENOENT, "no more entries");

  while (1)
    {
      ++dir->n.rnum;

      while (dir->n.rnum >= dir->n.nd.ndNRecs)
	{
	  if (dir->n.nd.ndFLink == 0)
	    {
	      dir->n.rnum = -1;
	      ERROR(ENOENT, "no more entries");
	    }

	  if (bt_getnode(&dir->n, dir->n.bt, dir->n.nd.ndFLink) == -1)
	    {
	      dir->n.rnum = -1;
	      goto fail;
	    }

	  dir->n.rnum = 0;
	}

      ptr = HFS_NODEREC(dir->n, dir->n.rnum);

      r_unpackcatkey(ptr, &key);

      if (key.ckrParID != dir->dirid)
	{
	  dir->n.rnum = -1;
	  ERROR(ENOENT, "no more entries");
	}

      r_unpackcatdata(HFS_RECDATA(ptr), &data);

      switch (data.cdrType)
	{
	case cdrDirRec:
	case cdrFilRec:
	  r_unpackdirent(key.ckrParID, key.ckrCName, &data, ent);
	  goto done;

	case cdrThdRec:
	case cdrFThdRec:
	  break;

	default:
	  dir->n.rnum = -1;
	  ERROR(EIO, "unexpected directory entry found");
	}
    }

done:
  return 0;

fail:
  return -1;
}
示例#8
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;
}
示例#9
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;
}