31 Commits

Author SHA1 Message Date
ksherlock
699c44cf15 check for SDK with binary II header.
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@379 aa027e90-d47c-11dd-86d7-074df07e0730
2011-03-09 04:10:33 +00:00
ksherlock
1a0bdd875c Implement better image type inspection.
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@378 aa027e90-d47c-11dd-86d7-074df07e0730
2011-03-08 05:16:59 +00:00
ksherlock
77e5994908 DC42 validation, fix infinite loop with validation.
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@377 aa027e90-d47c-11dd-86d7-074df07e0730
2011-03-08 03:20:14 +00:00
ksherlock
5ab8fd3d87 add no-throwing validation code.
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@376 aa027e90-d47c-11dd-86d7-074df07e0730
2011-03-07 23:39:52 +00:00
ksherlock
c6165e16d2 clean up sdk code.
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@375 aa027e90-d47c-11dd-86d7-074df07e0730
2011-03-07 00:44:14 +00:00
ksherlock
87d6070dcf add (read only) support for SDK images. Requires nufxlib.
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@374 aa027e90-d47c-11dd-86d7-074df07e0730
2011-03-07 00:09:37 +00:00
ksherlock
0e083d53e7 fix apple noattr error
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@373 aa027e90-d47c-11dd-86d7-074df07e0730
2011-03-01 22:48:29 +00:00
ksherlock
78b1b8b242 git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@372 aa027e90-d47c-11dd-86d7-074df07e0730 2011-02-28 05:17:12 +00:00
ksherlock
977f0530fc git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@371 aa027e90-d47c-11dd-86d7-074df07e0730 2011-02-28 05:17:05 +00:00
ksherlock
24757dc35c smart pointer macros
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@370 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-28 05:05:13 +00:00
ksherlock
ac8bbd5265 update Device with shared_ptr macros
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@369 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-28 05:04:30 +00:00
ksherlock
c7c4f13bf7 update Cache/
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@368 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-28 05:00:21 +00:00
ksherlock
68a7851f33 git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@366 aa027e90-d47c-11dd-86d7-074df07e0730 2011-02-28 04:28:40 +00:00
ksherlock
8550923cb3 use Endian/Endian.h code
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@349 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-24 03:21:17 +00:00
ksherlock
c9b260b753 enforce smart pointers for block cache.
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@344 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-22 02:06:56 +00:00
ksherlock
c44145f551 this to smart_ptr
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@343 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-21 22:47:56 +00:00
ksherlock
3f8e7ad7ae switch to BlockDevice, smart_ptr.
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@342 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-20 23:05:40 +00:00
ksherlock
4cdfc52c04 use tr1 smart_ptr.
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@341 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-20 23:05:09 +00:00
ksherlock
1fd924ae1b delete extraneous makefile
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@340 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-20 23:01:01 +00:00
ksherlock
40ea9f2289 Move DateTime to ProDOS/
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@339 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-20 23:00:41 +00:00
ksherlock
9a6e9150ef delete extraneous makefile
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@338 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-20 23:00:17 +00:00
ksherlock
2bd72b08b9 Move ProDOS File code
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@337 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-20 22:35:26 +00:00
ksherlock
664dee7578 new branch to integrate BlockDevice, BlockCache
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@336 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-19 19:51:51 +00:00
ksherlock
ea0d1c198b new branch to integrate BlockDevice, BlockCache
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@335 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-19 19:37:01 +00:00
ksherlock
c82cd3f8fa new branch to integrate BlockDevice, BlockCache
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@334 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-19 18:07:28 +00:00
ksherlock
5427db9990 new branch to integrate BlockDevice, BlockCache
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@333 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-19 18:07:04 +00:00
ksherlock
7fb0604b76 new branch to integrate BlockDevice, BlockCache
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@332 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-19 18:06:42 +00:00
ksherlock
14e9b43f32 new branch to integrate BlockDevice, BlockCache
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@331 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-19 18:05:57 +00:00
ksherlock
e5f935e435 new branch to integrate BlockDevice, BlockCache
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@330 aa027e90-d47c-11dd-86d7-074df07e0730
2011-02-19 18:05:34 +00:00
ksherlock
e36eb445bf MacRoman -> Unicode
git-svn-id: https://profuse.googlecode.com/svn/trunk@63 aa027e90-d47c-11dd-86d7-074df07e0730
2009-09-15 00:04:55 +00:00
ksherlock
caea19006a clean up 64-bit warnings, use ProDOS::DateTime for time conversion.
git-svn-id: https://profuse.googlecode.com/svn/trunk@62 aa027e90-d47c-11dd-86d7-074df07e0730
2009-09-09 04:14:12 +00:00
62 changed files with 6005 additions and 1107 deletions

73
Cache/BlockCache.cpp Normal file
View File

@@ -0,0 +1,73 @@
#include <algorithm>
#include <cerrno>
#include <cstring>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <Cache/BlockCache.h>
#include <Device/BlockDevice.h>
#include <ProFUSE/Exception.h>
#include <ProFUSE/auto.h>
using namespace Device;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
BlockCache::BlockCache(BlockDevicePointer device) :
_device(device)
{
_blocks = device->blocks();
_readOnly = device->readOnly();
}
BlockCache::~BlockCache()
{
}
void BlockCache::write(unsigned block, const void *bp)
{
void *address = acquire(block);
std::memcpy(address, bp, 512);
release(block, true);
}
void BlockCache::read(unsigned block, void *bp)
{
void *address = acquire(block);
std::memcpy(bp, address, 512);
release(block, false);
}
BlockCachePointer BlockCache::Create(BlockDevicePointer device)
{
// this just calls the device virtual function to create a cache.
if (!device) return BlockCachePointer();
return device->createBlockCache();
}
void BlockCache::zeroBlock(unsigned block)
{
/*
void *address = acquire(block);
std::memset(address, 0, 512);
release(block, true);
*/
uint8_t buffer[512];
std::memset(buffer, 0, 512);
write(block, buffer);
}

62
Cache/BlockCache.h Normal file
View File

@@ -0,0 +1,62 @@
#ifndef __BLOCKCACHE_H__
#define __BLOCKCACHE_H__
#include <stdint.h>
#include <vector>
#include <Device/Device.h>
class MappedFile;
namespace Device {
enum BlockReleaseFlags {
kBlockDirty = 1,
kBlockCommitNow = 2,
kBlockReuse = 3
};
class BlockCache {
public:
static BlockCachePointer Create(BlockDevicePointer device);
virtual ~BlockCache();
bool readOnly() { return _readOnly; }
unsigned blocks() { return _blocks; }
BlockDevicePointer device() { return _device; }
virtual void sync() = 0;
virtual void write(unsigned block, const void *bp);
virtual void read(unsigned block, void *bp);
virtual void *acquire(unsigned block) = 0;
virtual void release(unsigned block, int flags) = 0 ;
virtual void markDirty(unsigned block) = 0;
virtual void zeroBlock(unsigned block);
void release(unsigned block) { release(block, 0); }
void release(unsigned block, bool dirty)
{
release(block, dirty ? kBlockDirty : 0);
}
protected:
BlockCache(BlockDevicePointer device);
BlockDevicePointer _device;
private:
unsigned _blocks;
bool _readOnly;
};
} // namespace
#endif

View File

@@ -0,0 +1,382 @@
#include <algorithm>
#include <cerrno>
#include <cstring>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <Device/BlockDevice.h>
#include <Cache/ConcreteBlockCache.h>
#include <ProFUSE/Exception.h>
#include <ProFUSE/auto.h>
/*
* Note -- everything is assumed to be single-threaded.
*
*/
/*
* The primary purpose of the block cache is not as a cache
* (the OS probably does a decent job of that) but rather to
* simplify read/writes. Blocks will always be accessed by
* pointer, so any updates will be shared.
* For memory mapped prodos-order files, MappedBlockCache just
* returns a pointer to the memory.
* For dos-order, nibblized, or raw devices, ConcreteBlockCache
* uses an approach similar to minix (although the buffer pool will
* expand if needed).
*
* _buffers is a vector of all buffers and only exists to make
* freeing them easier.
* _hashTable is a simple hashtable of loaded blocks.
* _first and _last are a double-linked list of unused blocks, stored
* in lru order.
*
* The Entry struct contains the buffer, the block, a dirty flag, and an in-use
* count as well as pointer for the hashtable and lru list.
* When a block is loaded, it is stored in the _hashTable. It remains in the
* hash table when the in-use count goes to 0 (it will also be added to the
* end of the lru list).
*
* dirty buffers are only written to disk in 3 scenarios:
* a) sync() is called
* b) the cache is deleted
* c) a buffer is re-used from the lru list.
*/
using namespace Device;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
//typedef std::vector<ConcreteBlockCache::Entry *>::iterator EntryIter;
BlockCachePointer ConcreteBlockCache::Create(BlockDevicePointer device, unsigned size)
{
//return BlockCachePointer(new ConcreteBlockCache(device, size));
// constructor must be accessible to std::make_shared...
return MAKE_SHARED(ConcreteBlockCache, device, size);
}
ConcreteBlockCache::ConcreteBlockCache(BlockDevicePointer device, unsigned size) :
BlockCache(device)
{
if (size < 16) size = 16;
std::memset(_hashTable, 0, sizeof(Entry *) * HashTableSize);
for (unsigned i = 0; i < size; ++i)
{
Entry *e = new Entry;
std::memset(e, 0, sizeof(Entry));
_buffers.push_back(e);
}
_first = _last = NULL;
_first = _buffers.front();
_last = _buffers.back();
// form a chain....
for (unsigned i = 0; i < size; ++i)
{
Entry *e = _buffers[i];
if (i > 0) e->prev = _buffers[i - 1];
if (i < size - 1) e->next = _buffers[i + 1];
}
}
ConcreteBlockCache::~ConcreteBlockCache()
{
EntryIter iter;
for (iter = _buffers.begin(); iter != _buffers.end(); ++iter)
{
Entry *e = *iter;
if (e->dirty)
{
_device->write(e->block, e->buffer);
}
delete e;
}
_device->sync();
}
void ConcreteBlockCache::sync()
{
EntryIter iter;
for (iter = _buffers.begin(); iter != _buffers.end(); ++iter)
{
Entry *e = *iter;
if (e->dirty)
{
_device->write(e->block, e->buffer);
e->dirty = false;
}
}
_device->sync();
}
void ConcreteBlockCache::write(unsigned block, const void *bp)
{
Entry *e = findEntry(block);
if (e)
{
e->dirty = true;
std::memcpy(e->buffer, bp, 512);
return;
}
// returns a new entry not in the hashtable or the linked list.
// we add it to both.
e = newEntry(block);
e->count = 0;
e->dirty = true;
std::memcpy(e->buffer, bp, 512);
addEntry(e);
setLast(e);
}
void ConcreteBlockCache::markDirty(unsigned block)
{
Entry *e = findEntry(block);
if (e) e->dirty = true;
// error otherwise?
}
void ConcreteBlockCache::release(unsigned block, int flags)
{
Entry *e = findEntry(block);
bool dirty = flags & (kBlockDirty | kBlockCommitNow);
if (e)
{
if (dirty) e->dirty = true;
decrementCount(e);
if (flags & kBlockCommitNow)
{
_device->write(block, e->buffer);
e->dirty = false;
}
}
// error otherwise?
}
void *ConcreteBlockCache::acquire(unsigned block)
{
Entry *e = findEntry(block);
if (e)
{
incrementCount(e);
return e->buffer;
}
// returns a new entry, not in hash table, not in free list.
e = newEntry(block);
_device->read(block, e->buffer);
addEntry(e);
return e->buffer;
}
unsigned ConcreteBlockCache::hashFunction(unsigned block)
{
return block % HashTableSize;
}
ConcreteBlockCache::Entry *ConcreteBlockCache::findEntry(unsigned block)
{
Entry *e;
unsigned hash = hashFunction(block);
e = _hashTable[hash];
while ((e) && (e->block != block))
e = e->nextHash;
return e;
}
/*
* remove a block from the hashtable
* and write to dick if dirty.
*/
void ConcreteBlockCache::removeEntry(unsigned block)
{
Entry *e;
Entry *prev;
unsigned hash = hashFunction(block);
e = _hashTable[hash];
if (!e) return;
// head pointer, special case.
if (e->block == block)
{
_hashTable[hash] = e->nextHash;
e->nextHash = NULL;
return;
}
for(;;)
{
prev = e;
e = e->nextHash;
if (!e) break;
if (e->block == block)
{
prev->nextHash = e->nextHash;
e->nextHash = NULL;
break;
}
}
}
void ConcreteBlockCache::addEntry(Entry *e)
{
unsigned hash = hashFunction(e->block);
e->nextHash = _hashTable[hash];
_hashTable[hash] = e;
}
// increment the count and remove from the free list
// if necessary.
void ConcreteBlockCache::incrementCount(Entry *e)
{
if (e->count == 0)
{
Entry *prev = e->prev;
Entry *next = e->next;
e->prev = e->next = NULL;
if (prev) prev->next = next;
if (next) next->prev = prev;
if (_first == e) _first = next;
if (_last == e) _last = prev;
}
e->count = e->count + 1;
}
// decrement the count. If it goes to 0,
// add it as the last block entry.
void ConcreteBlockCache::decrementCount(Entry *e)
{
e->count = e->count - 1;
if (e->count == 0)
{
setLast(e);
}
}
ConcreteBlockCache::Entry *ConcreteBlockCache::newEntry(unsigned block)
{
Entry *e;
if (_first)
{
e = _first;
if (_first == _last)
{
_first = _last = NULL;
}
else
{
_first = e->next;
_first->prev = NULL;
}
if (e->dirty)
{
_device->write(e->block, e->buffer);
e->dirty = false;
}
removeEntry(e->block);
}
else
{
e = new Entry;
_buffers.push_back(e);
}
e->next = NULL;
e->prev= NULL;
e->nextHash = NULL;
e->count = 1;
e->block = block;
e->dirty = false;
return e;
}
void ConcreteBlockCache::setLast(Entry *e)
{
if (_last == NULL)
{
_first = _last = e;
return;
}
e->prev = _last;
_last->next = e;
_last = e;
}
void ConcreteBlockCache::setFirst(Entry *e)
{
if (_first == NULL)
{
_first = _last = e;
return;
}
e->next = _first;
_first->prev = e;
_first = e;
}

View File

@@ -0,0 +1,75 @@
#ifndef __CONCRETE_BLOCK_CACHE_H__
#define __CONCRETE_BLOCK_CACHE_H__
#include <vector>
#include <Cache/BlockCache.h>
namespace Device {
class ConcreteBlockCache : public BlockCache {
public:
static BlockCachePointer Create(BlockDevicePointer device, unsigned size = 16);
virtual ~ConcreteBlockCache();
virtual void sync();
virtual void write(unsigned block, const void *vp);
virtual void *acquire(unsigned block);
virtual void release(unsigned block, int flags);
virtual void markDirty(unsigned block);
private:
ConcreteBlockCache(BlockDevicePointer device, unsigned size);
struct Entry {
unsigned block;
unsigned count;
bool dirty;
struct Entry *next;
struct Entry *prev;
struct Entry *nextHash;
uint8_t buffer[512];
};
typedef std::vector<Entry *>::iterator EntryIter;
enum { HashTableSize = 23 };
std::vector<Entry *>_buffers;
Entry *_hashTable[HashTableSize];
Entry *_first;
Entry *_last;
unsigned hashFunction(unsigned block);
Entry *findEntry(unsigned block);
void removeEntry(unsigned block);
void addEntry(Entry *);
Entry *newEntry(unsigned block);
void pushEntry(Entry *);
void setLast(Entry *);
void setFirst(Entry *);
void incrementCount(Entry *);
void decrementCount(Entry *);
};
}
#endif

140
Cache/MappedBlockCache.cpp Normal file
View File

@@ -0,0 +1,140 @@
#include <algorithm>
#include <cerrno>
#include <cstring>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <Cache/MappedBlockCache.h>
#include <Device/BlockDevice.h>
#include <ProFUSE/Exception.h>
using namespace Device;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
BlockCachePointer MappedBlockCache::Create(BlockDevicePointer device, void *data)
{
//return BlockCachePointer(new MappedBlockCache(device, data));
return MAKE_SHARED(MappedBlockCache, device, data);
}
MappedBlockCache::MappedBlockCache(BlockDevicePointer device, void *data) :
BlockCache(device)
{
_data = (uint8_t *)data;
_dirty = false;
}
MappedBlockCache::~MappedBlockCache()
{
if (_dirty) sync();
}
void *MappedBlockCache::acquire(unsigned block)
{
#undef __METHOD__
#define __METHOD__ "MappedBlockCache::load"
if (block >= blocks())
throw Exception(__METHOD__ ": Invalid block.");
return _data + block * 512;
}
void MappedBlockCache::release(unsigned block, int flags)
{
#undef __METHOD__
#define __METHOD__ "MappedBlockCache::unload"
// kBlockCommitNow implies kBlockDirty.
if (flags & kBlockCommitNow)
{
sync(block);
return;
}
if (flags & kBlockDirty) _dirty = true;
}
void MappedBlockCache::write(unsigned block, const void *vp)
{
#undef __METHOD__
#define __METHOD__ "MappedBlockCache::write"
if (block >= blocks())
throw Exception(__METHOD__ ": Invalid block.");
_dirty = true;
std::memcpy(_data + block * 512, vp, 512);
}
void MappedBlockCache::zeroBlock(unsigned block)
{
#undef __METHOD__
#define __METHOD__ "MappedBlockCache::zeroBlock"
if (block >= blocks())
throw Exception(__METHOD__ ": Invalid block.");
_dirty = true;
std::memset(_data + block * 512, 0, 512);
}
// sync everything.
void MappedBlockCache::sync()
{
_device->sync();
_dirty = false;
}
/*
*
* sync an individual page.
*
*/
void MappedBlockCache::sync(unsigned block)
{
#undef __METHOD__
#define __METHOD__ "MappedBlockCache::sync"
int pagesize = ::getpagesize();
void *start = _data + block * 512;
void *end = _data + 512 + block * 512;
start = (void *)((ptrdiff_t)start / pagesize * pagesize);
end = (void *)((ptrdiff_t)end / pagesize * pagesize);
if (::msync(start, pagesize, MS_SYNC) != 0)
throw POSIXException(__METHOD__ ": msync", errno);
if (start != end)
{
if (::msync(end, pagesize, MS_SYNC) != 0)
throw POSIXException(__METHOD__ ": msync", errno);
}
}
void MappedBlockCache::markDirty(unsigned block)
{
_dirty = true;
}

38
Cache/MappedBlockCache.h Normal file
View File

@@ -0,0 +1,38 @@
#ifndef __MAPPED_BLOCK_CACHE_H__
#define __MAPPED_BLOCK_CACHE_H__
#include <Cache/BlockCache.h>
namespace Device {
class MappedBlockCache : public BlockCache {
public:
static BlockCachePointer Create(BlockDevicePointer device, void *data);
virtual ~MappedBlockCache();
virtual void sync();
virtual void write(unsigned block, const void *vp);
virtual void zeroBlock(unsigned block);
virtual void *acquire(unsigned block);
virtual void release(unsigned block, int flags);
virtual void markDirty(unsigned block);
private:
MappedBlockCache(BlockDevicePointer device, void *data);
void sync(unsigned block);
uint8_t *_data;
bool _dirty;
};
} // namespace
#endif

486
Device/Adaptor.cpp Normal file
View File

