mirror of
https://github.com/ksherlock/profuse.git
synced 2026-04-23 06:31:22 +00:00
Compare commits
31 Commits
2009-09-08
...
profuse_in
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
699c44cf15 | ||
|
|
1a0bdd875c | ||
|
|
77e5994908 | ||
|
|
5ab8fd3d87 | ||
|
|
c6165e16d2 | ||
|
|
87d6070dcf | ||
|
|
0e083d53e7 | ||
|
|
78b1b8b242 | ||
|
|
977f0530fc | ||
|
|
24757dc35c | ||
|
|
ac8bbd5265 | ||
|
|
c7c4f13bf7 | ||
|
|
68a7851f33 | ||
|
|
8550923cb3 | ||
|
|
c9b260b753 | ||
|
|
c44145f551 | ||
|
|
3f8e7ad7ae | ||
|
|
4cdfc52c04 | ||
|
|
1fd924ae1b | ||
|
|
40ea9f2289 | ||
|
|
9a6e9150ef | ||
|
|
2bd72b08b9 | ||
|
|
664dee7578 | ||
|
|
ea0d1c198b | ||
|
|
c82cd3f8fa | ||
|
|
5427db9990 | ||
|
|
7fb0604b76 | ||
|
|
14e9b43f32 | ||
|
|
e5f935e435 | ||
|
|
e36eb445bf | ||
|
|
caea19006a |
73
Cache/BlockCache.cpp
Normal file
73
Cache/BlockCache.cpp
Normal 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
62
Cache/BlockCache.h
Normal 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
|
||||
382
Cache/ConcreteBlockCache.cpp
Normal file
382
Cache/ConcreteBlockCache.cpp
Normal 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;
|
||||
}
|
||||
|
||||
75
Cache/ConcreteBlockCache.h
Normal file
75
Cache/ConcreteBlockCache.h
Normal 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
140
Cache/MappedBlockCache.cpp
Normal 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
38
Cache/MappedBlockCache.h
Normal 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
486
Device/Adaptor.cpp
Normal 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
81
Device/Adaptor.h
Normal 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
271
Device/BlockDevice.cpp
Normal 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
69
Device/BlockDevice.h
Normal 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
176
Device/DavexDiskImage.cpp
Normal 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
43
Device/DavexDiskImage.h
Normal 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
24
Device/Device.h
Normal 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
243
Device/DiskCopy42Image.cpp
Normal 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
42
Device/DiskCopy42Image.h
Normal 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
228
Device/DiskImage.cpp
Normal 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
97
Device/DiskImage.h
Normal 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
321
Device/RawDevice.cpp
Normal 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
57
Device/RawDevice.h
Normal 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
249
Device/SDKImage.cpp
Normal 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
30
Device/SDKImage.h
Normal 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
19
Device/TrackSector.h
Normal 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
|
||||
163
Device/UniversalDiskImage.cpp
Normal file
163
Device/UniversalDiskImage.cpp
Normal 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();
|
||||
}
|
||||
|
||||
|
||||
44
Device/UniversalDiskImage.h
Normal file
44
Device/UniversalDiskImage.h
Normal 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
166
Disk.cpp
@@ -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
20
Disk.h
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
31
DiskCopy42.h
31
DiskCopy42.h
@@ -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
105
Endian/Endian.cpp
Normal 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
159
Endian/Endian.h
Normal 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
103
Endian/IOBuffer.cpp.h
Normal 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
15
Endian/IOBuffer.h
Normal 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
128
File/File.cpp
Normal 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
58
File/File.h
Normal 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
187
File/MappedFile.cpp
Normal 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 ¬hrow)
|
||||
{
|
||||
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
53
File/MappedFile.h
Normal 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 ¬hrow);
|
||||
|
||||
~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
192
MacRoman.cpp
Normal 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
26
MacRoman.h
Normal 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
200
ProDOS/Bitmap.cpp
Normal 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
48
ProDOS/Bitmap.h
Normal 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
|
||||
@@ -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
|
||||
@@ -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];
|
||||
|
||||
@@ -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
148
ProFUSE/Exception.cpp
Normal 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
158
ProFUSE/Exception.h
Normal 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
28
ProFUSE/Lock.cpp
Normal 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
33
ProFUSE/Lock.h
Normal 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
104
ProFUSE/auto.h
Normal 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
35
ProFUSE/smart_pointers.h
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
30
common.h
30
common.h
@@ -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
189
main.cpp
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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 */,
|
||||
|
||||
@@ -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...
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user