Пример #1
0
/*
 * NAME:	node->new()
 * DESCRIPTION:	allocate a new b*-tree node
 */
int n_new(node *np)
{
  btree *bt = np->bt;
  unsigned long num;

  if (bt->hdr.bthFree == 0)
    ERROR(EIO, "b*-tree full");

  num = 0;
  while (num < bt->hdr.bthNNodes && BMTST(bt->map, num))
    ++num;

  if (num == bt->hdr.bthNNodes)
    ERROR(EIO, "free b*-tree node not found");

  np->nnum = num;

  BMSET(bt->map, num);
  --bt->hdr.bthFree;

  bt->flags |= HFS_BT_UPDATE_HDR;

  return 0;

fail:
  return -1;
}
Пример #2
0
/*
 * NAME:	vol->allocblocks()
 * DESCRIPTION:	allocate a contiguous range of blocks
 */
int v_allocblocks(hfsvol *vol, ExtDescriptor *blocks)
{
    unsigned int request, found, foundat, start, end;
    register unsigned int pt;
    const block *vbm;
    int wrap = 0;

    if (vol->mdb.drFreeBks == 0)
        ERROR(ENOSPC, "volume full");

    request = blocks->xdrNumABlks;
    found   = 0;
    foundat = 0;
    start   = vol->mdb.drAllocPtr;
    end     = vol->mdb.drNmAlBlks;
    vbm     = vol->vbm;

# ifdef DEBUG
    if (request == 0)
        abort();
# endif

    /* backtrack the start pointer to recover unused space */

    if (! BMTST(vbm, start))
    {
        while (start > 0 && ! BMTST(vbm, start - 1))
            --start;
    }

    /* find largest unused block which satisfies request */

    pt = start;

    while (1)
    {
        unsigned int mark;

        /* skip blocks in use */

        while (pt < end && BMTST(vbm, pt))
            ++pt;

        if (wrap && pt >= start)
            break;

        /* count blocks not in use */

        mark = pt;
        while (pt < end && pt - mark < request && ! BMTST(vbm, pt))
            ++pt;

        if (pt - mark > found)
        {
            found   = pt - mark;
            foundat = mark;
        }

        if (wrap && pt >= start)
            break;

        if (pt == end)
            pt = 0, wrap = 1;

        if (found == request)
            break;
    }

    if (found == 0 || found > vol->mdb.drFreeBks)
        ERROR(EIO, "bad volume bitmap or free block count");

    blocks->xdrStABN    = foundat;
    blocks->xdrNumABlks = found;

    vol->mdb.drAllocPtr = pt;
    vol->mdb.drFreeBks -= found;

    for (pt = foundat; pt < foundat + found; ++pt)
        BMSET(vbm, pt);

    vol->flags |= HFS_VOL_UPDATE_MDB | HFS_VOL_UPDATE_VBM;

    return 0;

fail:
    return -1;
}
Пример #3
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;
}
Пример #4
0
/*
 * NAME:	vol->allocblocks()
 * DESCRIPTION:	allocate a contiguous range of blocks
 */
int v_allocblocks(hfsvol *vol, ExtDescriptor *blocks)
{
  unsigned int request, found, foundat, start, end, pt;
  block *vbm;
  int wrap = 0;

  if (vol->mdb.drFreeBks == 0)
    {
      ERROR(ENOSPC, "volume full");
      return -1;
    }

  request = blocks->xdrNumABlks;
  found   = 0;
  foundat = 0;
  start   = vol->mdb.drAllocPtr;
  end     = vol->mdb.drNmAlBlks;
  pt      = start;
  vbm     = vol->vbm;

  if (request == 0)
    abort();

  while (1)
    {
      unsigned int mark;

      /* skip blocks in use */

      while (pt < end && BMTST(vbm, pt))
	++pt;

      if (wrap && pt >= start)
	break;

      /* count blocks not in use */

      mark = pt;
      while (pt < end && pt - mark < request && ! BMTST(vbm, pt))
	++pt;

      if (pt - mark > found)
	{
	  found   = pt - mark;
	  foundat = mark;
	}

      if (pt == end)
	pt = 0, wrap = 1;

      if (found == request)
	break;
    }

  if (found == 0 || found > vol->mdb.drFreeBks)
    {
      ERROR(EIO, "bad volume bitmap or free block count");
      return -1;
    }

  blocks->xdrStABN    = foundat;
  blocks->xdrNumABlks = found;

  vol->mdb.drAllocPtr = pt;
  vol->mdb.drFreeBks -= found;

  for (pt = foundat; pt < foundat + found; ++pt)
    BMSET(vbm, pt);

  vol->flags |= HFS_UPDATE_MDB | HFS_UPDATE_VBM;

  return 0;
}