@@ -0,0 +1,486 @@
#include <cstring>
#include <cstdio>
#include <Device/Adaptor.h>
#include <ProFUSE/Exception.h>
using namespace Device;
Adaptor::~Adaptor()
{
}
POAdaptor::POAdaptor(void *address)
{
_address = (uint8_t *)address;
}
void POAdaptor::readBlock(unsigned block, void *bp)
{
std::memcpy(bp, _address + block * 512, 512);
}
void POAdaptor::writeBlock(unsigned block, const void *bp)
{
std::memcpy(_address + block * 512, bp, 512);
}
unsigned DOAdaptor::Map[] = {
0x00, 0x0e, 0x0d, 0x0c,
0x0b, 0x0a, 0x09, 0x08,
0x07, 0x06, 0x05, 0x04,
0x03, 0x02, 0x01, 0x0f
};
DOAdaptor::DOAdaptor(void *address)
{
_address = (uint8_t *)address;
}
void DOAdaptor::readBlock(unsigned block, void *bp)
{
unsigned track = (block & ~0x07) << 9;
unsigned sector = (block & 0x07) << 1;
for (unsigned i = 0; i < 2; ++i)
{
size_t offset = track | (Map[sector+i] << 8);
std::memcpy(bp, _address + offset, 256);
bp = (uint8_t *)bp + 256;
}
}
void DOAdaptor::writeBlock(unsigned block, const void *bp)
{
unsigned track = (block & ~0x07) << 9;
unsigned sector = (block & 0x07) << 1;
for (unsigned i = 0; i < 2; ++i)
{
size_t offset = track | (Map[sector+i] << 8);
std::memcpy(_address + offset, bp, 256);
bp = (uint8_t *)bp + 256;
}
}
#pragma mark -
#pragma mark NibbleAdaptor
class CircleBuffer {
public:
CircleBuffer(void *address, unsigned length)
{
_address = (uint8_t *)address;
_length = length;
}
uint8_t operator[](unsigned i) const
{
if (i >= _length) i %= _length;
return _address[i];
}
uint8_t& operator[](unsigned i)
{
if (i >= _length) i %= _length;
return _address[i];
}
private:
uint8_t *_address;
unsigned _length;
};
uint8_t NibbleAdaptor::decode44(uint8_t x, uint8_t y)
{
return ((x << 1) | 0x01) & y;
}
std::pair<uint8_t, uint8_t> NibbleAdaptor::encode44(uint8_t val)
{
uint8_t x = (val >> 1) | 0xaa;
uint8_t y = val | 0xaa;
return std::make_pair(x,y);
}
uint8_t NibbleAdaptor::encode62(uint8_t val)
{
#undef __METHOD__
#define __METHOD__ "NibbleAdaptor::encode62"
static uint8_t table[64] = {
0x96, 0x97, 0x9a, 0x9b, 0x9d, 0x9e, 0x9f, 0xa6,
0xa7, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb2, 0xb3,
0xb4, 0xb5, 0xb6, 0xb7, 0xb9, 0xba, 0xbb, 0xbc,
0xbd, 0xbe, 0xbf, 0xcb, 0xcd, 0xce, 0xcf, 0xd3,
0xd6, 0xd7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde,
0xdf, 0xe5, 0xe6, 0xe7, 0xe9, 0xea, 0xeb, 0xec,
0xed, 0xee, 0xef, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
0xf7, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
if (val > 0x3f)
throw ProFUSE::Exception(__METHOD__ ": Invalid 6-2 value.");
return table[val];
}
uint8_t NibbleAdaptor::decode62(uint8_t val)
{
#undef __METHOD__
#define __METHOD__ "decode62"
// auto-generated via perl.
static uint8_t table[] = {
-1, -1, -1, -1, -1, -1, 0, 1, -1, -1, 2, 3, -1, 4, 5, 6,
-1, -1, -1, -1, -1, -1, 7, 8, -1, -1, -1, 9, 10, 11, 12, 13,
-1, -1, 14, 15, 16, 17, 18, 19, -1, 20, 21, 22, 23, 24, 25, 26,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, 28, 29, 30,
-1, -1, -1, 31, -1, -1, 32, 33, -1, 34, 35, 36, 37, 38, 39, 40,
-1, -1, -1, -1, -1, 41, 42, 43, -1, 44, 45, 46, 47, 48, 49, 50,
-1, -1, 51, 52, 53, 54, 55, 56, -1, 57, 58, 59, 60, 61, 62, 63
};
if ((val < 0x90) || (table[val - 0x90] == 0xff))
throw ProFUSE::Exception(__METHOD__ ": Invalid 6-2 encoding.");
return table[val - 0x90];
}
static int FindByte(void *address, uint8_t c, unsigned length, unsigned offset = 0)
{
for (unsigned i = offset; i < length; ++i)
{
if ( ((uint8_t *)address)[i] == c) return i;
}
return -1;
}
/*
* Address Field:
* prologue volume track sector checksum epilogue
* D5 AA 96 XX YY XX YY XX YY XX YY DE AA EB
*/
/*
* Data Field:
* prologue user data checksum epilogue
* D5 AA AD [6+2 encoded] XX DE AA EB
*/
NibbleAdaptor::NibbleAdaptor(void *address, unsigned length)
{
#undef __METHOD__
#define __METHOD__ "NibbleAdaptor::NibbleAdaptor"
_address = (uint8_t *)address;
_length = length;
// build a map of track/sectors.
unsigned state = 0;
_index.resize(35 * 16, -1);
int offset = 0;
unsigned track = 0;
unsigned sector = 0;
unsigned volume = 0;
unsigned checksum = 0;
CircleBuffer buffer(_address, _length);
for (;;)
{
offset = FindByte(address, 0xd5, length, offset);
if (offset < 0) break;
if (buffer[offset + 1] == 0xaa && buffer[offset + 2] == 0x96 && buffer[offset + 11] == 0xde && buffer[offset + 12] == 0xaa)
{
volume = decode44(buffer[offset + 3], buffer[offset + 4]);
track = decode44(buffer[offset + 5], buffer[offset + 6]);
sector = decode44(buffer[offset + 7], buffer[offset + 8]);
checksum = decode44(buffer[offset + 9], buffer[offset + 10]);
if (volume ^ track ^ sector ^ checksum)
throw ProFUSE::Exception(__METHOD__ ": Invalid address checksum.");
if (track > 35 || sector > 16)
throw ProFUSE::Exception(__METHOD__ ": Invalid track/sector.");
offset += 3 + 8 + 3;
state = 1;
continue;
}
if (buffer[offset + 1] == 0xaa && buffer[offset + 2] == 0xad && state == 1)
{
if (_index[track * 16 + sector] != -1)
{
std::fprintf(stderr, "track %u sector %u duplicated.\n", track, sector);
}
_index[track * 16 + sector] = (offset + 3) % _length;
//offset += 3 + 342 + 1 + 3;
offset++;
state = 0;
continue;
}
offset++; //???
// ????
}
// possible wraparound.
if (state == 1)
{
offset = FindByte(address, 0xd5, length, 0);
if (offset >= 0)
{
if (buffer[offset + 1] == 0xaa && buffer[offset + 2] == 0xad)
{
_index[track * 16 + sector] = (offset + 3) % _length;
}
}
}
// now check _index for offset = -1, which means the sector/track wasn't found.
for (std::vector<unsigned>::iterator iter = _index.begin(); iter != _index.end(); ++iter)
{
if (*iter == -1)
{
int offset = distance(_index.begin(), iter);
std::fprintf(stderr, "Error: track %u sector %u missing.\n", offset / 16, offset % 16);
//throw ProFUSE::Exception(__METHOD__ ": Sector missing.");
}
}
}
NibbleAdaptor::~NibbleAdaptor()
{
}
void NibbleAdaptor::readBlock(unsigned block, void *bp)
{
unsigned track = (block & ~0x07) << 9;
unsigned b = (block & 0x07) << 1;
/*
* block sectors
* 0 0, 2
* 1 4, 6
* 2 8, 10
* 3 12,14
* 4 1, 3
* 5 5, 7
* 6 9, 11
* 7 13, 15
*/
unsigned sector = b >> 2;
if (sector >= 16) sector -= 15;
readTrackSector(TrackSector(track, sector), bp);
readTrackSector(TrackSector(track, sector + 1), (uint8_t *)bp + 256);
}
void NibbleAdaptor::writeBlock(unsigned block, const void *bp)
{
unsigned track = (block & ~0x07) << 9;
unsigned b = (block & 0x07) << 1;
/*
* block sectors
* 0 0, 2
* 1 4, 6
* 2 8, 10
* 3 12,14
* 4 1, 3
* 5 5, 7
* 6 9, 11
* 7 13, 15
*/
unsigned sector = b >> 2;
if (sector >= 16) sector -= 15;
writeTrackSector(TrackSector(track, sector), bp);
writeTrackSector(TrackSector(track, sector + 1), (const uint8_t *)bp + 256);
}
void NibbleAdaptor::readTrackSector(TrackSector ts, void *bp)
{
#undef __METHOD__
#define __METHOD__ "NibbleAdaptor::readTrackSector"
if (ts.track > 35 || ts.sector > 16)
throw ProFUSE::Exception(__METHOD__ ": Invalid track/sector.");
CircleBuffer buffer(_address, _length);
uint8_t bits[86 * 3];
uint8_t checksum = 0;
unsigned offset = _index[ts.track * 16 + ts.sector];
if (offset == -1)
{
throw ProFUSE::Exception(__METHOD__ ": Missing track/sector.");
}
// first 86 bytes are in the auxbuffer, backwards.
unsigned index = offset;
for (unsigned i = 0; i < 86; ++i)
{
uint8_t x = buffer[index++];
x = decode62(x);
checksum ^= x;
uint8_t y = checksum;
/*
for (unsigned j = 0; j < 3; ++j)
{
//bits[i + j * 86] = ((y & 0x01) << 1) | ((y & 0x02) >> 1);
bits[i + j * 86] = "\x00\x01\x02\x03"[y & 0x03];
y >>= 2;
}
*/
bits[i + 86 * 0] = "\x00\x02\x01\x03"[y & 0x03];
bits[i + 86 * 1] = "\x00\x02\x01\x03"[(y >> 2) & 0x03];
bits[i + 86 * 2] = "\x00\x02\x01\x03"[(y >> 4) & 0x03];
}
for (unsigned i = 0; i < 256; ++i)
{
uint8_t x = buffer[index++];
x = decode62(x);
checksum ^= x;
uint8_t y = (checksum << 2) | bits[i];
((uint8_t *)bp)[i] = y;
}
if (checksum != decode62(buffer[index++]))
std::fprintf(stderr, "Invalid checksum on track %u, sector %u\n", ts.track, ts.sector);
//throw ProFUSE::Exception(__METHOD__ ": Invalid field checksum.");
}
void NibbleAdaptor::writeTrackSector(TrackSector ts, const void *bp)
{
#undef __METHOD__
#define __METHOD__ "NibbleAdaptor::writeTrackSector"
if (ts.track > 35 || ts.sector > 16)
throw ProFUSE::Exception(__METHOD__ ": Invalid track/sector.");
uint8_t auxBuffer[86];
uint8_t checksum = 0;
// create the aux buffer.
std::memset(auxBuffer, 0, sizeof(auxBuffer));
for (unsigned i = 0, j = 0, shift = 0; i < 256; ++i)
{
uint8_t x = ((const uint8_t *)bp)[i];
// grab the bottom 2 bytes and reverse them.
//uint8_t y = ((x & 0x01) << 1) | ((x & 0x02) >> 1);
uint8_t y = "\x00\x02\x01\x03"[x & 0x03];
auxBuffer[j++] |= (y << shift);
if (j == 86)
{
j = 0;
shift += 2;
}
}
unsigned offset = _index[ts.track * 16 + ts.sector];
CircleBuffer buffer(_address, _length);
// create the checksum while writing to disk..
// aux buffer
for (unsigned i = 0; i < 86; ++i)
{
uint8_t x = auxBuffer[i];
buffer[offset + i] = encode62(x ^ checksum);
checksum = x;
}
for (unsigned i = 0; i < 256; ++i)
{
uint8_t x = ((const uint8_t *)bp)[i];
x >>= 2;
buffer[offset + 86 + i] = encode62(x ^ checksum);
checksum = x;
}
buffer[offset + 342] = encode62(checksum);
}

81
Device/Adaptor.h Normal file
View File

@@ -0,0 +1,81 @@
#ifndef __DEVICE_ADAPTOR_H__
#define __DEVICE_ADAPTOR_H__
#include <utility>
#include <vector>
#include <stdint.h>
#include <Device/TrackSector.h>
namespace Device {
class Adaptor
{
public:
virtual ~Adaptor();
virtual void readBlock(unsigned block, void *bp) = 0;
virtual void writeBlock(unsigned block, const void *bp) = 0;
};
class POAdaptor : public Adaptor
{
public:
POAdaptor(void *address);
virtual void readBlock(unsigned block, void *bp);
virtual void writeBlock(unsigned block, const void *bp);
private:
uint8_t *_address;
};
class DOAdaptor : public Adaptor
{
public:
DOAdaptor(void *address);
virtual void readBlock(unsigned block, void *bp);
virtual void writeBlock(unsigned block, const void *bp);
static unsigned Map[];
private:
uint8_t *_address;
};
// TODO -- nibble adaptor.
class NibbleAdaptor : public Adaptor
{
public:
NibbleAdaptor(void *address, unsigned length);
virtual ~NibbleAdaptor();
virtual void readBlock(unsigned block, void *bp);
virtual void writeBlock(unsigned block, const void *bp);
virtual void readTrackSector(TrackSector ts, void *bp);
virtual void writeTrackSector(TrackSector ts, const void *bp);
static std::pair<uint8_t, uint8_t>encode44(uint8_t);
static uint8_t decode44(uint8_t, uint8_t);
static uint8_t encode62(uint8_t);
static uint8_t decode62(uint8_t);
private:
uint8_t *_address;
unsigned _length;
std::vector<unsigned> _index;
};
}
#endif

271
Device/BlockDevice.cpp Normal file
View File

@@ -0,0 +1,271 @@
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <Device/BlockDevice.h>
#include <Cache/ConcreteBlockCache.h>
#include <ProFUSE/Exception.h>
#include <Device/DiskImage.h>
#include <Device/UniversalDiskImage.h>
#include <Device/DiskCopy42Image.h>
#include <Device/DavexDiskImage.h>
#include <Device/RawDevice.h>
#include <Device/SDKImage.h>
using namespace Device;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
unsigned BlockDevice::ImageType(MappedFile *f, unsigned defv)
{
#undef __METHOD__
#define __METHOD__ "BlockDevice::ImageType"
if (UniversalDiskImage::Validate(f, std::nothrow))
return '2IMG';
if (DiskCopy42Image::Validate(f, std::nothrow))
return 'DC42';
if (SDKImage::Validate(f, std::nothrow))
return 'SDK_';
if (ProDOSOrderDiskImage::Validate(f, std::nothrow))
return 'PO__';
if (DOSOrderDiskImage::Validate(f, std::nothrow))
return 'DO__';
return defv;
}
unsigned BlockDevice::ImageType(const char *type, unsigned defv)
{
const char *tmp;
if (type == 0 || *type == 0) return defv;
// type could be a path, eg images/file, disk.images/file
// unix-specifix.
// basename alters the input string
tmp = std::strrchr(type, '/');
if (tmp) type = tmp + 1;
// type could be a filename, in which case we check the extension.
tmp = std::strrchr(type, '.');
if (tmp) type = tmp + 1;
if (*type == 0) return defv;
if (::strcasecmp(type, "2mg") == 0)
return '2IMG';
if (::strcasecmp(type, "2img") == 0)
return '2IMG';
if (::strcasecmp(type, "dc") == 0)
return 'DC42';
if (::strcasecmp(type, "dc42") == 0)
return 'DC42';
if (::strcasecmp(type, "po") == 0)
return 'PO__';
if (::strcasecmp(type, "dmg") == 0)
return 'PO__';
if (::strcasecmp(type, "dsk") == 0)
return 'DO__';
if (::strcasecmp(type, "do") == 0)
return 'DO__';
if (::strcasecmp(type, "dvx") == 0)
return 'DVX_';
if (::strcasecmp(type, "davex") == 0)
return 'DVX_';
// not supported yet.
if (::strcasecmp(type, "sdk") == 0)
return 'SDK_';
if (::strcasecmp(type, "shk") == 0)
return 'SDK_';
return defv;
}
BlockDevicePointer BlockDevice::Open(const char *name, File::FileFlags flags, unsigned imageType)
{
#undef __METHOD__
#define __METHOD__ "BlockDevice::Open"
struct stat st;
std::memset(&st, 0, sizeof(st));
if (::stat(name, &st) != 0)
{
throw POSIXException(__METHOD__ ": stat error", errno);
}
// /dev/xxx ignore the type.
if (S_ISBLK(st.st_mode))
return RawDevice::Open(name, flags);
MappedFile file(name, flags);
if (!imageType)
{
imageType = ImageType(&file, 'PO__');
}
switch (imageType)
{
case '2IMG':
return UniversalDiskImage::Open(&file);
case 'DC42':
return DiskCopy42Image::Open(&file);
case 'DO__':
return DOSOrderDiskImage::Open(&file);
case 'PO__':
return ProDOSOrderDiskImage::Open(&file);
case 'DVX_':
return DavexDiskImage::Open(&file);
case 'SDK_':
return SDKImage::Open(name);
}
// throw an error?
return BlockDevicePointer();
}
// return the basename, without an extension.
static std::string filename(const std::string& src)
{
unsigned start;
unsigned end;
if (src.empty()) return std::string("");
start = end = 0;
for(unsigned i = 0, l = src.length(); i < l; ++i)
{
char c = src[i];
if (c == '/') start = end = i + 1;
if (c == '.') end = i;
}
if (start == src.length()) return std::string("");
if (start == end) return src.substr(start);
return src.substr(start, end - start);
}
BlockDevicePointer BlockDevice::Create(const char *fname, const char *vname, unsigned blocks, unsigned imageType)
{
std::string xname;
if (!imageType) imageType = ImageType(fname, 'PO__');
if (vname == NULL)
{
xname = filename(std::string(fname));
vname = xname.c_str();
}
switch(imageType)
{
case '2IMG':
return UniversalDiskImage::Create(fname, blocks);
case 'DC42':
return DiskCopy42Image::Create(fname, blocks, vname);
case 'DO__':
return DOSOrderDiskImage::Create(fname, blocks);
case 'PO__':
return ProDOSOrderDiskImage::Create(fname, blocks);
case 'DVX_':
return DavexDiskImage::Create(fname, blocks, vname);
}
return BlockDevicePointer();
}
BlockDevice::BlockDevice()
{
}
BlockDevice::~BlockDevice()
{
}
void BlockDevice::zeroBlock(unsigned block)
{
uint8_t bp[512];
std::memset(bp, 0, 512);
write(block, bp);
}
bool BlockDevice::mapped()
{
return false;
}
void BlockDevice::sync(unsigned block)
{
sync();
}
/*
void BlockDevice::sync(TrackSector ts)
{
sync();
}
*/
BlockCachePointer BlockDevice::createBlockCache()
{
unsigned b = blocks();
unsigned size = std::max(16u, b / 16);
return ConcreteBlockCache::Create(shared_from_this(), size);
}

69
Device/BlockDevice.h Normal file
View File

@@ -0,0 +1,69 @@
#ifndef __BLOCKDEVICE_H__
#define __BLOCKDEVICE_H__
#include <stdint.h>
#include <sys/types.h>
#include <Device/Device.h>
#include <Device/TrackSector.h>
#include <ProFUSE/Exception.h>
#include <ProFUSE/smart_pointers.h>
#include <File/File.h>
class MappedFile;
namespace Device {
class BlockDevice : public ENABLE_SHARED_FROM_THIS(BlockDevice) {
public:
// static methods.
static unsigned ImageType(const char *type, unsigned defv = 0);
static unsigned ImageType(MappedFile *, unsigned defv = 0);
static BlockDevicePointer Open(const char *name, File::FileFlags flags, unsigned imageType = 0);
static BlockDevicePointer Create(const char *fname, const char *vname, unsigned blocks, unsigned imageType = 0);
virtual ~BlockDevice();
virtual BlockCachePointer createBlockCache();
virtual void read(unsigned block, void *bp) = 0;
//virtual void read(TrackSector ts, void *bp) = 0
virtual void write(unsigned block, const void *bp) = 0;
//virtual void write(TrackSector ts, const void *bp) = 0;
virtual unsigned blocks() = 0;
virtual bool mapped();
virtual bool readOnly() = 0;
virtual void sync() = 0;
virtual void sync(unsigned block);
//virtual void sync(TrackSector ts);
void zeroBlock(unsigned block);
protected:
BlockDevice();
};
}
#endif

176
Device/DavexDiskImage.cpp Normal file
View File

@@ -0,0 +1,176 @@
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <cstdio>
#include <algorithm>
#include <Device/DavexDiskImage.h>
#include <File/MappedFile.h>
#include <Device/Adaptor.h>
#include <Endian/Endian.h>
#include <Endian/IOBuffer.h>
#include <Cache/MappedBlockCache.h>
using namespace Device;
using namespace LittleEndian;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
/*
http://www.umich.edu/~archive/apple2/technotes/ftn/FTN.E0.8004
*/
static const char *IdentityCheck = "\x60VSTORE [Davex]\x00";
// private, validation already performed.
DavexDiskImage::DavexDiskImage(MappedFile *file) :
DiskImage(file)
{
// at this point, file is no longer valid.
// 512-bytes header
setBlocks((length() / 512) - 1);
setAdaptor(new POAdaptor(512 + (uint8_t *)address()));
}
DavexDiskImage::~DavexDiskImage()
{
// scan and update usedBlocks?
}
bool DavexDiskImage::Validate(MappedFile *f, const std::nothrow_t &)
{
#undef __METHOD__
#define __METHOD__ "DavexDiskImage::Validate"
size_t size = f->length();
const void * data = f->address();
unsigned blocks = (size / 512) - 1;
if (size < 512) return false;
if (size % 512) return false;
// identity.
if (std::memcmp(data, IdentityCheck, 16))
return false;
// file format.
if (Read8(data, 0x10) != 0)
return false;
// total blocks
if (Read32(data, 33) != blocks)
return false;
// file number -- must be 1
if (Read8(data, 64) != 1)
return false;
return true;
}
bool DavexDiskImage::Validate(MappedFile *f)
{
#undef __METHOD__
#define __METHOD__ "DavexDiskImage::Validate"
if (!Validate(f, std::nothrow))
throw Exception(__METHOD__ ": Invalid file format.");
return true;
}
BlockDevicePointer DavexDiskImage::Open(MappedFile *file)
{
#undef __METHOD__
#define __METHOD__ "DavexDiskImage::Open"
Validate(file);
//return BlockDevicePointer(new DavexDiskImage(file));
return MAKE_SHARED(DavexDiskImage, file);
}
BlockDevicePointer DavexDiskImage::Create(const char *name, size_t blocks)
{
return Create(name, blocks, "Untitled");
}
BlockDevicePointer DavexDiskImage::Create(const char *name, size_t blocks, const char *vname)
{
#undef __METHOD__
#define __METHOD__ "DavexDiskImage::Create"
uint8_t *data;
uint8_t tmp[512];
IOBuffer header(tmp,512);
MappedFile *file = MappedFile::Create(name, blocks * 512 + 512);
data = (uint8_t *)file->address();
header.writeBytes(IdentityCheck, 16);
// file Format
header.write8(0);
//version
header.write8(0);
// version
header.write8(0x10);
// reserved.
header.setOffset(32, true);
//deviceNum
header.write8(1);
// total blocks
header.write32(blocks);
// unused blocks
header.write32(0);
// volume Name
if (!vname || !*vname) vname = "Untitled";
unsigned l = std::strlen(vname);
header.write8(std::min(l, 15u));
header.writeBytes(vname, std::min(l, 15u));
// name + reserved.
header.setOffset(64, true);
// file number
header.write8(1);
//starting block
header.write32(0);
// reserved
header.setOffset(512, true);
std::memcpy(file->address(), header.buffer(), 512);
file->sync();
//return BlockDevicePointer(new DavexDiskImage(file));
return MAKE_SHARED(DavexDiskImage, file);
}
BlockCachePointer DavexDiskImage::createBlockCache()
{
// need a smart pointer, but only have this....
return MappedBlockCache::Create(shared_from_this(), 512 + (uint8_t *)address());
}

43
Device/DavexDiskImage.h Normal file
View File

@@ -0,0 +1,43 @@
#ifndef __DAVEXDISKIMAGE_H__
#define __DAVEXDISKIMAGE_H__
#include <string>
#include <new>
#include <Device/BlockDevice.h>
#include <Device/DiskImage.h>
namespace Device {
// only supports 1 file; may be split over multiple files.
class DavexDiskImage : public DiskImage {
public:
virtual ~DavexDiskImage();
static BlockDevicePointer Create(const char *name, size_t blocks);
static BlockDevicePointer Create(const char *name, size_t blocks, const char *vname);
static BlockDevicePointer Open(MappedFile *);
virtual BlockCachePointer createBlockCache();
static bool Validate(MappedFile *, const std::nothrow_t &);
static bool Validate(MappedFile *);
private:
DavexDiskImage();
DavexDiskImage(MappedFile *);
bool _changed;
std::string _volumeName;
};
}
#endif

24
Device/Device.h Normal file
View File

@@ -0,0 +1,24 @@
//
// Device.h
// profuse
//
// Created by Kelvin Sherlock on 2/19/2011.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#ifndef __DEVICE_DEVICE_H__
#define __DEVICE_DEVICE_H__
#include <ProFUSE/smart_pointers.h>
namespace Device {
class BlockDevice;
class BlockCache;
typedef SHARED_PTR(BlockDevice) BlockDevicePointer;
typedef SHARED_PTR(BlockCache) BlockCachePointer;
}
#endif

243
Device/DiskCopy42Image.cpp Normal file
View File

@@ -0,0 +1,243 @@
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <Device/DiskCopy42Image.h>
#include <Endian/Endian.h>
#include <Endian/IOBuffer.h>
#include <Cache/MappedBlockCache.h>
using namespace Device;
using namespace BigEndian;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
enum {
oDataSize = 64,
oDataChecksum = 72,
oPrivate = 82,
oUserData = 84
};
DiskCopy42Image::DiskCopy42Image(MappedFile *f) :
DiskImage(f),
_changed(false)
{
setAdaptor(new POAdaptor(oUserData + (uint8_t *)address()));
setBlocks(Read32(address(), oDataSize) / 512);
}
DiskCopy42Image::~DiskCopy42Image()
{
if (_changed)
{
MappedFile *f = file();
if (f)
{
void *data = f->address();
uint32_t cs = Checksum(oUserData + (uint8_t *)data, Read32(data, oDataSize));
Write32(data, oDataChecksum, cs);
f->sync();
}
// TODO -- checksum
}
}
uint32_t DiskCopy42Image::Checksum(void *data, size_t size)
{
uint32_t rv = 0;
uint8_t *dp = (uint8_t *)data;
if (size & 0x01) return rv;
for (size_t i = 0; i < size; i += 2)
{
rv += dp[i] << 8;
rv += dp[i+1];
rv = (rv >> 1) + (rv << 31);
}
return rv;
}
BlockDevicePointer DiskCopy42Image::Open(MappedFile *f)
{
Validate(f);
//return BlockDevicePointer(new DiskCopy42Image(f));
return MAKE_SHARED(DiskCopy42Image, f);
}
static uint8_t DiskFormat(size_t blocks)
{
switch (blocks)
{
case 800: return 0;
case 1600: return 1;
case 1440: return 2;
case 2880: return 3;
default: return 0xff;
}
}
static uint8_t FormatByte(size_t blocks)
{
switch(blocks)
{
case 800: return 0x12;
default: return 0x22;
}
}
BlockDevicePointer DiskCopy42Image::Create(const char *name, size_t blocks)
{
return Create(name, blocks, "Untitled");
}
BlockDevicePointer DiskCopy42Image::Create(const char *name, size_t blocks, const char *vname)
{
MappedFile *file = MappedFile::Create(name, blocks * 512 + oUserData);
uint8_t tmp[oUserData];
IOBuffer header(tmp, oUserData);
// name -- 64byte pstring.
if (vname == NULL) vname = "Untitled";
unsigned l = std::strlen(vname);
header.write8(std::min(l, 63u));
header.writeBytes(vname, std::min(l, 63u));
//header.resize(64);
header.setOffset(oDataSize, true);
// data size -- number of bytes
header.write32(blocks * 512);
// tag size
header.write32(0);
// data checksum
// if data is 0, will be 0.
//header.push32be(Checksum(file->fileData(), blocks * 512));
header.write32(0);
// tag checksum
header.write32(0);
// disk format.
/*
* 0 = 400k
* 1 = 800k
* 2 = 720k
* 3 = 1440k
* 0xff = other
*/
header.write8(DiskFormat(blocks));
// formatbyte
/*
* 0x12 = 400k
* 0x22 = >400k mac
* 0x24 = 800k appleII
*/
header.write8(FormatByte(blocks));
// private
header.write16(0x100);
std::memcpy(file->address(), header.buffer(), oUserData);
file->sync();
//return BlockDevicePointer(new DiskCopy42Image(file));
return MAKE_SHARED(DiskCopy42Image, file);
}
bool DiskCopy42Image::Validate(MappedFile *file, const std::nothrow_t &)
{
#undef __METHOD__
#define __METHOD__ "DiskCopy42Image::Validate"
size_t bytes = 0;
size_t size = file->length();
const void *data = file->address();
uint32_t checksum = 0;
if (size < oUserData)
return false;
// name must be < 64
if (Read8(data, 0) > 63)
return false;
if (Read16(data, oPrivate) != 0x100)
return false;
// bytes, not blocks.
bytes = Read32(data, oDataSize);
if (bytes % 512)
return false;
if (size < oUserData + bytes)
return false;
// todo -- checksum.
checksum = Read32(data, oDataChecksum);
uint32_t cs = Checksum(oUserData + (uint8_t *)data, bytes);
if (cs != checksum)
{
fprintf(stderr, __METHOD__ ": Warning: checksum invalid.\n");
}
return true;
}
bool DiskCopy42Image::Validate(MappedFile *file)
{
#undef __METHOD__
#define __METHOD__ "DiskCopy42Image::Validate"
if (!Validate(file, std::nothrow))
throw Exception(__METHOD__ ": Invalid file format.");
return true;
}
void DiskCopy42Image::write(unsigned block, const void *bp)
{
DiskImage::write(block, bp);
_changed = true;
}
BlockCachePointer DiskCopy42Image::createBlockCache()
{
// if not readonly, mark changed so crc will be updated at close.
if (!readOnly()) _changed = true;
return MappedBlockCache::Create(shared_from_this(), address());
}

42
Device/DiskCopy42Image.h Normal file
View File

@@ -0,0 +1,42 @@
#ifndef __DISKCOPY42IMAGE_H__
#define __DISKCOPY42IMAGE_H__
#include <Device/BlockDevice.h>
#include <Device/DiskImage.h>
#include <stdint.h>
namespace Device {
class DiskCopy42Image : public DiskImage {
public:
virtual ~DiskCopy42Image();
static BlockDevicePointer Create(const char *name, size_t blocks);
static BlockDevicePointer Create(const char *name, size_t blocks, const char *vname);
static BlockDevicePointer Open(MappedFile *);
static uint32_t Checksum(void *data, size_t size);
static bool Validate(MappedFile *, const std::nothrow_t &);
static bool Validate(MappedFile *);
virtual void write(unsigned block, const void *bp);
virtual BlockCachePointer createBlockCache();
private:
DiskCopy42Image();
DiskCopy42Image(MappedFile *);
bool _changed;
};
}
#endif

228
Device/DiskImage.cpp Normal file
View File

@@ -0,0 +1,228 @@
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <Device/DiskImage.h>
#include <File/MappedFile.h>
#include <Cache/MappedBlockCache.h>
#include <ProFUSE/Exception.h>
using namespace Device;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
/*
DiskImage::DiskImage(const char *name, bool readOnly)
{
File fd(name, readOnly ? O_RDONLY : O_RDWR);
MappedFile mf(fd, readOnly);
_file.adopt(mf);
_blocks = 0;
_readOnly = readOnly;
_adaptor = NULL;
}
*/
DiskImage::DiskImage(MappedFile *file)
{
_file.adopt(*file);
_blocks = 0;
_readOnly = _file.readOnly();
_adaptor = NULL;
}
DiskImage::~DiskImage()
{
delete _adaptor;
}
bool DiskImage::readOnly()
{
return _readOnly;
}
unsigned DiskImage::blocks()
{
return _blocks;
}
void DiskImage::setAdaptor(Adaptor *adaptor)
{
delete _adaptor;
_adaptor = adaptor;
}
void DiskImage::read(unsigned block, void *bp)
{
#undef __METHOD__
#define __METHOD__ "DiskImage::read"
if (block >= _blocks)
throw Exception(__METHOD__ ": Invalid block.");
_adaptor->readBlock(block, bp);
}
void DiskImage::write(unsigned block, const void *bp)
{
#undef __METHOD__
#define __METHOD__ "DiskImage::write"
if (block >= _blocks)
throw Exception(__METHOD__ ": Invalid block.");
_adaptor->writeBlock(block, bp);
}
void DiskImage::sync()
{
#undef __METHOD__
#define __METHOD__ "DiskImage::sync"
if (_file.isValid()) return _file.sync();
throw Exception(__METHOD__ ": File not set.");
}
ProDOSOrderDiskImage::ProDOSOrderDiskImage(MappedFile *file) :
DiskImage(file)
{
// at this point, file is no longer valid.
setBlocks(length() / 512);
setAdaptor(new POAdaptor(address()));
}
BlockDevicePointer ProDOSOrderDiskImage::Create(const char *name, size_t blocks)
{
MappedFile *file = MappedFile::Create(name, blocks * 512);
//return BlockDevicePointer(new ProDOSOrderDiskImage(file));
return MAKE_SHARED(ProDOSOrderDiskImage, file);
}
BlockDevicePointer ProDOSOrderDiskImage::Open(MappedFile *file)
{
Validate(file);
//return BlockDevicePointer(new ProDOSOrderDiskImage(file));
return MAKE_SHARED(ProDOSOrderDiskImage, file);
}
bool ProDOSOrderDiskImage::Validate(MappedFile *f, const std::nothrow_t &)
{
#undef __METHOD__
#define __METHOD__ "ProDOSOrderDiskImage::Validate"
size_t size = f->length();
if (size % 512)
return false;
return true;
}
bool ProDOSOrderDiskImage::Validate(MappedFile *f)
{
#undef __METHOD__
#define __METHOD__ "ProDOSOrderDiskImage::Validate"
if (!f || !f->isValid()) throw Exception(__METHOD__ ": File not set.");
if (!Validate(f, std::nothrow))
throw Exception(__METHOD__ ": Invalid file format.");
return true;
}
BlockCachePointer ProDOSOrderDiskImage::createBlockCache()
{
return MappedBlockCache::Create(shared_from_this(), address());
}
#pragma mark -
#pragma mark DOS Order Disk Image
/*
DOSOrderDiskImage::DOSOrderDiskImage(const char *name, bool readOnly) :
DiskImage(name, readOnly)
{
Validate(file());
}
*/
DOSOrderDiskImage::DOSOrderDiskImage(MappedFile *file) :
DiskImage(file)
{
// at this point, file is no longer valid.
setBlocks(length() / 512);
setAdaptor(new DOAdaptor(address()));
}
BlockDevicePointer DOSOrderDiskImage::Create(const char *name, size_t blocks)
{
MappedFile *file = MappedFile::Create(name, blocks * 512);
//return BlockDevicePointer(new DOSOrderDiskImage(file));
return MAKE_SHARED(DOSOrderDiskImage, file);
}
BlockDevicePointer DOSOrderDiskImage::Open(MappedFile *file)
{
Validate(file);
//return BlockDevicePointer(new DOSOrderDiskImage(file));
return MAKE_SHARED(DOSOrderDiskImage, file);
}
bool DOSOrderDiskImage::Validate(MappedFile *f, const std::nothrow_t &)
{
#undef __METHOD__
#define __METHOD__ "DOSOrderDiskImage::Validate"
size_t size = f->length();
if (size % 512)
return false;
return true;
}
bool DOSOrderDiskImage::Validate(MappedFile *f)
{
#undef __METHOD__
#define __METHOD__ "DOSOrderDiskImage::Validate"
if (!f || !f->isValid()) throw Exception(__METHOD__ ": File not set.");
if (!Validate(f, std::nothrow))
throw Exception(__METHOD__ ": Invalid file format.");
return true;
}

97
Device/DiskImage.h Normal file
View File

@@ -0,0 +1,97 @@
#ifndef __DISKIMAGE_H__
#define __DISKIMAGE_H__
#include <stdint.h>
#include <sys/types.h>
#include <ProFUSE/Exception.h>
#include <Device/BlockDevice.h>
#include <Device/Adaptor.h>
#include <File/MappedFile.h>
namespace Device {
class DiskImage : public BlockDevice {
public:
virtual ~DiskImage();
virtual void read(unsigned block, void *bp);
virtual void write(unsigned block, const void *bp);
virtual void sync();
virtual bool readOnly();
virtual unsigned blocks();
protected:
DiskImage();
DiskImage(MappedFile *file = 0);
void setBlocks(unsigned blocks) { _blocks = blocks; }
void setAdaptor(Adaptor *);
void *address() const { return _file.address(); }
size_t length() const { return _file.length(); }
MappedFile *file() { return &_file; }
private:
MappedFile _file;
Adaptor *_adaptor;
bool _readOnly;
unsigned _blocks;
};
class ProDOSOrderDiskImage : public DiskImage {
public:
static BlockDevicePointer Create(const char *name, size_t blocks);
static BlockDevicePointer Open(MappedFile *);
virtual BlockCachePointer createBlockCache();
static bool Validate(MappedFile *, const std::nothrow_t &);
static bool Validate(MappedFile *);
private:
ProDOSOrderDiskImage();
ProDOSOrderDiskImage(MappedFile *);
};
class DOSOrderDiskImage : public DiskImage {
public:
static BlockDevicePointer Create(const char *name, size_t blocks);
static BlockDevicePointer Open(MappedFile *);
static bool Validate(MappedFile *, const std::nothrow_t &);
static bool Validate(MappedFile *);
private:
DOSOrderDiskImage();
DOSOrderDiskImage(MappedFile *);
};
}
#endif

321
Device/RawDevice.cpp Normal file
View File

@@ -0,0 +1,321 @@
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <cerrno>
#ifdef __APPLE__
#include <sys/disk.h>
#endif
#ifdef __linux__
#include <sys/mount.h>
#endif
#ifdef __SUN__
#include <sys/dkio.h>
#endif
#ifdef __FREEBSD__
#include <sys/disk.h>
#endif
#ifdef __minix
#include <minix/partition.h>
#endif
#include <Device/RawDevice.h>
#include <ProFUSE/Exception.h>
using namespace Device;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
#ifdef __SUN__
void RawDevice::devSize(int fd)
{
#undef __METHOD__
#define __METHOD__ "RawDevice::devSize"
struct dk_minfo minfo;
if (::ioctl(fd, DKIOCGMEDIAINFO, &minfo) < 0)
throw POSIXException(__METHOD__ ": Unable to determine device size.", errno);
_size = minfo.dki_lbsize * minfo.dki_capacity;
_blockSize = 512; // not really, but whatever.
_blocks = _size / 512;
}
#endif
#ifdef __APPLE__
void RawDevice::devSize(int fd)
{
#undef __METHOD__
#define __METHOD__ "RawDevice::devSize"
uint32_t blockSize; // 32 bit
uint64_t blockCount; // 64 bit
if (::ioctl(fd, DKIOCGETBLOCKSIZE, &blockSize) < 0)
throw POSIXException(__METHOD__ ": Unable to determine block size.", errno);
if (::ioctl(fd, DKIOCGETBLOCKCOUNT, &blockCount) < 0)
throw POSIXException(__METHOD__ ": Unable to determine block count.", errno);
_blockSize = blockSize;
_size = _blockSize * blockCount;
_blocks = _size / 512;
}
#endif
#ifdef __linux__
void RawDevice::devSize(int fd)
{
#undef __METHOD__
#define __METHOD__ "RawDevice::devSize"
int blocks;
if (::ioctl(fd, BLKGETSIZE, &blocks) < 0)
throw POSIXException(__METHOD__ ": Unable to determine device size.", errno);
_size = 512 * blocks;
_blockSize = 512; //
_blocks = blocks;
}
#endif
// TODO -- FreeBSD/NetBSD/OpenBSD
#ifdef __FREEBSD__
void RawDevice::devSize(int fd)
{
#undef __METHOD__
#define __METHOD__ "RawDevice::devSize"
unsigned blockSize;
off_t mediaSize;
if (::ioctl(fd, DIOCGSECTORSIZE, &blockSize)
throw POSIXException(__METHOD__ ": Unable to determine block size.", errno);
if (::ioctl(fd, DIOCGMEDIASIZE, &mediaSize)
throw POSIXException(__METHOD__ ": Unable to determine media size.", errno);
_blockSize = blockSize;
_size = mediaSize;
_blocks = mediaSize / 512;
}
#endif
#ifdef __minix
void RawDevice::devSize(int fd)
{
#undef __METHOD__
#define __METHOD__ "RawDevice::devSize"
struct partition entry;
if (::ioctl(fd, DIOCGETP, &entry) < 0)
throw POSIXException(__METHOD__ ": Unable to determine device size.", errno);
_size = entry.size
_blockSize = 512; // not really but whatever.
_blocks = _size / 512;
}
#endif
RawDevice::RawDevice(const char *name, File::FileFlags flags) :
_file(name, flags)
{
#undef __METHOD__
#define __METHOD__ "RawDevice::RawDevice"
if (!_file.isValid())
{
throw Exception(__METHOD__ ": Invalid file handle.");
}
_readOnly = flags == File::ReadOnly;
_size = 0;
_blocks = 0;
_blockSize = 0;
devSize(_file.fd());
}
RawDevice::RawDevice(File& file, File::FileFlags flags) :
_file(file)
{
#undef __METHOD__
#define __METHOD__ "RawDevice::RawDevice"
if (!_file.isValid())
{
throw Exception(__METHOD__ ": Invalid file handle.");
}
_readOnly = flags == File::ReadOnly;
_size = 0;
_blocks = 0;
_blockSize = 0;
devSize(_file.fd());
}
RawDevice::~RawDevice()
{
}
BlockDevicePointer RawDevice::Open(const char *name, File::FileFlags flags)
{
//return BlockDevicePointer(new RawDevice(name, flags));
return MAKE_SHARED(RawDevice, name, flags);
}
void RawDevice::read(unsigned block, void *bp)
{
#undef __METHOD__
#define __METHOD__ "RawDevice::read"
if (block >= _blocks) throw Exception(__METHOD__ ": Invalid block number.");
if (bp == 0) throw Exception(__METHOD__ ": Invalid address.");
// sun -- use pread
// apple - read full native block(s) ?
off_t offset = block * 512;
ssize_t ok = ::pread(_file.fd(), bp, 512, offset);
// TODO -- EINTR?
if (ok != 512)
throw ok < 0
? POSIXException(__METHOD__ ": Error reading block.", errno)
: Exception(__METHOD__ ": Error reading block.");
}
void RawDevice::read(TrackSector ts, void *bp)
{
#undef __METHOD__
#define __METHOD__ "RawDevice::read"
unsigned block = ts.track * 8 + ts.sector / 2;
if (block >= _blocks) throw Exception(__METHOD__ ": Invalid block number.");
if (bp == 0) throw Exception(__METHOD__ ": Invalid address.");
// sun -- use pread
// apple - read full native block(s) ?
off_t offset = (ts.track * 16 + ts.sector) * 256;
ssize_t ok = ::pread(_file.fd(), bp, 256, offset);
// TODO -- EINTR?
if (ok != 256)
throw ok < 0
? POSIXException(__METHOD__ ": Error reading block.", errno)
: Exception(__METHOD__ ": Error reading block.");
}
void RawDevice::write(unsigned block, const void *bp)
{
#undef __METHOD__
#define __METHOD__ "RawDevice::write"
if (block > _blocks) throw Exception(__METHOD__ ": Invalid block number.");
if (_readOnly)
throw Exception(__METHOD__ ": File is readonly.");
off_t offset = block * 512;
ssize_t ok = ::pwrite(_file.fd(), bp, 512, offset);
if (ok != 512)
throw ok < 0
? POSIXException(__METHOD__ ": Error writing block.", errno)
: Exception(__METHOD__ ": Error writing block.");
}
void RawDevice::write(TrackSector ts, const void *bp)
{
#undef __METHOD__
#define __METHOD__ "RawDevice::write"
unsigned block = ts.track * 8 + ts.sector / 2;
if (block > _blocks) throw Exception(__METHOD__ ": Invalid block number.");
if (_readOnly)
throw Exception(__METHOD__ ": File is readonly.");
off_t offset = (ts.track * 16 + ts.sector) * 256;
ssize_t ok = ::pwrite(_file.fd(), bp, 256, offset);
if (ok != 256)
throw ok < 0
? POSIXException(__METHOD__ ": Error writing block.", errno)
: Exception(__METHOD__ ": Error writing block.");
}
bool RawDevice::readOnly()
{
return _readOnly;
}
bool RawDevice::mapped()
{
return false;
}
unsigned RawDevice::blocks()
{
return _blocks;
}
void RawDevice::sync()
{
#undef __METHOD__
#define __METHOD__ "RawDevice::sync"
if (_readOnly) return;
if (::fsync(_file.fd()) < 0)
throw POSIXException(__METHOD__ ": fsync error.", errno);
}

57
Device/RawDevice.h Normal file
View File

@@ -0,0 +1,57 @@
#ifndef __RAWDEVICE_H__
#define __RAWDEVICE_H__
#include <stdint.h>
#include <Device/BlockDevice.h>
#include <File/File.h>
namespace Device {
// /dev/xxx
class RawDevice : public BlockDevice {
public:
static BlockDevicePointer Open(const char *name, File::FileFlags flags);
virtual ~RawDevice();
virtual void read(unsigned block, void *bp);
virtual void read(TrackSector ts, void *bp);
virtual void write(unsigned block, const void *bp);
virtual void write(TrackSector ts, const void *bp);
virtual bool readOnly();
virtual bool mapped();
virtual void sync();
virtual unsigned blocks();
private:
RawDevice(const char *name, File::FileFlags flags);
RawDevice(File& file, File::FileFlags flags);
void devSize(int fd);
File _file;
bool _readOnly;
uint64_t _size; // size of device in bytes.
unsigned _blocks; // # of 512k blocks i.e. _size / 512
unsigned _blockSize; // native block size.
};
}
#endif

249
Device/SDKImage.cpp Normal file
View File

@@ -0,0 +1,249 @@
//
// SDKImage.cpp
// profuse
//
// Created by Kelvin Sherlock on 3/6/2011.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#include "SDKImage.h"
#include <unistd.h>
#include <cstdlib>
#include <cstdio>
#include <cerrno>
#include <NufxLib.h>
#include <File/File.h>
#include <File/MappedFile.h>
#include <ProFUSE/Exception.h>
using ProFUSE::Exception;
using ProFUSE::POSIXException;
class NuFXException : public Exception
{
public:
NuFXException(const char *cp, NuError error);
NuFXException(const std::string& string, NuError error);
virtual const char *errorString();
};
inline NuFXException::NuFXException(const char *cp, NuError error) :
Exception(cp, error)
{
}
inline NuFXException::NuFXException(const std::string& string, NuError error) :
Exception(string, error)
{
}
const char *NuFXException::errorString()
{
return ::NuStrError((NuError)error());
}
using namespace Device;
struct record_thread
{
NuRecordIdx record_index;
NuThreadIdx thread_index;
};
static record_thread FindDiskImageThread(NuArchive *archive)
{
#undef __METHOD__
#define __METHOD__ "SDKImage::FindThread"
record_thread rt;
NuError e;
NuAttr recordCount;
e = NuGetAttr(archive, kNuAttrNumRecords, &recordCount);
if (e)
{
throw NuFXException(__METHOD__ ": NuGetAttr", e);
}
for (unsigned position = 0; position < recordCount; ++position)
{
NuRecordIdx rIndex;
const NuRecord *record;
e = NuGetRecordIdxByPosition(archive, position, &rIndex);
if (e)
{
throw NuFXException(__METHOD__ ": NuGetRecordIdxByPosition", e);
}
e = NuGetRecord(archive, rIndex, &record);
if (e)
{
throw NuFXException(__METHOD__ ": NuGetRecord", e);
}
for (unsigned i = 0; i < NuRecordGetNumThreads(record); ++i)
{
const NuThread *thread = NuGetThread(record, i);
if (NuGetThreadID(thread) == kNuThreadIDDiskImage)
{
rt.thread_index = thread->threadIdx;
rt.record_index = record->recordIdx;
return rt;
}
}
}
throw Exception(__METHOD__ ": not a disk image");
}
/*
* helper function to extract SDK image to /tmp and return a
* ProDOSDiskImage of the /tmp file.
*
*/
BlockDevicePointer SDKImage::Open(const char *name)
{
#undef __METHOD__
#define __METHOD__ "SDKImage::Open"
char tmp[] = "/tmp/pfuse.XXXXXXXX";
int fd = -1;
FILE *fp = NULL;
NuArchive *archive = NULL;
//const NuThread *thread = NULL;
//const NuRecord *record = NULL;
NuDataSink *sink = NULL;
//NuRecordIdx rIndex;
//NuThreadIdx tIndex;
NuError e;
record_thread rt = {0, 0};
try {
e = NuOpenRO(name, &archive);
if (e)
{
throw NuFXException(__METHOD__ ": NuOpenRO", e);
}
rt = FindDiskImageThread(archive);
fd = mkstemp(tmp);
if (fd < 0)
{
throw POSIXException(__METHOD__ ": mkstemp", errno);
}
fp = fdopen(fd, "w");
if (!fp)
{
::close(fd);
throw POSIXException(__METHOD__ ": fdopen", errno);
}
e = NuCreateDataSinkForFP(true, kNuConvertOff, fp, &sink);
if (e)
{
throw NuFXException(__METHOD__ ": NuCreateDataSinkForFP", e);
}
e = NuExtractThread(archive, rt.thread_index, sink);
if (e)
{
throw NuFXException(__METHOD__ ": NuExtractThread", e);
}
fprintf(stderr, "Extracted disk image to %s\n", tmp);
fclose(fp);
NuClose(archive);
NuFreeDataSink(sink);
fp = NULL;
archive = NULL;
sink = NULL;
}
catch(...)
{
if (fp) fclose(fp);
if (archive) NuClose(archive);
if (sink) NuFreeDataSink(sink);
throw;
}
// todo -- maybe SDKImage should extend ProDOSOrderDiskImage, have destructor
// that unklinks the temp file.
MappedFile file(tmp, File::ReadOnly);
return ProDOSOrderDiskImage::Open(&file);
}
bool SDKImage::Validate(MappedFile * f, const std::nothrow_t &)
{
// NuFile, alternating ASCII.
static const char IdentityCheck[6] = { 0x4E, 0xF5, 0x46, 0xE9, 0x6C, 0xE5 };
static const char BXYIdentityCheck[3] = { 0x0A, 0x47, 0x4C };
uint8_t *address = (uint8_t *)f->address();
size_t length = f->length();
// check for a BXY header
if (length >= 128
&& std::memcmp(address, BXYIdentityCheck, sizeof(BXYIdentityCheck)) == 0)
{
length -= 128;
address += 128;
}
if (length > sizeof(IdentityCheck)
&& std::memcmp(address, IdentityCheck, sizeof(IdentityCheck)) == 0)
return true;
return false;
}
bool SDKImage::Validate(MappedFile * f)
{
#undef __METHOD__
#define __METHOD__ "SDKImage::Validate"
if (!Validate(f, std::nothrow))
throw Exception(__METHOD__ ": Invalid file format.");
return true;
}

30
Device/SDKImage.h Normal file
View File

@@ -0,0 +1,30 @@
//
// SDKImage.h
// profuse
//
// Created by Kelvin Sherlock on 3/6/2011.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#include <Device/BlockDevice.h>
#include <Device/DiskImage.h>
namespace Device {
class SDKImage : public DiskImage
{
public:
static BlockDevicePointer Open(const char *name);
static bool Validate(MappedFile *, const std::nothrow_t &);
static bool Validate(MappedFile *);
private:
SDKImage();
SDKImage(const SDKImage &);
~SDKImage();
SDKImage & operator=(const SDKImage &);
};
}

19
Device/TrackSector.h Normal file
View File

@@ -0,0 +1,19 @@
#ifndef __TRACKSECTOR_H__
#define __TRACKSECTOR_H__
namespace Device {
struct TrackSector {
TrackSector(unsigned, unsigned);
unsigned track;
unsigned sector;
};
inline TrackSector::TrackSector(unsigned t, unsigned s)
{
track = t;
sector = s;
}
}
#endif

View File

@@ -0,0 +1,163 @@
#include <Device/UniversalDiskImage.h>
#include <Endian/Endian.h>
#include <Endian/IOBuffer.h>
#include <ProFUSE/Exception.h>
#include <Cache/MappedBlockCache.h>
#include <Cache/ConcreteBlockCache.h>
using namespace Device;
using namespace LittleEndian;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
UniversalDiskImage::UniversalDiskImage(MappedFile *file) :
DiskImage(file)
{
// at this point, file is no longer valid.
uint8_t * data = (uint8_t *)address();
_format = Read32(data, 0x0c);
_flags = Read32(data, 0x10);
_blocks = Read32(data, 0x14);
_dataOffset = Read32(data, 0x18);
_dataLength = Read32(data, 0x1c);
setBlocks(_blocks);
// TODO -- DO, Nibble support.
setAdaptor(new POAdaptor(_dataOffset + data));
}
BlockDevicePointer UniversalDiskImage::Create(const char *name, size_t blocks)
{
// 64-byte header.
MappedFile *file = MappedFile::Create(name, blocks * 512 + 64);
uint8_t tmp[64];
IOBuffer header(tmp, 64);
// magic + creator
header.writeBytes("2IMGPRFS", 8);
// header size.
header.write16(64);
// version
header.write16(1);
//image format -- ProDOS order
header.write32(1);
// flags
header.write32(0);
// # blocks. s/b 0 unless prodos-order
header.write32(blocks);
// offset to disk data
header.write32(64);
// data length
header.write32(512 * blocks);
// comment offset, creator, reserved -- 0.
header.setOffset(64, true);
std::memcpy(file->address(), header.buffer(), 64);
//return BlockDevicePointer(new UniversalDiskImage(file));
return MAKE_SHARED(UniversalDiskImage, file);
}
BlockDevicePointer UniversalDiskImage::Open(MappedFile *file)
{
Validate(file);
//return BlockDevicePointer(new UniversalDiskImage(file));
return MAKE_SHARED(UniversalDiskImage, file);
}
/*
* TODO -- support dos-order & nibblized
* TODO -- honor read-only flag.
*
*/
bool UniversalDiskImage::Validate(MappedFile *file, const std::nothrow_t &)
{
#undef __METHOD__
#define __METHOD__ "UniversalDiskImage::Validate"
const void *data = file->address();
size_t size = file->length();
unsigned blocks = 0;
unsigned offset = 0;
if (size < 64) return false;
if (std::memcmp(data, "2IMG", 4)) return false;
// only prodos supported, for now...
// TODO -- Dos Order, Nibble support.
if (Read32(data, 0x0c) != 1) return false;
blocks = Read32(data, 0x14);
offset = Read32(data, 0x18);
// file size == blocks * 512
if (Read32(data, 0x1c) != blocks * 512) return false;
if (offset + blocks * 512 > size) return false;
return true;
}
bool UniversalDiskImage::Validate(MappedFile *file)
{
#undef __METHOD__
#define __METHOD__ "UniversalDiskImage::Validate"
if (!Validate(file, std::nothrow))
throw Exception(__METHOD__ ": Invalid file format.");
return true;
}
bool UniversalDiskImage::readOnly()
{
return (_flags & 0x8000000) || DiskImage::readOnly();
}
BlockCachePointer UniversalDiskImage::createBlockCache()
{
if (_format == 1)
{
return MappedBlockCache::Create(shared_from_this(), _dataOffset + (uint8_t *)address());
}
return DiskImage::createBlockCache();
}

View File

@@ -0,0 +1,44 @@
#ifndef __UNIVERSALDISKIMAGE_H__
#define __UNIVERSALDISKIMAGE_H__
#include <Device/BlockDevice.h>
#include <Device/DiskImage.h>
#include <stdint.h>
namespace Device {
class UniversalDiskImage : public DiskImage {
public:
static BlockDevicePointer Create(const char *name, size_t blocks);
static BlockDevicePointer Open(MappedFile *);
virtual bool readOnly();
virtual BlockCachePointer createBlockCache();
static bool Validate(MappedFile *, const std::nothrow_t &);
static bool Validate(MappedFile *);
private:
UniversalDiskImage();
UniversalDiskImage(MappedFile *);
uint32_t _format;
uint32_t _flags;
uint32_t _blocks;
uint32_t _dataOffset;
uint32_t _dataLength;
};
}
#endif

166
Disk.cpp
View File

@@ -7,8 +7,7 @@
*/
#include "Disk.h"
#include "DiskCopy42.h"
#include "UniversalDiskImage.h"
#include "common.h"
@@ -24,6 +23,8 @@
#include <set>
#include <vector>
#include <Endian/Endian.h>
struct ucmp
{
bool operator()(unsigned a, unsigned b) const
@@ -35,127 +36,32 @@ struct ucmp
using std::set;
using std::vector;
using namespace LittleEndian;
typedef set<unsigned, ucmp> uset;
Disk::Disk()
{
_data = (uint8_t *)-1;
_blocks = 0;
_offset = 0;
_size = 0;
_flags = 0;
}
Disk::~Disk()
{
if (_data != (uint8_t *)-1)
munmap(_data, _size);
}
Disk *Disk::OpenFile(const char *file, unsigned flags)
Disk::Disk(Device::BlockDevicePointer device) :
_device(device)
{
int fd;
struct stat st;
size_t size;
unsigned blocks;
unsigned offset;
void *map;
Disk *d = NULL;
fd = open(file, O_RDONLY);
if (fd >= 0)
{
if (fstat(fd, &st) == 0)
{
size = st.st_size;
// raw disk images must be a blocksize multiple and <= 32 Meg.
if ( (size & 0x1ff) == 0
&& size > 0
&& size <= 32 * 1024 * 1024
)
{
blocks = size >> 9;
offset = 0;
}
else {
// check for disk copy4.2 / universal disk image.
uint8_t buffer[1024];
if (read(fd, buffer, 1024) != 1024)
{
close(fd);
return NULL;
}
bool ok = false;
do {
DiskCopy42 dc;
if (dc.Load(buffer)
&& size == 84 + dc.data_size + dc.tag_size
&& (dc.data_size & 0x1ff) == 0)
{
offset = 84;
blocks = dc.data_size >> 9;
ok = true;
flags |= P8_DC42;
break;
}
UniversalDiskImage udi;
if (udi.Load(buffer)
//&& udi.version == 1
&& udi.image_format == UDI_FORMAT_PRODOS_ORDER)
{
blocks = udi.data_blocks;
offset = udi.data_offset;
ok = true;
flags |= P8_2MG;
break;
}
} while (false);
if (!ok)
{
close(fd);
return NULL;
}
lseek(fd, 0, SEEK_SET);
}
map = mmap(NULL, size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
if (map != (void *)-1)
{
d = new Disk();
d->_size = size;
d->_data = (uint8_t *)map;
d->_blocks = blocks;
d->_offset = offset;
d->_flags = flags;
}
}
close(fd);
}
return d;
_blocks = _device->blocks();
}
DiskPointer Disk::OpenFile(Device::BlockDevicePointer device)
{
DiskPointer disk(new Disk(device));
return disk;
}
// load the mini entry into the regular entry.
int Disk::Normalize(FileEntry &f, unsigned fork, ExtendedEntry *ee)
@@ -200,31 +106,11 @@ int Disk::Normalize(FileEntry &f, unsigned fork, ExtendedEntry *ee)
int Disk::Read(unsigned block, void *buffer)
{
if (block > _blocks) return -P8_INVALID_BLOCK;
if (_flags & P8_DOS_ORDER)
{
static unsigned do_map[] = {0x00, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x0f };
unsigned track = (block & ~0x07) << 9;
unsigned sector = (block & 0x07) << 1;
for (unsigned i = 0; i < 2; i++)
{
unsigned offset = track | (do_map[sector+i] << 8);
memcpy(buffer, _data + _offset + offset, 256);
buffer = (char *)buffer + 256;
}
return 1;
}
if (block > _blocks) return -P8_INVALID_BLOCK;
_device->read(block, buffer);
memcpy(buffer, _data + _offset + (block << 9), BLOCK_SIZE);
return 1;
}
@@ -458,8 +344,8 @@ int Disk::ReadVolume(VolumeEntry *volume, std::vector<FileEntry> *files)
if (ok < 0) return ok;
prev = load16(&buffer[0x00]);
next = load16(&buffer[0x02]);
prev = Read16(&buffer[0x00]);
next = Read16(&buffer[0x02]);
VolumeEntry v;
v.Load(buffer + 0x04);
@@ -505,8 +391,8 @@ int Disk::ReadVolume(VolumeEntry *volume, std::vector<FileEntry> *files)
if (ok < 0) return ok;
block = next;
prev = load16(&buffer[0x00]);
next = load16(&buffer[0x02]);
prev = Read16(&buffer[0x00]);
next = Read16(&buffer[0x02]);
index = 0;
}
@@ -535,8 +421,8 @@ int Disk::ReadDirectory(unsigned block, SubdirEntry *dir, std::vector<FileEntry>
if (ok < 0) return ok;
prev = load16(&buffer[0x00]);
next = load16(&buffer[0x02]);
prev = Read16(&buffer[0x00]);
next = Read16(&buffer[0x02]);
SubdirEntry v;
v.Load(buffer + 0x04);
@@ -585,8 +471,8 @@ int Disk::ReadDirectory(unsigned block, SubdirEntry *dir, std::vector<FileEntry>
block = next;
prev = load16(&buffer[0x00]);
next = load16(&buffer[0x02]);
prev = Read16(&buffer[0x00]);
next = Read16(&buffer[0x02]);
index = 0;
}

20
Disk.h
View File

@@ -13,7 +13,10 @@
#include <vector>
#include "File.h"
#include <ProDOS/File.h>
#include <Device/BlockDevice.h>
#include <tr1/memory>
enum {
@@ -40,6 +43,8 @@ enum {
};
class Disk;
typedef std::tr1::shared_ptr<Disk> DiskPointer;
class Disk {
@@ -47,7 +52,7 @@ public:
~Disk();
//static Disk *Open2MG(const char *file);
static Disk *OpenFile(const char *file, unsigned flags);
static DiskPointer OpenFile(Device::BlockDevicePointer device);
int Normalize(FileEntry &f, unsigned fork, ExtendedEntry *ee = NULL);
@@ -65,13 +70,14 @@ public:
private:
Disk();
uint8_t *_data;
unsigned _offset;
unsigned _blocks;
size_t _size;
Disk(Device::BlockDevicePointer device);
unsigned _flags;
unsigned _blocks;
Device::BlockDevicePointer _device;
};
#endif

View File

@@ -1,63 +0,0 @@
/*
* DiskCopy42.cpp
* profuse
*
* Created by Kelvin Sherlock on 1/4/09.
*
*/
#include "DiskCopy42.h"
#include "common.h"
#include <string.h>
uint32_t DiskCopy42::CheckSum(uint8_t *buffer, unsigned length)
{
uint32_t checksum = 0;
if (length & 0x01) return -1;
/*
* checksum starts at 0
* foreach big-endian 16-bit word w:
* checksum += w
* checksum = checksum rotate right 1 (bit 0 --> bit 31)
*/
for(unsigned i = 0; i < length; i += 2)
{
checksum += (buffer[i] << 8);
checksum += buffer[i + 1];
checksum = (checksum >> 1) | (checksum << 31);
//if (checksum & 0x01) checksum = (checksum >> 1) | 0x80000000;
//else checksum >>= 1;
}
return checksum;
}
bool DiskCopy42::Load(const uint8_t *buffer)
{
unsigned i;
i = buffer[0];
if (i >= 64) return false;
memcpy(disk_name, &buffer[1], i);
disk_name[i] = 0;
data_size = load32_be(&buffer[64]);
tag_size = load32_be(&buffer[68]);
data_checksum = load32_be(&buffer[72]);
tag_checksum = load32_be(&buffer[76]);
disk_format = buffer[80];
format_byte = buffer[81];
private_word = load16_be(&buffer[82]);
if (private_word != 0x100) return false;
return true;
}

View File

@@ -1,31 +0,0 @@
/*
* DiskCopy42.h
* profuse
*
* Created by Kelvin Sherlock on 1/4/09.
*
*/
#ifndef __DISKCOPY42__
#define __DISKCOPY42__
#include <stdint.h>
struct DiskCopy42
{
bool Load(const uint8_t *buffer);
static uint32_t CheckSum(uint8_t *buffer, unsigned length);
char disk_name[64];
uint32_t data_size;
uint32_t tag_size;
uint32_t data_checksum;
uint32_t tag_checksum;
unsigned disk_format;
unsigned format_byte;
unsigned private_word;
};
#endif

105
Endian/Endian.cpp Normal file
View File

@@ -0,0 +1,105 @@
#include <Endian/Endian.h>
namespace LittleEndian {
uint16_t Read16(const void *vp)
{
const uint8_t *p = (const uint8_t *)vp;
return p[0] | (p[1] << 8);
}
uint32_t Read24(const void *vp)
{
const uint8_t *p = (const uint8_t *)vp;
return (p[0]) | (p[1] << 8) | (p[2] << 16);
}
uint32_t Read32(const void *vp)
{
const uint8_t *p = (const uint8_t *)vp;
return (p[0]) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
}
void Write16(void *vp, uint16_t x)
{
uint8_t *p = (uint8_t *)vp;
p[0] = (x) & 0xff;
p[1] = (x >> 8) & 0xff;
}
void Write24(void *vp, uint32_t x)
{
uint8_t *p = (uint8_t *)vp;
p[0] = (x) & 0xff;
p[1] = (x >> 8) & 0xff;
p[2] = (x >> 16) & 0xff;
}
void Write32(void *vp, uint32_t x)
{
uint8_t *p = (uint8_t *)vp;
p[0] = (x) & 0xff;
p[1] = (x >> 8) & 0xff;
p[2] = (x >> 16) & 0xff;
p[3] = (x >> 24) & 0xff;
}
}
namespace BigEndian {
uint16_t Read16(const void *vp)
{
const uint8_t *p = (const uint8_t *)vp;
return (p[0] << 8) | (p[1]);
}
uint32_t Read24(const void *vp)
{
const uint8_t *p = (const uint8_t *)vp;
return (p[0] << 16) | (p[1] << 8) | (p[2]);
}
uint32_t Read32(const void *vp)
{
const uint8_t *p = (const uint8_t *)vp;
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]);
}
void Write16(void *vp, uint16_t x)
{
uint8_t *p = (uint8_t *)vp;
p[0] = (x >> 8) & 0xff;
p[1] = (x) & 0xff;
}
void Write24(void *vp, uint32_t x)
{
uint8_t *p = (uint8_t *)vp;
p[0] = (x >> 16) & 0xff;
p[1] = (x >> 8) & 0xff;
p[2] = (x) & 0xff;
}
void Write32(void *vp, uint32_t x)
{
uint8_t *p = (uint8_t *)vp;
p[0] = (x >> 24) & 0xff;
p[1] = (x >> 16) & 0xff;
p[2] = (x >> 8) & 0xff;
p[3] = (x) & 0xff;
}
}

159
Endian/Endian.h Normal file
View File

@@ -0,0 +1,159 @@
#ifndef __ENDIAN_H__
#define __ENDIAN_H__
// utlities to read/write bytes.
#include <stdint.h>
namespace LittleEndian {
inline uint8_t Read8(const void *vp)
{
const uint8_t *p = (const uint8_t *)vp;
return (p[0]);
}
uint16_t Read16(const void *vp);
uint32_t Read24(const void *vp);
uint32_t Read32(const void *vp);
inline uint8_t Read8(const void *vp, unsigned offset)
{
return Read8(offset + (const uint8_t *)vp);
}
inline uint16_t Read16(const void *vp, unsigned offset)
{
return Read16(offset + (const uint8_t *)vp);
}
inline uint32_t Read24(const void *vp, unsigned offset)
{
return Read24(offset + (const uint8_t *)vp);
}
inline uint32_t Read32(const void *vp, unsigned offset)
{
return Read32(offset + (const uint8_t *)vp);
}
// write
inline void Write8(void *vp, uint8_t x)
{
uint8_t *p = (uint8_t *)vp;
p[0] = x;
}
void Write16(void *vp, uint16_t x);
void Write24(void *vp, uint32_t x);
void Write32(void *vp, uint32_t x);
inline void Write8(void *vp, unsigned offset, uint8_t x)
{
Write8(offset + (uint8_t *)vp, x);
}
inline void Write16(void *vp, unsigned offset, uint16_t x)
{
Write16(offset + (uint8_t *)vp, x);
}
inline void Write24(void *vp, unsigned offset, uint32_t x)
{
Write24(offset + (uint8_t *)vp, x);
}
inline void Write32(void *vp, unsigned offset, uint32_t x)
{
Write32(offset + (uint8_t *)vp, x);
}
}
namespace BigEndian {
inline uint8_t Read8(const void *vp)
{
const uint8_t *p = (const uint8_t *)vp;
return p[0];
}
uint16_t Read16(const void *vp);
uint32_t Read24(const void *vp);
uint32_t Read32(const void *vp);
inline uint8_t Read8(const void *vp, unsigned offset)
{
return Read8(offset + (const uint8_t *)vp);
}
inline uint16_t Read16(const void *vp, unsigned offset)
{
return Read16(offset + (const uint8_t *)vp);
}
inline uint32_t Read24(const void *vp, unsigned offset)
{
return Read24(offset + (const uint8_t *)vp);
}
inline uint32_t Read32(const void *vp, unsigned offset)
{
return Read32(offset + (const uint8_t *)vp);
}
// write
inline void Write8(void *vp, uint8_t x)
{
uint8_t *p = (uint8_t *)vp;
p[0] = x;
}
void Write16(void *vp, uint16_t x);
void Write24(void *vp, uint32_t x);
void Write32(void *vp, uint32_t x);
inline void Write8(void *vp, unsigned offset, uint8_t x)
{
Write8(offset + (uint8_t *)vp, x);
}
inline void Write16(void *vp, unsigned offset, uint16_t x)
{
Write16(offset + (uint8_t *)vp, x);
}
inline void Write24(void *vp, unsigned offset, uint32_t x)
{
Write24(offset + (uint8_t *)vp, x);
}
inline void Write32(void *vp, unsigned offset, uint32_t x)
{
Write32(offset + (uint8_t *)vp, x);
}
}
#endif

103
Endian/IOBuffer.cpp.h Normal file
View File

@@ -0,0 +1,103 @@
class IOBuffer {
public:
IOBuffer(void *vp, unsigned size)
{
_buffer = vp;
_size = size;
_offset = 0;
}
void write8(uint8_t value)
{
Write8(_buffer, _offset, value);
_offset += 1;
}
void write16(uint16_t value)
{
Write16(_buffer, _offset, value);
_offset += 2;
}
void write24(uint32_t value)
{
Write24(_buffer, _offset, value);
_offset += 3;
}
void write32(uint32_t value)
{
Write32(_buffer, _offset, value);
_offset += 4;
}
void writeBytes(const void *src, unsigned count)
{
std::memcpy(_offset + (uint8_t *)_buffer, src, count);
_offset += count;
}
void writeZero(unsigned count)
{
std::memset(_offset + (uint8_t *)_buffer, 0, count);
_offset += count;
}
uint8_t read8()
{
uint8_t x = Read8(_buffer, _offset);
_offset += 1;
return x;
}
uint16_t read16()
{
uint16_t x = Read16(_buffer, _offset);
_offset += 2;
return x;
}
uint32_t read24()
{
uint32_t x = Read24(_buffer, _offset);
_offset += 3;
return x;
}
uint32_t read32()
{
uint32_t x = Read32(_buffer, _offset);
_offset += 4;
return x;
}
void readBytes(void *dest, unsigned count)
{
std::memcpy(dest, _offset + (uint8_t *)_buffer, count);
_offset += count;
}
unsigned offset() const { return _offset; }
void setOffset(unsigned offset) { _offset = offset; }
void setOffset(unsigned offset, bool zero)
{
if (zero && offset > _offset)
{
writeZero(offset - _offset);
}
else setOffset(offset);
}
unsigned size() const { return _size; }
void *buffer() const { return _buffer; }
private:
void *_buffer;
unsigned _size;
unsigned _offset;
};

15
Endian/IOBuffer.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef __IOBUFFER_H__
#define __IOBUFFER_H__
#include <Endian/Endian.h>
#include <cstring>
namespace LittleEndian {
#include "IOBuffer.cpp.h"
}
namespace BigEndian {
#include "IOBuffer.cpp.h"
}
#endif

128
File/File.cpp Normal file
View File

@@ -0,0 +1,128 @@
#include <algorithm>
#include <cerrno>
#include <File/File.h>
#include <ProFUSE/Exception.h>
using ProFUSE::Exception;
using ProFUSE::POSIXException;
File::File()
{
_fd = -1;
}
File::File(int fd)
{
_fd = fd;
}
File::File(File& f)
{
_fd = f._fd;
f._fd = -1;
}
File::File(const char *name, int flags, const std::nothrow_t&)
{
_fd = ::open(name, flags);
}
File::File(const char *name, int flags, mode_t mode, const std::nothrow_t&)
{
_fd = ::open(name, flags, mode);
}
File::File(const char *name, FileFlags flags, const std::nothrow_t&)
{
_fd = ::open(name, flags == ReadOnly ? O_RDONLY : O_RDWR);
}
File::File(const char *name, int flags)
{
#undef __METHOD__
#define __METHOD__ "File::File"
_fd = ::open(name, flags);
if (_fd < 0)
throw POSIXException( __METHOD__ ": open", errno);
}
File::File(const char *name, int flags, mode_t mode)
{
#undef __METHOD__
#define __METHOD__ "File::File"
_fd = ::open(name, flags, mode);
if (_fd < 0)
throw POSIXException( __METHOD__ ": open", errno);
}
File::File(const char *name, FileFlags flags)
{
#undef __METHOD__
#define __METHOD__ "File::File"
_fd = ::open(name, flags == ReadOnly ? O_RDONLY : O_RDWR);
if (_fd < 0)
throw POSIXException( __METHOD__ ": open", errno);
}
File::~File()
{
close();
}
int File::release()
{
int tmp = _fd;
_fd = -1;
return tmp;
}
void File::close()
{
#undef __METHOD__
#define __METHOD__ "File::close"
if (_fd >= 0)
{
::close(_fd);
_fd = -1;
// destructor shouldn't throw.
/*
if (::close(fd) != 0)
throw POSIXException(__METHOD__ ": close", errno);
*/
}
}
void File::adopt(File &f)
{
if (&f == this) return;
close();
_fd = f._fd;
f._fd = -1;
}
void File::adopt(int fd)
{
if (fd == _fd) return;
close();
_fd = fd;
}
void File::swap(File &f)
{
std::swap(_fd, f._fd);
}

58
File/File.h Normal file
View File

@@ -0,0 +1,58 @@
#ifndef __FILE_H__
#define __FILE_H__
#include <new>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
class File {
public:
enum FileFlags {
ReadOnly = 1,
ReadWrite = 2
};
File();
File(File &);
File(int fd);
File(const char *name, int flags);
File(const char *name, int flags, mode_t mode);
File(const char *name, FileFlags flags);
File(const char *name, int flags, const std::nothrow_t &);
File(const char *name, int flags, mode_t mode, const std::nothrow_t &);
File(const char *name, FileFlags flags, const std::nothrow_t &);
~File();
bool isValid() const
{
return _fd >= 0;
}
int fd() const { return _fd; }
int release();
void close();
void adopt(File &f);
void adopt(int fd);
void swap(File &f);
private:
// could call dup() or something.
File& operator=(const File &f);
int _fd;
};
#endif

187
File/MappedFile.cpp Normal file
View File

@@ -0,0 +1,187 @@
#include <algorithm>
#include <cerrno>
#include <sys/stat.h>
#include <File/MappedFile.h>
#include <ProFUSE/Exception.h>
using ProFUSE::POSIXException;
MappedFile::MappedFile()
{
_length = -1;
_address = MAP_FAILED;
_readOnly = true;
}
MappedFile::MappedFile(MappedFile &mf)
{
_address = mf._address;
_length = mf._length;
_readOnly = mf._readOnly;
mf._address = MAP_FAILED;
mf._length = -1;
mf._readOnly = true;
}
MappedFile::MappedFile(const File &f, File::FileFlags flags, size_t size)
{
_length = -1;
_address = MAP_FAILED;
_readOnly = true;
init(f, flags == File::ReadOnly, size);
}
MappedFile::MappedFile(const char *name, File::FileFlags flags)
{
File f(name, flags);
_length = -1;
_address = MAP_FAILED;
_readOnly = true;
init(f, flags == File::ReadOnly, 0);
}
MappedFile::MappedFile(const char *name, File::FileFlags flags, const std::nothrow_t &nothrow)
{
File f(name, flags, nothrow);
_length = -1;
_address = MAP_FAILED;
_readOnly = true;
if (f.isValid())
init(f, flags == File::ReadOnly, 0);
}
MappedFile::~MappedFile()
{
close();
}
void MappedFile::init(const File &f, bool readOnly, size_t size)
{
#undef __METHOD__
#define __METHOD__ "MappedFile::init"
struct stat st;
int prot = readOnly ? PROT_READ : PROT_READ | PROT_WRITE;
int flags = MAP_FILE | MAP_SHARED;
// close enough
if (f.fd() < 0)
throw POSIXException( __METHOD__, EBADF);
if (!size)
{
if (::fstat(f.fd(), &st) != 0)
throw POSIXException(__METHOD__ ": fstat", errno);
if (!S_ISREG(st.st_mode))
throw POSIXException(__METHOD__, ENODEV);
size = st.st_size;
}
_length = size;
_address = ::mmap(0, _length, prot, flags, f.fd(), 0);
if (_address == MAP_FAILED)
throw POSIXException(__METHOD__ ": mmap", errno);
_readOnly = readOnly;
}
void MappedFile::close()
{
#undef __METHOD__
#define __METHOD__ "MappedFile::close"
if (_address != MAP_FAILED)
{
/*
void *address = _address;
size_t length = _length;
*/
::munmap(_address, _length);
_address = MAP_FAILED;
_length = -1;
_readOnly = true;
// destructor shouldn't throw.
/*
if (::munmap(address, length) != 0)
throw POSIXException(__METHOD__ ": munmap", errno);
*/
}
}
void MappedFile::sync()
{
#undef __METHOD__
#define __METHOD__ "MappedFile::sync"
if (_address != MAP_FAILED)
{
if (::msync(_address, _length, MS_SYNC) != 0)
throw POSIXException(__METHOD__ ": msync", errno);
}
}
void MappedFile::adopt(MappedFile &mf)
{
close();
_address = mf._address;
_length = mf._length;
_readOnly = mf._readOnly;
mf._address = MAP_FAILED;
mf._length = -1;
mf._readOnly = true;
}
void MappedFile::swap(MappedFile &mf)
{
std::swap(_address, mf._address);
std::swap(_length, mf._length);
std::swap(_readOnly, mf._readOnly);
}
MappedFile *MappedFile::Create(const char *name, size_t size)
{
#undef __METHOD__
#define __METHOD__ "MappedFile::Create"
File fd(::open(name, O_CREAT | O_TRUNC | O_RDWR, 0644));
if (!fd.isValid())
{
throw POSIXException(__METHOD__ ": Unable to create file.", errno);
}
// TODO -- is ftruncate portable?
if (::ftruncate(fd.fd(), size) < 0)
{
// TODO -- unlink?
throw POSIXException(__METHOD__ ": Unable to truncate file.", errno);
}
return new MappedFile(fd, File::ReadWrite, size);
}

53
File/MappedFile.h Normal file
View File

@@ -0,0 +1,53 @@
#ifndef __MAPPED_FILE_H__
#define __MAPPED_FILE_H__
#include <new>
#include <sys/mman.h>
#include <File/File.h>
class File;
class MappedFile {
public:
MappedFile();
MappedFile(MappedFile&);
MappedFile(const File &f, File::FileFlags flags, size_t size = -1);
MappedFile(const char *name, File::FileFlags flags);
MappedFile(const char *name, File::FileFlags flags, const std::nothrow_t &nothrow);
~MappedFile();
static MappedFile *Create(const char *name, size_t size);
bool isValid() const
{
return _address != MAP_FAILED;
}
void sync();
void close();
void *address() const { return _address; }
size_t length() const { return _length; }
bool readOnly() const { return _readOnly; }
void swap(MappedFile &);
void adopt(MappedFile &);
private:
MappedFile& operator=(MappedFile &);
void init(const File &f, bool readOnly, size_t size);
void *_address;
size_t _length;
bool _readOnly;
};
#endif

192
MacRoman.cpp Normal file
View File

@@ -0,0 +1,192 @@
#include "MacRoman.h"
/*
* mapping of MacRoman characters (0x80-0xff) to unicode.
*/
static unsigned m2u[] = {
0x00C4,
0x00C5,
0x00C7,
0x00C9,
0x00D1,
0x00D6,
0x00DC,
0x00E1,
0x00E0,
0x00E2,
0x00E4,
0x00E3,
0x00E5,
0x00E7,
0x00E9,
0x00E8,
0x00EA,
0x00EB,
0x00ED,
0x00EC,
0x00EE,
0x00EF,
0x00F1,
0x00F3,
0x00F2,
0x00F4,
0x00F6,
0x00F5,
0x00FA,
0x00F9,
0x00FB,
0x00FC,
0x2020,
0x00B0,
0x00A2,
0x00A3,
0x00A7,
0x2022,
0x00B6,
0x00DF,
0x00AE,
0x00A9,
0x2122,
0x00B4,
0x00A8,
0x2260,
0x00C6,
0x00D8,
0x221E,
0x00B1,
0x2264,
0x2265,
0x00A5,
0x00B5,
0x2202,
0x2211,
0x220F,
0x03C0,
0x222B,
0x00AA,
0x00BA,
0x03A9,
0x00E6,
0x00F8,
0x00BF,
0x00A1,
0x00AC,
0x221A,
0x0192,
0x2248,
0x2206,
0x00AB,
0x00BB,
0x2026,
0x00A0,
0x00C0,
0x00C3,
0x00D5,
0x0152,
0x0153,
0x2013,
0x2014,
0x201C,
0x201D,
0x2018,
0x2019,
0x00F7,
0x25CA,
0x00FF,
0x0178,
0x2044,
0x20AC,
0x2039,
0x203A,
0xFB01,
0xFB02,
0x2021,
0x00B7,
0x201A,
0x201E,
0x2030,
0x00C2,
0x00CA,
0x00C1,
0x00CB,
0x00C8,
0x00CD,
0x00CE,
0x00CF,
0x00CC,
0x00D3,
0x00D4,
0xF8FF,
0x00D2,
0x00DA,
0x00DB,
0x00D9,
0x0131,
0x02C6,
0x02DC,
0x00AF,
0x02D8,
0x02D9,
0x02DA,
0x00B8,
0x02DD,
0x02DB,
0x02C7
};
bool MacRoman::isASCII() const
{
for (std::string::const_iterator iter = _string.begin(); iter != _string.end(); ++iter)
{
if (*iter & 0x80) return false;
}
return true;
}
std::string MacRoman::toUTF8() const
{
std::string out;
out.reserve(_string.length());
for (std::string::const_iterator iter = _string.begin(); iter != _string.end(); ++iter)
{
char c = *iter;
if (c & 0x80 == 0) out.push_back(c);
else
{
unsigned uc = m2u[c & 0x7f];
if (uc <= 0x7ff)
{
out.push_back(0xC0 | (uc >> 6));
out.push_back(0x80 | (uc & 0x3f));
}
else // nothing larger than 0xffff
{
out.push_back(0xe0 | (uc >> 12));
out.push_back(0x80 | ((uc >> 6) & 0x3f));
out.push_back(0x80 | (uc & 0x3f));
}
}
}
return out;
}
std::wstring MacRoman::toWString() const
{
std::wstring out;
out.reserve(_string.length());
for (std::string::const_iterator iter = _string.begin(); iter != _string.end(); ++iter)
{
char c = *iter;
if (c & 0x80 == 0) out.push_back(c);
else out.push_back(m2u[c & 0x7f]);
}
return out;
}

26
MacRoman.h Normal file
View File

@@ -0,0 +1,26 @@
#ifndef __MACROMAN_H__
#define __MACROMAN_H__
#include <string>
class MacRoman {
public:
MacRoman(const std::string& string);
bool isASCII() const;
std::string toUTF8() const;
std::wstring toWString() const;
private:
std::string _string;
};
inline MacRoman::MacRoman(const std::string& string) :
_string(string)
{
}
#endif

200
ProDOS/Bitmap.cpp Normal file
View File

@@ -0,0 +1,200 @@
#include <cstring>
#include <ProDOS/Bitmap.h>
#include <ProDOS/BlockDevice.h>
#include "auto.h"
using namespace ProDOS;
// returns # of 1-bits set (0-8)
inline static unsigned popCount(uint8_t x)
{
#ifdef __GNUC__
return __builtin_popcount(x);
#endif
// Brian Kernighan / Peter Wegner in CACM 3 (1960), 322.
unsigned count;
for (count = 0; x; ++count)
{
x &= x - 1;
}
return count;
}
Bitmap::Bitmap(unsigned blocks)
{
_blocks = _freeBlocks = blocks;
_bitmapBlocks = (blocks + 4095) / 4096;
_freeIndex = 0;
unsigned bitmapSize = _bitmapBlocks * 512;
unsigned blockSize = blocks / 8;
auto_array<uint8_t> bitmap(new uint8_t[bitmapSize]);
// mark overflow in use, everything else free.
std::memset(bitmap, 0xff, blocks / 8);
std::memset(bitmap + blockSize, 0x00, bitmapSize - blockSize);
// edge case
unsigned tmp = blocks & 0x07;
bitmap[blocks / 8] = ~(0xff >> tmp);
_bitmap = bitmap.release();
}
Bitmap::Bitmap(BlockDevice *device, unsigned keyPointer, unsigned blocks)
{
_blocks = blocks;
_freeBlocks = 0;
_freeIndex = 0;
_bitmapBlocks = (blocks + 4095) / 4096;
unsigned bitmapSize = _bitmapBlocks * 512;
unsigned blockSize = blocks / 8;
auto_array<uint8_t> bitmap(new uint8_t[bitmapSize]);
for (unsigned i = 0; i < blockSize; ++i)
{
device->read(keyPointer + i, bitmap + 512 * i);
}
// make sure all trailing bits are marked in use.
// edge case
unsigned tmp = blocks & 0x07;
bitmap[blocks / 8] &= ~(0xff >> tmp);
std::memset(bitmap + blockSize, 0x00, bitmapSize - blockSize);
// set _freeBlocks and _freeIndex;
for (unsigned i = 0; i < (blocks + 7) / 8; ++i)
{
_freeBlocks += popCount(bitmap[i]);
}
if (_freeBlocks)
{
for (unsigned i = 0; i < (blocks + 7) / 8; ++i)
{
if (bitmap[i])
{
_freeIndex = i;
break;
}
}
}
_bitmap = bitmap.release();
}
Bitmap::~Bitmap()
{
if (_bitmap) delete []_bitmap;
}
void Bitmap::freeBlock(unsigned block)
{
if (block >= _blocks) return;
unsigned index = block / 8;
unsigned offset = block & 0x07;
unsigned mask = 0x80 >> offset;
uint8_t tmp = _bitmap[index];
if ((tmp & mask) == 0)
{
++_freeBlocks;
_bitmap[index] = tmp | mask;
}
}
int Bitmap::allocBlock(unsigned block)
{
if (block >= _blocks) return -1;
unsigned index = block / 8;
unsigned offset = block & 0x07;
unsigned mask = 0x80 >> offset;
uint8_t tmp = _bitmap[index];
if ((tmp & mask))
{
--_freeBlocks;
_bitmap[index] = tmp & ~mask;
return block;
}
return -1;
}
int Bitmap::allocBlock()
{
if (!_freeBlocks) return -1;
unsigned freeIndex = _freeIndex;
unsigned maxIndex = (_blocks + 7) / 8;
for (unsigned index = _freeIndex; index < maxIndex; ++index)
{
uint8_t tmp = _bitmap[index];
if (!tmp) continue;
unsigned mask = 0x80;
for (unsigned offset = 0; offset < 8; ++offset)
{
if (tmp & mask)
{
_freeIndex = index;
_bitmap[index] = tmp & ~mask;
--_freeBlocks;
return index * 8 + offset;
}
mask = mask >> 1;
}
}
for (unsigned index = 0; index < freeIndex; ++index)
{
uint8_t tmp = _bitmap[index];
if (!tmp) continue;
unsigned mask = 0x80;
for (unsigned offset = 0; offset < 8; ++offset)
{
if (tmp & mask)
{
_freeIndex = index;
_bitmap[index] = tmp & ~mask;
--_freeBlocks;
return index * 8 + offset;
}
mask = mask >> 1;
}
}
// should never happen...
return -1;
}

48
ProDOS/Bitmap.h Normal file
View File

@@ -0,0 +1,48 @@
#ifndef __BITMAP_H__
#define __BITMAP_H__
#include <stdint.h>
namespace ProDOS {
class BlockDevice;
class Bitmap {
public:
Bitmap(unsigned blocks);
Bitmap(BlockDevice *device, unsigned keyPointer, unsigned blocks);
//todo -- constructor by loading from, block device...
~Bitmap();
int allocBlock();
int allocBlock(unsigned block);
void freeBlock(unsigned block);
unsigned freeBlocks() const { return _freeBlocks; }
unsigned blocks() const { return _blocks; }
unsigned bitmapBlocks() const { return _bitmapBlocks; }
unsigned bitmapSize() const { return _bitmapBlocks * 512; }
const void *bitmap() const { return _bitmap; }
private:
unsigned _freeIndex;
unsigned _freeBlocks;
unsigned _blocks;
unsigned _bitmapBlocks;
uint8_t *_bitmap;
};
}
#endif

View File

@@ -1,11 +1,12 @@
#include "DateTime.h"
#include <cstdio>
#include <ctime>
#include <cstring>
namespace ProDOS {
#include <ProDOS/DateTime.h>
using namespace ProDOS;
/*
* date is a 16 bit value:
@@ -141,4 +142,3 @@ std::time_t DateTime::toUnix() const
// convert back via locatime & fudge for dst?
}
} // namespace

View File

@@ -6,7 +6,9 @@
*
*/
#include "File.h"
#include <ProDOS/File.h>
#include <ProDOS/DateTime.h>
#include <Endian/Endian.h>
#include "common.h"
#include <string.h>
@@ -14,49 +16,7 @@
#include <ctype.h>
#include <stdio.h>
/*
* ProDOS technote 28
*
* The following definition allows the same range of years that the Apple IIgs
* Control Panel CDA currently does:
*
* o A seven-bit ProDOS year value is in the range 0 to 99
* (100 through 127 are invalid)
* o Year values from 40 to 99 represent 1940 through 1999
* o Year values from 0 to 39 represent 2000 through 2039
*/
/*
* A positive or 0 value for tm_isdst causes mktime() to presume initially
* that Daylight Savings Time, respectively, is or is not in effect for
* the specified time. A negative value for tm_isdst causes mktime() to
* attempt to determine whether Daylight Saving Time is in effect for the
* specified time.
*/
static time_t timeToUnix(unsigned yymmdd, unsigned hhmm)
{
printf("%x %x\n", yymmdd, hhmm);
if (yymmdd == 0) return 0;
tm t;
bzero(&t, sizeof(tm));
t.tm_min = hhmm & 0x3f;
// tm_hour is 0-23, but is_dst -1 compensates
t.tm_hour = (hhmm >> 8) & 0x1f;
t.tm_isdst = -1;
t.tm_mday = yymmdd & 0x1f;
t.tm_mon = ((yymmdd >> 5) & 0x0f) - 1;
t.tm_year = (yymmdd) >> 9;
if (t.tm_year <= 39) t.tm_year += 100;
return mktime(&t);
// convert back via locatime & fudge for dst?
}
using namespace LittleEndian;
bool FileEntry::Load(const void *data)
@@ -73,18 +33,18 @@ bool FileEntry::Load(const void *data)
file_type = cp[0x10];
key_pointer = load16(&cp[0x11]);
key_pointer = Read16(&cp[0x11]);
blocks_used = load16(&cp[0x13]);
blocks_used = Read16(&cp[0x13]);
eof = load24(&cp[0x15]);
eof = Read24(&cp[0x15]);
creation = timeToUnix(load16(&cp[0x18]), load16(&cp[0x1a]));
creation = ProDOS::DateTime(Read16(&cp[0x18]), Read16(&cp[0x1a]));
//version = cp[0x1c];
//min_version = cp[0x1d];
unsigned xcase = load16(&cp[0x1c]);
unsigned xcase = Read16(&cp[0x1c]);
if (xcase & 0x8000)
{
// gsos technote #8
@@ -101,11 +61,11 @@ bool FileEntry::Load(const void *data)
access = cp[0x1e];
aux_type = load16(&cp[0x1f]);
aux_type = Read16(&cp[0x1f]);
last_mod = timeToUnix(load16(&cp[0x21]), load16(&cp[0x23]));
last_mod = ProDOS::DateTime(Read16(&cp[0x21]), Read16(&cp[0x23]));
header_pointer = load16(&cp[0x25]);
header_pointer = Read16(&cp[0x25]);
return true;
}
@@ -121,16 +81,16 @@ bool ExtendedEntry::Load(const void *data)
// offset 0 - mini entry for data fork
dataFork.storage_type = cp[0x00] & 0x0f;
dataFork.key_block = load16(&cp[0x01]);
dataFork.blocks_used = load16(&cp[0x03]);
dataFork.eof = load24(&cp[0x05]);
dataFork.key_block = Read16(&cp[0x01]);
dataFork.blocks_used = Read16(&cp[0x03]);
dataFork.eof = Read24(&cp[0x05]);
// offset 256 - mini entry for resource fork.
resourceFork.storage_type = cp[256 + 0x00] & 0x0f;
resourceFork.key_block = load16(&cp[256 + 0x01]);
resourceFork.blocks_used = load16(&cp[256 + 0x03]);
resourceFork.eof = load24(&cp[256 + 0x05]);
resourceFork.key_block = Read16(&cp[256 + 0x01]);
resourceFork.blocks_used = Read16(&cp[256 + 0x03]);
resourceFork.eof = Read24(&cp[256 + 0x05]);
// xFInfo may be missing.
bzero(FInfo, sizeof(FInfo));
@@ -177,15 +137,15 @@ bool VolumeEntry::Load(const void *data)
// 0x14--0x1b reserved
creation = timeToUnix(load16(&cp[0x18]), load16(&cp[0x1a]));
last_mod = timeToUnix(load16(&cp[0x12]), load16(&cp[0x14]));
creation = ProDOS::DateTime(Read16(&cp[0x18]), Read16(&cp[0x1a]));
last_mod = ProDOS::DateTime(Read16(&cp[0x12]), Read16(&cp[0x14]));
if (last_mod == 0) last_mod = creation;
//version = cp[0x1c];
//min_version = cp[0x1d];
unsigned xcase = load16(&cp[0x16]);
unsigned xcase = Read16(&cp[0x16]);
if (xcase & 0x8000)
{
// gsos technote #8
@@ -204,11 +164,11 @@ bool VolumeEntry::Load(const void *data)
entries_per_block = cp[0x20];
file_count = load16(&cp[0x21]);
file_count = Read16(&cp[0x21]);
bit_map_pointer = load16(&cp[0x23]);
bit_map_pointer = Read16(&cp[0x23]);
total_blocks = load16(&cp[0x25]);
total_blocks = Read16(&cp[0x25]);
return true;
}
@@ -234,7 +194,7 @@ bool SubdirEntry::Load(const void *data)
// 0x145-0x1b reserved
creation = timeToUnix(load16(&cp[0x18]), load16(&cp[0x1a]));
creation = ProDOS::DateTime(Read16(&cp[0x18]), Read16(&cp[0x1a]));
//version = cp[0x1c];
//min_version = cp[0x1d];
@@ -258,9 +218,9 @@ bool SubdirEntry::Load(const void *data)
entries_per_block = cp[0x20];
file_count = load16(&cp[0x21]);
file_count = Read16(&cp[0x21]);
parent_pointer = load16(&cp[0x23]);
parent_pointer = Read16(&cp[0x23]);
parent_entry = cp[0x25];

View File

@@ -6,8 +6,8 @@
*
*/
#ifndef __FILE_H__
#define __FILE_H__
#ifndef __PRODOS_FILE_H__
#define __PRODOS_FILE_H__
#include <time.h>
#include <stdint.h>

148
ProFUSE/Exception.cpp Normal file
View File

@@ -0,0 +1,148 @@
#include <ProFUSE/Exception.h>
#include <stdio.h>
using namespace ProFUSE;
Exception::~Exception() throw()
{
}
const char *Exception::what()
{
return _string.c_str();
}
const char *Exception::errorString()
{
return "";
}
const char *POSIXException::errorString()
{
return strerror(error());
}
const char *ProDOSException::errorString()
{
switch (error())
{
case badSystemCall:
return "Bad System Call";
case invalidPcount:
return "Invalid Parameter Count";
case gsosActive:
return "GS/OS Active";
case devNotFound:
return "Device Not Found";
case invalidDevNum:
return "Invalid Device Number";
case drvrBadReq:
return "Driver Bad Request";
case drvrBadCode:
return "Driver Bad Code";
case drvrBadParm:
return "Driver Bad Parameter";
case drvrNotOpen:
return "Driver Not Open";
case drvrPriorOpen:
return "Driver Prior Open";
case irqTableFull:
return "IRQ Table Full";
case drvrNoResrc:
return "Driver No Resource";
case drvrIOError:
return "Driver IO Error";
case drvrNoDevice:
return "Driver No Device";
case drvrBusy:
return "Driver Busy";
case drvrWrtProt:
return "Driver Write Protected";
case drvrBadCount:
return "Driver Bad Count";
case drvrBadBlock:
return "Driver Bad Block";
case drvrDiskSwitch:
return "Driver Disk Switch";
case drvrOffLine:
return "Driver Off Line";
case badPathSyntax:
return "Bad Path Syntax";
case invalidRefNum:
return "Invalid Ref Num";
case pathNotFound:
return "Path Not Found";
case volNotFound:
return "Volume Not Found";
case fileNotFound:
return "File Not Found";
case dupPathName:
return "Duplicate Path Name";
case volumeFull:
return "Volume Full";
case volDirFull:
return "Volume Directory Full";
case badFileFormat:
return "Bad File Format";
case badStoreType:
return "Bad Storage Type";
case eofEncountered:
return "End of File";
case outOfRange:
return "Out of Range";
case invalidAccess:
return "Invalid Access";
case buffTooSmall:
return "Buffer Too Small";
case fileBusy:
return "File Busy";
case dirError:
return "Directory Error";
case unknownVol:
return "Unknown Volume";
case paramRangeError:
return "Parameter Range Error";
case outOfMem:
return "Out of Memory";
case dupVolume:
return "Duplicate Volume";
case notBlockDev:
return "Not a Block Device";
case invalidLevel:
return "Invalid Level";
case damagedBitMap:
return "Damaged Bit Map";
case badPathNames:
return "Bad Path Names";
case notSystemFile:
return "Not a System File";
case osUnsupported:
return "OS Unsupported";
case stackOverflow:
return "Stack Overflow";
case dataUnavail:
return "Data Unavailable";
case endOfDir:
return "End Of Directory";
case invalidClass:
return "Invalid Class";
case resForkNotFound:
return "Resource Fork Not Found";
case invalidFSTID:
return "Invalid FST ID";
case devNameErr:
return "Device Name Error";
case resExistsErr:
return "Resource Exists Error";
case resAddErr:
return "Resource Add Error";
default:
return "";
}
return "";
}

158
ProFUSE/Exception.h Normal file
View File

@@ -0,0 +1,158 @@
#ifndef __EXCEPTION_H__
#define __EXCEPTION_H__
#include <string>
#include <exception>
namespace ProFUSE {
// ProDOS Errors
enum
{
badSystemCall = 0x01,
invalidPcount = 0x04,
gsosActive = 0x07,
devNotFound = 0x10,
invalidDevNum = 0x11,
drvrBadReq = 0x20,
drvrBadCode = 0x21,
drvrBadParm = 0x22,
drvrNotOpen = 0x23,
drvrPriorOpen = 0x24,
irqTableFull = 0x25,
drvrNoResrc = 0x26,
drvrIOError = 0x27,
drvrNoDevice = 0x28,
drvrBusy = 0x29,
drvrWrtProt = 0x2b,
drvrBadCount = 0x2c,
drvrBadBlock = 0x2d,
drvrDiskSwitch = 0x2e,
drvrOffLine = 0x2f,
badPathSyntax = 0x40,
invalidRefNum = 0x43,
pathNotFound = 0x44,
volNotFound = 0x45,
fileNotFound = 0x46,
dupPathName = 0x47,
volumeFull = 0x48,
volDirFull = 0x49,
badFileFormat = 0x4a,
badStoreType = 0x4b,
eofEncountered = 0x4c,
outOfRange = 0x4d,
invalidAccess = 0x4e,
buffTooSmall = 0x4f,
fileBusy = 0x50,
dirError = 0x51,
unknownVol = 0x52,
paramRangeError = 0x53,
outOfMem = 0x54,
dupVolume = 0x57,
notBlockDev = 0x58,
invalidLevel = 0x59,
damagedBitMap = 0x5a,
badPathNames = 0x5b,
notSystemFile = 0x5c,
osUnsupported = 0x5d,
stackOverflow = 0x5f,
dataUnavail = 0x60,
endOfDir = 0x61,
invalidClass = 0x62,
resForkNotFound = 0x63,
invalidFSTID = 0x64,
devNameErr = 0x67,
resExistsErr = 0x70,
resAddErr = 0x71
};
class Exception : public std::exception
{
public:
Exception(const char *cp);
Exception(const std::string &str);
virtual ~Exception() throw ();
virtual const char *what();
virtual const char *errorString();
int error() const { return _error; }
protected:
Exception(const char *cp, int error);
Exception(const std::string& string, int error);
private:
int _error;
std::string _string;
};
class POSIXException : public Exception {
public:
POSIXException(const char *cp, int error);
POSIXException(const std::string& string, int error);
virtual const char *errorString();
};
class ProDOSException : public Exception {
public:
ProDOSException(const char *cp, int error);
ProDOSException(const std::string& string, int error);
virtual const char *errorString();
};
inline Exception::Exception(const char *cp):
_error(0),
_string(cp)
{
}
inline Exception::Exception(const std::string& string):
_error(0),
_string(string)
{
}
inline Exception::Exception(const char *cp, int error):
_error(error),
_string(cp)
{
}
inline Exception::Exception(const std::string& string, int error):
_error(error),
_string(string)
{
}
inline POSIXException::POSIXException(const char *cp, int error) :
Exception(cp, error)
{
}
inline POSIXException::POSIXException(const std::string& string, int error) :
Exception(string, error)
{
}
inline ProDOSException::ProDOSException(const char *cp, int error) :
Exception(cp, error)
{
}
inline ProDOSException::ProDOSException(const std::string& string, int error) :
Exception(string, error)
{
}
}
#endif

28
ProFUSE/Lock.cpp Normal file
View File

@@ -0,0 +1,28 @@
#include <ProFUSE/Lock.h>
using namespace ProFUSE;
Lock::Lock()
{
pthread_mutex_init(&_mutex, NULL);
}
Lock::~Lock()
{
pthread_mutex_destroy(&_mutex);
}
void Lock::lock()
{
pthread_mutex_lock(&_mutex);
}
void Lock::unlock()
{
pthread_mutex_unlock(&_mutex);
}
bool Lock::tryLock()
{
return pthread_mutex_trylock(&_mutex) == 0;
}

33
ProFUSE/Lock.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef __LOCK_H__
#define __LOCK_H__
#include <pthread.h>
namespace ProFUSE {
class Lock {
public:
Lock();
~Lock();
void lock();
void unlock();
bool tryLock();
private:
pthread_mutex_t _mutex;
};
class Locker {
public:
Locker(Lock& lock) : _lock(lock) { _lock.lock(); }
~Locker() { _lock.unlock(); }
private:
Lock &_lock;
};
}
#endif

104
ProFUSE/auto.h Normal file
View File

@@ -0,0 +1,104 @@
#ifndef __AUTO_H__
#define __AUTO_H__
#include <cstddef>
namespace ProFUSE {
template <class T>
class auto_array
{
public:
auto_array() : _t(NULL) {}
auto_array(T *t) : _t(t) {}
~auto_array() { if (_t) delete []_t; }
T* release()
{ T *tmp = _t; _t = NULL; return tmp; }
T* get() const { return _t; }
operator T*() const { return _t; }
T& operator[](int index) { return _t[index]; }
void reset(T *t)
{
if (t == _t) return;
if (_t) delete[] _t;
_t = t;
}
private:
T *_t;
};
// ::close
#if defined(O_CREAT)
class auto_fd
{
public:
auto_fd(int fd = -1) : _fd(fd) { }
~auto_fd() { close(); }
int release()
{ int tmp = _fd; _fd = -1; return tmp; }
int get() const { return _fd; }
operator int() const { return _fd; }
void reset(int fd)
{
if (fd != _fd)
{
close();
_fd = fd;
}
}
private:
auto_fd& operator=(const auto_fd&);
void close()
{
if (_fd >= 0)
{
::close(_fd);
_fd = -1;
}
}
int _fd;
};
#endif
// ::mmap, :munmap
#if defined(MAP_FAILED)
class auto_map
{
public:
auto_map(void *addr, size_t size, int prot, int flags, int fd, off_t offset)
:
_size(size),
_map(::mmap(addr, size, prot, flags, fd, offset))
{ }
~auto_map()
{ if (_map != MAP_FAILED) ::munmap(_map, _size); }
void *release()
{ void *tmp = _map; _map = MAP_FAILED; return tmp; }
void *get() const { return _map; }
operator void *() const { return _map; }
private:
size_t _size;
void *_map;
};
#endif
}
#endif

35
ProFUSE/smart_pointers.h Normal file
View File

@@ -0,0 +1,35 @@
#ifndef __PROFUSE_SMART_POINTERS_H__
#define __PROFUSE_SMART_POINTERS_H__
#ifdef CPP0X
//C++0x
#include <memory>
#define SHARED_PTR(T) std::shared_ptr<T>
#define WEAK_PTR(T) std::weak_ptr<T>
#define MAKE_SHARED(T, ...) std::make_shared<T>(__VA_ARGS__)
#define ENABLE_SHARED_FROM_THIS(T) std::enable_shared_from_this<T>
#define STATIC_POINTER_CAST(T, ARG) std::static_pointer_cast<T>(ARG)
#define DYNAMIC_POINTER_CAST(T, ARG) std::dynamic_pointer_cast<T>(ARG)
#else
// tr1
#include <tr1/memory>
#define SHARED_PTR(T) std::tr1::shared_ptr<T>
#define WEAK_PTR(T) std::tr1::weak_ptr<T>
#define MAKE_SHARED(T, ...) std::tr1::shared_ptr<T>(new T(__VA_ARGS__))
#define ENABLE_SHARED_FROM_THIS(T) std::tr1::enable_shared_from_this<T>
#define STATIC_POINTER_CAST(T, ARG) std::tr1::static_pointer_cast<T>(ARG)
#define DYNAMIC_POINTER_CAST(T, ARG) std::tr1::dynamic_pointer_cast<T>(ARG)
#endif
#endif

View File

@@ -1,51 +0,0 @@
/*
* UniversalDiskImage.cpp
* profuse
*
* Created by Kelvin Sherlock on 1/6/09.
*
*/
#include "UniversalDiskImage.h"
#include "common.h"
#include <string.h>
bool UniversalDiskImage::Load(const uint8_t *buffer)
{
if (strncmp((const char *)buffer, "2IMG", 4) != 0) return false;
// all numbers little-endian.
magic_word = load32(&buffer[0]);
creator = load32(&buffer[0x04]);
header_size = load16(&buffer[0x08]);
version = load16(&buffer[0x0a]);
image_format = load32(&buffer[0x0c]);
flags = load32(&buffer[0x10]);
data_blocks = load32(&buffer[0x14]);
data_offset = load32(&buffer[0x18]);
data_size = load32(&buffer[0x1c]);
comment_offset = load32(&buffer[0x20]);
comment_size = load32(&buffer[0x24]);
creator_data_offset = load32(&buffer[0x28]);
creator_data_size = load32(&buffer[0x2c]);
// 16 bytes reserved.
return true;
}

View File

@@ -1,40 +0,0 @@
/*
* UniversalDiskImage.h
* profuse
*
* Created by Kelvin Sherlock on 1/6/09.
*
*/
#ifndef __UNIVERSAL_DISK_IMAGE_H__
#define __UNIVERSAL_DISK_IMAGE_H__
#include <stdint.h>
#define UDI_FORMAT_DOS_ORDER 0
#define UDI_FORMAT_PRODOS_ORDER 1
#define UDI_FORMAT_NIBBLIZED 2
struct UniversalDiskImage
{
bool Load(const uint8_t * buffer);
uint32_t magic_word;
uint32_t creator;
unsigned header_size;
unsigned version;
unsigned image_format;
uint32_t flags;
unsigned data_blocks;
unsigned data_offset;
unsigned data_size;
unsigned comment_offset;
unsigned comment_size;
unsigned creator_data_offset;
unsigned creator_data_size;
};
#endif

View File

@@ -13,36 +13,6 @@
#define BLOCK_SIZE 512
// little endian.
inline unsigned load16(const uint8_t *cp)
{
return (cp[1] << 8 ) | cp[0];
}
inline unsigned load24(const uint8_t *cp)
{
return (cp[2] << 16 ) | (cp[1] << 8) | (cp[0]);
}
inline unsigned load32(const uint8_t *cp)
{
return (cp[3] << 24) | (cp[2] << 16 ) | (cp[1] << 8) | (cp[0]);
}
// big endian format.
inline unsigned load16_be(const uint8_t *cp)
{
return (cp[0] << 8) | (cp[1]);
}
inline unsigned load32_be(const uint8_t *cp)
{
return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | (cp[3]);
}
#endif

189
main.cpp
View File

@@ -14,29 +14,39 @@
#define _POSIX_C_SOURCE 200112L
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <vector>
#include <string>
#include <tr1/memory>
#include <Device/BlockDevice.h>
#include "profuse.h"
using std::vector;
using std::string;
using std::tr1::shared_ptr;
Disk *disk = NULL;
char *dfile = NULL;
/*
* globals variables.
*
*/
std::string fDiskImage;
DiskPointer disk;
VolumeEntry volume;
bool dos_order = false;
bool validProdosName(const char *name)
{
// OS X looks for hidden files that don't exist (and aren't legal prodos names)
@@ -70,46 +80,82 @@ static struct fuse_lowlevel_ops prodos_oper;
enum {
PRODOS_OPT_HELP,
PRODOS_OPT_VERSION,
PRODOS_OPT_DOS_ORDER
PRODOS_OPT_WRITE,
PRODOS_OPT_FORMAT,
PRODOS_OPT_VERBOSE
};
struct options {
char *format;
int readOnly;
int readWrite;
int verbose;
int debug;
} options;
#define PRODOS_OPT_KEY(T, P, V) {T, offsetof(struct options, P), V}
static struct fuse_opt prodos_opts[] = {
FUSE_OPT_KEY("-h", PRODOS_OPT_HELP),
FUSE_OPT_KEY("--help", PRODOS_OPT_HELP),
FUSE_OPT_KEY("-V", PRODOS_OPT_VERSION),
FUSE_OPT_KEY("--version", PRODOS_OPT_VERSION),
FUSE_OPT_KEY("--dos-order", PRODOS_OPT_DOS_ORDER),
PRODOS_OPT_KEY("-v", verbose, 1),
PRODOS_OPT_KEY("-w", readWrite, 1),
PRODOS_OPT_KEY("rw", readWrite, 1),
PRODOS_OPT_KEY("-d", debug, 1),
PRODOS_OPT_KEY("--format=%s", format, 0),
PRODOS_OPT_KEY("format=%s", format, 0),
{0, 0, 0}
};
static void usage()
{
fprintf(stderr, "profuse [options] disk_image mountpoint\n");
fprintf(stderr, "profuse [options] disk_image [mountpoint]\n"
"Options:\n"
" -d debug\n"
" -r readonly\n"
" -w mount writable [not yet]\n"
" -v verbose\n"
" --format=format specify the disk image format. Valid values are:\n"
" dc42 DiskCopy 4.2 Image\n"
" davex Davex Disk Image\n"
" sdk ShrinkIt Disk Image\n"
" 2img Universal Disk Image\n"
" do DOS Order Disk Image\n"
" po ProDOS Order Disk Image (default)\n"
" -o opt1,opt2... other mount parameters.\n"
);
}
static int prodos_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs)
{
switch(key)
{
/*
case PRODOS_OPT_HELP:
usage();
exit(0);
break;
*/
case PRODOS_OPT_VERSION:
// TODO
exit(1);
break;
case PRODOS_OPT_DOS_ORDER:
dos_order = true;
return 0;
break;
case FUSE_OPT_KEY_NONOPT:
if (dfile == NULL)
// first arg is the disk image.
if (fDiskImage.empty())
{
dfile = strdup(arg);
fDiskImage = arg;
return 0;
}
return 1;
@@ -159,15 +205,25 @@ int main(int argc, char *argv[])
struct fuse_chan *ch;
char *mountpoint = NULL;
int err = -1;
struct options options;
unsigned format = 0;
int foreground = false;
int multithread = false;
#if __APPLE__
string mountpath;
#endif
disk = NULL;
bzero(&prodos_oper, sizeof(prodos_oper));
std::memset(&prodos_oper, 0, sizeof(prodos_oper));
std::memset(&options, 0, sizeof(options));
prodos_oper.listxattr = prodos_listxattr;
prodos_oper.getxattr = prodos_getxattr;
@@ -183,25 +239,54 @@ int main(int argc, char *argv[])
prodos_oper.release = prodos_release;
prodos_oper.read = prodos_read;
prodos_oper.statfs = prodos_statfs;
// scan the argument list, looking for the name of the disk image.
if (fuse_opt_parse(&args, NULL , prodos_opts, prodos_opt_proc) == -1)
if (fuse_opt_parse(&args, &options , prodos_opts, prodos_opt_proc) == -1)
exit(1);
if (dfile == NULL || *dfile == 0)
if (fDiskImage.empty())
{
usage();
exit(0);
exit(1);
}
disk = Disk::OpenFile(dfile, dos_order);
if (!disk)
// default prodos-order disk image.
if (options.format)
{
fprintf(stderr, "Unable to mount disk %s\n", dfile);
exit(1);
}
format = Device::BlockDevice::ImageType(options.format);
if (!format)
std::fprintf(stderr, "Warning: Unknown image type ``%s''\n", options.format);
}
try {
Device::BlockDevicePointer device;
device = Device::BlockDevice::Open(fDiskImage.c_str(), File::ReadOnly, format);
if (!device)
{
std::fprintf(stderr, "Error: Unknown or unsupported device type.\n");
exit(1);
}
disk = Disk::OpenFile(device);
if (!disk)
{
fprintf(stderr, "Unable to mount disk %s\n", fDiskImage.c_str());
exit(1);
}
}
catch (ProFUSE::Exception &e)
{
std::fprintf(stderr, "%s\n", e.what());
std::fprintf(stderr, "%s\n", e.errorString());
return -1;
}
disk->ReadVolume(&volume, NULL);
@@ -235,6 +320,7 @@ int main(int argc, char *argv[])
#endif
foreground = options.debug;
if (mountpoint == NULL || *mountpoint == 0)
@@ -244,26 +330,32 @@ int main(int argc, char *argv[])
}
if ( (ch = fuse_mount(mountpoint, &args)) != NULL)
{
struct fuse_session *se;
se = fuse_lowlevel_new(&args, &prodos_oper, sizeof(prodos_oper), NULL);
if (se != NULL)
{
if (fuse_set_signal_handlers(se) != -1)
{
fuse_session_add_chan(se, ch);
err = fuse_session_loop(se);
fuse_remove_signal_handlers(se);
fuse_session_remove_chan(ch);
}
if (se != NULL) do {
err = fuse_daemonize(foreground);
if (err < 0 ) break;
fuse_session_destroy(se);
}
err = fuse_set_signal_handlers(se);
if (err < 0) break;
fuse_session_add_chan(se, ch);
if (multithread) err = fuse_session_loop_mt(se);
else err = fuse_session_loop(se);
fuse_remove_signal_handlers(se);
fuse_session_remove_chan(ch);
} while (false);
if (se) fuse_session_destroy(se);
fuse_unmount(mountpoint, ch);
}
@@ -271,9 +363,8 @@ int main(int argc, char *argv[])
fuse_opt_free_args(&args);
if (disk) delete disk;
disk.reset();
if (dfile) free(dfile);
#ifdef __APPLE__
if (mountpath.size()) rmdir(mountpath.c_str());

View File

@@ -9,7 +9,7 @@
#ifndef __PROFUSE_H__
#define __PROFUSE_H__
#include "File.h"
#include <ProDOS/File.h>
#include "Disk.h"
#include "common.h"
@@ -22,7 +22,7 @@
#define ERROR(cond,errno) if ( (cond) ){ fuse_reply_err(req, errno); return; }
extern Disk *disk;
extern DiskPointer disk;
bool validProdosName(const char *name);
@@ -40,6 +40,9 @@ void prodos_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, stru
void prodos_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi);
void prodos_lookup(fuse_req_t req, fuse_ino_t parent, const char *name);
void prodos_statfs(fuse_req_t req, fuse_ino_t ino);
// file io.
void prodos_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi);
void prodos_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi);

View File

@@ -208,15 +208,13 @@
<dict>
<key>ChosenToolbarItems</key>
<array>
<string>active-target-popup</string>
<string>active-buildstyle-popup</string>
<string>active-combo-popup</string>
<string>action</string>
<string>NSToolbarFlexibleSpaceItem</string>
<string>buildOrClean</string>
<string>build-and-goOrGo</string>
<string>debugger-enable-breakpoints</string>
<string>build-and-go</string>
<string>com.apple.ide.PBXToolbarStopButton</string>
<string>get-info</string>
<string>toggle-editor</string>
<string>NSToolbarFlexibleSpaceItem</string>
<string>com.apple.pbx.toolbar.searchfield</string>
</array>
@@ -239,7 +237,6 @@
<array>
<string>1C37FBAC04509CD000000102</string>
<string>1C37FAAC04509CD000000102</string>
<string>1C08E77C0454961000C914BD</string>
<string>1C37FABC05509CD000000102</string>
<string>1C37FABC05539CD112110102</string>
<string>E2644B35053B69B200211256</string>
@@ -282,13 +279,11 @@
<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
<array>
<array>
<integer>7</integer>
<integer>1</integer>
<integer>0</integer>
</array>
</array>
<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
<string>{{0, 0}, {246, 509}}</string>
<string>{{0, 0}, {246, 873}}</string>
</dict>
<key>PBXTopSmartGroupGIDs</key>
<array/>
@@ -300,7 +295,7 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{0, 0}, {263, 527}}</string>
<string>{{0, 0}, {263, 891}}</string>
<key>GroupTreeTableConfiguration</key>
<array>
<string>SCMStatusColumn</string>
@@ -309,7 +304,7 @@
<real>224</real>
</array>
<key>RubberWindowFrame</key>
<string>75 119 1212 568 0 0 1920 1178 </string>
<string>259 191 1361 932 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>PBXSmartGroupTreeModule</string>
@@ -325,7 +320,7 @@
<key>PBXProjectModuleGUID</key>
<string>1CE0B20306471E060097A5F4</string>
<key>PBXProjectModuleLabel</key>
<string>File.h</string>
<string>profuse_xattr.cpp</string>
<key>PBXSplitModuleInNavigatorKey</key>
<dict>
<key>Split0</key>
@@ -333,11 +328,11 @@
<key>PBXProjectModuleGUID</key>
<string>1CE0B20406471E060097A5F4</string>
<key>PBXProjectModuleLabel</key>
<string>File.h</string>
<string>profuse_xattr.cpp</string>
<key>_historyCapacity</key>
<integer>0</integer>
<key>bookmark</key>
<string>B64E30810F2C0D2F000543FE</string>
<string>B67F09B01057622100A13214</string>
<key>history</key>
<array>
<string>B6B767C80F0FFA3900D819C9</string>
@@ -347,36 +342,17 @@
<string>B6C786EE0F2A612600053681</string>
<string>B6C786EF0F2A612600053681</string>
<string>B6C786F70F2A64CC00053681</string>
<string>B6C786F80F2A64CC00053681</string>
<string>B6C786F90F2A64CC00053681</string>
<string>B6C786FA0F2A64CC00053681</string>
<string>B6F4740F0F2ACB4700CB75DA</string>
<string>B6E345420F2BB60B00B7FC78</string>
<string>B6E345610F2BC07F00B7FC78</string>
<string>B64E307D0F2C0D2F000543FE</string>
<string>B64E307E0F2C0D2F000543FE</string>
<string>B6614B050EFF5F280073C4E7</string>
</array>
<key>prevStack</key>
<array>
<string>B60E917F0EFD7E1E000E4348</string>
<string>B60E91800EFD7E1E000E4348</string>
<string>B60E91810EFD7E1E000E4348</string>
<string>B60E922B0EFD94CA000E4348</string>
<string>B60E929C0EFDA500000E4348</string>
<string>B679E4BB0F02EFA200FB3F0C</string>
<string>B6B767CB0F0FFA3900D819C9</string>
<string>B6B17F950F1136550060F7AA</string>
<string>B6B17FA80F1140160060F7AA</string>
<string>B6B7A8600F140BBB001024D2</string>
<string>B6C786E90F2A5FF300053681</string>
<string>B6C786EA0F2A5FF300053681</string>
<string>B6C786F20F2A612600053681</string>
<string>B6C786F30F2A612600053681</string>
<string>B6C786FD0F2A64CC00053681</string>
<string>B6F474110F2ACB4700CB75DA</string>
<string>B64E307F0F2C0D2F000543FE</string>
<string>B64E30800F2C0D2F000543FE</string>
<string>B64E309A0F2CD8F2000543FE</string>
<string>B6DA6C190FA6AFE90027FC1D</string>
<string>B67F09AC1057622100A13214</string>
<string>B67F09AD1057622100A13214</string>
<string>B67F09AE1057622100A13214</string>
<string>B67F09AF1057622100A13214</string>
</array>
</dict>
<key>SplitCount</key>
@@ -388,14 +364,14 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{0, 0}, {944, 349}}</string>
<string>{{0, 0}, {1093, 705}}</string>
<key>RubberWindowFrame</key>
<string>75 119 1212 568 0 0 1920 1178 </string>
<string>259 191 1361 932 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>PBXNavigatorGroup</string>
<key>Proportion</key>
<string>349pt</string>
<string>705pt</string>
</dict>
<dict>
<key>ContentConfiguration</key>
@@ -408,18 +384,18 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{0, 354}, {944, 173}}</string>
<string>{{0, 710}, {1093, 181}}</string>
<key>RubberWindowFrame</key>
<string>75 119 1212 568 0 0 1920 1178 </string>
<string>259 191 1361 932 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>XCDetailModule</string>
<key>Proportion</key>
<string>173pt</string>
<string>181pt</string>
</dict>
</array>
<key>Proportion</key>
<string>944pt</string>
<string>1093pt</string>
</dict>
</array>
<key>Name</key>
@@ -434,12 +410,14 @@
</array>
<key>TableOfContents</key>
<array>
<string>B64E30820F2C0D2F000543FE</string>
<string>B67F097610575F0E00A13214</string>
<string>1CE0B1FE06471DED0097A5F4</string>
<string>B64E30830F2C0D2F000543FE</string>
<string>B67F097710575F0E00A13214</string>
<string>1CE0B20306471E060097A5F4</string>
<string>1CE0B20506471E060097A5F4</string>
</array>
<key>ToolbarConfigUserDefaultsMinorVersion</key>
<string>2</string>
<key>ToolbarConfiguration</key>
<string>xcode.toolbar.config.defaultV3</string>
</dict>
@@ -570,11 +548,13 @@
<integer>5</integer>
<key>WindowOrderList</key>
<array>
<string>1CD10A99069EF8BA00B06720</string>
<string>B67F09B71057622100A13214</string>
<string>B60E918C0EFD7E1E000E4348</string>
<string>/Users/kelvin/Projects/profuse/profuse.xcodeproj</string>
<string>B64E30840F2C0D2F000543FE</string>
</array>
<key>WindowString</key>
<string>75 119 1212 568 0 0 1920 1178 </string>
<string>259 191 1361 932 0 0 1920 1178 </string>
<key>WindowToolsV3</key>
<array>
<dict>
@@ -590,8 +570,6 @@
<key>Dock</key>
<array>
<dict>
<key>BecomeActive</key>
<true/>
<key>ContentConfiguration</key>
<dict>
<key>PBXProjectModuleGUID</key>
@@ -606,7 +584,7 @@
<key>Frame</key>
<string>{{0, 0}, {857, 500}}</string>
<key>RubberWindowFrame</key>
<string>621 136 857 922 0 0 1920 1178 </string>
<string>925 143 857 922 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>PBXNavigatorGroup</string>
@@ -614,14 +592,14 @@
<string>500pt</string>
</dict>
<dict>
<key>BecomeActive</key>
<true/>
<key>ContentConfiguration</key>
<dict>
<key>PBXBuildLogShowsTranscriptDefaultKey</key>
<string>{{0, 5}, {857, 371}}</string>
<key>PBXProjectModuleGUID</key>
<string>XCMainBuildResultsModuleGUID</string>
<key>PBXProjectModuleLabel</key>
<string>Build</string>
<string>Build Results</string>
<key>XCBuildResultsTrigger_Collapse</key>
<integer>1021</integer>
<key>XCBuildResultsTrigger_Open</key>
@@ -632,7 +610,7 @@
<key>Frame</key>
<string>{{0, 505}, {857, 376}}</string>
<key>RubberWindowFrame</key>
<string>621 136 857 922 0 0 1920 1178 </string>
<string>925 143 857 922 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>PBXBuildResultsModule</string>
@@ -655,18 +633,18 @@
<key>TableOfContents</key>
<array>
<string>B60E918C0EFD7E1E000E4348</string>
<string>B64E30630F2C08EF000543FE</string>
<string>B67F097410575F0600A13214</string>
<string>1CD0528F0623707200166675</string>
<string>XCMainBuildResultsModuleGUID</string>
</array>
<key>ToolbarConfiguration</key>
<string>xcode.toolbar.config.buildV3</string>
<key>WindowString</key>
<string>621 136 857 922 0 0 1920 1178 </string>
<string>925 143 857 922 0 0 1920 1178 </string>
<key>WindowToolGUID</key>
<string>B60E918C0EFD7E1E000E4348</string>
<key>WindowToolIsVisible</key>
<false/>
<true/>
</dict>
<dict>
<key>FirstTimeWindowDisplayed</key>
@@ -775,13 +753,13 @@
<key>TableOfContents</key>
<array>
<string>1CD10A99069EF8BA00B06720</string>
<string>B64E30640F2C08EF000543FE</string>
<string>B67F09B11057622100A13214</string>
<string>1C162984064C10D400B95A72</string>
<string>B64E30650F2C08EF000543FE</string>
<string>B64E30660F2C08EF000543FE</string>
<string>B64E30670F2C08EF000543FE</string>
<string>B64E30680F2C08EF000543FE</string>
<string>B64E30690F2C08EF000543FE</string>
<string>B67F09B21057622100A13214</string>
<string>B67F09B31057622100A13214</string>
<string>B67F09B41057622100A13214</string>
<string>B67F09B51057622100A13214</string>
<string>B67F09B61057622100A13214</string>
</array>
<key>ToolbarConfiguration</key>
<string>xcode.toolbar.config.debugV3</string>
@@ -1007,7 +985,7 @@
<key>PBXProjectModuleGUID</key>
<string>1C78EAB2065D492600B07095</string>
<key>PBXProjectModuleLabel</key>
<string>File.cpp</string>
<string>profuse_xattr.cpp</string>
<key>StatusBarVisibility</key>
<true/>
</dict>
@@ -1084,7 +1062,7 @@
<key>TableOfContents</key>
<array>
<string>B60E929F0EFDA500000E4348</string>
<string>B6E345600F2BC07D00B7FC78</string>
<string>B6472E660FB732A400DFAB7C</string>
<string>1C78EAB2065D492600B07095</string>
<string>1CD052920623707200166675</string>
</array>

