29 Commits

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

2
.gitignore vendored
View File

@@ -1,2 +0,0 @@
*.o
o/

View File

@@ -1,11 +0,0 @@
language: cpp
# trusty has gcc 4.8
sudo: required
dist: trusty
compiler:
- clang++
- g++
script: make
before_install:
- sudo apt-get -qq update
- sudo apt-get install -y fuse libfuse-dev

243
Bitmap.cpp Normal file
View File

@@ -0,0 +1,243 @@
#include "Bitmap.h"
#include <cstring>
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;
}
inline static unsigned countLeadingZeros(uint8_t x)
{
if (x == 0) return sizeof(uint8_t);
#ifdef __GNUC__
return __builtin_clz(x) + sizeof(uint8_t) - sizeof(unsigned);
#endif
unsigned rv = 0;
if ((x & 0xf0) == 0) { x <<= 4; rv = 4; }
if (x & 0x80) return rv;
if (x & 0x40) return rv + 1;
if (x & 0x20) return rv + 2;
if (x & 0x10) return rv + 3;
// unreachable
return 0;
}
inline static unsigned countLeadingOnes(uint8_t x)
{
return countLeadingZeros(~x);
}
Bitmap::Bitmap(unsigned blocks) :
_blocks(blocks),
_freeBlocks(blocks),
_bitmapSize((blocks + 4096 - 1) >> 12),
_bitmap(NULL)
{
// 1 block = 512 bytes = 4096 bits
_bitmap = new uint8_t[_bitmapSize];
// mark every requested block as free.
unsigned bytes = blocks >> 3;
std::memset(_bitmap, 0xff, bytes);
// all trailing blocks are marked as used.
std::memset(_bitmap + bytes, 0x00, _bitmapSize - bytes);
// and handle the edge case...
/*
* 0 -> 0 0 0 0 0 0 0 0
* 1 -> 1 0 0 0 0 0 0 0
* 2 -> 1 1 0 0 0 0 0 0
* 3 -> 1 1 1 0 0 0 0 0
* ...
* 7 -> 1 1 1 1 1 1 1 0
*/
//unsigned tmp = (1 << (8 - (blocks & 0x07))) - 1;
//_bitmap[bytes] = ~tmp & 0xff;
_bitmap[bytes] = 0 - (1 << (8 - (blocks & 0x07)));
//_bitmap[bytes] = (0xff00 >> (blocks & 0x07)) & 0xff;
}
Bitmap::~Bitmap()
{
delete[] _bitmap;
}
bool Bitmap::markBlock(unsigned block, bool inUse)
{
if (block >= _blocks) return false;
unsigned index = BlockIndex(block);
unsigned mask = BlockMask(block);
uint8_t data = _bitmap[index];
_freeBlocks -= popCount(data);
if (inUse) data &= ~mask;
else data |= mask;
_bitmap[index] = data;
_freeBlocks += popCount(data);
return true;
}
// find the first block starting from (and including) the
// startingBlock
int Bitmap::firstFreeBlock(unsigned startingBlock) const
{
if (startingBlock >= _blocks) return -1;
if (!_freeBlocks) return -1;
unsigned index = BlockIndex(startingBlock);
unsigned bit = startingBlock & 0x0f;
unsigned bytes = (_blocks + 7) >> 3;
// special case for first (partial) bitmap
if (bit != 0)
{
uint8_t data = _bitmap[index];
unsigned mask = BlockMask(startingBlock);
// 0 0 1 0 0 0 0 0 -> 0 0 1 1 1 1 1 1
mask = (mask - 1) | mask;
data &= mask;
if (data) return (index << 3) + countLeadingZeros(data);
++index;
}
for ( ; index < bytes; ++index)
{
uint8_t data = _bitmap[index];
if (!data) continue;
return (index << 3) + countLeadingZeros(data);
}
return -1;
}
// count the number of unused blocks.... (including startingBlock)
int Bitmap::countUnusedBlocks(unsigned startingBlock, unsigned maxSearch) const
{
if (startingBlock >= _blocks) return -1;
if (!_freeBlocks) return -1;
unsigned count = 0;
unsigned index = BlockIndex(startingBlock);
unsigned bit = startingBlock & 0x0f;
unsigned bytes = (_blocks + 7) >> 3;
// special case for the first (partial) byte.
if (bit)
{
uint8_t data = _bitmap[index];
if (data == 0) return 0;
unsigned mask = BlockMask(startingBlock);
// 0 0 1 0 0 0 0 0 -> 1 1 0 0 0 0 0 0
mask = ~ ((mask - 1) | mask);
data = data | mask;
if (data == 0xff)
{
count = 8 - bit;
if (count >= maxSearch) return count;
++index;
}
else
{
return countLeadingOnes(data) - bit;
}
}
for ( ; index < bytes; ++index)
{
uint8_t data = _bitmap[index];
// no free blocks = end search
if (data == 0) break;
// all free = continue (if necessary)
if (data == 0xff)
{
count += 8;
if (count >= maxSearch) break;
continue;
}
// otherwise, add on any leading free and terminate.
count += countLeadingOnes(data);
break;
}
return count;
}
// finds the first free block (with a possible range).
int Bitmap::freeBlock(unsigned count) const
{
if (count == 0 || count > freeBlocks()) return -1;
// we could keep a linked list/etc of
// free ranges
// for now, scan the entire bitmap.
int startBlock = 0;
--count;
for(;;)
{
startBlock = firstFreeBlock(startBlock);
if (startBlock < 0) return -1;
if (count == 0) return startBlock;
int tmp = countUnusedBlocks(startBlock + 1, count);
if (tmp <= 0) break;
if (tmp >= count) return startBlock;
// miss ... jump ahead.
startBlock += tmp + 1;
}
return -1;
}
} // namespace

72
Bitmap.h Normal file
View File

@@ -0,0 +1,72 @@
#ifndef __PRODOS_BITMAP_H__
#define __PRODOS_BITMAP_H__
#include <stdint.h>
namespace ProDOS {
class Bitmap {
public:
Bitmap(unsigned blocks);
~Bitmap();
bool blockFree(unsigned block) const;
bool markBlock(unsigned block, bool inUse);
unsigned blocks() const;
unsigned bitmapBlocks() const;
unsigned freeBlocks() const;
int firstFreeBlock(unsigned startingBlock = 0) const;
int countUnusedBlocks(unsigned startingBlock = 0, unsigned maxSearch = -1) const;
int freeBlock(unsigned count = 1) const;
private:
static unsigned BlockMask(unsigned block);
static unsigned BlockIndex(unsigned block);
unsigned _blocks;
unsigned _freeBlocks;
unsigned _bitmapSize;
uint8_t *_bitmap;
};
inline unsigned Bitmap::blocks() const
{
return _blocks;
}
inline unsigned Bitmap::freeBlocks() const
{
return _blocks;
}
inline unsigned Bitmap::bitmapBlocks() const
{
return _bitmapSize >> 12;
}
inline unsigned Bitmap::BlockMask(unsigned block)
{
return 0x80 >> (block & 0x07);
}
inline unsigned Bitmap::BlockIndex(unsigned block)
{
return block >> 3;
}
inline bool Bitmap::blockFree(unsigned block) const
{
if (block >= _blocks) return false;
return (_bitmap[BlockIndex(block)] & BlockMask(block)) != 0;
}
} // namespace
#endif

View File

@@ -1,56 +0,0 @@
#include "Buffer.h"
using namespace ProFUSE;
void Buffer::push16be(uint16_t x)
{
_buffer.push_back((x >> 8) & 0xff);
_buffer.push_back(x & 0xff);
}
void Buffer::push16le(uint16_t x)
{
_buffer.push_back(x & 0xff);
_buffer.push_back((x >> 8) & 0xff);
}
void Buffer::push24be(uint32_t x)
{
_buffer.push_back((x >> 16) & 0xff);
_buffer.push_back((x >> 8) & 0xff);
_buffer.push_back(x & 0xff);
}
void Buffer::push24le(uint32_t x)
{
_buffer.push_back(x & 0xff);
_buffer.push_back((x >> 8) & 0xff);
_buffer.push_back((x >> 16) & 0xff);
}
void Buffer::push32be(uint32_t x)
{
_buffer.push_back((x >> 24) & 0xff);
_buffer.push_back((x >> 16) & 0xff);
_buffer.push_back((x >> 8) & 0xff);
_buffer.push_back(x & 0xff);
}
void Buffer::push32le(uint32_t x)
{
_buffer.push_back(x & 0xff);
_buffer.push_back((x >> 8) & 0xff);
_buffer.push_back((x >> 16) & 0xff);
_buffer.push_back((x >> 24) & 0xff);
}
void Buffer::pushBytes(const void *data, unsigned size)
{
for (unsigned i = 0; i < size; ++i)
{
_buffer.push_back( ((uint8_t *)data)[i] );
}
}

View File

@@ -1,39 +0,0 @@
#ifndef __BUFFER_H__
#define __BUFFER_H__
#include <vector>
namespace ProFUSE {
class Buffer {
public:
Buffer() {}
Buffer(unsigned size) { _buffer.reserve(size); }
void *buffer() const { return (void *)&_buffer[0]; }
unsigned size() const { return _buffer.size(); }
void resize(unsigned size) { _buffer.resize(size); }
void clear() { _buffer.clear(); }
void push8(uint8_t x) { _buffer.push_back(x); }
void push16be(uint16_t);
void push16le(uint16_t);
void push24be(uint32_t);
void push24le(uint32_t);
void push32be(uint32_t);
void push32le(uint32_t);
void pushBytes(const void *data, unsigned size);
private:
std::vector<uint8_t> _buffer;
};
}
#endif

View File

@@ -11,14 +11,16 @@
#include <Cache/BlockCache.h>
#include <Device/BlockDevice.h>
#include <Common/Exception.h>
#include <Common/auto.h>
#include <ProFUSE/Exception.h>
#include <ProFUSE/auto.h>
using namespace Device;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
BlockCache::BlockCache(BlockDevicePointer device) :

View File

