* NAME: vol->allocblocks() * DESCRIPTION: allocate a contiguous range of blocks */
| 623 | * DESCRIPTION: allocate a contiguous range of blocks |
| 624 | */ |
| 625 | int v_allocblocks(hfsvol *vol, ExtDescriptor *blocks) |
| 626 | { |
| 627 | unsigned int request, found, foundat, start, end; |
| 628 | register unsigned int pt; |
| 629 | block *vbm; |
| 630 | int wrap = 0; |
| 631 | |
| 632 | if (vol->mdb.drFreeBks == 0) |
| 633 | ERROR(ENOSPC, "volume full"); |
| 634 | |
| 635 | request = blocks->xdrNumABlks; |
| 636 | found = 0; |
| 637 | foundat = 0; |
| 638 | start = vol->mdb.drAllocPtr; |
| 639 | end = vol->mdb.drNmAlBlks; |
| 640 | vbm = vol->vbm; |
| 641 | |
| 642 | ASSERT(request > 0); |
| 643 | |
| 644 | /* backtrack the start pointer to recover unused space */ |
| 645 | |
| 646 | if (! BMTST(vbm, start)) |
| 647 | { |
| 648 | while (start > 0 && ! BMTST(vbm, start - 1)) |
| 649 | --start; |
| 650 | } |
| 651 | |
| 652 | /* find largest unused block which satisfies request */ |
| 653 | |
| 654 | pt = start; |
| 655 | |
| 656 | while (1) |
| 657 | { |
| 658 | unsigned int mark; |
| 659 | |
| 660 | /* skip blocks in use */ |
| 661 | |
| 662 | while (pt < end && BMTST(vbm, pt)) |
| 663 | ++pt; |
| 664 | |
| 665 | if (wrap && pt >= start) |
| 666 | break; |
| 667 | |
| 668 | /* count blocks not in use */ |
| 669 | |
| 670 | mark = pt; |
| 671 | while (pt < end && pt - mark < request && ! BMTST(vbm, pt)) |
| 672 | ++pt; |
| 673 | |
| 674 | if (pt - mark > found) |
| 675 | { |
| 676 | found = pt - mark; |
| 677 | foundat = mark; |
| 678 | } |
| 679 | |
| 680 | if (wrap && pt >= start) |
| 681 | break; |
| 682 |