View File

@@ -2,15 +2,15 @@
{
08FB7793FE84155DC02AAC07 /* Project object */ = {
activeArchitecturePreference = i386;
activeBuildConfigurationName = "Debug Universal 10.4";
activeBuildConfigurationName = "Debug Universal";
activeExecutable = B60E914A0EFB3612000E4348 /* profuse */;
activeSDKPreference = macosx10.6;
activeTarget = 8DD76F620486A84900D96B5E /* profuse */;
addToTargets = (
8DD76F620486A84900D96B5E /* profuse */,
);
breakpoints = (
B60E91C10EFD8049000E4348 /* xmain.cpp:129 */,
B60E92720EFDA086000E4348 /* File.cpp:74 */,
B6D81E5B0EFDE859000219B7 /* xmain.cpp:163 */,
B6AE1CFF0F0335FC00D36ADB /* main.cpp:20 */,
);
@@ -39,7 +39,7 @@
PBXFileTableDataSourceColumnWidthsKey = (
22,
300,
593,
583,
);
PBXFileTableDataSourceColumnsKey = (
PBXExecutablesDataSource_ActiveFlagID,
@@ -52,7 +52,7 @@
PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
PBXFileTableDataSourceColumnWidthsKey = (
20,
705,
695,
20,
48,
43,
@@ -75,7 +75,7 @@
PBXFileTableDataSourceColumnWidthsKey = (
20,
20,
681,
830,
20,
48,
43,
@@ -98,7 +98,7 @@
PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
PBXFileTableDataSourceColumnWidthsKey = (
20,
665,
655,
60,
20,
48,
@@ -115,49 +115,27 @@
PBXFileDataSource_Warnings_ColumnID,
);
};
PBXPerProjectTemplateStateSaveDate = 254545182;
PBXWorkspaceStateSaveDate = 254545182;
PBXPerProjectTemplateStateSaveDate = 320562725;
PBXWorkspaceStateSaveDate = 320562725;
};
perUserProjectItems = {
B60E917F0EFD7E1E000E4348 = B60E917F0EFD7E1E000E4348 /* PBXTextBookmark */;
B60E91800EFD7E1E000E4348 = B60E91800EFD7E1E000E4348 /* PBXTextBookmark */;
B60E91810EFD7E1E000E4348 = B60E91810EFD7E1E000E4348 /* PBXTextBookmark */;
B60E922B0EFD94CA000E4348 = B60E922B0EFD94CA000E4348 /* PBXTextBookmark */;
B60E929C0EFDA500000E4348 = B60E929C0EFDA500000E4348 /* PBXTextBookmark */;
B642F1540F133632001F7696 = B642F1540F133632001F7696 /* PBXTextBookmark */;
B642F16A0F1341D4001F7696 = B642F16A0F1341D4001F7696 /* PBXTextBookmark */;
B64E306A0F2C08F3000543FE = B64E306A0F2C08F3000543FE /* PBXTextBookmark */;
B64E306B0F2C08F3000543FE = B64E306B0F2C08F3000543FE /* PBXTextBookmark */;
B64E306C0F2C08F3000543FE = B64E306C0F2C08F3000543FE /* PBXTextBookmark */;
B64E306F0F2C0900000543FE = B64E306F0F2C0900000543FE /* PBXTextBookmark */;
B64E307D0F2C0D2F000543FE /* PBXTextBookmark */ = B64E307D0F2C0D2F000543FE /* PBXTextBookmark */;
B64E307E0F2C0D2F000543FE /* PBXTextBookmark */ = B64E307E0F2C0D2F000543FE /* PBXTextBookmark */;
B64E307F0F2C0D2F000543FE /* PBXTextBookmark */ = B64E307F0F2C0D2F000543FE /* PBXTextBookmark */;
B64E30800F2C0D2F000543FE /* PBXTextBookmark */ = B64E30800F2C0D2F000543FE /* PBXTextBookmark */;
B64E30810F2C0D2F000543FE /* PBXTextBookmark */ = B64E30810F2C0D2F000543FE /* PBXTextBookmark */;
B6614B050EFF5F280073C4E7 = B6614B050EFF5F280073C4E7 /* PBXTextBookmark */;
B679E4BB0F02EFA200FB3F0C = B679E4BB0F02EFA200FB3F0C /* PBXTextBookmark */;
B6B17F950F1136550060F7AA = B6B17F950F1136550060F7AA /* PBXTextBookmark */;
B6B17FA80F1140160060F7AA = B6B17FA80F1140160060F7AA /* PBXTextBookmark */;
B6B767C80F0FFA3900D819C9 = B6B767C80F0FFA3900D819C9 /* PBXTextBookmark */;
B6B767CB0F0FFA3900D819C9 = B6B767CB0F0FFA3900D819C9 /* PBXTextBookmark */;
B6B7A8600F140BBB001024D2 = B6B7A8600F140BBB001024D2 /* PBXTextBookmark */;
B6C786E50F2A5FF300053681 = B6C786E50F2A5FF300053681 /* PBXTextBookmark */;
B6C786E90F2A5FF300053681 = B6C786E90F2A5FF300053681 /* PBXTextBookmark */;
B6C786EA0F2A5FF300053681 = B6C786EA0F2A5FF300053681 /* PBXTextBookmark */;
B6C786EE0F2A612600053681 = B6C786EE0F2A612600053681 /* PBXTextBookmark */;
B6C786EF0F2A612600053681 = B6C786EF0F2A612600053681 /* PBXTextBookmark */;
B6C786F20F2A612600053681 = B6C786F20F2A612600053681 /* PBXTextBookmark */;
B6C786F30F2A612600053681 = B6C786F30F2A612600053681 /* PBXTextBookmark */;
B6C786F70F2A64CC00053681 = B6C786F70F2A64CC00053681 /* PBXTextBookmark */;
B6C786F80F2A64CC00053681 = B6C786F80F2A64CC00053681 /* PBXTextBookmark */;
B6C786F90F2A64CC00053681 = B6C786F90F2A64CC00053681 /* PBXTextBookmark */;
B6C786FA0F2A64CC00053681 = B6C786FA0F2A64CC00053681 /* PBXTextBookmark */;
B6C786FD0F2A64CC00053681 = B6C786FD0F2A64CC00053681 /* PBXTextBookmark */;
B6E345420F2BB60B00B7FC78 = B6E345420F2BB60B00B7FC78 /* PBXTextBookmark */;
B6E345610F2BC07F00B7FC78 = B6E345610F2BC07F00B7FC78 /* PBXTextBookmark */;
B6F4740F0F2ACB4700CB75DA = B6F4740F0F2ACB4700CB75DA /* PBXTextBookmark */;
B6F474110F2ACB4700CB75DA = B6F474110F2ACB4700CB75DA /* PBXTextBookmark */;
B61BCF86131B6627002DE159 /* PBXTextBookmark */ = B61BCF86131B6627002DE159 /* PBXTextBookmark */;
B61BCF96131B6643002DE159 /* PBXTextBookmark */ = B61BCF96131B6643002DE159 /* PBXTextBookmark */;
B61BCF97131B6643002DE159 /* PBXBookmark */ = B61BCF97131B6643002DE159 /* PBXBookmark */;
B61BCF98131B6643002DE159 /* PBXTextBookmark */ = B61BCF98131B6643002DE159 /* PBXTextBookmark */;
B61BCFA3131B6741002DE159 /* PBXTextBookmark */ = B61BCFA3131B6741002DE159 /* PBXTextBookmark */;
B61BCFA4131B6741002DE159 /* XCBuildMessageTextBookmark */ = B61BCFA4131B6741002DE159 /* XCBuildMessageTextBookmark */;
B61BCFA5131B6741002DE159 /* PBXTextBookmark */ = B61BCFA5131B6741002DE159 /* PBXTextBookmark */;
B6A53BB3131A17AF00C9070F = B6A53BB3131A17AF00C9070F /* PBXTextBookmark */;
B6A53BE3131B434600C9070F = B6A53BE3131B434600C9070F /* PBXTextBookmark */;
B6A53BE4131B434600C9070F = B6A53BE4131B434600C9070F /* PBXTextBookmark */;
B6A53C48131B634600C9070F = B6A53C48131B634600C9070F /* PBXTextBookmark */;
B6A53C49131B634600C9070F = B6A53C49131B634600C9070F /* PBXTextBookmark */;
B6A53C4A131B634600C9070F = B6A53C4A131B634600C9070F /* PBXTextBookmark */;
B6A53C4B131B634600C9070F = B6A53C4B131B634600C9070F /* PBXTextBookmark */;
B6A53C4C131B634600C9070F = B6A53C4C131B634600C9070F /* PBXTextBookmark */;
B6A53C4D131B634600C9070F = B6A53C4D131B634600C9070F /* PBXTextBookmark */;
B6A53C4E131B634600C9070F = B6A53C4E131B634600C9070F /* PBXTextBookmark */;
};
sourceControlManager = B60E91500EFB3628000E4348 /* Source Control */;
userBuildSettings = {
@@ -188,6 +166,9 @@
configStateDict = {
};
customDataFormattersEnabled = 1;
dataTipCustomDataFormattersEnabled = 1;
dataTipShowTypeColumn = 1;
dataTipSortType = 0;
debuggerPlugin = GDBDebugging;
disassemblyDisplayState = 0;
dylibVariantSuffix = "";
@@ -200,6 +181,7 @@
name = profuse;
savedGlobals = {
};
showTypeColumn = 0;
sourceDirectories = (
);
variableFormatDictionary = {
@@ -208,28 +190,15 @@
"xcase-unsigned int-FileEntry::FileEntry" = 3;
};
};
B60E914D0EFB3627000E4348 /* File.h */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {883, 1792}}";
sepNavSelRange = "{414, 0}";
sepNavVisRange = "{1197, 440}";
sepNavWindowFrame = "{{95, -86}, {555, 1173}}";
};
};
B60E914E0EFB3628000E4348 /* File.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {883, 3682}}";
sepNavSelRange = "{3323, 0}";
sepNavVisRange = "{1285, 523}";
sepNavWindowFrame = "{{667, -9}, {555, 1173}}";
};
};
B60E91500EFB3628000E4348 /* Source Control */ = {
isa = PBXSourceControlManager;
fallbackIsa = XCSourceControlManager;
isSCMEnabled = 0;
scmConfiguration = {
repositoryName = profuse.googlecode.com;
repositoryNamesForRoots = {
"" = profuse.googlecode.com;
};
};
};
B60E91510EFB3628000E4348 /* Code sense */ = {
@@ -238,17 +207,17 @@
};
B60E91530EFB51FE000E4348 /* Disk.h */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1250, 1092}}";
sepNavSelRange = "{1300, 0}";
sepNavVisRange = "{178, 1128}";
sepNavIntBoundsRect = "{{0, 0}, {1245, 1092}}";
sepNavSelRange = "{1156, 11}";
sepNavVisRange = "{76, 1374}";
sepNavWindowFrame = "{{77, 7}, {692, 1171}}";
};
};
B60E91540EFB51FE000E4348 /* Disk.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {883, 8652}}";
sepNavSelRange = "{5288, 0}";
sepNavVisRange = "{5127, 457}";
sepNavIntBoundsRect = "{{0, 0}, {1032, 8414}}";
sepNavSelRange = "{5390, 0}";
sepNavVisRange = "{4914, 1006}";
sepNavWindowFrame = "{{943, -6}, {692, 1171}}";
};
};
@@ -260,36 +229,6 @@
sepNavWindowFrame = "{{15, 2}, {692, 1171}}";
};
};
B60E917F0EFD7E1E000E4348 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B60E914D0EFB3627000E4348 /* File.h */;
name = "File.h: 1";
rLen = 0;
rLoc = 0;
rType = 0;
vrLen = 350;
vrLoc = 0;
};
B60E91800EFD7E1E000E4348 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B60E91530EFB51FE000E4348 /* Disk.h */;
name = "Disk.h: 1";
rLen = 0;
rLoc = 0;
rType = 0;
vrLen = 159;
vrLoc = 0;
};
B60E91810EFD7E1E000E4348 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B60E91540EFB51FE000E4348 /* Disk.cpp */;
name = "Disk.cpp: 1";
rLen = 0;
rLoc = 0;
rType = 0;
vrLen = 292;
vrLoc = 0;
};
B60E91C10EFD8049000E4348 /* xmain.cpp:129 */ = {
isa = PBXFileBreakpoint;
actions = (
@@ -305,197 +244,201 @@
lineNumber = 129;
location = "ProDOS-Fuse";
modificationTime = 251949619.113675;
originalNumberOfMultipleMatches = 0;
state = 2;
};
B60E922B0EFD94CA000E4348 /* PBXTextBookmark */ = {
B61BCF86131B6627002DE159 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B60E91580EFD77E3000E4348 /* common.h */;
name = "common.h: 14";
rLen = 0;
rLoc = 146;
fRef = B6DA7037131047D100E42AA6 /* DiskCopy42Image.cpp */;
name = "DiskCopy42Image.cpp: 49";
rLen = 12;
rLoc = 763;
rType = 0;
vrLen = 327;
vrLoc = 0;
vrLen = 851;
vrLoc = 395;
};
B60E92720EFDA086000E4348 /* File.cpp:74 */ = {
isa = PBXFileBreakpoint;
actions = (
);
breakpointStyle = 0;
continueAfterActions = 0;
countType = 0;
delayBeforeContinue = 0;
fileReference = B60E914E0EFB3628000E4348 /* File.cpp */;
functionName = "FileEntry::FileEntry(const void *data)";
hitCount = 0;
ignoreCount = 0;
lineNumber = 74;
location = "ProDOS-Fuse";
modificationTime = 251949619.113693;
state = 2;
};
B60E929C0EFDA500000E4348 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B60E914E0EFB3628000E4348 /* File.cpp */;
name = "File.cpp: 106";
rLen = 0;
rLoc = 3323;
rType = 0;
vrLen = 345;
vrLoc = 1359;
};
B642F1290F132FA3001F7696 /* UniversalDiskImage.h */ = {
B61BCF8F131B6633002DE159 /* smart_pointers.h */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1250, 831}}";
sepNavSelRange = "{217, 34}";
sepNavVisRange = "{0, 708}";
sepNavWindowFrame = "{{15, 249}, {1412, 924}}";
sepNavIntBoundsRect = "{{0, 0}, {873, 521}}";
sepNavSelRange = "{0, 0}";
sepNavVisRange = "{0, 903}";
};
};
B642F12A0F132FA3001F7696 /* UniversalDiskImage.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1250, 831}}";
sepNavSelRange = "{820, 0}";
sepNavVisRange = "{0, 966}";
sepNavWindowFrame = "{{668, 219}, {1412, 924}}";
};
};
B642F1540F133632001F7696 /* PBXTextBookmark */ = {
B61BCF96131B6643002DE159 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6B17FA00F1138830060F7AA /* DiskCopy42.h */;
name = "DiskCopy42.h: 1";
fRef = B6DA7037131047D100E42AA6 /* DiskCopy42Image.cpp */;
name = "DiskCopy42Image.cpp: 49";
rLen = 12;
rLoc = 763;
rType = 0;
vrLen = 851;
vrLoc = 395;
};
B61BCF97131B6643002DE159 /* PBXBookmark */ = {
isa = PBXBookmark;
fRef = B61BCF8F131B6633002DE159 /* smart_pointers.h */;
};
B61BCF98131B6643002DE159 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B61BCF8F131B6633002DE159 /* smart_pointers.h */;
name = "smart_pointers.h: 1";
rLen = 0;
rLoc = 0;
rType = 0;
vrLen = 355;
vrLen = 903;
vrLoc = 0;
};
B642F16A0F1341D4001F7696 /* PBXTextBookmark */ = {
B61BCFA3131B6741002DE159 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B60E91580EFD77E3000E4348 /* common.h */;
name = "common.h: 40";
fRef = B61BCF8F131B6633002DE159 /* smart_pointers.h */;
name = "smart_pointers.h: 1";
rLen = 0;
rLoc = 627;
rLoc = 0;
rType = 0;
vrLen = 313;
vrLen = 903;
vrLoc = 0;
};
B64E306A0F2C08F3000543FE /* PBXTextBookmark */ = {
B61BCFA4131B6741002DE159 /* XCBuildMessageTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B60E914E0EFB3628000E4348 /* File.cpp */;
name = "File.cpp: 176";
rLen = 0;
rLoc = 3323;
rType = 0;
vrLen = 532;
vrLoc = 1287;
};
B64E306B0F2C08F3000543FE /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
comments = "error: 'DATA_FORK' was not declared in this scope";
fRef = B60E91540EFB51FE000E4348 /* Disk.cpp */;
comments = "No matching function for call to 'std::tr1::shared_ptr<Device::BlockDevice>::reset(Device::BlockDevicePointer)'";
fRef = B679E4A70F02E79300FB3F0C /* main.cpp */;
fallbackIsa = XCBuildMessageTextBookmark;
rLen = 1;
rLoc = 239;
rLoc = 264;
rType = 1;
};
B64E306C0F2C08F3000543FE /* PBXTextBookmark */ = {
B61BCFA5131B6741002DE159 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B60E914E0EFB3628000E4348 /* File.cpp */;
name = "File.cpp: 176";
fRef = B679E4A70F02E79300FB3F0C /* main.cpp */;
name = "main.cpp: 275";
rLen = 0;
rLoc = 3323;
rLoc = 5894;
rType = 0;
vrLen = 532;
vrLoc = 1287;
vrLen = 1313;
vrLoc = 1695;
};
B64E306F0F2C0900000543FE /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B60E91540EFB51FE000E4348 /* Disk.cpp */;
name = "Disk.cpp: 240";
rLen = 0;
rLoc = 5288;
rType = 0;
vrLen = 457;
vrLoc = 5127;
B650C2C3131090D200046FAD /* File.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1245, 2990}}";
sepNavSelRange = "{0, 0}";
sepNavVisRange = "{1306, 1844}";
};
};
B64E307D0F2C0D2F000543FE /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B60E91540EFB51FE000E4348 /* Disk.cpp */;
name = "Disk.cpp: 240";
rLen = 0;
rLoc = 5288;
rType = 0;
vrLen = 457;
vrLoc = 5127;
};
B64E307E0F2C0D2F000543FE /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B60E914E0EFB3628000E4348 /* File.cpp */;
name = "File.cpp: 156";
rLen = 0;
rLoc = 3323;
rType = 0;
vrLen = 523;
vrLoc = 1285;
};
B64E307F0F2C0D2F000543FE /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B60E91540EFB51FE000E4348 /* Disk.cpp */;
name = "Disk.cpp: 240";
rLen = 0;
rLoc = 5288;
rType = 0;
vrLen = 457;
vrLoc = 5127;
};
B64E30800F2C0D2F000543FE /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B60E914E0EFB3628000E4348 /* File.cpp */;
name = "File.cpp: 156";
rLen = 0;
rLoc = 3323;
rType = 0;
vrLen = 523;
vrLoc = 1285;
};
B64E30810F2C0D2F000543FE /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B60E914D0EFB3627000E4348 /* File.h */;
name = "File.h: 30";
rLen = 0;
rLoc = 414;
rType = 0;
vrLen = 440;
vrLoc = 1197;
};
B6614B050EFF5F280073C4E7 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B60E914D0EFB3627000E4348 /* File.h */;
name = "File.h: 31";
rLen = 0;
rLoc = 414;
rType = 0;
vrLen = 330;
vrLoc = 1231;
B650C2C4131090D200046FAD /* File.h */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1245, 1742}}";
sepNavSelRange = "{1591, 0}";
sepNavVisRange = "{864, 1333}";
};
};
B679E4A70F02E79300FB3F0C /* main.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {759, 3948}}";
sepNavSelRange = "{1950, 0}";
sepNavVisRange = "{3049, 226}";
sepNavIntBoundsRect = "{{0, 0}, {873, 4888}}";
sepNavSelRange = "{5894, 0}";
sepNavVisRange = "{1695, 1313}";
sepNavWindowFrame = "{{342, 156}, {1412, 924}}";
};
};
B679E4BB0F02EFA200FB3F0C /* PBXTextBookmark */ = {
B6A53BB3131A17AF00C9070F /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B679E4A70F02E79300FB3F0C /* main.cpp */;
name = "main.cpp: 1";
name = "main.cpp: 253";
rLen = 11;
rLoc = 4534;
rType = 0;
vrLen = 241;
vrLoc = 4525;
};
B6A53BE3131B434600C9070F /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B60E91530EFB51FE000E4348 /* Disk.h */;
name = "Disk.h: 70";
rLen = 0;
rLoc = 1300;
rType = 0;
vrLen = 269;
vrLoc = 1042;
};
B6A53BE4131B434600C9070F /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6C786B40F2A59FE00053681 /* profuse_xattr.cpp */;
name = "profuse_xattr.cpp: 56";
rLen = 5;
rLoc = 1034;
rType = 0;
vrLen = 1279;
vrLoc = 998;
};
B6A53C48131B634600C9070F /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6C786BF0F2A5CC000053681 /* profuse_stat.cpp */;
name = "profuse_stat.cpp: 167";
rLen = 0;
rLoc = 3263;
rType = 0;
vrLen = 1000;
vrLoc = 2706;
};
B6A53C49131B634600C9070F /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6DA703E131047D100E42AA6 /* UniversalDiskImage.cpp */;
name = "UniversalDiskImage.cpp: 1";
rLen = 0;
rLoc = 0;
rType = 0;
vrLen = 356;
vrLen = 807;
vrLoc = 0;
};
B6A53C4A131B634600C9070F /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6DA7035131047D100E42AA6 /* DavexDiskImage.cpp */;
name = "DavexDiskImage.cpp: 56";
rLen = 12;
rLoc = 1104;
rType = 0;
vrLen = 856;
vrLoc = 684;
};
B6A53C4B131B634600C9070F /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6DA703A131047D100E42AA6 /* DiskImage.h */;
name = "DiskImage.h: 1";
rLen = 0;
rLoc = 0;
rType = 0;
vrLen = 756;
vrLoc = 0;
};
B6A53C4C131B634600C9070F /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6DA7038131047D100E42AA6 /* DiskCopy42Image.h */;
name = "DiskCopy42Image.h: 1";
rLen = 0;
rLoc = 0;
rType = 0;
vrLen = 778;
vrLoc = 0;
};
B6A53C4D131B634600C9070F /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6DA7037131047D100E42AA6 /* DiskCopy42Image.cpp */;
name = "DiskCopy42Image.cpp: 49";
rLen = 12;
rLoc = 763;
rType = 0;
vrLen = 851;
vrLoc = 395;
};
B6A53C4E131B634600C9070F /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6DA7037131047D100E42AA6 /* DiskCopy42Image.cpp */;
name = "DiskCopy42Image.cpp: 49";
rLen = 12;
rLoc = 763;
rType = 0;
vrLen = 851;
vrLoc = 395;
};
B6AE1CFF0F0335FC00D36ADB /* main.cpp:20 */ = {
isa = PBXFileBreakpoint;
actions = (
@@ -511,236 +454,44 @@
lineNumber = 20;
location = "ProDOS-Fuse";
modificationTime = 251949619.113812;
originalNumberOfMultipleMatches = 0;
state = 2;
};
B6B17F820F103AA70060F7AA /* fuse_common.h */ = {
isa = PBXFileReference;
lastKnownFileType = sourcecode.c.h;
name = fuse_common.h;
path = /usr/local/include/fuse/fuse_common.h;
sourceTree = "<absolute>";
};
B6B17F950F1136550060F7AA /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6B17F820F103AA70060F7AA /* fuse_common.h */;
name = "fuse_common.h: 36";
rLen = 0;
rLoc = 921;
rType = 0;
vrLen = 579;
vrLoc = 535;
};
B6B17FA00F1138830060F7AA /* DiskCopy42.h */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1353, 796}}";
sepNavSelRange = "{226, 0}";
sepNavVisRange = "{0, 434}";
sepNavWindowFrame = "{{310, 58}, {1412, 924}}";
};
};
B6B17FA10F1138830060F7AA /* DiskCopy42.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {883, 616}}";
sepNavSelRange = "{150, 0}";
sepNavVisRange = "{0, 333}";
sepNavWindowFrame = "{{299, 31}, {1412, 924}}";
};
};
B6B17FA80F1140160060F7AA /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6B17FA00F1138830060F7AA /* DiskCopy42.h */;
name = "DiskCopy42.h: 1";
rLen = 0;
rLoc = 0;
rType = 0;
vrLen = 374;
vrLoc = 0;
};
B6B767C80F0FFA3900D819C9 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6DBB4E70F0C6BBD00F385F2 /* profuse.1 */;
name = "profuse.1: 10";
rLen = 0;
rLoc = 429;
rType = 0;
vrLen = 722;
vrLoc = 2400;
};
B6B767CB0F0FFA3900D819C9 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6DBB4E70F0C6BBD00F385F2 /* profuse.1 */;
name = "profuse.1: 10";
rLen = 0;
rLoc = 429;
rType = 0;
vrLen = 722;
vrLoc = 2400;
};
B6B7A8600F140BBB001024D2 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6B17FA10F1138830060F7AA /* DiskCopy42.cpp */;
name = "DiskCopy42.cpp: 11";
rLen = 0;
rLoc = 150;
rType = 0;
vrLen = 333;
vrLoc = 0;
};
B6C786B30F2A59AF00053681 /* profuse.h */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {796, 728}}";
sepNavSelRange = "{1382, 0}";
sepNavVisRange = "{243, 1139}";
sepNavIntBoundsRect = "{{0, 0}, {1245, 1011}}";
sepNavSelRange = "{1165, 0}";
sepNavVisRange = "{0, 1449}";
};
};
B6C786B40F2A59FE00053681 /* profuse_xattr.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1250, 5138}}";
sepNavSelRange = "{3730, 0}";
sepNavVisRange = "{3045, 1256}";
sepNavIntBoundsRect = "{{0, 0}, {873, 7371}}";
sepNavSelRange = "{1034, 5}";
sepNavVisRange = "{998, 1279}";
};
};
B6C786BB0F2A5C0800053681 /* profuse_dirent.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {796, 1792}}";
sepNavSelRange = "{974, 0}";
sepNavVisRange = "{1797, 951}";
sepNavIntBoundsRect = "{{0, 0}, {1198, 1781}}";
sepNavSelRange = "{1946, 0}";
sepNavVisRange = "{756, 1661}";
};
};
B6C786BF0F2A5CC000053681 /* profuse_stat.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1250, 3038}}";
sepNavSelRange = "{3676, 0}";
sepNavVisRange = "{3020, 1612}";
sepNavIntBoundsRect = "{{0, 0}, {1245, 3146}}";
sepNavSelRange = "{5137, 0}";
sepNavVisRange = "{3413, 2039}";
};
};
B6C786C30F2A5DCE00053681 /* profuse_file.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {796, 1988}}";
sepNavSelRange = "{502, 0}";
sepNavVisRange = "{1178, 692}";
sepNavIntBoundsRect = "{{0, 0}, {1198, 1781}}";
sepNavSelRange = "{1753, 0}";
sepNavVisRange = "{1323, 1590}";
};
};
B6C786E50F2A5FF300053681 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B679E4A70F02E79300FB3F0C /* main.cpp */;
name = "main.cpp: 33";
rLen = 0;
rLoc = 323;
rType = 0;
vrLen = 330;
vrLoc = 441;
};
B6C786E90F2A5FF300053681 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6C786B30F2A59AF00053681 /* profuse.h */;
name = "profuse.h: 15";
rLen = 0;
rLoc = 592;
rType = 0;
vrLen = 176;
vrLoc = 0;
};
B6C786EA0F2A5FF300053681 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6C786B40F2A59FE00053681 /* profuse_xattr.cpp */;
name = "profuse_xattr.cpp: 1";
rLen = 0;
rLoc = 0;
rType = 0;
vrLen = 360;
vrLoc = 0;
};
B6C786EE0F2A612600053681 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6B17F820F103AA70060F7AA /* fuse_common.h */;
name = "fuse_common.h: 266";
rLen = 63;
rLoc = 6850;
rType = 0;
vrLen = 708;
vrLoc = 5837;
};
B6C786EF0F2A612600053681 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B642F12A0F132FA3001F7696 /* UniversalDiskImage.cpp */;
name = "UniversalDiskImage.cpp: 42";
rLen = 0;
rLoc = 820;
rType = 0;
vrLen = 463;
vrLoc = 500;
};
B6C786F20F2A612600053681 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B642F12A0F132FA3001F7696 /* UniversalDiskImage.cpp */;
name = "UniversalDiskImage.cpp: 42";
rLen = 0;
rLoc = 820;
rType = 0;
vrLen = 463;
vrLoc = 500;
};
B6C786F30F2A612600053681 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6C786C30F2A5DCE00053681 /* profuse_file.cpp */;
name = "profuse_file.cpp: 11";
rLen = 0;
rLoc = 132;
rType = 0;
vrLen = 365;
vrLoc = 0;
};
B6C786F70F2A64CC00053681 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6B17FA10F1138830060F7AA /* DiskCopy42.cpp */;
name = "DiskCopy42.cpp: 11";
rLen = 0;
rLoc = 150;
rType = 0;
vrLen = 333;
vrLoc = 0;
};
B6C786F80F2A64CC00053681 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6C786B40F2A59FE00053681 /* profuse_xattr.cpp */;
name = "profuse_xattr.cpp: 1";
rLen = 0;
rLoc = 0;
rType = 0;
vrLen = 371;
vrLoc = 3;
};
B6C786F90F2A64CC00053681 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6C786BF0F2A5CC000053681 /* profuse_stat.cpp */;
name = "profuse_stat.cpp: 15";
rLen = 0;
rLoc = 181;
rType = 0;
vrLen = 303;
vrLoc = 0;
};
B6C786FA0F2A64CC00053681 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6C786C30F2A5DCE00053681 /* profuse_file.cpp */;
name = "profuse_file.cpp: 11";
rLen = 0;
rLoc = 132;
rType = 0;
vrLen = 365;
vrLoc = 0;
};
B6C786FD0F2A64CC00053681 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6C786BF0F2A5CC000053681 /* profuse_stat.cpp */;
name = "profuse_stat.cpp: 15";
rLen = 0;
rLoc = 181;
rType = 0;
vrLen = 303;
vrLoc = 0;
};
B6D81E5B0EFDE859000219B7 /* xmain.cpp:163 */ = {
isa = PBXFileBreakpoint;
actions = (
@@ -756,8 +507,51 @@
lineNumber = 163;
location = "ProDOS-Fuse";
modificationTime = 251949619.113805;
originalNumberOfMultipleMatches = 0;
state = 2;
};
B6DA7035131047D100E42AA6 /* DavexDiskImage.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {873, 2210}}";
sepNavSelRange = "{1104, 12}";
sepNavVisRange = "{684, 856}";
};
};
B6DA7037131047D100E42AA6 /* DiskCopy42Image.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {873, 3094}}";
sepNavSelRange = "{763, 12}";
sepNavVisRange = "{395, 851}";
};
};
B6DA7038131047D100E42AA6 /* DiskCopy42Image.h */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {873, 529}}";
sepNavSelRange = "{0, 0}";
sepNavVisRange = "{0, 778}";
};
};
B6DA7039131047D100E42AA6 /* DiskImage.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1245, 2743}}";
sepNavSelRange = "{197, 0}";
sepNavVisRange = "{0, 1141}";
};
};
B6DA703A131047D100E42AA6 /* DiskImage.h */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1245, 1144}}";
sepNavSelRange = "{0, 0}";
sepNavVisRange = "{0, 1475}";
};
};
B6DA703E131047D100E42AA6 /* UniversalDiskImage.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1245, 2080}}";
sepNavSelRange = "{0, 0}";
sepNavVisRange = "{0, 1547}";
};
};
B6DBB4E70F0C6BBD00F385F2 /* profuse.1 */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {883, 1162}}";
@@ -766,44 +560,4 @@
sepNavWindowFrame = "{{15, 249}, {1412, 924}}";
};
};
B6E345420F2BB60B00B7FC78 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B60E91530EFB51FE000E4348 /* Disk.h */;
name = "Disk.h: 65";
rLen = 21;
rLoc = 1281;
rType = 0;
vrLen = 597;
vrLoc = 627;
};
B6E345610F2BC07F00B7FC78 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6C786B30F2A59AF00053681 /* profuse.h */;
name = "profuse.h: 48";
rLen = 0;
rLoc = 1372;
rType = 0;
vrLen = 973;
vrLoc = 409;
};
B6F4740F0F2ACB4700CB75DA /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6C786BB0F2A5C0800053681 /* profuse_dirent.cpp */;
name = "profuse_dirent.cpp: 16";
rLen = 0;
rLoc = 193;
rType = 0;
vrLen = 368;
vrLoc = 0;
};
B6F474110F2ACB4700CB75DA /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6C786BB0F2A5C0800053681 /* profuse_dirent.cpp */;
name = "profuse_dirent.cpp: 16";
rLen = 0;
rLoc = 193;
rType = 0;
vrLen = 368;
vrLoc = 0;
};
}