@@ -10,8 +10,8 @@
#include <Device/BlockDevice.h>
#include <Cache/ConcreteBlockCache.h>
#include <Common/Exception.h>
#include <Common/auto.h>
#include <ProFUSE/Exception.h>
#include <ProFUSE/auto.h>
/*
@@ -51,6 +51,8 @@
using namespace Device;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
//typedef std::vector<ConcreteBlockCache::Entry *>::iterator EntryIter;

View File

@@ -22,13 +22,11 @@ public:
virtual void release(unsigned block, int flags);
virtual void markDirty(unsigned block);
// public so make_shared can access it.
ConcreteBlockCache(BlockDevicePointer device, unsigned size);
private:
ConcreteBlockCache(BlockDevicePointer device, unsigned size);
struct Entry {
unsigned block;

View File

@@ -2,7 +2,6 @@
#include <algorithm>
#include <cerrno>
#include <cstring>
#include <cstddef>
#include <sys/types.h>
#include <sys/mman.h>
@@ -11,12 +10,14 @@
#include <Cache/MappedBlockCache.h>
#include <Device/BlockDevice.h>
#include <Common/Exception.h>
#include <POSIX/Exception.h>
#include <ProFUSE/Exception.h>
using namespace Device;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
BlockCachePointer MappedBlockCache::Create(BlockDevicePointer device, void *data)
{
@@ -123,12 +124,12 @@ void MappedBlockCache::sync(unsigned block)
end = (void *)((ptrdiff_t)end / pagesize * pagesize);
if (::msync(start, pagesize, MS_SYNC) != 0)
throw POSIX::Exception(__METHOD__ ": msync", errno);
throw POSIXException(__METHOD__ ": msync", errno);
if (start != end)
{
if (::msync(end, pagesize, MS_SYNC) != 0)
throw POSIX::Exception(__METHOD__ ": msync", errno);
throw POSIXException(__METHOD__ ": msync", errno);
}
}

View File

@@ -22,12 +22,10 @@ class MappedBlockCache : public BlockCache {
virtual void release(unsigned block, int flags);
virtual void markDirty(unsigned block);
// public so make_shared can access it.
MappedBlockCache(BlockDevicePointer device, void *data);
private:
MappedBlockCache(BlockDevicePointer device, void *data);
void sync(unsigned block);
uint8_t *_data;

View File

@@ -1,44 +0,0 @@
#include "Exception.h"
#include <cstdio>
#include <cstring>
Exception::Exception(const char *cp):
_error(0),
_string(cp)
{
}
Exception::Exception(const std::string& string):
_error(0),
_string(string)
{
}
Exception::Exception(const char *cp, int error):
_error(error),
_string(cp)
{
}
Exception::Exception(const std::string& string, int error):
_error(error),
_string(string)
{
}
Exception::~Exception() throw()
{
}
const char *Exception::what() const throw()
{
return _string.c_str();
}
const char *Exception::errorString()
{
return "";
}

View File

@@ -1,36 +0,0 @@
#ifndef __COMMON_EXCEPTION_H__
#define __COMMON_EXCEPTION_H__
#include <string>
#include <exception>
class Exception : public std::exception
{
public:
Exception(const char *cp);
Exception(const std::string &str);
virtual ~Exception() throw ();
virtual const char *what() const throw();
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;
};
#endif

View File

@@ -1,14 +0,0 @@
#ifndef __COMMON_UNORDERED_MAP_H__
#define __COMMON_UNORDERED_MAP_H__
#if 1
//c++0x
#include <unordered_map>
#define UNORDERED_MAP(...) std::unordered_map(__VA_ARGS__)
#else
// tr1
#include <tr1/unordered_map>
#define UNORDERED_MAP(...) std::tr1::unordered_map(__VA_ARGS__)
#endif
#endif

View File

@@ -5,7 +5,7 @@
#include <cstdio>
#include <Device/Adaptor.h>
#include <Common/Exception.h>
#include <ProFUSE/Exception.h>
using namespace Device;
@@ -142,7 +142,7 @@ uint8_t NibbleAdaptor::encode62(uint8_t val)
};
if (val > 0x3f)
throw ::Exception(__METHOD__ ": Invalid 6-2 value.");
throw ProFUSE::Exception(__METHOD__ ": Invalid 6-2 value.");
return table[val];
}
@@ -165,7 +165,7 @@ uint8_t NibbleAdaptor::decode62(uint8_t val)
};
if ((val < 0x90) || (table[val - 0x90] == 0xff))
throw ::Exception(__METHOD__ ": Invalid 6-2 encoding.");
throw ProFUSE::Exception(__METHOD__ ": Invalid 6-2 encoding.");
return table[val - 0x90];
}
@@ -238,10 +238,10 @@ NibbleAdaptor::NibbleAdaptor(void *address, unsigned length)
checksum = decode44(buffer[offset + 9], buffer[offset + 10]);
if (volume ^ track ^ sector ^ checksum)
throw ::Exception(__METHOD__ ": Invalid address checksum.");
throw ProFUSE::Exception(__METHOD__ ": Invalid address checksum.");
if (track > 35 || sector > 16)
throw ::Exception(__METHOD__ ": Invalid track/sector.");
throw ProFUSE::Exception(__METHOD__ ": Invalid track/sector.");
offset += 3 + 8 + 3;
@@ -294,7 +294,7 @@ NibbleAdaptor::NibbleAdaptor(void *address, unsigned length)
{
int offset = distance(_index.begin(), iter);
std::fprintf(stderr, "Error: track %u sector %u missing.\n", offset / 16, offset % 16);
//throw ::Exception(__METHOD__ ": Sector missing.");
//throw ProFUSE::Exception(__METHOD__ ": Sector missing.");
}
}
@@ -361,7 +361,7 @@ void NibbleAdaptor::readTrackSector(TrackSector ts, void *bp)
#define __METHOD__ "NibbleAdaptor::readTrackSector"
if (ts.track > 35 || ts.sector > 16)
throw ::Exception(__METHOD__ ": Invalid track/sector.");
throw ProFUSE::Exception(__METHOD__ ": Invalid track/sector.");
CircleBuffer buffer(_address, _length);
@@ -374,7 +374,7 @@ void NibbleAdaptor::readTrackSector(TrackSector ts, void *bp)
if (offset == -1)
{
throw ::Exception(__METHOD__ ": Missing track/sector.");
throw ProFUSE::Exception(__METHOD__ ": Missing track/sector.");
}
// first 86 bytes are in the auxbuffer, backwards.
@@ -418,7 +418,7 @@ void NibbleAdaptor::readTrackSector(TrackSector ts, void *bp)
if (checksum != decode62(buffer[index++]))
std::fprintf(stderr, "Invalid checksum on track %u, sector %u\n", ts.track, ts.sector);
//throw ::Exception(__METHOD__ ": Invalid field checksum.");
//throw ProFUSE::Exception(__METHOD__ ": Invalid field checksum.");
}
@@ -428,7 +428,7 @@ void NibbleAdaptor::writeTrackSector(TrackSector ts, const void *bp)
#define __METHOD__ "NibbleAdaptor::writeTrackSector"
if (ts.track > 35 || ts.sector > 16)
throw ::Exception(__METHOD__ ": Invalid track/sector.");
throw ProFUSE::Exception(__METHOD__ ": Invalid track/sector.");
uint8_t auxBuffer[86];
uint8_t checksum = 0;

View File

@@ -12,21 +12,19 @@
#include <Device/BlockDevice.h>
#include <Cache/ConcreteBlockCache.h>
#include <Common/Exception.h>
#include <POSIX/Exception.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>
#ifdef HAVE_NUFX
#include <Device/SDKImage.h>
#endif
using namespace Device;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
unsigned BlockDevice::ImageType(MappedFile *f, unsigned defv)
@@ -40,11 +38,9 @@ unsigned BlockDevice::ImageType(MappedFile *f, unsigned defv)
if (DiskCopy42Image::Validate(f, std::nothrow))
return 'DC42';
#ifdef HAVE_NUFX
if (SDKImage::Validate(f, std::nothrow))
return 'SDK_';
#endif
if (ProDOSOrderDiskImage::Validate(f, std::nothrow))
return 'PO__';
@@ -101,14 +97,13 @@ unsigned BlockDevice::ImageType(const char *type, unsigned defv)
if (::strcasecmp(type, "davex") == 0)
return 'DVX_';
#ifdef HAVE_NUFX
// not supported yet.
if (::strcasecmp(type, "sdk") == 0)
return 'SDK_';
if (::strcasecmp(type, "shk") == 0)
return 'SDK_';
#endif
return defv;
}
@@ -123,7 +118,7 @@ BlockDevicePointer BlockDevice::Open(const char *name, File::FileFlags flags, un
if (::stat(name, &st) != 0)
{
throw POSIX::Exception(__METHOD__ ": stat error", errno);
throw POSIXException(__METHOD__ ": stat error", errno);
}
// /dev/xxx ignore the type.
@@ -155,11 +150,9 @@ BlockDevicePointer BlockDevice::Open(const char *name, File::FileFlags flags, un
case 'DVX_':
return DavexDiskImage::Open(&file);
#if HAVE_NUFX
case 'SDK_':
return SDKImage::Open(name);
#endif
}

View File

@@ -7,8 +7,8 @@
#include <Device/Device.h>
#include <Device/TrackSector.h>
#include <Common/Exception.h>
#include <Common/smart_pointers.h>
#include <ProFUSE/Exception.h>
#include <ProFUSE/smart_pointers.h>
#include <File/File.h>

View File

@@ -19,6 +19,8 @@
using namespace Device;
using namespace LittleEndian;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
/*
http://www.umich.edu/~archive/apple2/technotes/ftn/FTN.E0.8004
@@ -84,7 +86,7 @@ bool DavexDiskImage::Validate(MappedFile *f)
if (!Validate(f, std::nothrow))
throw ::Exception(__METHOD__ ": Invalid file format.");
throw Exception(__METHOD__ ": Invalid file format.");
return true;
}

View File

@@ -25,11 +25,13 @@ public:
static bool Validate(MappedFile *, const std::nothrow_t &);
static bool Validate(MappedFile *);
DavexDiskImage(MappedFile *);
private:
DavexDiskImage();
DavexDiskImage(MappedFile *);
bool _changed;
std::string _volumeName;

View File

@@ -9,7 +9,7 @@
#ifndef __DEVICE_DEVICE_H__
#define __DEVICE_DEVICE_H__
#include <Common/smart_pointers.h>
#include <ProFUSE/smart_pointers.h>
namespace Device {

View File

@@ -16,6 +16,9 @@ using namespace Device;
using namespace BigEndian;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
enum {
@@ -218,7 +221,7 @@ bool DiskCopy42Image::Validate(MappedFile *file)
if (!Validate(file, std::nothrow))
throw ::Exception(__METHOD__ ": Invalid file format.");
throw Exception(__METHOD__ ": Invalid file format.");
return true;
}

View File

@@ -28,13 +28,12 @@ public:
virtual BlockCachePointer createBlockCache();
DiskCopy42Image();
DiskCopy42Image(MappedFile *);
private:
DiskCopy42Image();
DiskCopy42Image(MappedFile *);
bool _changed;
};

View File

@@ -14,11 +14,13 @@
#include <Cache/MappedBlockCache.h>
#include <Common/Exception.h>
#include <ProFUSE/Exception.h>
using namespace Device;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
/*
@@ -72,7 +74,7 @@ void DiskImage::read(unsigned block, void *bp)
#define __METHOD__ "DiskImage::read"
if (block >= _blocks)
throw ::Exception(__METHOD__ ": Invalid block.");
throw Exception(__METHOD__ ": Invalid block.");
_adaptor->readBlock(block, bp);
}
@@ -83,7 +85,7 @@ void DiskImage::write(unsigned block, const void *bp)
#define __METHOD__ "DiskImage::write"
if (block >= _blocks)
throw ::Exception(__METHOD__ ": Invalid block.");
throw Exception(__METHOD__ ": Invalid block.");
_adaptor->writeBlock(block, bp);
}
@@ -95,7 +97,7 @@ void DiskImage::sync()
if (_file.isValid()) return _file.sync();
throw ::Exception(__METHOD__ ": File not set.");
throw Exception(__METHOD__ ": File not set.");
}
@@ -145,10 +147,10 @@ bool ProDOSOrderDiskImage::Validate(MappedFile *f)
#undef __METHOD__
#define __METHOD__ "ProDOSOrderDiskImage::Validate"
if (!f || !f->isValid()) throw ::Exception(__METHOD__ ": File not set.");
if (!f || !f->isValid()) throw Exception(__METHOD__ ": File not set.");
if (!Validate(f, std::nothrow))
throw ::Exception(__METHOD__ ": Invalid file format.");
throw Exception(__METHOD__ ": Invalid file format.");
return true;
}
@@ -216,11 +218,11 @@ bool DOSOrderDiskImage::Validate(MappedFile *f)
#undef __METHOD__
#define __METHOD__ "DOSOrderDiskImage::Validate"
if (!f || !f->isValid()) throw ::Exception(__METHOD__ ": File not set.");
if (!f || !f->isValid()) throw Exception(__METHOD__ ": File not set.");
if (!Validate(f, std::nothrow))
throw ::Exception(__METHOD__ ": Invalid file format.");
throw Exception(__METHOD__ ": Invalid file format.");
return true;
}

View File

@@ -4,6 +4,8 @@
#include <stdint.h>
#include <sys/types.h>
#include <ProFUSE/Exception.h>
#include <Device/BlockDevice.h>
#include <Device/Adaptor.h>
@@ -64,11 +66,10 @@ public:
static bool Validate(MappedFile *, const std::nothrow_t &);
static bool Validate(MappedFile *);
ProDOSOrderDiskImage(MappedFile *);
private:
ProDOSOrderDiskImage();
ProDOSOrderDiskImage(MappedFile *);
};
class DOSOrderDiskImage : public DiskImage {
@@ -80,12 +81,11 @@ public:
static bool Validate(MappedFile *, const std::nothrow_t &);
static bool Validate(MappedFile *);
DOSOrderDiskImage(MappedFile *);
private:
DOSOrderDiskImage();
DOSOrderDiskImage(MappedFile *);
};

View File

@@ -31,11 +31,12 @@
#include <Device/RawDevice.h>
#include <Common/Exception.h>
#include <POSIX/Exception.h>
#include <ProFUSE/Exception.h>
using namespace Device;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
#ifdef __SUN__
void RawDevice::devSize(int fd)
@@ -46,7 +47,7 @@ void RawDevice::devSize(int fd)
struct dk_minfo minfo;
if (::ioctl(fd, DKIOCGMEDIAINFO, &minfo) < 0)
throw POSIX::Exception(__METHOD__ ": Unable to determine device size.", errno);
throw POSIXException(__METHOD__ ": Unable to determine device size.", errno);
_size = minfo.dki_lbsize * minfo.dki_capacity;
_blockSize = 512; // not really, but whatever.
@@ -65,11 +66,11 @@ void RawDevice::devSize(int fd)
uint64_t blockCount; // 64 bit
if (::ioctl(fd, DKIOCGETBLOCKSIZE, &blockSize) < 0)
throw POSIX::Exception(__METHOD__ ": Unable to determine block size.", errno);
throw POSIXException(__METHOD__ ": Unable to determine block size.", errno);
if (::ioctl(fd, DKIOCGETBLOCKCOUNT, &blockCount) < 0)
throw POSIX::Exception(__METHOD__ ": Unable to determine block count.", errno);
throw POSIXException(__METHOD__ ": Unable to determine block count.", errno);
_blockSize = blockSize;
_size = _blockSize * blockCount;
@@ -89,7 +90,7 @@ void RawDevice::devSize(int fd)
int blocks;
if (::ioctl(fd, BLKGETSIZE, &blocks) < 0)
throw POSIX::Exception(__METHOD__ ": Unable to determine device size.", errno);
throw POSIXException(__METHOD__ ": Unable to determine device size.", errno);
_size = 512 * blocks;
_blockSize = 512; //
@@ -112,10 +113,10 @@ void RawDevice::devSize(int fd)
off_t mediaSize;
if (::ioctl(fd, DIOCGSECTORSIZE, &blockSize)
throw POSIX::Exception(__METHOD__ ": Unable to determine block size.", errno);
throw POSIXException(__METHOD__ ": Unable to determine block size.", errno);
if (::ioctl(fd, DIOCGMEDIASIZE, &mediaSize)
throw POSIX::Exception(__METHOD__ ": Unable to determine media size.", errno);
throw POSIXException(__METHOD__ ": Unable to determine media size.", errno);
_blockSize = blockSize;
_size = mediaSize;
@@ -137,7 +138,7 @@ void RawDevice::devSize(int fd)
if (::ioctl(fd, DIOCGETP, &entry) < 0)
throw POSIX::Exception(__METHOD__ ": Unable to determine device size.", errno);
throw POSIXException(__METHOD__ ": Unable to determine device size.", errno);
_size = entry.size
_blockSize = 512; // not really but whatever.
@@ -156,7 +157,7 @@ RawDevice::RawDevice(const char *name, File::FileFlags flags) :
if (!_file.isValid())
{
throw ::Exception(__METHOD__ ": Invalid file handle.");
throw Exception(__METHOD__ ": Invalid file handle.");
}
_readOnly = flags == File::ReadOnly;
@@ -177,7 +178,7 @@ RawDevice::RawDevice(File& file, File::FileFlags flags) :
if (!_file.isValid())
{
throw ::Exception(__METHOD__ ": Invalid file handle.");
throw Exception(__METHOD__ ": Invalid file handle.");
}
_readOnly = flags == File::ReadOnly;
@@ -207,8 +208,8 @@ 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.");
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) ?
@@ -219,8 +220,8 @@ void RawDevice::read(unsigned block, void *bp)
// TODO -- EINTR?
if (ok != 512)
throw ok < 0
? POSIX::Exception(__METHOD__ ": Error reading block.", errno)
: ::Exception(__METHOD__ ": Error reading block.");
? POSIXException(__METHOD__ ": Error reading block.", errno)
: Exception(__METHOD__ ": Error reading block.");
}
@@ -230,8 +231,8 @@ void RawDevice::read(TrackSector ts, void *bp)
#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.");
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) ?
@@ -242,8 +243,8 @@ void RawDevice::read(TrackSector ts, void *bp)
// TODO -- EINTR?
if (ok != 256)
throw ok < 0
? POSIX::Exception(__METHOD__ ": Error reading block.", errno)
: ::Exception(__METHOD__ ": Error reading block.");
? POSIXException(__METHOD__ ": Error reading block.", errno)
: Exception(__METHOD__ ": Error reading block.");
}
@@ -252,10 +253,10 @@ void RawDevice::write(unsigned block, const void *bp)
#undef __METHOD__
#define __METHOD__ "RawDevice::write"
if (block > _blocks) throw ::Exception(__METHOD__ ": Invalid block number.");
if (block > _blocks) throw Exception(__METHOD__ ": Invalid block number.");
if (_readOnly)
throw ::Exception(__METHOD__ ": File is readonly.");
throw Exception(__METHOD__ ": File is readonly.");
off_t offset = block * 512;
@@ -263,8 +264,8 @@ void RawDevice::write(unsigned block, const void *bp)
if (ok != 512)
throw ok < 0
? POSIX::Exception(__METHOD__ ": Error writing block.", errno)
: ::Exception(__METHOD__ ": Error writing block.");
? POSIXException(__METHOD__ ": Error writing block.", errno)
: Exception(__METHOD__ ": Error writing block.");
}
@@ -274,10 +275,10 @@ void RawDevice::write(TrackSector ts, const void *bp)
#define __METHOD__ "RawDevice::write"
unsigned block = ts.track * 8 + ts.sector / 2;
if (block > _blocks) throw ::Exception(__METHOD__ ": Invalid block number.");
if (block > _blocks) throw Exception(__METHOD__ ": Invalid block number.");
if (_readOnly)
throw ::Exception(__METHOD__ ": File is readonly.");
throw Exception(__METHOD__ ": File is readonly.");
off_t offset = (ts.track * 16 + ts.sector) * 256;
@@ -285,8 +286,8 @@ void RawDevice::write(TrackSector ts, const void *bp)
if (ok != 256)
throw ok < 0
? POSIX::Exception(__METHOD__ ": Error writing block.", errno)
: ::Exception(__METHOD__ ": Error writing block.");
? POSIXException(__METHOD__ ": Error writing block.", errno)
: Exception(__METHOD__ ": Error writing block.");
}
@@ -315,6 +316,6 @@ void RawDevice::sync()
if (_readOnly) return;
if (::fsync(_file.fd()) < 0)
throw POSIX::Exception(__METHOD__ ": fsync error.", errno);
throw POSIXException(__METHOD__ ": fsync error.", errno);
}

View File

@@ -33,11 +33,13 @@ public:
virtual void sync();
virtual unsigned blocks();
RawDevice(const char *name, File::FileFlags flags);
RawDevice(File& file, File::FileFlags flags);
private:
RawDevice(const char *name, File::FileFlags flags);
RawDevice(File& file, File::FileFlags flags);
void devSize(int fd);

View File

@@ -12,7 +12,6 @@
#include <cstdlib>
#include <cstdio>
#include <cerrno>
#include <cstring>
#include <NufxLib.h>
@@ -20,9 +19,39 @@
#include <File/File.h>
#include <File/MappedFile.h>
#include <Common/Exception.h>
#include <NuFX/Exception.h>
#include <POSIX/Exception.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;
@@ -46,7 +75,7 @@ static record_thread FindDiskImageThread(NuArchive *archive)
e = NuGetAttr(archive, kNuAttrNumRecords, &recordCount);
if (e)
{
throw NuFX::Exception(__METHOD__ ": NuGetAttr", e);
throw NuFXException(__METHOD__ ": NuGetAttr", e);
}
for (unsigned position = 0; position < recordCount; ++position)
@@ -57,20 +86,20 @@ static record_thread FindDiskImageThread(NuArchive *archive)
e = NuGetRecordIdxByPosition(archive, position, &rIndex);
if (e)
{
throw NuFX::Exception(__METHOD__ ": NuGetRecordIdxByPosition", e);
throw NuFXException(__METHOD__ ": NuGetRecordIdxByPosition", e);
}
e = NuGetRecord(archive, rIndex, &record);
if (e)
{
throw NuFX::Exception(__METHOD__ ": NuGetRecord", e);
throw NuFXException(__METHOD__ ": NuGetRecord", e);
}
for (unsigned i = 0; i < NuRecordGetNumThreads(record); ++i)
{
const NuThread *thread = NuGetThread(record, i);
if (thread && NuGetThreadID(thread) == kNuThreadIDDiskImage)
if (NuGetThreadID(thread) == kNuThreadIDDiskImage)
{
rt.thread_index = thread->threadIdx;
rt.record_index = record->recordIdx;
@@ -79,7 +108,7 @@ static record_thread FindDiskImageThread(NuArchive *archive)
}
}
throw ::Exception(__METHOD__ ": not a disk image");
throw Exception(__METHOD__ ": not a disk image");
}
@@ -117,7 +146,7 @@ BlockDevicePointer SDKImage::Open(const char *name)
e = NuOpenRO(name, &archive);
if (e)
{
throw NuFX::Exception(__METHOD__ ": NuOpenRO", e);
throw NuFXException(__METHOD__ ": NuOpenRO", e);
}
rt = FindDiskImageThread(archive);
@@ -125,27 +154,27 @@ BlockDevicePointer SDKImage::Open(const char *name)
fd = mkstemp(tmp);
if (fd < 0)
{
throw POSIX::Exception(__METHOD__ ": mkstemp", errno);
throw POSIXException(__METHOD__ ": mkstemp", errno);
}
fp = fdopen(fd, "w");
if (!fp)
{
::close(fd);
throw POSIX::Exception(__METHOD__ ": fdopen", errno);
throw POSIXException(__METHOD__ ": fdopen", errno);
}
e = NuCreateDataSinkForFP(true, kNuConvertOff, fp, &sink);
if (e)
{
throw NuFX::Exception(__METHOD__ ": NuCreateDataSinkForFP", e);
throw NuFXException(__METHOD__ ": NuCreateDataSinkForFP", e);
}
e = NuExtractThread(archive, rt.thread_index, sink);
if (e)
{
throw NuFX::Exception(__METHOD__ ": NuExtractThread", e);
throw NuFXException(__METHOD__ ": NuExtractThread", e);
}
fprintf(stderr, "Extracted disk image to %s\n", tmp);
@@ -211,7 +240,7 @@ bool SDKImage::Validate(MappedFile * f)
#define __METHOD__ "SDKImage::Validate"
if (!Validate(f, std::nothrow))
throw ::Exception(__METHOD__ ": Invalid file format.");
throw Exception(__METHOD__ ": Invalid file format.");
return true;
}

View File

@@ -3,7 +3,7 @@
#include <Endian/Endian.h>
#include <Endian/IOBuffer.h>
#include <Common/Exception.h>
#include <ProFUSE/Exception.h>
#include <Cache/MappedBlockCache.h>
#include <Cache/ConcreteBlockCache.h>
@@ -11,6 +11,10 @@
using namespace Device;
using namespace LittleEndian;
using ProFUSE::Exception;
using ProFUSE::POSIXException;
UniversalDiskImage::UniversalDiskImage(MappedFile *file) :
@@ -107,7 +111,6 @@ bool UniversalDiskImage::Validate(MappedFile *file, const std::nothrow_t &)
unsigned blocks = 0;
unsigned offset = 0;
unsigned fileSize = 0;
if (size < 64) return false;
@@ -122,11 +125,8 @@ bool UniversalDiskImage::Validate(MappedFile *file, const std::nothrow_t &)
offset = Read32(data, 0x18);
// file size == blocks * 512
// file size blank in some cases.
//if (Read32(data, 0x1c) != blocks * 512) return false;
fileSize = Read32(data, 0x1c);
if (fileSize != 0 && fileSize != blocks * 512) return false;
if (Read32(data, 0x1c) != blocks * 512) return false;
if (offset + blocks * 512 > size) return false;
return true;
@@ -138,7 +138,7 @@ bool UniversalDiskImage::Validate(MappedFile *file)
#define __METHOD__ "UniversalDiskImage::Validate"
if (!Validate(file, std::nothrow))
throw ::Exception(__METHOD__ ": Invalid file format.");
throw Exception(__METHOD__ ": Invalid file format.");
return true;
}

View File

@@ -26,10 +26,11 @@ public:
static bool Validate(MappedFile *);
UniversalDiskImage(MappedFile *);
private:
UniversalDiskImage();
UniversalDiskImage(MappedFile *);
uint32_t _format;
uint32_t _flags;

View File

@@ -1,107 +0,0 @@
#include <cstring>
#include <memory>
#include "Entry.h"
#include "Buffer.h"
#include "Endian.h"
#include "BlockDevice.h"
#include "Exception.h"
using namespace ProFUSE;
using namespace LittleEndian;
Directory::Directory(unsigned type, const char *name) :
Entry(type, name)
{
#undef __METHOD__
#define __METHOD__ "Directory::Directory"
_access = 0xe3;
_entryLength = 0x27;
_entriesPerBlock = 13;
_fileCount = 0;
_version = 5; // ProDOS FST uses 5, ProDOS uses 0.
_minVersion = 0;
}
Directory::Directory(const void *bp) :
Entry(4 + (const uint8_t *)bp),
_creation(0, 0)
{
#undef __METHOD__
#define __METHOD__ "Directory::Directory"
// input is a block pointer. To simplify,
// create a new pointer past the 4-byte linked list part.
const void *dp = 4 + (const uint8_t *)bp;
_creation = DateTime(Read16(dp, 0x18), Read16(dp, 0x1a));
_version = Read8(dp, 0x1c);
_minVersion = Read8(dp, 0x1d);
_access = Read8(dp, 0x1e);
_entryLength = Read8(dp, 0x1f);
_entriesPerBlock = Read8(dp, 0x20);
_fileCount = Read16(dp, 0x21);
// parse child file entries ... requires ability to read other blocks.
}
Directory::~Directory()
{
}
void Directory::setAccess(unsigned access)
{
#undef __METHOD__
#define __METHOD__ "Directory::setAccess"
_access = access;
// todo -- mark dirty? update block?
}
void Directory::loadChildren(BlockDevice *device, unsigned block)
{
uint8_t buffer[512];
unsigned next;
bool first = true;
unsigned offset;
// set of already-visited blocks?
while(block)
{
device->read(block, buffer);
next = Read16(buffer, 2);
_entryBlocks.push_back(block);
offset = 4;
if (!first)
{
// storage type 0 is deleted, don't load...
}
first = false;
block = next;
}
}

View File

@@ -16,8 +16,8 @@
#include <sys/stat.h>
#include <sys/mman.h>
#include <cstdio>
#include <cstring>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <set>
@@ -207,9 +207,6 @@ void *Disk::ReadFile(const FileEntry &f, unsigned fork, uint32_t *size, int *err
case TREE_FILE:
ok = ReadIndex(f.key_pointer, buffer, 2, 0, blocks);
break;
default:
ok = false;
}
if (ok < 0)

View File

@@ -16,8 +16,7 @@
#include <ProDOS/File.h>
#include <Device/BlockDevice.h>
#include <memory>
#include <Common/smart_pointers.h>
#include <tr1/memory>
enum {
@@ -45,7 +44,7 @@ enum {
};
class Disk;
typedef SHARED_PTR(Disk) DiskPointer;
typedef std::tr1::shared_ptr<Disk> DiskPointer;
class Disk {

View File

@@ -1,7 +0,0 @@
CC = g++
CPPFLAGS += -g -Wall -I../
all : Endian.o
Endian.o : Endian.cpp Endian.h

173
Entry.cpp
View File

@@ -1,173 +0,0 @@
#include "Entry.h"
#include "Endian.h"
#include "Buffer.h"
#include "Exception.h"
using namespace ProFUSE;
using namespace LittleEndian;
// do it ourselves since could be different locale or something.
#undef isalpha
#undef isalnumdot
#undef islower
#undef tolower
#undef toupper
static bool isalpha(char c)
{
return (c >= 'A' && c <= 'Z')
|| (c >= 'a' && c <= 'z') ;
}
static bool isalnumdot(char c)
{
return (c >= 'A' && c <= 'Z')
|| (c >= 'a' && c <= 'z')
|| (c >= '0' && c <='9')
|| (c == '.') ;
}
static bool islower(char c)
{
return c >= 'a' && c <= 'z';
}
inline char tolower(char c) { return c | 0x20; }
inline char toupper(char c) { return c & ~0x20; }
/*
* ProDOS names:
* 1-15 letters, digits, or '.'
* first character must be a letter.
*/
unsigned Entry::ValidName(const char *name)
{
unsigned length = 1;
if (!name) return 0;
if (!isalpha(*name)) return 0;
for (length = 1; length < 17; ++length)
{
char c = name[length];
if (isalnumdot(c)) continue;
if (c == 0) break;
return 0;
}
if (length > 15) return 0;
return length;
}
Entry::Entry(unsigned type, const char *name)
{
_address = 0;
_index = 0;
_volume = NULL;
_nameLength = 0;
_caseFlag = 0;
_storageType = type;
// everything else initialized in setName.
setName(name);
}
Entry::Entry(const void *bp)
{
#undef __METHOD__
#define __METHOD__ "Entry::Entry"
uint8_t x;
uint16_t xcase = 0;
_address = 0;
_index = 0;
_volume = NULL;
_caseFlag = 0;
_nameLength = 0;
std::memset(_name, 0, 16);
std::memset(_namei, 0, 16);
x = Read8(bp, 0x00);
_storageType = x >> 4;
_nameLength = x & 0x0f;
for (unsigned i = 0; i < _nameLength; ++i)
{
_name[i] = _namei[i] = Read8(bp, i + 1);
// check legality?
}
switch (_storageType)
{
case SeedlingFile:
case SaplingFile:
case TreeFile:
case PascalFile:
case ExtendedFile:
case DirectoryFile:
xcase = Read16(bp, 0x1c);
break;
case VolumeHeader:
xcase = Read16(bp, 0x16);
break;
}
if (xcase & 0x8000)
{
_caseFlag = xcase;
xcase <<= 1;
for (unsigned i = 0; i < _nameLength; ++i, xcase <<= 1)
{
if (xcase & 0x8000)
_name[i] = tolower(_name[i]);
}
}
}
Entry::~Entry()
{
}
/*
* IIgs Technote #8:
*
* bit 15 set
* bit 14 + i set if name[i] is lowercase.
*/
void Entry::setName(const char *name)
{
#undef __METHOD__
#define __METHOD__ "Entry::setName"
unsigned caseFlag = 0x8000;
unsigned length = ValidName(name);
if (!length) throw Exception("Invalid name.");
std::memset(_name, 0, 16);
std::memset(_namei, 0, 16);
for (unsigned i = 0; i < length; ++i)
{
char c = name[i];
_name[i] = c;
_namei[i] = toupper(c);
if (islower(c))
{
caseFlag |= (0x4000 >> i);
}
}
_nameLength = length;
_caseFlag = caseFlag;
}

