Wim Lewis


Mac::Finder::DSStore::BuddyAllocator - Allocate space within a file


Mac::Finder::DSStore::BuddyAllocator implements a buddy-allocation scheme within a file. It's used by Mac::Finder::DSStore to read certain files created by the Macintosh Finder.

The allocation methods do not perform any actual file I/O. The contents of allocated blocks are read and written by the caller using methods on BuddyAllocator::Block. If the allocate and free methods are used, or if the toc hash is modified, writeMetaData must be called for the changes to be reflected in the file.


$allocator = Mac::Finder::DSStore::BuddyAllocator->open($fh)

open($fh) constructs a new buddy allocator and initializes its state from the information in the file. The file handle is retained by the allocator for future operations.

$allocator = Mac::Finder::DSStore::BuddyAllocator->new($fh)

Similar to open, but does not read anything from the file. This can be used to create a new file from scratch.

$allocator->close( )

Closes the underlying file handle.


List all the blocks in order and see if there are any gaps or overlaps. If $verbose is true, then the blocks are listed to the current output filehandle. Returns true if the allocated and free blocks have no gaps or overlaps.

$allocator->writeMetaData( )

Writes the allocator's metadata (header block and root block) back to the file.

$block = $allocator->blockByNumber(blocknumber[, write])

Retrieves a block by its block number (aka block ID).

If write is supplied and is true, then the returned block implements the write method but not the read method.

$block = $allocator->getBlock(offset, size)

Retrieves a block (a BuddyAllocator::Block instance) by offset & length. Normally you should use blockByNumber instead of this method.

( $offset, $size ) = $allocator->blockOffset(blockid)

Retrieves the file offset and size in bytes of a given block. The offset doesn't include the 4-byte fudge. In scalar context, just returns the offset.

$blocknumber = $allocator->allocate($size, [$blocknumber])

Allocates or re-allocates a block to be at least $size bytes long. If $blocknumber is given, the specified block will be grown or shrunk if needed, otherwise a new block number will be chosen and given to the allocated block.

Unlike the libc realloc function, this may move a block even if the block is not grown.


Releases the block number and the block associated with it back to the block pool.



toc holds a hashref whose keys are short strings and whose values are integers. This table of contents is read and written as part of the allocator's metadata but is not otherwise used by the allocator; users of the allocator use it to find their data within the file.


The file handle passed in to open or new. If you find yourself needing to use this, you should probably try to extend the class so that you don't.


BuddyAllocator::Block instances are returned by the blockByNumber and getBlock methods. They hold a pointer into the file and provide a handful of useful methods.

(There are also two other classes, WriteBlock and StringBlock, which might be returned instead. Think of this as an interface rather than as a concrete class.)

$block->read(length, [format])

Reads length bytes from the block (advancing the read pointer correspondingly). If format is specified, the bytes read are unpacked using the format; otherwise a byte string is returned.

$block->length( )

Returns the length (or size) of this block.

$block->seek(position[, whence])

Adjusts the read/write pointer within the block.


$block->write(format, items...)

Writes data to the underlying file, at the position represented by this block. If multiple arguments are given, the first is a format string and the rest are the remaining arguments to pack.

$block->close([ zerofill ])

This is generally a no-op, but if called on a writable block with zerofill = true, then zeroes will be written from the current location to the end of the allocated block.

$block->copyback( )

Returns the block's contents as a string. For write blocks, this reads from the file. This is just here for debugging purposes and might change.


Written by Wim Lewis as part of the Mac::Finder::DSStore package.

This file is copyright 2008 by Wim Lewis. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.