mirror of
https://github.com/ksherlock/profuse.git
synced 2026-04-23 06:31:22 +00:00
Compare commits
29 Commits
2016-08-16
...
profuse_in
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
699c44cf15 | ||
|
|
1a0bdd875c | ||
|
|
77e5994908 | ||
|
|
5ab8fd3d87 | ||
|
|
c6165e16d2 | ||
|
|
87d6070dcf | ||
|
|
0e083d53e7 | ||
|
|
78b1b8b242 | ||
|
|
977f0530fc | ||
|
|
24757dc35c | ||
|
|
ac8bbd5265 | ||
|
|
c7c4f13bf7 | ||
|
|
68a7851f33 | ||
|
|
8550923cb3 | ||
|
|
c9b260b753 | ||
|
|
c44145f551 | ||
|
|
3f8e7ad7ae | ||
|
|
4cdfc52c04 | ||
|
|
1fd924ae1b | ||
|
|
40ea9f2289 | ||
|
|
9a6e9150ef | ||
|
|
2bd72b08b9 | ||
|
|
664dee7578 | ||
|
|
ea0d1c198b | ||
|
|
c82cd3f8fa | ||
|
|
5427db9990 | ||
|
|
7fb0604b76 | ||
|
|
14e9b43f32 | ||
|
|
e5f935e435 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
*.o
|
||||
o/
|
||||
11
.travis.yml
11
.travis.yml
@@ -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
243
Bitmap.cpp
Normal 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
72
Bitmap.h
Normal 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
|
||||
|
||||
56
Buffer.cpp
56
Buffer.cpp
@@ -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] );
|
||||
}
|
||||
}
|
||||
39
Buffer.h
39
Buffer.h
@@ -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
|
||||
@@ -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) :
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 "";
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef __DEVICE_DEVICE_H__
|
||||
#define __DEVICE_DEVICE_H__
|
||||
|
||||
#include <Common/smart_pointers.h>
|
||||
#include <ProFUSE/smart_pointers.h>
|
||||
|
||||
namespace Device {
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -28,13 +28,12 @@ public:
|
||||
|
||||
|
||||
virtual BlockCachePointer createBlockCache();
|
||||
|
||||
|
||||
DiskCopy42Image();
|
||||
DiskCopy42Image(MappedFile *);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
DiskCopy42Image();
|
||||
|
||||
DiskCopy42Image(MappedFile *);
|
||||
bool _changed;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 *);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -26,10 +26,11 @@ public:
|
||||
static bool Validate(MappedFile *);
|
||||
|
||||
|
||||
UniversalDiskImage(MappedFile *);
|
||||
private:
|
||||
|
||||
UniversalDiskImage();
|
||||
|
||||
UniversalDiskImage(MappedFile *);
|
||||
|
||||
uint32_t _format;
|
||||
uint32_t _flags;
|
||||
|
||||
107
Directory.cpp
107
Directory.cpp
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
CC = g++
|
||||
CPPFLAGS += -g -Wall -I../
|
||||
|
||||
|
||||
all : Endian.o
|
||||
|
||||
Endian.o : Endian.cpp Endian.h
|
||||
173
Entry.cpp
173
Entry.cpp
@@ -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
284
Entry.h
@@ -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
|
||||
@@ -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);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
192
MacRoman.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
|
||||
#include "MacRoman.h"
|
||||
|
||||
/*
|
||||
* mapping of MacRoman characters (0x80-0xff) to unicode.
|
||||
*/
|
||||
static unsigned m2u[] = {
|
||||
0x00C4,
|
||||
0x00C5,
|
||||
0x00C7,
|
||||
0x00C9,
|
||||
0x00D1,
|
||||
0x00D6,
|
||||
0x00DC,
|
||||
0x00E1,
|
||||
0x00E0,
|
||||
0x00E2,
|
||||
0x00E4,
|
||||
0x00E3,
|
||||
0x00E5,
|
||||
0x00E7,
|
||||
0x00E9,
|
||||
0x00E8,
|
||||
0x00EA,
|
||||
0x00EB,
|
||||
0x00ED,
|
||||
0x00EC,
|
||||
0x00EE,
|
||||
0x00EF,
|
||||
0x00F1,
|
||||
0x00F3,
|
||||
0x00F2,
|
||||
0x00F4,
|
||||
0x00F6,
|
||||
0x00F5,
|
||||
0x00FA,
|
||||
0x00F9,
|
||||
0x00FB,
|
||||
0x00FC,
|
||||
0x2020,
|
||||
0x00B0,
|
||||
0x00A2,
|
||||
0x00A3,
|
||||
0x00A7,
|
||||
0x2022,
|
||||
0x00B6,
|
||||
0x00DF,
|
||||
0x00AE,
|
||||
0x00A9,
|
||||
0x2122,
|
||||
0x00B4,
|
||||
0x00A8,
|
||||
0x2260,
|
||||
0x00C6,
|
||||
0x00D8,
|
||||
0x221E,
|
||||
0x00B1,
|
||||
0x2264,
|
||||
0x2265,
|
||||
0x00A5,
|
||||
0x00B5,
|
||||
0x2202,
|
||||
0x2211,
|
||||
0x220F,
|
||||
0x03C0,
|
||||
0x222B,
|
||||
0x00AA,
|
||||
0x00BA,
|
||||
0x03A9,
|
||||
0x00E6,
|
||||
0x00F8,
|
||||
0x00BF,
|
||||
0x00A1,
|
||||
0x00AC,
|
||||
0x221A,
|
||||
0x0192,
|
||||
0x2248,
|
||||
0x2206,
|
||||
0x00AB,
|
||||
0x00BB,
|
||||
0x2026,
|
||||
0x00A0,
|
||||
0x00C0,
|
||||
0x00C3,
|
||||
0x00D5,
|
||||
0x0152,
|
||||
0x0153,
|
||||
0x2013,
|
||||
0x2014,
|
||||
0x201C,
|
||||
0x201D,
|
||||
0x2018,
|
||||
0x2019,
|
||||
0x00F7,
|
||||
0x25CA,
|
||||
0x00FF,
|
||||
0x0178,
|
||||
0x2044,
|
||||
0x20AC,
|
||||
0x2039,
|
||||
0x203A,
|
||||
0xFB01,
|
||||
0xFB02,
|
||||
0x2021,
|
||||
0x00B7,
|
||||
0x201A,
|
||||
0x201E,
|
||||
0x2030,
|
||||
0x00C2,
|
||||
0x00CA,
|
||||
0x00C1,
|
||||
0x00CB,
|
||||
0x00C8,
|
||||
0x00CD,
|
||||
0x00CE,
|
||||
0x00CF,
|
||||
0x00CC,
|
||||
0x00D3,
|
||||
0x00D4,
|
||||
0xF8FF,
|
||||
0x00D2,
|
||||
0x00DA,
|
||||
0x00DB,
|
||||
0x00D9,
|
||||
0x0131,
|
||||
0x02C6,
|
||||
0x02DC,
|
||||
0x00AF,
|
||||
0x02D8,
|
||||
0x02D9,
|
||||
0x02DA,
|
||||
0x00B8,
|
||||
0x02DD,
|
||||
0x02DB,
|
||||
0x02C7
|
||||
};
|
||||
|
||||
|
||||
|
||||
bool MacRoman::isASCII() const
|
||||
{
|
||||
for (std::string::const_iterator iter = _string.begin(); iter != _string.end(); ++iter)
|
||||
{
|
||||
if (*iter & 0x80) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacRoman::toUTF8() const
|
||||
{
|
||||
std::string out;
|
||||
out.reserve(_string.length());
|
||||
|
||||
for (std::string::const_iterator iter = _string.begin(); iter != _string.end(); ++iter)
|
||||
{
|
||||
char c = *iter;
|
||||
if (c & 0x80 == 0) out.push_back(c);
|
||||
else
|
||||
{
|
||||
unsigned uc = m2u[c & 0x7f];
|
||||
if (uc <= 0x7ff)
|
||||
{
|
||||
out.push_back(0xC0 | (uc >> 6));
|
||||
out.push_back(0x80 | (uc & 0x3f));
|
||||
}
|
||||
else // nothing larger than 0xffff
|
||||
{
|
||||
out.push_back(0xe0 | (uc >> 12));
|
||||
out.push_back(0x80 | ((uc >> 6) & 0x3f));
|
||||
out.push_back(0x80 | (uc & 0x3f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::wstring MacRoman::toWString() const
|
||||
{
|
||||
std::wstring out;
|
||||
out.reserve(_string.length());
|
||||
|
||||
for (std::string::const_iterator iter = _string.begin(); iter != _string.end(); ++iter)
|
||||
{
|
||||
char c = *iter;
|
||||
if (c & 0x80 == 0) out.push_back(c);
|
||||
else out.push_back(m2u[c & 0x7f]);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
26
MacRoman.h
Normal file
26
MacRoman.h
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
#ifndef __MACROMAN_H__
|
||||
#define __MACROMAN_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
class MacRoman {
|
||||
public:
|
||||
MacRoman(const std::string& string);
|
||||
|
||||
bool isASCII() const;
|
||||
std::string toUTF8() const;
|
||||
std::wstring toWString() const;
|
||||
|
||||
|
||||
private:
|
||||
std::string _string;
|
||||
};
|
||||
|
||||
inline MacRoman::MacRoman(const std::string& string) :
|
||||
_string(string)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
284
Makefile
284
Makefile
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
69
NuFX/Entry.h
69
NuFX/Entry.h
@@ -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
|
||||
@@ -1,10 +0,0 @@
|
||||
#include "Exception.h"
|
||||
|
||||
namespace NuFX {
|
||||
|
||||
const char *NuFX::Exception::errorString()
|
||||
{
|
||||
return ::NuStrError((NuError)error());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
#include "Exception.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
namespace POSIX {
|
||||
|
||||
const char *Exception::errorString()
|
||||
{
|
||||
return strerror(error());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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 "";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "Lock.h"
|
||||
#include <ProFUSE/Lock.h>
|
||||
|
||||
using namespace ProFUSE;
|
||||
|
||||
Lock::Lock()
|
||||
{
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace ProFUSE {
|
||||
|
||||
class Lock {
|
||||
public:
|
||||
@@ -27,4 +28,6 @@ private:
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace ProFUSE {
|
||||
|
||||
template <class T>
|
||||
class auto_array
|
||||
@@ -97,6 +98,7 @@ private:
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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>
|
||||
|
||||
92
Volume.h
92
Volume.h
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
1077
bin/apfm.cpp
1077
bin/apfm.cpp
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
33
makefile.freebsd
Executable 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
33
makefile.linux
Executable 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
199
newfs_prodos.cpp
Normal 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
79
profuse.1
Normal 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
|
||||
@@ -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>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
563
profuse.xcodeproj/kelvin.pbxuser
Normal file
563
profuse.xcodeproj/kelvin.pbxuser
Normal 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}}";
|
||||
};
|
||||
};
|
||||
}
|
||||
565
profuse.xcodeproj/project.pbxproj
Normal file
565
profuse.xcodeproj/project.pbxproj
Normal 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 */;
|
||||
}
|
||||
@@ -8,11 +8,9 @@
|
||||
|
||||
#include "profuse.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cerrno>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -7,8 +7,8 @@
|
||||
*/
|
||||
|
||||
#include "profuse.h"
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#pragma mark Read Functions
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
27
test.cpp
27
test.cpp
@@ -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
Reference in New Issue
Block a user