284
Entry.h
View File

@@ -1,284 +0,0 @@
#ifndef __DIRECTORY_H__
#define __DIRECTORY_H__
#include <vector>
#include <stdint.h>
#include "DateTime.h"
namespace ProFUSE {
class BlockDevice;
class Bitmap;
class FileEntry;
class Volume;
class Buffer;
enum Access {
DestroyEnabled = 0x80,
RenameEnabled = 0x40,
BackupNeeded = 0x20,
Invisible = 0x04,
WriteEnabled = 0x02,
ReadEnabled = 0x01
};
enum StorageType {
DeletedFile = 0x00,
SeedlingFile = 0x01,
SaplingFile = 0x02,
TreeFile = 0x03,
PascalFile = 0x04,
ExtendedFile = 0x05,
DirectoryFile = 0x0d,
DirectoryHeader = 0x0e,
VolumeHeader = 0x0f
};
class Entry {
public:
virtual ~Entry();
virtual void write(Buffer *) = 0;
unsigned storageType() const { return _storageType; }
unsigned nameLength() const { return _nameLength; }
const char *name() const { return _name; }
const char *namei() const { return _namei; }
unsigned caseFlag() const { return _caseFlag; }
void setName(const char *name);
// returns strlen() on success, 0 on failure.
static unsigned ValidName(const char *);
unsigned block() const { return _address / 512; }
unsigned offset() const { return _address % 512; }
unsigned address() const { return _address; }
unsigned index() const { return _index; }
Volume *volume() { return _volume; }
protected:
Entry(unsigned storageType, const char *name);
Entry(const void *bp);
void setStorageType(unsigned type)
{ _storageType = type; }
void setAddress(unsigned address)
{ _address = address; }
void setIndex(unsigned index)
{ _index = index; }
void setVolume(Volume *v)
{ _volume = v; }
private:
unsigned _address;
unsigned _index;
Volume *_volume;
unsigned _storageType;
unsigned _nameLength;
char _namei[15+1]; // insensitive, ie, uppercase.
char _name[15+1];
unsigned _caseFlag;
};
class Directory : public Entry {
public:
enum {
OffsetCreation = 0x18,
OffsetVersion = 0x1c,
OffsetMinVersion = 0x1d,
OffsetAccess = 0x1e,
OffsetEntryLength = 0x1f,
OffsetEntriesPerBlock = 0x20,
OffsetFileCount = 0x21
};
virtual ~Directory();
DateTime creation() const { return _creation; }
unsigned access() const { return _access; }
unsigned entryLength() const { return _entryLength; }
unsigned entriesPerBlock() const { return _entriesPerBlock; }
unsigned fileCount() const { return _fileCount; }
unsigned version() const { return _version; }
unsigned minVersion() const { return _minVersion; }
void setAccess(unsigned access);
protected:
Directory(unsigned type, const char *name);
Directory(const void *bp);
std::vector<FileEntry *> _children;
std::vector<unsigned> _entryBlocks;
void loadChildren(BlockDevice *, unsigned block);
private:
DateTime _creation;
unsigned _version;
unsigned _minVersion;
unsigned _access;
unsigned _entryLength; // always 0x27
unsigned _entriesPerBlock; //always 0x0d
unsigned _fileCount;
};
class VolumeDirectory: public Directory {
public:
enum {
OffsetLastMod = 0x12,
OffsetFileNameCaseFlag = 0x16,
OffsetBitmapPointer = 0x23,
OffsetTotalBlocks = 0x25
};
static VolumeDirectory *Create(const char *name, BlockDevice *device);
static VolumeDirectory *Create(BlockDevice *);
virtual ~VolumeDirectory();
unsigned bitmapPointer() const { return _bitmapPointer; }
unsigned totalBlocks() const { return _totalBlocks; }
// bitmap stuff...
int allocBlock();
void freeBlock(unsigned block);
virtual void write(Buffer *);
BlockDevice *device() const { return _device; }
private:
VolumeDirectory(const char *name, BlockDevice *device);
VolumeDirectory(BlockDevice *device, const void *bp);
Bitmap *_bitmap;
BlockDevice *_device;
DateTime _modification;
unsigned _totalBlocks;
unsigned _bitmapPointer;
// inode / free inode list?
};
class SubDirectory : public Directory {
public:
enum {
OffsetPasswordEnabled = 0x10,
OffsetParentPointer = 0x23,
OffsetParentEntryNumber = 0x25,
OffsetParentEntryLength = 0x26
};
SubDirectory(FileEntry *);
private:
unsigned _parentPointer;
unsigned _parentEntryNumber;
unsigned _parentEntryLength;
};
class FileEntry : public Entry {
public:
enum {
OffsetFileType = 0x10,
OffsetKeyPointer = 0x11,
OffsetBlocksUsed = 0x13,
OffsetEOF = 0x15,
OffsetCreation = 0x18,
OffsetVersion = 0x1c,
OffsetMinVersion = 0x1d,
OffsetFileNameCaseFlag = 0x1c,
OffsetAccess = 0x1e,
OffsetAuxType = 0x1f,
OffsetLastMod = 0x21,
OffsetHeaderPointer = 0x25
};
unsigned fileType() const { return _fileType; }
unsigned auxType() const { return _auxType; }
unsigned blocksUsed() const { return _blocksUsed; }
unsigned eof() const { return _eof; }
unsigned access() const { return _access; }
DateTime creation() const { return _creation; }
DateTime modification() const { return _modification; }
private:
void *acquirePointer();
void releasePointer();
unsigned _fileType;
unsigned _keyPointer;
unsigned _blocksUsed;
unsigned _eof;
DateTime _creation;
//version
//min version
unsigned _access;
unsigned _auxType;
DateTime _modification;
unsigned _headerPointer;
};
}
#endif

View File

@@ -2,8 +2,12 @@
#include <cerrno>
#include <File/File.h>
#include <Common/Exception.h>
#include <POSIX/Exception.h>
#include <ProFUSE/Exception.h>
using ProFUSE::Exception;
using ProFUSE::POSIXException;
File::File()
@@ -45,7 +49,7 @@ File::File(const char *name, int flags)
_fd = ::open(name, flags);
if (_fd < 0)
throw POSIX::Exception( __METHOD__ ": open", errno);
throw POSIXException( __METHOD__ ": open", errno);
}
File::File(const char *name, int flags, mode_t mode)
@@ -55,7 +59,7 @@ File::File(const char *name, int flags, mode_t mode)
_fd = ::open(name, flags, mode);
if (_fd < 0)
throw POSIX::Exception( __METHOD__ ": open", errno);
throw POSIXException( __METHOD__ ": open", errno);
}
@@ -66,7 +70,7 @@ File::File(const char *name, FileFlags flags)
_fd = ::open(name, flags == ReadOnly ? O_RDONLY : O_RDWR);
if (_fd < 0)
throw POSIX::Exception( __METHOD__ ": open", errno);
throw POSIXException( __METHOD__ ": open", errno);
}
@@ -95,7 +99,7 @@ void File::close()
// destructor shouldn't throw.
/*
if (::close(fd) != 0)
throw POSIX::Exception(__METHOD__ ": close", errno);
throw POSIXException(__METHOD__ ": close", errno);
*/
}
}

View File

@@ -4,8 +4,10 @@
#include <sys/stat.h>
#include <File/MappedFile.h>
#include <Common/Exception.h>
#include <POSIX/Exception.h>
#include <ProFUSE/Exception.h>
using ProFUSE::POSIXException;
MappedFile::MappedFile()
{
@@ -79,16 +81,16 @@ void MappedFile::init(const File &f, bool readOnly, size_t size)
// close enough
if (f.fd() < 0)
throw POSIX::Exception( __METHOD__, EBADF);
throw POSIXException( __METHOD__, EBADF);
if (!size)
{
if (::fstat(f.fd(), &st) != 0)
throw POSIX::Exception(__METHOD__ ": fstat", errno);
throw POSIXException(__METHOD__ ": fstat", errno);
if (!S_ISREG(st.st_mode))
throw POSIX::Exception(__METHOD__, ENODEV);
throw POSIXException(__METHOD__, ENODEV);
size = st.st_size;
}
@@ -97,7 +99,7 @@ void MappedFile::init(const File &f, bool readOnly, size_t size)
_address = ::mmap(0, _length, prot, flags, f.fd(), 0);
if (_address == MAP_FAILED)
throw POSIX::Exception(__METHOD__ ": mmap", errno);
throw POSIXException(__METHOD__ ": mmap", errno);
_readOnly = readOnly;
}
@@ -125,7 +127,7 @@ void MappedFile::close()
// destructor shouldn't throw.
/*
if (::munmap(address, length) != 0)
throw POSIX::Exception(__METHOD__ ": munmap", errno);
throw POSIXException(__METHOD__ ": munmap", errno);
*/
}
}
@@ -138,7 +140,7 @@ void MappedFile::sync()
if (_address != MAP_FAILED)
{
if (::msync(_address, _length, MS_SYNC) != 0)
throw POSIX::Exception(__METHOD__ ": msync", errno);
throw POSIXException(__METHOD__ ": msync", errno);
}
}
@@ -171,14 +173,14 @@ MappedFile *MappedFile::Create(const char *name, size_t size)
if (!fd.isValid())
{
throw POSIX::Exception(__METHOD__ ": Unable to create file.", errno);
throw POSIXException(__METHOD__ ": Unable to create file.", errno);
}
// TODO -- is ftruncate portable?
if (::ftruncate(fd.fd(), size) < 0)
{
// TODO -- unlink?
throw POSIX::Exception(__METHOD__ ": Unable to truncate file.", errno);
throw POSIXException(__METHOD__ ": Unable to truncate file.", errno);
}
return new MappedFile(fd, File::ReadWrite, size);

192
MacRoman.cpp Normal file
View File

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

26
MacRoman.h Normal file
View File

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

284
Makefile
View File