View File

@@ -7,15 +7,29 @@
objects = {
/* Begin PBXBuildFile section */
B60E914F0EFB3628000E4348 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B60E914E0EFB3628000E4348 /* File.cpp */; };
B60E91550EFB51FE000E4348 /* Disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B60E91540EFB51FE000E4348 /* Disk.cpp */; };
B642F12B0F132FA3001F7696 /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B642F12A0F132FA3001F7696 /* UniversalDiskImage.cpp */; };
B650C2C5131090D200046FAD /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650C2C3131090D200046FAD /* File.cpp */; };
B679E4A80F02E79300FB3F0C /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B679E4A70F02E79300FB3F0C /* main.cpp */; };
B6B17FA20F1138830060F7AA /* DiskCopy42.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6B17FA10F1138830060F7AA /* DiskCopy42.cpp */; };
B6C786B50F2A59FF00053681 /* profuse_xattr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6C786B40F2A59FE00053681 /* profuse_xattr.cpp */; };
B6C786BC0F2A5C0800053681 /* profuse_dirent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6C786BB0F2A5C0800053681 /* profuse_dirent.cpp */; };
B6C786C00F2A5CC000053681 /* profuse_stat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6C786BF0F2A5CC000053681 /* profuse_stat.cpp */; };
B6C786C40F2A5DCE00053681 /* profuse_file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6C786C30F2A5DCE00053681 /* profuse_file.cpp */; };
B6DA702D131047CA00E42AA6 /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DA7027131047CA00E42AA6 /* BlockCache.cpp */; };
B6DA702E131047CA00E42AA6 /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DA7029131047CA00E42AA6 /* ConcreteBlockCache.cpp */; };
B6DA702F131047CA00E42AA6 /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DA702B131047CA00E42AA6 /* MappedBlockCache.cpp */; };
B6DA7040131047D100E42AA6 /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DA7031131047D100E42AA6 /* Adaptor.cpp */; };
B6DA7041131047D100E42AA6 /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DA7033131047D100E42AA6 /* BlockDevice.cpp */; };
B6DA7042131047D100E42AA6 /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DA7035131047D100E42AA6 /* DavexDiskImage.cpp */; };
B6DA7043131047D100E42AA6 /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DA7037131047D100E42AA6 /* DiskCopy42Image.cpp */; };
B6DA7044131047D100E42AA6 /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DA7039131047D100E42AA6 /* DiskImage.cpp */; };
B6DA7045131047D100E42AA6 /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DA703B131047D100E42AA6 /* RawDevice.cpp */; };
B6DA7046131047D100E42AA6 /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DA703E131047D100E42AA6 /* UniversalDiskImage.cpp */; };
B6DA704C131047F400E42AA6 /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DA7048131047F400E42AA6 /* Endian.cpp */; };
B6DA7052131047FA00E42AA6 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DA704E131047FA00E42AA6 /* File.cpp */; };
B6DA7053131047FA00E42AA6 /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DA7050131047FA00E42AA6 /* MappedFile.cpp */; };
B6DA705A1310551500E42AA6 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DA70561310551500E42AA6 /* Exception.cpp */; };
B6DA705B1310551500E42AA6 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DA70581310551500E42AA6 /* Lock.cpp */; };
B6DA706E1310571B00E42AA6 /* DateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DA706B1310571B00E42AA6 /* DateTime.cpp */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -32,21 +46,55 @@
/* Begin PBXFileReference section */
8DD76F6C0486A84900D96B5E /* profuse */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = profuse; sourceTree = BUILT_PRODUCTS_DIR; };
B60E914D0EFB3627000E4348 /* File.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = File.h; sourceTree = "<group>"; };
B60E914E0EFB3628000E4348 /* File.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = File.cpp; sourceTree = "<group>"; };
B60E91530EFB51FE000E4348 /* Disk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Disk.h; sourceTree = "<group>"; };
B60E91540EFB51FE000E4348 /* Disk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Disk.cpp; sourceTree = "<group>"; };
B60E91580EFD77E3000E4348 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = "<group>"; };
B642F1290F132FA3001F7696 /* UniversalDiskImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UniversalDiskImage.h; sourceTree = "<group>"; };
B642F12A0F132FA3001F7696 /* UniversalDiskImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UniversalDiskImage.cpp; sourceTree = "<group>"; };
B61BCF8F131B6633002DE159 /* smart_pointers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = smart_pointers.h; sourceTree = "<group>"; };
B650C2C3131090D200046FAD /* File.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = File.cpp; sourceTree = "<group>"; };
B650C2C4131090D200046FAD /* File.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = File.h; sourceTree = "<group>"; };
B650C2C6131095C200046FAD /* Device.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Device.h; sourceTree = "<group>"; };
B679E4A70F02E79300FB3F0C /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
B6B17FA00F1138830060F7AA /* DiskCopy42.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiskCopy42.h; sourceTree = "<group>"; };
B6B17FA10F1138830060F7AA /* DiskCopy42.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DiskCopy42.cpp; sourceTree = "<group>"; };
B6C786B30F2A59AF00053681 /* profuse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = profuse.h; sourceTree = "<group>"; };
B6C786B40F2A59FE00053681 /* profuse_xattr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_xattr.cpp; sourceTree = "<group>"; };
B6C786BB0F2A5C0800053681 /* profuse_dirent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_dirent.cpp; sourceTree = "<group>"; };
B6C786BF0F2A5CC000053681 /* profuse_stat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_stat.cpp; sourceTree = "<group>"; };
B6C786C30F2A5DCE00053681 /* profuse_file.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_file.cpp; sourceTree = "<group>"; };
B6DA7027131047CA00E42AA6 /* BlockCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BlockCache.cpp; sourceTree = "<group>"; };
B6DA7028131047CA00E42AA6 /* BlockCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockCache.h; sourceTree = "<group>"; };
B6DA7029131047CA00E42AA6 /* ConcreteBlockCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConcreteBlockCache.cpp; sourceTree = "<group>"; };
B6DA702A131047CA00E42AA6 /* ConcreteBlockCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConcreteBlockCache.h; sourceTree = "<group>"; };
B6DA702B131047CA00E42AA6 /* MappedBlockCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MappedBlockCache.cpp; sourceTree = "<group>"; };
B6DA702C131047CA00E42AA6 /* MappedBlockCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MappedBlockCache.h; sourceTree = "<group>"; };
B6DA7031131047D100E42AA6 /* Adaptor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Adaptor.cpp; sourceTree = "<group>"; };
B6DA7032131047D100E42AA6 /* Adaptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Adaptor.h; sourceTree = "<group>"; };
B6DA7033131047D100E42AA6 /* BlockDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BlockDevice.cpp; sourceTree = "<group>"; };
B6DA7034131047D100E42AA6 /* BlockDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockDevice.h; sourceTree = "<group>"; };
B6DA7035131047D100E42AA6 /* DavexDiskImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DavexDiskImage.cpp; sourceTree = "<group>"; };
B6DA7036131047D100E42AA6 /* DavexDiskImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DavexDiskImage.h; sourceTree = "<group>"; };
B6DA7037131047D100E42AA6 /* DiskCopy42Image.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DiskCopy42Image.cpp; sourceTree = "<group>"; };
B6DA7038131047D100E42AA6 /* DiskCopy42Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiskCopy42Image.h; sourceTree = "<group>"; };
B6DA7039131047D100E42AA6 /* DiskImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DiskImage.cpp; sourceTree = "<group>"; };
B6DA703A131047D100E42AA6 /* DiskImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiskImage.h; sourceTree = "<group>"; };
B6DA703B131047D100E42AA6 /* RawDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RawDevice.cpp; sourceTree = "<group>"; };
B6DA703C131047D100E42AA6 /* RawDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RawDevice.h; sourceTree = "<group>"; };
B6DA703D131047D100E42AA6 /* TrackSector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackSector.h; sourceTree = "<group>"; };
B6DA703E131047D100E42AA6 /* UniversalDiskImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UniversalDiskImage.cpp; sourceTree = "<group>"; };
B6DA703F131047D100E42AA6 /* UniversalDiskImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UniversalDiskImage.h; sourceTree = "<group>"; };
B6DA7048131047F400E42AA6 /* Endian.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Endian.cpp; sourceTree = "<group>"; };
B6DA7049131047F400E42AA6 /* Endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Endian.h; sourceTree = "<group>"; };
B6DA704A131047F400E42AA6 /* IOBuffer.cpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOBuffer.cpp.h; sourceTree = "<group>"; };
B6DA704B131047F400E42AA6 /* IOBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOBuffer.h; sourceTree = "<group>"; };
B6DA704E131047FA00E42AA6 /* File.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = File.cpp; sourceTree = "<group>"; };
B6DA704F131047FA00E42AA6 /* File.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = File.h; sourceTree = "<group>"; };
B6DA7050131047FA00E42AA6 /* MappedFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MappedFile.cpp; sourceTree = "<group>"; };
B6DA7051131047FA00E42AA6 /* MappedFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MappedFile.h; sourceTree = "<group>"; };
B6DA70551310551500E42AA6 /* auto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = auto.h; sourceTree = "<group>"; };
B6DA70561310551500E42AA6 /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = "<group>"; };
B6DA70571310551500E42AA6 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = "<group>"; };
B6DA70581310551500E42AA6 /* Lock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Lock.cpp; sourceTree = "<group>"; };
B6DA70591310551500E42AA6 /* Lock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Lock.h; sourceTree = "<group>"; };
B6DA706B1310571B00E42AA6 /* DateTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DateTime.cpp; sourceTree = "<group>"; };
B6DA706C1310571B00E42AA6 /* DateTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DateTime.h; sourceTree = "<group>"; };
B6DBB4E70F0C6BBD00F385F2 /* profuse.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = profuse.1; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -75,16 +123,16 @@
08FB7795FE84155DC02AAC07 /* Source */ = {
isa = PBXGroup;
children = (
B642F1290F132FA3001F7696 /* UniversalDiskImage.h */,
B642F12A0F132FA3001F7696 /* UniversalDiskImage.cpp */,
B6DA70681310571B00E42AA6 /* ProDOS */,
B6DA70541310551500E42AA6 /* ProFUSE */,
B6DA704D131047FA00E42AA6 /* File */,
B6DA7047131047F400E42AA6 /* Endian */,
B6DA7030131047D100E42AA6 /* Device */,
B6DA7026131047CA00E42AA6 /* Cache */,
B60E91580EFD77E3000E4348 /* common.h */,
B60E91530EFB51FE000E4348 /* Disk.h */,
B60E91540EFB51FE000E4348 /* Disk.cpp */,
B60E914D0EFB3627000E4348 /* File.h */,
B60E914E0EFB3628000E4348 /* File.cpp */,
B679E4A70F02E79300FB3F0C /* main.cpp */,
B6B17FA00F1138830060F7AA /* DiskCopy42.h */,
B6B17FA10F1138830060F7AA /* DiskCopy42.cpp */,
B6C786B30F2A59AF00053681 /* profuse.h */,
B6C786BB0F2A5C0800053681 /* profuse_dirent.cpp */,
B6C786C30F2A5DCE00053681 /* profuse_file.cpp */,
@@ -109,6 +157,88 @@
name = Libraries;
sourceTree = "<group>";
};
B6DA7026131047CA00E42AA6 /* Cache */ = {
isa = PBXGroup;
children = (
B6DA7027131047CA00E42AA6 /* BlockCache.cpp */,
B6DA7028131047CA00E42AA6 /* BlockCache.h */,
B6DA7029131047CA00E42AA6 /* ConcreteBlockCache.cpp */,
B6DA702A131047CA00E42AA6 /* ConcreteBlockCache.h */,
B6DA702B131047CA00E42AA6 /* MappedBlockCache.cpp */,
B6DA702C131047CA00E42AA6 /* MappedBlockCache.h */,
);
path = Cache;
sourceTree = "<group>";
};
B6DA7030131047D100E42AA6 /* Device */ = {
isa = PBXGroup;
children = (
B6DA7031131047D100E42AA6 /* Adaptor.cpp */,
B6DA7032131047D100E42AA6 /* Adaptor.h */,
B6DA7033131047D100E42AA6 /* BlockDevice.cpp */,
B6DA7034131047D100E42AA6 /* BlockDevice.h */,
B6DA7035131047D100E42AA6 /* DavexDiskImage.cpp */,
B6DA7036131047D100E42AA6 /* DavexDiskImage.h */,
B6DA7037131047D100E42AA6 /* DiskCopy42Image.cpp */,
B6DA7038131047D100E42AA6 /* DiskCopy42Image.h */,
B6DA7039131047D100E42AA6 /* DiskImage.cpp */,
B6DA703A131047D100E42AA6 /* DiskImage.h */,
B6DA703B131047D100E42AA6 /* RawDevice.cpp */,
B6DA703C131047D100E42AA6 /* RawDevice.h */,
B6DA703D131047D100E42AA6 /* TrackSector.h */,
B6DA703E131047D100E42AA6 /* UniversalDiskImage.cpp */,
B6DA703F131047D100E42AA6 /* UniversalDiskImage.h */,
B650C2C6131095C200046FAD /* Device.h */,
);
path = Device;
sourceTree = "<group>";
};
B6DA7047131047F400E42AA6 /* Endian */ = {
isa = PBXGroup;
children = (
B6DA7048131047F400E42AA6 /* Endian.cpp */,
B6DA7049131047F400E42AA6 /* Endian.h */,
B6DA704A131047F400E42AA6 /* IOBuffer.cpp.h */,
B6DA704B131047F400E42AA6 /* IOBuffer.h */,
);
path = Endian;
sourceTree = "<group>";
};
B6DA704D131047FA00E42AA6 /* File */ = {
isa = PBXGroup;
children = (
B6DA704E131047FA00E42AA6 /* File.cpp */,
B6DA704F131047FA00E42AA6 /* File.h */,
B6DA7050131047FA00E42AA6 /* MappedFile.cpp */,
B6DA7051131047FA00E42AA6 /* MappedFile.h */,
);
path = File;
sourceTree = "<group>";
};
B6DA70541310551500E42AA6 /* ProFUSE */ = {
isa = PBXGroup;
children = (
B6DA70551310551500E42AA6 /* auto.h */,
B61BCF8F131B6633002DE159 /* smart_pointers.h */,
B6DA70561310551500E42AA6 /* Exception.cpp */,
B6DA70571310551500E42AA6 /* Exception.h */,
B6DA70581310551500E42AA6 /* Lock.cpp */,
B6DA70591310551500E42AA6 /* Lock.h */,
);
path = ProFUSE;
sourceTree = "<group>";
};
B6DA70681310571B00E42AA6 /* ProDOS */ = {
isa = PBXGroup;
children = (
B650C2C3131090D200046FAD /* File.cpp */,
B650C2C4131090D200046FAD /* File.h */,
B6DA706B1310571B00E42AA6 /* DateTime.cpp */,
B6DA706C1310571B00E42AA6 /* DateTime.h */,
);
path = ProDOS;
sourceTree = "<group>";
};
C6859E8C029090F304C91782 /* Documentation */ = {
isa = PBXGroup;
children = (
@@ -145,7 +275,11 @@
isa = PBXProject;
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "profuse" */;
compatibilityVersion = "Xcode 3.1";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
en,
);
mainGroup = 08FB7794FE84155DC02AAC07 /* ProDOS-Fuse */;
projectDirPath = "";
projectRoot = "";
@@ -160,15 +294,29 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B60E914F0EFB3628000E4348 /* File.cpp in Sources */,
B60E91550EFB51FE000E4348 /* Disk.cpp in Sources */,
B679E4A80F02E79300FB3F0C /* main.cpp in Sources */,
B6B17FA20F1138830060F7AA /* DiskCopy42.cpp in Sources */,
B642F12B0F132FA3001F7696 /* UniversalDiskImage.cpp in Sources */,
B6C786B50F2A59FF00053681 /* profuse_xattr.cpp in Sources */,
B6C786BC0F2A5C0800053681 /* profuse_dirent.cpp in Sources */,
B6C786C00F2A5CC000053681 /* profuse_stat.cpp in Sources */,
B6C786C40F2A5DCE00053681 /* profuse_file.cpp in Sources */,
B6DA702D131047CA00E42AA6 /* BlockCache.cpp in Sources */,
B6DA702E131047CA00E42AA6 /* ConcreteBlockCache.cpp in Sources */,
B6DA702F131047CA00E42AA6 /* MappedBlockCache.cpp in Sources */,
B6DA7040131047D100E42AA6 /* Adaptor.cpp in Sources */,
B6DA7041131047D100E42AA6 /* BlockDevice.cpp in Sources */,
B6DA7042131047D100E42AA6 /* DavexDiskImage.cpp in Sources */,
B6DA7043131047D100E42AA6 /* DiskCopy42Image.cpp in Sources */,
B6DA7044131047D100E42AA6 /* DiskImage.cpp in Sources */,
B6DA7045131047D100E42AA6 /* RawDevice.cpp in Sources */,
B6DA7046131047D100E42AA6 /* UniversalDiskImage.cpp in Sources */,
B6DA704C131047F400E42AA6 /* Endian.cpp in Sources */,
B6DA7052131047FA00E42AA6 /* File.cpp in Sources */,
B6DA7053131047FA00E42AA6 /* MappedFile.cpp in Sources */,
B6DA705A1310551500E42AA6 /* Exception.cpp in Sources */,
B6DA705B1310551500E42AA6 /* Lock.cpp in Sources */,
B6DA706E1310571B00E42AA6 /* DateTime.cpp in Sources */,
B650C2C5131090D200046FAD /* File.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -184,10 +332,8 @@
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"_GLIBCXX_DEBUG=1",
"_GLIBCXX_DEBUG_PEDANTIC=1",
);
GCC_PREPROCESSOR_DEFINITIONS = "";
GCC_VERSION = com.apple.compilers.llvmgcc42;
INSTALL_PATH = /usr/local/bin;
PRODUCT_NAME = profuse;
};
@@ -199,6 +345,7 @@
ALWAYS_SEARCH_USER_PATHS = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_MODEL_TUNING = G5;
GCC_VERSION = com.apple.compilers.llvmgcc42;
INSTALL_PATH = /usr/local/bin;
PRODUCT_NAME = "ProDOS-Fuse";
};
@@ -211,9 +358,13 @@
GCC_C_LANGUAGE_STANDARD = c99;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = "";
GCC_VERSION = com.apple.compilers.llvmgcc42;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = /usr/local/include/fuse;
HEADER_SEARCH_PATHS = (
/usr/local/include/fuse,
.,
);
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = (
"-D__FreeBSD__=10",
@@ -226,7 +377,7 @@
"-lfuse_ino64",
);
PREBINDING = NO;
SDKROOT = macosx10.5;
SDKROOT = macosx;
};
name = Debug;
};
@@ -235,10 +386,11 @@
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
GCC_C_LANGUAGE_STANDARD = c99;
GCC_VERSION = com.apple.compilers.llvmgcc42;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO;
SDKROOT = macosx10.5;
SDKROOT = macosx;
};
name = Release;
};
@@ -249,9 +401,13 @@
GCC_C_LANGUAGE_STANDARD = c99;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = "";
GCC_VERSION = com.apple.compilers.llvmgcc42;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = /usr/local/include/fuse;
HEADER_SEARCH_PATHS = (
/usr/local/include/fuse,
.,
);
ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = (
"-D__FreeBSD__=10",
@@ -264,7 +420,7 @@
"-lfuse_ino64",
);
PREBINDING = NO;
SDKROOT = macosx10.5;
SDKROOT = macosx;
};
name = "Debug Universal";
};
@@ -277,15 +433,60 @@
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"_GLIBCXX_DEBUG=1",
"_GLIBCXX_DEBUG_PEDANTIC=1",
);
GCC_PREPROCESSOR_DEFINITIONS = "";
GCC_VERSION = com.apple.compilers.llvmgcc42;
INSTALL_PATH = /usr/local/bin;
PRODUCT_NAME = profuse;
};
name = "Debug Universal";
};
B67F09801057600400A13214 /* Debug 10.6 */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
GCC_C_LANGUAGE_STANDARD = c99;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = "";
GCC_VERSION = com.apple.compilers.llvmgcc42;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
/usr/local/include/fuse,
.,
);
ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = (
"-D__FreeBSD__=10",
"-D_FILE_OFFSET_BITS=64",
"-D__DARWIN_64_BIT_INO_T=1",
"-DHAVE_STAT_BIRTHTIME",
);
OTHER_LDFLAGS = (
"-L/usr/local/lib/",
"-lfuse_ino64",
);
PREBINDING = NO;
SDKROOT = macosx;
VALID_ARCHS = "i386 x86_64";
};
name = "Debug 10.6";
};
B67F09811057600400A13214 /* Debug 10.6 */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = "";
GCC_VERSION = com.apple.compilers.llvmgcc42;
INSTALL_PATH = /usr/local/bin;
PRODUCT_NAME = profuse;
};
name = "Debug 10.6";
};
B6B767C10F0FF90400D819C9 /* Debug Universal 10.4 */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -293,9 +494,14 @@
GCC_C_LANGUAGE_STANDARD = c99;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = "";
GCC_VERSION = com.apple.compilers.llvmgcc42;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = /usr/local/include/fuse;
HEADER_SEARCH_PATHS = (
/usr/local/include/fuse,
.,
);
MACOSX_DEPLOYMENT_TARGET = 10.4;
ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = (
"-D__FreeBSD__=10",
@@ -306,7 +512,7 @@
"-lfuse",
);
PREBINDING = NO;
SDKROOT = macosx10.4;
SDKROOT = macosx;
};
name = "Debug Universal 10.4";
};
@@ -319,10 +525,8 @@
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"_GLIBCXX_DEBUG=1",
"_GLIBCXX_DEBUG_PEDANTIC=1",
);
GCC_PREPROCESSOR_DEFINITIONS = "";
GCC_VERSION = com.apple.compilers.llvmgcc42;
INSTALL_PATH = /usr/local/bin;
PRODUCT_NAME = profuse;
};
@@ -335,6 +539,7 @@
isa = XCConfigurationList;
buildConfigurations = (
1DEB923208733DC60010E9CD /* Debug */,
B67F09811057600400A13214 /* Debug 10.6 */,
B618461B0F0AF6CC0045CCF7 /* Debug Universal */,
B6B767C20F0FF90400D819C9 /* Debug Universal 10.4 */,
1DEB923308733DC60010E9CD /* Release */,
@@ -346,6 +551,7 @@
isa = XCConfigurationList;
buildConfigurations = (
1DEB923608733DC60010E9CD /* Debug */,
B67F09801057600400A13214 /* Debug 10.6 */,
B618461A0F0AF6CC0045CCF7 /* Debug Universal */,
B6B767C10F0FF90400D819C9 /* Debug Universal 10.4 */,
1DEB923708733DC60010E9CD /* Release */,

View File

@@ -27,7 +27,7 @@ using std::vector;
*/
void prodos_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
{
fprintf(stderr, "opendir: %u\n", ino);
fprintf(stderr, "opendir: %u\n", (unsigned)ino);
// verify it's a directory/volume here?
@@ -72,7 +72,7 @@ void prodos_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
void prodos_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
{
fprintf(stderr,"releasedir: %d\n", ino);
fprintf(stderr,"releasedir: %u\n", (unsigned)ino);
vector<FileEntry> *files = (vector<FileEntry> *)fi->fh;
if (files) delete files;
@@ -85,7 +85,7 @@ void prodos_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, stru
vector<FileEntry> *files = (vector<FileEntry> *)fi->fh;
struct stat st;
fprintf(stderr, "readdir %u %u %u\n", ino, size, off);
fprintf(stderr, "readdir %u %u %u\n", (unsigned)ino, (unsigned)size, (unsigned)off);
// TODO -- add "." and ".." entries...

View File

@@ -15,7 +15,7 @@
void prodos_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
{
fprintf(stderr, "open: %u\n", ino);
fprintf(stderr, "open: %u\n", (unsigned)ino);
uint8_t buffer[BLOCK_SIZE];
@@ -70,7 +70,7 @@ void prodos_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
void prodos_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
{
fprintf(stderr, "release: %d\n", ino);
fprintf(stderr, "release: %u\n", (unsigned)ino);
FileEntry *e = (FileEntry *)fi->fh;
@@ -82,7 +82,7 @@ void prodos_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
void prodos_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
{
fprintf(stderr, "read: %u %u %u\n", ino, size, off);
fprintf(stderr, "read: %u %u %u\n", (unsigned)ino, (unsigned)size, (unsigned)off);
FileEntry *e = (FileEntry *)fi->fh;

View File

@@ -16,6 +16,8 @@
#include <vector>
#include <sys/stat.h>
#include <sys/statvfs.h>
using std::vector;
@@ -109,7 +111,7 @@ void prodos_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
struct stat st;
int ok;
fprintf(stderr, "get_attr %u\n", ino);
fprintf(stderr, "get_attr %u\n", (unsigned)ino);
bzero(&st, sizeof(st));
@@ -162,7 +164,7 @@ void prodos_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
vector<FileEntry> files;
fprintf(stderr, "lookup: %d %s\n", parent, name);
fprintf(stderr, "lookup: %u %s\n", (unsigned)parent, name);
ERROR(!validProdosName(name), ENOENT)
@@ -217,3 +219,34 @@ void prodos_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
fuse_reply_entry(req, &entry);
}
void prodos_statfs(fuse_req_t req, fuse_ino_t ino)
{
struct statvfs vst;
VolumeEntry volume;
disk->ReadVolume(&volume, NULL);
// returns statvfs for the mount path or any file in the fs
// therefore, ignore ino.
std::memset(&vst, 0, sizeof(vst));
vst.f_bsize = 512; // fs block size
vst.f_frsize = 512; // fundamental fs block size
vst.f_blocks = volume.total_blocks;
vst.f_bfree = 0; // free blocks
vst.f_bavail = 0; // free blocks (non-root)
vst.f_files = 0; // ?
vst.f_ffree = -1; // free inodes.
vst.f_favail = -1; // free inodes (non-root)
vst.f_fsid = 0; // file system id?
vst.f_flag = ST_RDONLY | ST_NOSUID;
vst.f_namemax = 15;
fuse_reply_statfs(req, &vst);
}

View File

@@ -18,6 +18,13 @@
using std::string;
#ifdef __APPLE__
#define NO_ATTRIBUTE ENOATTR
#else
#define NO_ATTRIBUTE EOPNOTSUPP
#endif
static bool isTextFile(unsigned ftype, unsigned auxtype)
{
if (ftype == 0x04) return true; // ascii text
@@ -186,7 +193,7 @@ static void xattr_charset(FileEntry& e, fuse_req_t req, size_t size, off_t off)
const char attr[] = "macintosh";
unsigned attr_size = sizeof(attr) - 1;
ERROR(!isTextFile(e.file_type, e.aux_type), ENOENT)
ERROR(!isTextFile(e.file_type, e.aux_type), NO_ATTRIBUTE)
if (size == 0)
{
@@ -205,7 +212,7 @@ static void xattr_textencoding(FileEntry& e, fuse_req_t req, size_t size, off_t
const char attr[] = "MACINTOSH;0";
unsigned attr_size = sizeof(attr) - 1;
ERROR(!isTextFile(e.file_type, e.aux_type), ENOENT)
ERROR(!isTextFile(e.file_type, e.aux_type), NO_ATTRIBUTE)
if (size == 0)
{
@@ -223,7 +230,7 @@ static void xattr_rfork(FileEntry& e, fuse_req_t req, size_t size, off_t off)
int ok;
unsigned level;
ERROR (e.storage_type != EXTENDED_FILE, ENOENT)
ERROR (e.storage_type != EXTENDED_FILE, NO_ATTRIBUTE)
ok = disk->Normalize(e, 1);
ERROR(ok < 0, EIO)
@@ -306,7 +313,7 @@ static void xattr_finfo(FileEntry& e, fuse_req_t req, size_t size, off_t off)
break;
default:
ERROR(true, ENOENT);
ERROR(true, NO_ATTRIBUTE);
}
@@ -347,7 +354,7 @@ static void xattr_mimetype(FileEntry& e, fuse_req_t req, size_t size, off_t off)
{
unsigned attr_size;
const char *mime = mimeType(e.file_type, e.aux_type);
ERROR(!mime, ENOENT);
ERROR(!mime, NO_ATTRIBUTE);
attr_size = strlen(mime);
@@ -375,7 +382,7 @@ else fuse_reply_xattr(req, 0); \
return; \
}
fprintf(stderr, "listxattr %u\n", ino);
fprintf(stderr, "listxattr %u\n", (unsigned)ino);
uint8_t buffer[BLOCK_SIZE];
int ok;
@@ -478,13 +485,9 @@ return; \
*/
void prodos_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, size_t size, uint32_t off)
{
#ifdef __APPLE__
#define NO_ATTRIBUTE ENOENT
#else
#define NO_ATTRIBUTE EOPNOTSUPP
#endif
fprintf(stderr, "getxattr: %u %s %u %u \n", ino, name, (int)size, (int)off);
fprintf(stderr, "getxattr: %u %s %u %u \n", (unsigned)ino, name, (unsigned)size, (unsigned)off);
uint8_t buffer[BLOCK_SIZE];