@@ -1,284 +0,0 @@
CC = c++
CPPFLAGS += -Wall -W -Wno-multichar -Wno-unused-parameter -Wno-unknown-pragmas -Wno-narrowing -I. -O2 -g -std=c++11
LDFLAGS += -pthread
UNAME = $(shell uname -s)
ifeq ($(UNAME),Darwin)
# should use pkg-config but it may not be installed.
FUSE_LIBS += -losxfuse -pthread -liconv
CPPFLAGS += -I/usr/local/include/osxfuse/fuse -D_FILE_OFFSET_BITS=64 -D_DARWIN_USE_64_BIT_INODE
else
CPPFLAGS += $(shell pkg-config --cflags fuse)
FUSE_LIBS += $(shell pkg-config --libs fuse)
endif
ifdef HAVE_NUFX
DEVICE_OBJECTS += Device/SDKImage.o
EXCEPTION_OBJECTS += NuFX/Exception.o
LDFLAGS += -L/usr/local/lib/
LIBS += -lnufx -lz
ifeq ($(UNAME),Darwin)
LIBS += -framework carbon
endif
CPPFLAGS += -DHAVE_NUFX=1
endif
OBJECTS += ${wildcard *.o}
OBJECTS += ${wildcard bin/*.o}
OBJECTS += ${wildcard Cache/*.o}
OBJECTS += ${wildcard Device/*.o}
OBJECTS += ${wildcard Endian/*.o}
OBJECTS += ${wildcard File/*.o}
OBJECTS += ${wildcard Pascal/*.o}
OBJECTS += ${wildcard Common/*.o}
OBJECTS += ${wildcard ProDOS/*.o}
OBJECTS += ${wildcard POSIX/*.o}
OBJECTS += ${wildcard NuFX/*.o}
TARGETS = o/apfm o/newfs_pascal o/fuse_pascal o/profuse o/xattr
BIN_OBJECTS += bin/apfm.o
BIN_OBJECTS += bin/fuse_pascal_ops.o
BIN_OBJECTS += bin/newfs_prodos.o
BIN_OBJECTS += bin/fuse_pascal.o
BIN_OBJECTS += bin/newfs_pascal.o
BIN_OBJECTS += bin/xattr.o
BIN_OBJECTS += bin/profuse.o
BIN_OBJECTS += bin/profuse_dirent.o
BIN_OBJECTS += bin/profuse_file.o
BIN_OBJECTS += bin/profuse_stat.o
BIN_OBJECTS += bin/profuse_xattr.o
CACHE_OBJECTS += Cache/BlockCache.o
CACHE_OBJECTS += Cache/ConcreteBlockCache.o
CACHE_OBJECTS += Cache/MappedBlockCache.o
DEVICE_OBJECTS += Device/Adaptor.o
DEVICE_OBJECTS += Device/BlockDevice.o
DEVICE_OBJECTS += Device/DavexDiskImage.o
DEVICE_OBJECTS += Device/DiskCopy42Image.o
DEVICE_OBJECTS += Device/DiskImage.o
DEVICE_OBJECTS += Device/RawDevice.o
DEVICE_OBJECTS += Device/UniversalDiskImage.o
ENDIAN_OBJECTS += Endian/Endian.o
FILE_OBJECTS += File/File.o
FILE_OBJECTS += File/MappedFile.o
PASCAL_OBJECTS += Pascal/Date.o
PASCAL_OBJECTS += Pascal/FileEntry.o
PASCAL_OBJECTS += Pascal/TextWriter.o
PASCAL_OBJECTS += Pascal/Entry.o
PASCAL_OBJECTS += Pascal/VolumeEntry.o
COMMON_OBJECTS += Common/Lock.o
PRODOS_OBJECTS += ProDOS/DateTime.o
PRODOS_OBJECTS += ProDOS/Disk.o
PRODOS_OBJECTS += ProDOS/File.o
EXCEPTION_OBJECTS += Common/Exception.o
EXCEPTION_OBJECTS += ProDOS/Exception.o
EXCEPTION_OBJECTS += POSIX/Exception.o
all: $(TARGETS)
apfm: o/apfm
@true
fuse_pascal: o/fuse_pascal
@true
newfs_pascal: o/newfs_pascal
@true
profuse: o/profuse
@true
xattr: o/xattr
@true
o:
mkdir $@
o/xattr: bin/xattr.o | o
$(CC) $(LDFLAGS) $^ $(LIBS) -o $@
o/newfs_pascal: bin/newfs_pascal.o \
${CACHE_OBJECTS} \
${DEVICE_OBJECTS} \
${ENDIAN_OBJECTS} \
${FILE_OBJECTS} \
${COMMON_OBJECTS} \
${EXCEPTION_OBJECTS} \
${PASCAL_OBJECTS} | o
$(CC) $(LDFLAGS) $^ $(LIBS) -o $@
o/apfm: bin/apfm.o \
${CACHE_OBJECTS} \
${DEVICE_OBJECTS} \
${ENDIAN_OBJECTS} \
${FILE_OBJECTS} \
${COMMON_OBJECTS} \
${EXCEPTION_OBJECTS} \
${PASCAL_OBJECTS} | o
$(CC) $(LDFLAGS) $^ $(LIBS) -o $@
o/fuse_pascal: bin/fuse_pascal.o bin/fuse_pascal_ops.o \
${CACHE_OBJECTS} \
${DEVICE_OBJECTS} \
${ENDIAN_OBJECTS} \
${FILE_OBJECTS} \
${COMMON_OBJECTS} \
${EXCEPTION_OBJECTS} \
${PASCAL_OBJECTS} | o
$(CC) $(LDFLAGS) $^ $(LIBS) $(FUSE_LIBS) -o $@
o/profuse: bin/profuse.o bin/profuse_dirent.o bin/profuse_file.o \
bin/profuse_stat.o bin/profuse_xattr.o \
${CACHE_OBJECTS} \
${DEVICE_OBJECTS} \
${ENDIAN_OBJECTS} \
${FILE_OBJECTS} \
${COMMON_OBJECTS} \
${EXCEPTION_OBJECTS} \
${PRODOS_OBJECTS} | o
$(CC) $(LDFLAGS) $^ $(LIBS) $(FUSE_LIBS) -o $@
clean:
rm -f ${OBJECTS} ${TARGETS}
xattr.o: bin/xattr.cpp
newfs_pascal.o: bin/newfs_pascal.cpp Device/BlockDevice.h Common/Exception.h \
Device/TrackSector.h Cache/BlockCache.h Device/RawDevice.h File/File.h \
Pascal/Pascal.h Pascal/Date.h
fuse_pascal.o: bin/fuse_pascal.cpp Pascal/Pascal.h Pascal/Date.h \
Common/Exception.h Device/BlockDevice.h Device/TrackSector.h \
Cache/BlockCache.h
fuse_pascal_ops.o: bin/fuse_pascal_ops.cpp Pascal/Pascal.h Pascal/Date.h \
Common/auto.h Common/Exception.h
apfm.o: bin/apfm.cpp Pascal/Pascal.h Pascal/Date.h Device/BlockDevice.h \
Common/Exception.h Device/TrackSector.h Cache/BlockCache.h
File/File.o: File/File.cpp File/File.h Common/Exception.h
File/MappedFile.o: File/MappedFile.cpp File/MappedFile.h File/File.h \
Common/Exception.h
Device/Adaptor.o: Device/Adaptor.cpp Device/Adaptor.h Device/TrackSector.h \
Common/Exception.h
Device/BlockDevice.o: Device/BlockDevice.cpp Device/BlockDevice.h \
Common/Exception.h Device/TrackSector.h Cache/BlockCache.h \
Cache/ConcreteBlockCache.h Device/DiskImage.h Device/Adaptor.h \
File/MappedFile.h File/File.h Device/UniversalDiskImage.h \
Device/DiskCopy42Image.h Device/DavexDiskImage.h Device/RawDevice.h
Device/DavexDiskImage.o: Device/DavexDiskImage.cpp \
Device/DavexDiskImage.h \
Device/BlockDevice.h Common/Exception.h Device/TrackSector.h \
Cache/BlockCache.h Device/DiskImage.h Device/Adaptor.h \
File/MappedFile.h File/File.h Endian/Endian.h Endian/IOBuffer.h \
Endian/IOBuffer.cpp.h Cache/MappedBlockCache.h
Device/DiskCopy42Image.o: Device/DiskCopy42Image.cpp \
Device/DiskCopy42Image.h \
Device/BlockDevice.h Common/Exception.h Device/TrackSector.h \
Cache/BlockCache.h Device/DiskImage.h Device/Adaptor.h \
File/MappedFile.h File/File.h Endian/Endian.h Endian/IOBuffer.h \
Endian/IOBuffer.cpp.h Cache/MappedBlockCache.h
Device/DiskImage.o: Device/DiskImage.cpp Device/DiskImage.h \
Common/Exception.h \
Device/BlockDevice.h Device/TrackSector.h Cache/BlockCache.h \
Device/Adaptor.h File/MappedFile.h File/File.h Cache/MappedBlockCache.h
Device/RawDevice.o: Device/RawDevice.cpp Device/RawDevice.h \
Device/BlockDevice.h \
Common/Exception.h Device/TrackSector.h Cache/BlockCache.h File/File.h
Device/UniversalDiskImage.o: Device/UniversalDiskImage.cpp \
Device/UniversalDiskImage.h Device/BlockDevice.h Common/Exception.h \
Device/TrackSector.h Cache/BlockCache.h Device/DiskImage.h \
Device/Adaptor.h File/MappedFile.h File/File.h Endian/Endian.h \
Endian/IOBuffer.h Endian/IOBuffer.cpp.h Cache/MappedBlockCache.h \
Cache/ConcreteBlockCache.h
Endian/Endian.o: Endian/Endian.cpp Endian/Endian.h
Cache/BlockCache.o: Cache/BlockCache.cpp Cache/BlockCache.h \
Device/BlockDevice.h Common/Exception.h Device/TrackSector.h \
Common/auto.h
Cache/ConcreteBlockCache.o: Cache/ConcreteBlockCache.cpp \
Device/BlockDevice.h \
Common/Exception.h Device/TrackSector.h Cache/BlockCache.h \
Cache/ConcreteBlockCache.h Common/auto.h
Cache/MappedBlockCache.o: Cache/MappedBlockCache.cpp \
Cache/MappedBlockCache.h \
Cache/BlockCache.h Device/BlockDevice.h Common/Exception.h \
Device/TrackSector.h
Common/Exception.o: Common/Exception.cpp Common/Exception.h
Common/Lock.o: Common/Lock.cpp Common/Lock.h
Pascal/Date.o: Pascal/Date.cpp Pascal/Date.h
Pascal/Entry.o: Pascal/Entry.cpp Pascal/Entry.h Pascal/Date.h \
Common/Exception.h Endian/Endian.h Endian/IOBuffer.h \
Endian/IOBuffer.cpp.h Device/BlockDevice.h Device/TrackSector.h \
Cache/BlockCache.h
Pascal/FileEntry.o: Pascal/FileEntry.cpp Pascal/Pascal.h Pascal/Date.h \
Pascal/Entry.h Pascal/FileEntry.h Pascal/VolumeEntry.h Common/auto.h \
Common/Exception.h Endian/Endian.h Endian/IOBuffer.h \
Endian/IOBuffer.cpp.h Device/BlockDevice.h Device/TrackSector.h \
Cache/BlockCache.h Pascal/TextWriter.h
Pascal/VolumeEntry.o: Pascal/VolumeEntry.cpp Pascal/Pascal.h Pascal/Date.h \
Pascal/Entry.h Pascal/FileEntry.h Pascal/VolumeEntry.h Common/auto.h \
Common/Exception.h Endian/Endian.h Endian/IOBuffer.h \
Endian/IOBuffer.cpp.h Device/BlockDevice.h Device/TrackSector.h \
Cache/BlockCache.h
Pascal/TextWriter.o: Pascal/TextWriter.cpp Pascal/TextWriter.h \
Pascal/FileEntry.h Pascal/Entry.h Pascal/Date.h Common/Exception.h
ProDOS/DateTime.o: ProDOS/DateTime.cpp ProDOS/DateTime.h
ProDOS/Disk.o: ProDOS/Disk.cpp ProDOS/Disk.h
ProDOS/File.o: ProDOS/File.cpp ProDOS/File.h
ProDOS/Exception.o: ProDOS/Exception.cpp ProDOS/Exception.h Common/Exception.h
NuFX/Exception.o: NuFX/Exception.cpp NuFX/Exception.h Common/Exception.h
POSIX/Exception.o: POSIX/Exception.cpp POSIX/Exception.h Common/Exception.h

View File

@@ -1,63 +0,0 @@
#include "DirectoryEntry.h"
#include <cstring>
using namespace NuFX;
EntryPointer DirectoryEntry::lookup(const std::string& name) const
{
EntryIterator iter;
for (iter = _children.begin(); iter != _children.end(); ++iter)
{
EntryPointer e = *iter;
if (e->name() == name) return e;
}
return EntryPointer(); // empty.
}
DirectoryEntryPointer DirectoryEntry::dir_lookup(const std::string &name)
{
EntryIterator iter;
for (iter = _children.begin(); iter != _children.end(); ++iter)
{
EntryPointer e = *iter;
if (e->name() == name)
{
// dynamic cast, will return as empty pointer if
// not a directory.
return DYNAMIC_POINTER_CAST(DirectoryEntryPointer, e);
}
}
// not found, insert it..
DirectoryEntryPointer e(new DirectoryEntryPointer(name));
VolumeEntryPointer v = volume().lock();
_children.add(e);
if (v)
{
v->addEntry(e);
}
return e;
}
#pragma mark -
#pragma mark fuse-support
EntryPointer DirectoryEntry::childAtIndex(unsigned index) const
{
if (index >= _children.size()) return EntryPointer();
return _children[index];
}

View File

@@ -1,38 +0,0 @@
#ifndef __NUFX_DIRECTORYENTRY_H__
#define __NUFX_DIRECTORYENTRY_H__
#include "Entry.h"
#include <vector>
#include <dirent.t>
namespace NuFX {
class DirectoryEntry : public Entry
{
public:
EntryPointer lookup(const std::string & name) const;
EntryPointer childAtIndex(unsigned index) const;
protected:
// creates directory if it does not exist.
DirectoryEntryPointer dir_lookup(const std::string &name);
private:
std::vector<EntryPointer> _children;
typedef std::vector<EntryPointer>::iterator EntryIterator;
};
}
#endif

View File

@@ -1,66 +0,0 @@
#include "Entry.h"
#include "Exception.h"
using namespace NuFX;
Entry::Entry() :
_inode(0)
{
}
Entry::Entry(const std::string& name) :
_name(name), _inode(0)
{
}
Entry::~Entry()
{
}
unsigned Entry::inode() const
{
return _inode;
}
const std::string& Entry::name() const
{
return _name;
}
void Entry::setName(const std::string& name)
{
_name = name;
}
VolumeEntryWeakPointer Entry::volume() const
{
return _volume;
}
void Entry::setVolume(VolumeEntryWeakPointer volume)
{
_volume = volume;
}
int Entry::stat(struct stat *st) const
{
return -1;
}
ssize_t Entry::read(size_t size, off_t offset) const
{
return -1;
}
ssize_t Entry::listxattr(char *namebuf, size_t size, int options) const
{
return -1;
}
ssize_t Entry::getxattr(const std::string &name, void *value, size_t size, u_int32_t position, int options) const
{
return -1;
}

View File

@@ -1,69 +0,0 @@
#ifndef __NUFX_ENTRY_H__
#define __NUFX_ENTRY_H__
#include <Common/smart_pointers.h>
#include <string>
#include <stdint.h>
#include <NufxLib.h>
#include <sys/stat.h>
#include <sys/xattr.h>
#include <dirent.h>
namespace NuFX {
class DirectoryEntry;
class Entry;
class FileEntry;
class VolumeEntry;
typedef SHARED_PTR(DirectoryEntry) DirectoryEntryPointer;
typedef SHARED_PTR(Entry) EntryPointer;
typedef SHARED_PTR(FileEntry) FileEntryPointer;
typedef SHARED_PTR(VolumeEntry) VolumeEntryPointer;
typedef WEAK_PTR(Entry) EntryWeakPointer;
typedef WEAK_PTR(VolumeEntry) VolumeEntryWeakPointer;
class Entry : public ENABLE_SHARED_FROM_THIS(Entry) {
public:
virtual ~Entry();
virtual unsigned inode() const;
virtual const std::string& name() const;
// operations...
virtual int stat(VolumeEntryPointer, struct stat *) const;
virtual ssize_t read(VolumeEntryPointer, size_t size, off_t offset) const;
virtual ssize_t listxattr(VolumeEntryPointer, char *namebuf, size_t size, int options) const;
virtual ssize_t getxattr(VolumeEntryPointer, const std::string &name, void *value, size_t size, u_int32_t position, int options) const;
virtual int open(VolumeEntryPointer, int flags);
virtual int close(VolumeEntryPointer);
protected:
Entry();
Entry(const std::string& name);
void setName(const std::string&);
private:
Entry(const Entry&);
Entry& operator=(const Entry&);
friend VolumeEntry;
std::string _name;
unsigned _inode;
};
}
#endif

View File

@@ -1,10 +0,0 @@
#include "Exception.h"
namespace NuFX {
const char *NuFX::Exception::errorString()
{
return ::NuStrError((NuError)error());
}
}

View File

@@ -1,35 +0,0 @@
#ifndef __NUFX_EXCEPTION_H__
#define __NUFX_EXCEPTION_H__
#include <Common/Exception.h>
#include <NufxLib.h>
namespace NuFX {
class Exception : public ::Exception
{
public:
Exception(const char *cp, NuError error);
Exception(const std::string& string, NuError error);
virtual const char *errorString();
private:
typedef ::Exception super;
};
inline Exception::Exception(const char *cp, NuError error) :
super(cp, error)
{
}
inline Exception::Exception(const std::string& string, NuError error) :
super(string, error)
{
}
}
#endif

View File

@@ -1,23 +0,0 @@
#ifndef __NUFX_FILEENTRY_H__
#define __NUFX_FILEENTRY_H__
#include "Entry.h"
#include <NufxLib.h>
namespace NuFX {
class FileEntry : public Entry
{
public:
private:
NuRecordIdx _recordID;
unsigned _flags; // threads
size_t _size; // data size
};
}
#endif

View File

@@ -1,14 +0,0 @@
#include "VolumeEntry.h"
using namespace NuFX;
void VolumeEntry::addEntry(EntryPointer e)
{
if (!e) return;
e->setVolume(pointer());
_inodeIndex->push_back(e);
e->_inode = _inodeIndex->length() + 100 - 1;
}

View File

@@ -1,35 +0,0 @@
#ifndef __NUFX_VOLUMEENTRY_H__
#define __NUFX_VOLUMEENTRY_H__
#include "DirectoryEntry.h"
#include <Common/unordered_map.h>
namespace NuFX {
class VolumeEntry : public DirectoryEntry
{
public:
void addEntry(EntryPointer);
private:
VolumeEntryPointer pointer() const
{
return STATIC_POINTER_CAST(VolumeEntryPointer, shared_from_this());
}
void parse();
NuArchive *_archive;
//unsigned _inodeGenerator;
std::vector<WeakPointer> _inodeIndex;
};
}
#endif

View File

@@ -1,13 +0,0 @@
#include "Exception.h"
#include <cstdio>
#include <cstring>
namespace POSIX {
const char *Exception::errorString()
{
return strerror(error());
}
}

View File

@@ -1,34 +0,0 @@
#ifndef __POSIX_EXCEPTION_H__
#define __POSIX_EXCEPTION_H__
#include <Common/Exception.h>
namespace POSIX {
class Exception : public ::Exception {
public:
Exception(const char *cp, int error);
Exception(const std::string& string, int error);
virtual const char *errorString();
private:
typedef ::Exception super;
};
inline Exception::Exception(const char *cp, int error) :
super(cp, error)
{
}
inline Exception::Exception(const std::string& string, int error) :
super(string, error)
{
}
}
#endif

View File

@@ -1,47 +0,0 @@
#include <Pascal/Date.h>
#include <cstring>
using namespace Pascal;
Date::Date(unsigned val)
{
// yyyy yyym mmmm dddd
_month = val & 0xf;
_day = (val >> 4) & 0x1f;
_year = (val >> 9) & 0x7f;
}
Date::operator std::time_t() const {
struct tm tm;
if (_day == 0 || _month == 0) return (std::time_t)-1;
std::memset(&tm, 0, sizeof(tm));
tm.tm_hour = 12;
tm.tm_mday = _day;
tm.tm_mon = _month;
tm.tm_year = _year;
tm.tm_isdst = -1;
// ProDOS standard for dealing w/ y2k.
if (_year <= 39) tm.tm_year += 100;
return std::mktime(&tm);
}
Date::operator uint16_t() const {
// year must be 0 .. 127
return (_year << 9) | (_day << 4) | _month;
}
Date Date::Today()
{
struct tm tm;
std::time_t t = std::time(NULL);
::localtime_r(&t, &tm);
return Date(tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday);
}

View File

@@ -1,48 +0,0 @@
#ifndef __PASCAL_DATE_H__
#define __PASCAL_DATE_H__
#include <ctime>
#include <stdint.h>
namespace Pascal {
class Date {
public:
static Date Today();
Date();
Date(unsigned yy, unsigned mm, unsigned dd);
Date(unsigned);
operator std::time_t() const;
operator uint16_t() const;
unsigned month() const { return _month; }
unsigned day() const { return _day; }
unsigned year() const { return _year; }
private:
unsigned _year;
unsigned _month;
unsigned _day;
};
inline Date::Date()
{
_year = 0;
_month = 0;
_day = 0;
}
inline Date::Date(unsigned yy, unsigned mm, unsigned dd)
{
_year = yy;
_month = mm;
_day = dd;
}
}
#endif

View File

@@ -1,96 +0,0 @@
#include <Pascal/Entry.h>
#include <Common/Exception.h>
#include <Endian/Endian.h>
#include <Endian/IOBuffer.h>
#include <Device/BlockDevice.h>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <memory>
using namespace LittleEndian;
using namespace Pascal;
#pragma mark -
#pragma mark DirEntry
unsigned Entry::ValidName(const char *cp, unsigned maxLength)
{
// any printable char except:
// white space
// $ = ? , (file only)
// : (volume only)
if (!cp || !*cp) return 0;
for (unsigned i = 0; ; ++i)
{
unsigned c = cp[i];
if (c == 0) return i;
if (i >= maxLength) return 0;
switch(c)
{
case ':':
if (maxLength == 7) return 0;
break;
case '$':
case '=':
case ',':
case '?':
if (maxLength == 15) return 0;
break;
default:
if (!::isascii(c)) return 0;
if (!std::isgraph(c)) return 0;
}
}
}
Entry::Entry()
{
_firstBlock = 0;
_lastBlock = 0;
_fileKind = 0;
_inode = 0;
_address = NULL;
}
Entry::Entry(void *vp)
{
init(vp);
}
Entry::~Entry()
{
}
void Entry::init(void *vp)
{
_firstBlock = Read16(vp, 0x00);
_lastBlock = Read16(vp, 0x02);
_fileKind = Read8(vp, 0x04);
_inode = 0;
}
void Entry::writeDirectoryEntry(IOBuffer *b)
{
b->write16(_firstBlock);
b->write16(_lastBlock);
b->write8(_fileKind);
}

View File

@@ -1,89 +0,0 @@
#ifndef __PASCAL_ENTRY_H__
#define __PASCAL_ENTRY_H__
#include <Common/smart_pointers.h>
namespace Device {
class BlockDevice;
class BlockCache;
}
namespace LittleEndian {
class IOBuffer;
}
namespace Pascal {
enum {
kUntypedFile,
kBadBlockFile,
kCodeFile,
kTextFile,
kInfoFile,
kDataFile,
kGrafFile,
kFotoFile,
kSecureDir
};
class FileEntry;
class VolumeEntry;
typedef SHARED_PTR(FileEntry) FileEntryPointer;
typedef SHARED_PTR(VolumeEntry) VolumeEntryPointer;
typedef WEAK_PTR(FileEntry) FileEntryWeakPointer;
typedef WEAK_PTR(VolumeEntry) VolumeEntryWeakPointer;
class Entry : public ENABLE_SHARED_FROM_THIS(Entry) {
public:
virtual ~Entry();
unsigned blocks() const { return _lastBlock - _firstBlock; }
unsigned firstBlock() const { return _firstBlock; }
unsigned lastBlock() const { return _lastBlock; }
unsigned fileKind() const { return _fileKind; }
unsigned inode() const { return _inode; }
void setInode(unsigned inode) { _inode = inode; }
VolumeEntryWeakPointer parent() { return _parent; }
protected:
static unsigned ValidName(const char *name, unsigned maxSize);
virtual void writeDirectoryEntry(LittleEndian::IOBuffer *);
Entry();
Entry(void *);
void init(void *);
unsigned _firstBlock;
unsigned _lastBlock;
unsigned _fileKind;
unsigned _inode;
private:
friend class VolumeEntry;
VolumeEntryWeakPointer _parent;
unsigned _address;
};
}
#endif

View File

@@ -1,734 +0,0 @@
#include <algorithm>
#include <cstring>
#include <cctype>
#include <memory>
#include <cerrno>
#include <Pascal/Pascal.h>
#include <Pascal/TextWriter.h>
#include <Common/auto.h>
#include <Common/Exception.h>
#include <ProDOS/Exception.h>
#include <Endian/Endian.h>
#include <Endian/IOBuffer.h>
#include <Device/BlockDevice.h>
using namespace LittleEndian;
using namespace Pascal;
enum {
kDLE = 16
};
/*
* _lastByte is in the range 1..512 and indicates how many bytes in the last
* block are in use.
* _lastBlock is the block *after* the actual last block.
* _maxFileSize is the maximum file size the file can grow to.
*
*/
unsigned FileEntry::ValidName(const char *cp)
{
return Entry::ValidName(cp, 15);
}
FileEntryPointer FileEntry::Open(void *vp)
{
//return FileEntryPointer(new FileEntry(vp));
return MAKE_SHARED(FileEntry, vp);
}
FileEntryPointer FileEntry::Create(const char *name, unsigned fileKind)
{
//return FileEntryPointer(new FileEntry(name, fileKind));
return MAKE_SHARED(FileEntry, name, fileKind);
}
FileEntry::FileEntry(void *vp) :
Entry(vp)
{
_status = Read8(vp, 0x05) & 0x01;
_fileNameLength = Read8(vp, 0x06);
std::memset(_fileName, 0, 16);
std::memcpy(_fileName, 0x07 + (uint8_t *)vp, _fileNameLength);
_lastByte = Read16(vp, 0x16);
_modification = Date(Read16(vp, 0x18));
_fileSize = 0;
_pageSize = NULL;
_maxFileSize = 0;
}
FileEntry::FileEntry(const char *name, unsigned fileKind)
{
#undef __METHOD__
#define __METHOD__ "FileEntry::FileEntry"
unsigned length = ValidName(name);
if (!length)
throw ::Exception(__METHOD__ ": Invalid file name.");
_fileKind = fileKind;
_status = 0;
_fileNameLength = length;
std::memset(_fileName, 0, sizeof(_fileName));
for (unsigned i = 0; i < length; ++i)
_fileName[i] = std::toupper(name[i]);
_modification = Date::Today();
_lastByte = 0;
_fileSize = 0;
_pageSize = NULL;
_maxFileSize = 0;
}
FileEntry::~FileEntry()
{
delete _pageSize;
}
void FileEntry::setFileKind(unsigned kind)
{
_fileKind = kind;
if (_pageSize)
{
delete _pageSize;
_fileSize = 0;
_pageSize = NULL;
}
VolumeEntryPointer v = parent().lock();
// throw if expired?
if (v) v->writeEntry(this);
}
void FileEntry::setName(const char *name)
{
#undef __METHOD__
#define __METHOD__ "FileEntry::setName"
unsigned length = ValidName(name);
if (!length)
throw ProDOS::Exception(__METHOD__ ": Invalid file name.", ProDOS::badPathSyntax);
_fileNameLength = length;
for (unsigned i = 0; i < length; ++i)
_fileName[i] = std::toupper(name[i]);
// parent's responsibility.
//parent()->writeEntry(this);
}
unsigned FileEntry::fileSize()
{
switch(fileKind())
{
case kTextFile:
return textFileSize();
break;
default:
return dataFileSize();
break;
}
}
void FileEntry::writeDirectoryEntry(IOBuffer *b)
{
Entry::writeDirectoryEntry(b);
b->write8(_status ? 0x01 : 0x00);
b->write8(_fileNameLength);
b->writeBytes(_fileName, 15);
b->write16(_lastByte);
b->write16(_modification);
}
int FileEntry::read(uint8_t *buffer, unsigned size, unsigned offset)
{
unsigned fsize = fileSize();
if (offset + size > fsize) size = fsize - offset;
if (offset >= fsize) return 0;
switch(fileKind())
{
case kTextFile:
return textRead(buffer, size, offset);
break;
default:
return dataRead(buffer, size, offset);
break;
}
}
int FileEntry::truncate(unsigned newSize)
{
#undef __METHOD__
#define __METHOD__ "FileEntry::truncate"
unsigned currentSize = fileSize();
if (currentSize == newSize) return 0;
if (fileKind() == kTextFile)
{
if (newSize)
{
errno = EINVAL;
return -1;
}
newSize = 2; // text files have a 2-page scratch buffer for the editor.
if (_pageSize)
{
_pageSize->clear();
_fileSize = 0;
}
}
if (truncateCommon(newSize) != 0)
return -1;
_modification = Date::Today();
VolumeEntryPointer v = parent().lock();
if (v) v->writeEntry(this);
return 0;
}
/*
* truncateCommon -- common truncation code.
* updates _lastByte and _lastBlock but does
* not update _modification or commit to disk.
*/
int FileEntry::truncateCommon(unsigned newSize)
{
#undef __METHOD__
#define __METHOD__ "FileEntry::truncateCommon"
unsigned currentSize = fileSize();
VolumeEntryPointer v = parent().lock();
if (newSize == currentSize) return 0;
if (newSize > currentSize)
{
if (newSize > _maxFileSize)
{
errno = ENOSPC;
return -1;
}
unsigned remainder = newSize - currentSize;
unsigned block = _lastBlock - 1;
if (_lastByte != 512)
{
// last page not full
unsigned count = std::min(512 - _lastByte, remainder);
if (v)
{
uint8_t *address = (uint8_t *)v->loadBlock(block);
std::memset(address + _lastByte, 0, count);
v->unloadBlock(block, true);
}
remainder -= count;
}
block++;
while (remainder)
{
unsigned count = std::min(512u, remainder);
if (v)
{
uint8_t *address = (uint8_t *)v->loadBlock(block);
std::memset(address, 0, count);
v->unloadBlock(block, true);
}
remainder -= count;
block++;
}
}
setFileSize(newSize);
return 0;
}
int FileEntry::write(TextWriter &text)
{
unsigned blocks = text.blocks();
VolumeEntryPointer v = parent().lock();
if (!v)
{
errno = EROFS;
return -1;
}
if (v->readOnly())
{
errno = EROFS;
return -1;
}
if (fileKind() != kTextFile)
{
errno = EINVAL;
return -1;
}
if (blocks * 512 > _maxFileSize)
{
errno = ENOSPC;
return -1;
}
for (unsigned i = 0; i < blocks; ++i)
{
void *buffer = text.data(i);
v->writeBlock(_firstBlock + i, buffer);
}
_modification = Date::Today();
setFileSize(blocks * 512);
v->writeEntry(this);
v->sync();
return blocks * 512;
}
int FileEntry::write(const uint8_t *buffer, unsigned size, unsigned offset)
{
#undef __METHOD__
#define __METHOD__ "FileEntry::write"
VolumeEntryPointer v = parent().lock();
if (!v)
{
errno = EROFS;
return -1;
}
if (v->readOnly())
{
errno = EROFS;
return -1;
}
if (fileKind() == kTextFile)
{
errno = EINVAL;
return -1;
}
unsigned currentSize = fileSize();
unsigned newSize = std::max(offset + size, currentSize);
if (newSize > _maxFileSize)
{
errno = ENOSPC;
return -1;
}
if (offset > currentSize)
{
if (truncateCommon(offset) != 0) return -1;
}
// now write the data...
unsigned block = firstBlock() + offset / 512;
unsigned start = offset % 512;
unsigned remainder = size;
if (start)
{
unsigned count = std::min(512 - start, remainder);
uint8_t *address = (uint8_t *)v->loadBlock(block);
std::memcpy(address + start, buffer, count);
v->unloadBlock(block, true);
remainder -= count;
buffer += count;
block++;
}
while (remainder)
{
uint8_t *address = (uint8_t *)v->loadBlock(block);
unsigned count = std::min(512u, size);
std::memcpy(address, buffer, count);
v->unloadBlock(block, true);
remainder -= count;
buffer += count;
block++;
}
if (newSize > currentSize) setFileSize(newSize);
_modification = Date::Today();
v->writeEntry(this);
return size;
}
/*
* private
* set the file size. Does not check if > _maxFileSize.
*
*/
void FileEntry::setFileSize(unsigned size)
{
if (size == 0)
{
// TODO -- verify how 0 byte files are handled.
_lastBlock = _firstBlock + 1;
_lastByte = 0;
return;
}
_lastBlock = 1 + _firstBlock + size / 512;
_lastByte = size % 512;
if (_lastByte == 0) _lastByte = 512;
}
unsigned FileEntry::dataFileSize()
{
return blocks() * 512 - 512 + _lastByte;
}
unsigned FileEntry::textFileSize()
{
if (!_pageSize) textInit();
return _fileSize;
}
int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset)
{
uint8_t tmp[512];
unsigned count = 0;
unsigned block = 0;
VolumeEntryPointer v = parent().lock();
if (!v)
{
errno = EROFS;
return 0;
}
block = _firstBlock + (offset / 512);
// returned value (count) is equal to size at this point.
// (no partial reads).
/*
* 1. Block align everything
*/
if (offset % 512)
{
unsigned bytes = std::min(offset % 512, size);
v->readBlock(block++, tmp);
std::memcpy(buffer, tmp + 512 - bytes, bytes);
buffer += bytes;
count += bytes;
size -= bytes;
}
/*
* 2. read full blocks into the buffer.
*/
while (size >= 512)
{
v->readBlock(block++, buffer);
buffer += 512;
count += 512;
size -= 512;
}
/*
* 3. Read any trailing blocks.
*/
if (size)
{
v->readBlock(block, tmp);
std::memcpy(buffer, tmp, size);
count += size;
}
return count;
}
int FileEntry::textRead(uint8_t *buffer, unsigned size, unsigned offset)
{
unsigned page = 0;
unsigned to = 0;
unsigned block;
unsigned l;
unsigned count = 0;
::auto_array<uint8_t> tmp;
unsigned tmpSize = 0;
if (!_pageSize) textInit();
l = _pageSize->size();
// find the first page.
for (page = 0; page < l; ++page)
{
unsigned pageSize = (*_pageSize)[page];
if (to + pageSize > offset)
{
break;
}
to += pageSize;
}
// first 2 pages are spare, for editor use, not actually text.
block = _firstBlock + 2 + (page * 2);
// offset not needed anymore,
// convert to offset from *this* page.
offset -= to;
while (size)
{
unsigned pageSize = (*_pageSize)[page];
unsigned bytes = std::min(size, pageSize - offset);
if (pageSize > tmpSize)
{
tmp.reset(new uint8_t[pageSize]);
tmpSize = pageSize;
}
// can decode straight to buffer if size >= bytes && offset = 0.
textDecodePage(block, tmp.get());
std::memcpy(buffer, tmp.get() + offset, bytes);
block += 2;
page += 1;
size -= bytes;
buffer += bytes;
count += bytes;
offset = 0;
}
return count;
}
unsigned FileEntry::textDecodePage(unsigned block, uint8_t *out)
{
uint8_t buffer[1024];
unsigned size = 0;
bool dle = false;
unsigned bytes = textReadPage(block, buffer);
for (unsigned i = 0; i < bytes; ++i)
{
uint8_t c = buffer[i];
if (!c) continue;
if (dle)
{
if (c > 32)
{
unsigned x = c - 32;
size += x;
if (out) for (unsigned j = 0; j < x; ++j)
*out++ = ' ';
}
dle = false;
continue;
}
if (c == kDLE) { dle = true; continue; }
//if (c & 0x80) continue; // ascii only.
if (c == 0x0d) c = 0x0a; // convert to unix format.
if (out) *out++ = c;
size += 1;
}
return size;
}
unsigned FileEntry::textReadPage(unsigned block, uint8_t *in)
{
// reads up to 2 blocks.
// assumes block within _startBlock ... _lastBlock - 1
VolumeEntryPointer v = parent().lock();
if (!v)
{
errno = EROFS;
return 0;
}
v->readBlock(block, in);
if (block + 1 == _lastBlock)
{
return _lastByte;
}
v->readBlock(block + 1, in + 512);
if (block +2 == _lastBlock)
{
return 512 + _lastByte;
}
return 1024;
}
void FileEntry::textInit()
{
// calculate the file size and page offsets.
_pageSize = new std::vector<unsigned>;
_pageSize->reserve((_lastBlock - _firstBlock + 1 - 2) / 2);
_fileSize = 0;
for (unsigned block = _firstBlock + 2; block < _lastBlock; block += 2)
{
unsigned size = textDecodePage(block, NULL);
//printf("%u: %u\n", block, size);
_fileSize += size;
_pageSize->push_back(size);
}
}
/*
* compress white space into a dle.
* returns true if altered.
* nb -- only leading white space is compressed.
*/
bool FileEntry::Compress(std::string& text)
{
std::string out;
size_t pos;
size_t count;
if (text.length() < 3) return false;
if (text[0] != ' ') return false;
pos = text.find_first_not_of(' ');
if (pos == std::string::npos)
count = text.length();
else count = pos;
if (count < 3) return false;
count = std::min((int)count, 255 - 32);
out.push_back(kDLE);
out.push_back(32 + count);
out.append(text.begin() + count, text.end());
text.swap(out);
return true;
}
/*
* dle will only occur at start.
*
*/
bool FileEntry::Uncompress(std::string& text)
{
std::string out;
unsigned c;
if (text.length() < 2) return false;
if (text[0] != kDLE) return false;
c = text[1];
if (c < 32) c = 32;
out.append(c - 32, ' ');
out.append(text.begin() + 2, text.end());
text.swap(out);
return true;
}

View File

@@ -1,111 +0,0 @@
#ifndef __PASCAL_FILEENTRY_H__
#define __PASCAL_FILEENTRY_H__
#include <Pascal/Entry.h>
#include <Pascal/Date.h>
#include <vector>
#include <string>
namespace Pascal {
class TextWriter;
class FileEntry : public Entry {
public:
static unsigned ValidName(const char *);
static bool Compress(std::string& text);
static bool Uncompress(std::string& text);
static FileEntryPointer Create(const char *name, unsigned fileKind);
static FileEntryPointer Open(void *vp);
virtual ~FileEntry();
unsigned fileSize();
unsigned lastByte() const { return _lastByte; }
const char *name() const { return _fileName; }
Date modification() const { return _modification; }
void setFileKind(unsigned kind);
int read(uint8_t *buffer, unsigned size, unsigned offset);
int write(const uint8_t *buffer, unsigned size, unsigned offset);
int write(TextWriter& text);
int truncate(unsigned newSize);
FileEntry(const char *name, unsigned fileKind);
FileEntry(void *vp);
protected:
virtual void writeDirectoryEntry(LittleEndian::IOBuffer *);
private:
friend class VolumeEntry;
FileEntryPointer thisPointer()
{
return STATIC_POINTER_CAST(FileEntry, shared_from_this());
}
void setName(const char *name);
int truncateCommon(unsigned newSize);
void setFileSize(unsigned size);
unsigned _status;
unsigned _fileNameLength;
char _fileName[16];
unsigned _lastByte;
Date _modification;
unsigned _maxFileSize; // maximum file size.
// non-text files
unsigned dataFileSize();
int dataRead(uint8_t *buffer, unsigned size, unsigned offset);
// for text files.
void textInit();
unsigned textFileSize();
int textRead(uint8_t *buffer, unsigned size, unsigned offset);
unsigned textReadPage(unsigned block, uint8_t *in);
unsigned textDecodePage(unsigned block, uint8_t *out);
std::vector<unsigned> *_pageSize;
unsigned _fileSize;
};
}
#endif

View File

@@ -1,14 +0,0 @@
CC = g++
CPPFLAGS += -g -Wall -I../
all : Date.o Entry.o FileEntry.o VolumeEntry.o
Date.o : Date.cpp Date.h
Entry.o : Entry.cpp File.h
FileEntry.o : FileEntry.cpp File.h Date.h
VolumeEntry.o : VolumeEntry.cpp File.h Date.h

View File

@@ -1,48 +0,0 @@
CC = g++
CPPFLAGS += -Wall -O2 -g -fexceptions \
-D__FreeBSD__=10 \
-D_FILE_OFFSET_BITS=64 \
-D__DARWIN_64_BIT_INO_T=1 \
-DHAVE_STAT_BIRTHTIME
LDFLAGS += -L/usr/local/lib -lfuse_ino64
newfs_pascal: \
newfs_pascal.o \
Date.o \
File.o \
../Exception.o \
../BlockDevice.o \
../BlockCache.o \
../DiskCopy42Image.o \
../RawDevice.o \
../MappedFile.o \
../Buffer.o
fileman : \
FileMan.o \
Date.o \
File.o \
../Exception.o \
../BlockDevice.o \
../BlockCache.o \
../DiskCopy42Image.o \
../RawDevice.o \
../MappedFile.o \
../Buffer.o
profuse_pascal : \
profuse_pascal.o \
profuse_pascal_ops.o \
Date.o \
File.o \
../Exception.o \
../BlockDevice.o \
../BlockCache.o \
../DiskCopy42Image.o \
../RawDevice.o \
../MappedFile.o \
../Buffer.o

View File

@@ -1,9 +0,0 @@
#ifndef __PASCAL_FILE_H__
#define __PASCAL_FILE_H__
#include <Pascal/Date.h>
#include <Pascal/Entry.h>
#include <Pascal/FileEntry.h>
#include <Pascal/VolumeEntry.h>
#endif

View File

@@ -1,92 +0,0 @@
class TextFile {
public:
unsigned size() const;
unsigned read(void *buffer, unsigned size, unsigned offset);
private:
static unsigned decodeBlock(uint8_t *in, unsigned inSize, uint8_t *out);
unsigned _size;
std::vector<unsigned> _pageSize
};
unsigned decodeBlock(uint8_t *in, unsigned inSize, uint8_t *out)
{
const unsigned DLE = 16;
unsigned size = 0;
for (unsigned i = 0; i < inSize; ++i)
{
uint8_t c = in[i];
if (!c) break;
if ((c == DLE) && (i + 1 < inSize))
{
unsigned x = in[++i] - 32;
if (out)
{
for (unsigned i = 0; i < x; ++i)
*out++ = ' ';
}
size += x;
}
else
{
if (out) *out++ = c;
++size;
}
}
return size;
}
{
// first 2 blocks are header information
_fileSize = 0;
unsigned pages = (_endBlock - _startBlock - 2) >> 1
uint8_t buffer[1024];
unsigned offset = 0;
for (unsigned i _startBlock + 2; i <= _endBlock; i += 2)
{
uint8_t buffer[1024];
unsigned dataSize = 0;
unsigned offset = 0;
unsigned size;
// load a 2-block page.
for (j = i; j <= _endBlock; ++j)
{
_device->readBlock(j, buffer + offset);
dataSize += j == _endBlock ? _lastByte : 512;
}
size = decodeBlock(buffer, dataSize, NULL);
_pageSize.push_back(size);
_fileSize += size;
}
}

View File

View File

@@ -1,104 +0,0 @@
#include <Pascal/TextWriter.h>
#include <Pascal/FileEntry.h>
#include <Common/Exception.h>
#include <string>
#include <cstring>
using namespace Pascal;
TextWriter::TextWriter()
{
_offset = 0;
_current = new uint8_t[1024];
_blocks.push_back(new uint8_t[1024]); // 1024k for editor scratch data.
std::memset(_blocks.back(), 0, 1024);
std::memset(_current, 0, 1024);
}
TextWriter::~TextWriter()
{
std::vector<uint8_t *>::iterator iter;
if (_current) delete[] _current;
for (iter = _blocks.begin(); iter != _blocks.end(); ++iter)
{
delete[] *iter;
}
}
unsigned TextWriter::blocks() const
{
if (_offset == 0) return _blocks.size() * 2;
if (_offset <= 512) return _blocks.size() * 2 + 1;
return _blocks.size() * 2 + 2;
}
void *TextWriter::data(unsigned block) const
{
unsigned offset = (block & 0x01) * 512;
unsigned halfBlock = block >> 1;
if (halfBlock < _blocks.size())
{
return _blocks[halfBlock] + offset;
}
if (halfBlock == _blocks.size())
{
if (offset > _offset) return NULL;
return _current + offset;
}
return NULL;
}
void TextWriter::writeLine(const char *line)
{
writeLine(line, std::strlen(line));
}
void TextWriter::writeLine(const char *line, unsigned length)
{
#undef __METHOD__
#define __METHOD__ "TextWriter::writeLine"
if (line == NULL) line = "";
std::string text(line, length);
if (length)
{
char c = text[length - 1];
if (c == 0x0a) text[length - 1] = 0x0d;
else if (c != 0x0d) text.push_back(0x0d);
FileEntry::Compress(text);
}
else
{
text.push_back(0x0d);
}
length = text.length();
if (length > 1024)
{
throw ::Exception(__METHOD__ ": String is too long.");
}
if (_offset + length > 1024)
{
_blocks.push_back(_current);
_offset = 0;
_current = new uint8_t[1024];
std::memset(_current, 0, 1024);
}
std::memcpy(_current + _offset, text.data(), length);
_offset += length;
}

View File

@@ -1,37 +0,0 @@
#ifndef __PASCAL_TEXTWRITER_H__
#define __PASCAL_TEXTWRITER_H__
#include <vector>
#include <stdint.h>
namespace Pascal {
class TextWriter {
public:
TextWriter();
~TextWriter();
unsigned blocks() const;
void *data(unsigned block) const;
void writeLine(const char *);
void writeLine(const char *, unsigned length);
private:
std::vector<uint8_t *> _blocks;
unsigned _offset;
uint8_t *_current;
};
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,117 +0,0 @@
#ifndef __PASCAL_VOLUMEENTRY_H__
#define __PASCAL_VOLUMEENTRY_H__
#include <Pascal/Entry.h>
#include <vector>
#include <Device/BlockDevice.h>
namespace Pascal {
class VolumeEntry : public Entry {
public:
static unsigned ValidName(const char *);
static VolumeEntryPointer Open(Device::BlockDevicePointer);
static VolumeEntryPointer Create(Device::BlockDevicePointer, const char *name);
//
virtual ~VolumeEntry();
const char *name() const { return _fileName; }
unsigned fileCount() const { return _fileCount; }
unsigned volumeBlocks() const { return _lastVolumeBlock; }
Pascal::Date lastBoot() const { return _lastBoot; }
unsigned freeBlocks(bool krunched = false) const;
unsigned maxContiguousBlocks() const;
bool canKrunch() const;
FileEntryPointer fileAtIndex(unsigned i) const;
FileEntryPointer fileByName(const char *name) const;
void *loadBlock(unsigned block);
void unloadBlock(unsigned block, bool dirty = false);
void readBlock(unsigned block, void *);
void writeBlock(unsigned block, void *);
void sync();
bool readOnly() { return _device->readOnly(); }
int unlink(const char *name);
int rename(const char *oldName, const char *newName);
int copy(const char *oldName, const char *newName);
FileEntryPointer create(const char *name, unsigned blocks);
int krunch();
VolumeEntry(Device::BlockDevicePointer, const char *name);
VolumeEntry(Device::BlockDevicePointer);
protected:
virtual void writeDirectoryEntry(LittleEndian::IOBuffer *);
private:
friend class FileEntry;
VolumeEntry();
VolumeEntryPointer thisPointer()
{
return STATIC_POINTER_CAST(VolumeEntry, shared_from_this());
}
void init(void *);
void setParents();
uint8_t *readDirectoryHeader();
void writeDirectoryHeader(void *);
uint8_t *readBlocks(unsigned startingBlock, unsigned count);
void writeBlocks(void *buffer, unsigned startingBlock, unsigned count);
void writeEntry(FileEntry *e);
void writeEntry();
void calcMaxFileSize();
unsigned _fileNameLength;
char _fileName[8];
unsigned _lastVolumeBlock;
unsigned _fileCount;
unsigned _accessTime;
Pascal::Date _lastBoot;
std::vector<FileEntryPointer> _files;
unsigned _inodeGenerator;
Device::BlockDevicePointer _device;
Device::BlockCachePointer _cache;
};
}
#endif

View File

@@ -1,8 +1,9 @@
#include <cstring>
#include <ProDOS/Bitmap.h>
#include <Device/BlockDevice.h>
#include <Cache/BlockCache.h>
#include <ProDOS/BlockDevice.h>
#include "auto.h"
using namespace ProDOS;
@@ -33,25 +34,26 @@ Bitmap::Bitmap(unsigned blocks)
_freeIndex = 0;
unsigned bitmapSize = _bitmapBlocks * 512;
unsigned blockSize = blocks / 8;
_bitmap.reserve(bitmapSize);
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);
// mark blocks as free..
_bitmap.resize(blocks / 8, 0xff);
// edge case
unsigned tmp = blocks & 0x07;
// edge case...
bitmap[blocks / 8] = ~(0xff >> tmp);
if (blocks & 0x0f)
{
_bitmap.push_back( ~(0xff >> (blocks & 0x0f)) );
}
_bitmap = bitmap.release();
// mark any trailing blocks as in use.
_bitmap.resize(bitmapSize, 0x00);
}
Bitmap::Bitmap(Device::BlockCache *cache, unsigned keyPointer, unsigned blocks)
Bitmap::Bitmap(BlockDevice *device, unsigned keyPointer, unsigned blocks)
{
_blocks = blocks;
_freeBlocks = 0;
@@ -62,68 +64,47 @@ Bitmap::Bitmap(Device::BlockCache *cache, unsigned keyPointer, unsigned blocks)
unsigned bitmapSize = _bitmapBlocks * 512;
unsigned blockSize = blocks / 8;
_bitmap.reserve(bitmapSize);
auto_array<uint8_t> bitmap(new uint8_t[bitmapSize]);
// load the full block(s).
for (unsigned i = 0; i < blockSize; ++i)
{
uint8_t *buffer = (uint8_t *)cache->acquire(keyPointer);
_bitmap.insert(_bitmap.end(), buffer, buffer + 512);
cache->release(keyPointer);
keyPointer++;
device->read(keyPointer + i, bitmap + 512 * i);
}
// and any remaining partial block.
// make sure all trailing bits are marked in use.
// edge case
unsigned tmp = blocks & 0x07;
if (blocks & 4095)
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)
{
uint8_t *buffer = (uint8_t *)cache->acquire(keyPointer);
unsigned bits = blocks & 4095;
unsigned bytes = bits / 8;
//for (unsigned i = 0; i < bits / 8; ++i) _bitmap.push_back(buffer[i]);
_bitmap.insert(_bitmap.end(), buffer, buffer + bytes);
// partial...
if (blocks & 0x0f)
_freeBlocks += popCount(bitmap[i]);
}
if (_freeBlocks)
{
for (unsigned i = 0; i < (blocks + 7) / 8; ++i)
{
uint8_t tmp = buffer[bytes];
tmp &= ~(0xff >> (blocks & 0x0f));
_bitmap.push_back(tmp);
if (bitmap[i])
{
_freeIndex = i;
break;
}
}
// remainder set to in use.
_bitmap.resize(bitmapSize, 0x00);
}
cache->release(keyPointer);
keyPointer++;
}
// now set _freeBlocks and _freeIndex;
std::vector<uint8_t>::iterator iter;
_freeIndex = -1;
for (iter = _bitmap.begin(); iter != _bitmap.end(); ++iter)
{
_freeBlocks += popCount(*iter);
if (_freeIndex == -1 && *iter)
_freeIndex = std::distance(_bitmap.begin(), iter);
}
_bitmap = bitmap.release();
}
Bitmap::~Bitmap()
{
if (_bitmap) delete []_bitmap;
}

View File

@@ -2,25 +2,20 @@
#define __BITMAP_H__
#include <stdint.h>
#include <vector>
namespace Device
{
class BlockDevice;
class BlockCache;
}
namespace ProDOS {
class BlockDevice;
class Bitmap {
public:
Bitmap(unsigned blocks);
Bitmap(Device::BlockCache *cache, unsigned keyPointer, unsigned blocks);
Bitmap(BlockDevice *device, unsigned keyPointer, unsigned blocks);
//todo -- constructor by loading from, block device...
~Bitmap();
int allocBlock();
@@ -33,7 +28,7 @@ public:
unsigned blocks() const { return _blocks; }
unsigned bitmapBlocks() const { return _bitmapBlocks; }
unsigned bitmapSize() const { return _bitmapBlocks * 512; }
const void *bitmap() const { return &_bitmap[0]; }
const void *bitmap() const { return _bitmap; }
private:
@@ -43,7 +38,7 @@ private:
unsigned _blocks;
unsigned _bitmapBlocks;
std::vector<uint8_t> _bitmap;
uint8_t *_bitmap;
};

View File

@@ -11,11 +11,10 @@
#include <Endian/Endian.h>
#include "common.h"
#include <cstring>
#include <cctype>
#include <cstdio>
#include <string.h>
#include <stdint.h>
#include <ctype.h>
#include <stdio.h>
using namespace LittleEndian;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,32 @@
#include "Exception.h"
#include <cstdio>
#include <cstring>
#include <ProFUSE/Exception.h>
#include <stdio.h>
namespace ProDOS {
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())
{
@@ -127,6 +145,4 @@ const char *Exception::errorString()
return "";
}
return "";
}
}
}

View File

@@ -1,9 +1,10 @@
#ifndef __PRODOS_EXCEPTION_H__
#define __PRODOS_EXCEPTION_H__
#ifndef __EXCEPTION_H__
#define __EXCEPTION_H__
#include <Common/Exception.h>
#include <string>
#include <exception>
namespace ProDOS {
namespace ProFUSE {
// ProDOS Errors
@@ -66,27 +67,87 @@ enum
resAddErr = 0x71
};
class Exception : public ::Exception {
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);
virtual const char *errorString();
private:
typedef ::Exception super;
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, int error) :
super(cp, error)
inline Exception::Exception(const char *cp):
_error(0),
_string(cp)
{
}
inline Exception::Exception(const std::string& string, int error) :
super(string, error)
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)
{
}
@@ -94,4 +155,4 @@ inline Exception::Exception(const std::string& string, int error) :
}
#endif
#endif

View File

@@ -1,5 +1,6 @@
#include "Lock.h"
#include <ProFUSE/Lock.h>
using namespace ProFUSE;
Lock::Lock()
{

View File

@@ -3,6 +3,7 @@
#include <pthread.h>
namespace ProFUSE {
class Lock {
public:
@@ -27,4 +28,6 @@ private:
};
}
#endif

View File

@@ -3,6 +3,7 @@
#include <cstddef>
namespace ProFUSE {
template <class T>
class auto_array
@@ -97,6 +98,7 @@ private:
};
#endif
}
#endif

View File

@@ -1,8 +1,8 @@
#ifndef __COMMON_SMART_POINTERS_H__
#define __COMMON_SMART_POINTERS_H__
#ifndef __PROFUSE_SMART_POINTERS_H__
#define __PROFUSE_SMART_POINTERS_H__
#if 1
#ifdef CPP0X
//C++0x
#include <memory>

View File

@@ -1,92 +0,0 @@
#ifndef __VOLUME_H__
#define __VOLUME_H__
#include <vector>
#include <stdint.h>
namespace ProFUSE {
class Bitmap;
class BlockDevice;
class Volume;
class Directory;
class FileEntry;
class Entry {
public:
Entry() : _address(0), _volume(NULL) { }
virtual ~Entry();
unsigned address() { return _address; }
void setAddress(unsigned address) { _address = address; }
Volume *volume() const { return _volume; }
void setVolume(Volume *v) { _volume = v; }
private:
// physical location on disk (block * 512 + offset)
unsigned _address;
Volume *_volume;
};
class Directory {
FileEntry *childAtIndex(unsigned index);
private:
unsigned _childCount;
std::vector<FileEntry *>_children;
};
class FileEntry {
virtual ~FileEntry();
virtual unsigned inode();
Directory *directory();
Directory *parent();
private:
Directory *_parent;
Volume *_volume;
}
class Volume {
public:
~Volume();
Volume *Create(BlockDevice *);
Volume *Open(BlockDevice *);
int allocBlock();
private:
Volume(BlockDevice *, int);
Bitmap *_bitmap;
BlockDevice *_device;
};
class FileEntry : public Entry {
public:
virtual ~FileEntry();
unsigned inode();
private:
_unsigned _inode;
_unsigned _lookupCount;
_unsigned _openCount;
};
}
#endif

View File

@@ -1,179 +0,0 @@
#include <cstring>
#include <memory>
#include "Bitmap.h"
#include "BlockDevice.h"
#include "Buffer.h"
#include "Endian.h"
#include "Entry.h"
#include "Exception.h"
using namespace ProFUSE;
using namespace LittleEndian;
#pragma mark VolumeDirectory
VolumeDirectory *VolumeDirectory::Create(const char *name, BlockDevice *device)
{
return new VolumeDirectory(name, device);
}
VolumeDirectory *VolumeDirectory::Create(BlockDevice *device)
{
uint8_t block[512];
// always block 2.
device->read(2, block);
return new VolumeDirectory(device, block);
}
VolumeDirectory::VolumeDirectory(const char *name, BlockDevice *device) :
Directory(VolumeHeader, name)
{
_totalBlocks = device->blocks();
_bitmapPointer = 6;
_entryBlocks.push_back(2);
_entryBlocks.push_back(3);
_entryBlocks.push_back(4);
_entryBlocks.push_back(5);
std::auto_ptr<Bitmap> bitmap(new Bitmap(_totalBlocks));
Buffer buffer(512);
// 2 bootcode blocks
for (unsigned i = 0; i < 2; ++i)
{
bitmap->allocBlock(i);
device->zeroBlock(i);
}
//4 volume header blocks.
for (unsigned i = 2; i < 6; ++i)
{
bitmap->allocBlock(i);
buffer.clear();
// prev block, next block
buffer.push16le(i == 2 ? 0 : i - 1);
buffer.push16le(i == 5 ? 0 : i + 1);
if (i == 2)
{
// create the volume header.
// all ivars must be set.
write(&buffer);
}
buffer.resize(512);
device->write(i, buffer.buffer());
}
// allocate blocks for the bitmap itself
unsigned bb = bitmap->bitmapBlocks();
for (unsigned i = 0; i < bb; ++i)
bitmap->allocBlock(_bitmapPointer + i);
// now write the bitmap...
const uint8_t *bm = (const uint8_t *)bitmap->bitmap();
for (unsigned i = 0; i < bb; ++i)
{
device->write(_bitmapPointer + i, 512 * i + bm);
}
_device = device;
_bitmap = bitmap.release();
}
VolumeDirectory::VolumeDirectory(BlockDevice *device, const void *bp) :
Directory(bp),
_modification(0,0)
{
#undef __METHOD__
#define __METHOD__ "VolumeDirectory::VolumeDirectory"
// + 4 to skip over the block poitners.
std::auto_ptr<Bitmap> bitmap;
const void *vp = 4 + (const uint8_t *)bp;
if (storageType() != VolumeHeader)
throw ProDOSException(__METHOD__ ": Invalid storage type.", 0x4b);
_modification = DateTime(Read16(vp, 0x12), Read16(vp, 0x14));
_bitmapPointer = Read16(vp, 0x23);
_totalBlocks = Read16(vp, 0x25);
// verify totalBlocks <= device->blocks() ?
if (_bitmapPointer >= _totalBlocks)
throw ProDOSException(__METHOD__ ": Invalid bitmap pointer.", 0x5a);
// bitmap pointer...
bitmap.reset(new Bitmap(device, _bitmapPointer, _totalBlocks));
// parse the directory header....
_bitmap = bitmap.release();
}
VolumeDirectory::~VolumeDirectory()
{
if (_device)
{
_device->sync();
delete _device;
}
delete _bitmap;
}
void VolumeDirectory::write(Buffer *out)
{
out->push8((VolumeHeader << 4 ) | nameLength());
out->pushBytes(namei(), 15);
// reserved. SOS uses 0x75 for the first byte [?]
out->push8(0);
out->push8(0);
// last mod
out->push16le(_modification.date());
out->push16le(_modification.time());
// filename case bits
out->push16le(caseFlag());
// creation
out->push16le(creation().date());
out->push16le(creation().time());
out->push8(version());
out->push8(minVersion());
out->push8(access());
out->push8(entryLength());
out->push8(entriesPerBlock());
out->push16le(fileCount());
out->push16le(_bitmapPointer);
out->push16le(_totalBlocks);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,305 +0,0 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cstddef>
#include <vector>
#include <string>
#include <memory>
#include <unistd.h>
#define FUSE_USE_VERSION 27
#include <fuse_opt.h>
#include <fuse_lowlevel.h>
#include <Pascal/Pascal.h>
#include <Common/Exception.h>
#include <File/File.h>
#include <Device/Device.h>
#include <Device/BlockDevice.h>
std::string fDiskImage;
void usage()
{
std::printf("profuse_pascal 0.1\n\n");
std::printf(
"usage:\n"
"profuse_pascal [options] diskimage [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"
" 2img Universal Disk Image\n"
#ifdef HAVE_NUFX
" sdk ShrinkIt Disk Image\n"
#endif
" do DOS Order Disk Image\n"
" po ProDOS Order Disk Image (default)\n"
" -o opt1,opt2... other mount parameters.\n"
);
}
static struct fuse_lowlevel_ops pascal_ops;
enum {
PASCAL_OPT_HELP,
PASCAL_OPT_VERSION,
PASCAL_OPT_WRITE,
PASCAL_OPT_FORMAT,
PASCAL_OPT_VERBOSE
};
struct options {
char *format;
int readOnly;
int readWrite;
int verbose;
} options;
#define PASCAL_OPT_KEY(T, P, V) {T, offsetof(struct options, P), V}
static struct fuse_opt pascal_options[] = {
FUSE_OPT_KEY("-h", PASCAL_OPT_HELP),
FUSE_OPT_KEY("--help", PASCAL_OPT_HELP),
FUSE_OPT_KEY("-V", PASCAL_OPT_VERSION),
FUSE_OPT_KEY("--version", PASCAL_OPT_VERSION),
PASCAL_OPT_KEY("-v", verbose, 1),
PASCAL_OPT_KEY("-w", readWrite, 1),
PASCAL_OPT_KEY("rw", readWrite, 1),
PASCAL_OPT_KEY("--format=%s", format, 0),
PASCAL_OPT_KEY("format=%s", format, 0),
{0, 0, 0}
};
static int pascal_option_proc(void *data, const char *arg, int key, struct fuse_args *outargs)
{
switch(key)
{
case PASCAL_OPT_HELP:
usage();
exit(0);
break;
case PASCAL_OPT_VERSION:
// TODO
exit(0);
break;
case FUSE_OPT_KEY_NONOPT:
// first arg is the disk image.
if (fDiskImage.empty())
{
fDiskImage = arg;
return 0;
}
return 1;
}
return 1;
}
#ifdef __APPLE__
// create a dir in /Volumes/diskname.
bool make_mount_dir(std::string name, std::string &path)
{
path = "";
if (name.find('/') != std::string::npos
|| name.find('\\') != std::string::npos
|| name.find(':') != std::string::npos )
{
name = "Pascal Volume";
}
path = "";
path = "/Volumes/" + name;
rmdir(path.c_str());
if (mkdir(path.c_str(), 0777) == 0) return true;
for (unsigned i = 0; i < 26; i++)
{
path = "/Volumes/" + name + " " + (char)('a' + i);
rmdir(path.c_str());
if (mkdir(path.c_str(), 0777) == 0) return true;
}
path = "";
return false;
}
#endif
int main(int argc, char **argv)
{
extern void init_ops(fuse_lowlevel_ops *ops);
struct options options;
std::memset(&options, 0, sizeof(options));
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
struct fuse_chan *ch;
char *mountpoint = NULL;
int err = -1;
std::string mountPath;
unsigned format = 0;
int foreground = false;
int multithread = false;
Pascal::VolumeEntryPointer volume;
init_ops(&pascal_ops);
// scan the argument list, looking for the name of the disk image.
if (fuse_opt_parse(&args, &options ,pascal_options, pascal_option_proc) == -1)
exit(1);
if (fDiskImage.empty())
{
usage();
exit(1);
}
// default prodos-order disk image.
if (options.format)
{
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.get())
{
std::fprintf(stderr, "Error: Unknown or unsupported device type.\n");
exit(1);
}
volume = Pascal::VolumeEntry::Open(device);
}
catch (::Exception &e)
{
std::fprintf(stderr, "%s\n", e.what());
std::fprintf(stderr, "%s\n", std::strerror(e.error()));
return -1;
}
#ifdef __APPLE__
{
// Macfuse supports custom volume names (displayed in Finder)
std::string str("-ovolname=");
str += volume->name();
fuse_opt_add_arg(&args, str.c_str());
// 512 byte blocksize.
fuse_opt_add_arg(&args, "-oiosize=512");
}
#endif
fuse_opt_add_arg(&args, "-ofsname=PascalFS");
if (!options.readOnly)
fuse_opt_add_arg(&args, "-ordonly");
if (options.readWrite)
{
std::fprintf(stderr, "Warning: write support is not yet enabled.\n");
}
if (fuse_parse_cmdline(&args, &mountpoint, &multithread, &foreground) == -1)
{
usage();
return -1;
}
#ifdef __APPLE__
if (mountpoint == NULL || *mountpoint == 0)
{
if (make_mount_dir(volume->name(), mountPath))
mountpoint = (char *)mountPath.c_str();
}
#endif
if ((ch = fuse_mount(mountpoint, &args)) != NULL)
{
struct fuse_session* se;
std::printf("Mounting ``%s'' on ``%s''\n", volume->name(), mountpoint);
se = fuse_lowlevel_new(&args, &pascal_ops, sizeof(pascal_ops), volume.get());
if (se) do {
err = fuse_daemonize(foreground);
if (err < 0 ) break;
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);
}
fuse_opt_free_args(&args);
#ifdef __APPLE__
if (!mountPath.empty()) rmdir(mountPath.c_str());
#endif
return err ? 1 : 0;
}

View File

@@ -1,547 +0,0 @@
#define FUSE_USE_VERSION 27
#include <string>
#include <vector>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <fuse_opt.h>
#include <fuse_lowlevel.h>
#include <Pascal/Pascal.h>
#include <Common/auto.h>
#include <Common/Exception.h>
#include <POSIX/Exception.h>
#define NO_ATTR() \
{ \
if (size) fuse_reply_buf(req, NULL, 0); \
else fuse_reply_xattr(req, 0); \
return; \
}
#undef ERROR
#define ERROR(cond,errno) if ( (cond) ){ fuse_reply_err(req, errno); return; }
#define RETURN_XATTR(DATA, SIZE) \
{ \
if (size == 0) { fuse_reply_xattr(req, SIZE); return; } \
if (size < SIZE) { fuse_reply_err(req, ERANGE); return; } \
fuse_reply_buf(req, DATA, SIZE); return; \
}
#define DEBUGNAME() \
if (0) { std::fprintf(stderr, "%s\n", __func__); }
// linux doesn't have ENOATTR.
#ifndef ENOATTR
#define ENOATTR ENOENT
#endif
using namespace Pascal;
// fd_table is files which have been open.
// fd_table_available is a list of indexes in fd_table which are not currently used.
static std::vector<FileEntryPointer> fd_table;
static std::vector<unsigned> fd_table_available;
static FileEntryPointer findChild(VolumeEntry *volume, unsigned inode)
{
for (unsigned i = 0, l = volume->fileCount(); i < l; ++i)
{
FileEntryPointer child = volume->fileAtIndex(i);
if (!child) continue;
if (inode == child->inode()) return child;
}
return FileEntryPointer();
}
#pragma mark -
#pragma mark fs
static void pascal_init(void *userdata, struct fuse_conn_info *conn)
{
DEBUGNAME()
// nop
// text files have a non-thread safe index.
// which is initialized via read() or fileSize()
VolumeEntry *volume = (VolumeEntry *)userdata;
for (unsigned i = 0, l = volume->fileCount(); i < l; ++i)
{
FileEntryPointer child = volume->fileAtIndex(i);
child->fileSize();
}
}
static void pascal_destroy(void *userdata)
{
DEBUGNAME()
// nop
}
static void pascal_statfs(fuse_req_t req, fuse_ino_t ino)
{
DEBUGNAME()
struct statvfs vst;
VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
ERROR(!volume, EIO)
// 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->volumeBlocks();
vst.f_bfree = volume->freeBlocks(true); // free blocks
vst.f_bavail = volume->freeBlocks(false); // free blocks (non-root)
vst.f_files = volume->fileCount();
vst.f_ffree = -1; // free inodes.
vst.f_favail = -1; // free inodes (non-root)
vst.f_fsid = 0; // file system id?
vst.f_flag = volume->readOnly() ? ST_RDONLY | ST_NOSUID : ST_NOSUID;
vst.f_namemax = 15;
fuse_reply_statfs(req, &vst);
}
#pragma mark -
#pragma mark xattr
static void pascal_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
{
DEBUGNAME()
VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
FileEntryPointer file;
std::string attr;
unsigned attrSize;
if (ino == 1) NO_ATTR()
file = findChild(volume, ino);
ERROR(file == NULL, ENOENT)
attr += "pascal.fileKind";
attr.append(1, 0);
if (file->fileKind() == kTextFile)
{
attr += "com.apple.TextEncoding";
attr.append(1, 0);
attr += "user.charset";
attr.append(1, 0);
}
// user.mime_type ? text/plain, ...
attrSize = attr.size();
if (size == 0)
{
fuse_reply_xattr(req, attrSize);
return;
}
ERROR(size < attrSize, ERANGE)
fuse_reply_buf(req, attr.data(), attrSize);
}
static void pascal_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, size_t size)
{
DEBUGNAME()
VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
FileEntryPointer file;
std::string attr(name);
ERROR(ino == 1, ENOATTR)
file = findChild(volume, ino);
ERROR(file == NULL, ENOENT)
if (attr == "pascal.fileKind")
{
uint8_t fk = file->fileKind();
RETURN_XATTR((const char *)&fk, 1)
}
if (file->fileKind() == kTextFile)
{
if (attr == "user.charset")
{
static const char data[]="ascii";
static unsigned dataSize = sizeof(data) - 1;
RETURN_XATTR(data, dataSize)
}
if (attr == "com.apple.TextEncoding")
{
static const char data[] = "us-ascii;1536";
static unsigned dataSize = sizeof(data) - 1;
RETURN_XATTR(data, dataSize)
}
}
ERROR(true, ENOATTR);
return;
}
// OS X version.
static void pascal_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, size_t size, uint32_t off)
{
DEBUGNAME()
pascal_getxattr(req, ino, name, size);
}
#pragma mark -
#pragma mark dirent
static void pascal_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
{
DEBUGNAME()
ERROR(ino != 1, ENOTDIR)
fi->fh = 0;
fuse_reply_open(req, fi);
}
static void pascal_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
{
DEBUGNAME()
fuse_reply_err(req, 0);
}
static void pascal_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
{
DEBUGNAME()
VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
::auto_array<uint8_t> buffer(new uint8_t[size]);
unsigned count = volume->fileCount();
struct stat st;
unsigned currentSize = 0;
std::memset(&st, 0, sizeof(struct stat));
// . and .. need to be added in here but are handled by the fs elsewhere.
do {
if (off == 0)
{
unsigned tmp;
st.st_mode = S_IFDIR | 0555;
st.st_ino = 1;
tmp = fuse_add_direntry(req, NULL, 0, ".", NULL, 0);
if (tmp + currentSize > size) break;
fuse_add_direntry(req, (char *)buffer.get() + currentSize, size, ".", &st, ++off);
currentSize += tmp;
}
if (off == 1)
{
unsigned tmp;
st.st_mode = S_IFDIR | 0555;
st.st_ino = 1;
tmp = fuse_add_direntry(req, NULL, 0, "..", NULL, 0);
if (tmp + currentSize > size) break;
fuse_add_direntry(req, (char *)buffer.get() + currentSize, size, "..", &st, ++off);
currentSize += tmp;
}
for (unsigned i = off - 2; i < count; ++i)
{
unsigned tmp;
FileEntryPointer file = volume->fileAtIndex(i);
if (file == NULL) break; //?
// only these fields are used.
st.st_mode = S_IFREG | 0444;
st.st_ino = file->inode();
tmp = fuse_add_direntry(req, NULL, 0, file->name(), NULL, 0);
if (tmp + currentSize > size) break;
fuse_add_direntry(req, (char *)buffer.get() + currentSize, size, file->name(), &st, ++off);
currentSize += tmp;
}
} while (false);
fuse_reply_buf(req, (char *)buffer.get(), currentSize);
}
#pragma mark -
#pragma mark stat
static void stat(FileEntry *file, struct stat *st)
{
DEBUGNAME()
std::memset(st, 0, sizeof(struct stat));
time_t t = file->modification();
st->st_ino = file->inode();
st->st_nlink = 1;
st->st_mode = S_IFREG | 0444;
st->st_size = file->fileSize();
st->st_blocks = file->blocks();
st->st_blksize = 512;
st->st_atime = t;
st->st_mtime = t;
st->st_ctime = t;
// st.st_birthtime not yet supported by MacFUSE.
}
static void stat(VolumeEntry *volume, struct stat *st)
{
DEBUGNAME()
std::memset(st, 0, sizeof(struct stat));
time_t t = volume->lastBoot();
st->st_ino = volume->inode();
st->st_nlink = 1 + volume->fileCount();
st->st_mode = S_IFDIR | 0555;
st->st_size = volume->blocks() * 512;
st->st_blocks = volume->blocks();
st->st_blksize = 512;
st->st_atime = t;
st->st_mtime = t;
st->st_ctime = t;
// st.st_birthtime not yet supported by MacFUSE.
}
static void pascal_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
{
DEBUGNAME()
VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
struct fuse_entry_param entry;
ERROR(parent != 1, ENOTDIR)
ERROR(!FileEntry::ValidName(name), ENOENT)
for (unsigned i = 0, l = volume->fileCount(); i < l; ++i)
{
FileEntryPointer file = volume->fileAtIndex(i);
if (file == NULL) break;
if (::strcasecmp(file->name(), name)) continue;
// found it!
std::memset(&entry, 0, sizeof(entry));
entry.attr_timeout = 0.0;
entry.entry_timeout = 0.0;
entry.ino = file->inode();
stat(file.get(), &entry.attr);
fuse_reply_entry(req, &entry);
return;
}
ERROR(true, ENOENT)
}
static void pascal_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
{
DEBUGNAME()
struct stat st;
VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
FileEntryPointer file;
if (ino == 1)
{
stat(volume, &st);
fuse_reply_attr(req, &st, 0.0);
return;
}
file = findChild(volume, ino);
ERROR(file == NULL, ENOENT)
//printf("\t%s\n", file->name());
stat(file.get(), &st);
fuse_reply_attr(req, &st, 0.0);
}
#pragma mark -
#pragma mark file
static void pascal_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
{
unsigned index;
DEBUGNAME()
VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
FileEntryPointer file;
ERROR(ino == 1, EISDIR)
file = findChild(volume, ino);
ERROR(file == NULL, ENOENT)
ERROR((fi->flags & O_ACCMODE) != O_RDONLY, EACCES)
// insert the FileEntryPointer into fd_table.
if (fd_table_available.size())
{
index = fd_table_available.back();
fd_table_available.pop_back();
fd_table[index] = file;
}
else
{
index = fd_table.size();
fd_table.push_back(file);
}
fi->fh = index;
fuse_reply_open(req, fi);
}
static void pascal_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
{
unsigned index = fi->fh;
DEBUGNAME()
fd_table[index].reset();
fd_table_available.push_back(index);
fuse_reply_err(req, 0);
}
static void pascal_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
{
unsigned index = fi->fh;
DEBUGNAME()
//VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
FileEntryPointer file = fd_table[index];
try
{
::auto_array<uint8_t> buffer(new uint8_t[size]);
unsigned rsize = file->read(buffer.get(), size, off);
fuse_reply_buf(req, (char *)(buffer.get()), rsize);
return;
}
catch (POSIX::Exception &e)
{
printf("posix error...\n");
ERROR(true, e.error());
}
catch( ... )
{
printf("error...\n");
ERROR(true, EIO)
}
}
void init_ops(fuse_lowlevel_ops *ops)
{
DEBUGNAME()
std::memset(ops, 0, sizeof(fuse_lowlevel_ops));
ops->init = pascal_init;
ops->destroy = pascal_destroy;
ops->statfs = pascal_statfs;
// returns pascal.filekind, text encoding.
ops->listxattr = pascal_listxattr;
ops->getxattr = pascal_getxattr;
// volume is a dir.
ops->opendir = pascal_opendir;
ops->releasedir = pascal_releasedir;
ops->readdir = pascal_readdir;
ops->lookup = pascal_lookup;
ops->getattr = pascal_getattr;
ops->open = pascal_open;
ops->release = pascal_release;
ops->read = pascal_read;
}

View File

@@ -1,314 +0,0 @@
#include <memory>
#include <new>
#include <cstdio>
#include <cstring>
#include <cerrno>
#include <cstdlib>
#include <unistd.h>
#include <sys/stat.h>
#include <Device/BlockDevice.h>
#include <Device/RawDevice.h>
#include <Common/Exception.h>
#include <Pascal/Pascal.h>
#include <File/File.h>
#include <File/MappedFile.h>
using namespace Pascal;
using namespace Device;
#define NEWFS_VERSION "0.1"
bool yes_or_no()
{
int ch, first;
(void)fflush(stderr);
first = ch = getchar();
while (ch != '\n' && ch != EOF)
ch = getchar();
return (first == 'y' || first == 'Y');
}
/*
* \d+ by block
* \d+[Kk] by kilobyte
* \d+[Mm] by megabyte
*/
unsigned parseBlocks(const char *cp)
{
unsigned long blocks = 0;
char *mod;
errno = 0;
blocks = std::strtoul(cp, &mod, 10);
if (errno) return -1;
if (mod == cp) return -1;
if (blocks > 0xffff) return -1;
if (mod)
{
switch(*mod)
{
case 0:
break;
case 'm': // 1m = 1024*1024b = 2048 blocks
case 'M':
blocks *= 2048;
break;
case 'k': // 1k = 1024b = 2 blocks
case 'K':
blocks *= 2;
break;
}
if (blocks > 0xffff) return -1;
}
return (unsigned)blocks;
}
// return the basename, without an extension.
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);
}
void usage()
{
std::printf("newfs_pascal %s\n", NEWFS_VERSION);
std::printf("\n");
std::printf("newfs_pascal [-v volume_name] [-s size] [-f format] file\n");
std::printf("\n");
std::printf(" -v volume_name Specify the volume name.\n"
" Default is Untitled.\n"
" -s size Specify size in blocks.\n"
" Default is 1600 blocks (800K)\n"
" -b bootfile Specify a file that contains the boot block\n"
" -f format Specify the disk image format. Valid values are:\n"
" 2img Universal Disk Image\n"
" dc42 DiskCopy 4.2 Image\n"
" davex Davex Disk Image\n"
" do DOS Order Disk Image\n"
" po ProDOS Order Disk Image (default)\n"
);
}
int main(int argc, char **argv)
{
unsigned blocks = 1600;
std::string volumeName;
std::string fileName;
std::string bootFile;
int format = 0;
const char *fname;
int c;
while ( (c = ::getopt(argc, argv, "hf:s:v:")) != -1)
{
switch(c)
{
case 'h':
default:
usage();
return c == 'h' ? 0 : 1;
break;
case 'v':
volumeName = optarg;
// make sure it's legal.
if (!VolumeEntry::ValidName(optarg))
{
std::fprintf(stderr, "Error: `%s' is not a valid Pascal volume name.\n", optarg);
return 0x40;
}
break;
case 's':
blocks = parseBlocks(optarg);
if (blocks > 0xffff)
{
std::fprintf(stderr, "Error: `%s' is not a valid disk size.\n", optarg);
return 0x5a;
}
break;
case 'f':
format = Device::BlockDevice::ImageType(optarg);
if (format == 0)
{
std::fprintf(stderr, "Error: `%s' is not a supported disk image format.\n", optarg);
return -1;
}
break;
case 'b':
bootFile = optarg;
break;
}
}
argc -= optind;
argv += optind;
if (argc != 1)
{
usage();
return -1;
}
fname = argv[0];
fileName = argv[0];
try
{
struct stat st;
bool rawDevice = false;
BlockDevicePointer device;
VolumeEntryPointer volume;
// Check for block device. if so, verify.
// if file exists, verify before overwrite.
std::memset(&st, 0, sizeof(st));
if (::stat(fname, &st) == 0)
{
if (S_ISBLK(st.st_mode))
{
fprintf(stderr, "`%s' is a raw device. Are you sure you want to initialize it? ", fname);
if (!yes_or_no()) return -1;
device = RawDevice::Open(fname, File::ReadWrite);
blocks = device->blocks();
rawDevice = true;
if (blocks > 0xffff)
{
std::fprintf(stderr, "Error: device is too large.\n");
return 0x5a;
}
}
else
{
// file exists, verify we want to destroy it.
fprintf(stderr, "`%s' already exists. Are you sure you want to overwrite it? ", fname);
if (!yes_or_no()) return -1;
}
}
// generate a filename.
if (volumeName.empty())
{
if (!rawDevice)
volumeName = filename(fileName);
if (volumeName.empty() || !VolumeEntry::ValidName(volumeName.c_str()))
volumeName = "PASCAL";
}
if (!rawDevice)
device = BlockDevice::Create(fname, volumeName.c_str(), blocks, format);
if (!device.get())
{
std::fprintf(stderr, "Error: Unsupported diskimage format.\n");
return -1;
}
if (!bootFile.empty())
{
MappedFile bf(bootFile.c_str(), File::ReadOnly, std::nothrow);
if (!bf.isValid())
{
std::fprintf(stderr, "Warning: unable to open boot file `%s'.\n", bootFile.c_str());
}
else
{
size_t length = bf.length();
// either 1 or 2 blocks.
if (length == 512)
{
device->write(0, bf.address());
}
else if (length == 1024)
{
device->write(0, bf.address());
device->write(1, (uint8_t*)bf.address() + 512);
}
else
{
std::fprintf(stderr, "Warning: boot file must be 512 or 1024 bytes.\n");
}
}
}
volume = VolumeEntry::Create(device, volumeName.c_str());
}
catch (::Exception& e)
{
std::fprintf(stderr, "%s\n", e.what());
std::fprintf(stderr, "%s\n", ::strerror(e.error()));
return -2;
}
return 0;
}

View File

@@ -1,249 +0,0 @@
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cerrno>
#include <memory>
#include <unistd.h>
#include <Device/BlockDevice.h>
#include <ProFUSE/Exception.h>
#define NEWFS_VERSION "0.1"
using namespace ProFUSE;
using namespace Device;
void usage()
{
std::printf("newfs_prodos %s\n", NEWFS_VERSION);
std::printf("\n");
std::printf("newfs_prodos [-v volume_name] [-s size] [-f format] file\n");
std::printf("\n");
std::printf(" -v volume_name specify the volume name.\n"
" Default is Untitled.\n"
" -s size specify size in blocks.\n"
" Default is 1600 blocks (800K)\n"
" -f format specify the disk image format. Valid values are:\n"
" 2mg Universal Disk Image (default)\n"
" dc42 DiskCopy 4.2 Image\n"
" po ProDOS Order Disk Image\n"
" do DOS Order Disk Image\n"
" davex Davex Disk Image\n"
);
}
/*
* \d+ by block
* \d+[Kk] by kilobyte
* \d+[Mm] by megabyte
*/
unsigned parseBlocks(const char *cp)
{
unsigned long blocks = 0;
char *mod;
errno = 0;
blocks = std::strtoul(cp, &mod, 10);
if (errno) return -1;
if (mod == cp) return -1;
if (blocks > 0xffff) return -1;
if (mod)
{
switch(*mod)
{
case 0:
break;
case 'm': // 1m = 1024*1024b = 2048 blocks
case 'M':
blocks *= 2048;
break;
case 'k': // 1k = 1024b = 2 blocks
case 'K':
blocks *= 2;
break;
}
if (blocks > 0xffff) return -1;
}
return (unsigned)blocks;
}
// return the basename, without an extension.
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);
}
bool ValidName(const char *cp)
{
unsigned i = 0;
if (!cp || !*cp) return false;
if (!isalpha(*cp)) return false;
for (i = 1; i <17; ++i)
{
unsigned char c = cp[i];
if (c == 0) break;
if (c == '.') continue;
if (isalnum(c)) continue;
return false;
}
return i < 16;
}
int main(int argc, char **argv)
{
unsigned blocks = 1600;
std::string volumeName;
std::string fileName;
int format = 0;
const char *fname;
int c;
// ctype uses ascii only.
::setlocale(LC_ALL, "C");
while ( (c = ::getopt(argc, argv, "hf:s:v:")) != -1)
{
switch(c)
{
case '?':
case 'h':
usage();
return 0;
break;
case 'v':
volumeName = optarg;
// make sure it's legal.
if (!ValidName(optarg))
{
std::fprintf(stderr, "Error: `%s' is not a valid ProDOS volume name.\n", optarg);
return 0x40;
}
break;
case 's':
blocks = parseBlocks(optarg);
if (blocks > 0xffff)
{
std::fprintf(stderr, "Error: `%s' is not a valid disk size.\n", optarg);
return 0x5a;
}
break;
case 'f':
{
format = BlockDevice::ImageType(optarg);
if (format == 0)
{
std::fprintf(stderr, "Error: `%s' is not a supported disk image format.\n", optarg);
return -1;
}
}
}
}
argc -= optind;
argv += optind;
if (argc != 1)
{
usage();
return -1;
}
fname = argv[0];
fileName = argv[0];
// generate a filename.
if (volumeName.empty())
{
volumeName = filename(fileName);
if (volumeName.empty() || !ValidName(volumeName.c_str()))
volumeName = "Untitled";
}
if (format == 0) format = BlockDevice::ImageType(fname, '2IMG');
try
{
std::auto_ptr<BlockDevice> device;
std::auto_ptr<VolumeDirectory> volume;
// todo -- check if path matches /dev/xxx; if so, use RawDevice.
// todo -- check if file exists at path?
switch(format)
{
case 'DC42':
device.reset(DiskCopy42Image::Create(fname, blocks, volumeName.c_str()));
break;
case 'PO__':
device.reset(ProDOSOrderDiskImage::Create(fname, blocks));
break;
case 'DO__':
device.reset(DOSOrderDiskImage::Create(fname, blocks));
break;
case 'DVX_':
device.reset(DavexDiskImage::Create(fname, blocks, volumeName.c_str()));
break;
case '2IMG':
default:
device.reset(UniversalDiskImage::Create(fname, blocks));
}
// VolumeDirectory assumes ownership of device,
// but doesn't release it on exception.
volume.reset(VolumeDirectory::Create(volumeName.c_str(), device.get()));
device.release();
}
catch (Exception e)
{
std::fprintf(stderr, "Error: %s\n", e.what());
return -1;
}
return 0;
}

BIN
libNuFX.a

Binary file not shown.

View File

@@ -18,11 +18,12 @@
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cstddef>
#include <vector>
#include <string>
#include <tr1/memory>
#include <Device/BlockDevice.h>
@@ -32,6 +33,7 @@
using std::vector;
using std::string;
using std::tr1::shared_ptr;
/*
@@ -126,9 +128,7 @@ static void usage()
" --format=format specify the disk image format. Valid values are:\n"
" dc42 DiskCopy 4.2 Image\n"
" davex Davex Disk Image\n"
#ifdef HAVE_NUFX
" sdk ShrinkIt Disk Image\n"
#endif
" 2img Universal Disk Image\n"
" do DOS Order Disk Image\n"
" po ProDOS Order Disk Image (default)\n"
@@ -280,7 +280,7 @@ int main(int argc, char *argv[])
}
}
catch (::Exception &e)
catch (ProFUSE::Exception &e)
{
std::fprintf(stderr, "%s\n", e.what());
std::fprintf(stderr, "%s\n", e.errorString());

33
makefile.freebsd Executable file
View File

@@ -0,0 +1,33 @@
CC=g++
CFLAGS=-c `pkg-config fuse --cflags`
LDFLAGS=`pkg-config fuse --libs`
SOURCES=main.cpp File.cpp Disk.cpp DiskCopy42.cpp UniversalDiskImage.cpp profuse_dirent.cpp profuse_file.cpp profuse_stat.cpp profuse_xattr.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=profuse
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $@
.cpp.o:
$(CC) $(CFLAGS) $< -o $@
UniversalDiskImage.o: UniversalDiskImage.cpp UniversalDiskImage.h
DiskCopy42.o: DiskCopy42.cpp DiskCopy42.h
File.o: File.cpp File.h
Disk.o: Disk.cpp Disk.h File.h DiskCopy42.h UniversalDiskImage.h
main.o: main.cpp Disk.h File.h profuse.h
profuse_dirent.o: profuse_dirent.cpp profuse.h
profuse_file.o: profuse_file.cpp profuse.h
profuse_stat.o: profuse_stat.cpp profuse.h
profuse_xattr.o: profuse_xattr.cpp profuse.h

33
makefile.linux Executable file
View File

@@ -0,0 +1,33 @@
CC=g++
CFLAGS=-c $(shell pkg-config fuse --cflags)
LDFLAGS=$(shell pkg-config fuse --libs)
SOURCES=main.cpp File.cpp Disk.cpp DiskCopy42.cpp UniversalDiskImage.cpp profuse_dirent.cpp profuse_file.cpp profuse_stat.cpp profuse_xattr.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=profuse
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $@
.cpp.o:
$(CC) $(CFLAGS) $< -o $@
UniversalDiskImage.o: UniversalDiskImage.cpp UniversalDiskImage.h
DiskCopy42.o: DiskCopy42.cpp DiskCopy42.h
File.o: File.cpp File.h
Disk.o: Disk.cpp Disk.h File.h DiskCopy42.h UniversalDiskImage.h
main.o: main.cpp Disk.h File.h profuse.h
profuse_dirent.o: profuse_dirent.cpp profuse.h
profuse_file.o: profuse_file.cpp profuse.h
profuse_stat.o: profuse_stat.cpp profuse.h
profuse_xattr.o: profuse_xattr.cpp profuse.h

199
newfs_prodos.cpp Normal file
View File

@@ -0,0 +1,199 @@
/*
* newfs_prodos.cpp
* ProFUSE
*
* Created by Kelvin Sherlock on 9/2/2009.
*
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cctype>
#include <unistd.h>
#include <libgen.h>
#define VERSION_STRING "0.1"
void help(void)
{
printf("newfs_prodos v %s\n", VERSION_STRING);
printf("usage: newfs_prodos -N -s size -v volname file\n");
printf("\t-N test mode (do not create)\n");
printf("\t-s size file size in blocks (or use K/M)\n");
printf("\t-v volname volume name");
exit(0);
}
//returns number of blocks.
long parseBlocks(const char *cp)
{
long size;
char *end;
unsigned base = 0;
const char *ocp = cp;
if (cp && *cp == '$')
{
base = 16;
cp++;
}
if (!cp || !*cp)
{
fprintf(stderr, "Invalid size.\n");
exit(1);
}
size = strtol(cp, &end, base);
if (end == cp)
{
fprintf(stderr, "Invalid size: `%s'\n", ocp);
exit(1);
}
// number may be M, K, or null (blocks)
if (*end == 0) return size;
if (*end == 'K') return size << 1;
if (*end == 'M') return size << 10;
fprintf(stderr, "Invalid size modifier: `%s'\n", end);
exit(1);
return -1;
}
// verify a size is reasonable for a ProDOS volume
bool validBlocks(long blocks)
{
if (blocks < 280) return false;
if (blocks > (32 << 10)) return false;
return true;
}
bool validName(const char *name)
{
unsigned i;
if (name == 0 || *name == 0) return false;
for(i = 0; name[i]; ++i)
{
char c = name[i];
if (c == '.') continue;
if (c & 0x80) return false;
if (isdigit(c) && i) continue;
if (isalpha(c)) continue;
return false;
}
// i = strlen(name) + 1
return i < 16;
}
const char *generateName(const char *src)
{
// basename may alter it's argument.
char * cp = strdup(src);
cp = basename(cp);
unsigned l = strlen(cp);
// remove any extension...
for (unsigned i = l; i; --i)
{
if (cp[i-1] == '.')
{
cp[i-1] = 0;
l = i - 1;
break;
}
}
if (validName(cp)) return cp;
free(cp);
return "Untitled";
}
int main(int argc, char **argv)
{
int ch;
bool fTest = false;
const char *fVolname = NULL;
const char *filename;
long fBlocks = 800 << 1;
while ((ch = getopt(argc, argv, "hNs:v:")) != -1)
{
switch(ch)
{
case 'h':
default:
help();
break;
case 'N':
fTest = true;
break;
case 'v':
fVolname = optarg;
break;
case 's':
fBlocks = parseBlocks(optarg);
break;
}
}
// verify size is ok
if (!validBlocks(fBlocks))
{
fprintf(stderr, "Invalid size. Please use 140K -- 32M\n");
exit(1);
}
if (fVolname && !validName(fVolname))
{
fprintf(stderr, "Invalid volume name: `%s'.\n", fVolname);
exit(1);
}
argv += optind;
argc -= optind;
if (argc != 1)
{
help();
}
filename = *argv;
if (!fVolname) fVolname = generateName(filename);
if (fTest)
{
printf(" Image Name: %s\n", filename);
printf("Volume Name: %s\n", fVolname);
printf("Volume Size: %u blocks (%uK)\n", fBlocks, fBlocks >> 1);
exit(0);
}
exit(0);
}

79
profuse.1 Normal file
View File

@@ -0,0 +1,79 @@
.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples.
.\"See Also:
.\"man mdoc.samples for a complete listing of options
.\"man mdoc for the short list of editing options
.\"/usr/share/misc/mdoc.template
.Dd 12/18/08 \" DATE
.Dt profuse 1 \" Program name and manual section number
.Os Darwin
.Sh NAME \" Section Header - required - don't modify
.Nm ProFUSE,
.\" The following lines are read in generating the apropos(man -k) database. Use only key
.\" words here as the database is built based on the words here and in the .ND line.
.Nm Other_name_for_same_program(),
.Nm Yet another name for the same program.
.\" Use .Nm macro to designate other names for the documented program.
.Nd This line parsed for whatis database.
.Sh SYNOPSIS \" Section Header - required - don't modify
.Nm
.Op Fl abcd \" [-abcd]
.Op Fl a Ar path \" [-a path]
.Op Ar file \" [file]
.Op Ar \" [file ...]
.Ar arg0 \" Underlined argument - use .Ar anywhere to underline
arg2 ... \" Arguments
.Sh DESCRIPTION \" Section Header - required - don't modify
Use the .Nm macro to refer to your program throughout the man page like such:
.Nm
Underlining is accomplished with the .Ar macro like this:
.Ar underlined text .
.Pp \" Inserts a space
A list of items with descriptions:
.Bl -tag -width -indent \" Begins a tagged list
.It item a \" Each item preceded by .It macro
Description of item a
.It item b
Description of item b
.El \" Ends the list
.Pp
A list of flags and their descriptions:
.Bl -tag -width -indent \" Differs from above in tag removed
.It Fl a \"-a flag as a list item
Description of -a flag
.It Fl b
Description of -b flag
.El \" Ends the list
.Pp
.\" .Sh ENVIRONMENT \" May not be needed
.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1
.\" .It Ev ENV_VAR_1
.\" Description of ENV_VAR_1
.\" .It Ev ENV_VAR_2
.\" Description of ENV_VAR_2
.\" .El
.Sh FILES \" File used or created by the topic of the man page
.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact
.It Pa /usr/share/file_name
FILE_1 description
.It Pa /Users/joeuser/Library/really_long_file_name
FILE_2 description
.El \" Ends the list
.\" .Sh DIAGNOSTICS \" May not be needed
.\" .Bl -diag
.\" .It Diagnostic Tag
.\" Diagnostic informtion here.
.\" .It Diagnostic Tag
.\" Diagnostic informtion here.
.\" .El
.Sh SEE ALSO
.\" List links in ascending order by section, alphabetically within a section.
.\" Please do not reference files that do not exist without filing a bug report
.Xr a 1 ,
.Xr b 1 ,
.Xr c 1 ,
.Xr a 2 ,
.Xr b 2 ,
.Xr a 3 ,
.Xr b 3
.\" .Sh BUGS \" Document known, unremedied bugs
.\" .Sh HISTORY \" Document history if command behaves in a unique manner

View File

@@ -10,13 +10,11 @@
#define __PROFUSE_H__
#include <ProDOS/File.h>
#include <ProDOS/Disk.h>
#include <ProDOS/common.h>
#include "Disk.h"
#include "common.h"
#define FUSE_USE_VERSION 26
#define FUSE_USE_VERSION 27
#include <fuse_opt.h>
#include <fuse_lowlevel.h>

View File

@@ -0,0 +1,563 @@
// !$*UTF8*$!
{
08FB7793FE84155DC02AAC07 /* Project object */ = {
activeArchitecturePreference = i386;
activeBuildConfigurationName = "Debug Universal";
activeExecutable = B60E914A0EFB3612000E4348 /* profuse */;
activeSDKPreference = macosx10.6;
activeTarget = 8DD76F620486A84900D96B5E /* profuse */;
addToTargets = (
8DD76F620486A84900D96B5E /* profuse */,
);
breakpoints = (
B60E91C10EFD8049000E4348 /* xmain.cpp:129 */,
B6D81E5B0EFDE859000219B7 /* xmain.cpp:163 */,
B6AE1CFF0F0335FC00D36ADB /* main.cpp:20 */,
);
codeSenseManager = B60E91510EFB3628000E4348 /* Code sense */;
executables = (
B60E914A0EFB3612000E4348 /* profuse */,
);
perUserDictionary = {
PBXConfiguration.PBXFileTableDataSource3.PBXErrorsWarningsDataSource = {
PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
PBXFileTableDataSourceColumnSortingKey = PBXErrorsWarningsDataSource_LocationID;
PBXFileTableDataSourceColumnWidthsKey = (
20,
300,
595,
);
PBXFileTableDataSourceColumnsKey = (
PBXErrorsWarningsDataSource_TypeID,
PBXErrorsWarningsDataSource_MessageID,
PBXErrorsWarningsDataSource_LocationID,
);
};
PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = {
PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID;
PBXFileTableDataSourceColumnWidthsKey = (
22,
300,
583,
);
PBXFileTableDataSourceColumnsKey = (
PBXExecutablesDataSource_ActiveFlagID,
PBXExecutablesDataSource_NameID,
PBXExecutablesDataSource_CommentsID,
);
};
PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = {
PBXFileTableDataSourceColumnSortingDirectionKey = 1;
PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
PBXFileTableDataSourceColumnWidthsKey = (
20,
695,
20,
48,
43,
43,
20,
);
PBXFileTableDataSourceColumnsKey = (
PBXFileDataSource_FiletypeID,
PBXFileDataSource_Filename_ColumnID,
PBXFileDataSource_Built_ColumnID,
PBXFileDataSource_ObjectSize_ColumnID,
PBXFileDataSource_Errors_ColumnID,
PBXFileDataSource_Warnings_ColumnID,
PBXFileDataSource_Target_ColumnID,
);
};
PBXConfiguration.PBXFileTableDataSource3.XCSCMDataSource = {
PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
PBXFileTableDataSourceColumnWidthsKey = (
20,
20,
830,
20,
48,
43,
43,
20,
);
PBXFileTableDataSourceColumnsKey = (
PBXFileDataSource_SCM_ColumnID,
PBXFileDataSource_FiletypeID,
PBXFileDataSource_Filename_ColumnID,
PBXFileDataSource_Built_ColumnID,
PBXFileDataSource_ObjectSize_ColumnID,
PBXFileDataSource_Errors_ColumnID,
PBXFileDataSource_Warnings_ColumnID,
PBXFileDataSource_Target_ColumnID,
);
};
PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = {
PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
PBXFileTableDataSourceColumnWidthsKey = (
20,
655,
60,
20,
48,
43,
43,
);
PBXFileTableDataSourceColumnsKey = (
PBXFileDataSource_FiletypeID,
PBXFileDataSource_Filename_ColumnID,
PBXTargetDataSource_PrimaryAttribute,
PBXFileDataSource_Built_ColumnID,
PBXFileDataSource_ObjectSize_ColumnID,
PBXFileDataSource_Errors_ColumnID,
PBXFileDataSource_Warnings_ColumnID,
);
};
PBXPerProjectTemplateStateSaveDate = 320562725;
PBXWorkspaceStateSaveDate = 320562725;
};
perUserProjectItems = {
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 = {
};
};
08FB7796FE84155DC02AAC07 /* xmain.cpp */ = {
isa = PBXFileReference;
fileEncoding = 4;
lastKnownFileType = sourcecode.cpp.cpp;
name = xmain.cpp;
path = "/Users/kelvin/Projects/ProDOS-Fuse/xmain.cpp";
sourceTree = "<absolute>";
};
8DD76F620486A84900D96B5E /* profuse */ = {
activeExec = 0;
executables = (
B60E914A0EFB3612000E4348 /* profuse */,
);
};
B60E914A0EFB3612000E4348 /* profuse */ = {
isa = PBXExecutable;
activeArgIndices = (
);
argumentStrings = (
);
autoAttachOnCrash = 1;
breakpointsEnabled = 0;
configStateDict = {
};
customDataFormattersEnabled = 1;
dataTipCustomDataFormattersEnabled = 1;
dataTipShowTypeColumn = 1;
dataTipSortType = 0;
debuggerPlugin = GDBDebugging;
disassemblyDisplayState = 0;
dylibVariantSuffix = "";
enableDebugStr = 1;
environmentEntries = (
);
executableSystemSymbolLevel = 0;
executableUserSymbolLevel = 0;
libgmallocEnabled = 0;
name = profuse;
savedGlobals = {
};
showTypeColumn = 0;
sourceDirectories = (
);
variableFormatDictionary = {
"_data-char *-Disk::Read" = 1;
"entry_length-unsigned int-Disk::ReadDirectory" = 1;
"xcase-unsigned int-FileEntry::FileEntry" = 3;
};
};
B60E91500EFB3628000E4348 /* Source Control */ = {
isa = PBXSourceControlManager;
fallbackIsa = XCSourceControlManager;
isSCMEnabled = 0;
scmConfiguration = {
repositoryName = profuse.googlecode.com;
repositoryNamesForRoots = {
"" = profuse.googlecode.com;
};
};
};
B60E91510EFB3628000E4348 /* Code sense */ = {
isa = PBXCodeSenseManager;
indexTemplatePath = "";
};
B60E91530EFB51FE000E4348 /* Disk.h */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1245, 1092}}";
sepNavSelRange = "{1156, 11}";
sepNavVisRange = "{76, 1374}";
sepNavWindowFrame = "{{77, 7}, {692, 1171}}";
};
};
B60E91540EFB51FE000E4348 /* Disk.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1032, 8414}}";
sepNavSelRange = "{5390, 0}";
sepNavVisRange = "{4914, 1006}";
sepNavWindowFrame = "{{943, -6}, {692, 1171}}";
};
};
B60E91580EFD77E3000E4348 /* common.h */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {883, 686}}";
sepNavSelRange = "{627, 0}";
sepNavVisRange = "{0, 313}";
sepNavWindowFrame = "{{15, 2}, {692, 1171}}";
};
};
B60E91C10EFD8049000E4348 /* xmain.cpp:129 */ = {
isa = PBXFileBreakpoint;
actions = (
);
breakpointStyle = 0;
continueAfterActions = 0;
countType = 0;
delayBeforeContinue = 0;
fileReference = 08FB7796FE84155DC02AAC07 /* xmain.cpp */;
functionName = "main (int argc, char * const argv[])";
hitCount = 0;
ignoreCount = 0;
lineNumber = 129;
location = "ProDOS-Fuse";
modificationTime = 251949619.113675;
originalNumberOfMultipleMatches = 0;
state = 2;
};
B61BCF86131B6627002DE159 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B6DA7037131047D100E42AA6 /* DiskCopy42Image.cpp */;
name = "DiskCopy42Image.cpp: 49";
rLen = 12;
rLoc = 763;
rType = 0;
vrLen = 851;
vrLoc = 395;
};
B61BCF8F131B6633002DE159 /* smart_pointers.h */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {873, 521}}";
sepNavSelRange = "{0, 0}";
sepNavVisRange = "{0, 903}";
};
};
B61BCF96131B6643002DE159 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
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 = 903;
vrLoc = 0;
};
B61BCFA3131B6741002DE159 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B61BCF8F131B6633002DE159 /* smart_pointers.h */;
name = "smart_pointers.h: 1";
rLen = 0;
rLoc = 0;
rType = 0;
vrLen = 903;
vrLoc = 0;
};
B61BCFA4131B6741002DE159 /* XCBuildMessageTextBookmark */ = {
isa = PBXTextBookmark;
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 = 264;
rType = 1;
};
B61BCFA5131B6741002DE159 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B679E4A70F02E79300FB3F0C /* main.cpp */;
name = "main.cpp: 275";
rLen = 0;
rLoc = 5894;
rType = 0;
vrLen = 1313;
vrLoc = 1695;
};
B650C2C3131090D200046FAD /* File.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1245, 2990}}";
sepNavSelRange = "{0, 0}";
sepNavVisRange = "{1306, 1844}";
};
};
B650C2C4131090D200046FAD /* File.h */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1245, 1742}}";
sepNavSelRange = "{1591, 0}";
sepNavVisRange = "{864, 1333}";
};
};
B679E4A70F02E79300FB3F0C /* main.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {873, 4888}}";
sepNavSelRange = "{5894, 0}";
sepNavVisRange = "{1695, 1313}";
sepNavWindowFrame = "{{342, 156}, {1412, 924}}";
};
};
B6A53BB3131A17AF00C9070F /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = B679E4A70F02E79300FB3F0C /* main.cpp */;
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 = 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 = (
);
breakpointStyle = 0;
continueAfterActions = 0;
countType = 0;
delayBeforeContinue = 0;
fileReference = B679E4A70F02E79300FB3F0C /* main.cpp */;
functionName = "prodos_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)";
hitCount = 0;
ignoreCount = 0;
lineNumber = 20;
location = "ProDOS-Fuse";
modificationTime = 251949619.113812;
originalNumberOfMultipleMatches = 0;
state = 2;
};
B6C786B30F2A59AF00053681 /* profuse.h */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1245, 1011}}";
sepNavSelRange = "{1165, 0}";
sepNavVisRange = "{0, 1449}";
};
};
B6C786B40F2A59FE00053681 /* profuse_xattr.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {873, 7371}}";
sepNavSelRange = "{1034, 5}";
sepNavVisRange = "{998, 1279}";
};
};
B6C786BB0F2A5C0800053681 /* profuse_dirent.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1198, 1781}}";
sepNavSelRange = "{1946, 0}";
sepNavVisRange = "{756, 1661}";
};
};
B6C786BF0F2A5CC000053681 /* profuse_stat.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1245, 3146}}";
sepNavSelRange = "{5137, 0}";
sepNavVisRange = "{3413, 2039}";
};
};
B6C786C30F2A5DCE00053681 /* profuse_file.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {1198, 1781}}";
sepNavSelRange = "{1753, 0}";
sepNavVisRange = "{1323, 1590}";
};
};
B6D81E5B0EFDE859000219B7 /* xmain.cpp:163 */ = {
isa = PBXFileBreakpoint;
actions = (
);
breakpointStyle = 0;
continueAfterActions = 0;
countType = 0;
delayBeforeContinue = 0;
fileReference = 08FB7796FE84155DC02AAC07 /* xmain.cpp */;
functionName = "main (int argc, char * const argv[])";
hitCount = 0;
ignoreCount = 0;
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}}";
sepNavSelRange = "{429, 0}";
sepNavVisRange = "{2400, 722}";
sepNavWindowFrame = "{{15, 249}, {1412, 924}}";
};
};
}

View File

@@ -0,0 +1,565 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 45;
objects = {
/* Begin PBXBuildFile section */
B60E91550EFB51FE000E4348 /* Disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B60E91540EFB51FE000E4348 /* Disk.cpp */; };
B650C2C5131090D200046FAD /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650C2C3131090D200046FAD /* File.cpp */; };
B679E4A80F02E79300FB3F0C /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B679E4A70F02E79300FB3F0C /* main.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 */
8DD76F690486A84900D96B5E /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
8DD76F6C0486A84900D96B5E /* profuse */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = profuse; sourceTree = BUILT_PRODUCTS_DIR; };
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>"; };
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>"; };
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 */
/* Begin PBXFrameworksBuildPhase section */
8DD76F660486A84900D96B5E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
08FB7794FE84155DC02AAC07 /* ProDOS-Fuse */ = {
isa = PBXGroup;
children = (
08FB7795FE84155DC02AAC07 /* Source */,
C6859E8C029090F304C91782 /* Documentation */,
1AB674ADFE9D54B511CA2CBB /* Products */,
B679E49D0F02E71D00FB3F0C /* Libraries */,
);
name = "ProDOS-Fuse";
sourceTree = "<group>";
};
08FB7795FE84155DC02AAC07 /* Source */ = {
isa = PBXGroup;
children = (
B6DA70681310571B00E42AA6 /* ProDOS */,
B6DA70541310551500E42AA6 /* ProFUSE */,
B6DA704D131047FA00E42AA6 /* File */,
B6DA7047131047F400E42AA6 /* Endian */,
B6DA7030131047D100E42AA6 /* Device */,
B6DA7026131047CA00E42AA6 /* Cache */,
B60E91580EFD77E3000E4348 /* common.h */,
B60E91530EFB51FE000E4348 /* Disk.h */,
B60E91540EFB51FE000E4348 /* Disk.cpp */,
B679E4A70F02E79300FB3F0C /* main.cpp */,
B6C786B30F2A59AF00053681 /* profuse.h */,
B6C786BB0F2A5C0800053681 /* profuse_dirent.cpp */,
B6C786C30F2A5DCE00053681 /* profuse_file.cpp */,
B6C786BF0F2A5CC000053681 /* profuse_stat.cpp */,
B6C786B40F2A59FE00053681 /* profuse_xattr.cpp */,
);
name = Source;
sourceTree = "<group>";
};
1AB674ADFE9D54B511CA2CBB /* Products */ = {
isa = PBXGroup;
children = (
8DD76F6C0486A84900D96B5E /* profuse */,
);
name = Products;
sourceTree = "<group>";
};
B679E49D0F02E71D00FB3F0C /* Libraries */ = {
isa = PBXGroup;
children = (
);
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 = (
B6DBB4E70F0C6BBD00F385F2 /* profuse.1 */,
);
name = Documentation;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
8DD76F620486A84900D96B5E /* profuse */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "profuse" */;
buildPhases = (
8DD76F640486A84900D96B5E /* Sources */,
8DD76F660486A84900D96B5E /* Frameworks */,
8DD76F690486A84900D96B5E /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = profuse;
productInstallPath = "$(HOME)/bin";
productName = "ProDOS-Fuse";
productReference = 8DD76F6C0486A84900D96B5E /* profuse */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
08FB7793FE84155DC02AAC07 /* Project object */ = {
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 = "";
targets = (
8DD76F620486A84900D96B5E /* profuse */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
8DD76F640486A84900D96B5E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B60E91550EFB51FE000E4348 /* Disk.cpp in Sources */,
B679E4A80F02E79300FB3F0C /* main.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;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
1DEB923208733DC60010E9CD /* Debug */ = {
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;
};
1DEB923308733DC60010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
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";
};
name = Release;
};
1DEB923608733DC60010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_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 = YES;
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;
};
name = Debug;
};
1DEB923708733DC60010E9CD /* Release */ = {
isa = XCBuildConfiguration;
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 = macosx;
};
name = Release;
};
B618461A0F0AF6CC0045CCF7 /* Debug Universal */ = {
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;
};
name = "Debug Universal";
};
B618461B0F0AF6CC0045CCF7 /* Debug Universal */ = {
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 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 = {
ARCHS = "$(ARCHS_STANDARD_32_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,
.,
);
MACOSX_DEPLOYMENT_TARGET = 10.4;
ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = (
"-D__FreeBSD__=10",
"-D_FILE_OFFSET_BITS=64",
);
OTHER_LDFLAGS = (
"-L/usr/local/lib/",
"-lfuse",
);
PREBINDING = NO;
SDKROOT = macosx;
};
name = "Debug Universal 10.4";
};
B6B767C20F0FF90400D819C9 /* Debug Universal 10.4 */ = {
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 Universal 10.4";
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "profuse" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB923208733DC60010E9CD /* Debug */,
B67F09811057600400A13214 /* Debug 10.6 */,
B618461B0F0AF6CC0045CCF7 /* Debug Universal */,
B6B767C20F0FF90400D819C9 /* Debug Universal 10.4 */,
1DEB923308733DC60010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "profuse" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB923608733DC60010E9CD /* Debug */,
B67F09801057600400A13214 /* Debug 10.6 */,
B618461A0F0AF6CC0045CCF7 /* Debug Universal */,
B6B767C10F0FF90400D819C9 /* Debug Universal 10.4 */,
1DEB923708733DC60010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
}

View File

@@ -8,11 +8,9 @@
#include "profuse.h"
#include <errno.h>
#include <strings.h>
#include <cstdio>
#include <cerrno>
#include <algorithm>
#include <string>
#include <vector>

View File

@@ -7,8 +7,8 @@
*/
#include "profuse.h"
#include <cerrno>
#include <cstdio>
#include <errno.h>
#include <stdio.h>
#pragma mark Read Functions

View File

@@ -10,10 +10,9 @@
#pragma mark Stat Functions
#include "profuse.h"
#include <cerrno>
#include <cstring>
#include <cstdio>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <vector>

View File

@@ -12,10 +12,8 @@
#include <algorithm>
#include <string>
#include <cerrno>
#include <cstring>
#include <cstdio>
#include <errno.h>
#include <string.h>
#include <strings.h>
using std::string;

View File

@@ -1,27 +0,0 @@
#include "BlockDevice.h"
#include "Exception.h"
#include "DavexDiskImage.h"
#include "UniversalDiskImage.h"
#include "DiskCopy42Image.h"
#include <cstdio>
int main(int argc, char **argv)
{
if (argc == 2)
{
try {
//ProFUSE::BlockDevice *dev = ProFUSE::ProDOSOrderDiskImage::Create(argv[1], 1600);
//ProFUSE::BlockDevice *dev = ProFUSE::DavexDiskImage::Create(argv[1], 1600);
//ProFUSE::BlockDevice *dev = ProFUSE::UniversalDiskImage::Create(argv[1], 1600);
ProFUSE::BlockDevice *dev = ProFUSE::DiskCopy42Image::Create(argv[1], 1600);
delete dev;
} catch (ProFUSE::Exception e) {
if (e.error()) printf("%s %s", e.what(), strerror(e.error()));
else printf("%s\n", e.what());
}
}
return 0;
}

Some files were not shown because too many files have changed in this diff Show More