From a3cc7627b860705c98c88cf457128a18747ebbfe Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 21 Nov 2009 01:45:08 +0000 Subject: [PATCH 002/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@68 aa027e90-d47c-11dd-86d7-074df07e0730 --- Bitmap.cpp | 197 ++++++++++++++++++++++++++ Bitmap.h | 44 ++++++ BlockDevice.cpp | 167 ++++++++++++++++++++++ BlockDevice.h | 83 +++++++++++ Buffer.cpp | 40 ++++++ Buffer.h | 33 +++++ DavexDiskImage.cpp | 144 +++++++++++++++++++ DavexDiskImage.h | 30 ++++ Directory.cpp | 133 ++++++++++++++++++ Directory.h | 151 ++++++++++++++++++++ DiskCopy42Image.cpp | 181 ++++++++++++++++++++++++ DiskCopy42Image.h | 32 +++++ Exception.cpp | 13 ++ Exception.h | 59 ++++++++ Lock.cpp | 26 ++++ Lock.h | 28 ++++ MappedFile.cpp | 307 +++++++++++++++++++++++++++++++++++++++++ MappedFile.h | 78 +++++++++++ UniversalDiskImage.cpp | 110 +++++++++++++++ UniversalDiskImage.h | 23 +++ Volume.h | 92 ++++++++++++ auto.h | 72 ++++++++++ test.cpp | 27 ++++ 23 files changed, 2070 insertions(+) create mode 100644 Bitmap.cpp create mode 100644 Bitmap.h create mode 100644 BlockDevice.cpp create mode 100644 BlockDevice.h create mode 100644 Buffer.cpp create mode 100644 Buffer.h create mode 100644 DavexDiskImage.cpp create mode 100644 DavexDiskImage.h create mode 100644 Directory.cpp create mode 100644 Directory.h create mode 100644 DiskCopy42Image.cpp create mode 100644 DiskCopy42Image.h create mode 100644 Exception.cpp create mode 100644 Exception.h create mode 100644 Lock.cpp create mode 100644 Lock.h create mode 100644 MappedFile.cpp create mode 100644 MappedFile.h create mode 100644 UniversalDiskImage.cpp create mode 100644 UniversalDiskImage.h create mode 100644 Volume.h create mode 100644 auto.h create mode 100644 test.cpp diff --git a/Bitmap.cpp b/Bitmap.cpp new file mode 100644 index 0000000..3605d9e --- /dev/null +++ b/Bitmap.cpp @@ -0,0 +1,197 @@ +#include "Bitmap.h" +#include + +#include "auto.h" + + +// returns # of 1-bits set (0-8) +inline static unsigned popCount(uint8_t x) +{ + #ifdef __GNUC__ + return __builtin_popcount(x); + #endif + + // Brian Kernighan / Peter Wegner in CACM 3 (1960), 322. + + unsigned count; + for (count = 0; x; ++count) + { + x &= x - 1; + } + return count; +} + + + +Bitmap::Bitmap(unsigned blocks) +{ + _blocks = _freeBlocks = blocks; + + _bitmapBlocks = (blocks + 4095) / 4096; + _freeIndex = 0; + + unsigned bitmapSize = _bitmapBlocks * 512; + unsigned blockSize = blocks / 8; + + auto_array bitmap(new uint8_t[bitmapSize]); + + // mark overflow in use, everything else free. + + std::memset(bitmap, 0xff, blocks / 8); + std::memset(bitmap + blockSize, 0x00, bitmapSize - blockSize); + + // edge case + unsigned tmp = blocks & 0x07; + + bitmap[blocks / 8] = ~(0xff >> tmp); + + _bitmap = bitmap.release(); + + +} + +Bitmap::Bitmap(BlockDevice *device, unsigned keyPointer, unsigned blocks) +{ + _blocks = blocks; + _freeBlocks = 0; + _freeIndex = 0; + + _bitmapBlocks = (blocks + 4095) / 4096; + + unsigned bitmapSize = _bitmapBlocks * 512; + unsigned blockSize = blocks / 8; + + auto_array bitmap(new uint8_t[bitmapSize]); + + for (unsigned i = 0; i < blockSize; ++i) + { + device->readBlock(keyPointer + i, bitmap + 512 * i); + } + + // make sure all trailing bits are marked in use. + + // edge case + unsigned tmp = blocks & 0x07; + + bitmap[blocks / 8] &= ~(0xff >> tmp); + + std::memset(bitmap + blockSize, 0x00, bitmapSize - blockSize); + + // set _freeBlocks and _freeIndex; + for (unsigned i = 0; i < (blocks + 7) / 8; ++i) + { + _freeBlocks += popCount(bitmap[i]); + } + + if (_freeblocks) + { + for (unsigned i = 0; i < (blocks + 7) / 8; ++i) + { + if (tmp[i]) + { + _freeIndex = i; + break; + } + } + } + + + _bitmap = bitmap.release(); +} + +Bitmap::~Bitmap() +{ + if (_bitmap) delete []_bitmap; +} + + +void Bitmap::freeBlock(unsigned block) +{ + if (block >= _blocks) return; + + unsigned index = block / 8; + unsigned offset = block & 0x07; + unsigned mask = 0x80 >> offset; + + uint8_t tmp = _bitmap[index]; + + if ((tmp & mask) == 0) + { + ++_freeBlocks; + _bitmap[index] = tmp | mask; + } +} + + +int Bitmap::allocBlock(unsigned block) +{ + if (block >= _blocks) return -1; + + + unsigned index = block / 8; + unsigned offset = block & 0x07; + unsigned mask = 0x80 >> offset; + + uint8_t tmp = _bitmap[index]; + + if ((tmp & mask)) + { + --_freeBlocks; + _bitmap[index] = tmp & ~mask; + return block; + } + + return -1; +} + + +int Bitmap::allocBlock() +{ + if (!_freeBlocks) return -1; + + unsigned firstIndex = _firstIndex; + unsigned maxIndex = (_blocks + 7) / 8; + + + for (unsigned index = _firstIndex; index < maxIndex; ++index) + { + uint8_t tmp = _bitmap[index]; + if (!tmp) continue; + + unsigned mask = 0x80; + for (unsigned offset = 0; offset < 8; ++offset) + { + if (tmp & mask) + { + _firstIndex = index; + _bitmap[index] = tmp & ~mask; + --_freeBlocks; + return index * 8 + offset; + } + mask = mask >> 1; + } + } + + for (unsigned index = 0; index < _firstIndex; ++index) + { + uint8_t tmp = _bitmap[index]; + if (!tmp) continue; + + unsigned mask = 0x80; + for (unsigned offset = 0; offset < 8; ++offset) + { + if (tmp & mask) + { + _firstIndex = index; + _bitmap[index] = tmp & ~mask; + --_freeBlocks; + return index * 8 + offset; + } + mask = mask >> 1; + } + } + + + // should never happen... + return -1; +} \ No newline at end of file diff --git a/Bitmap.h b/Bitmap.h new file mode 100644 index 0000000..b4dcf40 --- /dev/null +++ b/Bitmap.h @@ -0,0 +1,44 @@ +#ifndef __BITMAP_H__ +#define __BITMAP_H__ + +#include +class BlockDevice; + +namespace ProFUSE { + +class Bitmap { +public: + + Bitmap(unsigned blocks); + Bitmap(BlockDevice *device, int keyPointer, int blocks); + //todo -- constructor by loading fro, block device... + ~Bitmap(); + + int allocBlock(); + int allocBlock(unsigned block); + + void freeBlock(unsigned block); + + + unsigned freeBlocks() const { return _freeBlocks; } + unsigned blocks() const { return _blocks; } + unsigned bitmapBlocks() const { return _bitmapBlocks; } + unsigned bitmapSize() const { return _bitmapBlocks * 512; } + const void *bitmap() const { return _bitmap; } + +private: + + unsigned _freeIndex; + unsigned _freeBlocks; + + unsigned _blocks; + unsigned _bitmapBlocks; + + uint8_t *_bitmap; +}; + + + +} + +#endif diff --git a/BlockDevice.cpp b/BlockDevice.cpp new file mode 100644 index 0000000..feeae82 --- /dev/null +++ b/BlockDevice.cpp @@ -0,0 +1,167 @@ +#include "BlockDevice.h" +#include "Exception.h" +#include "MappedFile.h" + +#include +#include +#include + +#include +#include +#include + +using namespace ProFUSE; + + + +BlockDevice::~BlockDevice() +{ +} + + +#pragma mark DiskImage + +DiskImage::DiskImage(const char *name, bool readOnly) : + _file(NULL) +{ + _file = new MappedFile(name, readOnly); +} + +DiskImage::DiskImage(MappedFile *file) : + _file(file) +{ +} + +DiskImage::~DiskImage() +{ + delete _file; +} + +bool DiskImage::readOnly() +{ + #undef __METHOD__ + #define __METHOD__ "DiskImage::readOnly" + + if (_file) return _file->readOnly(); + + throw Exception(__METHOD__ ": File not set."); +} + + + + + +void DiskImage::read(unsigned block, void *bp) +{ + #undef __METHOD__ + #define __METHOD__ "DiskImage::read" + + + if (_file) return _file->readBlock(block, bp); + + throw Exception(__METHOD__ ": File not set."); +} + +void DiskImage::write(unsigned block, const void *bp) +{ + #undef __METHOD__ + #define __METHOD__ "DiskImage::write" + + if (_file) return _file->writeBlock(block, bp); + + throw Exception(__METHOD__ ": File not set."); +} + + + +void DiskImage::sync() +{ + #undef __METHOD__ + #define __METHOD__ "DiskImage::sync" + + if (_file) return _file->sync(); + + throw Exception(__METHOD__ ": File not set."); +} + + + +ProDOSOrderDiskImage::ProDOSOrderDiskImage(const char *name, bool readOnly) : + DiskImage(name, readOnly) +{ + Validate(file()); +} + +ProDOSOrderDiskImage::ProDOSOrderDiskImage(MappedFile *file) : + DiskImage(file) +{ +} + +ProDOSOrderDiskImage *ProDOSOrderDiskImage::Create(const char *name, size_t blocks) +{ + MappedFile *file = new MappedFile(name, blocks * 512); + return new ProDOSOrderDiskImage(file); +} + +ProDOSOrderDiskImage *ProDOSOrderDiskImage::Open(MappedFile *file) +{ + Validate(file); + return new ProDOSOrderDiskImage(file); +} + +void ProDOSOrderDiskImage::Validate(MappedFile *f) +{ + #undef __METHOD__ + #define __METHOD__ "ProDOSOrderDiskImage::Validate" + + if (!f) throw Exception(__METHOD__ ": File not set."); + + size_t size = f->fileSize(); + + if (size % 512) + throw Exception(__METHOD__ ": Invalid file format."); + + f->reset(); + f->setBlocks(size / 512); +} + +DOSOrderDiskImage::DOSOrderDiskImage(const char *name, bool readOnly) : + DiskImage(name, readOnly) +{ + Validate(file()); +} + +DOSOrderDiskImage::DOSOrderDiskImage(MappedFile *file) : + DiskImage(file) +{ +} + +DOSOrderDiskImage *DOSOrderDiskImage::Create(const char *name, size_t blocks) +{ + MappedFile *file = new MappedFile(name, blocks * 512); + file->setDosOrder(true); + return new DOSOrderDiskImage(file); +} + +DOSOrderDiskImage *DOSOrderDiskImage::Open(MappedFile *file) +{ + Validate(file); + return new DOSOrderDiskImage(file); +} + +void DOSOrderDiskImage::Validate(MappedFile *f) +{ + #undef __METHOD__ + #define __METHOD__ "DOSOrderDiskImage::Validate" + + if (!f) throw Exception(__METHOD__ ": File not set."); + + size_t size = f->fileSize(); + + if (size % 512) + throw Exception(__METHOD__ ": Invalid file format."); + + f->reset(); + f->setDosOrder(true); + f->setBlocks(size / 512); +} diff --git a/BlockDevice.h b/BlockDevice.h new file mode 100644 index 0000000..e024161 --- /dev/null +++ b/BlockDevice.h @@ -0,0 +1,83 @@ +#ifndef __BLOCKDEVICE_H__ +#define __BLOCKDEVICE_H__ + +#include +#include + +#include "Exception.h" + +namespace ProFUSE { + +class MappedFile; + +class BlockDevice { +public: + virtual ~BlockDevice(); + + virtual void read(unsigned block, void *bp) = 0; + virtual void write(unsigned block, const void *bp) = 0; + + virtual bool readOnly() = 0; + virtual void sync() = 0; +}; + + + +class DiskImage : public BlockDevice { +public: + + virtual ~DiskImage(); + + virtual void read(unsigned block, void *bp); + virtual void write(unsigned block, const void *bp); + virtual void sync(); + + virtual bool readOnly(); + + +protected: + + DiskImage(MappedFile * = NULL); + DiskImage(const char *name, bool readOnly); + + MappedFile *file() { return _file; } + void setFile(MappedFile *); + +private: + MappedFile *_file; +}; + + +class ProDOSOrderDiskImage : public DiskImage { +public: + + ProDOSOrderDiskImage(const char *name, bool readOnly); + + static ProDOSOrderDiskImage *Create(const char *name, size_t blocks); + static ProDOSOrderDiskImage *Open(MappedFile *); + +private: + ProDOSOrderDiskImage(MappedFile *); + static void Validate(MappedFile *); +}; + +class DOSOrderDiskImage : public DiskImage { +public: + + DOSOrderDiskImage(const char *name, bool readOnly); + + static DOSOrderDiskImage *Create(const char *name, size_t blocks); + static DOSOrderDiskImage *Open(MappedFile *); + +private: + DOSOrderDiskImage(MappedFile *); + static void Validate(MappedFile *); +}; + + + + + +} + +#endif \ No newline at end of file diff --git a/Buffer.cpp b/Buffer.cpp new file mode 100644 index 0000000..9e855ad --- /dev/null +++ b/Buffer.cpp @@ -0,0 +1,40 @@ + +#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::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] ); + } +} \ No newline at end of file diff --git a/Buffer.h b/Buffer.h new file mode 100644 index 0000000..5a0ebf1 --- /dev/null +++ b/Buffer.h @@ -0,0 +1,33 @@ +#ifndef __BUFFER_H__ +#define __BUFFER_H__ + +#include + +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 push8(uint8_t x) { _buffer.push_back(x); } + + void push16be(uint16_t); + void push16le(uint16_t); + + void push32be(uint32_t); + void push32le(uint32_t); + + void pushBytes(const void *data, unsigned size); + + +private: + std::vector _buffer; +}; + +} +#endif diff --git a/DavexDiskImage.cpp b/DavexDiskImage.cpp new file mode 100644 index 0000000..ac8818b --- /dev/null +++ b/DavexDiskImage.cpp @@ -0,0 +1,144 @@ +#include "DavexDiskImage.h" +#include "MappedFile.h" +#include "Buffer.h" + +#include +#include +#include +#include +#include +#include + +using namespace ProFUSE; + +/* + http://www.umich.edu/~archive/apple2/technotes/ftn/FTN.E0.8004 + */ + +static const char *IdentityCheck = "\x60VSTORE [Davex]\x00"; + +DavexDiskImage::DavexDiskImage(const char *name, bool readOnly) : + DiskImage(name, readOnly) +{ + Validate(file()); +} + +// private, validation already performed. +DavexDiskImage::DavexDiskImage(MappedFile *f) : + DiskImage(f) +{ +} + + +DavexDiskImage::~DavexDiskImage() +{ + // scan and update usedBlocks? +} + +void DavexDiskImage::Validate(MappedFile *f) +{ +#undef __METHOD__ +#define __METHOD__ "DavexDiskImage::Validate" + + size_t size = f->fileSize(); + void * data = f->fileData(); + bool ok = false; + unsigned blocks = (size / 512) - 1; + + do { + if (size < 512) break; + if (size % 512) break; + + // identity. + if (std::memcmp(data, IdentityCheck, 16)) + break; + + // file format. + if (f->read8(16) != 0) + break; + + // total blocks + if (f->read32(33, LittleEndian) != blocks) + break; + + // file number -- must be 1 + if (f->read8(64) != 1) + break; + + ok = true; + } while (false); + + + if (!ok) + throw Exception(__METHOD__ ": Invalid file format."); + + f->setBlocks(blocks); + f->setOffset(512); + f->setDosOrder(false); +} + +DavexDiskImage *DavexDiskImage::Open(MappedFile *file) +{ +#undef __METHOD__ +#define __METHOD__ "DavexDiskImage::Open" + Validate(file); + + return new DavexDiskImage(file); +} + +DavexDiskImage *DavexDiskImage::Create(const char *name, size_t blocks) +{ +#undef __METHOD__ +#define __METHOD__ "DavexDiskImage::Create" + + uint8_t *data; + + MappedFile *file = new MappedFile(name, blocks * 512 + 512); + + data = (uint8_t *)file->fileData(); + + Buffer header(512); + + header.pushBytes(IdentityCheck, 16); + // file Format + header.push8(0); + //version + header.push8(0); + // version + header.push8(0x10); + + // reserved. + header.resize(32); + + //deviceNum + header.push8(1); + + // total blocks + header.push32le(blocks); + + // unused blocks + header.push32le(0); + + // volume Name + header.pushBytes("\x08Untitled", 9); + + // name + reserved. + header.resize(64); + + // file number + header.push8(1); + + //starting block + header.push32le(0); + + // reserved + header.resize(512); + + + std::memcpy(file->fileData(), header.buffer(), 512); + file->sync(); + + file->setOffset(512); + file->setBlocks(blocks); + return new DavexDiskImage(file); +} diff --git a/DavexDiskImage.h b/DavexDiskImage.h new file mode 100644 index 0000000..0541428 --- /dev/null +++ b/DavexDiskImage.h @@ -0,0 +1,30 @@ + + +#include "BlockDevice.h" +#include + +namespace ProFUSE { + +// only supports 1 file; may be split over multiple files. + +class DavexDiskImage : public DiskImage { +public: + + DavexDiskImage(const char *, bool readOnly); + virtual ~DavexDiskImage(); + + static DavexDiskImage *Create(const char *name, size_t blocks); + static DavexDiskImage *Open(MappedFile *); + + +private: + + DavexDiskImage(MappedFile *); + static void Validate(MappedFile *); + + bool _changed; + std::string _volumeName; +}; + + +} \ No newline at end of file diff --git a/Directory.cpp b/Directory.cpp new file mode 100644 index 0000000..83d7058 --- /dev/null +++ b/Directory.cpp @@ -0,0 +1,133 @@ +#include "Directory" + +#include + +#include "Exception.h" + +using namespace ProFUSE; + +static bool isalpha(unsigned c) +{ + return (c >= 'A' && c <= 'Z') + || (c >= 'a' && x <= 'z') ; +} + +static bool isalnumdot(unsigned c) +{ + return (c >= 'A' && c <= 'Z') + || (c >= 'a' && c <= 'z') + || (c >= '0' && c <='9') + || (c == '.') ; + +} + +static uint16_t read16(uint8_t *data, unsigned offset) +{ + return data[offset + 0] + | (data[offset + 1] << 8) ; +} + +static uint32_t read24(uint8_t *data, unsigned offset) +{ + return data[offset + 0] + | (data[offset + 1] << 8) + | (data[offset + 2] << 16) ; +} + + +static uint32_t read32(uint8_t *data, unsigned offset) +{ + return data[offset + 0] + | (data[offset + 1] << 8) + | (data[offset + 2] << 16) ; + | (data[offset + 3] << 24) ; +} + +unsigned ValidName(const char *name) +{ + unsigned length; + + if (!name) return 0; + + if (!isalpha(*name)) return 0; + length = 1; + + for (length = 1; length < 17; ++length) + { + if (!isalnumdot(name[length])) return 0; + } + + if (length > 15) return 0; + return length; +} + +Directory::Directory(unsigned type, const char *name) +{ +#undef __METHOD__ +#define __METHOD__ "Directory::Directory" + + _nameLength = ValidName(name); + + if (!_length) + throw Exception(__METHOD__ ": Invalid name."); + + _storageType = type; + std::strncpy(_name, name, 16); + + _access = 0xc3; + _entryLength = 0x27; + _entriesPerBlock = 13; + _fileCount = 0; + + _device = NULL; +} + +Directory::Directory(const void *bp) : + _creation(0, 0) +{ +#undef __METHOD__ +#define __METHOD__ "Directory::Directory" + + const uint8_t *data = (const uint8_t *)bp; + + _storageType = data[0x00] >> 4; + _nameLength = data[0x00] & 0x0f; + std::memcpy(_name, data + 1, _nameLength); + _name[_nameLength] = 0; + _creation = DateTime(read16(data, 0x1c), read16(data, 0x1e)); + + _access = data[0x22]; + _entryLength = data[0x23]; + _entriesPerBlock = data[0x24]; + + _fileCount = read16(data, 0x25); + + // parse child file entries. +} + +Directory::~Directory() +{ +} + +Directory::setAccess(unsigned access) +{ +#undef __METHOD__ +#define __METHOD__ "Directory::setAccess" + + if ((access & 0xe3) != access) + throw Exception(__METHOD__ ": Illegal access."); + _access = access; + + // todo -- mark dirty? update block? +} + +Directory::setName(const char *name) +{ + unsigned length = ValidName(name); + if (!length) + throw Exception(__METHOD__ ": Invalid name."); + _nameLength = length; + std::strncpy(_name, name, 16); + + // todo -- update or mark dirty. +} diff --git a/Directory.h b/Directory.h new file mode 100644 index 0000000..8fe229c --- /dev/null +++ b/Directory.h @@ -0,0 +1,151 @@ +#ifndef __DIRECTORY_H__ +#define __DIRECTORY_H__ + +#include +#include + +#include "DateTime.h" + + +namespace ProFUSE { + +class BlockDevice; +class Bitmap; +class FileEntry; +class Volume; + + +enum { + DestroyEnabled = 0x80, + RenameEnabled = 0x40, + BackupNeeded = 0x20, + WriteEnabled = 0x02, + ReadEnabled = 0x01 +}; + + +class Entry { +public: + virtual ~Entry(); + + + + unsigned storageType() const { return _storageType; } + + unsigned nameLength() const { return _nameLength; } + const char *name() const { return _name; } + void setName(const char *name); + + + + // returns strlen() on success, 0 on failure. + static unsigned ValidName(const char *); + +protected: + Entry(int storageType, const char *name); + +private: + + unsigned _address; // absolute address on disk. + Volume *_volume; + + unsigned _storageType; + unsigned _nameLength; + char _name[15+1]; + +}; + +class Directory public Entry { +public: + 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; } + + void setAccess(unsigned access); + + +protected: + Directory(unsigned type, const char *name); + Directory(BlockDevice *, unsigned block); + + std::vector _children; + std::vector _entryBlocks; + + BlockDevice *_device; + + +private: + + DateTime _creation; + // version + // min version + unsigned _access; + usnigned _entryLength; // always 0x27 + unsigned _entriesPerBlock; //always 0x0d + + unsigned _fileCount; +}; + + + +class VolumeDirectory: public Directory { +public: + + virtual ~VolumeDirectory(); + + unsigned bitmapPointer() const { return _bitmapPointer; } + unsigned totalBlocks() const { return _totalBlocks; } + + // bitmap stuff... + int allocBlock(); + void freeBlock(unsigned block); + +private: + Bitmap *_bitmap; + + unsigned _totalBlocks; + unsigned _bitmapPointer; + + // inode / free inode list? + +}; + + +class SubDirectory : public Directory { +public: + +private: + unsigned _parentPointer; + unsigned _parentEntryNumber; + unsigned _parentEntryLength; +}; + + +class FileEntry : public Entry { +public: + + +private: + unsigned _fileType; + unsigned _keyPointer; + unsigned _blocksUsed; + unsigned _eof; + DateTime _creation; + //version + //min version + unsigned _access; + unsigned _auxType; + DateTime _modification; + unsigned _headerPointer; + +}; + +} +#endif diff --git a/DiskCopy42Image.cpp b/DiskCopy42Image.cpp new file mode 100644 index 0000000..10f1d94 --- /dev/null +++ b/DiskCopy42Image.cpp @@ -0,0 +1,181 @@ +#include "DiskCopy42Image.h" +#include "MappedFile.h" +#include "Buffer.h" + +#include + +using namespace ProFUSE; + +DiskCopy42Image::DiskCopy42Image(MappedFile *f) : + DiskImage(f), + _changed(false) +{ +} + +DiskCopy42Image::DiskCopy42Image(const char *name, bool readOnly) : + DiskImage(name, readOnly), + _changed(false) +{ + Validate(file()); +} + +DiskCopy42Image::~DiskCopy42Image() +{ + if (_changed) + { + MappedFile *f = file(); + if (f) + { + uint32_t cs = Checksum(f->offset() + (uint8_t *)f->fileData(), + f->blocks() * 512); + + f->write32(72, cs, BigEndian); + f->sync(); + } + // TODO -- checksum + } +} + +uint32_t DiskCopy42Image::Checksum(void *data, size_t size) +{ + uint32_t rv = 0; + uint8_t *dp = (uint8_t *)data; + + if (size & 0x01) return rv; + + for (size_t i = 0; i < size; i += 2) + { + rv += dp[i] << 8; + rv += dp[i+1]; + + rv = (rv >> 1) + (rv << 31); + } + + return rv; +} + +DiskCopy42Image *DiskCopy42Image::Open(MappedFile *f) +{ + Validate(f); + return new DiskCopy42Image(f); +} + +static uint8_t DiskFormat(size_t blocks) +{ + switch (blocks) + { + case 800: return 0; + case 1600: return 1; + case 1440: return 2; + case 2880: return 3; + default: return 0xff; + } +} + +static uint8_t FormatByte(size_t blocks) +{ + switch(blocks) + { + case 800: return 0x12; + default: return 0x22; + } +} +DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks) +{ + MappedFile *file = new MappedFile(name, blocks * 512 + 84); + file->setOffset(84); + file->setBlocks(blocks); + + Buffer header(84); + + // name -- 64byte pstring. + header.pushBytes("\x08Untitled", 9); + header.resize(64); + + // data size -- number of bytes + header.push32be(blocks * 512); + + // tag size + header.push32be(0); + + // data checksum + // if data is 0, will be 0. + //header.push32be(Checksum(file->fileData(), blocks * 512)); + header.push32be(0); + + // tag checksum + header.push32be(0); + + // disk format. + /* + * 0 = 400k + * 1 = 800k + * 2 = 720k + * 3 = 1440k + * 0xff = other + */ + header.push8(DiskFormat(blocks)); + + // formatbyte + /* + * 0x12 = 400k + * 0x22 = >400k mac + * 0x24 = 800k appleII + */ + header.push8(FormatByte(blocks)); + + // private + header.push16be(0x100); + + std::memcpy(file->fileData(), header.buffer(), 84); + file->sync(); + + return new DiskCopy42Image(file); +} + +void DiskCopy42Image::Validate(MappedFile *file) +{ + size_t bytes = 0; + size_t size = file->fileSize(); + bool ok = false; + uint32_t checksum; + + do { + if (size < 84) break; + + // name must be < 64 + if (file->read8(0) > 63) break; + + if (file->read32(82, BigEndian) != 0x100) + break; + + // bytes, not blocks. + bytes = file->read32(64, BigEndian); + + if (bytes % 512) break; + + if (size < 84 + bytes) break; + + // todo -- checksum. + checksum = file->read32(72, BigEndian); + + ok = true; + } while (false); + + + uint32_t cs = Checksum(64 + (uint8_t *)file->fileData(), bytes); + + if (cs != checksum) + { + fprintf(stderr, "Warning: checksum invalid.\n"); + } + file->reset(); + file->setOffset(64); + file->setBlocks(bytes / 512); +} + +void DiskCopy42Image::write(unsigned block, const void *bp) +{ + DiskImage::write(block, bp); + _changed = true; +} \ No newline at end of file diff --git a/DiskCopy42Image.h b/DiskCopy42Image.h new file mode 100644 index 0000000..689deca --- /dev/null +++ b/DiskCopy42Image.h @@ -0,0 +1,32 @@ +#ifndef __DISKCOPY42IMAGE_H__ +#define __DISKCOPY42IMAGE_H__ + +#include "BlockDevice.h" + +#include + +namespace ProFUSE { + +class DiskCopy42Image : public DiskImage { +public: + DiskCopy42Image(const char *name, bool readOnly); + virtual ~DiskCopy42Image(); + + static DiskCopy42Image *Create(const char *name, size_t blocks); + static DiskCopy42Image *Open(MappedFile *); + + static uint32_t Checksum(void *data, size_t size); + + virtual void write(unsigned block, const void *bp); + + +private: + + DiskCopy42Image(MappedFile *); + static void Validate(MappedFile *); + bool _changed; +}; + +} + +#endif \ No newline at end of file diff --git a/Exception.cpp b/Exception.cpp new file mode 100644 index 0000000..ee0cbee --- /dev/null +++ b/Exception.cpp @@ -0,0 +1,13 @@ + +#include "Exception.h" + +using namespace ProFUSE; + +Exception::~Exception() throw() +{ +} + +const char *Exception::what() +{ + return _string.c_str(); +} \ No newline at end of file diff --git a/Exception.h b/Exception.h new file mode 100644 index 0000000..cf9ffb7 --- /dev/null +++ b/Exception.h @@ -0,0 +1,59 @@ +#ifndef __EXCEPTION_H__ +#define __EXCEPTION_H__ + +#include +#include + +namespace ProFUSE { + +class Exception : public std::exception +{ +public: + Exception(const char *cp); + Exception(const std::string &str); + Exception(const char *cp, int error); + Exception(const std::string& string, int error); + + virtual ~Exception() throw (); + + virtual const char *what(); + + int error() const; +private: + int _error; + std::string _string; + +}; + +inline Exception::Exception(const char *cp): + _error(0), + _string(cp) +{ +} + +inline Exception::Exception(const std::string& string): + _error(0), + _string(string) +{ +} + +inline Exception::Exception(const char *cp, int error): + _error(error), + _string(cp) +{ +} + +inline Exception::Exception(const std::string& string, int error): + _error(error), + _string(string) +{ +} + +inline int Exception::error() const +{ + return _error; +} + +} + +#endif \ No newline at end of file diff --git a/Lock.cpp b/Lock.cpp new file mode 100644 index 0000000..ddd9fa4 --- /dev/null +++ b/Lock.cpp @@ -0,0 +1,26 @@ +#include "Lock.h" + +Lock::Lock() +{ + pthread_mutex_init(&_mutex, NULL); +} + +Lock::~Lock() +{ + pthread_mutex_destroy(&_mutex); +} + +void Lock::lock() +{ + pthread_mutex_lock(&_mutex); +} + +void Lock::unlock() +{ + pthread_mutex_unlock(&_mutex); +} + +bool Lock::tryLock() +{ + return pthread_mutex_trylock(&_mutex) == 0; +} \ No newline at end of file diff --git a/Lock.h b/Lock.h new file mode 100644 index 0000000..cbb3bc7 --- /dev/null +++ b/Lock.h @@ -0,0 +1,28 @@ +#ifndef __LOCK_H__ +#define __LOCK_H__ + +#include + +class Lock { +public: + Lock(); + ~Lock(); + + void lock(); + void unlock(); + + bool tryLock(); + +private: + pthread_mutex_t _mutex; +}; + +class Locker { +public: + Locker(Lock& lock) : _lock(lock) { _lock.lock(); } + ~Locker() { _lock.unlock(); } +private: + Lock &_lock; +}; + +#endif \ No newline at end of file diff --git a/MappedFile.cpp b/MappedFile.cpp new file mode 100644 index 0000000..fa3b198 --- /dev/null +++ b/MappedFile.cpp @@ -0,0 +1,307 @@ +#include "MappedFile.h" +#include "Exception.h" +#include +#include +#include + +#include +#include +#include + +#include "auto.h" + +using namespace ProFUSE; + + + +MappedFile::MappedFile(const char *name, bool readOnly) : + _fd(-1), + _map(MAP_FAILED) +{ + #undef __METHOD__ + #define __METHOD__ "MappedFile::MappedFile" + + auto_fd fd(::open(name, readOnly ? O_RDONLY : O_RDWR)); + + if (fd < 0) + { + throw Exception(__METHOD__ ": Unable to open file.", errno); + } + // + init(fd.release(), readOnly); +} + +MappedFile::MappedFile(int fd, bool readOnly) : + _fd(-1), + _map(MAP_FAILED) +{ + init(fd, readOnly); +} + +// todo -- verify throw calls destructor. +MappedFile::MappedFile(const char *name, size_t size) : + _fd(-1), + _map(MAP_FAILED) +{ + #undef __METHOD__ + #define __METHOD__ "MappedFile::MappedFile" + + _size = size; + _readOnly = false; + auto_fd fd(::open(name, O_CREAT | O_TRUNC | O_RDWR, 0644)); + + if (fd < 0) + throw Exception(__METHOD__ ": Unable to create file.", errno); + + // TODO -- is ftruncate portable? + if (::ftruncate(fd, _size) < 0) + { + throw Exception(__METHOD__ ": Unable to truncate file.", errno); + } + + //_map = ::mmap(NULL, _size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, _fd, 0); + + auto_map map( + fd, + _size, + PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED + ); + + if (map == MAP_FAILED) throw Exception(__METHOD__ ": Unable to map file.", errno); + + _fd = fd.release(); + _map = map.release(); +} + +MappedFile::~MappedFile() +{ + if (_map != MAP_FAILED) ::munmap(_map, _size); + if (_fd >= 0) ::close(_fd); +} + +void MappedFile::init(int f, bool readOnly) +{ + #undef __METHOD__ + #define __METHOD__ "MappedFile::init" + + auto_fd fd(f); + + _offset = 0; + _blocks = 0; + _size = 0; + _readOnly = readOnly; + _dosOrder = false; + + _size = ::lseek(_fd, 0, SEEK_END); + + if (_size < 0) + throw Exception(__METHOD__ ": Unable to determine file size.", errno); + +/* + _map = ::mmap(NULL, _size, readOnly ? PROT_READ : PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED, fd, 0); +*/ + auto_map map( + fd, + _size, + readOnly ? PROT_READ : PROT_READ | PROT_WRITE, + readOnly ? MAP_FILE : MAP_FILE | MAP_SHARED + ); + + if (map == MAP_FAILED) throw Exception(__METHOD__ ": Unable to map file.", errno); + + _fd = fd.release(); + _map = map.release(); +} + + +const unsigned MappedFile::DOSMap[] = { + 0x00, 0x0e, 0x0d, 0x0c, + 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x0f +}; + + +void MappedFile::readBlock(unsigned block, void *bp) +{ + #undef __METHOD__ + #define __METHOD__ "MappedFile::readBlock" + + + if (block >= _blocks) throw Exception(__METHOD__ ": Invalid block number."); + if (bp == 0) throw Exception(__METHOD__ ": Invalid address."); + + + if (_dosOrder) + { + unsigned track = (block & ~0x07) << 9; + unsigned sector = (block & 0x07) << 1; + + for (unsigned i = 0; i < 2; ++i) + { + size_t address = track | (DOSMap[sector+i] << 8); + + std::memcpy(bp, (uint8_t *)_map + _offset + address, 256); + + bp = (uint8_t *)bp + 256; + } + + } + else + { + size_t address = block * 512; + std::memcpy(bp, (uint8_t *)_map + _offset + address, 512); + } +} + +void MappedFile::writeBlock(unsigned block, const void *bp) +{ + #undef __METHOD__ + #define __METHOD__ "MappedFile::writeBlock" + + if (block > _blocks) throw Exception(__METHOD__ ": Invalid block number."); + + if ( (_readOnly) || (_map == MAP_FAILED)) + throw Exception(__METHOD__ ": File is readonly."); + + if (_dosOrder) + { + unsigned track = (block & ~0x07) << 9; + unsigned sector = (block & 0x07) << 1; + + for (unsigned i = 0; i < 2; ++i) + { + size_t address = track | (DOSMap[sector+i] << 8); + + std::memcpy((uint8_t *)_map + _offset + address, bp, 256); + bp = (uint8_t *)bp + 256; + } + } + else + { + size_t address = block * 512; + std::memcpy((uint8_t *)_map + _offset + address , bp, 512); + } +} + +void MappedFile::sync() +{ + #undef __METHOD__ + #define __METHOD__ "MappedFile::sync" + + if ( (_readOnly) || (_map == MAP_FAILED)) + return; + + if (::msync(_map, _size, MS_SYNC) < 0) + throw Exception(__METHOD__ ": msync error.", errno); +} + +void MappedFile::reset() +{ + _offset = 0; + _blocks = 0; + _dosOrder = false; +} + +/* +uint8_t MappedFile::read8(size_t location) const +{ + // check for size? + uint8_t *map = (uint8_t *)_map; + + return map[location]; +} +*/ + +uint16_t MappedFile::read16(size_t location, int byteOrder) const +{ + // check for size? + uint8_t *map = (uint8_t *)_map; + + switch(byteOrder) + { + case LittleEndian: + return (map[location + 1] << 8) + | (map[location]); + case BigEndian: + return (map[location] << 8) + | (map[location+1]); + default: + return 0; + } +} + +uint32_t MappedFile::read32(size_t location, int byteOrder) const +{ + // check for size? + uint8_t *map = (uint8_t *)_map; + + switch(byteOrder) + { + case LittleEndian: + return (map[location+3] << 24) + | (map[location+2] << 16) + | (map[location+1] << 8) + | (map[location]) + ; + case BigEndian: + return (map[location] << 24) + | (map[location+1] << 16) + | (map[location+2] << 8) + | (map[location+3]) + ; + + default: + return 0; + } +} + + +/* +void MappedFile::write8(size_t location, uint8_t data) +{ + uint8_t *map = (uint8_t *)_map; + + map[location] = data; +} +*/ + +void MappedFile::write16(size_t location, uint16_t data, int byteOrder) +{ + uint8_t *map = (uint8_t *)_map; + + switch(byteOrder) + { + case LittleEndian: + map[location] = data & 0xff; + map[location+1] = (data >> 8) & 0xff; + break; + case BigEndian: + map[location] = (data >> 8) & 0xff; + map[location+1] = data & 0xff; + break; + } +} + +void MappedFile::write32(size_t location, uint32_t data, int byteOrder) +{ + uint8_t *map = (uint8_t *)_map; + + switch(byteOrder) + { + case LittleEndian: + map[location] = data & 0xff; + map[location+1] = (data >> 8) & 0xff; + map[location+2] = (data >> 16) & 0xff; + map[location+3] = (data >> 24) & 0xff; + break; + case BigEndian: + map[location] = (data >> 24) & 0xff; + map[location+1] = (data >> 16) & 0xff; + map[location+2] = (data >> 8) & 0xff; + map[location+3] = data & 0xff; + break; + } +} diff --git a/MappedFile.h b/MappedFile.h new file mode 100644 index 0000000..9414067 --- /dev/null +++ b/MappedFile.h @@ -0,0 +1,78 @@ +#ifndef __MAPPED_FILE__ +#define __MAPPED_FILE__ + + +#include +#include + +namespace ProFUSE { + + +enum { + LittleEndian = 0x3412, + BigEndian = 0x1234 +}; + +class MappedFile { +public: + MappedFile(const char *name, bool ReadOnly); + MappedFile(int fd, bool readOnly); + MappedFile(const char *name, size_t size); + + ~MappedFile(); + + void readBlock(unsigned block, void *bp); + void writeBlock(unsigned block, const void *bp); + + void sync(); + + void reset(); + + bool dosOrder() const { return _dosOrder; } + void setDosOrder(bool tf) { _dosOrder = tf; } + + unsigned offset() const { return _offset; } + void setOffset(unsigned o) { _offset = o; } + + unsigned blocks() const { return _blocks; } + void setBlocks(unsigned b) { _blocks = b; } + + bool readOnly() const { return _readOnly; } + size_t fileSize() const { return _size; } + void *fileData() const { return _map; } + + uint8_t read8(size_t location) const + { + return ((uint8_t *)_map)[location]; + } + uint16_t read16(size_t location, int byteOrder) const; + uint32_t read32(size_t location, int byteOrder) const; + + void write8(size_t location, uint8_t data) + { + ((uint8_t *)_map)[location] = data; + } + void write16(size_t location, uint16_t data, int byteOrder); + void write32(size_t location, uint32_t data, int byteOrder); + + +private: + MappedFile& operator=(const MappedFile& other); + + void init(int fd, bool readOnly); + + static const unsigned DOSMap[]; + + int _fd; + void *_map; + + size_t _size; + bool _readOnly; + + bool _dosOrder; + unsigned _offset; + unsigned _blocks; + +}; +} +#endif \ No newline at end of file diff --git a/UniversalDiskImage.cpp b/UniversalDiskImage.cpp new file mode 100644 index 0000000..688b93f --- /dev/null +++ b/UniversalDiskImage.cpp @@ -0,0 +1,110 @@ +#include "UniversalDiskImage.h" +#include "MappedFile.h" +#include "Buffer.h" + +using namespace ProFUSE; + +UniversalDiskImage::UniversalDiskImage(const char *name, bool readOnly) : + DiskImage(name, readOnly) +{ + Validate(file()); +} + +UniversalDiskImage::UniversalDiskImage(MappedFile *file) : + DiskImage(file) +{ +} + +UniversalDiskImage *UniversalDiskImage::Create(const char *name, size_t blocks) +{ + // 64-byte header. + MappedFile *file = new MappedFile(name, blocks * 512 + 64); + + Buffer header(64); + + + // magic + creator + header.pushBytes("2IMGPRFS", 8); + + // header size. + header.push16le(64); + + // version + header.push16le(1); + + //image format -- ProDOS order + header.push32le(1); + + // flags + header.push32le(0); + + // # blocks. s/b 0 unless prodos-order + header.push32le(blocks); + + // offset to disk data + header.push32le(64); + + // data length + header.push32le(512 * blocks); + + // comment offset, creator, reserved -- 0. + header.resize(64); + + std::memcpy(file->fileData(), header.buffer(), 64); + + + file->setOffset(64); + file->setBlocks(blocks); + return new UniversalDiskImage(file); +} + +UniversalDiskImage *UniversalDiskImage::Open(MappedFile *file) +{ + Validate(file); + return new UniversalDiskImage(file); +} + + +/* + * TODO -- support dos-order & nibblized + * TODO -- honor read-only flag. + * + */ +void UniversalDiskImage::Validate(MappedFile *file) +{ +#undef __METHOD__ +#define __METHOD__ "DavexDiskImage::Validate" + + uint8_t *data = (uint8_t *)file->fileData(); + size_t size = file->fileSize(); + bool ok = false; + unsigned blocks = 0; + unsigned offset = 0; + + do { + + if (size < 64) break; + + if (std::memcmp(data, "2IMG", 4)) break; + + // only prodos supported, for now... + if (file->read32(0x0c, LittleEndian) != 1) break; + + offset = file->read32(0x20, LittleEndian); + blocks = file->read32(0x14, LittleEndian); + + // file size == blocks * 512 + if (file->read32(0x1c, LittleEndian) != blocks * 512) break; + + if (offset + blocks * 512 > size) break; + + ok = true; + } while (false); + + if (!ok) + throw Exception(__METHOD__ ": Invalid file format."); + + file->reset(); + file->setOffset(offset); + file->setBlocks(blocks); +} \ No newline at end of file diff --git a/UniversalDiskImage.h b/UniversalDiskImage.h new file mode 100644 index 0000000..cfcd887 --- /dev/null +++ b/UniversalDiskImage.h @@ -0,0 +1,23 @@ +#ifndef __UNIVERSALDISKIMAGE_H__ +#define __UNIVERSALDISKIMAGE_H__ + + +#include "BlockDevice.h" + +namespace ProFUSE { + +class UniversalDiskImage : public DiskImage { +public: + UniversalDiskImage(const char *name, bool readOnly); + + static UniversalDiskImage *Create(const char *name, size_t blocks); + static UniversalDiskImage *Open(MappedFile *); + +private: + UniversalDiskImage(MappedFile *); + static void Validate(MappedFile *); +}; + +} + +#endif diff --git a/Volume.h b/Volume.h new file mode 100644 index 0000000..47c6973 --- /dev/null +++ b/Volume.h @@ -0,0 +1,92 @@ +#ifndef __VOLUME_H__ +#define __VOLUME_H__ + +#include +#include + +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_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 \ No newline at end of file diff --git a/auto.h b/auto.h new file mode 100644 index 0000000..73f6768 --- /dev/null +++ b/auto.h @@ -0,0 +1,72 @@ +#ifndef __AUTO_H__ +#define __AUTO_H__ + +template +class auto_array +{ +public: + auto_array() : _t(NULL) {} + auto_array(T *t) : _t(t) {} + ~auto_array() { if (_t) delete []_t; } + + + T* release() + { T *tmp = _t; _t = NULL; return tmp; } + + T* get() const { return _t; } + operator T*() const { return _t; } + T& operator[](int index) { return _t[index]; } + +private: + T *_t; +}; + +// ::close +#if defined(O_CREAT) +class auto_fd +{ +public: + auto_fd(int fd) : _fd(fd) { } + + ~auto_fd() + { if (_fd != -1) ::close(_fd); } + + int release() + { int tmp = _fd; _fd = -1; return tmp; } + + int get() const { return _fd; } + operator int() const { return _fd; } + +private: + int _fd; +}; +#endif + +// ::mmap, :munmap +#if defined(MAP_FAILED) +class auto_map +{ +public: + auto_map(int fd, size_t size, int prot, int flags) : + _size(size), + _map(::mmap(NULL, size, prot, flags, fd, 0)) + { } + + ~auto_map() + { if (_map != MAP_FAILED) ::munmap(_map, _size); } + + void *release() + { void *tmp = _map; _map = MAP_FAILED; return tmp; } + + void *get() const { return _map; } + operator void *() const { return _map; } + +private: + size_t _size; + void *_map; +}; +#endif + + +#endif + diff --git a/test.cpp b/test.cpp new file mode 100644 index 0000000..3a657f8 --- /dev/null +++ b/test.cpp @@ -0,0 +1,27 @@ +#include "BlockDevice.h" +#include "Exception.h" +#include "DavexDiskImage.h" +#include "UniversalDiskImage.h" +#include "DiskCopy42Image.h" + +#include + +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; +} From 23cf78b5ab32aecabed3b0e47def916da657d847 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 21 Nov 2009 01:46:19 +0000 Subject: [PATCH 003/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@69 aa027e90-d47c-11dd-86d7-074df07e0730 --- version2.txt | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 version2.txt diff --git a/version2.txt b/version2.txt new file mode 100644 index 0000000..6e948d2 --- /dev/null +++ b/version2.txt @@ -0,0 +1,32 @@ +Version 2 Goals + +Version 2 is a more or less complete rewrite with the following goals: + +- better code modularity (disk image code should be usable for dos, pascal, cpm, stand alone utlities, etc) + +- better c++ coding + + +- sdk (shrinkit) support +- nibblized disk image support +- raw device support + + +- write support. + +Other utilites: +- fsck - verify and fix image integrity +- newfs - create a new disk image + + +inodes: + +Unix (and fuse) expect every file to have an inode, a unique integer file identifier. ProDOS does not use inodes (or anything like them). + +v1 used the file entry address as an inode, reloading the file entry every time. + +Since file entries are stored in the parent directory, moving a file changes the address, so this won't work with write support. + +(A file may be moved or deleted while it's open without affecting open references to it.) + +To handle inodes, perhaps I should use the key pointer (which would require a hash to convert it back to the entry) or generate one on the fly and maintain it until necessary \ No newline at end of file From ebb502b1f5c931fc3651da733dd7424971fe9ace Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 21 Nov 2009 03:37:02 +0000 Subject: [PATCH 004/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@70 aa027e90-d47c-11dd-86d7-074df07e0730 --- RawDevice.cpp | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++ RawDevice.h | 40 ++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 RawDevice.cpp create mode 100644 RawDevice.h diff --git a/RawDevice.cpp b/RawDevice.cpp new file mode 100644 index 0000000..4c83ed3 --- /dev/null +++ b/RawDevice.cpp @@ -0,0 +1,174 @@ + +#include +#include +#include +#include +#include + + + +#ifdef __APPLE__ +#include +#endif + +#ifdef __LINUX__ +#include +#endif + +#ifdef __SUN__ +#include +#endif + + +#include "RawDevice.h" +#include "auto.h" +#include "Exception.h" + +using Namespace ProFUSE; + +#ifdef __SUN__ +void RawDevice::devSize(int fd) +{ +#undef __METHOD__ +#define __METHOD__ "RawDevice::devSize" + + struct dk_minfo minfo; + + if (::ioctl(fd, DKIOCGMEDIAINFO, &minfo) < 0) + throw Exception(__METHOD__ ": Unable to determine device size.", errno); + + _size = minfo.dki_lbsize * minfo.dki_capacity; + _blockSize = 512; // not really, but whatever. + _blocks = _size / 512; + +} +#endif + +#ifdef __APPLE__ +void RawDevice::devSize(int fd) +{ +#undef __METHOD__ +#define __METHOD__ "RawDevice::devSize" + + uint32_t blockSize; // 32 bit + uint64_t blockCount; // 64 bit + + if (::ioctl(fd, DKIOCGETBLOCKSIZE, &blockSize) < 0) + throw Exception(__METHOD__ ": Unable to determine block size.", errno); + + + if (::ioctl(fd, DKIOCGETBLOCKCOUNT, &blockCount) < 0) + throw Exception(__METHOD__ ": Unable to determine block count.", errno); + + _blockSize = blockSize; + _size = _blockSize * _blockCount; + _blocks = _size / 512; +} + +#endif + + +#ifdef __LINUX__ + +void RawDevice::devSize(int fd) +{ +#undef __METHOD__ +#define __METHOD__ "RawDevice::devSize" + + int blocks; + + if (::ioctl(fd, BLKGETSIZE, &blocks) < 0) + throw Exception(__METHOD__ ": Unable to determine device size.", errno); + + _size = 512 * blocks; + _blockSize = 512; // + _blocks = blocks; + +} + + +#endif + +RawDevice::RawDevice(const char *name, bool readOnly) : +{ + // open read-only, verify if device is readable, and then try to upgrade to read/write? + + auto_fd fd(::open(name, readOnly ? O_RDONLY : O_RDWR)); + + if (fd < 0) + throw Exception(__METHOD__ ": Unable to open device.", errno); + + _fd = -1; + + _readOnly = readOnly; + _size = 0; + _blocks = 0; + _blockSize = 0; + + + devSize(fd); + + _fd = fd.release(); +} + + +RawDevice::~RawDevice() +{ + if (_fd >= 0) ::close(_fd); +} + + +void RawDevice::read(unsigned block, void *bp) +{ +#undef __METHOD__ +#define __METHOD__ "RawDevice::read" + + if (block >= _blocks) throw Exception(__METHOD__ ": Invalid block number."); + if (bp == 0) throw Exception(__METHOD__ ": Invalid address."); + + // sun -- use pread + // apple - read full native block(s) ? + + size_t ok = ::pread(_fd, bp, 512, block * 512); + + // TODO -- EINTR? + if (ok != 512) + throw Exception(__METHOD__ : ": Error reading block.", + ok < 0 : errno, 0); + + +} +void RawDevice::write(unsigned block, const void *bp) +{ +#undef __METHOD__ +#define __METHOD__ "RawDevice::write" + + if (block > _blocks) throw Exception(__METHOD__ ": Invalid block number."); + + if (_readOnly) + throw Exception(__METHOD__ ": File is readonly."); + + + size_t ok = ::pwrite(_fd, bp, 512, block * 512); + + if (ok != 512) + throw Exception(__METHOD__ : ": Error writing block.", + ok < 0 : errno, 0); +} + + +bool RawDevice::readOnly() +{ + return _readOnly; +} + +void RawDevice::sync() +{ +#undef __METHOD__ +#define __METHOD__ "RawDevice::sync" + + if (_readOnly) return; + + if (::fsync(_fd) < 0) + throw Exception(__METHOD__ ": msync error.", errno); +} \ No newline at end of file diff --git a/RawDevice.h b/RawDevice.h new file mode 100644 index 0000000..b2f5bc7 --- /dev/null +++ b/RawDevice.h @@ -0,0 +1,40 @@ +#ifndef __RAWDEVICE_H__ +#define __RAWDEVICE_H__ + +#include + +#include "BlockDevice.h" + +namespace ProFUSE { + +// /dev/xxx + + +class RawDevice : BlockDevice { +public: + + RawDevice(const char *name, bool readOnly); + + virtual ~RawDevice(); + + virtual void read(unsigned block, void *bp); + virtual void write(unsigned block, const void *bp); + + virtual bool readOnly(); + virtual void sync(); + +private: + + void devSize(int fd); + + int _fd; + bool _readOnly; + + uint64_t _size; + unsigned _blocks; + + unsigned _blockSize; +} + + +#endif From 8090387723008d29d5abf59b8b5ed8bcddc1ed15 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 22 Nov 2009 21:56:32 +0000 Subject: [PATCH 005/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@94 aa027e90-d47c-11dd-86d7-074df07e0730 --- BlockDevice.cpp | 8 + BlockDevice.h | 2 + Buffer.h | 2 + DateTime.cpp | 144 ++++++++++++++++ DateTime.h | 96 +++++++++++ Directory.cpp | 425 ++++++++++++++++++++++++++++++++++++++++++------ Directory.h | 53 +++++- Endian.h | 219 +++++++++++++++++++++++++ 8 files changed, 889 insertions(+), 60 deletions(-) create mode 100644 DateTime.cpp create mode 100644 DateTime.h create mode 100644 Endian.h diff --git a/BlockDevice.cpp b/BlockDevice.cpp index feeae82..99a61f2 100644 --- a/BlockDevice.cpp +++ b/BlockDevice.cpp @@ -18,6 +18,14 @@ BlockDevice::~BlockDevice() { } +BlockDevice::zeroBlock(unsigned block) +{ + uint8_t bp[512]; + std::memset(bp, 0, 512); + + write(block, bp); +} + #pragma mark DiskImage diff --git a/BlockDevice.h b/BlockDevice.h index e024161..4a7ae92 100644 --- a/BlockDevice.h +++ b/BlockDevice.h @@ -19,6 +19,8 @@ public: virtual bool readOnly() = 0; virtual void sync() = 0; + + void zeroBlock(unsigned block); }; diff --git a/Buffer.h b/Buffer.h index 5a0ebf1..4436862 100644 --- a/Buffer.h +++ b/Buffer.h @@ -12,7 +12,9 @@ public: 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); } diff --git a/DateTime.cpp b/DateTime.cpp new file mode 100644 index 0000000..f406ee9 --- /dev/null +++ b/DateTime.cpp @@ -0,0 +1,144 @@ +#include "DateTime.h" + + +#include +#include +#include + +namespace ProDOS { + +/* + * date is a 16 bit value: + * + * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ + * | Year | Month | Day | + * +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ + * + * time is a 16 bit value: + * + * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ + * |0 0 0| Hour | |0 0| Minute | + * +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ + * + */ + + +/* + * ProDOS technote 28 + * + * The following definition allows the same range of years that the Apple IIgs + * Control Panel CDA currently does: + * + * o A seven-bit ProDOS year value is in the range 0 to 99 + * (100 through 127 are invalid) + * o Year values from 40 to 99 represent 1940 through 1999 + * o Year values from 0 to 39 represent 2000 through 2039 + */ + + +DateTime::DateTime() : + _yymmdd(0), _hhmm(0) +{ + init(std::time(NULL)); +} + +DateTime::DateTime(uint32_t dtm) : + _yymmdd((dtm >> 16) & 0xff), _hhmm(dtm & 0xff) +{ +} + +DateTime::DateTime(unsigned yymmdd, unsigned hhmm) : + _yymmdd(yymmdd), _hhmm(hhmm) +{ +} + +DateTime::DateTime(std::time_t time) : + _yymmdd(0), _hhmm(0) +{ + init(time); +} + + +DateTime::DateTime(unsigned year, unsigned month, unsigned day, + unsigned hour, unsigned minute) : + _yymmdd(0), _hhmm(0) +{ + init(year, month, day, hour, minute); +} + +void DateTime::init(std::time_t time) +{ + tm t; + ::localtime_r(&time, &t); + init(t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min); +} + +void DateTime::init(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned minute) +{ + + //printf("%d %d %d %d %d\n", year, month, day, hour, minute); + + // 1940 is the earliest year, so clamp to 1940-01-01 00:00 + if (year < 1940) + { + _yymmdd = (40 << 9) | (1 << 5) | 1; + _hhmm = 0; + return; + } + // 2039 is the latest year, so clamp to 2039-12-31 23:59 + if (year > 2039) + { + _yymmdd = (39 << 9) | (12 << 5) | 31; + _hhmm = (23 << 8) | 59; + return; + } + + if (year >= 2000) year -= 2000; + else year -= 1900; + + _hhmm = minute | (hour << 8); + + _yymmdd = day | (month << 5) | (year << 9); +} + +unsigned DateTime::year() const +{ + unsigned tmp = _yymmdd >> 9; + //if (tmp > 100) return 0; + + if (tmp <= 39) tmp += 100; + + return tmp + 1900; +} + +/* + * A positive or 0 value for tm_isdst causes mktime() to presume initially + * that Daylight Savings Time, respectively, is or is not in effect for + * the specified time. A negative value for tm_isdst causes mktime() to + * attempt to determine whether Daylight Saving Time is in effect for the + * specified time. + */ + +std::time_t DateTime::toUnix() const +{ + tm t; + + if (_yymmdd == 0) return 0; + + std::memset(&t, 0, sizeof(tm)); + + t.tm_min = minute(); + t.tm_hour = hour(); + t.tm_isdst = -1; + + t.tm_mday = day(); + t.tm_mon = month() - 1; + t.tm_year = year() - 1900; + + return std::mktime(&t); + // convert back via locatime & fudge for dst? +} + +} // namespace diff --git a/DateTime.h b/DateTime.h new file mode 100644 index 0000000..9f3aa78 --- /dev/null +++ b/DateTime.h @@ -0,0 +1,96 @@ +#ifndef __PRODOS_DATE_TIME__ +#define __PRODOS_DATE_TIME__ + +#include +#include + +namespace ProDOS { + +class DateTime +{ +public: + DateTime(); + DateTime(std::time_t); + DateTime(uint32_t); + DateTime(unsigned, unsigned); + + DateTime(unsigned year, unsigned month, unsigned day, + unsigned hour, unsigned minute); + + std::time_t toUnix() const; + + + operator std::time_t() const; + operator uint32_t() const; + + unsigned date() const; + unsigned time() const; + + unsigned minute() const; + unsigned hour() const; + unsigned day() const; + unsigned month() const; + unsigned year() const; + +private: + void init(std::time_t); + void init(unsigned, unsigned, unsigned, unsigned, unsigned); + + unsigned _yymmdd; + unsigned _hhmm; +}; + + +inline DateTime::operator std::time_t() const +{ + return toUnix(); +} + +inline DateTime::operator uint32_t() const +{ + return (_yymmdd << 16) | _hhmm; +} + +inline unsigned DateTime::date() const +{ + return _yymmdd; +} + +inline unsigned DateTime::time() const +{ + return _hhmm; +} + +inline unsigned DateTime::minute() const +{ + return _hhmm & 0x3f; +} + +inline unsigned DateTime::hour() const +{ + return (_hhmm >> 8) & 0x1f; +} + +inline unsigned DateTime::day() const +{ + return _yymmdd & 0x1f; +} + +inline unsigned DateTime::month() const +{ + return (_yymmdd >> 5) & 0x0f; +} + +/* +inline unsigned DateTime::year() const +{ + unsigned tmp = _yymmdd >> 9; + if (tmp <= 39) tmp += 100; + return tmp + 1900; +} +*/ + +} // namespace + +#endif + diff --git a/Directory.cpp b/Directory.cpp index 83d7058..da017fa 100644 --- a/Directory.cpp +++ b/Directory.cpp @@ -1,10 +1,16 @@ -#include "Directory" #include +#include + +#include "Directory" +#include "Buffer.h" +#include "Endian.h" #include "Exception.h" + using namespace ProFUSE; +using namespace LittleEndian; static bool isalpha(unsigned c) { @@ -21,29 +27,18 @@ static bool isalnumdot(unsigned c) } -static uint16_t read16(uint8_t *data, unsigned offset) +static bool islower(unsigned c) { - return data[offset + 0] - | (data[offset + 1] << 8) ; -} - -static uint32_t read24(uint8_t *data, unsigned offset) -{ - return data[offset + 0] - | (data[offset + 1] << 8) - | (data[offset + 2] << 16) ; + return c >= 'a' && c <= 'z'; } -static uint32_t read32(uint8_t *data, unsigned offset) -{ - return data[offset + 0] - | (data[offset + 1] << 8) - | (data[offset + 2] << 16) ; - | (data[offset + 3] << 24) ; -} - -unsigned ValidName(const char *name) +/* + * ProDOS names: + * 1-15 letters, digits, or '.' + * first character must be a letter. + */ +unsigned Entry::ValidName(const char *name) { unsigned length; @@ -61,48 +56,148 @@ unsigned ValidName(const char *name) return length; } -Directory::Directory(unsigned type, const char *name) +Entry::Entry(unsigned type, const char *name) +{ + _storageType = type; + _address = 0; + _volume = NULL; + + // 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; + _volume = NULL; + _caseFlag = 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] = _name[i] | 0x20; + } + } +} + +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] = c & ~0x20; // upper + if (islower(c)) + { + caseFlag |= (0x4000 >> i); + } + } + + _length = length; + _caseFlag = caseFlag; +} + + + + + + + +Directory::Directory(unsigned type, const char *name) : + Entry(type, name) { #undef __METHOD__ #define __METHOD__ "Directory::Directory" - _nameLength = ValidName(name); - if (!_length) - throw Exception(__METHOD__ ": Invalid name."); - - _storageType = type; - std::strncpy(_name, name, 16); - - _access = 0xc3; + _access = 0xe3; _entryLength = 0x27; _entriesPerBlock = 13; _fileCount = 0; - - _device = NULL; + _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" - const uint8_t *data = (const uint8_t *)bp; + // input is a block pointer. To simplify, + // create a new pointer past the 4-byte linked list part. + void *dp = 4 + (const uint8_t *)bp; - _storageType = data[0x00] >> 4; - _nameLength = data[0x00] & 0x0f; - std::memcpy(_name, data + 1, _nameLength); - _name[_nameLength] = 0; - _creation = DateTime(read16(data, 0x1c), read16(data, 0x1e)); + _creation = DateTime(Read16(dp, 0x18), Read16(dp, 0x1a)); - _access = data[0x22]; - _entryLength = data[0x23]; - _entriesPerBlock = data[0x24]; + _version = Read8(dp, 0x1c); + _minVersion = Read8(dp, 0x1d); - _fileCount = read16(data, 0x25); + _access = Read8(dp, 0x1e); + _entryLength = Read8(dp, 0x1f); + _entriesPerBlock = Read8(dp, 0x20); - // parse child file entries. + _fileCount = read16(dp, 0x21); + + // parse child file entries ... requires ability to read other blocks. } Directory::~Directory() @@ -114,20 +209,248 @@ Directory::setAccess(unsigned access) #undef __METHOD__ #define __METHOD__ "Directory::setAccess" - if ((access & 0xe3) != access) + if ((access & 0xe7) != access) throw Exception(__METHOD__ ": Illegal access."); _access = access; // todo -- mark dirty? update block? } -Directory::setName(const char *name) -{ - unsigned length = ValidName(name); - if (!length) - throw Exception(__METHOD__ ": Invalid name."); - _nameLength = length; - std::strncpy(_name, name, 16); - // todo -- update or mark dirty. +#pragma mark 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(new Bitmap(_totalBlocks)); + + + // 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(&out); + } + + buffer.rezize(512); + device->write(i, buffer.buffer()); + } + + // TODO -- create/write the volume entry.... + + // allocate blocks for the bitmap itself + unsigned bb = bitmap->bitmapBlocks(); + for (unsigned i = 0; i < bb; ++i) + bitmap->allocBlock(i); + + // now write the bitmap... + const uint8_t *bm = (const uint8_t *)bitmap->bitmap(); + for (unsigned i = 0; i < bb; ++i) + { + device->writeBlock(_bitmapPointer + i, 512 * i + bm); + } + + setDevice(device); + _bitmap = bitmap.release(); } + +VolumeDirectory::~VolumeDirectory() +{ +} + +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); +} + +#pragma mark SubDirectory + +SubDirectory::SubDirectory(unsigned type, const char *name) : + Directory(type, name) +{ + _parentPointer = 0; + _parentEntryNumber = 0; + _parentEntryLength = 0x27; +} + +SubDirectory::SubDirectory(const void *bp) : + Directory(bp) +{ + const void *dp = 4 + (const uint8_t *)bp; + + _parentPointer = Read16(dp, 0x23); + _parentEntryNumber = Read8(dp, 0x25); + _parentEntryLength = Read8(dp, 0x26); +} + +SubDirectory::~SubDirectory +{ +} + +void SubDirectory::write(Buffer *out) +{ + out->push8((VolumeHeader << 4 ) | (nameLength()); + out->pushBytes(namei(), 15); + + // reserved. 0x76 is stored in the first byte. + // no one knows why. + out->push8(0x76); + out->push8(0); + out->push8(0); + out->push8(0); + out->push8(0); + out->push8(0); + out->push8(0); + out->push8(0); + + // 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(_parentPointer); + out->push8(_parentEntryNumber); + out->push8(_parentEntryLength); +} + + + + +FileEntry::FileEntry(unsigned type, const char *name) : + Entry(type, name) +{ + _fileType = type == DirectoryFile ? 0x0f : 0x00; + _keyPointer = 0; + _blocksUsed = 0; + _eof = 0; + _access = 0xe3; + _auxType = 0; + _headerPointer = 0; +} + + +FileEntry::FileEntry(const void *vp) : + Entry(vp), + _creation(0,0), + _modification(0,0) +{ +#undef __METHOD__ +#define __METHOD__ "FileEntry::FileEntry" + + switch(storageType()) + { + case SeedlingFile: + case SaplingFile: + case TreeFile: + case PascalFile: + case ExtendedFile: + case DirectoryFile: + break; + default: + throw Exception(__METHOD__ ": Invalid storage type."); + } + + + _fileType = Read8(vp, 0x10); + _keyPointer = Read16(vp, 0x11); + _blocksUsed = Read16(vp, 0x13); + _eof = Read24(vp, 0x15); + _creation = DateTime(Read16(vp, 0x18), Read16(vp, 0x1a)); + _access = Read8(vp, 0x1e); + _auxType = Read16(vp, 0x1f); + _modification = DateTime(Read16(vp, 0x21), Read16(vp, 0x23)); + _headerPointer = Read16(vp, 0x25); + + +} + +FileEntry::~FileEntry() +{ +} + + +void FileEntry::write(Buffer *out) +{ + out->push8((VolumeHeader << 4 ) | (nameLength()); + out->pushBytes(namei(), 15); + + out->push8(_fileType); + out->push16le(_keyPointer); + out->push16le(_blocksUsed); + out-push24le(_eof); + + // creation + out->push16le(_creation.date()); + out->push16le(_creation.time()); + + // case bits + out->push16le(caseFlag()); + + out->push8(_access); + put->push16le(_auxType); + + // modification + out->push16le(_modification.date()); + out->push16le(_modification.time()); + + out->push16le(_headerPointer); +} \ No newline at end of file diff --git a/Directory.h b/Directory.h index 8fe229c..7b8be06 100644 --- a/Directory.h +++ b/Directory.h @@ -15,25 +15,44 @@ class FileEntry; class Volume; -enum { +enum Access { DestroyEnabled = 0x80, RenameEnabled = 0x40, BackupNeeded = 0x20, + Invisible = 0x04, WriteEnabled = 0x02, ReadEnabled = 0x01 }; +enum StorageType { + 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 caseFlags() const { return _caseFlags; } + + void setName(const char *name); @@ -43,6 +62,20 @@ public: protected: Entry(int storageType, const char *name); + Entry(const void *bp); + + + setStorageType(unsigned type) + { + _storageType = type; + } + + setAddress(unsigned address) + { + _address = address; + } + + Volume *volume() { return _volume; } private: @@ -51,11 +84,13 @@ private: unsigned _storageType; unsigned _nameLength; + char _namei[15+1]; // insensitive, ie, uppercase. char _name[15+1]; - + + unsigned _caseFlag; }; -class Directory public Entry { +class Directory : public Entry { public: virtual ~Directory(); @@ -68,24 +103,24 @@ public: 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(BlockDevice *, unsigned block); + Directory(const void *bp); std::vector _children; std::vector _entryBlocks; - - BlockDevice *_device; - private: DateTime _creation; - // version - // min version + unsigned _version + unsigned _minVersion unsigned _access; usnigned _entryLength; // always 0x27 unsigned _entriesPerBlock; //always 0x0d diff --git a/Endian.h b/Endian.h new file mode 100644 index 0000000..355ceac --- /dev/null +++ b/Endian.h @@ -0,0 +1,219 @@ +#ifndef __ENDIAN_H__ +#define __ENDIAN_H__ + +// utlities to read/write bytes. + +#include + +namespace LittleEndian { + + + uint8_t Read8(const void *vp) + { + const uint8_t *p = (const uint8_t *)vp; + return (p[0]); + } + + uint16_t Read16(const void *vp) + { + const uint8_t *p = (const uint8_t *)vp; + return p[0] | (p[1] << 8); + } + + uint32_t Read24(const void *vp) + { + const uint8_t *p = (const uint8_t *)vp; + return (p[0]) | (p[1] << 8) | (p[2] << 16); + } + + + uint32_t Read32(const void *vp) + { + const uint8_t *p = (const uint8_t *)vp; + return (p[0]) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); + } + + + uint8_t Read8(const void *vp, unsigned offset) + { + return Read8(offset + (const uint8_t *)vp); + } + + uint16_t Read16(const void *vp, unsigned offset) + { + return Read16(offset + (const uint8_t *)vp); + } + + uint32_t Read24(const void *vp, unsigned offset) + { + return Read24(offset + (const uint8_t *)vp); + } + + uint32_t Read32(const void *vp, unsigned offset) + { + return Read32(offset + (const uint8_t *)vp); + } + + + // write + void Write8(void *vp, uint8_t x) + { + uint8_t *p = (uint8_t *)vp; + p[0] = x; + } + + void Write16(void *vp, uint16_t x) + { + uint8_t *p = (uint8_t *)vp; + p[0] = (x) & 0xff; + p[1] = (x >> 8) & 0xff; + } + + void Write24(void *vp, uint32_t x) + { + uint8_t *p = (uint8_t *)vp; + p[0] = (x) & 0xff; + p[1] = (x >> 8) & 0xff; + p[2] = (x >> 16) & 0xff; + } + + void Write32(void *vp, uint32_t x) + { + uint8_t *p = (uint8_t *)vp; + p[0] = (x) & 0xff; + p[1] = (x >> 8) & 0xff; + p[2] = (x >> 16) & 0xff; + p[3] = (x >> 24) & 0xff; + } + + void Write8(void *vp, unsigned offset, uint8_t x) + { + Write8(offset + (uint8_t *)vp, x); + } + + void Write16(void *vp, unsigned offset, uint16_t x) + { + Write16(offset + (uint8_t *)vp, x); + } + + void Write24(void *vp, unsigned offset, uint32_t x) + { + Write24(offset + (uint8_t *)vp, x); + } + + void Write32(void *vp, unsigned offset, uint32_t x) + { + Write32(offset + (uint8_t *)vp, x); + } + +} + + +namespace BigEndian { + + + uint8_t Read8(const void *vp) + { + const uint8_t *p = (const uint8_t *)vp; + return p[0]; + } + + uint16_t Read16(const void *vp) + { + const uint8_t *p = (const uint8_t *)vp; + return (p[0] << 8) | (p[1]); + } + + uint32_t Read24(const void *vp) + { + const uint8_t *p = (const uint8_t *)vp; + return (p[0] << 16) | (p[1] << 8) | (p[2]); + } + + + uint32_t Read32(const void *vp) + { + const uint8_t *p = (const uint8_t *)vp; + return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); + } + + + uint8_t Read8(const void *vp, unsigned offset) + { + return Read8(offset + (const uint8_t *)vp); + } + + uint16_t Read16(const void *vp, unsigned offset) + { + return Read16(offset + (const uint8_t *)vp); + } + + uint32_t Read24(const void *vp, unsigned offset) + { + return Read24(offset + (const uint8_t *)vp); + } + + uint32_t Read32(const void *vp, unsigned offset) + { + return Read32(offset + (const uint8_t *)vp); + } + + + + // write + void Write8(void *vp, uint8_t x) + { + uint8_t *p = (uint8_t *)vp; + p[0] = x; + } + + void Write16(void *vp, uint16_t x) + { + uint8_t *p = (uint8_t *)vp; + p[0] = (x >> 8) & 0xff; + p[1] = (x) & 0xff; + } + + void Write24(void *vp, uint32_t x) + { + uint8_t *p = (uint8_t *)vp; + p[0] = (x >> 16) & 0xff; + p[1] = (x >> 8) & 0xff; + p[2] = (x) & 0xff; + } + + void Write32(void *vp, uint32_t x) + { + uint8_t *p = (uint8_t *)vp; + p[0] = (x >> 24) & 0xff; + p[1] = (x >> 16) & 0xff; + p[2] = (x >> 8) & 0xff; + p[3] = (x) & 0xff; + } + + void Write8(void *vp, unsigned offset, uint8_t x) + { + Write8(offset + (uint8_t *)vp, x); + } + + void Write16(void *vp, unsigned offset, uint16_t x) + { + Write16(offset + (uint8_t *)vp, x); + } + + void Write24(void *vp, unsigned offset, uint32_t x) + { + Write24(offset + (uint8_t *)vp, x); + } + + void Write32(void *vp, unsigned offset, uint32_t x) + { + Write32(offset + (uint8_t *)vp, x); + } + + +} + + + +#endif \ No newline at end of file From f8ddc09a70d4a867ab02b3ee8e9e1ffa8796a7c7 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 23 Nov 2009 03:19:38 +0000 Subject: [PATCH 006/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@97 aa027e90-d47c-11dd-86d7-074df07e0730 --- BlockDevice.h | 2 ++ Buffer.cpp | 16 ++++++++++++++++ Buffer.h | 4 ++++ Directory.h | 8 ++++++++ 4 files changed, 30 insertions(+) diff --git a/BlockDevice.h b/BlockDevice.h index 4a7ae92..b35d899 100644 --- a/BlockDevice.h +++ b/BlockDevice.h @@ -20,6 +20,8 @@ public: virtual bool readOnly() = 0; virtual void sync() = 0; + virtual unsigned blocks(); + void zeroBlock(unsigned block); }; diff --git a/Buffer.cpp b/Buffer.cpp index 9e855ad..563d9ef 100644 --- a/Buffer.cpp +++ b/Buffer.cpp @@ -15,6 +15,22 @@ void Buffer::push16le(uint16_t x) _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); diff --git a/Buffer.h b/Buffer.h index 4436862..8f98641 100644 --- a/Buffer.h +++ b/Buffer.h @@ -21,6 +21,10 @@ public: void push16be(uint16_t); void push16le(uint16_t); + + void push24be(uint32_t); + void push24le(uint32_t); + void push32be(uint32_t); void push32le(uint32_t); diff --git a/Directory.h b/Directory.h index 7b8be06..c546d68 100644 --- a/Directory.h +++ b/Directory.h @@ -25,6 +25,7 @@ enum Access { }; enum StorageType { + DeletedFile = 0x00, SeedlingFile = 0x01, SaplingFile = 0x02, TreeFile = 0x03, @@ -166,6 +167,13 @@ private: class FileEntry : public Entry { public: + unsigned fileType() const { return _fileType; } + unsigned auxType() const { return _auxType; } + unsigned blocksUsed() const { return _blocksUsed; } + unsigned eof() const { return _eof; } + + DateTime creation() const { return _creation; } + DateTime modification() const { return _modification; } private: unsigned _fileType; From 9f0b5f100415204676c78011bcd87795fba0f1a8 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 23 Nov 2009 22:36:05 +0000 Subject: [PATCH 007/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@98 aa027e90-d47c-11dd-86d7-074df07e0730 --- Directory.cpp | 20 +++++++++++++++++--- Directory.h | 27 ++++++++++++++++++++++++--- MappedFile.cpp | 17 +++++++++++++++-- UniversalDiskImage.cpp | 23 ++++++++++++++++++----- UniversalDiskImage.h | 4 ++++ auto.h | 25 ++++++++++++++++++++++--- 6 files changed, 100 insertions(+), 16 deletions(-) diff --git a/Directory.cpp b/Directory.cpp index da017fa..48c2af5 100644 --- a/Directory.cpp +++ b/Directory.cpp @@ -60,6 +60,7 @@ Entry::Entry(unsigned type, const char *name) { _storageType = type; _address = 0; + _index = 0; _volume = NULL; // everything else initialized in setName. @@ -74,6 +75,7 @@ Entry::Entry(const void *bp) uint8_t x; uint16_t xcase = 0; _address = 0; + _index = 0; _volume = NULL; _caseFlag = 0; std::memset(_name, 0, 16); @@ -318,12 +320,24 @@ void VolumeDirectory::write(Buffer *out) #pragma mark SubDirectory -SubDirectory::SubDirectory(unsigned type, const char *name) : - Directory(type, name) +SubDirectory::SubDirectory(FileEntry *e) : + Directory(DirectoryHeader, e->iname()) +{ + _creation = e->creation(); + setAccess(e->access()); + + _parentEntryPointer = e->block(); + _parentEntryNumber = e->index(); + _parentEntryLength = 0x27; + +} + +SubDirectory::SubDirectory(const char *name) : + Directory(DirectoryHeader, name) { _parentPointer = 0; _parentEntryNumber = 0; - _parentEntryLength = 0x27; + _parentEntryLength = 0x27; } SubDirectory::SubDirectory(const void *bp) : diff --git a/Directory.h b/Directory.h index c546d68..bf70cfe 100644 --- a/Directory.h +++ b/Directory.h @@ -61,6 +61,14 @@ public: // 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; } + protected: Entry(int storageType, const char *name); Entry(const void *bp); @@ -71,16 +79,26 @@ protected: _storageType = type; } + setAddress(unsigned address) { _address = address; } + + setIndex(unsigned index) + { + _index = index; + } + + Volume *volume() { return _volume; } private: - unsigned _address; // absolute address on disk. + unsigned _address; + unsigned _index; + Volume *_volume; unsigned _storageType; @@ -123,7 +141,7 @@ private: unsigned _version unsigned _minVersion unsigned _access; - usnigned _entryLength; // always 0x27 + unsigned _entryLength; // always 0x27 unsigned _entriesPerBlock; //always 0x0d unsigned _fileCount; @@ -156,7 +174,7 @@ private: class SubDirectory : public Directory { public: - + SubDirectory(FileEntry *); private: unsigned _parentPointer; unsigned _parentEntryNumber; @@ -172,6 +190,9 @@ public: 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; } diff --git a/MappedFile.cpp b/MappedFile.cpp index fa3b198..bbc6bd7 100644 --- a/MappedFile.cpp +++ b/MappedFile.cpp @@ -21,8 +21,21 @@ MappedFile::MappedFile(const char *name, bool readOnly) : #undef __METHOD__ #define __METHOD__ "MappedFile::MappedFile" - auto_fd fd(::open(name, readOnly ? O_RDONLY : O_RDWR)); + // if unable to open as read/write, open as read-only. + + auto_fd fd; + + if (!readOnly) + { + fd.reset(::open(name, O_RDWR)); + } + if (fd < 0) + { + fd.reset(::open(name, O_RDONLY)); + readOnly = true; + } + if (fd < 0) { throw Exception(__METHOD__ ": Unable to open file.", errno); @@ -38,7 +51,6 @@ MappedFile::MappedFile(int fd, bool readOnly) : init(fd, readOnly); } -// todo -- verify throw calls destructor. MappedFile::MappedFile(const char *name, size_t size) : _fd(-1), _map(MAP_FAILED) @@ -48,6 +60,7 @@ MappedFile::MappedFile(const char *name, size_t size) : _size = size; _readOnly = false; + auto_fd fd(::open(name, O_CREAT | O_TRUNC | O_RDWR, 0644)); if (fd < 0) diff --git a/UniversalDiskImage.cpp b/UniversalDiskImage.cpp index 688b93f..8b08773 100644 --- a/UniversalDiskImage.cpp +++ b/UniversalDiskImage.cpp @@ -1,18 +1,25 @@ #include "UniversalDiskImage.h" #include "MappedFile.h" #include "Buffer.h" +#inluce "Endian.h" using namespace ProFUSE; +using namespace LittleEndian; UniversalDiskImage::UniversalDiskImage(const char *name, bool readOnly) : DiskImage(name, readOnly) { Validate(file()); + const void *data = file()->fileData(); + + // flags. bit 31 = locked. + _flags = Read32(data, 0x10; } UniversalDiskImage::UniversalDiskImage(MappedFile *file) : DiskImage(file) { + _flags = 0; } UniversalDiskImage *UniversalDiskImage::Create(const char *name, size_t blocks) @@ -75,7 +82,7 @@ void UniversalDiskImage::Validate(MappedFile *file) #undef __METHOD__ #define __METHOD__ "DavexDiskImage::Validate" - uint8_t *data = (uint8_t *)file->fileData(); + const void *data = file->fileData(); size_t size = file->fileSize(); bool ok = false; unsigned blocks = 0; @@ -88,13 +95,13 @@ void UniversalDiskImage::Validate(MappedFile *file) if (std::memcmp(data, "2IMG", 4)) break; // only prodos supported, for now... - if (file->read32(0x0c, LittleEndian) != 1) break; + if (Read32(data, 0x0c) != 1) break; - offset = file->read32(0x20, LittleEndian); - blocks = file->read32(0x14, LittleEndian); + offset = Read32(data, 0x20); + blocks = Read32(data, 0x14); // file size == blocks * 512 - if (file->read32(0x1c, LittleEndian) != blocks * 512) break; + if (Read32(data, 0x1c) != blocks * 512) break; if (offset + blocks * 512 > size) break; @@ -107,4 +114,10 @@ void UniversalDiskImage::Validate(MappedFile *file) file->reset(); file->setOffset(offset); file->setBlocks(blocks); +} + + +bool UniversalDiskImage::readOnly() +{ + return (_flags & 0x8000000) || DiskImage::readOnly(); } \ No newline at end of file diff --git a/UniversalDiskImage.h b/UniversalDiskImage.h index cfcd887..e26e18e 100644 --- a/UniversalDiskImage.h +++ b/UniversalDiskImage.h @@ -13,9 +13,13 @@ public: static UniversalDiskImage *Create(const char *name, size_t blocks); static UniversalDiskImage *Open(MappedFile *); + virtual bool readOnly(); + private: UniversalDiskImage(MappedFile *); static void Validate(MappedFile *); + + uint32_t flags; }; } diff --git a/auto.h b/auto.h index 73f6768..3e3d16c 100644 --- a/auto.h +++ b/auto.h @@ -26,18 +26,37 @@ private: class auto_fd { public: - auto_fd(int fd) : _fd(fd) { } + auto_fd(int fd = -1) : _fd(fd) { } - ~auto_fd() - { if (_fd != -1) ::close(_fd); } + ~auto_fd() { close(); } int release() { int tmp = _fd; _fd = -1; return tmp; } int get() const { return _fd; } operator int() const { return _fd; } + + void reset(int fd) + { + if (fd != _fd) + { + close(); + _fd = fd; + } + } private: + auto_fd& operator=(const auto_fd&); + + void close() + { + if (_fd >= 0) + { + ::close(_fd); + fd = -1; + } + } + int _fd; }; #endif From 2209b44225062a5ab85d80ad07353f49a0149aec Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 24 Nov 2009 03:56:19 +0000 Subject: [PATCH 008/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@99 aa027e90-d47c-11dd-86d7-074df07e0730 --- DavexDiskImage.cpp | 10 +++-- Directory.h | 2 +- DiskCopy42Image.cpp | 21 ++++++---- MappedFile.cpp | 99 --------------------------------------------- 4 files changed, 20 insertions(+), 112 deletions(-) diff --git a/DavexDiskImage.cpp b/DavexDiskImage.cpp index ac8818b..f93e003 100644 --- a/DavexDiskImage.cpp +++ b/DavexDiskImage.cpp @@ -1,6 +1,7 @@ #include "DavexDiskImage.h" #include "MappedFile.h" #include "Buffer.h" +#include "Endian.h" #include #include @@ -10,6 +11,7 @@ #include using namespace ProFUSE; +using namespace LittleEndian; /* http://www.umich.edu/~archive/apple2/technotes/ftn/FTN.E0.8004 @@ -41,7 +43,7 @@ void DavexDiskImage::Validate(MappedFile *f) #define __METHOD__ "DavexDiskImage::Validate" size_t size = f->fileSize(); - void * data = f->fileData(); + const void * data = f->fileData(); bool ok = false; unsigned blocks = (size / 512) - 1; @@ -54,15 +56,15 @@ void DavexDiskImage::Validate(MappedFile *f) break; // file format. - if (f->read8(16) != 0) + if (Read8(data, 0x10) != 0) break; // total blocks - if (f->read32(33, LittleEndian) != blocks) + if (Read32(data, 33) != blocks) break; // file number -- must be 1 - if (f->read8(64) != 1) + if (Read8(data, 64) != 1) break; ok = true; diff --git a/Directory.h b/Directory.h index bf70cfe..1b317f8 100644 --- a/Directory.h +++ b/Directory.h @@ -87,7 +87,7 @@ protected: setIndex(unsigned index) { - _index = index; + _index = index;w } diff --git a/DiskCopy42Image.cpp b/DiskCopy42Image.cpp index 10f1d94..343b660 100644 --- a/DiskCopy42Image.cpp +++ b/DiskCopy42Image.cpp @@ -1,10 +1,12 @@ #include "DiskCopy42Image.h" #include "MappedFile.h" #include "Buffer.h" +#include "Endian.h" -#include +#include using namespace ProFUSE; +using namespace BigEndian; DiskCopy42Image::DiskCopy42Image(MappedFile *f) : DiskImage(f), @@ -24,12 +26,14 @@ DiskCopy42Image::~DiskCopy42Image() if (_changed) { MappedFile *f = file(); + void *data = file->fileData(); + if (f) { - uint32_t cs = Checksum(f->offset() + (uint8_t *)f->fileData(), + uint32_t cs = Checksum(f->offset() + (uint8_t *)data, f->blocks() * 512); - f->write32(72, cs, BigEndian); + Write32(data, 72, cs); f->sync(); } // TODO -- checksum @@ -137,6 +141,7 @@ void DiskCopy42Image::Validate(MappedFile *file) { size_t bytes = 0; size_t size = file->fileSize(); + const void *data = file->fileData(); bool ok = false; uint32_t checksum; @@ -144,26 +149,26 @@ void DiskCopy42Image::Validate(MappedFile *file) if (size < 84) break; // name must be < 64 - if (file->read8(0) > 63) break; + if (Read8(data, 0) > 63) break; - if (file->read32(82, BigEndian) != 0x100) + if (Read32(data, 82) != 0x100) break; // bytes, not blocks. - bytes = file->read32(64, BigEndian); + bytes = Read32(data, 64); if (bytes % 512) break; if (size < 84 + bytes) break; // todo -- checksum. - checksum = file->read32(72, BigEndian); + checksum = Read32(data, 72); ok = true; } while (false); - uint32_t cs = Checksum(64 + (uint8_t *)file->fileData(), bytes); + uint32_t cs = Checksum(64 + (uint8_t *)data, bytes); if (cs != checksum) { diff --git a/MappedFile.cpp b/MappedFile.cpp index bbc6bd7..c54c5ec 100644 --- a/MappedFile.cpp +++ b/MappedFile.cpp @@ -218,103 +218,4 @@ void MappedFile::reset() _dosOrder = false; } -/* -uint8_t MappedFile::read8(size_t location) const -{ - // check for size? - uint8_t *map = (uint8_t *)_map; - - return map[location]; -} -*/ -uint16_t MappedFile::read16(size_t location, int byteOrder) const -{ - // check for size? - uint8_t *map = (uint8_t *)_map; - - switch(byteOrder) - { - case LittleEndian: - return (map[location + 1] << 8) - | (map[location]); - case BigEndian: - return (map[location] << 8) - | (map[location+1]); - default: - return 0; - } -} - -uint32_t MappedFile::read32(size_t location, int byteOrder) const -{ - // check for size? - uint8_t *map = (uint8_t *)_map; - - switch(byteOrder) - { - case LittleEndian: - return (map[location+3] << 24) - | (map[location+2] << 16) - | (map[location+1] << 8) - | (map[location]) - ; - case BigEndian: - return (map[location] << 24) - | (map[location+1] << 16) - | (map[location+2] << 8) - | (map[location+3]) - ; - - default: - return 0; - } -} - - -/* -void MappedFile::write8(size_t location, uint8_t data) -{ - uint8_t *map = (uint8_t *)_map; - - map[location] = data; -} -*/ - -void MappedFile::write16(size_t location, uint16_t data, int byteOrder) -{ - uint8_t *map = (uint8_t *)_map; - - switch(byteOrder) - { - case LittleEndian: - map[location] = data & 0xff; - map[location+1] = (data >> 8) & 0xff; - break; - case BigEndian: - map[location] = (data >> 8) & 0xff; - map[location+1] = data & 0xff; - break; - } -} - -void MappedFile::write32(size_t location, uint32_t data, int byteOrder) -{ - uint8_t *map = (uint8_t *)_map; - - switch(byteOrder) - { - case LittleEndian: - map[location] = data & 0xff; - map[location+1] = (data >> 8) & 0xff; - map[location+2] = (data >> 16) & 0xff; - map[location+3] = (data >> 24) & 0xff; - break; - case BigEndian: - map[location] = (data >> 24) & 0xff; - map[location+1] = (data >> 16) & 0xff; - map[location+2] = (data >> 8) & 0xff; - map[location+3] = data & 0xff; - break; - } -} From 2462938c3a4ded082871d860422773ec272b8bae Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 24 Nov 2009 04:04:42 +0000 Subject: [PATCH 009/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@100 aa027e90-d47c-11dd-86d7-074df07e0730 --- MappedFile.h | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/MappedFile.h b/MappedFile.h index 9414067..009c8bc 100644 --- a/MappedFile.h +++ b/MappedFile.h @@ -8,10 +8,6 @@ namespace ProFUSE { -enum { - LittleEndian = 0x3412, - BigEndian = 0x1234 -}; class MappedFile { public: @@ -41,20 +37,7 @@ public: size_t fileSize() const { return _size; } void *fileData() const { return _map; } - uint8_t read8(size_t location) const - { - return ((uint8_t *)_map)[location]; - } - uint16_t read16(size_t location, int byteOrder) const; - uint32_t read32(size_t location, int byteOrder) const; - - void write8(size_t location, uint8_t data) - { - ((uint8_t *)_map)[location] = data; - } - void write16(size_t location, uint16_t data, int byteOrder); - void write32(size_t location, uint32_t data, int byteOrder); - + private: MappedFile& operator=(const MappedFile& other); From 8212b0208837b7e5b81ea359ae1266a1b2598369 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 24 Nov 2009 04:36:48 +0000 Subject: [PATCH 010/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@101 aa027e90-d47c-11dd-86d7-074df07e0730 --- BlockDevice.cpp | 14 ++++++++++---- BlockDevice.h | 4 ++-- DiskCopy42Image.cpp | 2 +- RawDevice.cpp | 6 ++++-- RawDevice.h | 2 +- UniversalDiskImage.cpp | 4 ++-- UniversalDiskImage.h | 3 ++- 7 files changed, 22 insertions(+), 13 deletions(-) diff --git a/BlockDevice.cpp b/BlockDevice.cpp index 99a61f2..be371cb 100644 --- a/BlockDevice.cpp +++ b/BlockDevice.cpp @@ -18,7 +18,7 @@ BlockDevice::~BlockDevice() { } -BlockDevice::zeroBlock(unsigned block) +void BlockDevice::zeroBlock(unsigned block) { uint8_t bp[512]; std::memset(bp, 0, 512); @@ -55,9 +55,15 @@ bool DiskImage::readOnly() throw Exception(__METHOD__ ": File not set."); } - - - +unsigned DiskImage::blocks() +{ + #undef __METHOD__ + #define __METHOD__ "DiskImage::blocks" + + if (_file) return _file->blocks(); + + throw Exception(__METHOD__ ": File not set."); +} void DiskImage::read(unsigned block, void *bp) { diff --git a/BlockDevice.h b/BlockDevice.h index b35d899..8b8d23e 100644 --- a/BlockDevice.h +++ b/BlockDevice.h @@ -20,7 +20,7 @@ public: virtual bool readOnly() = 0; virtual void sync() = 0; - virtual unsigned blocks(); + virtual unsigned blocks() = 0; void zeroBlock(unsigned block); }; @@ -37,7 +37,7 @@ public: virtual void sync(); virtual bool readOnly(); - + virtual unsigned blocks(); protected: diff --git a/DiskCopy42Image.cpp b/DiskCopy42Image.cpp index 343b660..7f1169c 100644 --- a/DiskCopy42Image.cpp +++ b/DiskCopy42Image.cpp @@ -26,7 +26,7 @@ DiskCopy42Image::~DiskCopy42Image() if (_changed) { MappedFile *f = file(); - void *data = file->fileData(); + void *data = f->fileData(); if (f) { diff --git a/RawDevice.cpp b/RawDevice.cpp index 4c83ed3..092a4ff 100644 --- a/RawDevice.cpp +++ b/RawDevice.cpp @@ -1,5 +1,5 @@ -#include +#include #include #include #include @@ -89,6 +89,8 @@ void RawDevice::devSize(int fd) #endif +// TODO -- FreeBSD/NetBSD/OpenBSD + RawDevice::RawDevice(const char *name, bool readOnly) : { // open read-only, verify if device is readable, and then try to upgrade to read/write? @@ -133,7 +135,7 @@ void RawDevice::read(unsigned block, void *bp) // TODO -- EINTR? if (ok != 512) - throw Exception(__METHOD__ : ": Error reading block.", + throw Exception(__METHOD__ ": Error reading block.", ok < 0 : errno, 0); diff --git a/RawDevice.h b/RawDevice.h index b2f5bc7..521d21f 100644 --- a/RawDevice.h +++ b/RawDevice.h @@ -34,7 +34,7 @@ private: unsigned _blocks; unsigned _blockSize; -} +}; #endif diff --git a/UniversalDiskImage.cpp b/UniversalDiskImage.cpp index 8b08773..87c6055 100644 --- a/UniversalDiskImage.cpp +++ b/UniversalDiskImage.cpp @@ -1,7 +1,7 @@ #include "UniversalDiskImage.h" #include "MappedFile.h" #include "Buffer.h" -#inluce "Endian.h" +#include "Endian.h" using namespace ProFUSE; using namespace LittleEndian; @@ -13,7 +13,7 @@ UniversalDiskImage::UniversalDiskImage(const char *name, bool readOnly) : const void *data = file()->fileData(); // flags. bit 31 = locked. - _flags = Read32(data, 0x10; + _flags = Read32(data, 0x10); } UniversalDiskImage::UniversalDiskImage(MappedFile *file) : diff --git a/UniversalDiskImage.h b/UniversalDiskImage.h index e26e18e..1bcac1b 100644 --- a/UniversalDiskImage.h +++ b/UniversalDiskImage.h @@ -3,6 +3,7 @@ #include "BlockDevice.h" +#include namespace ProFUSE { @@ -19,7 +20,7 @@ private: UniversalDiskImage(MappedFile *); static void Validate(MappedFile *); - uint32_t flags; + uint32_t _flags; }; } From 5d10a7cbb6657666977c50a665647c518e886141 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 24 Nov 2009 04:46:29 +0000 Subject: [PATCH 011/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@102 aa027e90-d47c-11dd-86d7-074df07e0730 --- RawDevice.cpp | 30 +++++++++++++++++++++--------- RawDevice.h | 1 + auto.h | 2 +- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/RawDevice.cpp b/RawDevice.cpp index 092a4ff..2635143 100644 --- a/RawDevice.cpp +++ b/RawDevice.cpp @@ -5,6 +5,7 @@ #include #include +#include #ifdef __APPLE__ @@ -24,7 +25,7 @@ #include "auto.h" #include "Exception.h" -using Namespace ProFUSE; +using namespace ProFUSE; #ifdef __SUN__ void RawDevice::devSize(int fd) @@ -61,7 +62,7 @@ void RawDevice::devSize(int fd) throw Exception(__METHOD__ ": Unable to determine block count.", errno); _blockSize = blockSize; - _size = _blockSize * _blockCount; + _size = _blockSize * blockCount; _blocks = _size / 512; } @@ -91,12 +92,23 @@ void RawDevice::devSize(int fd) // TODO -- FreeBSD/NetBSD/OpenBSD -RawDevice::RawDevice(const char *name, bool readOnly) : +RawDevice::RawDevice(const char *name, bool readOnly) { +#undef __METHOD__ +#define __METHOD__ "RawDevice::RawDevice" + + // open read-only, verify if device is readable, and then try to upgrade to read/write? + + auto_fd fd; - auto_fd fd(::open(name, readOnly ? O_RDONLY : O_RDWR)); - + if (!readOnly) fd.reset(::open(name, O_RDWR)); + if (fd < 0) + { + readOnly = false; + fd.reset(::open(name, O_RDONLY)); + } + if (fd < 0) throw Exception(__METHOD__ ": Unable to open device.", errno); @@ -136,7 +148,7 @@ void RawDevice::read(unsigned block, void *bp) // TODO -- EINTR? if (ok != 512) throw Exception(__METHOD__ ": Error reading block.", - ok < 0 : errno, 0); + ok < 0 ? errno : 0); } @@ -154,8 +166,8 @@ void RawDevice::write(unsigned block, const void *bp) size_t ok = ::pwrite(_fd, bp, 512, block * 512); if (ok != 512) - throw Exception(__METHOD__ : ": Error writing block.", - ok < 0 : errno, 0); + throw Exception(__METHOD__ ": Error writing block.", + ok < 0 ? errno : 0); } @@ -172,5 +184,5 @@ void RawDevice::sync() if (_readOnly) return; if (::fsync(_fd) < 0) - throw Exception(__METHOD__ ": msync error.", errno); + throw Exception(__METHOD__ ": fsync error.", errno); } \ No newline at end of file diff --git a/RawDevice.h b/RawDevice.h index 521d21f..b2bafe9 100644 --- a/RawDevice.h +++ b/RawDevice.h @@ -36,5 +36,6 @@ private: unsigned _blockSize; }; +} #endif diff --git a/auto.h b/auto.h index 3e3d16c..b9dd6fd 100644 --- a/auto.h +++ b/auto.h @@ -53,7 +53,7 @@ private: if (_fd >= 0) { ::close(_fd); - fd = -1; + _fd = -1; } } From cdd55ee726c944cd3fb7c73bd1deaccd70baddc8 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 24 Nov 2009 04:57:41 +0000 Subject: [PATCH 012/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@103 aa027e90-d47c-11dd-86d7-074df07e0730 --- Bitmap.cpp | 25 ++++++++++++++----------- Bitmap.h | 8 ++++++-- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/Bitmap.cpp b/Bitmap.cpp index 3605d9e..1e3d246 100644 --- a/Bitmap.cpp +++ b/Bitmap.cpp @@ -1,9 +1,12 @@ -#include "Bitmap.h" #include +#include "Bitmap.h" +#include "BlockDevice.h" #include "auto.h" +using namespace ProFUSE; + // returns # of 1-bits set (0-8) inline static unsigned popCount(uint8_t x) { @@ -33,7 +36,7 @@ Bitmap::Bitmap(unsigned blocks) unsigned bitmapSize = _bitmapBlocks * 512; unsigned blockSize = blocks / 8; - auto_array bitmap(new uint8_t[bitmapSize]); + auto_array bitmap(new uint8_t[bitmapSize]); // mark overflow in use, everything else free. @@ -61,11 +64,11 @@ Bitmap::Bitmap(BlockDevice *device, unsigned keyPointer, unsigned blocks) unsigned bitmapSize = _bitmapBlocks * 512; unsigned blockSize = blocks / 8; - auto_array bitmap(new uint8_t[bitmapSize]); + auto_array bitmap(new uint8_t[bitmapSize]); for (unsigned i = 0; i < blockSize; ++i) { - device->readBlock(keyPointer + i, bitmap + 512 * i); + device->read(keyPointer + i, bitmap + 512 * i); } // make sure all trailing bits are marked in use. @@ -83,11 +86,11 @@ Bitmap::Bitmap(BlockDevice *device, unsigned keyPointer, unsigned blocks) _freeBlocks += popCount(bitmap[i]); } - if (_freeblocks) + if (_freeBlocks) { for (unsigned i = 0; i < (blocks + 7) / 8; ++i) { - if (tmp[i]) + if (bitmap[i]) { _freeIndex = i; break; @@ -149,11 +152,11 @@ int Bitmap::allocBlock() { if (!_freeBlocks) return -1; - unsigned firstIndex = _firstIndex; + unsigned freeIndex = _freeIndex; unsigned maxIndex = (_blocks + 7) / 8; - for (unsigned index = _firstIndex; index < maxIndex; ++index) + for (unsigned index = _freeIndex; index < maxIndex; ++index) { uint8_t tmp = _bitmap[index]; if (!tmp) continue; @@ -163,7 +166,7 @@ int Bitmap::allocBlock() { if (tmp & mask) { - _firstIndex = index; + _freeIndex = index; _bitmap[index] = tmp & ~mask; --_freeBlocks; return index * 8 + offset; @@ -172,7 +175,7 @@ int Bitmap::allocBlock() } } - for (unsigned index = 0; index < _firstIndex; ++index) + for (unsigned index = 0; index < freeIndex; ++index) { uint8_t tmp = _bitmap[index]; if (!tmp) continue; @@ -182,7 +185,7 @@ int Bitmap::allocBlock() { if (tmp & mask) { - _firstIndex = index; + _freeIndex = index; _bitmap[index] = tmp & ~mask; --_freeBlocks; return index * 8 + offset; diff --git a/Bitmap.h b/Bitmap.h index b4dcf40..243db9d 100644 --- a/Bitmap.h +++ b/Bitmap.h @@ -2,15 +2,19 @@ #define __BITMAP_H__ #include -class BlockDevice; + + namespace ProFUSE { +class BlockDevice; + + class Bitmap { public: Bitmap(unsigned blocks); - Bitmap(BlockDevice *device, int keyPointer, int blocks); + Bitmap(BlockDevice *device, unsigned keyPointer, unsigned blocks); //todo -- constructor by loading fro, block device... ~Bitmap(); From 1ba3d83ec7680c4f0d62ff64b33358d85c1a9a3d Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 25 Nov 2009 02:26:00 +0000 Subject: [PATCH 013/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@104 aa027e90-d47c-11dd-86d7-074df07e0730 --- BlockDevice.cpp | 4 +- DavexDiskImage.cpp | 2 +- MappedFile.cpp | 123 ++++++++++++++++++++++++++------------------- MappedFile.h | 14 ++++-- 4 files changed, 85 insertions(+), 58 deletions(-) diff --git a/BlockDevice.cpp b/BlockDevice.cpp index be371cb..e75bef8 100644 --- a/BlockDevice.cpp +++ b/BlockDevice.cpp @@ -153,7 +153,7 @@ DOSOrderDiskImage::DOSOrderDiskImage(MappedFile *file) : DOSOrderDiskImage *DOSOrderDiskImage::Create(const char *name, size_t blocks) { MappedFile *file = new MappedFile(name, blocks * 512); - file->setDosOrder(true); + file->setEncoding(MappedFile::DOSOrder); return new DOSOrderDiskImage(file); } @@ -176,6 +176,6 @@ void DOSOrderDiskImage::Validate(MappedFile *f) throw Exception(__METHOD__ ": Invalid file format."); f->reset(); - f->setDosOrder(true); + f->setEncoding(MappedFile::DOSOrder); f->setBlocks(size / 512); } diff --git a/DavexDiskImage.cpp b/DavexDiskImage.cpp index f93e003..e16ed13 100644 --- a/DavexDiskImage.cpp +++ b/DavexDiskImage.cpp @@ -74,9 +74,9 @@ void DavexDiskImage::Validate(MappedFile *f) if (!ok) throw Exception(__METHOD__ ": Invalid file format."); + f->reset(); f->setBlocks(blocks); f->setOffset(512); - f->setDosOrder(false); } DavexDiskImage *DavexDiskImage::Open(MappedFile *file) diff --git a/MappedFile.cpp b/MappedFile.cpp index c54c5ec..b8b055d 100644 --- a/MappedFile.cpp +++ b/MappedFile.cpp @@ -14,9 +14,7 @@ using namespace ProFUSE; -MappedFile::MappedFile(const char *name, bool readOnly) : - _fd(-1), - _map(MAP_FAILED) +MappedFile::MappedFile(const char *name, bool readOnly) { #undef __METHOD__ #define __METHOD__ "MappedFile::MappedFile" @@ -40,26 +38,27 @@ MappedFile::MappedFile(const char *name, bool readOnly) : { throw Exception(__METHOD__ ": Unable to open file.", errno); } - // - init(fd.release(), readOnly); + // init may throw; auto_fd guarantees the file will be closed if that happens. + init(fd, readOnly); + fd.release(); } -MappedFile::MappedFile(int fd, bool readOnly) : - _fd(-1), - _map(MAP_FAILED) +// does NOT close fd on failure. +MappedFile::MappedFile(int fd, bool readOnly) { init(fd, readOnly); } -MappedFile::MappedFile(const char *name, size_t size) : - _fd(-1), - _map(MAP_FAILED) +MappedFile::MappedFile(const char *name, size_t size) { #undef __METHOD__ #define __METHOD__ "MappedFile::MappedFile" + _fd = -1; + _map = MAP_FAILED; _size = size; _readOnly = false; + _encoding = ProDOSOrder; auto_fd fd(::open(name, O_CREAT | O_TRUNC | O_RDWR, 0644)); @@ -93,20 +92,22 @@ MappedFile::~MappedFile() if (_fd >= 0) ::close(_fd); } +// does NOT close f on exception. void MappedFile::init(int f, bool readOnly) { #undef __METHOD__ #define __METHOD__ "MappedFile::init" - auto_fd fd(f); - + //auto_fd fd(f); + + _fd = -1; + _map = MAP_FAILED; _offset = 0; _blocks = 0; _size = 0; _readOnly = readOnly; - _dosOrder = false; - - _size = ::lseek(_fd, 0, SEEK_END); + _encoding = ProDOSOrder; + _size = ::lseek(f, 0, SEEK_END); if (_size < 0) throw Exception(__METHOD__ ": Unable to determine file size.", errno); @@ -116,7 +117,7 @@ void MappedFile::init(int f, bool readOnly) MAP_FILE | MAP_SHARED, fd, 0); */ auto_map map( - fd, + f, _size, readOnly ? PROT_READ : PROT_READ | PROT_WRITE, readOnly ? MAP_FILE : MAP_FILE | MAP_SHARED @@ -124,7 +125,7 @@ void MappedFile::init(int f, bool readOnly) if (map == MAP_FAILED) throw Exception(__METHOD__ ": Unable to map file.", errno); - _fd = fd.release(); + _fd = f; _map = map.release(); } @@ -147,26 +148,35 @@ void MappedFile::readBlock(unsigned block, void *bp) if (bp == 0) throw Exception(__METHOD__ ": Invalid address."); - if (_dosOrder) + switch(_encoding) { - unsigned track = (block & ~0x07) << 9; - unsigned sector = (block & 0x07) << 1; - - for (unsigned i = 0; i < 2; ++i) + case ProDOSOrder: { - size_t address = track | (DOSMap[sector+i] << 8); - - std::memcpy(bp, (uint8_t *)_map + _offset + address, 256); - - bp = (uint8_t *)bp + 256; + size_t address = block * 512; + std::memcpy(bp, (uint8_t *)_map + _offset + address, 512); } + break; + case DOSOrder: + { + unsigned track = (block & ~0x07) << 9; + unsigned sector = (block & 0x07) << 1; + + for (unsigned i = 0; i < 2; ++i) + { + size_t address = track | (DOSMap[sector+i] << 8); + + std::memcpy(bp, (uint8_t *)_map + _offset + address, 256); + + bp = (uint8_t *)bp + 256; + } + } + break; + + default: + throw Exception(__METHOD__ ": Unsupported Encoding."); } - else - { - size_t address = block * 512; - std::memcpy(bp, (uint8_t *)_map + _offset + address, 512); - } + } void MappedFile::writeBlock(unsigned block, const void *bp) @@ -176,27 +186,37 @@ void MappedFile::writeBlock(unsigned block, const void *bp) if (block > _blocks) throw Exception(__METHOD__ ": Invalid block number."); - if ( (_readOnly) || (_map == MAP_FAILED)) - throw Exception(__METHOD__ ": File is readonly."); + if (_readOnly) throw Exception(__METHOD__ ": File is readonly."); - if (_dosOrder) + + switch(_encoding) { - unsigned track = (block & ~0x07) << 9; - unsigned sector = (block & 0x07) << 1; - - for (unsigned i = 0; i < 2; ++i) + case ProDOSOrder: { - size_t address = track | (DOSMap[sector+i] << 8); - - std::memcpy((uint8_t *)_map + _offset + address, bp, 256); - bp = (uint8_t *)bp + 256; + size_t address = block * 512; + std::memcpy((uint8_t *)_map + _offset + address , bp, 512); } + break; + + case DOSOrder: + { + unsigned track = (block & ~0x07) << 9; + unsigned sector = (block & 0x07) << 1; + + for (unsigned i = 0; i < 2; ++i) + { + size_t address = track | (DOSMap[sector+i] << 8); + + std::memcpy((uint8_t *)_map + _offset + address, bp, 256); + bp = (uint8_t *)bp + 256; + } + } + break; + + default: + throw Exception(__METHOD__ ": Unsupported Encoding."); } - else - { - size_t address = block * 512; - std::memcpy((uint8_t *)_map + _offset + address , bp, 512); - } + } void MappedFile::sync() @@ -204,8 +224,7 @@ void MappedFile::sync() #undef __METHOD__ #define __METHOD__ "MappedFile::sync" - if ( (_readOnly) || (_map == MAP_FAILED)) - return; + if (_readOnly) return; if (::msync(_map, _size, MS_SYNC) < 0) throw Exception(__METHOD__ ": msync error.", errno); @@ -215,7 +234,7 @@ void MappedFile::reset() { _offset = 0; _blocks = 0; - _dosOrder = false; + _encoding = ProDOSOrder; } diff --git a/MappedFile.h b/MappedFile.h index 009c8bc..c174391 100644 --- a/MappedFile.h +++ b/MappedFile.h @@ -11,6 +11,14 @@ namespace ProFUSE { class MappedFile { public: + + enum Encoding { + ProDOSOrder = 0, + DOSOrder, + Nibblized62, + Nibblized53 + }; + MappedFile(const char *name, bool ReadOnly); MappedFile(int fd, bool readOnly); MappedFile(const char *name, size_t size); @@ -24,8 +32,8 @@ public: void reset(); - bool dosOrder() const { return _dosOrder; } - void setDosOrder(bool tf) { _dosOrder = tf; } + Encoding encoding() const { return _encoding; } + void setEncoding(Encoding e) { _encoding = e; } unsigned offset() const { return _offset; } void setOffset(unsigned o) { _offset = o; } @@ -52,7 +60,7 @@ private: size_t _size; bool _readOnly; - bool _dosOrder; + Encoding _encoding; unsigned _offset; unsigned _blocks; From ee7736d7b827273174010eb02155bf1cf2818ee8 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 26 Nov 2009 15:58:10 +0000 Subject: [PATCH 014/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@115 aa027e90-d47c-11dd-86d7-074df07e0730 --- DavexDiskImage.cpp | 10 +- DavexDiskImage.h | 1 + DiskCopy42Image.cpp | 23 +++- DiskCopy42Image.h | 2 + Endian.h | 64 ++++----- UniversalDiskImage.cpp | 2 +- newfs_prodos.cpp | 288 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 353 insertions(+), 37 deletions(-) create mode 100644 newfs_prodos.cpp diff --git a/DavexDiskImage.cpp b/DavexDiskImage.cpp index e16ed13..fafb8a9 100644 --- a/DavexDiskImage.cpp +++ b/DavexDiskImage.cpp @@ -9,6 +9,7 @@ #include #include #include +#include using namespace ProFUSE; using namespace LittleEndian; @@ -89,6 +90,10 @@ DavexDiskImage *DavexDiskImage::Open(MappedFile *file) } DavexDiskImage *DavexDiskImage::Create(const char *name, size_t blocks) +{ + return Create(name, blocks, "Untitled"); +} +DavexDiskImage *DavexDiskImage::Create(const char *name, size_t blocks, const char *vname) { #undef __METHOD__ #define __METHOD__ "DavexDiskImage::Create" @@ -122,7 +127,10 @@ DavexDiskImage *DavexDiskImage::Create(const char *name, size_t blocks) header.push32le(0); // volume Name - header.pushBytes("\x08Untitled", 9); + if (!vname || !*vname) vname = "Untitled"; + unsigned l = std::strlen(vname); + header.push8(std::min(l, 15u)); + header.pushBytes(vname, std::min(l, 15u)); // name + reserved. header.resize(64); diff --git a/DavexDiskImage.h b/DavexDiskImage.h index 0541428..5f75934 100644 --- a/DavexDiskImage.h +++ b/DavexDiskImage.h @@ -14,6 +14,7 @@ public: virtual ~DavexDiskImage(); static DavexDiskImage *Create(const char *name, size_t blocks); + static DavexDiskImage *Create(const char *name, size_t blocks, const char *vname); static DavexDiskImage *Open(MappedFile *); diff --git a/DiskCopy42Image.cpp b/DiskCopy42Image.cpp index 7f1169c..5502130 100644 --- a/DiskCopy42Image.cpp +++ b/DiskCopy42Image.cpp @@ -4,6 +4,8 @@ #include "Endian.h" #include +#include +#include using namespace ProFUSE; using namespace BigEndian; @@ -85,6 +87,11 @@ static uint8_t FormatByte(size_t blocks) } } DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks) +{ + return Create(name, blocks, "Untitled"); +} + +DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks, const char *vname) { MappedFile *file = new MappedFile(name, blocks * 512 + 84); file->setOffset(84); @@ -92,8 +99,13 @@ DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks) Buffer header(84); - // name -- 64byte pstring. - header.pushBytes("\x08Untitled", 9); + // name -- 64byte pstring. + + if (vname == NULL) vname = "Untitled"; + unsigned l = std::strlen(vname); + header.push8(std::min(l, 63u)); + header.pushBytes(vname, std::min(l, 63u)); + header.resize(64); // data size -- number of bytes @@ -139,11 +151,14 @@ DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks) void DiskCopy42Image::Validate(MappedFile *file) { +#undef __METHOD__ +#define __METHOD__ "DiskCopy42Image::Validate" + size_t bytes = 0; size_t size = file->fileSize(); const void *data = file->fileData(); bool ok = false; - uint32_t checksum; + uint32_t checksum = 0; do { if (size < 84) break; @@ -167,6 +182,8 @@ void DiskCopy42Image::Validate(MappedFile *file) ok = true; } while (false); + if (!ok) + throw Exception(__METHOD__ ": Invalid file format."); uint32_t cs = Checksum(64 + (uint8_t *)data, bytes); diff --git a/DiskCopy42Image.h b/DiskCopy42Image.h index 689deca..7a80f87 100644 --- a/DiskCopy42Image.h +++ b/DiskCopy42Image.h @@ -13,6 +13,8 @@ public: virtual ~DiskCopy42Image(); static DiskCopy42Image *Create(const char *name, size_t blocks); + static DiskCopy42Image *Create(const char *name, size_t blocks, const char *vname); + static DiskCopy42Image *Open(MappedFile *); static uint32_t Checksum(void *data, size_t size); diff --git a/Endian.h b/Endian.h index 355ceac..7241f7e 100644 --- a/Endian.h +++ b/Endian.h @@ -8,68 +8,68 @@ namespace LittleEndian { - uint8_t Read8(const void *vp) + inline uint8_t Read8(const void *vp) { const uint8_t *p = (const uint8_t *)vp; return (p[0]); } - uint16_t Read16(const void *vp) + inline uint16_t Read16(const void *vp) { const uint8_t *p = (const uint8_t *)vp; return p[0] | (p[1] << 8); } - uint32_t Read24(const void *vp) + inline uint32_t Read24(const void *vp) { const uint8_t *p = (const uint8_t *)vp; return (p[0]) | (p[1] << 8) | (p[2] << 16); } - uint32_t Read32(const void *vp) + inline uint32_t Read32(const void *vp) { const uint8_t *p = (const uint8_t *)vp; return (p[0]) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); } - uint8_t Read8(const void *vp, unsigned offset) + inline uint8_t Read8(const void *vp, unsigned offset) { return Read8(offset + (const uint8_t *)vp); } - uint16_t Read16(const void *vp, unsigned offset) + inline uint16_t Read16(const void *vp, unsigned offset) { return Read16(offset + (const uint8_t *)vp); } - uint32_t Read24(const void *vp, unsigned offset) + inline uint32_t Read24(const void *vp, unsigned offset) { return Read24(offset + (const uint8_t *)vp); } - uint32_t Read32(const void *vp, unsigned offset) + inline uint32_t Read32(const void *vp, unsigned offset) { return Read32(offset + (const uint8_t *)vp); } // write - void Write8(void *vp, uint8_t x) + inline void Write8(void *vp, uint8_t x) { uint8_t *p = (uint8_t *)vp; p[0] = x; } - void Write16(void *vp, uint16_t x) + inline void Write16(void *vp, uint16_t x) { uint8_t *p = (uint8_t *)vp; p[0] = (x) & 0xff; p[1] = (x >> 8) & 0xff; } - void Write24(void *vp, uint32_t x) + inline void Write24(void *vp, uint32_t x) { uint8_t *p = (uint8_t *)vp; p[0] = (x) & 0xff; @@ -77,7 +77,7 @@ namespace LittleEndian { p[2] = (x >> 16) & 0xff; } - void Write32(void *vp, uint32_t x) + inline void Write32(void *vp, uint32_t x) { uint8_t *p = (uint8_t *)vp; p[0] = (x) & 0xff; @@ -86,22 +86,22 @@ namespace LittleEndian { p[3] = (x >> 24) & 0xff; } - void Write8(void *vp, unsigned offset, uint8_t x) + inline void Write8(void *vp, unsigned offset, uint8_t x) { Write8(offset + (uint8_t *)vp, x); } - void Write16(void *vp, unsigned offset, uint16_t x) + inline void Write16(void *vp, unsigned offset, uint16_t x) { Write16(offset + (uint8_t *)vp, x); } - void Write24(void *vp, unsigned offset, uint32_t x) + inline void Write24(void *vp, unsigned offset, uint32_t x) { Write24(offset + (uint8_t *)vp, x); } - void Write32(void *vp, unsigned offset, uint32_t x) + inline void Write32(void *vp, unsigned offset, uint32_t x) { Write32(offset + (uint8_t *)vp, x); } @@ -112,48 +112,48 @@ namespace LittleEndian { namespace BigEndian { - uint8_t Read8(const void *vp) + inline uint8_t Read8(const void *vp) { const uint8_t *p = (const uint8_t *)vp; return p[0]; } - uint16_t Read16(const void *vp) + inline uint16_t Read16(const void *vp) { const uint8_t *p = (const uint8_t *)vp; return (p[0] << 8) | (p[1]); } - uint32_t Read24(const void *vp) + inline uint32_t Read24(const void *vp) { const uint8_t *p = (const uint8_t *)vp; return (p[0] << 16) | (p[1] << 8) | (p[2]); } - uint32_t Read32(const void *vp) + inline uint32_t Read32(const void *vp) { const uint8_t *p = (const uint8_t *)vp; return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); } - uint8_t Read8(const void *vp, unsigned offset) + inline uint8_t Read8(const void *vp, unsigned offset) { return Read8(offset + (const uint8_t *)vp); } - uint16_t Read16(const void *vp, unsigned offset) + inline uint16_t Read16(const void *vp, unsigned offset) { return Read16(offset + (const uint8_t *)vp); } - uint32_t Read24(const void *vp, unsigned offset) + inline uint32_t Read24(const void *vp, unsigned offset) { return Read24(offset + (const uint8_t *)vp); } - uint32_t Read32(const void *vp, unsigned offset) + inline uint32_t Read32(const void *vp, unsigned offset) { return Read32(offset + (const uint8_t *)vp); } @@ -161,20 +161,20 @@ namespace BigEndian { // write - void Write8(void *vp, uint8_t x) + inline void Write8(void *vp, uint8_t x) { uint8_t *p = (uint8_t *)vp; p[0] = x; } - void Write16(void *vp, uint16_t x) + inline void Write16(void *vp, uint16_t x) { uint8_t *p = (uint8_t *)vp; p[0] = (x >> 8) & 0xff; p[1] = (x) & 0xff; } - void Write24(void *vp, uint32_t x) + inline void Write24(void *vp, uint32_t x) { uint8_t *p = (uint8_t *)vp; p[0] = (x >> 16) & 0xff; @@ -182,7 +182,7 @@ namespace BigEndian { p[2] = (x) & 0xff; } - void Write32(void *vp, uint32_t x) + inline void Write32(void *vp, uint32_t x) { uint8_t *p = (uint8_t *)vp; p[0] = (x >> 24) & 0xff; @@ -191,22 +191,22 @@ namespace BigEndian { p[3] = (x) & 0xff; } - void Write8(void *vp, unsigned offset, uint8_t x) + inline void Write8(void *vp, unsigned offset, uint8_t x) { Write8(offset + (uint8_t *)vp, x); } - void Write16(void *vp, unsigned offset, uint16_t x) + inline void Write16(void *vp, unsigned offset, uint16_t x) { Write16(offset + (uint8_t *)vp, x); } - void Write24(void *vp, unsigned offset, uint32_t x) + inline void Write24(void *vp, unsigned offset, uint32_t x) { Write24(offset + (uint8_t *)vp, x); } - void Write32(void *vp, unsigned offset, uint32_t x) + inline void Write32(void *vp, unsigned offset, uint32_t x) { Write32(offset + (uint8_t *)vp, x); } diff --git a/UniversalDiskImage.cpp b/UniversalDiskImage.cpp index 87c6055..0e077c7 100644 --- a/UniversalDiskImage.cpp +++ b/UniversalDiskImage.cpp @@ -80,7 +80,7 @@ UniversalDiskImage *UniversalDiskImage::Open(MappedFile *file) void UniversalDiskImage::Validate(MappedFile *file) { #undef __METHOD__ -#define __METHOD__ "DavexDiskImage::Validate" +#define __METHOD__ "UniversalDiskImage::Validate" const void *data = file->fileData(); size_t size = file->fileSize(); diff --git a/newfs_prodos.cpp b/newfs_prodos.cpp new file mode 100644 index 0000000..e4d1728 --- /dev/null +++ b/newfs_prodos.cpp @@ -0,0 +1,288 @@ +#include "BlockDevice.h" +#include "UniversalDiskImage.h" +#include "DiskCopy42Image.h" +#include "DavexDiskImage.h" +#include "RawDevice.h" +#include "Exception.h" + +#include +#include +#include +#include +#include + +#include + +#include + +#define NEWFS_VERSION "0.1" + +using namespace ProFUSE; + +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; +} + +unsigned parseFormat(const char *type, unsigned defv = 0) +{ + if (type == 0 || *type == 0) return defv; + + if (::strcasecmp(type, "2mg") == 0) + return '2IMG'; + if (::strcasecmp(type, "2img") == 0) + return '2IMG'; + if (::strcasecmp(type, "dc42") == 0) + return 'DC42'; + if (::strcasecmp(type, "po") == 0) + return 'PO__'; + if (::strcasecmp(type, "do") == 0) + return 'DO__'; + if (::strcasecmp(type, "davex") == 0) + return 'DVX_'; + + return defv; +} + +// return the filename extension, NULL if none. +const char *extname(const char *src) +{ + if (!src) return NULL; + unsigned l = std::strlen(src); + + for (unsigned i = 0; i < l; ++i) + { + char c = src[l - 1 - i]; + if (c == '/') return NULL; + if (c == '.') return src + l - i; + } + + return NULL; +} + +// 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 = parseFormat(optarg); + if (format == 0) + { + std::fprintf(stderr, "Error: `%s' is not a supposed 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 = parseFormat(extname(fname)); + + + try + { + std::auto_ptr device; + //auto_ptr volume; + + // todo -- check if path matches /dev/xxx; if so, use RawDevice. + // todo -- check if file exists at path? + + switch(format) + { + case 'DC42': + // todo -- pass in volume name + 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(new VolumeDirectory(name, device)); + device.release(); + + } + catch (Exception e) + { + std::fprintf(stderr, "Error: %s\n", e.what()); + return -1; + } + return 0; +} From 6f6338bc19389b56ba02e3d04d00be615330fba1 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 26 Nov 2009 18:06:42 +0000 Subject: [PATCH 015/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@116 aa027e90-d47c-11dd-86d7-074df07e0730 --- DateTime.cpp | 2 +- DateTime.h | 2 +- Directory.h => Entry.h | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) rename Directory.h => Entry.h (99%) diff --git a/DateTime.cpp b/DateTime.cpp index f406ee9..6c0062a 100644 --- a/DateTime.cpp +++ b/DateTime.cpp @@ -5,7 +5,7 @@ #include #include -namespace ProDOS { +using namespace ProFUSE; /* * date is a 16 bit value: diff --git a/DateTime.h b/DateTime.h index 9f3aa78..24055d4 100644 --- a/DateTime.h +++ b/DateTime.h @@ -4,7 +4,7 @@ #include #include -namespace ProDOS { +namespace ProFUSE { class DateTime { diff --git a/Directory.h b/Entry.h similarity index 99% rename from Directory.h rename to Entry.h index 1b317f8..64cd21a 100644 --- a/Directory.h +++ b/Entry.h @@ -13,6 +13,7 @@ class BlockDevice; class Bitmap; class FileEntry; class Volume; +class Buffer; enum Access { From 736746052b9ae912373581159393e9ee9b65f9f4 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 26 Nov 2009 19:30:12 +0000 Subject: [PATCH 016/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@117 aa027e90-d47c-11dd-86d7-074df07e0730 --- Directory.cpp | 409 +------------------------------------------- Entry.cpp | 169 ++++++++++++++++++ Entry.h | 48 +++--- VolumeDirectory.cpp | 119 +++++++++++++ 4 files changed, 318 insertions(+), 427 deletions(-) create mode 100644 Entry.cpp create mode 100644 VolumeDirectory.cpp diff --git a/Directory.cpp b/Directory.cpp index 48c2af5..04ee1ed 100644 --- a/Directory.cpp +++ b/Directory.cpp @@ -2,7 +2,7 @@ #include #include -#include "Directory" +#include "Entry.h" #include "Buffer.h" #include "Endian.h" @@ -12,154 +12,6 @@ using namespace ProFUSE; using namespace LittleEndian; -static bool isalpha(unsigned c) -{ - return (c >= 'A' && c <= 'Z') - || (c >= 'a' && x <= 'z') ; -} - -static bool isalnumdot(unsigned c) -{ - return (c >= 'A' && c <= 'Z') - || (c >= 'a' && c <= 'z') - || (c >= '0' && c <='9') - || (c == '.') ; - -} - -static bool islower(unsigned c) -{ - return c >= 'a' && c <= 'z'; -} - - -/* - * ProDOS names: - * 1-15 letters, digits, or '.' - * first character must be a letter. - */ -unsigned Entry::ValidName(const char *name) -{ - unsigned length; - - if (!name) return 0; - - if (!isalpha(*name)) return 0; - length = 1; - - for (length = 1; length < 17; ++length) - { - if (!isalnumdot(name[length])) return 0; - } - - if (length > 15) return 0; - return length; -} - -Entry::Entry(unsigned type, const char *name) -{ - _storageType = type; - _address = 0; - _index = 0; - _volume = NULL; - - // 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; - 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] = _name[i] | 0x20; - } - } -} - -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] = c & ~0x20; // upper - if (islower(c)) - { - caseFlag |= (0x4000 >> i); - } - } - - _length = length; - _caseFlag = caseFlag; -} - - - - - Directory::Directory(unsigned type, const char *name) : @@ -186,7 +38,7 @@ Directory::Directory(const void *bp) : // input is a block pointer. To simplify, // create a new pointer past the 4-byte linked list part. - void *dp = 4 + (const uint8_t *)bp; + const void *dp = 4 + (const uint8_t *)bp; _creation = DateTime(Read16(dp, 0x18), Read16(dp, 0x1a)); @@ -197,7 +49,7 @@ Directory::Directory(const void *bp) : _entryLength = Read8(dp, 0x1f); _entriesPerBlock = Read8(dp, 0x20); - _fileCount = read16(dp, 0x21); + _fileCount = Read16(dp, 0x21); // parse child file entries ... requires ability to read other blocks. } @@ -206,265 +58,14 @@ Directory::~Directory() { } -Directory::setAccess(unsigned access) +void Directory::setAccess(unsigned access) { #undef __METHOD__ #define __METHOD__ "Directory::setAccess" - if ((access & 0xe7) != access) - throw Exception(__METHOD__ ": Illegal access."); + _access = access; // todo -- mark dirty? update block? } - -#pragma mark 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(new Bitmap(_totalBlocks)); - - - // 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(&out); - } - - buffer.rezize(512); - device->write(i, buffer.buffer()); - } - - // TODO -- create/write the volume entry.... - - // allocate blocks for the bitmap itself - unsigned bb = bitmap->bitmapBlocks(); - for (unsigned i = 0; i < bb; ++i) - bitmap->allocBlock(i); - - // now write the bitmap... - const uint8_t *bm = (const uint8_t *)bitmap->bitmap(); - for (unsigned i = 0; i < bb; ++i) - { - device->writeBlock(_bitmapPointer + i, 512 * i + bm); - } - - setDevice(device); - _bitmap = bitmap.release(); -} - -VolumeDirectory::~VolumeDirectory() -{ -} - -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); -} - -#pragma mark SubDirectory - -SubDirectory::SubDirectory(FileEntry *e) : - Directory(DirectoryHeader, e->iname()) -{ - _creation = e->creation(); - setAccess(e->access()); - - _parentEntryPointer = e->block(); - _parentEntryNumber = e->index(); - _parentEntryLength = 0x27; - -} - -SubDirectory::SubDirectory(const char *name) : - Directory(DirectoryHeader, name) -{ - _parentPointer = 0; - _parentEntryNumber = 0; - _parentEntryLength = 0x27; -} - -SubDirectory::SubDirectory(const void *bp) : - Directory(bp) -{ - const void *dp = 4 + (const uint8_t *)bp; - - _parentPointer = Read16(dp, 0x23); - _parentEntryNumber = Read8(dp, 0x25); - _parentEntryLength = Read8(dp, 0x26); -} - -SubDirectory::~SubDirectory -{ -} - -void SubDirectory::write(Buffer *out) -{ - out->push8((VolumeHeader << 4 ) | (nameLength()); - out->pushBytes(namei(), 15); - - // reserved. 0x76 is stored in the first byte. - // no one knows why. - out->push8(0x76); - out->push8(0); - out->push8(0); - out->push8(0); - out->push8(0); - out->push8(0); - out->push8(0); - out->push8(0); - - // 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(_parentPointer); - out->push8(_parentEntryNumber); - out->push8(_parentEntryLength); -} - - - - -FileEntry::FileEntry(unsigned type, const char *name) : - Entry(type, name) -{ - _fileType = type == DirectoryFile ? 0x0f : 0x00; - _keyPointer = 0; - _blocksUsed = 0; - _eof = 0; - _access = 0xe3; - _auxType = 0; - _headerPointer = 0; -} - - -FileEntry::FileEntry(const void *vp) : - Entry(vp), - _creation(0,0), - _modification(0,0) -{ -#undef __METHOD__ -#define __METHOD__ "FileEntry::FileEntry" - - switch(storageType()) - { - case SeedlingFile: - case SaplingFile: - case TreeFile: - case PascalFile: - case ExtendedFile: - case DirectoryFile: - break; - default: - throw Exception(__METHOD__ ": Invalid storage type."); - } - - - _fileType = Read8(vp, 0x10); - _keyPointer = Read16(vp, 0x11); - _blocksUsed = Read16(vp, 0x13); - _eof = Read24(vp, 0x15); - _creation = DateTime(Read16(vp, 0x18), Read16(vp, 0x1a)); - _access = Read8(vp, 0x1e); - _auxType = Read16(vp, 0x1f); - _modification = DateTime(Read16(vp, 0x21), Read16(vp, 0x23)); - _headerPointer = Read16(vp, 0x25); - - -} - -FileEntry::~FileEntry() -{ -} - - -void FileEntry::write(Buffer *out) -{ - out->push8((VolumeHeader << 4 ) | (nameLength()); - out->pushBytes(namei(), 15); - - out->push8(_fileType); - out->push16le(_keyPointer); - out->push16le(_blocksUsed); - out-push24le(_eof); - - // creation - out->push16le(_creation.date()); - out->push16le(_creation.time()); - - // case bits - out->push16le(caseFlag()); - - out->push8(_access); - put->push16le(_auxType); - - // modification - out->push16le(_modification.date()); - out->push16le(_modification.time()); - - out->push16le(_headerPointer); -} \ No newline at end of file diff --git a/Entry.cpp b/Entry.cpp new file mode 100644 index 0000000..15b84b1 --- /dev/null +++ b/Entry.cpp @@ -0,0 +1,169 @@ +#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) + { + if (!isalnumdot(name[length])) 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; +} + + diff --git a/Entry.h b/Entry.h index 64cd21a..3ff3d39 100644 --- a/Entry.h +++ b/Entry.h @@ -52,7 +52,7 @@ public: const char *name() const { return _name; } const char *namei() const { return _namei; } - unsigned caseFlags() const { return _caseFlags; } + unsigned caseFlag() const { return _caseFlag; } void setName(const char *name); @@ -63,37 +63,33 @@ public: static unsigned ValidName(const char *); - unsigned block() const { return _address / 512; } + 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(int storageType, const char *name); + Entry(unsigned storageType, const char *name); Entry(const void *bp); - setStorageType(unsigned type) - { - _storageType = type; - } + void setStorageType(unsigned type) + { _storageType = type; } + void setAddress(unsigned address) + { _address = address; } - setAddress(unsigned address) - { - _address = address; - } - - setIndex(unsigned index) - { - _index = index;w - } - + void setIndex(unsigned index) + { _index = index; } - - Volume *volume() { return _volume; } + void setVolume(Volume *v) + { _volume = v; } + + private: @@ -101,7 +97,7 @@ private: unsigned _index; Volume *_volume; - + unsigned _storageType; unsigned _nameLength; char _namei[15+1]; // insensitive, ie, uppercase. @@ -139,8 +135,8 @@ protected: private: DateTime _creation; - unsigned _version - unsigned _minVersion + unsigned _version; + unsigned _minVersion; unsigned _access; unsigned _entryLength; // always 0x27 unsigned _entriesPerBlock; //always 0x0d @@ -153,6 +149,7 @@ private: class VolumeDirectory: public Directory { public: + VolumeDirectory(const char *name, BlockDevice *device); virtual ~VolumeDirectory(); unsigned bitmapPointer() const { return _bitmapPointer; } @@ -162,12 +159,17 @@ public: int allocBlock(); void freeBlock(unsigned block); + virtual void write(Buffer *); + + BlockDevice *device() const { return _device; } private: Bitmap *_bitmap; + BlockDevice *_device; + DateTime _modification; unsigned _totalBlocks; unsigned _bitmapPointer; - + // inode / free inode list? }; diff --git a/VolumeDirectory.cpp b/VolumeDirectory.cpp new file mode 100644 index 0000000..20f0c63 --- /dev/null +++ b/VolumeDirectory.cpp @@ -0,0 +1,119 @@ + +#include +#include + +#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(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(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()); + } + + // TODO -- create/write the volume entry.... + + // allocate blocks for the bitmap itself + unsigned bb = bitmap->bitmapBlocks(); + for (unsigned i = 0; i < bb; ++i) + bitmap->allocBlock(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() +{ + if (_device) + { + _device->sync(); + delete _device; + } +} + +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); +} From da22eb1114994a11b1d63cce9e0e4e9b538dc159 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 26 Nov 2009 19:45:54 +0000 Subject: [PATCH 017/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@118 aa027e90-d47c-11dd-86d7-074df07e0730 --- DateTime.cpp | 1 - Makefile | 21 +++++++++++++++++++++ VolumeDirectory.cpp | 1 + 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 Makefile diff --git a/DateTime.cpp b/DateTime.cpp index 6c0062a..bacf62b 100644 --- a/DateTime.cpp +++ b/DateTime.cpp @@ -141,4 +141,3 @@ std::time_t DateTime::toUnix() const // convert back via locatime & fudge for dst? } -} // namespace diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..552e7d1 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +CC = g++ +CPPFLAGS += -Wall -O2 + +newfs_prodos: \ + newfs_prodos.o \ + Exception.o \ + BlockDevice.o \ + UniversalDiskImage.o \ + DiskCopy42Image.o \ + DavexDiskImage.o \ + RawDevice.o \ + MappedFile.o \ + Buffer.o \ + Entry.o \ + Directory.o \ + VolumeDirectory.o \ + Bitmap.o \ + DateTime.o + + + \ No newline at end of file diff --git a/VolumeDirectory.cpp b/VolumeDirectory.cpp index 20f0c63..f4c8df1 100644 --- a/VolumeDirectory.cpp +++ b/VolumeDirectory.cpp @@ -83,6 +83,7 @@ VolumeDirectory::~VolumeDirectory() _device->sync(); delete _device; } + delete _bitmap; } void VolumeDirectory::write(Buffer *out) From b3334ac2104a1956538f14ecc15cbd243d3c3548 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 28 Nov 2009 23:22:37 +0000 Subject: [PATCH 018/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@123 aa027e90-d47c-11dd-86d7-074df07e0730 --- BlockDevice.cpp | 2 ++ Entry.cpp | 6 +++++- Makefile | 2 +- VolumeDirectory.cpp | 5 ++--- newfs_prodos.cpp | 22 +++++++++++----------- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/BlockDevice.cpp b/BlockDevice.cpp index e75bef8..3463965 100644 --- a/BlockDevice.cpp +++ b/BlockDevice.cpp @@ -114,6 +114,7 @@ ProDOSOrderDiskImage::ProDOSOrderDiskImage(MappedFile *file) : ProDOSOrderDiskImage *ProDOSOrderDiskImage::Create(const char *name, size_t blocks) { MappedFile *file = new MappedFile(name, blocks * 512); + file->setBlocks(blocks); return new ProDOSOrderDiskImage(file); } @@ -154,6 +155,7 @@ DOSOrderDiskImage *DOSOrderDiskImage::Create(const char *name, size_t blocks) { MappedFile *file = new MappedFile(name, blocks * 512); file->setEncoding(MappedFile::DOSOrder); + file->setBlocks(blocks); return new DOSOrderDiskImage(file); } diff --git a/Entry.cpp b/Entry.cpp index 15b84b1..3d3d982 100644 --- a/Entry.cpp +++ b/Entry.cpp @@ -52,7 +52,11 @@ unsigned Entry::ValidName(const char *name) for (length = 1; length < 17; ++length) { - if (!isalnumdot(name[length])) return 0; + char c = name[length]; + if (isalnumdot(c)) continue; + if (c == 0) break; + + return 0; } if (length > 15) return 0; diff --git a/Makefile b/Makefile index 552e7d1..840038b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = g++ -CPPFLAGS += -Wall -O2 +CPPFLAGS += -Wall -O2 -g newfs_prodos: \ newfs_prodos.o \ diff --git a/VolumeDirectory.cpp b/VolumeDirectory.cpp index f4c8df1..1f81c14 100644 --- a/VolumeDirectory.cpp +++ b/VolumeDirectory.cpp @@ -58,12 +58,11 @@ VolumeDirectory::VolumeDirectory(const char *name, BlockDevice *device) : device->write(i, buffer.buffer()); } - // TODO -- create/write the volume entry.... - + // allocate blocks for the bitmap itself unsigned bb = bitmap->bitmapBlocks(); for (unsigned i = 0; i < bb; ++i) - bitmap->allocBlock(i); + bitmap->allocBlock(_bitmapPointer + i); // now write the bitmap... const uint8_t *bm = (const uint8_t *)bitmap->bitmap(); diff --git a/newfs_prodos.cpp b/newfs_prodos.cpp index e4d1728..a8dd84d 100644 --- a/newfs_prodos.cpp +++ b/newfs_prodos.cpp @@ -1,20 +1,21 @@ -#include "BlockDevice.h" -#include "UniversalDiskImage.h" -#include "DiskCopy42Image.h" -#include "DavexDiskImage.h" -#include "RawDevice.h" -#include "Exception.h" - #include #include #include #include #include - #include #include +#include "BlockDevice.h" +#include "DavexDiskImage.h" +#include "DiskCopy42Image.h" +#include "Entry.h" +#include "Exception.h" +#include "RawDevice.h" +#include "UniversalDiskImage.h" + + #define NEWFS_VERSION "0.1" using namespace ProFUSE; @@ -244,7 +245,7 @@ int main(int argc, char **argv) try { std::auto_ptr device; - //auto_ptr volume; + std::auto_ptr volume; // todo -- check if path matches /dev/xxx; if so, use RawDevice. // todo -- check if file exists at path? @@ -252,7 +253,6 @@ int main(int argc, char **argv) switch(format) { case 'DC42': - // todo -- pass in volume name device.reset(DiskCopy42Image::Create(fname, blocks, volumeName.c_str())); break; @@ -275,7 +275,7 @@ int main(int argc, char **argv) // VolumeDirectory assumes ownership of device, // but doesn't release it on exception. - //volume.reset(new VolumeDirectory(name, device)); + volume.reset(new VolumeDirectory(volumeName.c_str(), device.get())); device.release(); } From b660593d259757474bccd485e30a80707a740028 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 2 Dec 2009 01:19:34 +0000 Subject: [PATCH 019/236] ProDOS/Posix Exceptions git-svn-id: https://profuse.googlecode.com/svn/branches/v2@124 aa027e90-d47c-11dd-86d7-074df07e0730 --- Exception.h | 43 ++++++++++++++++++++++++++++++++++++++----- MappedFile.cpp | 14 +++++++------- RawDevice.cpp | 23 +++++++++++++---------- 3 files changed, 58 insertions(+), 22 deletions(-) diff --git a/Exception.h b/Exception.h index cf9ffb7..cd23c37 100644 --- a/Exception.h +++ b/Exception.h @@ -11,20 +11,36 @@ class Exception : public std::exception public: Exception(const char *cp); Exception(const std::string &str); - Exception(const char *cp, int error); - Exception(const std::string& string, int error); + virtual ~Exception() throw (); virtual const char *what(); - int error() const; + int error() const { return _error; } + +protected: + Exception(const char *cp, int error); + Exception(const std::string& string, int error); + private: int _error; std::string _string; }; +class POSIXException : public Exception { +public: + POSIXException(const char *cp, int error); + POSIXException(const std::string& string, int error); +}; + +class ProDOSException : public Exception { +public: + ProDOSException(const char *cp, int error); + ProDOSException(const std::string& string, int error); +}; + inline Exception::Exception(const char *cp): _error(0), _string(cp) @@ -49,11 +65,28 @@ inline Exception::Exception(const std::string& string, int error): { } -inline int Exception::error() const +inline POSIXException::POSIXException(const char *cp, int error) : + Exception(cp, error) { - return _error; } +inline POSIXException::POSIXException(const std::string& string, int error) : + Exception(string, error) +{ +} + +inline ProDOSException::ProDOSException(const char *cp, int error) : + Exception(cp, error) +{ +} + +inline ProDOSException::ProDOSException(const std::string& string, int error) : + Exception(string, error) +{ +} + + + } #endif \ No newline at end of file diff --git a/MappedFile.cpp b/MappedFile.cpp index b8b055d..7b078b3 100644 --- a/MappedFile.cpp +++ b/MappedFile.cpp @@ -36,7 +36,7 @@ MappedFile::MappedFile(const char *name, bool readOnly) if (fd < 0) { - throw Exception(__METHOD__ ": Unable to open file.", errno); + throw POSIXException(__METHOD__ ": Unable to open file.", errno); } // init may throw; auto_fd guarantees the file will be closed if that happens. init(fd, readOnly); @@ -63,12 +63,12 @@ MappedFile::MappedFile(const char *name, size_t size) auto_fd fd(::open(name, O_CREAT | O_TRUNC | O_RDWR, 0644)); if (fd < 0) - throw Exception(__METHOD__ ": Unable to create file.", errno); + throw POSIXException(__METHOD__ ": Unable to create file.", errno); // TODO -- is ftruncate portable? if (::ftruncate(fd, _size) < 0) { - throw Exception(__METHOD__ ": Unable to truncate file.", errno); + throw POSIXException(__METHOD__ ": Unable to truncate file.", errno); } //_map = ::mmap(NULL, _size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, _fd, 0); @@ -80,7 +80,7 @@ MappedFile::MappedFile(const char *name, size_t size) MAP_FILE | MAP_SHARED ); - if (map == MAP_FAILED) throw Exception(__METHOD__ ": Unable to map file.", errno); + if (map == MAP_FAILED) throw POSIXException(__METHOD__ ": Unable to map file.", errno); _fd = fd.release(); _map = map.release(); @@ -110,7 +110,7 @@ void MappedFile::init(int f, bool readOnly) _size = ::lseek(f, 0, SEEK_END); if (_size < 0) - throw Exception(__METHOD__ ": Unable to determine file size.", errno); + throw POSIXException(__METHOD__ ": Unable to determine file size.", errno); /* _map = ::mmap(NULL, _size, readOnly ? PROT_READ : PROT_READ | PROT_WRITE, @@ -123,7 +123,7 @@ void MappedFile::init(int f, bool readOnly) readOnly ? MAP_FILE : MAP_FILE | MAP_SHARED ); - if (map == MAP_FAILED) throw Exception(__METHOD__ ": Unable to map file.", errno); + if (map == MAP_FAILED) throw POSIXException(__METHOD__ ": Unable to map file.", errno); _fd = f; _map = map.release(); @@ -227,7 +227,7 @@ void MappedFile::sync() if (_readOnly) return; if (::msync(_map, _size, MS_SYNC) < 0) - throw Exception(__METHOD__ ": msync error.", errno); + throw POSIXException(__METHOD__ ": msync error.", errno); } void MappedFile::reset() diff --git a/RawDevice.cpp b/RawDevice.cpp index 2635143..bc19ce5 100644 --- a/RawDevice.cpp +++ b/RawDevice.cpp @@ -36,7 +36,7 @@ void RawDevice::devSize(int fd) struct dk_minfo minfo; if (::ioctl(fd, DKIOCGMEDIAINFO, &minfo) < 0) - throw 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. @@ -55,11 +55,11 @@ void RawDevice::devSize(int fd) uint64_t blockCount; // 64 bit if (::ioctl(fd, DKIOCGETBLOCKSIZE, &blockSize) < 0) - throw Exception(__METHOD__ ": Unable to determine block size.", errno); + throw POSIXException(__METHOD__ ": Unable to determine block size.", errno); if (::ioctl(fd, DKIOCGETBLOCKCOUNT, &blockCount) < 0) - throw Exception(__METHOD__ ": Unable to determine block count.", errno); + throw POSIXException(__METHOD__ ": Unable to determine block count.", errno); _blockSize = blockSize; _size = _blockSize * blockCount; @@ -79,7 +79,7 @@ void RawDevice::devSize(int fd) int blocks; if (::ioctl(fd, BLKGETSIZE, &blocks) < 0) - throw Exception(__METHOD__ ": Unable to determine device size.", errno); + throw POSIXException(__METHOD__ ": Unable to determine device size.", errno); _size = 512 * blocks; _blockSize = 512; // @@ -110,7 +110,7 @@ RawDevice::RawDevice(const char *name, bool readOnly) } if (fd < 0) - throw Exception(__METHOD__ ": Unable to open device.", errno); + throw POSIXException(__METHOD__ ": Unable to open device.", errno); _fd = -1; @@ -147,8 +147,10 @@ void RawDevice::read(unsigned block, void *bp) // TODO -- EINTR? if (ok != 512) - throw Exception(__METHOD__ ": Error reading block.", - ok < 0 ? errno : 0); + throw ok < 0 + ? POSIXException(__METHOD__ ": Error reading block.", errno) + : Exception(__METHOD__ ": Error reading block."); + } @@ -166,8 +168,9 @@ void RawDevice::write(unsigned block, const void *bp) size_t ok = ::pwrite(_fd, bp, 512, block * 512); if (ok != 512) - throw Exception(__METHOD__ ": Error writing block.", - ok < 0 ? errno : 0); + throw ok < 0 + ? POSIXException(__METHOD__ ": Error writing block.", errno) + : Exception(__METHOD__ ": Error writing block."); } @@ -184,5 +187,5 @@ void RawDevice::sync() if (_readOnly) return; if (::fsync(_fd) < 0) - throw Exception(__METHOD__ ": fsync error.", errno); + throw POSIXException(__METHOD__ ": fsync error.", errno); } \ No newline at end of file From dcd31997ed2146f0287ac5f6744957786a52819e Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 6 Dec 2009 02:44:01 +0000 Subject: [PATCH 020/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@125 aa027e90-d47c-11dd-86d7-074df07e0730 --- Directory.cpp | 38 ++++++++++++++++++++++++++++- Entry.h | 12 ++++++++- VolumeDirectory.cpp | 59 +++++++++++++++++++++++++++++++++++++++++++++ newfs_prodos.cpp | 2 +- 4 files changed, 108 insertions(+), 3 deletions(-) diff --git a/Directory.cpp b/Directory.cpp index 04ee1ed..786e16c 100644 --- a/Directory.cpp +++ b/Directory.cpp @@ -5,7 +5,7 @@ #include "Entry.h" #include "Buffer.h" #include "Endian.h" - +#include "BlockDevice.h" #include "Exception.h" @@ -69,3 +69,39 @@ void Directory::setAccess(unsigned 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; + } + + +} + + diff --git a/Entry.h b/Entry.h index 3ff3d39..1e2ca82 100644 --- a/Entry.h +++ b/Entry.h @@ -131,6 +131,8 @@ protected: std::vector _children; std::vector _entryBlocks; + + void loadChildren(BlockDevice *, unsigned block); private: @@ -149,7 +151,10 @@ private: class VolumeDirectory: public Directory { public: - VolumeDirectory(const char *name, BlockDevice *device); + static VolumeDirectory *Create(const char *name, BlockDevice *device); + static VolumeDirectory *Create(BlockDevice *); + + virtual ~VolumeDirectory(); unsigned bitmapPointer() const { return _bitmapPointer; } @@ -162,7 +167,12 @@ public: 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; diff --git a/VolumeDirectory.cpp b/VolumeDirectory.cpp index 1f81c14..dd67bdb 100644 --- a/VolumeDirectory.cpp +++ b/VolumeDirectory.cpp @@ -15,6 +15,25 @@ 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) { @@ -75,6 +94,46 @@ VolumeDirectory::VolumeDirectory(const char *name, BlockDevice *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; + 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) diff --git a/newfs_prodos.cpp b/newfs_prodos.cpp index a8dd84d..756f607 100644 --- a/newfs_prodos.cpp +++ b/newfs_prodos.cpp @@ -275,7 +275,7 @@ int main(int argc, char **argv) // VolumeDirectory assumes ownership of device, // but doesn't release it on exception. - volume.reset(new VolumeDirectory(volumeName.c_str(), device.get())); + volume.reset(VolumeDirectory::Create(volumeName.c_str(), device.get())); device.release(); } From 5c48dcb813f615be2f3f009981bd872f5f789e8c Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 7 Dec 2009 22:19:24 +0000 Subject: [PATCH 021/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@126 aa027e90-d47c-11dd-86d7-074df07e0730 --- DataWriter.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++ DataWriter.h | 72 +++++++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 DataWriter.cpp create mode 100644 DataWriter.h diff --git a/DataWriter.cpp b/DataWriter.cpp new file mode 100644 index 0000000..9f7036b --- /dev/null +++ b/DataWriter.cpp @@ -0,0 +1,98 @@ +#include "DataWriter.h" +#include "Endian.h" + +#include + +using namespace ProFUSE; + +DataWriter::DataWriter(unsigned size) +{ + _size = size; + _release = true; + _offset = 0; + _buffer = new uint8_t[size]; +} + +DataWriter::DataWriter(unsigned size, void *buffer) +{ + _size = size; + _buffer = (uint8_t *)buffer; + _release = false; + _offset = 0; +} + +DataWriter::~DataWriter() +{ + if (_release && _buffer) delete[] _buffer; +} + +void DataWriter::write8(uint8_t data) +{ + _buffer[_offset] = data; + _offset += 1; +} + +void DataWriter::write(const void *data, unsigned size) +{ + std::memcpy(pointer(), data, size); + _offset += size; +} + + + +DataWriterLE::DataWriterLE(unsigned size) : + DataWriter(size) +{} + +DataWriterLE::DataWriterLE(unsigned size, void *buffer) : + DataWriter(size, buffer) +{} + + +void DataWriterLE::write16(uint16_t data) +{ + LittleEndian::Write16(pointer(), data); + _offset += 2; +} + +void DataWriterLE::write24(uint32_t data) +{ + LittleEndian::Write24(pointer(), data); + _offset += 3; +} + +void DataWriterLE::write32(uint32_t data) +{ + LittleEndian::Write32(pointer(), data); + _offset += 4; +} + + + +DataWriterBE::DataWriterBE(unsigned size) : + DataWriter(size) +{} + +DataWriterBE::DataWriterBE(unsigned size, void *buffer) : + DataWriter(size, buffer) +{} + + +void DataWriterBE::write16(uint16_t data) +{ + BigEndian::Write16(pointer(), data); + _offset += 2; +} + +void DataWriterBE::write24(uint32_t data) +{ + BigEndian::Write24(pointer(), data); + _offset += 3; +} + +void DataWriterBE::write32(uint32_t data) +{ + BigEndian::Write32(pointer(), data); + _offset += 4; +} + diff --git a/DataWriter.h b/DataWriter.h new file mode 100644 index 0000000..5323842 --- /dev/null +++ b/DataWriter.h @@ -0,0 +1,72 @@ + +#ifndef __DATAWRITER_H__ +#define __DATAWRITER_H__ + +#include + +namespace ProFUSE { + +class DataWriter { + +public: + + DataWriter(unsigned size); + DataWriter(unsigned size, void *data); + virtual ~DataWriter(); + + void write8(uint8_t); + virtual void write16(uint16_t) = 0; + virtual void write24(uint32_t) = 0; + virtual void write32(uint32_t) = 0; + + void write(const void *data, unsigned size); + + + void setOffset(unsigned o) { _offset = o; } + unsigned offset() const { return _offset; } + + void forward(unsigned count) { _offset += count; } + void rewind(unsigned count) { _offset -= count; } + + void *data() const { return _buffer; } + unsigned size() const { return _size; } + +protected: + + uint8_t *pointer() const { return _offset + _buffer; } + + bool _release; + unsigned _size; + + unsigned _offset; + uint8_t *_buffer; + + +}; + +class DataWriterLE : public DataWriter { +public: + DataWriterLE(unsigned); + DataWriterLE(unsigned, void *); + + virtual void write8(uint8_t); + virtual void write16(uint16_t); + virtual void write24(uint32_t); + virtual void write32(uint32_t); +}; + + +class DataWriterBE : public DataWriter { +public: + DataWriterBE(unsigned); + DataWriterBE(unsigned, void *); + + virtual void write8(uint8_t); + virtual void write16(uint16_t); + virtual void write24(uint32_t); + virtual void write32(uint32_t); +}; + +} + +#endif \ No newline at end of file From 9fc279ef643a093c2cbe4c5b5f57944f30fed833 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 8 Dec 2009 00:01:24 +0000 Subject: [PATCH 022/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@127 aa027e90-d47c-11dd-86d7-074df07e0730 --- BlockCache.cpp | 120 ++++++++++++++++++++++++++++++++++++++++++++ BlockCache.h | 37 ++++++++++++++ VolumeDirectory.cpp | 1 + 3 files changed, 158 insertions(+) create mode 100644 BlockCache.cpp create mode 100644 BlockCache.h diff --git a/BlockCache.cpp b/BlockCache.cpp new file mode 100644 index 0000000..b0d4c74 --- /dev/null +++ b/BlockCache.cpp @@ -0,0 +1,120 @@ +#include "BlockCache.h" +#include "BlockDevice.h" +#include "auto.h" + +#include + + + +/* + * Note -- everything is assumed to be single-threaded. + * + */ + + + +using namespace ProFUSE; + +typedef std::vector::iterator BDIter; + +const unsigned CacheSize = 16; + +BlockCache::BlockCache(BlockDevice *device) +{ + _device = device; + _ts = 0; + _blocks.reserve(CacheSize); +} + +BlockCache::~BlockCache() +{ + for (BDIter iter = _blocks.begin(); iter != _blocks.end(); ++iter) + { + if (iter->data) delete[] iter->data; + } +} + + +void *BlockCache::acquire(unsigned block) +{ + unsigned mints = -1; + unsigned freeCount = 0; + + BDIter oldest; + + + ++_ts; + + /* + * keep a pointer to the oldest free entry (according to ts). + * and re-use if >= 16 entries. + */ + + + for (BDIter iter = _blocks.begin(); iter != _blocks.end(); ++iter) + { + if (iter->block == block) + { + ++iter->count; + iter->ts = _ts; + return iter->data; + } + + if (iter->count == 0) + { + ++freeCount; + if (iter->ts < mints) + { + mints = iter->ts; + oldest = iter; + } + } + } + + + if (freeCount && (_blocks.size() >= CacheSize)) + { + oldest->block = block; + oldest->count = 1; + oldest->ts = _ts; + + _device->read(block, oldest->data); + return oldest->data; + } + + + auto_array buffer(new uint8_t[512]); + BlockDescriptor bd = { block, 1, _ts, buffer.get() }; + + _device->read(block, buffer.get()); + + _blocks.push_back(bd); + + + return buffer.release(); +} + + +void BlockCache::release(unsigned block) +{ + + for (BDIter iter = _blocks.begin(); iter != _blocks.end(); ++iter) + { + if (iter->block == block) + { + if (!--iter->count) + { + _device->write(block, iter->data); + + // trim back if too many entries. + + if (_blocks.size() > CacheSize) + { + delete[] iter->data; + _blocks.erase(iter); + } + } + return; + } + } +} \ No newline at end of file diff --git a/BlockCache.h b/BlockCache.h new file mode 100644 index 0000000..4e65719 --- /dev/null +++ b/BlockCache.h @@ -0,0 +1,37 @@ +#ifndef __BLOCKCACHE_H__ +#define __BLOCKCACHE_H__ + +#include +#include + +namespace ProFUSE { + +class BlockDevice; + +struct BlockDescriptor { + unsigned block; + unsigned count; + unsigned ts; + uint8_t *data; +}; + + + +class BlockCache { + BlockCache(BlockDevice *device); + ~BlockCache(); + + void write(); + + void *acquire(unsigned block); + void release(unsigned block); + +private: + std::vector _blocks; + BlockDevice *_device; + unsigned _ts; +}; + +} + +#endif \ No newline at end of file diff --git a/VolumeDirectory.cpp b/VolumeDirectory.cpp index dd67bdb..fe1e94e 100644 --- a/VolumeDirectory.cpp +++ b/VolumeDirectory.cpp @@ -16,6 +16,7 @@ using namespace LittleEndian; #pragma mark VolumeDirectory + VolumeDirectory *VolumeDirectory::Create(const char *name, BlockDevice *device) { return new VolumeDirectory(name, device); From b8d728c78190f3f883521e0135c6a4bd35724687 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 8 Dec 2009 03:42:22 +0000 Subject: [PATCH 023/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@128 aa027e90-d47c-11dd-86d7-074df07e0730 --- Entry.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/Entry.h b/Entry.h index 1e2ca82..4ab7810 100644 --- a/Entry.h +++ b/Entry.h @@ -41,6 +41,8 @@ enum StorageType { class Entry { public: + + virtual ~Entry(); virtual void write(Buffer *) = 0; @@ -108,6 +110,18 @@ private: class Directory : public Entry { public: + + enum { + + OffsetCreation = 0x18, + OffsetVersion = 0x1c, + OffsetMinVersion = 0x1d, + OffsetAccess = 0x1e, + OffsetEntryLength = 0x1f, + OffsetEntriesPerBlock = 0x20, + OffsetFileCount = 0x21 + }; + virtual ~Directory(); @@ -151,6 +165,14 @@ private: 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 *); @@ -182,11 +204,21 @@ private: // inode / free inode list? + + }; class SubDirectory : public Directory { public: + + enum { + OffsetPasswordEnabled = 0x10, + OffsetParentPointer = 0x23, + OffsetParentEntryNumber = 0x25, + OffsetParentEntryLength = 0x26 + }; + SubDirectory(FileEntry *); private: unsigned _parentPointer; @@ -197,6 +229,26 @@ private: 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; } @@ -210,6 +262,10 @@ public: DateTime modification() const { return _modification; } private: + + void *acquirePointer(); + void releasePointer(); + unsigned _fileType; unsigned _keyPointer; unsigned _blocksUsed; From 26757971368ce70ae60caab4b0fb9d87b09828c2 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 10 Dec 2009 01:41:37 +0000 Subject: [PATCH 024/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@134 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/DateRec.cpp | 29 ++++ pascal/DateRec.h | 44 ++++++ pascal/File.cpp | 359 ++++++++++++++++++++++++++++++++++++++++++++ pascal/File.h | 111 ++++++++++++++ pascal/TextFile.cpp | 92 ++++++++++++ pascal/TextFile.h | 0 6 files changed, 635 insertions(+) create mode 100644 pascal/DateRec.cpp create mode 100644 pascal/DateRec.h create mode 100644 pascal/File.cpp create mode 100644 pascal/File.h create mode 100644 pascal/TextFile.cpp create mode 100644 pascal/TextFile.h diff --git a/pascal/DateRec.cpp b/pascal/DateRec.cpp new file mode 100644 index 0000000..3f42f5f --- /dev/null +++ b/pascal/DateRec.cpp @@ -0,0 +1,29 @@ +#include "DateRec.h" +#include + +using namespace Pascal; + + + +DateRec::DateRec(unsigned val) +{ + // yyyy yyym mmmm dddd + _day = val & 0xf; + _month = (val >> 4) & 0x1f; + _year = (val >> 9) & 0x7f; +} + +DateRec::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; + + return std::mktime(&tm); +} \ No newline at end of file diff --git a/pascal/DateRec.h b/pascal/DateRec.h new file mode 100644 index 0000000..8f9e2e4 --- /dev/null +++ b/pascal/DateRec.h @@ -0,0 +1,44 @@ +#ifndef __DATEREC_H__ +#define __DATEREC_H__ + +#include + +namespace Pascal { + +class DateRec { +public: + + DateRec(); + DateRec(unsigned yy, unsigned mm, unsigned dd); + DateRec(unsigned); + + operator std::time_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 DateRec::DateRec() +{ + _year = 0; + _month = 0; + _day = 0; +} + +inline DateRec::DateRec(unsigned yy, unsigned mm, unsigned dd) +{ + _year = yy; + _month = mm; + _day = dd; +} + +} + +#endif diff --git a/pascal/File.cpp b/pascal/File.cpp new file mode 100644 index 0000000..ae8ff86 --- /dev/null +++ b/pascal/File.cpp @@ -0,0 +1,359 @@ +#include "File.h" +#include "../auto.h" +#include "../Endian.h" +#include "../BlockDevice.h" + +#include +#include + +using namespace LittleEndian; +using namespace Pascal; + +#pragma mark - +#pragma mark DirEntry + +Entry::Entry() +{ + _firstBlock = 0; + _lastBlock = 0; + _fileKind = 0; + _inode = 0; +} + +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; +} + + +#pragma mark - +#pragma mark VolumeEntry + +VolumeEntry::VolumeEntry() +{ + _fileNameLength = 0; + std::memset(_fileName, 0, 8); + _lastVolumeBlock = 0; + _numberOfFiles = 0; + _accessTime = 0; + + setInode(1); + _inodeGenerator = 1; +} + +VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device) +{ + auto_array buffer(new uint8_t[512]); + unsigned blockCount; + + // read the header block, then load up all the header + // blocks. + + device->read(2, buffer.get()); + + init(tmp); + + // todo -- verify reasonable values. + blockCount = blocks(); + if (blockCount > 1) + { + buffer.reset(new uint8_t[512 * blockCount]); + + for (unsigned i = 0; i < blockCount; ++i) + { + device->read(2 + i, buffer.get() + 512 * i); + } + } + + // now load up all the children. + // if this throws, memory could be lost... + + try + { + for (unsigned i = 1; i < _numberFiles; ++i) + { + std::auto_ptr child; + + child.reset(new FileEntry(buffer.get() + i * 0x1a)); + + child->setInode(++_inodeGenerator); + _files.push_back(child.release()); + } + } + catch (...) + { + std::vectoriterator iter; + for(iter = _files.begin(); iter != _files.end(); ++iter) + { + if (*iter) delete *iter; + } + + throw; + } + +} + +VolumeEntry::~VolumeEntry() +{ + std::vectoriterator iter; + for(iter = _files.begin(); iter != _files.end(); ++iter) + { + if (*iter) delete *iter; + } +} + + +void VolumeEntry::init(void *vp) +{ + Entry::init(vp); + _fileNameLength = Read8(vp, 6); + + // verify filenamelength <= 7 + // verify fileKind == 0 + + std::memcpy(_fileName, 7 + (uint8_t *)vp, _fileNameLength); + + _lastVolumeBlock = Read16(vp, 0x0e); + _numberFile = Read16(vp, 0x10); + _accessTime = Read16(vp, 0x12); + _bootDate = DateRec(Read16(vp, 0x14); + + setInode(1); + _inodeGenerator = 1; +} + + +FileEntry *VolumeEntry::fileAtIndex(unsigned i) const +{ + return i < _files.length() ? _files[i] : NULL; +} + + + +#pragma mark - +#pragma mark FileEntry + +FileEntry::FileEntry(void *vp) : + Entry(vp) +{ + + +} + +unsigned File::fileSize() { + return (_lastBlock - _firstBlock - 1) * 512 + _lastByte; +} + +int File::read(uint8_t *buffer, unsigned size, unsigned offset) +{ + uint8_t tmp[512]; + + unsigned fileSize = fileSize(); + unsigned count = 0; + unsigned block = 0; + + if (offset >= fileSize) return 0; + + if (offset + size > fileSize) size = fileSize - offset; + + block = _startBlock + (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); + + _device->read(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) + { + _device->read(block++, buffer); + + buffer += 512; + count += 512; + size -= 512; + } + + /* + * 3. Read any trailing blocks. + */ + if (size) + { + _device->read(block, tmp); + std::memcpy(buffer, tmp, size); + + count += size; + + } + + + return count; +} + + + +int TextFile::read(uint8_t *buffer, unsigned size, unsigned offset) +{ + unsigned page = 0; + unsigned to = 0; + unsigned l = _pageSize.length(); + unsigned block; + unsigned count = 0; + + auto_array tmp; + unsigned tmpSize = 0; + + if (offset >= _fileSize) return 0; + if (offset + size > _fileSize) size = _fileSize - offset; + + + // find the first page. + for (page = 1; page < l; ++page) + { + if (to + _pageSize[page] > offset) + { + break; + } + + to += _pageSize[i]; + } + + --page; + + block = _startBlock + 2 + (page * 2); + + + // offset not needed anymore, + // convert to offset from *this* page. + offset -= to; + + while (size) + { + unsigned pageSize = _pageSize[page]; + if (pageSize > tmp) + { + tmp.reset(new uint8_t[pageSize]); + tmpSize = pageSize; + } + + bytes = std::min(size, pageSize - offset); + + decodePage(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 TextFile::decodePage(unsigned block, uint8_t *out) +{ + uint8_t buffer[1024]; + unsigned size = 0; + unsigned bytes = readPage(block, buffer); + + for (unsigned i = 0; i < bytes; ++i) + { + uint8_t c = buffer[i]; + + if (!c) break; + if (c == 16 && i != bytes - 1) + { + // DLE + // 16, n -> n-32 spaces. + unsigned x = buffer[++i] - 32; + + if (out) for(unsigned i = 0; i < x; ++i) *out++ = ' '; + size += x; + } + else + { + if (out) *out++ = c; + size += 1; + } + } + + return size; +} + +unsigned TextFile::readPage(unsigned block, uint8_t *in) +{ + // reads up to 2 blocks. + // assumes block within _startBlock ... _endBlock - 1 + unsigned size = 0; + + _device->read(block, in); + if (block + 1 == _endBlock) + { + return _lastByte; + } + + _device->read(block + 1, in + 512); + if (block +2 == _endBlock) + { + return 512 + _lastByte; + } + + return 1024; +} + + + +void TextFile::init() +{ + // calculate the file size and page offsets. + + _pageSize.reserve((_endBlock - _startBlock - 2) / 2); + + _fileSize = 0; + for (unsigned block = _startBlock + 2; block < _endBlock; block += 2) + { + unsigned size = decodePage(block, NULL); + _fileSize += size; + _pageSize.push_back(size); + } +} \ No newline at end of file diff --git a/pascal/File.h b/pascal/File.h new file mode 100644 index 0000000..ab2edfc --- /dev/null +++ b/pascal/File.h @@ -0,0 +1,111 @@ +#ifndef __FILE_H__ +#define __FILE_H__ + +#include "DateRec.h" + +#include + +namespace ProFUSE { + class BlockDevice; +}; + +namespace Pascal { + +class FileEntry; + +class Entry { + +public: + + virtual ~Entry(); + + unsigned firstBlock() const { return _firstBlock; } + unsigned lastBlock() const { return _lastBlock; } + unsigned blocks() const { return _firstBlock - lastBlock; } + + unsigned fileKind() const { return _fileKind; } + + unsigned inode() const { return _inode; } + void setInode(unsigned inode) { _inode = inode; } + +protected: + + Entry(); + Entry(void *); + void init(void *); + + unsigned _firstBlock; + unsigned _lastBlock; + unsigned _fileKind; + + unsigned _inode; +} + + +class VolumeEntry : public Entry { + +public: + + VolumeEntry(ProFUSE::BlockDevice *); + virtual ~VolumeEntry(); + + const char *name() const { return _fileName; } + unsigned fileCount() const { return _numberFiles; } + + Pascal::DateRec lastBoot() const { return _lastBoot; } + + FileEntry *fileAtIndex(unsigned i) const; + +private: + + unsigned _fileNameLength; + char _fileName[8]; + unsigned _lastVolumeBlock; + unsigned _numberFiles; + unsigned _accessTime; + Pascal::DateRec _lastBoot; + + std::vector _files; + unsigned _inodeGenerator; + +}; + + +class FileEntry : public Entry { + public: + + FileEntry(void *vp); + virtual ~FileEntry(); + + unsigned fileSize(); + int read(uint8_t *buffer, unsigned size, unsigned offset); + + const char *name() const { return _fileName; } + DateRec modification() const { return _modification; } + + protected: + + unsigned _status; + + unsigned _fileNameLength; + char _fileName[16]; + + unsigned _lastByte; + DateRec _modification; + + // for text files. + + unsigned readTextPage(unsigned block, uint8_t *in); + unsigned decodeTextPage(unsigned block, uint8_t *out); + + + std::vector *_pageLengths; + unsigned _fileSize; + +}; + + + +} + +#endif diff --git a/pascal/TextFile.cpp b/pascal/TextFile.cpp new file mode 100644 index 0000000..727858c --- /dev/null +++ b/pascal/TextFile.cpp @@ -0,0 +1,92 @@ + + + +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 _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; + } + + +} + + diff --git a/pascal/TextFile.h b/pascal/TextFile.h new file mode 100644 index 0000000..e69de29 From 982b7547139bce03f330740ff787ee708cd77670 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 10 Dec 2009 02:04:54 +0000 Subject: [PATCH 025/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@135 aa027e90-d47c-11dd-86d7-074df07e0730 --- auto.h | 7 +++++++ pascal/File.cpp | 22 ++++++++++++---------- pascal/File.h | 16 ++++++++++------ 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/auto.h b/auto.h index b9dd6fd..d971b68 100644 --- a/auto.h +++ b/auto.h @@ -17,6 +17,13 @@ public: operator T*() const { return _t; } T& operator[](int index) { return _t[index]; } + void reset(T *t) + { + if (t == _t) return; + if (_t) delete[] _t; + _t = t; + } + private: T *_t; }; diff --git a/pascal/File.cpp b/pascal/File.cpp index ae8ff86..43c5e07 100644 --- a/pascal/File.cpp +++ b/pascal/File.cpp @@ -48,7 +48,7 @@ VolumeEntry::VolumeEntry() _fileNameLength = 0; std::memset(_fileName, 0, 8); _lastVolumeBlock = 0; - _numberOfFiles = 0; + _fileCount = 0; _accessTime = 0; setInode(1); @@ -65,7 +65,7 @@ VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device) device->read(2, buffer.get()); - init(tmp); + init(buffer.get()); // todo -- verify reasonable values. blockCount = blocks(); @@ -84,7 +84,7 @@ VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device) try { - for (unsigned i = 1; i < _numberFiles; ++i) + for (unsigned i = 1; i < _fileCount; ++i) { std::auto_ptr child; @@ -96,7 +96,7 @@ VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device) } catch (...) { - std::vectoriterator iter; + std::vector::iterator iter; for(iter = _files.begin(); iter != _files.end(); ++iter) { if (*iter) delete *iter; @@ -109,7 +109,7 @@ VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device) VolumeEntry::~VolumeEntry() { - std::vectoriterator iter; + std::vector::iterator iter; for(iter = _files.begin(); iter != _files.end(); ++iter) { if (*iter) delete *iter; @@ -128,9 +128,9 @@ void VolumeEntry::init(void *vp) std::memcpy(_fileName, 7 + (uint8_t *)vp, _fileNameLength); _lastVolumeBlock = Read16(vp, 0x0e); - _numberFile = Read16(vp, 0x10); + _fileCount = Read16(vp, 0x10); _accessTime = Read16(vp, 0x12); - _bootDate = DateRec(Read16(vp, 0x14); + _lastBoot = DateRec(Read16(vp, 0x14)); setInode(1); _inodeGenerator = 1; @@ -139,10 +139,10 @@ void VolumeEntry::init(void *vp) FileEntry *VolumeEntry::fileAtIndex(unsigned i) const { - return i < _files.length() ? _files[i] : NULL; + return i < _files.size() ? _files[i] : NULL; } - +#if 0 #pragma mark - #pragma mark FileEntry @@ -356,4 +356,6 @@ void TextFile::init() _fileSize += size; _pageSize.push_back(size); } -} \ No newline at end of file +} + +#endif diff --git a/pascal/File.h b/pascal/File.h index ab2edfc..c1d7f3c 100644 --- a/pascal/File.h +++ b/pascal/File.h @@ -7,7 +7,7 @@ namespace ProFUSE { class BlockDevice; -}; +} namespace Pascal { @@ -19,9 +19,10 @@ public: virtual ~Entry(); + unsigned blocks() const { return _firstBlock - _lastBlock; } + unsigned firstBlock() const { return _firstBlock; } unsigned lastBlock() const { return _lastBlock; } - unsigned blocks() const { return _firstBlock - lastBlock; } unsigned fileKind() const { return _fileKind; } @@ -39,7 +40,7 @@ protected: unsigned _fileKind; unsigned _inode; -} +}; class VolumeEntry : public Entry { @@ -50,18 +51,21 @@ public: virtual ~VolumeEntry(); const char *name() const { return _fileName; } - unsigned fileCount() const { return _numberFiles; } + unsigned fileCount() const { return _fileCount; } Pascal::DateRec lastBoot() const { return _lastBoot; } FileEntry *fileAtIndex(unsigned i) const; private: - + VolumeEntry(); + + void init(void *); + unsigned _fileNameLength; char _fileName[8]; unsigned _lastVolumeBlock; - unsigned _numberFiles; + unsigned _fileCount; unsigned _accessTime; Pascal::DateRec _lastBoot; From 99321a3f9362cc312b866a4017719a723d089423 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 10 Dec 2009 02:18:05 +0000 Subject: [PATCH 026/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@136 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/File.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++--- pascal/File.h | 25 ++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/pascal/File.cpp b/pascal/File.cpp index 43c5e07..72916d9 100644 --- a/pascal/File.cpp +++ b/pascal/File.cpp @@ -142,7 +142,7 @@ FileEntry *VolumeEntry::fileAtIndex(unsigned i) const return i < _files.size() ? _files[i] : NULL; } -#if 0 + #pragma mark - #pragma mark FileEntry @@ -150,10 +150,49 @@ FileEntry *VolumeEntry::fileAtIndex(unsigned i) const 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 = DateRec(Read16(vp, 0x18)); } +FileEntry::~FileEntry() +{ + delete _pageLength; +} + + +unsigned FileEntry::fileSize() +{ + switch(fileKind()) + { + case kTextFile: + return textFileSize(); + break; + default: + return dataFileSize(); + break; + } +} + + +int FileEntry::read(uint8_t *buffer, unsigned size, unsigned offset) +{ + switch(fileKind()) + { + case kTextFile: + return textRead(buffer, size, offset); + break; + default: + return dataRead(buffer, size, offset); + break; + } +} + +#if 0 + unsigned File::fileSize() { return (_lastBlock - _firstBlock - 1) * 512 + _lastByte; } diff --git a/pascal/File.h b/pascal/File.h index c1d7f3c..c5297ee 100644 --- a/pascal/File.h +++ b/pascal/File.h @@ -11,6 +11,19 @@ namespace ProFUSE { namespace Pascal { + +enum { + kUntypedFile, + kBadBlockFile, + kCodeFile, + kTextFile, + kInfoFile, + kDataFile, + kGrafFile, + kFotoFile, + kSecureDir +}; + class FileEntry; class Entry { @@ -97,13 +110,19 @@ class FileEntry : public Entry { unsigned _lastByte; DateRec _modification; + // non-text files + unsigned dataFileSize(); + int dataRead(uint8_t *buffer, unsigned size, unsigned offset); + // for text files. + unsigned textFileSize(); + int textRead(uint8_t *buffer, unsigned size, unsigned offset); - unsigned readTextPage(unsigned block, uint8_t *in); - unsigned decodeTextPage(unsigned block, uint8_t *out); + unsigned textReadPage(unsigned block, uint8_t *in); + unsigned textDecodePage(unsigned block, uint8_t *out); - std::vector *_pageLengths; + std::vector *_pageLength; unsigned _fileSize; }; From f469d4e4d4c289c50b79070525dccc3dceca6455 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 10 Dec 2009 02:40:41 +0000 Subject: [PATCH 027/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@137 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/File.cpp | 20 ++++++++++++++++---- pascal/File.h | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/pascal/File.cpp b/pascal/File.cpp index 72916d9..7e99fb2 100644 --- a/pascal/File.cpp +++ b/pascal/File.cpp @@ -191,13 +191,25 @@ int FileEntry::read(uint8_t *buffer, unsigned size, unsigned offset) } } -#if 0 -unsigned File::fileSize() { - return (_lastBlock - _firstBlock - 1) * 512 + _lastByte; +unsigned FileEntry::dataFileSize() +{ + return blocks() * 512 - 512 + _lastByte; } -int File::read(uint8_t *buffer, unsigned size, unsigned offset) +unsigned FileEntry::textFileSize() +{ + if (!_pageLength()) textInit(); + return _fileSize; +} + + + +#if 0 + + + +int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset) { uint8_t tmp[512]; diff --git a/pascal/File.h b/pascal/File.h index c5297ee..d69bc5e 100644 --- a/pascal/File.h +++ b/pascal/File.h @@ -115,13 +115,13 @@ class FileEntry : public Entry { 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 *_pageLength; unsigned _fileSize; From 922494caa69d7a8d7270b4dc1c22d8563240761f Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 11 Dec 2009 00:59:53 +0000 Subject: [PATCH 028/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@139 aa027e90-d47c-11dd-86d7-074df07e0730 --- BlockCache.cpp | 105 +++++++++++++++++++++++++++++++++++++++++------- BlockCache.h | 62 ++++++++++++++++++++++------ BlockDevice.cpp | 30 +++++++++++++- BlockDevice.h | 13 +++++- Exception.h | 2 +- MappedFile.cpp | 2 + MappedFile.h | 5 ++- pascal/File.cpp | 33 ++++++++------- 8 files changed, 204 insertions(+), 48 deletions(-) diff --git a/BlockCache.cpp b/BlockCache.cpp index b0d4c74..f2a955a 100644 --- a/BlockCache.cpp +++ b/BlockCache.cpp @@ -1,9 +1,15 @@ -#include "BlockCache.h" -#include "BlockDevice.h" -#include "auto.h" #include +#include +#include +#include + + +#include "BlockDevice.h" +#include "BlockCache.h" +#include "Exception.h" +#include "auto.h" /* @@ -15,15 +21,64 @@ using namespace ProFUSE; -typedef std::vector::iterator BDIter; +#pragma mark - +#pragma mark AbstractBlockCache -const unsigned CacheSize = 16; +AbstractBlockCache::~AbstractBlockCache() +{ +} -BlockCache::BlockCache(BlockDevice *device) +#pragma mark - +#pragma mark MappedBlockCache + +MappedBlockCache::MappedBlockCache(void *data, unsigned blocks) +{ + _blocks = blocks; + _data = (uint8_t *)_data; +} + +void MappedBlockCache::write() +{ + // TODO... +} + +void *MappedBlockCache::load(unsigned block) +{ +#undef __METHOD__ +#define __METHOD__ "MappedBlockCache::load" + + if (block >= _blocks) + throw Exception(__METHOD__ ": Invalid block."); + + + return _data + block * 512; +} +void MappedBlockCache::unload(unsigned block, bool dirty) +{ +#undef __METHOD__ +#define __METHOD__ "MappedBlockCache::unload" + + if (!dirty) return; + if (::msync(_data + block * 512, 512, MS_ASYNC) < 0) + { + throw POSIXException(__METHOD__ ": msync failed.", errno); + } +} + + +#pragma mark - +#pragma mark BlockCache + +typedef std::vector::iterator BDIter; + + + +BlockCache::BlockCache(BlockDevice *device, unsigned size) { _device = device; _ts = 0; - _blocks.reserve(CacheSize); + _cacheSize = std::max(16u, size); + _blocks.reserve(_cacheSize); } BlockCache::~BlockCache() @@ -34,8 +89,21 @@ BlockCache::~BlockCache() } } +void BlockCache::write() +{ + for (BDIter iter = _blocks.begin(); iter != _blocks.end(); ++iter) + { + if (iter->dirty) + { + _device->write(iter->block, iter->data); + iter->dirty = false; + } + } +} -void *BlockCache::acquire(unsigned block) + + +void *BlockCache::load(unsigned block) { unsigned mints = -1; unsigned freeCount = 0; @@ -57,6 +125,7 @@ void *BlockCache::acquire(unsigned block) { ++iter->count; iter->ts = _ts; + return iter->data; } @@ -72,11 +141,14 @@ void *BlockCache::acquire(unsigned block) } - if (freeCount && (_blocks.size() >= CacheSize)) + if (freeCount && (_blocks.size() >= _cacheSize)) { + // re-use old buffer. + oldest->block = block; oldest->count = 1; oldest->ts = _ts; + oldest->dirty = false; _device->read(block, oldest->data); return oldest->data; @@ -84,7 +156,7 @@ void *BlockCache::acquire(unsigned block) auto_array buffer(new uint8_t[512]); - BlockDescriptor bd = { block, 1, _ts, buffer.get() }; + BlockDescriptor bd = { block, 1, _ts, false, buffer.get() }; _device->read(block, buffer.get()); @@ -95,20 +167,23 @@ void *BlockCache::acquire(unsigned block) } -void BlockCache::release(unsigned block) +void BlockCache::unload(unsigned block, bool dirty) { for (BDIter iter = _blocks.begin(); iter != _blocks.end(); ++iter) { if (iter->block == block) { + iter->dirty = dirty || iter->dirty; if (!--iter->count) { - _device->write(block, iter->data); - + if (iter->dirty) + { + _device->write(block, iter->data); + iter->dirty = false; + } // trim back if too many entries. - - if (_blocks.size() > CacheSize) + if (_blocks.size() > _cacheSize) { delete[] iter->data; _blocks.erase(iter); diff --git a/BlockCache.h b/BlockCache.h index 4e65719..4126c4f 100644 --- a/BlockCache.h +++ b/BlockCache.h @@ -8,30 +8,66 @@ namespace ProFUSE { class BlockDevice; -struct BlockDescriptor { - unsigned block; - unsigned count; - unsigned ts; - uint8_t *data; + + +class AbstractBlockCache { +public: + virtual ~AbstractBlockCache(); + + virtual void write() = 0; + + virtual void *load(unsigned block); + virtual void unload(unsigned block, bool dirty); + + void unload(unsigned block) { unload(block, false); } }; - -class BlockCache { - BlockCache(BlockDevice *device); +class BlockCache : public AbstractBlockCache { +public: + BlockCache(BlockDevice *device, unsigned size = 16); ~BlockCache(); - void write(); - - void *acquire(unsigned block); - void release(unsigned block); + virtual void write(); + virtual void *load(unsigned block); + virtual void unload(unsigned block, bool dirty); + + private: + + struct BlockDescriptor { + unsigned block; + unsigned count; + unsigned ts; + bool dirty; + uint8_t *data; + }; + + + std::vector _blocks; BlockDevice *_device; unsigned _ts; + unsigned _cacheSize; + }; -} +class MappedBlockCache : public AbstractBlockCache { + public: + + MappedBlockCache(void *data, unsigned blocks); + + virtual void write(); + + virtual void *load(unsigned block); + virtual void unload(unsigned block, bool dirty); + + private: + unsigned _blocks; + uint8_t * _data; +}; + +} // namespace #endif \ No newline at end of file diff --git a/BlockDevice.cpp b/BlockDevice.cpp index 3463965..d58c39d 100644 --- a/BlockDevice.cpp +++ b/BlockDevice.cpp @@ -1,4 +1,5 @@ #include "BlockDevice.h" +#include "BlockCache.h" #include "Exception.h" #include "MappedFile.h" @@ -12,10 +13,12 @@ using namespace ProFUSE; - +#pragma mark - +#pragma mark BlockDevice BlockDevice::~BlockDevice() { + delete _cache; } void BlockDevice::zeroBlock(unsigned block) @@ -26,7 +29,23 @@ void BlockDevice::zeroBlock(unsigned block) write(block, bp); } +AbstractBlockCache *BlockDevice::blockCache() +{ + if (!_cache) + { + _cache = createBlockCache(); + } + return _cache; +} +AbstractBlockCache *BlockDevice::createBlockCache() +{ + return new BlockCache(this); +} + + + +#pragma mark - #pragma mark DiskImage DiskImage::DiskImage(const char *name, bool readOnly) : @@ -100,6 +119,15 @@ void DiskImage::sync() +AbstractBlockCache *DiskImage::createBlockCache() +{ + if (_file->encoding() == MappedFile::ProDOSOrder) + return new MappedBlockCache(_file->imageData(), _file->blocks()); + + return BlockDevice::createBlockCache(); +} + + ProDOSOrderDiskImage::ProDOSOrderDiskImage(const char *name, bool readOnly) : DiskImage(name, readOnly) { diff --git a/BlockDevice.h b/BlockDevice.h index 8b8d23e..9712f4c 100644 --- a/BlockDevice.h +++ b/BlockDevice.h @@ -9,6 +9,7 @@ namespace ProFUSE { class MappedFile; +class AbstractBlockCache; class BlockDevice { public: @@ -23,6 +24,14 @@ public: virtual unsigned blocks() = 0; void zeroBlock(unsigned block); + + AbstractBlockCache *blockCache(); + +protected: + virtual AbstractBlockCache *createBlockCache(); + +private: + AbstractBlockCache *_cache; }; @@ -41,7 +50,9 @@ public: protected: - DiskImage(MappedFile * = NULL); + virtual AbstractBlockCache *createBlockCache(); + + DiskImage(MappedFile * = 0); DiskImage(const char *name, bool readOnly); MappedFile *file() { return _file; } diff --git a/Exception.h b/Exception.h index cd23c37..a163ec9 100644 --- a/Exception.h +++ b/Exception.h @@ -1,8 +1,8 @@ #ifndef __EXCEPTION_H__ #define __EXCEPTION_H__ -#include #include +#include namespace ProFUSE { diff --git a/MappedFile.cpp b/MappedFile.cpp index 7b078b3..00042d3 100644 --- a/MappedFile.cpp +++ b/MappedFile.cpp @@ -1,5 +1,6 @@ #include "MappedFile.h" #include "Exception.h" + #include #include #include @@ -238,3 +239,4 @@ void MappedFile::reset() } + diff --git a/MappedFile.h b/MappedFile.h index c174391..ce2c768 100644 --- a/MappedFile.h +++ b/MappedFile.h @@ -8,7 +8,6 @@ namespace ProFUSE { - class MappedFile { public: @@ -44,10 +43,12 @@ public: bool readOnly() const { return _readOnly; } size_t fileSize() const { return _size; } void *fileData() const { return _map; } - + void *imageData() const { return _offset + (uint8_t *)_map; } private: + + MappedFile& operator=(const MappedFile& other); void init(int fd, bool readOnly); diff --git a/pascal/File.cpp b/pascal/File.cpp index 7e99fb2..2278aa1 100644 --- a/pascal/File.cpp +++ b/pascal/File.cpp @@ -3,8 +3,9 @@ #include "../Endian.h" #include "../BlockDevice.h" +#include #include -#include +#include using namespace LittleEndian; using namespace Pascal; @@ -156,6 +157,9 @@ FileEntry::FileEntry(void *vp) : std::memcpy(_fileName, 0x07 + (uint8_t *)vp, _fileNameLength); _lastByte = Read16(vp, 0x16); _modification = DateRec(Read16(vp, 0x18)); + + _fileSize = 0; + _pageLength = NULL; } FileEntry::~FileEntry() @@ -180,6 +184,11 @@ unsigned FileEntry::fileSize() 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: @@ -199,7 +208,7 @@ unsigned FileEntry::dataFileSize() unsigned FileEntry::textFileSize() { - if (!_pageLength()) textInit(); + if (!_pageLength) textInit(); return _fileSize; } @@ -213,14 +222,9 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset) { uint8_t tmp[512]; - unsigned fileSize = fileSize(); unsigned count = 0; unsigned block = 0; - - if (offset >= fileSize) return 0; - - if (offset + size > fileSize) size = fileSize - offset; - + block = _startBlock + (offset / 512); // returned value (count) is equal to size at this point. @@ -274,7 +278,7 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset) -int TextFile::read(uint8_t *buffer, unsigned size, unsigned offset) +int FileEntry::textRead(uint8_t *buffer, unsigned size, unsigned offset) { unsigned page = 0; unsigned to = 0; @@ -285,9 +289,8 @@ int TextFile::read(uint8_t *buffer, unsigned size, unsigned offset) auto_array tmp; unsigned tmpSize = 0; - if (offset >= _fileSize) return 0; - if (offset + size > _fileSize) size = _fileSize - offset; - + if (!_pageLength) textInit(); + // find the first page. for (page = 1; page < l; ++page) @@ -341,7 +344,7 @@ int TextFile::read(uint8_t *buffer, unsigned size, unsigned offset) -unsigned TextFile::decodePage(unsigned block, uint8_t *out) +unsigned FileEntry::textDecodePage(unsigned block, uint8_t *out) { uint8_t buffer[1024]; unsigned size = 0; @@ -371,7 +374,7 @@ unsigned TextFile::decodePage(unsigned block, uint8_t *out) return size; } -unsigned TextFile::readPage(unsigned block, uint8_t *in) +unsigned FileEntry::textReadPage(unsigned block, uint8_t *in) { // reads up to 2 blocks. // assumes block within _startBlock ... _endBlock - 1 @@ -394,7 +397,7 @@ unsigned TextFile::readPage(unsigned block, uint8_t *in) -void TextFile::init() +void FileEntry::textInit() { // calculate the file size and page offsets. From e3b89b22016022ab7642d85ae91d303a252f18a6 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 11 Dec 2009 02:04:27 +0000 Subject: [PATCH 029/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@140 aa027e90-d47c-11dd-86d7-074df07e0730 --- BlockCache.h | 4 +-- Entry.h | 2 +- Makefile | 1 + pascal/File.cpp | 96 +++++++++++++++++++++++++++++++++---------------- pascal/File.h | 23 ++++++++++-- 5 files changed, 91 insertions(+), 35 deletions(-) diff --git a/BlockCache.h b/BlockCache.h index 4126c4f..36b4066 100644 --- a/BlockCache.h +++ b/BlockCache.h @@ -16,8 +16,8 @@ public: virtual void write() = 0; - virtual void *load(unsigned block); - virtual void unload(unsigned block, bool dirty); + virtual void *load(unsigned block) = 0; + virtual void unload(unsigned block, bool dirty) = 0; void unload(unsigned block) { unload(block, false); } }; diff --git a/Entry.h b/Entry.h index 4ab7810..3a71085 100644 --- a/Entry.h +++ b/Entry.h @@ -167,7 +167,7 @@ public: enum { OffsetLastMod = 0x12, - OffsetFileNameCaseFlag = 0x16 + OffsetFileNameCaseFlag = 0x16, OffsetBitmapPointer = 0x23, OffsetTotalBlocks = 0x25 diff --git a/Makefile b/Makefile index 840038b..c0ae947 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ newfs_prodos: \ newfs_prodos.o \ Exception.o \ BlockDevice.o \ + BlockCache.o \ UniversalDiskImage.o \ DiskCopy42Image.o \ DavexDiskImage.o \ diff --git a/pascal/File.cpp b/pascal/File.cpp index 2278aa1..7a3e380 100644 --- a/pascal/File.cpp +++ b/pascal/File.cpp @@ -2,6 +2,7 @@ #include "../auto.h" #include "../Endian.h" #include "../BlockDevice.h" +#include "../BlockCache.h" #include #include @@ -19,6 +20,7 @@ Entry::Entry() _lastBlock = 0; _fileKind = 0; _inode = 0; + _parent = NULL; } Entry::Entry(void *vp) @@ -53,7 +55,10 @@ VolumeEntry::VolumeEntry() _accessTime = 0; setInode(1); + _inodeGenerator = 1; + _cache = NULL; + _device = NULL; } VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device) @@ -64,6 +69,9 @@ VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device) // read the header block, then load up all the header // blocks. + _device = device; + _cache = device->blockCache(); + device->read(2, buffer.get()); init(buffer.get()); @@ -83,8 +91,10 @@ VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device) // now load up all the children. // if this throws, memory could be lost... + try { + for (unsigned i = 1; i < _fileCount; ++i) { std::auto_ptr child; @@ -92,6 +102,7 @@ VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device) child.reset(new FileEntry(buffer.get() + i * 0x1a)); child->setInode(++_inodeGenerator); + child->_parent = this; _files.push_back(child.release()); } } @@ -106,6 +117,7 @@ VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device) throw; } + } VolumeEntry::~VolumeEntry() @@ -115,6 +127,9 @@ VolumeEntry::~VolumeEntry() { if (*iter) delete *iter; } + + // _blockCache does not need deleting. + delete _device; } @@ -145,6 +160,25 @@ FileEntry *VolumeEntry::fileAtIndex(unsigned i) const +void *VolumeEntry::loadBlock(unsigned block) +{ + return _cache->load(block); +} +void VolumeEntry::unloadBlock(unsigned block, bool dirty) +{ + return _cache->unload(block, dirty); +} + +void VolumeEntry::readBlock(unsigned block, void *buffer) +{ + _device->read(block, buffer); +} +void VolumeEntry::writeBlock(unsigned block, void *buffer) +{ + _device->write(block, buffer); +} + + #pragma mark - #pragma mark FileEntry @@ -159,12 +193,12 @@ FileEntry::FileEntry(void *vp) : _modification = DateRec(Read16(vp, 0x18)); _fileSize = 0; - _pageLength = NULL; + _pageSize = NULL; } FileEntry::~FileEntry() { - delete _pageLength; + delete _pageSize; } @@ -208,13 +242,12 @@ unsigned FileEntry::dataFileSize() unsigned FileEntry::textFileSize() { - if (!_pageLength) textInit(); + if (!_pageSize) textInit(); return _fileSize; } -#if 0 @@ -225,7 +258,7 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset) unsigned count = 0; unsigned block = 0; - block = _startBlock + (offset / 512); + block = _firstBlock + (offset / 512); // returned value (count) is equal to size at this point. // (no partial reads). @@ -238,7 +271,7 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset) { unsigned bytes = std::min(offset % 512, size); - _device->read(block++, tmp); + parent()->readBlock(block++, tmp); std::memcpy(buffer, tmp + 512 - bytes, bytes); @@ -253,7 +286,7 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset) while (size >= 512) { - _device->read(block++, buffer); + parent()->readBlock(block++, buffer); buffer += 512; count += 512; @@ -265,7 +298,7 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset) */ if (size) { - _device->read(block, tmp); + parent()->readBlock(block, tmp); std::memcpy(buffer, tmp, size); count += size; @@ -282,30 +315,33 @@ int FileEntry::textRead(uint8_t *buffer, unsigned size, unsigned offset) { unsigned page = 0; unsigned to = 0; - unsigned l = _pageSize.length(); unsigned block; + unsigned l; unsigned count = 0; auto_array tmp; unsigned tmpSize = 0; - if (!_pageLength) textInit(); + if (!_pageSize) textInit(); + + l = _pageSize->size(); // find the first page. for (page = 1; page < l; ++page) { - if (to + _pageSize[page] > offset) + unsigned pageSize = (*_pageSize)[page]; + if (to + pageSize > offset) { break; } - to += _pageSize[i]; + to += pageSize; } --page; - block = _startBlock + 2 + (page * 2); + block = _firstBlock + 2 + (page * 2); // offset not needed anymore, @@ -314,16 +350,18 @@ int FileEntry::textRead(uint8_t *buffer, unsigned size, unsigned offset) while (size) { - unsigned pageSize = _pageSize[page]; - if (pageSize > tmp) + unsigned pageSize = (*_pageSize)[page]; + unsigned bytes = std::min(size, pageSize - offset); + + if (pageSize > tmpSize) { tmp.reset(new uint8_t[pageSize]); tmpSize = pageSize; } - bytes = std::min(size, pageSize - offset); - decodePage(block, tmp.get()); + // can decode straight to buffer if size >= bytes && offset = 0. + textDecodePage(block, tmp.get()); std::memcpy(buffer, tmp.get() + offset, bytes); @@ -348,7 +386,7 @@ unsigned FileEntry::textDecodePage(unsigned block, uint8_t *out) { uint8_t buffer[1024]; unsigned size = 0; - unsigned bytes = readPage(block, buffer); + unsigned bytes = textReadPage(block, buffer); for (unsigned i = 0; i < bytes; ++i) { @@ -361,7 +399,7 @@ unsigned FileEntry::textDecodePage(unsigned block, uint8_t *out) // 16, n -> n-32 spaces. unsigned x = buffer[++i] - 32; - if (out) for(unsigned i = 0; i < x; ++i) *out++ = ' '; + if (out) for (unsigned i = 0; i < x; ++i) *out++ = ' '; size += x; } else @@ -377,17 +415,16 @@ unsigned FileEntry::textDecodePage(unsigned block, uint8_t *out) unsigned FileEntry::textReadPage(unsigned block, uint8_t *in) { // reads up to 2 blocks. - // assumes block within _startBlock ... _endBlock - 1 - unsigned size = 0; + // assumes block within _startBlock ... _lastBlock - 1 - _device->read(block, in); - if (block + 1 == _endBlock) + parent()->readBlock(block, in); + if (block + 1 == _lastBlock) { return _lastByte; } - _device->read(block + 1, in + 512); - if (block +2 == _endBlock) + parent()->readBlock(block + 1, in + 512); + if (block +2 == _lastBlock) { return 512 + _lastByte; } @@ -401,15 +438,14 @@ void FileEntry::textInit() { // calculate the file size and page offsets. - _pageSize.reserve((_endBlock - _startBlock - 2) / 2); + _pageSize->reserve((_lastBlock - _firstBlock + 1 - 2) / 2); _fileSize = 0; - for (unsigned block = _startBlock + 2; block < _endBlock; block += 2) + for (unsigned block = _firstBlock + 2; block < _lastBlock; block += 2) { - unsigned size = decodePage(block, NULL); + unsigned size = textDecodePage(block, NULL); _fileSize += size; - _pageSize.push_back(size); + _pageSize->push_back(size); } } -#endif diff --git a/pascal/File.h b/pascal/File.h index d69bc5e..1190ea0 100644 --- a/pascal/File.h +++ b/pascal/File.h @@ -7,6 +7,7 @@ namespace ProFUSE { class BlockDevice; + class AbstractBlockCache; } namespace Pascal { @@ -25,6 +26,7 @@ enum { }; class FileEntry; +class VolumeEntry; class Entry { @@ -42,6 +44,9 @@ public: unsigned inode() const { return _inode; } void setInode(unsigned inode) { _inode = inode; } + VolumeEntry *parent() { return _parent; } + + protected: Entry(); @@ -53,6 +58,11 @@ protected: unsigned _fileKind; unsigned _inode; + +private: + friend class VolumeEntry; + VolumeEntry *_parent; + }; @@ -70,6 +80,13 @@ public: FileEntry *fileAtIndex(unsigned i) const; + + void *loadBlock(unsigned block); + void unloadBlock(unsigned block, bool dirty = false); + + void readBlock(unsigned block, void *); + void writeBlock(unsigned block, void *); + private: VolumeEntry(); @@ -84,7 +101,9 @@ private: std::vector _files; unsigned _inodeGenerator; - + + ProFUSE::BlockDevice *_device; + ProFUSE::AbstractBlockCache *_cache; }; @@ -122,7 +141,7 @@ class FileEntry : public Entry { unsigned textReadPage(unsigned block, uint8_t *in); unsigned textDecodePage(unsigned block, uint8_t *out); - std::vector *_pageLength; + std::vector *_pageSize; unsigned _fileSize; }; From 15315bad1742d442bdee8a58859d885227dbb7f7 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 11 Dec 2009 03:28:51 +0000 Subject: [PATCH 030/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@141 aa027e90-d47c-11dd-86d7-074df07e0730 --- MappedFile.cpp | 21 ++++++++++++++++----- auto.h | 5 +++-- pascal/File.h | 3 ++- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/MappedFile.cpp b/MappedFile.cpp index 00042d3..3c16710 100644 --- a/MappedFile.cpp +++ b/MappedFile.cpp @@ -75,10 +75,12 @@ MappedFile::MappedFile(const char *name, size_t size) //_map = ::mmap(NULL, _size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, _fd, 0); auto_map map( - fd, + NULL, _size, PROT_READ | PROT_WRITE, - MAP_FILE | MAP_SHARED + MAP_FILE | MAP_SHARED, + fd, + 0 ); if (map == MAP_FAILED) throw POSIXException(__METHOD__ ": Unable to map file.", errno); @@ -117,13 +119,22 @@ void MappedFile::init(int f, bool readOnly) _map = ::mmap(NULL, _size, readOnly ? PROT_READ : PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 0); */ + ::lseek(f, 0, SEEK_SET); + + auto_map map( - f, + NULL, _size, readOnly ? PROT_READ : PROT_READ | PROT_WRITE, - readOnly ? MAP_FILE : MAP_FILE | MAP_SHARED + MAP_FILE | MAP_SHARED, //readOnly ? MAP_FILE : MAP_FILE | MAP_SHARED, + f, + 0 ); - + + /* + _map = ::mmap(NULL, _size, readOnly ? PROT_READ : PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED, f, 0); + */ if (map == MAP_FAILED) throw POSIXException(__METHOD__ ": Unable to map file.", errno); _fd = f; diff --git a/auto.h b/auto.h index d971b68..f23c3c2 100644 --- a/auto.h +++ b/auto.h @@ -73,9 +73,10 @@ private: class auto_map { public: - auto_map(int fd, size_t size, int prot, int flags) : + auto_map(void *addr, size_t size, int prot, int flags, int fd, off_t offset) + : _size(size), - _map(::mmap(NULL, size, prot, flags, fd, 0)) + _map(::mmap(addr, size, prot, flags, fd, offset)) { } ~auto_map() diff --git a/pascal/File.h b/pascal/File.h index 1190ea0..d955525 100644 --- a/pascal/File.h +++ b/pascal/File.h @@ -34,7 +34,7 @@ public: virtual ~Entry(); - unsigned blocks() const { return _firstBlock - _lastBlock; } + unsigned blocks() const { return _lastBlock - _firstBlock; } unsigned firstBlock() const { return _firstBlock; } unsigned lastBlock() const { return _lastBlock; } @@ -75,6 +75,7 @@ public: const char *name() const { return _fileName; } unsigned fileCount() const { return _fileCount; } + unsigned volumeBlocks() const { return _lastVolumeBlock; } Pascal::DateRec lastBoot() const { return _lastBoot; } From acd4072872c00e3bf1278d7c516d2b83b7f4400c Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 11 Dec 2009 04:03:21 +0000 Subject: [PATCH 031/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@143 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/DateRec.cpp | 4 +- pascal/File.cpp | 8 ++- pascal/File.h | 3 + pascal/FileMan.cpp | 149 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 pascal/FileMan.cpp diff --git a/pascal/DateRec.cpp b/pascal/DateRec.cpp index 3f42f5f..7a8bd7d 100644 --- a/pascal/DateRec.cpp +++ b/pascal/DateRec.cpp @@ -8,8 +8,8 @@ using namespace Pascal; DateRec::DateRec(unsigned val) { // yyyy yyym mmmm dddd - _day = val & 0xf; - _month = (val >> 4) & 0x1f; + _month = val & 0xf; + _day = (val >> 4) & 0x1f; _year = (val >> 9) & 0x7f; } diff --git a/pascal/File.cpp b/pascal/File.cpp index 7a3e380..efc3b7c 100644 --- a/pascal/File.cpp +++ b/pascal/File.cpp @@ -77,7 +77,12 @@ VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device) init(buffer.get()); // todo -- verify reasonable values. + + //printf("%u %u\n", blocks(), _lastBlock - _firstBlock); + + // why the fuck didn't this work???? blockCount = blocks(); + if (blockCount > 1) { buffer.reset(new uint8_t[512 * blockCount]); @@ -95,10 +100,11 @@ VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device) try { - for (unsigned i = 1; i < _fileCount; ++i) + for (unsigned i = 1; i <= _fileCount; ++i) { std::auto_ptr child; + // child.reset(new FileEntry(buffer.get() + i * 0x1a)); child->setInode(++_inodeGenerator); diff --git a/pascal/File.h b/pascal/File.h index d955525..297986b 100644 --- a/pascal/File.h +++ b/pascal/File.h @@ -115,6 +115,9 @@ class FileEntry : public Entry { virtual ~FileEntry(); unsigned fileSize(); + + unsigned lastByte() const { return _lastByte; } + int read(uint8_t *buffer, unsigned size, unsigned offset); const char *name() const { return _fileName; } diff --git a/pascal/FileMan.cpp b/pascal/FileMan.cpp new file mode 100644 index 0000000..0452653 --- /dev/null +++ b/pascal/FileMan.cpp @@ -0,0 +1,149 @@ +/* + * FileMan utilities. + * + * L - list dir + * E - + */ + + +#include +#include +#include + +#include "File.h" +#include "DateRec.h" +#include "../BlockDevice.h" + + +const char *MonthName(unsigned m) +{ + static const char *months[] = { + "", + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + }; + + if (m > 12) return ""; + return months[m]; +} + +const char *FileType(unsigned ft) +{ + static const char *types[] = { + "Unknown", + "Badblocks", + "Codefile", + "Textfile", + "Infofile", + "Datafile", + "Graffile", + "Fotofile", + "SecureDir" + + }; + + if (ft < 8) return types[ft]; + + return ""; +} + +void list(Pascal::VolumeEntry *volume, bool extended) +{ + unsigned fileCount = volume->fileCount(); + unsigned used = volume->blocks(); + unsigned max = 0; + + std::fprintf(stdout, "%s:\n", volume->name()); + + for (unsigned i = 0; i < fileCount; ++i) + { + Pascal::FileEntry *e = volume->fileAtIndex(i); + if (!e) continue; + + Pascal::DateRec dt = e->modification(); + + //TODO -- include gaps. + + if (extended) + { + + std::fprintf(stdout, "%-15s %4u %2u-%s-%2u %5u %5u %s\n", + e->name(), + e->blocks(), + dt.day(), + MonthName(dt.month()), + dt.year() % 100, + e->firstBlock(), + e->lastByte(), + FileType(e->fileKind()) + ); + + } + else + { + std::fprintf(stdout, "%-15s %4u %2u-%s-%2u\n", + e->name(), + e->blocks(), + dt.day(), + MonthName(dt.month()), + dt.year() % 100 + ); + } + used += e->blocks(); + max = std::max(max, e->blocks()); + } + // TODO -- largest refers to largest unused block, + // not the largest file. + + std::fprintf(stdout, + "%u/%u files, " + "%u blocks used, " + "%u unused, " + "%u in largest\n", + fileCount, fileCount, + used, + volume->volumeBlocks() - used, + max + ); + + +} + + +int main(int argc, char **argv) +{ + std::auto_ptr volume; + std::auto_ptr device; + + + const char *file = argv[1]; + + try { + + device.reset( new ProFUSE::DOSOrderDiskImage(file, true)); + + volume.reset( new Pascal::VolumeEntry(device.get())); + + device.release(); + + list(volume.get(), true); + + } + catch (ProFUSE::Exception& e) + { + std::fprintf(stderr, "%s\n", e.what()); + std::fprintf(stderr, "%s\n", strerror(e.error())); + } + + +} \ No newline at end of file From 0c14721b0df0a114f44c27d868703b127eecc9ed Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 11 Dec 2009 05:31:13 +0000 Subject: [PATCH 032/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@144 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/FileMan.cpp | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/pascal/FileMan.cpp b/pascal/FileMan.cpp index 0452653..47f0afe 100644 --- a/pascal/FileMan.cpp +++ b/pascal/FileMan.cpp @@ -57,11 +57,18 @@ const char *FileType(unsigned ft) return ""; } +void printUnusedRecord(unsigned block, unsigned size) +{ + std::printf("< UNUSED > %4u %4u\n", size, block); +} + void list(Pascal::VolumeEntry *volume, bool extended) { unsigned fileCount = volume->fileCount(); unsigned used = volume->blocks(); unsigned max = 0; + unsigned volumeSize = volume->volumeBlocks(); + unsigned lastBlock = volume->lastBlock(); std::fprintf(stdout, "%s:\n", volume->name()); @@ -74,10 +81,22 @@ void list(Pascal::VolumeEntry *volume, bool extended) //TODO -- include gaps. + if (lastBlock != e->firstBlock()) + { + unsigned size = e->firstBlock() - lastBlock; + max = std::max(max, size); + + if (extended) + { + printUnusedRecord(lastBlock, size); + } + } + lastBlock = e->lastBlock(); + if (extended) { - std::fprintf(stdout, "%-15s %4u %2u-%s-%2u %5u %5u %s\n", + std::printf("%-15s %4u %2u-%s-%2u %5u %5u %s\n", e->name(), e->blocks(), dt.day(), @@ -91,7 +110,7 @@ void list(Pascal::VolumeEntry *volume, bool extended) } else { - std::fprintf(stdout, "%-15s %4u %2u-%s-%2u\n", + std::printf("%-15s %4u %2u-%s-%2u\n", e->name(), e->blocks(), dt.day(), @@ -100,10 +119,13 @@ void list(Pascal::VolumeEntry *volume, bool extended) ); } used += e->blocks(); - max = std::max(max, e->blocks()); } - // TODO -- largest refers to largest unused block, - // not the largest file. + + if (extended && (lastBlock != volumeSize)) + { + printUnusedRecord(lastBlock, volumeSize - lastBlock); + } + std::fprintf(stdout, "%u/%u files, " @@ -112,10 +134,10 @@ void list(Pascal::VolumeEntry *volume, bool extended) "%u in largest\n", fileCount, fileCount, used, - volume->volumeBlocks() - used, + volumeSize- used, max ); - + } From 8d93501d0d296446964f1dab084184cb1a31e04b Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 11 Dec 2009 14:47:44 +0000 Subject: [PATCH 033/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@145 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/FileMan.cpp | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/pascal/FileMan.cpp b/pascal/FileMan.cpp index 47f0afe..5bfec89 100644 --- a/pascal/FileMan.cpp +++ b/pascal/FileMan.cpp @@ -10,6 +10,8 @@ #include #include +#include + #include "File.h" #include "DateRec.h" #include "../BlockDevice.h" @@ -142,11 +144,46 @@ void list(Pascal::VolumeEntry *volume, bool extended) } +void usage() +{ + std::printf( + "Pascal File Manager v 0.0\n\n" + "Usage: fileman [-h] [-f format] action diskimage\n" + "Options:\n" + " -h Show usage information.\n" + " -f format Specify disk format. Valid values are:\n" + " po: ProDOS order disk image\n" + " do: DOS Order disk image\n" + "\n" + "Actions:\n" + " L List files\n" + " E List files (extended)\n" + ); + +} + int main(int argc, char **argv) { std::auto_ptr volume; std::auto_ptr device; + std::string format; + + while ((int c = ::getopt(argc, argv, "f:h")) != -1) + { + switch(c) + { + case 'f': + format = optarg; + break; + + case 'h': + case '?': + usage(); + exit(); + } + } + const char *file = argv[1]; From 6bbeb86da3da4e3ec92d5bbcbfa7fd5eb5fa446a Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 11 Dec 2009 15:03:04 +0000 Subject: [PATCH 034/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@146 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/FileMan.cpp | 47 +++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/pascal/FileMan.cpp b/pascal/FileMan.cpp index 5bfec89..2569414 100644 --- a/pascal/FileMan.cpp +++ b/pascal/FileMan.cpp @@ -7,10 +7,14 @@ #include +#include +#include + #include #include #include +#include #include "File.h" #include "DateRec.h" @@ -64,7 +68,7 @@ void printUnusedRecord(unsigned block, unsigned size) std::printf("< UNUSED > %4u %4u\n", size, block); } -void list(Pascal::VolumeEntry *volume, bool extended) +int list(Pascal::VolumeEntry *volume, bool extended) { unsigned fileCount = volume->fileCount(); unsigned used = volume->blocks(); @@ -125,7 +129,9 @@ void list(Pascal::VolumeEntry *volume, bool extended) if (extended && (lastBlock != volumeSize)) { - printUnusedRecord(lastBlock, volumeSize - lastBlock); + unsigned size = volumeSize - lastBlock; + max = std::max(max, size); + printUnusedRecord(lastBlock, size); } @@ -140,6 +146,7 @@ void list(Pascal::VolumeEntry *volume, bool extended) max ); + return 0; } @@ -148,7 +155,7 @@ void usage() { std::printf( "Pascal File Manager v 0.0\n\n" - "Usage: fileman [-h] [-f format] action diskimage\n" + "Usage: fileman [-h] [-f format] diskimage action\n" "Options:\n" " -h Show usage information.\n" " -f format Specify disk format. Valid values are:\n" @@ -166,11 +173,13 @@ int main(int argc, char **argv) { std::auto_ptr volume; std::auto_ptr device; + int c; std::string format; - while ((int c = ::getopt(argc, argv, "f:h")) != -1) + while ((c = ::getopt(argc, argv, "f:h")) != -1) { + std::printf("%c\n", c); switch(c) { case 'f': @@ -180,23 +189,35 @@ int main(int argc, char **argv) case 'h': case '?': usage(); - exit(); + std::exit(0); } } + + argc -= optind; + argv += optind; - const char *file = argv[1]; + if (argc != 2) + { + usage(); + std::exit(1); + } + + + const char *file = argv[0]; + const char *action = argv[1]; try { - device.reset( new ProFUSE::DOSOrderDiskImage(file, true)); - - volume.reset( new Pascal::VolumeEntry(device.get())); - - device.release(); - - list(volume.get(), true); + device.reset( new ProFUSE::DOSOrderDiskImage(file, true)); + + volume.reset( new Pascal::VolumeEntry(device.get())); + + device.release(); + if (!::strcasecmp("E", action)) return list(volume.get(), true); + if (!::strcasecmp("L", action)) return list(volume.get(), false); + } catch (ProFUSE::Exception& e) { From d0960d1266f053c53b486ffd6d60e0eefda1fa75 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 12 Dec 2009 04:43:47 +0000 Subject: [PATCH 035/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@149 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/FileMan.cpp | 147 +++++++++++++++++++++++++++++++++------------ 1 file changed, 108 insertions(+), 39 deletions(-) diff --git a/pascal/FileMan.cpp b/pascal/FileMan.cpp index 2569414..a6a66a2 100644 --- a/pascal/FileMan.cpp +++ b/pascal/FileMan.cpp @@ -19,6 +19,46 @@ #include "File.h" #include "DateRec.h" #include "../BlockDevice.h" +#include "../DiskCopy42Image.h" + + +unsigned parseFormat(const char *type, unsigned defv = 0) +{ + if (type == 0 || *type == 0) return defv; + + if (::strcasecmp(type, "2mg") == 0) + return '2IMG'; + if (::strcasecmp(type, "2img") == 0) + return '2IMG'; + if (::strcasecmp(type, "dc42") == 0) + return 'DC42'; + if (::strcasecmp(type, "po") == 0) + return 'PO__'; + if (::strcasecmp(type, "do") == 0) + return 'DO__'; + if (::strcasecmp(type, "dsk") == 0) + return 'DO__'; + if (::strcasecmp(type, "davex") == 0) + return 'DVX_'; + + return defv; +} + +// return the filename extension, NULL if none. +const char *extname(const char *src) +{ + if (!src) return NULL; + unsigned l = std::strlen(src); + + for (unsigned i = 0; i < l; ++i) + { + char c = src[l - 1 - i]; + if (c == '/') return NULL; + if (c == '.') return src + l - i; + } + + return NULL; +} const char *MonthName(unsigned m) @@ -63,11 +103,42 @@ const char *FileType(unsigned ft) return ""; } -void printUnusedRecord(unsigned block, unsigned size) +void printUnusedEntry(unsigned block, unsigned size) { std::printf("< UNUSED > %4u %4u\n", size, block); } +void printFileEntry(Pascal::FileEntry *e, bool extended) +{ + Pascal::DateRec dt = e->modification(); + + if (extended) + { + std::printf("%-15s %4u %2u-%s-%2u %5u %5u %s\n", + e->name(), + e->blocks(), + dt.day(), + MonthName(dt.month()), + dt.year() % 100, + e->firstBlock(), + e->lastByte(), + FileType(e->fileKind()) + ); + + } + else + { + std::printf("%-15s %4u %2u-%s-%2u\n", + e->name(), + e->blocks(), + dt.day(), + MonthName(dt.month()), + dt.year() % 100 + ); + } + +} + int list(Pascal::VolumeEntry *volume, bool extended) { unsigned fileCount = volume->fileCount(); @@ -83,9 +154,6 @@ int list(Pascal::VolumeEntry *volume, bool extended) Pascal::FileEntry *e = volume->fileAtIndex(i); if (!e) continue; - Pascal::DateRec dt = e->modification(); - - //TODO -- include gaps. if (lastBlock != e->firstBlock()) { @@ -94,36 +162,13 @@ int list(Pascal::VolumeEntry *volume, bool extended) if (extended) { - printUnusedRecord(lastBlock, size); + printUnusedEntry(lastBlock, size); } } + + printFileEntry(e, extended); + lastBlock = e->lastBlock(); - - if (extended) - { - - std::printf("%-15s %4u %2u-%s-%2u %5u %5u %s\n", - e->name(), - e->blocks(), - dt.day(), - MonthName(dt.month()), - dt.year() % 100, - e->firstBlock(), - e->lastByte(), - FileType(e->fileKind()) - ); - - } - else - { - std::printf("%-15s %4u %2u-%s-%2u\n", - e->name(), - e->blocks(), - dt.day(), - MonthName(dt.month()), - dt.year() % 100 - ); - } used += e->blocks(); } @@ -131,7 +176,7 @@ int list(Pascal::VolumeEntry *volume, bool extended) { unsigned size = volumeSize - lastBlock; max = std::max(max, size); - printUnusedRecord(lastBlock, size); + printUnusedEntry(lastBlock, size); } @@ -142,12 +187,11 @@ int list(Pascal::VolumeEntry *volume, bool extended) "%u in largest\n", fileCount, fileCount, used, - volumeSize- used, + volumeSize - used, max ); return 0; - } @@ -155,7 +199,7 @@ void usage() { std::printf( "Pascal File Manager v 0.0\n\n" - "Usage: fileman [-h] [-f format] diskimage action\n" + "Usage: fileman [-h] [-f format] action diskimage\n" "Options:\n" " -h Show usage information.\n" " -f format Specify disk format. Valid values are:\n" @@ -173,9 +217,13 @@ int main(int argc, char **argv) { std::auto_ptr volume; std::auto_ptr device; + + const char *format = NULL; + unsigned fmt = 0; + int c; - std::string format; + while ((c = ::getopt(argc, argv, "f:h")) != -1) { @@ -204,12 +252,33 @@ int main(int argc, char **argv) } - const char *file = argv[0]; - const char *action = argv[1]; + const char *file = argv[1]; + const char *action = argv[0]; + + if (format == NULL) format = extname(file); + + fmt = parseFormat(format, 'PO__'); + try { - device.reset( new ProFUSE::DOSOrderDiskImage(file, true)); + switch(fmt) + { + case 'DO__': + device.reset( new ProFUSE::DOSOrderDiskImage(file, true) ); + break; + case 'PO__': + device.reset( new ProFUSE::ProDOSOrderDiskImage(file, true) ); + break; + case 'DC42': + device.reset( new ProFUSE::DiskCopy42Image(file, true) ); + break; + + default: + std::fprintf(stderr, "Unable to determine format. Please use -f flag.\n"); + exit(2); + } + volume.reset( new Pascal::VolumeEntry(device.get())); From 72a5a28745fbbc8ab85324cc6838c45c1bf2eb77 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 12 Dec 2009 04:44:16 +0000 Subject: [PATCH 036/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@150 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/{DateRec.cpp => Date.cpp} | 0 pascal/{DateRec.h => Date.h} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename pascal/{DateRec.cpp => Date.cpp} (100%) rename pascal/{DateRec.h => Date.h} (100%) diff --git a/pascal/DateRec.cpp b/pascal/Date.cpp similarity index 100% rename from pascal/DateRec.cpp rename to pascal/Date.cpp diff --git a/pascal/DateRec.h b/pascal/Date.h similarity index 100% rename from pascal/DateRec.h rename to pascal/Date.h From 147a16085a1303d291a9152fd01eb31cdf3c2826 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 12 Dec 2009 04:51:53 +0000 Subject: [PATCH 037/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@151 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/Date.cpp | 21 ++++++++++++++++++--- pascal/Date.h | 19 +++++++++++-------- pascal/File.cpp | 4 ++-- pascal/File.h | 10 +++++----- pascal/FileMan.cpp | 4 ++-- 5 files changed, 38 insertions(+), 20 deletions(-) diff --git a/pascal/Date.cpp b/pascal/Date.cpp index 7a8bd7d..6efcb0d 100644 --- a/pascal/Date.cpp +++ b/pascal/Date.cpp @@ -1,11 +1,11 @@ -#include "DateRec.h" +#include "Date.h" #include using namespace Pascal; -DateRec::DateRec(unsigned val) +Date::Date(unsigned val) { // yyyy yyym mmmm dddd _month = val & 0xf; @@ -13,7 +13,7 @@ DateRec::DateRec(unsigned val) _year = (val >> 9) & 0x7f; } -DateRec::operator std::time_t() const { +Date::operator std::time_t() const { struct tm tm; if (_day == 0 || _month == 0) return (std::time_t)-1; @@ -26,4 +26,19 @@ DateRec::operator std::time_t() const { tm.tm_isdst = -1; return std::mktime(&tm); +} + +Date::operator unsigned() 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, tm.tm_month, tm.tm_mday); } \ No newline at end of file diff --git a/pascal/Date.h b/pascal/Date.h index 8f9e2e4..510aa73 100644 --- a/pascal/Date.h +++ b/pascal/Date.h @@ -1,18 +1,21 @@ -#ifndef __DATEREC_H__ -#define __DATEREC_H__ +#ifndef __PASCAL_DATE_H__ +#define __PASCAL_DATE_H__ #include namespace Pascal { -class DateRec { +class Date { public: - DateRec(); - DateRec(unsigned yy, unsigned mm, unsigned dd); - DateRec(unsigned); + static Date Today(); + + Date(); + Date(unsigned yy, unsigned mm, unsigned dd); + Date(unsigned); operator std::time_t() const; + operator unsigned() const; unsigned month() const { return _month; } unsigned day() const { return _day; } @@ -25,14 +28,14 @@ private: }; -inline DateRec::DateRec() +inline Date::Date() { _year = 0; _month = 0; _day = 0; } -inline DateRec::DateRec(unsigned yy, unsigned mm, unsigned dd) +inline Date::Date(unsigned yy, unsigned mm, unsigned dd) { _year = yy; _month = mm; diff --git a/pascal/File.cpp b/pascal/File.cpp index efc3b7c..7e73cda 100644 --- a/pascal/File.cpp +++ b/pascal/File.cpp @@ -152,7 +152,7 @@ void VolumeEntry::init(void *vp) _lastVolumeBlock = Read16(vp, 0x0e); _fileCount = Read16(vp, 0x10); _accessTime = Read16(vp, 0x12); - _lastBoot = DateRec(Read16(vp, 0x14)); + _lastBoot = Date(Read16(vp, 0x14)); setInode(1); _inodeGenerator = 1; @@ -196,7 +196,7 @@ FileEntry::FileEntry(void *vp) : std::memset(_fileName, 0, 16); std::memcpy(_fileName, 0x07 + (uint8_t *)vp, _fileNameLength); _lastByte = Read16(vp, 0x16); - _modification = DateRec(Read16(vp, 0x18)); + _modification = Date(Read16(vp, 0x18)); _fileSize = 0; _pageSize = NULL; diff --git a/pascal/File.h b/pascal/File.h index 297986b..66c2c8b 100644 --- a/pascal/File.h +++ b/pascal/File.h @@ -1,7 +1,7 @@ #ifndef __FILE_H__ #define __FILE_H__ -#include "DateRec.h" +#include "Date.h" #include @@ -77,7 +77,7 @@ public: unsigned fileCount() const { return _fileCount; } unsigned volumeBlocks() const { return _lastVolumeBlock; } - Pascal::DateRec lastBoot() const { return _lastBoot; } + Pascal::Date lastBoot() const { return _lastBoot; } FileEntry *fileAtIndex(unsigned i) const; @@ -98,7 +98,7 @@ private: unsigned _lastVolumeBlock; unsigned _fileCount; unsigned _accessTime; - Pascal::DateRec _lastBoot; + Pascal::Date _lastBoot; std::vector _files; unsigned _inodeGenerator; @@ -121,7 +121,7 @@ class FileEntry : public Entry { int read(uint8_t *buffer, unsigned size, unsigned offset); const char *name() const { return _fileName; } - DateRec modification() const { return _modification; } + Date modification() const { return _modification; } protected: @@ -131,7 +131,7 @@ class FileEntry : public Entry { char _fileName[16]; unsigned _lastByte; - DateRec _modification; + Date _modification; // non-text files unsigned dataFileSize(); diff --git a/pascal/FileMan.cpp b/pascal/FileMan.cpp index a6a66a2..f06ca52 100644 --- a/pascal/FileMan.cpp +++ b/pascal/FileMan.cpp @@ -17,7 +17,7 @@ #include #include "File.h" -#include "DateRec.h" +#include "Date.h" #include "../BlockDevice.h" #include "../DiskCopy42Image.h" @@ -110,7 +110,7 @@ void printUnusedEntry(unsigned block, unsigned size) void printFileEntry(Pascal::FileEntry *e, bool extended) { - Pascal::DateRec dt = e->modification(); + Pascal::Date dt = e->modification(); if (extended) { From e3ef4d7c104a7c7b4f47c71163ae6833e652f850 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 12 Dec 2009 15:26:51 +0000 Subject: [PATCH 038/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@152 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/File.cpp | 163 ++++++++++++++++++++++++++++++++++++++++++++++ pascal/File.h | 32 ++++++++- pascal/IOBuffer.h | 70 ++++++++++++++++++++ 3 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 pascal/IOBuffer.h diff --git a/pascal/File.cpp b/pascal/File.cpp index 7e73cda..7834a4e 100644 --- a/pascal/File.cpp +++ b/pascal/File.cpp @@ -4,6 +4,8 @@ #include "../BlockDevice.h" #include "../BlockCache.h" +#include "IOBuffer.h" + #include #include #include @@ -11,9 +13,54 @@ using namespace LittleEndian; using namespace Pascal; +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; } + + + #pragma mark - #pragma mark DirEntry +unsigned Entry::ValidName(const char *cp, unsigned maxLength) +{ + unsigned length; + + if (!cp || !*cp) return 0; + + if (!isalpaha(*cp)) return 0; + + for (length = 1; cp[length]; ++length) + { + if (length >= maxLength) return 0; + + if (!isalnumdot(cp[length])) return 0; + } + + return length; + +} + Entry::Entry() { _firstBlock = 0; @@ -42,10 +89,22 @@ void Entry::init(void *vp) _inode = 0; } +void Entry::writeDirectoryEntry(IOBuffer *b) +{ + b->write16(_firstBlock); + b->write16(_lastBlock); + b->write8(_fileKind); +} + #pragma mark - #pragma mark VolumeEntry +unsigned VolumeEntry::ValidName(const char *cp) +{ + return Entry::ValidName(cp, 7); +} + VolumeEntry::VolumeEntry() { _fileNameLength = 0; @@ -61,6 +120,54 @@ VolumeEntry::VolumeEntry() _device = NULL; } +VolumeEntry::VolumeEntry(const char *name, ProFUSE::BlockDevice *device) +{ +#undef __METHOD__ +#define __METHOD__ "VolumeEntry::VolumeEntry" + + unsigned length; + length = ValidName(name); + + if (!length) + throw Exception(__METHOD__ ": Invalid volume name."); + + _firstBlock = 2; + _lastBlock = 6; + _fileKind = kUntypedFile; + _inode = 1; + _inodeGenerator = 1; + + _fileNameLength = length; + + std::memset(_fileName, 0, sizeof(_fileName)); + for (unsigned i = 0; i < _fileNameLength; ++i) + { + _fileName[i] = toupper(name[i]); + } + + _lastVolumeBlock = device->blocks(); + _fileCount = 0; + _accessTime = 0; + _lastBoot = Date.Today(); + + _cache = device->blockCache(); + _device = device; + + for (unsigned i = 2; i < 6; ++i) + { + device->zeroBlock(i); + } + + void *vp = _blockCache->lock(2); + IOBuffer b(vp, 0x1a); + + write(&b); + + _blockCache->unlock(2, true); + +} + + VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device) { auto_array buffer(new uint8_t[512]); @@ -185,9 +292,30 @@ void VolumeEntry::writeBlock(unsigned block, void *buffer) } + +void VolumeEntry::writeDirectoryEntry(IOBuffer *b) +{ + Entry::writeDirectoryEntry(b); + + b->write8(0); // reserved + b->write8(_fileNameLength); + b->writeBytes(_fileName, 7); + b->write16(_fileCount); + b->write16(_accessTime); + b->write16((unsigned)_lastBoot); + + // rest is reserved. + b->writeZero(4); +} + #pragma mark - #pragma mark FileEntry +unsigned FileEntry::ValidName(const char *cp) +{ + return Entry::ValidName(cp, 15); +} + FileEntry::FileEntry(void *vp) : Entry(vp) { @@ -202,6 +330,31 @@ FileEntry::FileEntry(void *vp) : _pageSize = NULL; } +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 = kind; + _status = 0; + + _fileNameLength = length; + std::memset(_fileName, 0, sizeof(_fileName)); + for (unsigned i = 0; i < length; ++i) + _fileName[i] = toupper(name[i]); + + _modification = Date::Today(); + _lastByte = 0; + + _fileSize = 0; + _pageSize = NULL; +} + FileEntry::~FileEntry() { delete _pageSize; @@ -221,6 +374,16 @@ unsigned FileEntry::fileSize() } } +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) { diff --git a/pascal/File.h b/pascal/File.h index 66c2c8b..453126f 100644 --- a/pascal/File.h +++ b/pascal/File.h @@ -10,6 +10,10 @@ namespace ProFUSE { class AbstractBlockCache; } +namespace LittleEndian { + class IOBuffer; +} + namespace Pascal { @@ -48,6 +52,10 @@ public: protected: + + unsigned static ValidName(const char *name, unsigned maxSize); + + virtual void writeDirectoryEntry(LittleEndian::IOBuffer *); Entry(); Entry(void *); @@ -70,6 +78,10 @@ class VolumeEntry : public Entry { public: + // create new + VolumeEntry(const char *name, ProFUSE::BlockDevice *); + + // open existing VolumeEntry(ProFUSE::BlockDevice *); virtual ~VolumeEntry(); @@ -80,6 +92,9 @@ public: Pascal::Date lastBoot() const { return _lastBoot; } FileEntry *fileAtIndex(unsigned i) const; + + void addChild(FileEntry *child, unsigned blocks); + void *loadBlock(unsigned block); @@ -88,6 +103,12 @@ public: void readBlock(unsigned block, void *); void writeBlock(unsigned block, void *); + + static ValidName(const char *); + +protected: + virtual void writeDirectoryEntry(LittleEndian::IOBuffer *); + private: VolumeEntry(); @@ -111,6 +132,7 @@ private: class FileEntry : public Entry { public: + FileEntry(const char *name, unsigned fileKind); FileEntry(void *vp); virtual ~FileEntry(); @@ -118,13 +140,21 @@ class FileEntry : public Entry { unsigned lastByte() const { return _lastByte; } - int read(uint8_t *buffer, unsigned size, unsigned offset); + int read(uint8_t *buffer, unsigned size, unsigned offset); + int write(uint8_t *buffer, unsigned size, unsigned offset); const char *name() const { return _fileName; } Date modification() const { return _modification; } + static ValidName(const char *); + + protected: + virtual void writeDirectoryEntry(LittleEndian::IOBuffer *); + + private: + unsigned _status; unsigned _fileNameLength; diff --git a/pascal/IOBuffer.h b/pascal/IOBuffer.h new file mode 100644 index 0000000..842a65b --- /dev/null +++ b/pascal/IOBuffer.h @@ -0,0 +1,70 @@ +#ifndef __IOBUFFER_H__ +#define __IOBUFFER_H__ + +#include "../Endian.h" + +namespace LittleEndian { + + class IOBuffer { + public: + + IOBuffer(void *vp, unsigned size) + { + _buffer = vp; + _size = size; + _offset = 0; + } + + void write8(uint8_t value) + { + Write8(_buffer, _offset, value); + _offset += 1; + } + void write16(uint16_t value) + { + Write16(_buffer, _offset, value); + _offset += 2; + } + + void write24(uint32_t value) + { + Write24(_buffer, _offset, value); + _offset += 3; + } + void write32(uint32_t value) + { + Write32(_buffer, _offset, value); + _offset += 4; + } + + void writeBytes(const void *value, unsigned count); + { + std::memcpy(_offset + (uint8_t *)_buffer, value, count); + _size += count; + } + + void writeZero(unsigned count) + { + uint8_t *cp = _offset + (uint8_t *)_buffer; + for (unsigned i = 0; i < count; ++i) + { + cp[i] = 0; + } + _offset += count; + } + + unsigned offset() const { return _offset; } + void setOffset(unsigned offset) { _offset = offset; } + + unsinged size() const { return _size; } + + private: + void *_buffer; + unsigned _size; + unsigned _offset; + + }; + +} + +#endif \ No newline at end of file From 05e13f91a5ba0f3649265df1cbd7ecad7147a74a Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 12 Dec 2009 15:38:12 +0000 Subject: [PATCH 039/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@153 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/Date.cpp | 5 +++-- pascal/Date.h | 3 ++- pascal/File.cpp | 19 ++++++++++--------- pascal/File.h | 6 +++--- pascal/IOBuffer.h | 5 +++-- 5 files changed, 21 insertions(+), 17 deletions(-) diff --git a/pascal/Date.cpp b/pascal/Date.cpp index 6efcb0d..5ccb29d 100644 --- a/pascal/Date.cpp +++ b/pascal/Date.cpp @@ -1,5 +1,6 @@ #include "Date.h" #include +#include using namespace Pascal; @@ -28,7 +29,7 @@ Date::operator std::time_t() const { return std::mktime(&tm); } -Date::operator unsigned() const { +Date::operator uint16_t() const { // year must be 0 .. 127 return (_year << 9) | (_day << 4) | _month; } @@ -40,5 +41,5 @@ Date Date::Today() ::localtime_r(&t, &tm); - return Date(tm.tm_year, tm.tm_month, tm.tm_mday); + return Date(tm.tm_year, tm.tm_mon, tm.tm_mday); } \ No newline at end of file diff --git a/pascal/Date.h b/pascal/Date.h index 510aa73..6387a80 100644 --- a/pascal/Date.h +++ b/pascal/Date.h @@ -2,6 +2,7 @@ #define __PASCAL_DATE_H__ #include +#include namespace Pascal { @@ -15,7 +16,7 @@ public: Date(unsigned); operator std::time_t() const; - operator unsigned() const; + operator uint16_t() const; unsigned month() const { return _month; } unsigned day() const { return _day; } diff --git a/pascal/File.cpp b/pascal/File.cpp index 7834a4e..adea791 100644 --- a/pascal/File.cpp +++ b/pascal/File.cpp @@ -3,6 +3,7 @@ #include "../Endian.h" #include "../BlockDevice.h" #include "../BlockCache.h" +#include "../Exception.h" #include "IOBuffer.h" @@ -48,7 +49,7 @@ unsigned Entry::ValidName(const char *cp, unsigned maxLength) if (!cp || !*cp) return 0; - if (!isalpaha(*cp)) return 0; + if (!isalpha(*cp)) return 0; for (length = 1; cp[length]; ++length) { @@ -129,7 +130,7 @@ VolumeEntry::VolumeEntry(const char *name, ProFUSE::BlockDevice *device) length = ValidName(name); if (!length) - throw Exception(__METHOD__ ": Invalid volume name."); + throw ProFUSE::Exception(__METHOD__ ": Invalid volume name."); _firstBlock = 2; _lastBlock = 6; @@ -148,7 +149,7 @@ VolumeEntry::VolumeEntry(const char *name, ProFUSE::BlockDevice *device) _lastVolumeBlock = device->blocks(); _fileCount = 0; _accessTime = 0; - _lastBoot = Date.Today(); + _lastBoot = Date::Today(); _cache = device->blockCache(); _device = device; @@ -158,12 +159,12 @@ VolumeEntry::VolumeEntry(const char *name, ProFUSE::BlockDevice *device) device->zeroBlock(i); } - void *vp = _blockCache->lock(2); + void *vp = _cache->load(2); IOBuffer b(vp, 0x1a); - write(&b); + writeDirectoryEntry(&b); - _blockCache->unlock(2, true); + _cache->unload(2, true); } @@ -302,7 +303,7 @@ void VolumeEntry::writeDirectoryEntry(IOBuffer *b) b->writeBytes(_fileName, 7); b->write16(_fileCount); b->write16(_accessTime); - b->write16((unsigned)_lastBoot); + b->write16(_lastBoot); // rest is reserved. b->writeZero(4); @@ -338,9 +339,9 @@ FileEntry::FileEntry(const char *name, unsigned fileKind) unsigned length = ValidName(name); if (!length) - throw Exception(__METHOD__ ": Invalid file name."); + throw ProFUSE::Exception(__METHOD__ ": Invalid file name."); - _fileKind = kind; + _fileKind = fileKind; _status = 0; _fileNameLength = length; diff --git a/pascal/File.h b/pascal/File.h index 453126f..4464f2c 100644 --- a/pascal/File.h +++ b/pascal/File.h @@ -53,7 +53,7 @@ public: protected: - unsigned static ValidName(const char *name, unsigned maxSize); + static unsigned ValidName(const char *name, unsigned maxSize); virtual void writeDirectoryEntry(LittleEndian::IOBuffer *); @@ -104,7 +104,7 @@ public: void writeBlock(unsigned block, void *); - static ValidName(const char *); + unsigned static ValidName(const char *); protected: virtual void writeDirectoryEntry(LittleEndian::IOBuffer *); @@ -146,7 +146,7 @@ class FileEntry : public Entry { const char *name() const { return _fileName; } Date modification() const { return _modification; } - static ValidName(const char *); + unsigned static ValidName(const char *); protected: diff --git a/pascal/IOBuffer.h b/pascal/IOBuffer.h index 842a65b..ea3991e 100644 --- a/pascal/IOBuffer.h +++ b/pascal/IOBuffer.h @@ -3,6 +3,7 @@ #include "../Endian.h" +#include namespace LittleEndian { class IOBuffer { @@ -37,7 +38,7 @@ namespace LittleEndian { _offset += 4; } - void writeBytes(const void *value, unsigned count); + void writeBytes(const void *value, unsigned count) { std::memcpy(_offset + (uint8_t *)_buffer, value, count); _size += count; @@ -56,7 +57,7 @@ namespace LittleEndian { unsigned offset() const { return _offset; } void setOffset(unsigned offset) { _offset = offset; } - unsinged size() const { return _size; } + unsigned size() const { return _size; } private: void *_buffer; From e8c1af2d2c1f51c301e368b6d975fb05e7fe4a17 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 12 Dec 2009 19:27:08 +0000 Subject: [PATCH 040/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@159 aa027e90-d47c-11dd-86d7-074df07e0730 --- BlockCache.cpp | 13 +++++++++--- pascal/Date.cpp | 3 +-- pascal/File.cpp | 54 +++++++++++++++++++++++++++++++++++------------ pascal/IOBuffer.h | 2 +- 4 files changed, 52 insertions(+), 20 deletions(-) diff --git a/BlockCache.cpp b/BlockCache.cpp index f2a955a..8971383 100644 --- a/BlockCache.cpp +++ b/BlockCache.cpp @@ -4,7 +4,7 @@ #include #include - +#include #include "BlockDevice.h" #include "BlockCache.h" @@ -34,7 +34,7 @@ AbstractBlockCache::~AbstractBlockCache() MappedBlockCache::MappedBlockCache(void *data, unsigned blocks) { _blocks = blocks; - _data = (uint8_t *)_data; + _data = (uint8_t *)data; } void MappedBlockCache::write() @@ -59,7 +59,14 @@ void MappedBlockCache::unload(unsigned block, bool dirty) #define __METHOD__ "MappedBlockCache::unload" if (!dirty) return; - if (::msync(_data + block * 512, 512, MS_ASYNC) < 0) + + // msync must be page-size aligned. + unsigned pagesize = ::getpagesize(); + unsigned offset = block * 512; + void *address = _data + offset / pagesize * pagesize; + unsigned length = offset % pagesize + 512; + + if (::msync(address, length, MS_ASYNC) < 0) { throw POSIXException(__METHOD__ ": msync failed.", errno); } diff --git a/pascal/Date.cpp b/pascal/Date.cpp index 5ccb29d..fa30630 100644 --- a/pascal/Date.cpp +++ b/pascal/Date.cpp @@ -1,6 +1,5 @@ #include "Date.h" #include -#include using namespace Pascal; @@ -41,5 +40,5 @@ Date Date::Today() ::localtime_r(&t, &tm); - return Date(tm.tm_year, tm.tm_mon, tm.tm_mday); + return Date(tm.tm_year, tm.tm_mon + 1, tm.tm_mday); } \ No newline at end of file diff --git a/pascal/File.cpp b/pascal/File.cpp index adea791..44a98a1 100644 --- a/pascal/File.cpp +++ b/pascal/File.cpp @@ -9,11 +9,13 @@ #include #include +#include #include using namespace LittleEndian; using namespace Pascal; +/* static bool isalpha(char c) { return (c >= 'A' && c <= 'Z') @@ -37,7 +39,7 @@ static bool islower(char c) inline char tolower(char c) { return c | 0x20; } inline char toupper(char c) { return c & ~0x20; } - +*/ #pragma mark - @@ -45,23 +47,42 @@ inline char toupper(char c) { return c & ~0x20; } unsigned Entry::ValidName(const char *cp, unsigned maxLength) { - unsigned length; - + + // any printable char except: + // white space + // $ = ? , (file only) + // : (volume only) if (!cp || !*cp) return 0; - if (!isalpha(*cp)) return 0; - - for (length = 1; cp[length]; ++length) + for (unsigned i = 0; ; ++i) { - if (length >= maxLength) return 0; - - if (!isalnumdot(cp[length])) return 0; - } + unsigned c = cp[i]; + if (c == 0) return i - 1; + if (i > maxLength) return 0; - return length; + switch(c) + { + + case ':': + if (maxLength == 7) return 0; + break; + case '$': + case '=': + case ',': + case '?': + if (maxLength == 15) return 0; + break; + + default: + if (!std::isascii(c)) return 0; + if (!std::isgraph(c)) return 0; + } + } + } + Entry::Entry() { _firstBlock = 0; @@ -103,6 +124,10 @@ void Entry::writeDirectoryEntry(IOBuffer *b) unsigned VolumeEntry::ValidName(const char *cp) { + // 7 chars max. Legal values: ascii, printable, + // no space/tab, + // no $=?,: + return Entry::ValidName(cp, 7); } @@ -132,7 +157,7 @@ VolumeEntry::VolumeEntry(const char *name, ProFUSE::BlockDevice *device) if (!length) throw ProFUSE::Exception(__METHOD__ ": Invalid volume name."); - _firstBlock = 2; + _firstBlock = 0; _lastBlock = 6; _fileKind = kUntypedFile; _inode = 1; @@ -143,7 +168,7 @@ VolumeEntry::VolumeEntry(const char *name, ProFUSE::BlockDevice *device) std::memset(_fileName, 0, sizeof(_fileName)); for (unsigned i = 0; i < _fileNameLength; ++i) { - _fileName[i] = toupper(name[i]); + _fileName[i] = std::toupper(name[i]); } _lastVolumeBlock = device->blocks(); @@ -301,6 +326,7 @@ void VolumeEntry::writeDirectoryEntry(IOBuffer *b) b->write8(0); // reserved b->write8(_fileNameLength); b->writeBytes(_fileName, 7); + b->write16(_lastVolumeBlock); b->write16(_fileCount); b->write16(_accessTime); b->write16(_lastBoot); @@ -347,7 +373,7 @@ FileEntry::FileEntry(const char *name, unsigned fileKind) _fileNameLength = length; std::memset(_fileName, 0, sizeof(_fileName)); for (unsigned i = 0; i < length; ++i) - _fileName[i] = toupper(name[i]); + _fileName[i] = std::toupper(name[i]); _modification = Date::Today(); _lastByte = 0; diff --git a/pascal/IOBuffer.h b/pascal/IOBuffer.h index ea3991e..a923e0e 100644 --- a/pascal/IOBuffer.h +++ b/pascal/IOBuffer.h @@ -41,7 +41,7 @@ namespace LittleEndian { void writeBytes(const void *value, unsigned count) { std::memcpy(_offset + (uint8_t *)_buffer, value, count); - _size += count; + _offset += count; } void writeZero(unsigned count) From c2518dbcccb2b7f864886c256ed6c0a099f59fb7 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 12 Dec 2009 22:16:37 +0000 Subject: [PATCH 041/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@160 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/File.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pascal/File.cpp b/pascal/File.cpp index 44a98a1..251122d 100644 --- a/pascal/File.cpp +++ b/pascal/File.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include using namespace LittleEndian; @@ -74,7 +74,7 @@ unsigned Entry::ValidName(const char *cp, unsigned maxLength) break; default: - if (!std::isascii(c)) return 0; + if (!::isascii(c)) return 0; if (!std::isgraph(c)) return 0; } } From fbe95823d39e9681fb94195a3e01517afef63af8 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 12 Dec 2009 23:57:17 +0000 Subject: [PATCH 042/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@161 aa027e90-d47c-11dd-86d7-074df07e0730 --- BlockDevice.cpp | 43 +++++++ BlockDevice.h | 4 + newfs_prodos.cpp | 2 +- pascal/Makefile | 17 +++ pascal/newfs_pascal.cpp | 251 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 316 insertions(+), 1 deletion(-) create mode 100644 pascal/Makefile create mode 100644 pascal/newfs_pascal.cpp diff --git a/BlockDevice.cpp b/BlockDevice.cpp index d58c39d..0d8b3c1 100644 --- a/BlockDevice.cpp +++ b/BlockDevice.cpp @@ -48,6 +48,49 @@ AbstractBlockCache *BlockDevice::createBlockCache() #pragma mark - #pragma mark DiskImage +unsigned DiskImage::ImageType(const char *type, unsigned defv) +{ + const char *tmp; + + if (type == 0 || *type == 0) return defv; + + // type could be a filename, in which case we check the extension. + tmp = std::strrchr(type, '.'); + if (tmp) type = tmp + 1; + if (*type == 0) return defv; + + + if (::strcasecmp(type, "2mg") == 0) + return '2IMG'; + if (::strcasecmp(type, "2img") == 0) + return '2IMG'; + + if (::strcasecmp(type, "dc42") == 0) + return 'DC42'; + + if (::strcasecmp(type, "po") == 0) + return 'PO__'; + if (::strcasecmp(type, "dmg") == 0) + return 'PO__'; + + if (::strcasecmp(type, "dsk") == 0) + return 'DO__'; + if (::strcasecmp(type, "do") == 0) + return 'DO__'; + + if (::strcasecmp(type, "davex") == 0) + return 'DVX_'; + + /* + // not supported yet. + if (::strcasecmp(tmp, "sdk") == 0) + return 'SDK_'; + */ + return defv; +} + + + DiskImage::DiskImage(const char *name, bool readOnly) : _file(NULL) { diff --git a/BlockDevice.h b/BlockDevice.h index 9712f4c..04a3be0 100644 --- a/BlockDevice.h +++ b/BlockDevice.h @@ -11,8 +11,10 @@ namespace ProFUSE { class MappedFile; class AbstractBlockCache; + class BlockDevice { public: + virtual ~BlockDevice(); virtual void read(unsigned block, void *bp) = 0; @@ -39,6 +41,8 @@ private: class DiskImage : public BlockDevice { public: + static unsigned ImageType(const char *type, unsigned defv = 0); + virtual ~DiskImage(); virtual void read(unsigned block, void *bp); diff --git a/newfs_prodos.cpp b/newfs_prodos.cpp index 756f607..3ac7c66 100644 --- a/newfs_prodos.cpp +++ b/newfs_prodos.cpp @@ -211,7 +211,7 @@ int main(int argc, char **argv) format = parseFormat(optarg); if (format == 0) { - std::fprintf(stderr, "Error: `%s' is not a supposed disk image format.\n", optarg); + std::fprintf(stderr, "Error: `%s' is not a supported disk image format.\n", optarg); return -1; } } diff --git a/pascal/Makefile b/pascal/Makefile new file mode 100644 index 0000000..69952bd --- /dev/null +++ b/pascal/Makefile @@ -0,0 +1,17 @@ +CC = g++ +CPPFLAGS += -Wall -O2 -g + +newfs_pascal: \ + newfs_pascal.o \ + Date.o \ + File.o \ + ../Exception.o \ + ../BlockDevice.o \ + ../BlockCache.o \ + ../DiskCopy42Image.o \ + ../RawDevice.o \ + ../MappedFile.o \ + ../Buffer.o \ + + + diff --git a/pascal/newfs_pascal.cpp b/pascal/newfs_pascal.cpp new file mode 100644 index 0000000..a05d9bd --- /dev/null +++ b/pascal/newfs_pascal.cpp @@ -0,0 +1,251 @@ +#include "../BlockDevice.h" +#include "../Exception.h" +#include "../MappedFile.h" +#include "../DiskCopy42Image.h" + +#include "File.h" + + +#include +#include +#include +#include + +#include + + +using namespace Pascal; + +#define NEWFS_VERSION "0.1" + + + +/* + * \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" + " -f format specify the disk image format. Valid values are:\n" + " dc42 DiskCopy 4.2 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; + int format = 0; + const char *fname; + int 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 (!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 = ProFUSE::DiskImage::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() || !VolumeEntry::ValidName(volumeName.c_str())) + volumeName = "PASCAL"; + } + + if (format == 0) format = ProFUSE::DiskImage::ImageType(fname, 'PO__'); + + + try + { + std::auto_ptr device; + std::auto_ptr volume; + + // TODO -- check for raw device. + + + switch(format) + { + case 'DC42': + device.reset(ProFUSE::DiskCopy42Image::Create(fname, blocks, volumeName.c_str())); + break; + + case 'PO__': + device.reset(ProFUSE::ProDOSOrderDiskImage::Create(fname, blocks)); + break; + + case 'DO__': + device.reset(ProFUSE::DOSOrderDiskImage::Create(fname, blocks)); + break; + + + default: + std::fprintf(stderr, "Error: Unsupported diskimage format.\n"); + return-1; + } + + + volume.reset( + new Pascal::VolumeEntry(volumeName.c_str(), device.get()) + ); + device.release(); + + /* + ProFUSE::MappedFile bootBlock("pascal.bootblock", true); + + if (bootBlock.fileSize() == 1024) + { + uint8_t buffer[512]; + bootBlock.setBlocks(2); + + for (unsigned block = 0; block < 2; ++block) + { + bootBlock.readBlock(block, buffer); + volume->writeBlock(block, buffer); + } + } + */ + + } + catch (ProFUSE::POSIXException& e) + { + std::fprintf(stderr, "%s\n", e.what()); + std::fprintf(stderr, "%s\n", ::strerror(e.error())); + return -2; + } + catch (ProFUSE::Exception& e) + { + std::fprintf(stderr, "%s\n", e.what()); + return -2; + } + + return 0; +} \ No newline at end of file From 4544a7d649cc116e6978b53be9b6ab021680132c Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 13 Dec 2009 00:08:07 +0000 Subject: [PATCH 043/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@162 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/File.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pascal/File.cpp b/pascal/File.cpp index 251122d..24bdeb4 100644 --- a/pascal/File.cpp +++ b/pascal/File.cpp @@ -57,8 +57,8 @@ unsigned Entry::ValidName(const char *cp, unsigned maxLength) for (unsigned i = 0; ; ++i) { unsigned c = cp[i]; - if (c == 0) return i - 1; - if (i > maxLength) return 0; + if (c == 0) return i; + if (i >= maxLength) return 0; switch(c) { From e99ae3b59602c640828f2cbea6aa71f002106175 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 13 Dec 2009 02:21:07 +0000 Subject: [PATCH 044/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@163 aa027e90-d47c-11dd-86d7-074df07e0730 --- newfs_prodos.cpp | 39 ++------------------------------------- 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/newfs_prodos.cpp b/newfs_prodos.cpp index 3ac7c66..a7aaab0 100644 --- a/newfs_prodos.cpp +++ b/newfs_prodos.cpp @@ -82,41 +82,6 @@ unsigned parseBlocks(const char *cp) return (unsigned)blocks; } -unsigned parseFormat(const char *type, unsigned defv = 0) -{ - if (type == 0 || *type == 0) return defv; - - if (::strcasecmp(type, "2mg") == 0) - return '2IMG'; - if (::strcasecmp(type, "2img") == 0) - return '2IMG'; - if (::strcasecmp(type, "dc42") == 0) - return 'DC42'; - if (::strcasecmp(type, "po") == 0) - return 'PO__'; - if (::strcasecmp(type, "do") == 0) - return 'DO__'; - if (::strcasecmp(type, "davex") == 0) - return 'DVX_'; - - return defv; -} - -// return the filename extension, NULL if none. -const char *extname(const char *src) -{ - if (!src) return NULL; - unsigned l = std::strlen(src); - - for (unsigned i = 0; i < l; ++i) - { - char c = src[l - 1 - i]; - if (c == '/') return NULL; - if (c == '.') return src + l - i; - } - - return NULL; -} // return the basename, without an extension. std::string filename(const std::string& src) @@ -208,7 +173,7 @@ int main(int argc, char **argv) case 'f': { - format = parseFormat(optarg); + format = DiskImage::ImageType(optarg); if (format == 0) { std::fprintf(stderr, "Error: `%s' is not a supported disk image format.\n", optarg); @@ -239,7 +204,7 @@ int main(int argc, char **argv) volumeName = "Untitled"; } - if (format == 0) format = parseFormat(extname(fname)); + if (format == 0) format = DiskImage::ImageType(fname, '2IMG'); try From 332910a2abc2cc7ef422906343b4bb24aea0e8e1 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 13 Dec 2009 20:19:06 +0000 Subject: [PATCH 045/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@164 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/newfs_pascal.cpp | 2 +- pascal/profuse_pascal.cpp | 316 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 pascal/profuse_pascal.cpp diff --git a/pascal/newfs_pascal.cpp b/pascal/newfs_pascal.cpp index a05d9bd..838a1c6 100644 --- a/pascal/newfs_pascal.cpp +++ b/pascal/newfs_pascal.cpp @@ -209,7 +209,7 @@ int main(int argc, char **argv) default: std::fprintf(stderr, "Error: Unsupported diskimage format.\n"); - return-1; + return -1; } diff --git a/pascal/profuse_pascal.cpp b/pascal/profuse_pascal.cpp new file mode 100644 index 0000000..ceb58db --- /dev/null +++ b/pascal/profuse_pascal.cpp @@ -0,0 +1,316 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include + +#define __FreeBSD__ 10 +#define __DARWIN_64_BIT_INO_T 1 +#define _FILE_OFFSET_BITS 64 +#define FUSE_USE_VERSION 27 + +#include +#include + + +#include "File.h" +#include "../BlockDevice.h" +#include "../Exception.h" +#include "../MappedFile.h" +#include "../DiskCopy42Image.h" + +Pascal::VolumeEntry *fVolume = NULL; +std::string fDiskImage; + +unsigned fFormat = 0; +bool fVerbose = false; +bool fReadOnly = true; + +void usage() +{ + std::printf("profuse_pascal 0.1\n\n"); + std::printf( + "usage:\n" + "profuse_pascal [-w] [-f format] [-o options] diskimage [mountpoint]\n" + " -w mount writable [not yet]\n" + " -f format specify the disk image format. Valid values are:\n" + " dc42 DiskCopy 4.2 Image\n" + " do DOS Order Disk Image\n" + " po ProDOS Order Disk Image (default)\n" + ); +} + + +static struct fuse_lowlevel_ops pascal_ops; + +enum { + PASCAL_OPT_HELP, + PASCAL_OPT_VERSION, + PASCAL_OPT_WRITE, + PASCAL_OPT_FORMAT, + PASCAL_OPT_VERBOSE +}; + +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), + + FUSE_OPT_KEY("-v", PASCAL_OPT_VERBOSE), + + FUSE_OPT_KEY("-w", PASCAL_OPT_WRITE), + FUSE_OPT_KEY("rw", PASCAL_OPT_WRITE), + + FUSE_OPT_KEY("-f=", PASCAL_OPT_FORMAT), + + {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 PASCAL_OPT_VERBOSE: + fVerbose = true; + return 0; + break; + + case PASCAL_OPT_WRITE: + fReadOnly = false; + return 0; + + case PASCAL_OPT_FORMAT: + fFormat = ProFUSE::DiskImage::ImageType(arg); + if (fFormat == 0) + { + std::fprintf(stderr, "Invalid image format: ``%s''\n", + arg); + } + return 0; + + case FUSE_OPT_KEY_NONOPT: + 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) return false; + if (name.find('\\') != std::string::npos) return false; + if (name.find(':') != std::string::npos) return false; + + 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) +{ + + + struct fuse_args args = FUSE_ARGS_INIT(argc, argv); + struct fuse_chan *ch; + char *mountpoint = NULL; + int err = -1; + std::string mountPath; + + int foreground = false; + int multithread = false; + + std::memset(&pascal_ops, 0, sizeof(pascal_ops)); + + + + // returns pascal.filekind, text encoding. + pascal_ops.listxattr = pascal_listxattr; + pascal_ops.getxattr = pascal_getxattr; + + // volume is a dir. + pascal_ops.opendir = pascal_opendir; + pascal_ops.releasedir = pascal_releasedir; + pascal_ops.readdir = pascal_readdir; + + + pascal_ops.lookup = pascal_lookup; + pascal_ops.getattr = pascal_getattr; + + pascal_ops.open = pascal_open; + pascal_ops.release = pascal_release; + pascal_ops.read = pascal_read; + + + // scan the argument list, looking for the name of the disk image. + if (fuse_opt_parse(&args, NULL ,pascal_options, pascal_option_proc) == -1) + exit(1); + + if (fDiskImage.empty()) + { + usage(); + exit(1); + } + + // default prodos-order disk image. + if (!fFormat) + fFormat = ProFUSE::DiskImage::ImageType(fDiskImage.c_str(), 'PO__'); + + try { + std::auto_ptr device; + + switch(fFormat) + { + case 'DC42': + device.reset(new ProFUSE::DiskCopy42Image(fDiskImage.c_str(), fReadOnly)); + break; + + case 'PO__': + device.reset(new ProFUSE::ProDOSOrderDiskImage(fDiskImage.c_str(), fReadOnly)); + break; + + case 'DO__': + device.reset(new ProFUSE::DOSOrderDiskImage(fDiskImage.c_str(), fReadOnly)); + break; + + + default: + std::fprintf(stderr, "Error: Unknown or unsupported device type.\n"); + exit(1); + } + + fVolume = new Pascal::VolumeEntry(device.get()); + device.release(); + + } + catch (ProFUSE::POSIXException &e) + { + std::fprintf(stderr, "%s\n", e.what()); + std::fprintf(stderr, "%s\n", std::strerror(e.error())); + } + catch (ProFUSE::Exception &e) + { + std::fprintf(stderr, "%s\n", e.what()); + } + + + + #ifdef __APPLE__ + { + // Macfuse supports custom volume names (displayed in Finder) + std::string str("-ovolname="); + str += fVolume->name(); + fuse_opt_add_arg(&args, str.c_str()); + + // 512 byte blocksize. + fuse_opt_add_arg(&args, "-oiosize=512"); + + } + #endif + + if (fReadOnly) + fuse_opt_add_arg(&args, "-ordonly"); + + if (fuse_parse_cmdline(&args, &mountpoint, &multithread, &foreground) == -1) + { + usage(); + return -1; + } + +#ifdef __APPLE__ + + if (mountpoint == NULL || *mountpoint == 0) + { + if (make_mount_dir(fVolume->name(), mountPath)) + mountpoint = (char *)mountPath.c_str(); + } + +#endif + + + if ((ch = fuse_mount(mountpoint, &args)) != NULL) + { + struct fuse_session* se; + + se = fuse_lowlevel_new(&args, &pascal_ops, sizeof(pascal_ops), fVolume); + + if (se) do { + foreground = 1; + multithread = 0; + + err = fuse_daemonize(foreground); // todo + 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); + delete fVolume; + + +#ifdef __APPLE__ + if (!mountPath.empty()) rmdir(mountPath.c_str()); +#endif + + + return err ? 1 : 0; +} \ No newline at end of file From d3b89e328d0cf0434fd6567a2ef11d820f7d94e7 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 13 Dec 2009 23:08:58 +0000 Subject: [PATCH 046/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@165 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/Makefile | 29 +++++++++++++++++++++++++++-- pascal/profuse_pascal.cpp | 22 ++-------------------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/pascal/Makefile b/pascal/Makefile index 69952bd..219eb3d 100644 --- a/pascal/Makefile +++ b/pascal/Makefile @@ -1,5 +1,6 @@ CC = g++ CPPFLAGS += -Wall -O2 -g +LDFLAGS += -L/usr/local/lib -lfuse newfs_pascal: \ newfs_pascal.o \ @@ -11,7 +12,31 @@ newfs_pascal: \ ../DiskCopy42Image.o \ ../RawDevice.o \ ../MappedFile.o \ - ../Buffer.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 \ No newline at end of file diff --git a/pascal/profuse_pascal.cpp b/pascal/profuse_pascal.cpp index ceb58db..44e3cea 100644 --- a/pascal/profuse_pascal.cpp +++ b/pascal/profuse_pascal.cpp @@ -153,6 +153,7 @@ bool make_mount_dir(std::string name, std::string &path) int main(int argc, char **argv) { + extern void init_ops(fuse_lowlevel_ops *ops); struct fuse_args args = FUSE_ARGS_INIT(argc, argv); @@ -164,26 +165,7 @@ int main(int argc, char **argv) int foreground = false; int multithread = false; - std::memset(&pascal_ops, 0, sizeof(pascal_ops)); - - - - // returns pascal.filekind, text encoding. - pascal_ops.listxattr = pascal_listxattr; - pascal_ops.getxattr = pascal_getxattr; - - // volume is a dir. - pascal_ops.opendir = pascal_opendir; - pascal_ops.releasedir = pascal_releasedir; - pascal_ops.readdir = pascal_readdir; - - - pascal_ops.lookup = pascal_lookup; - pascal_ops.getattr = pascal_getattr; - - pascal_ops.open = pascal_open; - pascal_ops.release = pascal_release; - pascal_ops.read = pascal_read; + init_ops(&pascal_ops); // scan the argument list, looking for the name of the disk image. From 96eb6a4d36f62a6d58ca1793062696f27eeed0ba Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 13 Dec 2009 23:34:29 +0000 Subject: [PATCH 047/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@166 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/Makefile | 2 +- pascal/profuse_pascal.cpp | 13 ++ pascal/profuse_pascal_ops.cpp | 391 ++++++++++++++++++++++++++++++++++ 3 files changed, 405 insertions(+), 1 deletion(-) create mode 100644 pascal/profuse_pascal_ops.cpp diff --git a/pascal/Makefile b/pascal/Makefile index 219eb3d..008c490 100644 --- a/pascal/Makefile +++ b/pascal/Makefile @@ -1,5 +1,5 @@ CC = g++ -CPPFLAGS += -Wall -O2 -g +CPPFLAGS += -Wall -O2 -g -fexceptions LDFLAGS += -L/usr/local/lib -lfuse newfs_pascal: \ diff --git a/pascal/profuse_pascal.cpp b/pascal/profuse_pascal.cpp index 44e3cea..80e4ed8 100644 --- a/pascal/profuse_pascal.cpp +++ b/pascal/profuse_pascal.cpp @@ -56,6 +56,13 @@ enum { PASCAL_OPT_VERBOSE }; +struct options { + char *format; + int readOnly; + int readWrite; + +}; + static struct fuse_opt pascal_options[] = { FUSE_OPT_KEY("-h", PASCAL_OPT_HELP), FUSE_OPT_KEY("--help", PASCAL_OPT_HELP), @@ -182,6 +189,7 @@ int main(int argc, char **argv) if (!fFormat) fFormat = ProFUSE::DiskImage::ImageType(fDiskImage.c_str(), 'PO__'); + try { std::auto_ptr device; @@ -205,20 +213,25 @@ int main(int argc, char **argv) exit(1); } + fVolume = new Pascal::VolumeEntry(device.get()); device.release(); + } catch (ProFUSE::POSIXException &e) { std::fprintf(stderr, "%s\n", e.what()); std::fprintf(stderr, "%s\n", std::strerror(e.error())); + return -1; } catch (ProFUSE::Exception &e) { std::fprintf(stderr, "%s\n", e.what()); + return -1; } + return 0; #ifdef __APPLE__ diff --git a/pascal/profuse_pascal_ops.cpp b/pascal/profuse_pascal_ops.cpp new file mode 100644 index 0000000..36e83a0 --- /dev/null +++ b/pascal/profuse_pascal_ops.cpp @@ -0,0 +1,391 @@ + + +#include +#include +#include + +#include +#include + + +#define __FreeBSD__ 10 +#define __DARWIN_64_BIT_INO_T 1 +#define _FILE_OFFSET_BITS 64 +#define FUSE_USE_VERSION 27 + +#include +#include + + + + +#include "File.h" +#include "../auto.h" +#include "../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; \ +} + + + +using namespace Pascal; + + +static FileEntry *findChild(VolumeEntry *volume, unsigned inode) +{ + + for (unsigned i = 0, l = volume->fileCount(); i < l; ++i) + { + FileEntry *child = volume->fileAtIndex(i); + if (inode == child->inode()) return child; + } + + return NULL; +} + +static void pascal_init(void *userdata, struct fuse_conn_info *conn) +{ + // nop +} + +static void pascal_destroy(void *userdata) +{ + // nop +} + + + +#pragma mark - +#pragma mark xattr + +static void pascal_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) +{ + VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); + FileEntry *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) +{ + VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); + FileEntry *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) +{ + 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) +{ + + 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) +{ + // nop. +} + +static void pascal_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) +{ + VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); + auto_array buffer(new char[size]); + unsigned count = volume->fileCount(); + + struct stat st; + unsigned currentSize = 0; + + std::memset(&st, 0, sizeof(st)); + + for (unsigned i = off; i < count; ++i) + { + unsigned tmp; + + FileEntry *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, buffer.get() + currentSize, size, file->name(), &st, i + 1); + currentSize += tmp; + } + + fuse_reply_buf(req,buffer.get(), currentSize); + +} + + +#pragma mark - +#pragma mark stat + + +static void stat(FileEntry *file, struct stat *st) +{ + std::memset(st, 0, sizeof(st)); + + 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) +{ + std::memset(st, 0, sizeof(st)); + + 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) +{ + 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) + { + FileEntry *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, &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) +{ + struct stat st; + VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); + FileEntry *file; + + if (ino == 1) + { + stat(volume, &st); + fuse_reply_attr(req, &st, 0.0); + return; + } + + file = findChild(volume, ino); + + ERROR(file == NULL, ENOENT) + + stat(file, &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) +{ + VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); + FileEntry *file; + + ERROR(ino == 1, EISDIR) + + file = findChild(volume, ino); + + ERROR(file == NULL, ENOENT) + + ERROR((fi->flags & O_ACCMODE) != O_RDONLY, EACCES) + + fi->fh = (uint64_t)file; + + fuse_reply_open(req, fi); +} + + +static void pascal_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) +{ + // nop +} + + +static void pascal_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) +{ + VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); + FileEntry *file = (FileEntry *)fi->fh; + + try + { + auto_array buffer(new uint8_t[size]); + unsigned rsize = file->read(buffer.get(), size, off); + + fuse_reply_buf(req, (const char *)(buffer.get()), rsize); + return; + } + catch (ProFUSE::POSIXException &e) + { + ERROR(true, e.error()); + } + catch( ... ) + { + ERROR(true, EIO) + } + +} + + +void init_ops(fuse_lowlevel_ops *ops) +{ + + std::memset(ops, 0, sizeof(fuse_lowlevel_ops)); + + + // 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; + +} From e40355ecc51acbc7bdcfd4705de1bd128b14d772 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 14 Dec 2009 00:14:59 +0000 Subject: [PATCH 048/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@167 aa027e90-d47c-11dd-86d7-074df07e0730 --- BlockDevice.cpp | 4 +++ BlockDevice.h | 1 + pascal/profuse_pascal.cpp | 62 +++++++++++++++++---------------------- 3 files changed, 32 insertions(+), 35 deletions(-) diff --git a/BlockDevice.cpp b/BlockDevice.cpp index 0d8b3c1..df17519 100644 --- a/BlockDevice.cpp +++ b/BlockDevice.cpp @@ -16,6 +16,10 @@ using namespace ProFUSE; #pragma mark - #pragma mark BlockDevice +BlockDevice::BlockDevice() +{ + _cache = NULL; +} BlockDevice::~BlockDevice() { delete _cache; diff --git a/BlockDevice.h b/BlockDevice.h index 04a3be0..c76a713 100644 --- a/BlockDevice.h +++ b/BlockDevice.h @@ -30,6 +30,7 @@ public: AbstractBlockCache *blockCache(); protected: + BlockDevice(); virtual AbstractBlockCache *createBlockCache(); private: diff --git a/pascal/profuse_pascal.cpp b/pascal/profuse_pascal.cpp index 80e4ed8..f24a95d 100644 --- a/pascal/profuse_pascal.cpp +++ b/pascal/profuse_pascal.cpp @@ -27,9 +27,6 @@ Pascal::VolumeEntry *fVolume = NULL; std::string fDiskImage; -unsigned fFormat = 0; -bool fVerbose = false; -bool fReadOnly = true; void usage() { @@ -60,8 +57,10 @@ 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), @@ -70,12 +69,12 @@ static struct fuse_opt pascal_options[] = { FUSE_OPT_KEY("-V", PASCAL_OPT_VERSION), FUSE_OPT_KEY("--version", PASCAL_OPT_VERSION), - FUSE_OPT_KEY("-v", PASCAL_OPT_VERBOSE), + PASCAL_OPT_KEY("-v", verbose, 1), - FUSE_OPT_KEY("-w", PASCAL_OPT_WRITE), - FUSE_OPT_KEY("rw", PASCAL_OPT_WRITE), + PASCAL_OPT_KEY("-w", readWrite, 1), + PASCAL_OPT_KEY("rw", readWrite, 1), - FUSE_OPT_KEY("-f=", PASCAL_OPT_FORMAT), + PASCAL_OPT_KEY("-f %s", format, 0), {0, 0, 0} }; @@ -94,23 +93,7 @@ static int pascal_option_proc(void *data, const char *arg, int key, struct fuse_ // TODO exit(0); break; - case PASCAL_OPT_VERBOSE: - fVerbose = true; - return 0; - break; - - case PASCAL_OPT_WRITE: - fReadOnly = false; - return 0; - - case PASCAL_OPT_FORMAT: - fFormat = ProFUSE::DiskImage::ImageType(arg); - if (fFormat == 0) - { - std::fprintf(stderr, "Invalid image format: ``%s''\n", - arg); - } - return 0; + case FUSE_OPT_KEY_NONOPT: if (fDiskImage.empty()) @@ -161,13 +144,14 @@ bool make_mount_dir(std::string name, std::string &path) int main(int argc, char **argv) { extern void init_ops(fuse_lowlevel_ops *ops); - + struct options options = { 0 }; struct fuse_args args = FUSE_ARGS_INIT(argc, argv); struct fuse_chan *ch; char *mountpoint = NULL; int err = -1; std::string mountPath; + unsigned format; int foreground = false; int multithread = false; @@ -176,7 +160,7 @@ int main(int argc, char **argv) // scan the argument list, looking for the name of the disk image. - if (fuse_opt_parse(&args, NULL ,pascal_options, pascal_option_proc) == -1) + if (fuse_opt_parse(&args, &options ,pascal_options, pascal_option_proc) == -1) exit(1); if (fDiskImage.empty()) @@ -186,25 +170,29 @@ int main(int argc, char **argv) } // default prodos-order disk image. - if (!fFormat) - fFormat = ProFUSE::DiskImage::ImageType(fDiskImage.c_str(), 'PO__'); + format = ProFUSE::DiskImage::ImageType(options.format); + if (!format) + format = ProFUSE::DiskImage::ImageType(fDiskImage.c_str(), 'PO__'); + + + bool readOnly = true; try { std::auto_ptr device; - switch(fFormat) + switch(format) { case 'DC42': - device.reset(new ProFUSE::DiskCopy42Image(fDiskImage.c_str(), fReadOnly)); + device.reset(new ProFUSE::DiskCopy42Image(fDiskImage.c_str(), readOnly)); break; case 'PO__': - device.reset(new ProFUSE::ProDOSOrderDiskImage(fDiskImage.c_str(), fReadOnly)); + device.reset(new ProFUSE::ProDOSOrderDiskImage(fDiskImage.c_str(), readOnly)); break; case 'DO__': - device.reset(new ProFUSE::DOSOrderDiskImage(fDiskImage.c_str(), fReadOnly)); + device.reset(new ProFUSE::DOSOrderDiskImage(fDiskImage.c_str(), readOnly)); break; @@ -231,7 +219,6 @@ int main(int argc, char **argv) return -1; } - return 0; #ifdef __APPLE__ @@ -247,8 +234,13 @@ int main(int argc, char **argv) } #endif - if (fReadOnly) + 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) { From ff90d3d8d369b70d2d24278692353ae062d8e7ee Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 14 Dec 2009 00:48:01 +0000 Subject: [PATCH 049/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@168 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/Makefile | 10 ++++++++-- pascal/profuse_pascal_ops.cpp | 32 ++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/pascal/Makefile b/pascal/Makefile index 008c490..78694b3 100644 --- a/pascal/Makefile +++ b/pascal/Makefile @@ -1,6 +1,12 @@ CC = g++ -CPPFLAGS += -Wall -O2 -g -fexceptions -LDFLAGS += -L/usr/local/lib -lfuse +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 \ diff --git a/pascal/profuse_pascal_ops.cpp b/pascal/profuse_pascal_ops.cpp index 36e83a0..59f4dca 100644 --- a/pascal/profuse_pascal_ops.cpp +++ b/pascal/profuse_pascal_ops.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -60,11 +61,13 @@ static FileEntry *findChild(VolumeEntry *volume, unsigned inode) static void pascal_init(void *userdata, struct fuse_conn_info *conn) { + std::printf("pascal_init\n"); // nop } static void pascal_destroy(void *userdata) { + std::printf("pascal_destroy\n"); // nop } @@ -75,6 +78,8 @@ static void pascal_destroy(void *userdata) static void pascal_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) { + std::printf("pascal_listxattr\n"); + VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); FileEntry *file; std::string attr; @@ -116,6 +121,9 @@ static void pascal_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) static void pascal_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, size_t size) { + std::printf("pascal_getxattr\n"); + + VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); FileEntry *file; std::string attr(name); @@ -168,6 +176,8 @@ static void pascal_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, si static void pascal_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { + std::printf("pascal_opendir\n"); + ERROR(ino != 1, ENOTDIR) @@ -178,13 +188,17 @@ static void pascal_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info static void pascal_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { + std::printf("pascal_releasedir\n"); + // nop. } static void pascal_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) { + std::printf("pascal_readdir %u, %u, %u\n", (unsigned)ino, (unsigned)size, (unsigned)off); + VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); - auto_array buffer(new char[size]); + auto_array buffer(new uint8_t[size]); unsigned count = volume->fileCount(); struct stat st; @@ -208,11 +222,11 @@ static void pascal_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t of if (tmp + currentSize > size) break; - fuse_add_direntry(req, buffer.get() + currentSize, size, file->name(), &st, i + 1); + fuse_add_direntry(req, (char *)buffer.get() + currentSize, size, file->name(), &st, i + 1); currentSize += tmp; } - fuse_reply_buf(req,buffer.get(), currentSize); + fuse_reply_buf(req, currentSize ? (char *)buffer.get() : NULL, currentSize); } @@ -246,7 +260,7 @@ static void stat(VolumeEntry *volume, struct stat *st) time_t t = volume->lastBoot(); - st->st_ino = volume->inode(); + st->st_ino = volume->inode(); st->st_nlink = 1 + volume->fileCount(); st->st_mode = S_IFDIR | 0555; st->st_size = volume->blocks() * 512; @@ -261,6 +275,8 @@ static void stat(VolumeEntry *volume, struct stat *st) static void pascal_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) { + std::printf("pascal_lookup %u %s\n", (unsigned)parent, name); + VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); struct fuse_entry_param entry; @@ -292,6 +308,8 @@ static void pascal_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) static void pascal_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { + std::printf("pascal_getattr\n"); + struct stat st; VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); FileEntry *file; @@ -317,6 +335,8 @@ static void pascal_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info static void pascal_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { + std::printf("pascal_open\n"); + VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); FileEntry *file; @@ -336,12 +356,16 @@ static void pascal_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *f static void pascal_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { + std::printf("pascal_release\n"); + // nop } static void pascal_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) { + std::printf("pascal_read\n"); + VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); FileEntry *file = (FileEntry *)fi->fh; From 777c1c3424482f906720d964519dd7f42b02c0a8 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 14 Dec 2009 01:28:34 +0000 Subject: [PATCH 050/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@169 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/File.cpp | 3 +- pascal/profuse_pascal_ops.cpp | 61 ++++++++++++++++++++++++++++------- 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/pascal/File.cpp b/pascal/File.cpp index 24bdeb4..42a5b24 100644 --- a/pascal/File.cpp +++ b/pascal/File.cpp @@ -633,13 +633,14 @@ unsigned FileEntry::textReadPage(unsigned block, uint8_t *in) void FileEntry::textInit() { // calculate the file size and page offsets. - + _pageSize = new std::vector; _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); } diff --git a/pascal/profuse_pascal_ops.cpp b/pascal/profuse_pascal_ops.cpp index 59f4dca..ca8621c 100644 --- a/pascal/profuse_pascal_ops.cpp +++ b/pascal/profuse_pascal_ops.cpp @@ -8,10 +8,11 @@ #include #include - +/* #define __FreeBSD__ 10 #define __DARWIN_64_BIT_INO_T 1 #define _FILE_OFFSET_BITS 64 +*/ #define FUSE_USE_VERSION 27 #include @@ -146,7 +147,7 @@ static void pascal_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, si if (attr == "user.charset") { - static const char *data="ascii"; + static const char data[]="ascii"; static unsigned dataSize = sizeof(data) - 1; RETURN_XATTR(data, dataSize) @@ -154,7 +155,7 @@ static void pascal_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, si if (attr == "com.apple.TextEncoding") { - static const char *data = "us-ascii;1536"; + static const char data[] = "us-ascii;1536"; static unsigned dataSize = sizeof(data) - 1; RETURN_XATTR(data, dataSize) @@ -190,7 +191,7 @@ static void pascal_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_i { std::printf("pascal_releasedir\n"); - // nop. + 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) @@ -201,12 +202,47 @@ static void pascal_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t of auto_array buffer(new uint8_t[size]); unsigned count = volume->fileCount(); + struct stat st; unsigned currentSize = 0; std::memset(&st, 0, sizeof(st)); - for (unsigned i = off; i < count; ++i) + // . && .. entries. + + if (off == 0) + { + unsigned tmp; + + st.st_mode = S_IFDIR | 0555; + st.st_ino = 1; + + tmp = fuse_add_direntry(req, NULL, 0, ".", NULL, 0); + + ERROR(tmp + currentSize > size, ERANGE) + + 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) + { + fuse_reply_buf(req, (char *)buffer.get(), currentSize); + } + + fuse_add_direntry(req, (char *)buffer.get() + currentSize, size, "..", &st, ++off); + currentSize += tmp; + } + + for (unsigned i = off - 2; i < count; ++i) { unsigned tmp; @@ -222,11 +258,11 @@ static void pascal_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t of if (tmp + currentSize > size) break; - fuse_add_direntry(req, (char *)buffer.get() + currentSize, size, file->name(), &st, i + 1); + fuse_add_direntry(req, (char *)buffer.get() + currentSize, size, file->name(), &st, ++off); currentSize += tmp; } - fuse_reply_buf(req, currentSize ? (char *)buffer.get() : NULL, currentSize); + fuse_reply_buf(req, (char *)buffer.get(), currentSize); } @@ -260,7 +296,7 @@ static void stat(VolumeEntry *volume, struct stat *st) time_t t = volume->lastBoot(); - st->st_ino = volume->inode(); + st->st_ino = volume->inode(); st->st_nlink = 1 + volume->fileCount(); st->st_mode = S_IFDIR | 0555; st->st_size = volume->blocks() * 512; @@ -308,7 +344,7 @@ static void pascal_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) static void pascal_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { - std::printf("pascal_getattr\n"); + std::printf("pascal_getattr %u\n", (unsigned)ino); struct stat st; VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); @@ -324,6 +360,7 @@ static void pascal_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info file = findChild(volume, ino); ERROR(file == NULL, ENOENT) + printf("\t%s\n", file->name()); stat(file, &st); fuse_reply_attr(req, &st, 0.0); @@ -358,7 +395,7 @@ static void pascal_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info { std::printf("pascal_release\n"); - // nop + fuse_reply_err(req, 0); } @@ -366,7 +403,7 @@ static void pascal_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, { std::printf("pascal_read\n"); - VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); + //VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); FileEntry *file = (FileEntry *)fi->fh; try @@ -394,6 +431,8 @@ void init_ops(fuse_lowlevel_ops *ops) std::memset(ops, 0, sizeof(fuse_lowlevel_ops)); + ops->init = pascal_init; + ops->destroy = pascal_destroy; // returns pascal.filekind, text encoding. ops->listxattr = pascal_listxattr; From 102998ec6637a10834cb8d21fe4a9fa6e6db8142 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 14 Dec 2009 03:32:57 +0000 Subject: [PATCH 051/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@170 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/File.cpp | 40 +++++++++------ pascal/profuse_pascal_ops.cpp | 96 ++++++++++++++++++----------------- 2 files changed, 75 insertions(+), 61 deletions(-) diff --git a/pascal/File.cpp b/pascal/File.cpp index 42a5b24..b305ae9 100644 --- a/pascal/File.cpp +++ b/pascal/File.cpp @@ -524,7 +524,7 @@ int FileEntry::textRead(uint8_t *buffer, unsigned size, unsigned offset) // find the first page. - for (page = 1; page < l; ++page) + for (page = 0; page < l; ++page) { unsigned pageSize = (*_pageSize)[page]; if (to + pageSize > offset) @@ -535,7 +535,6 @@ int FileEntry::textRead(uint8_t *buffer, unsigned size, unsigned offset) to += pageSize; } - --page; block = _firstBlock + 2 + (page * 2); @@ -582,27 +581,38 @@ 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) break; - if (c == 16 && i != bytes - 1) + if (!c) continue; + + + if (dle) { - // DLE - // 16, n -> n-32 spaces. - unsigned x = buffer[++i] - 32; - - if (out) for (unsigned i = 0; i < x; ++i) *out++ = ' '; - size += x; - } - else - { - if (out) *out++ = c; - size += 1; + if (c > 32) + { + unsigned x = c - 32; + size += x; + if (out) for (unsigned j = 0; j < x; ++j) + *out++ = ' '; + } + dle = false; + continue; } + if (c == 16) { 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; diff --git a/pascal/profuse_pascal_ops.cpp b/pascal/profuse_pascal_ops.cpp index ca8621c..7ead116 100644 --- a/pascal/profuse_pascal_ops.cpp +++ b/pascal/profuse_pascal_ops.cpp @@ -210,57 +210,59 @@ static void pascal_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t of // . && .. entries. - if (off == 0) - { - unsigned tmp; - - st.st_mode = S_IFDIR | 0555; - st.st_ino = 1; - - tmp = fuse_add_direntry(req, NULL, 0, ".", NULL, 0); - - ERROR(tmp + currentSize > size, ERANGE) - - 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) + do { + if (off == 0) { - fuse_reply_buf(req, (char *)buffer.get(), currentSize); + 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; } - - fuse_add_direntry(req, (char *)buffer.get() + currentSize, size, "..", &st, ++off); - currentSize += tmp; - } - - for (unsigned i = off - 2; i < count; ++i) - { - unsigned tmp; - FileEntry *file = volume->fileAtIndex(i); - if (file == NULL) break; //? + 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; - // only these fields are used. - st.st_mode = S_IFREG | 0444; - st.st_ino = file->inode(); + fuse_add_direntry(req, (char *)buffer.get() + currentSize, size, "..", &st, ++off); + currentSize += tmp; + } + + for (unsigned i = off - 2; i < count; ++i) + { + unsigned tmp; + + FileEntry *file = volume->fileAtIndex(i); + if (file == NULL) break; //? - - tmp = fuse_add_direntry(req, NULL, 0, file->name(), NULL, 0); + // only these fields are used. + st.st_mode = S_IFREG | 0444; + st.st_ino = file->inode(); + - if (tmp + currentSize > size) break; + 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_add_direntry(req, (char *)buffer.get() + currentSize, size, file->name(), &st, ++off); - currentSize += tmp; - } fuse_reply_buf(req, (char *)buffer.get(), currentSize); @@ -401,7 +403,7 @@ static void pascal_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info static void pascal_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) { - std::printf("pascal_read\n"); + std::printf("pascal_read %u %u %u\n", (unsigned)ino, (unsigned)size, (unsigned)off); //VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); FileEntry *file = (FileEntry *)fi->fh; @@ -411,15 +413,17 @@ static void pascal_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, auto_array buffer(new uint8_t[size]); unsigned rsize = file->read(buffer.get(), size, off); - fuse_reply_buf(req, (const char *)(buffer.get()), rsize); + fuse_reply_buf(req, (char *)(buffer.get()), rsize); return; } catch (ProFUSE::POSIXException &e) { + printf("posix error...\n"); ERROR(true, e.error()); } catch( ... ) { + printf("error...\n"); ERROR(true, EIO) } From e2c27e72f4ca185da79b6627c70dabd1825fdc61 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 14 Dec 2009 03:59:39 +0000 Subject: [PATCH 052/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@171 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/profuse_pascal.cpp | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/pascal/profuse_pascal.cpp b/pascal/profuse_pascal.cpp index f24a95d..1aed2ac 100644 --- a/pascal/profuse_pascal.cpp +++ b/pascal/profuse_pascal.cpp @@ -33,12 +33,17 @@ void usage() std::printf("profuse_pascal 0.1\n\n"); std::printf( "usage:\n" - "profuse_pascal [-w] [-f format] [-o options] diskimage [mountpoint]\n" - " -w mount writable [not yet]\n" - " -f format specify the disk image format. Valid values are:\n" - " dc42 DiskCopy 4.2 Image\n" - " do DOS Order Disk Image\n" - " po ProDOS Order Disk Image (default)\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" + " do DOS Order Disk Image\n" + " po ProDOS Order Disk Image (default)\n" + " -o opt1,opt2... other mount parameters.\n" ); } @@ -74,7 +79,8 @@ static struct fuse_opt pascal_options[] = { PASCAL_OPT_KEY("-w", readWrite, 1), PASCAL_OPT_KEY("rw", readWrite, 1), - PASCAL_OPT_KEY("-f %s", format, 0), + PASCAL_OPT_KEY("--format=%s", format, 0), + PASCAL_OPT_KEY("format=%s", format, 0), {0, 0, 0} }; @@ -170,8 +176,12 @@ int main(int argc, char **argv) } // default prodos-order disk image. - format = ProFUSE::DiskImage::ImageType(options.format); - + if (options.format) + { + format = ProFUSE::DiskImage::ImageType(options.format); + if (!format) + std::fprintf(stderr, "Warning: Unknown image type ``%s''\n", options.format); + } if (!format) format = ProFUSE::DiskImage::ImageType(fDiskImage.c_str(), 'PO__'); @@ -234,6 +244,8 @@ int main(int argc, char **argv) } #endif + fuse_opt_add_arg(&args, "-ofsname=PascalFS"); + if (!options.readOnly) fuse_opt_add_arg(&args, "-ordonly"); From 23e6ad6592891b8119fb0234b427657742b76e62 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 15 Dec 2009 20:04:14 +0000 Subject: [PATCH 053/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@172 aa027e90-d47c-11dd-86d7-074df07e0730 --- Endian.h => Endian/Endian.h | 0 {pascal => Endian}/IOBuffer.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename Endian.h => Endian/Endian.h (100%) rename {pascal => Endian}/IOBuffer.h (100%) diff --git a/Endian.h b/Endian/Endian.h similarity index 100% rename from Endian.h rename to Endian/Endian.h diff --git a/pascal/IOBuffer.h b/Endian/IOBuffer.h similarity index 100% rename from pascal/IOBuffer.h rename to Endian/IOBuffer.h From 7d8a4e990737b21d8e44ed6dae6254a5083db0f8 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 15 Dec 2009 20:16:28 +0000 Subject: [PATCH 054/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@173 aa027e90-d47c-11dd-86d7-074df07e0730 --- Endian/Endian.cpp | 105 ++++++++++++++++++++++++++++++++++++++++++ Endian/Endian.h | 94 +++++++------------------------------ Endian/IOBuffer.h | 70 +++------------------------- Endian/IOBuffer.t.cpp | 59 ++++++++++++++++++++++++ 4 files changed, 188 insertions(+), 140 deletions(-) create mode 100644 Endian/Endian.cpp create mode 100644 Endian/IOBuffer.t.cpp diff --git a/Endian/Endian.cpp b/Endian/Endian.cpp new file mode 100644 index 0000000..f45e356 --- /dev/null +++ b/Endian/Endian.cpp @@ -0,0 +1,105 @@ +#include "Endian.h" + +using namespace LittleEndian { + + + uint16_t Read16(const void *vp) + { + const uint8_t *p = (const uint8_t *)vp; + return p[0] | (p[1] << 8); + } + + uint32_t Read24(const void *vp) + { + const uint8_t *p = (const uint8_t *)vp; + return (p[0]) | (p[1] << 8) | (p[2] << 16); + } + + + uint32_t Read32(const void *vp) + { + const uint8_t *p = (const uint8_t *)vp; + return (p[0]) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); + } + + + + void Write16(void *vp, uint16_t x) + { + uint8_t *p = (uint8_t *)vp; + p[0] = (x) & 0xff; + p[1] = (x >> 8) & 0xff; + } + + void Write24(void *vp, uint32_t x) + { + uint8_t *p = (uint8_t *)vp; + p[0] = (x) & 0xff; + p[1] = (x >> 8) & 0xff; + p[2] = (x >> 16) & 0xff; + } + + void Write32(void *vp, uint32_t x) + { + uint8_t *p = (uint8_t *)vp; + p[0] = (x) & 0xff; + p[1] = (x >> 8) & 0xff; + p[2] = (x >> 16) & 0xff; + p[3] = (x >> 24) & 0xff; + } + + + + + +} + +using namespace BigEndian { + + + inline uint16_t Read16(const void *vp) + { + const uint8_t *p = (const uint8_t *)vp; + return (p[0] << 8) | (p[1]); + } + + inline uint32_t Read24(const void *vp) + { + const uint8_t *p = (const uint8_t *)vp; + return (p[0] << 16) | (p[1] << 8) | (p[2]); + } + + + inline uint32_t Read32(const void *vp) + { + const uint8_t *p = (const uint8_t *)vp; + return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); + } + + + inline void Write16(void *vp, uint16_t x) + { + uint8_t *p = (uint8_t *)vp; + p[0] = (x >> 8) & 0xff; + p[1] = (x) & 0xff; + } + + inline void Write24(void *vp, uint32_t x) + { + uint8_t *p = (uint8_t *)vp; + p[0] = (x >> 16) & 0xff; + p[1] = (x >> 8) & 0xff; + p[2] = (x) & 0xff; + } + + inline void Write32(void *vp, uint32_t x) + { + uint8_t *p = (uint8_t *)vp; + p[0] = (x >> 24) & 0xff; + p[1] = (x >> 16) & 0xff; + p[2] = (x >> 8) & 0xff; + p[3] = (x) & 0xff; + } + + +} \ No newline at end of file diff --git a/Endian/Endian.h b/Endian/Endian.h index 7241f7e..c917a7f 100644 --- a/Endian/Endian.h +++ b/Endian/Endian.h @@ -14,24 +14,11 @@ namespace LittleEndian { return (p[0]); } - inline uint16_t Read16(const void *vp) - { - const uint8_t *p = (const uint8_t *)vp; - return p[0] | (p[1] << 8); - } + uint16_t Read16(const void *vp); - inline uint32_t Read24(const void *vp) - { - const uint8_t *p = (const uint8_t *)vp; - return (p[0]) | (p[1] << 8) | (p[2] << 16); - } + uint32_t Read24(const void *vp); - - inline uint32_t Read32(const void *vp) - { - const uint8_t *p = (const uint8_t *)vp; - return (p[0]) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); - } + uint32_t Read32(const void *vp); inline uint8_t Read8(const void *vp, unsigned offset) @@ -62,29 +49,12 @@ namespace LittleEndian { p[0] = x; } - inline void Write16(void *vp, uint16_t x) - { - uint8_t *p = (uint8_t *)vp; - p[0] = (x) & 0xff; - p[1] = (x >> 8) & 0xff; - } + void Write16(void *vp, uint16_t x); + + void Write24(void *vp, uint32_t x); + + void Write32(void *vp, uint32_t x); - inline void Write24(void *vp, uint32_t x) - { - uint8_t *p = (uint8_t *)vp; - p[0] = (x) & 0xff; - p[1] = (x >> 8) & 0xff; - p[2] = (x >> 16) & 0xff; - } - - inline void Write32(void *vp, uint32_t x) - { - uint8_t *p = (uint8_t *)vp; - p[0] = (x) & 0xff; - p[1] = (x >> 8) & 0xff; - p[2] = (x >> 16) & 0xff; - p[3] = (x >> 24) & 0xff; - } inline void Write8(void *vp, unsigned offset, uint8_t x) { @@ -118,24 +88,11 @@ namespace BigEndian { return p[0]; } - inline uint16_t Read16(const void *vp) - { - const uint8_t *p = (const uint8_t *)vp; - return (p[0] << 8) | (p[1]); - } + uint16_t Read16(const void *vp); - inline uint32_t Read24(const void *vp) - { - const uint8_t *p = (const uint8_t *)vp; - return (p[0] << 16) | (p[1] << 8) | (p[2]); - } + uint32_t Read24(const void *vp); - - inline uint32_t Read32(const void *vp) - { - const uint8_t *p = (const uint8_t *)vp; - return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); - } + uint32_t Read32(const void *vp); inline uint8_t Read8(const void *vp, unsigned offset) @@ -167,30 +124,13 @@ namespace BigEndian { p[0] = x; } - inline void Write16(void *vp, uint16_t x) - { - uint8_t *p = (uint8_t *)vp; - p[0] = (x >> 8) & 0xff; - p[1] = (x) & 0xff; - } + void Write16(void *vp, uint16_t x); + + void Write24(void *vp, uint32_t x); + + void Write32(void *vp, uint32_t x); + - inline void Write24(void *vp, uint32_t x) - { - uint8_t *p = (uint8_t *)vp; - p[0] = (x >> 16) & 0xff; - p[1] = (x >> 8) & 0xff; - p[2] = (x) & 0xff; - } - - inline void Write32(void *vp, uint32_t x) - { - uint8_t *p = (uint8_t *)vp; - p[0] = (x >> 24) & 0xff; - p[1] = (x >> 16) & 0xff; - p[2] = (x >> 8) & 0xff; - p[3] = (x) & 0xff; - } - inline void Write8(void *vp, unsigned offset, uint8_t x) { Write8(offset + (uint8_t *)vp, x); diff --git a/Endian/IOBuffer.h b/Endian/IOBuffer.h index a923e0e..77092c9 100644 --- a/Endian/IOBuffer.h +++ b/Endian/IOBuffer.h @@ -1,71 +1,15 @@ #ifndef __IOBUFFER_H__ #define __IOBUFFER_H__ -#include "../Endian.h" - +#include "Endian.h" #include -namespace LittleEndian { - - class IOBuffer { - public: - - IOBuffer(void *vp, unsigned size) - { - _buffer = vp; - _size = size; - _offset = 0; - } - - void write8(uint8_t value) - { - Write8(_buffer, _offset, value); - _offset += 1; - } - void write16(uint16_t value) - { - Write16(_buffer, _offset, value); - _offset += 2; - } - - void write24(uint32_t value) - { - Write24(_buffer, _offset, value); - _offset += 3; - } - void write32(uint32_t value) - { - Write32(_buffer, _offset, value); - _offset += 4; - } - - void writeBytes(const void *value, unsigned count) - { - std::memcpy(_offset + (uint8_t *)_buffer, value, count); - _offset += count; - } - - void writeZero(unsigned count) - { - uint8_t *cp = _offset + (uint8_t *)_buffer; - for (unsigned i = 0; i < count; ++i) - { - cp[i] = 0; - } - _offset += count; - } - - unsigned offset() const { return _offset; } - void setOffset(unsigned offset) { _offset = offset; } - - unsigned size() const { return _size; } - - private: - void *_buffer; - unsigned _size; - unsigned _offset; - - }; +namespace LittleEndian { +#include "IOBuffer.t.cpp" +} + +namespace BigEndian { +#inclue "IOBuffer.t.cpp" } #endif \ No newline at end of file diff --git a/Endian/IOBuffer.t.cpp b/Endian/IOBuffer.t.cpp new file mode 100644 index 0000000..dfd4e6a --- /dev/null +++ b/Endian/IOBuffer.t.cpp @@ -0,0 +1,59 @@ + class IOBuffer { + public: + + IOBuffer(void *vp, unsigned size) + { + _buffer = vp; + _size = size; + _offset = 0; + } + + void write8(uint8_t value) + { + Write8(_buffer, _offset, value); + _offset += 1; + } + void write16(uint16_t value) + { + Write16(_buffer, _offset, value); + _offset += 2; + } + + void write24(uint32_t value) + { + Write24(_buffer, _offset, value); + _offset += 3; + } + void write32(uint32_t value) + { + Write32(_buffer, _offset, value); + _offset += 4; + } + + void writeBytes(const void *value, unsigned count) + { + std::memcpy(_offset + (uint8_t *)_buffer, value, count); + _offset += count; + } + + void writeZero(unsigned count) + { + uint8_t *cp = _offset + (uint8_t *)_buffer; + for (unsigned i = 0; i < count; ++i) + { + cp[i] = 0; + } + _offset += count; + } + + unsigned offset() const { return _offset; } + void setOffset(unsigned offset) { _offset = offset; } + + unsigned size() const { return _size; } + + private: + void *_buffer; + unsigned _size; + unsigned _offset; + + }; \ No newline at end of file From 7e9e3a5b447be9eb666f91d31ecf153b800e6f16 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 15 Dec 2009 20:22:23 +0000 Subject: [PATCH 055/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@174 aa027e90-d47c-11dd-86d7-074df07e0730 --- Endian/Endian.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Endian/Endian.cpp b/Endian/Endian.cpp index f45e356..bf57534 100644 --- a/Endian/Endian.cpp +++ b/Endian/Endian.cpp @@ -1,6 +1,6 @@ #include "Endian.h" -using namespace LittleEndian { +namespace LittleEndian { uint16_t Read16(const void *vp) @@ -54,7 +54,7 @@ using namespace LittleEndian { } -using namespace BigEndian { +namespace BigEndian { inline uint16_t Read16(const void *vp) From c80ef92da8f752d4437e196722e7957c97301875 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 15 Dec 2009 20:29:03 +0000 Subject: [PATCH 056/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@175 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/profuse_pascal.cpp => fuse_pascal.cpp | 0 pascal/profuse_pascal_ops.cpp => fuse_pascal_ops.cpp | 0 pascal/newfs_pascal.cpp => newfs_pascal.cpp | 0 pascal/FileMan.cpp => pascal_fileman.cpp | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename pascal/profuse_pascal.cpp => fuse_pascal.cpp (100%) rename pascal/profuse_pascal_ops.cpp => fuse_pascal_ops.cpp (100%) rename pascal/newfs_pascal.cpp => newfs_pascal.cpp (100%) rename pascal/FileMan.cpp => pascal_fileman.cpp (100%) diff --git a/pascal/profuse_pascal.cpp b/fuse_pascal.cpp similarity index 100% rename from pascal/profuse_pascal.cpp rename to fuse_pascal.cpp diff --git a/pascal/profuse_pascal_ops.cpp b/fuse_pascal_ops.cpp similarity index 100% rename from pascal/profuse_pascal_ops.cpp rename to fuse_pascal_ops.cpp diff --git a/pascal/newfs_pascal.cpp b/newfs_pascal.cpp similarity index 100% rename from pascal/newfs_pascal.cpp rename to newfs_pascal.cpp diff --git a/pascal/FileMan.cpp b/pascal_fileman.cpp similarity index 100% rename from pascal/FileMan.cpp rename to pascal_fileman.cpp From 98d80e4e3568bd0e41ba8b2286dbe27128e5412f Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 15 Dec 2009 20:44:50 +0000 Subject: [PATCH 057/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@176 aa027e90-d47c-11dd-86d7-074df07e0730 --- BlockCache.cpp => Device/BlockCache.cpp | 0 BlockCache.h => Device/BlockCache.h | 0 BlockDevice.cpp => Device/BlockDevice.cpp | 0 BlockDevice.h => Device/BlockDevice.h | 0 DavexDiskImage.cpp => Device/DavexDiskImage.cpp | 0 DavexDiskImage.h => Device/DavexDiskImage.h | 0 DiskCopy42Image.cpp => Device/DiskCopy42Image.cpp | 0 DiskCopy42Image.h => Device/DiskCopy42Image.h | 0 MappedFile.cpp => Device/MappedFile.cpp | 0 MappedFile.h => Device/MappedFile.h | 0 RawDevice.cpp => Device/RawDevice.cpp | 0 RawDevice.h => Device/RawDevice.h | 0 UniversalDiskImage.cpp => Device/UniversalDiskImage.cpp | 0 UniversalDiskImage.h => Device/UniversalDiskImage.h | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename BlockCache.cpp => Device/BlockCache.cpp (100%) rename BlockCache.h => Device/BlockCache.h (100%) rename BlockDevice.cpp => Device/BlockDevice.cpp (100%) rename BlockDevice.h => Device/BlockDevice.h (100%) rename DavexDiskImage.cpp => Device/DavexDiskImage.cpp (100%) rename DavexDiskImage.h => Device/DavexDiskImage.h (100%) rename DiskCopy42Image.cpp => Device/DiskCopy42Image.cpp (100%) rename DiskCopy42Image.h => Device/DiskCopy42Image.h (100%) rename MappedFile.cpp => Device/MappedFile.cpp (100%) rename MappedFile.h => Device/MappedFile.h (100%) rename RawDevice.cpp => Device/RawDevice.cpp (100%) rename RawDevice.h => Device/RawDevice.h (100%) rename UniversalDiskImage.cpp => Device/UniversalDiskImage.cpp (100%) rename UniversalDiskImage.h => Device/UniversalDiskImage.h (100%) diff --git a/BlockCache.cpp b/Device/BlockCache.cpp similarity index 100% rename from BlockCache.cpp rename to Device/BlockCache.cpp diff --git a/BlockCache.h b/Device/BlockCache.h similarity index 100% rename from BlockCache.h rename to Device/BlockCache.h diff --git a/BlockDevice.cpp b/Device/BlockDevice.cpp similarity index 100% rename from BlockDevice.cpp rename to Device/BlockDevice.cpp diff --git a/BlockDevice.h b/Device/BlockDevice.h similarity index 100% rename from BlockDevice.h rename to Device/BlockDevice.h diff --git a/DavexDiskImage.cpp b/Device/DavexDiskImage.cpp similarity index 100% rename from DavexDiskImage.cpp rename to Device/DavexDiskImage.cpp diff --git a/DavexDiskImage.h b/Device/DavexDiskImage.h similarity index 100% rename from DavexDiskImage.h rename to Device/DavexDiskImage.h diff --git a/DiskCopy42Image.cpp b/Device/DiskCopy42Image.cpp similarity index 100% rename from DiskCopy42Image.cpp rename to Device/DiskCopy42Image.cpp diff --git a/DiskCopy42Image.h b/Device/DiskCopy42Image.h similarity index 100% rename from DiskCopy42Image.h rename to Device/DiskCopy42Image.h diff --git a/MappedFile.cpp b/Device/MappedFile.cpp similarity index 100% rename from MappedFile.cpp rename to Device/MappedFile.cpp diff --git a/MappedFile.h b/Device/MappedFile.h similarity index 100% rename from MappedFile.h rename to Device/MappedFile.h diff --git a/RawDevice.cpp b/Device/RawDevice.cpp similarity index 100% rename from RawDevice.cpp rename to Device/RawDevice.cpp diff --git a/RawDevice.h b/Device/RawDevice.h similarity index 100% rename from RawDevice.h rename to Device/RawDevice.h diff --git a/UniversalDiskImage.cpp b/Device/UniversalDiskImage.cpp similarity index 100% rename from UniversalDiskImage.cpp rename to Device/UniversalDiskImage.cpp diff --git a/UniversalDiskImage.h b/Device/UniversalDiskImage.h similarity index 100% rename from UniversalDiskImage.h rename to Device/UniversalDiskImage.h From b29c12d0478663a3b9a4b8940464931d0b391666 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 15 Dec 2009 20:55:40 +0000 Subject: [PATCH 058/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@177 aa027e90-d47c-11dd-86d7-074df07e0730 --- Exception.cpp => ProFUSE/Exception.cpp | 0 Exception.h => ProFUSE/Exception.h | 0 Lock.cpp => ProFUSE/Lock.cpp | 0 Lock.h => ProFUSE/Lock.h | 0 auto.h => ProFUSE/auto.h | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename Exception.cpp => ProFUSE/Exception.cpp (100%) rename Exception.h => ProFUSE/Exception.h (100%) rename Lock.cpp => ProFUSE/Lock.cpp (100%) rename Lock.h => ProFUSE/Lock.h (100%) rename auto.h => ProFUSE/auto.h (100%) diff --git a/Exception.cpp b/ProFUSE/Exception.cpp similarity index 100% rename from Exception.cpp rename to ProFUSE/Exception.cpp diff --git a/Exception.h b/ProFUSE/Exception.h similarity index 100% rename from Exception.h rename to ProFUSE/Exception.h diff --git a/Lock.cpp b/ProFUSE/Lock.cpp similarity index 100% rename from Lock.cpp rename to ProFUSE/Lock.cpp diff --git a/Lock.h b/ProFUSE/Lock.h similarity index 100% rename from Lock.h rename to ProFUSE/Lock.h diff --git a/auto.h b/ProFUSE/auto.h similarity index 100% rename from auto.h rename to ProFUSE/auto.h From 81e532b25b8bc3148aff9674214806c21737cde8 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 15 Dec 2009 21:18:56 +0000 Subject: [PATCH 059/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@178 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal/Date.cpp | 7 +- pascal/Entry.cpp | 98 +++++++++ pascal/File.h | 10 +- pascal/{File.cpp => FileEntry.cpp} | 335 +---------------------------- pascal/VolumeEntry.cpp | 228 ++++++++++++++++++++ 5 files changed, 344 insertions(+), 334 deletions(-) create mode 100644 pascal/Entry.cpp rename pascal/{File.cpp => FileEntry.cpp} (50%) create mode 100644 pascal/VolumeEntry.cpp diff --git a/pascal/Date.cpp b/pascal/Date.cpp index fa30630..0d393a6 100644 --- a/pascal/Date.cpp +++ b/pascal/Date.cpp @@ -1,4 +1,4 @@ -#include "Date.h" +#include #include using namespace Pascal; @@ -25,6 +25,9 @@ Date::operator std::time_t() const { 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); } @@ -40,5 +43,5 @@ Date Date::Today() ::localtime_r(&t, &tm); - return Date(tm.tm_year, tm.tm_mon + 1, tm.tm_mday); + return Date(tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday); } \ No newline at end of file diff --git a/pascal/Entry.cpp b/pascal/Entry.cpp new file mode 100644 index 0000000..b0b5e83 --- /dev/null +++ b/pascal/Entry.cpp @@ -0,0 +1,98 @@ +#include + +#include +#include + +#include +#include + +#include +#include + + +#include +#include +#include +#include + +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; + _parent = 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); +} + + diff --git a/pascal/File.h b/pascal/File.h index 4464f2c..5a3e389 100644 --- a/pascal/File.h +++ b/pascal/File.h @@ -1,7 +1,7 @@ #ifndef __FILE_H__ #define __FILE_H__ -#include "Date.h" +#include #include @@ -79,10 +79,10 @@ class VolumeEntry : public Entry { public: // create new - VolumeEntry(const char *name, ProFUSE::BlockDevice *); + VolumeEntry(const char *name, Device::BlockDevice *); // open existing - VolumeEntry(ProFUSE::BlockDevice *); + VolumeEntry(Device::BlockDevice *); virtual ~VolumeEntry(); const char *name() const { return _fileName; } @@ -124,8 +124,8 @@ private: std::vector _files; unsigned _inodeGenerator; - ProFUSE::BlockDevice *_device; - ProFUSE::AbstractBlockCache *_cache; + Device::BlockDevice *_device; + Device::AbstractBlockCache *_cache; }; diff --git a/pascal/File.cpp b/pascal/FileEntry.cpp similarity index 50% rename from pascal/File.cpp rename to pascal/FileEntry.cpp index b305ae9..2889b56 100644 --- a/pascal/File.cpp +++ b/pascal/FileEntry.cpp @@ -1,11 +1,12 @@ -#include "File.h" -#include "../auto.h" -#include "../Endian.h" -#include "../BlockDevice.h" -#include "../BlockCache.h" -#include "../Exception.h" +#include -#include "IOBuffer.h" +#include +#include + +#include + +#include +#include #include #include @@ -15,325 +16,6 @@ using namespace LittleEndian; using namespace Pascal; -/* -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; } -*/ - - -#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; - _parent = 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); -} - - -#pragma mark - -#pragma mark VolumeEntry - -unsigned VolumeEntry::ValidName(const char *cp) -{ - // 7 chars max. Legal values: ascii, printable, - // no space/tab, - // no $=?,: - - return Entry::ValidName(cp, 7); -} - -VolumeEntry::VolumeEntry() -{ - _fileNameLength = 0; - std::memset(_fileName, 0, 8); - _lastVolumeBlock = 0; - _fileCount = 0; - _accessTime = 0; - - setInode(1); - - _inodeGenerator = 1; - _cache = NULL; - _device = NULL; -} - -VolumeEntry::VolumeEntry(const char *name, ProFUSE::BlockDevice *device) -{ -#undef __METHOD__ -#define __METHOD__ "VolumeEntry::VolumeEntry" - - unsigned length; - length = ValidName(name); - - if (!length) - throw ProFUSE::Exception(__METHOD__ ": Invalid volume name."); - - _firstBlock = 0; - _lastBlock = 6; - _fileKind = kUntypedFile; - _inode = 1; - _inodeGenerator = 1; - - _fileNameLength = length; - - std::memset(_fileName, 0, sizeof(_fileName)); - for (unsigned i = 0; i < _fileNameLength; ++i) - { - _fileName[i] = std::toupper(name[i]); - } - - _lastVolumeBlock = device->blocks(); - _fileCount = 0; - _accessTime = 0; - _lastBoot = Date::Today(); - - _cache = device->blockCache(); - _device = device; - - for (unsigned i = 2; i < 6; ++i) - { - device->zeroBlock(i); - } - - void *vp = _cache->load(2); - IOBuffer b(vp, 0x1a); - - writeDirectoryEntry(&b); - - _cache->unload(2, true); - -} - - -VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device) -{ - auto_array buffer(new uint8_t[512]); - unsigned blockCount; - - // read the header block, then load up all the header - // blocks. - - _device = device; - _cache = device->blockCache(); - - device->read(2, buffer.get()); - - init(buffer.get()); - - // todo -- verify reasonable values. - - //printf("%u %u\n", blocks(), _lastBlock - _firstBlock); - - // why the fuck didn't this work???? - blockCount = blocks(); - - if (blockCount > 1) - { - buffer.reset(new uint8_t[512 * blockCount]); - - for (unsigned i = 0; i < blockCount; ++i) - { - device->read(2 + i, buffer.get() + 512 * i); - } - } - - // now load up all the children. - // if this throws, memory could be lost... - - - try - { - - for (unsigned i = 1; i <= _fileCount; ++i) - { - std::auto_ptr child; - - // - child.reset(new FileEntry(buffer.get() + i * 0x1a)); - - child->setInode(++_inodeGenerator); - child->_parent = this; - _files.push_back(child.release()); - } - } - catch (...) - { - std::vector::iterator iter; - for(iter = _files.begin(); iter != _files.end(); ++iter) - { - if (*iter) delete *iter; - } - - throw; - } - - -} - -VolumeEntry::~VolumeEntry() -{ - std::vector::iterator iter; - for(iter = _files.begin(); iter != _files.end(); ++iter) - { - if (*iter) delete *iter; - } - - // _blockCache does not need deleting. - delete _device; -} - - -void VolumeEntry::init(void *vp) -{ - Entry::init(vp); - _fileNameLength = Read8(vp, 6); - - // verify filenamelength <= 7 - // verify fileKind == 0 - - std::memcpy(_fileName, 7 + (uint8_t *)vp, _fileNameLength); - - _lastVolumeBlock = Read16(vp, 0x0e); - _fileCount = Read16(vp, 0x10); - _accessTime = Read16(vp, 0x12); - _lastBoot = Date(Read16(vp, 0x14)); - - setInode(1); - _inodeGenerator = 1; -} - - -FileEntry *VolumeEntry::fileAtIndex(unsigned i) const -{ - return i < _files.size() ? _files[i] : NULL; -} - - - -void *VolumeEntry::loadBlock(unsigned block) -{ - return _cache->load(block); -} -void VolumeEntry::unloadBlock(unsigned block, bool dirty) -{ - return _cache->unload(block, dirty); -} - -void VolumeEntry::readBlock(unsigned block, void *buffer) -{ - _device->read(block, buffer); -} -void VolumeEntry::writeBlock(unsigned block, void *buffer) -{ - _device->write(block, buffer); -} - - - -void VolumeEntry::writeDirectoryEntry(IOBuffer *b) -{ - Entry::writeDirectoryEntry(b); - - b->write8(0); // reserved - b->write8(_fileNameLength); - b->writeBytes(_fileName, 7); - b->write16(_lastVolumeBlock); - b->write16(_fileCount); - b->write16(_accessTime); - b->write16(_lastBoot); - - // rest is reserved. - b->writeZero(4); -} #pragma mark - #pragma mark FileEntry @@ -655,4 +337,3 @@ void FileEntry::textInit() _pageSize->push_back(size); } } - diff --git a/pascal/VolumeEntry.cpp b/pascal/VolumeEntry.cpp new file mode 100644 index 0000000..a4d3386 --- /dev/null +++ b/pascal/VolumeEntry.cpp @@ -0,0 +1,228 @@ +#include + +#include +#include + +#include +#include + +#include +#include + +#pragma mark - +#pragma mark VolumeEntry + +unsigned VolumeEntry::ValidName(const char *cp) +{ + // 7 chars max. Legal values: ascii, printable, + // no space/tab, + // no $=?,: + + return Entry::ValidName(cp, 7); +} + +VolumeEntry::VolumeEntry() +{ + _fileNameLength = 0; + std::memset(_fileName, 0, 8); + _lastVolumeBlock = 0; + _fileCount = 0; + _accessTime = 0; + + setInode(1); + + _inodeGenerator = 1; + _cache = NULL; + _device = NULL; +} + +VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device) +{ +#undef __METHOD__ +#define __METHOD__ "VolumeEntry::VolumeEntry" + + unsigned length; + length = ValidName(name); + + if (!length) + throw ProFUSE::Exception(__METHOD__ ": Invalid volume name."); + + _firstBlock = 0; + _lastBlock = 6; + _fileKind = kUntypedFile; + _inode = 1; + _inodeGenerator = 1; + + _fileNameLength = length; + + std::memset(_fileName, 0, sizeof(_fileName)); + for (unsigned i = 0; i < _fileNameLength; ++i) + { + _fileName[i] = std::toupper(name[i]); + } + + _lastVolumeBlock = device->blocks(); + _fileCount = 0; + _accessTime = 0; + _lastBoot = Date::Today(); + + _cache = device->blockCache(); + _device = device; + + for (unsigned i = 2; i < 6; ++i) + { + device->zeroBlock(i); + } + + void *vp = _cache->load(2); + IOBuffer b(vp, 0x1a); + + writeDirectoryEntry(&b); + + _cache->unload(2, true); + +} + + +VolumeEntry::VolumeEntry(Device::BlockDevice *device) +{ + auto_array buffer(new uint8_t[512]); + unsigned blockCount; + + // read the header block, then load up all the header + // blocks. + + _device = device; + _cache = device->blockCache(); + + device->read(2, buffer.get()); + + init(buffer.get()); + + // todo -- verify reasonable values. + + //printf("%u %u\n", blocks(), _lastBlock - _firstBlock); + + // why the fuck didn't this work???? + blockCount = blocks(); + + if (blockCount > 1) + { + buffer.reset(new uint8_t[512 * blockCount]); + + for (unsigned i = 0; i < blockCount; ++i) + { + device->read(2 + i, buffer.get() + 512 * i); + } + } + + // now load up all the children. + // if this throws, memory could be lost... + + + try + { + + for (unsigned i = 1; i <= _fileCount; ++i) + { + std::auto_ptr child; + + // + child.reset(new FileEntry(buffer.get() + i * 0x1a)); + + child->setInode(++_inodeGenerator); + child->_parent = this; + _files.push_back(child.release()); + } + } + catch (...) + { + std::vector::iterator iter; + for(iter = _files.begin(); iter != _files.end(); ++iter) + { + if (*iter) delete *iter; + } + + throw; + } + + +} + +VolumeEntry::~VolumeEntry() +{ + std::vector::iterator iter; + for(iter = _files.begin(); iter != _files.end(); ++iter) + { + if (*iter) delete *iter; + } + + // _blockCache does not need deleting. + delete _device; +} + + +void VolumeEntry::init(void *vp) +{ + Entry::init(vp); + _fileNameLength = Read8(vp, 6); + + // verify filenamelength <= 7 + // verify fileKind == 0 + + std::memcpy(_fileName, 7 + (uint8_t *)vp, _fileNameLength); + + _lastVolumeBlock = Read16(vp, 0x0e); + _fileCount = Read16(vp, 0x10); + _accessTime = Read16(vp, 0x12); + _lastBoot = Date(Read16(vp, 0x14)); + + setInode(1); + _inodeGenerator = 1; +} + + +FileEntry *VolumeEntry::fileAtIndex(unsigned i) const +{ + return i < _files.size() ? _files[i] : NULL; +} + + + +void *VolumeEntry::loadBlock(unsigned block) +{ + return _cache->load(block); +} +void VolumeEntry::unloadBlock(unsigned block, bool dirty) +{ + return _cache->unload(block, dirty); +} + +void VolumeEntry::readBlock(unsigned block, void *buffer) +{ + _device->read(block, buffer); +} +void VolumeEntry::writeBlock(unsigned block, void *buffer) +{ + _device->write(block, buffer); +} + + + +void VolumeEntry::writeDirectoryEntry(IOBuffer *b) +{ + Entry::writeDirectoryEntry(b); + + b->write8(0); // reserved + b->write8(_fileNameLength); + b->writeBytes(_fileName, 7); + b->write16(_lastVolumeBlock); + b->write16(_fileCount); + b->write16(_accessTime); + b->write16(_lastBoot); + + // rest is reserved. + b->writeZero(4); +} + + From 5a0fc071a51b19e2f3e97511e6dc5fb59c592e60 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 15 Dec 2009 21:47:05 +0000 Subject: [PATCH 060/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@179 aa027e90-d47c-11dd-86d7-074df07e0730 --- {pascal => Pascal}/Date.cpp | 0 {pascal => Pascal}/Date.h | 0 {pascal => Pascal}/Entry.cpp | 0 {pascal => Pascal}/File.h | 0 {pascal => Pascal}/FileEntry.cpp | 0 {pascal => Pascal}/Makefile | 0 {pascal => Pascal}/TextFile.cpp | 0 {pascal => Pascal}/TextFile.h | 0 {pascal => Pascal}/VolumeEntry.cpp | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename {pascal => Pascal}/Date.cpp (100%) rename {pascal => Pascal}/Date.h (100%) rename {pascal => Pascal}/Entry.cpp (100%) rename {pascal => Pascal}/File.h (100%) rename {pascal => Pascal}/FileEntry.cpp (100%) rename {pascal => Pascal}/Makefile (100%) rename {pascal => Pascal}/TextFile.cpp (100%) rename {pascal => Pascal}/TextFile.h (100%) rename {pascal => Pascal}/VolumeEntry.cpp (100%) diff --git a/pascal/Date.cpp b/Pascal/Date.cpp similarity index 100% rename from pascal/Date.cpp rename to Pascal/Date.cpp diff --git a/pascal/Date.h b/Pascal/Date.h similarity index 100% rename from pascal/Date.h rename to Pascal/Date.h diff --git a/pascal/Entry.cpp b/Pascal/Entry.cpp similarity index 100% rename from pascal/Entry.cpp rename to Pascal/Entry.cpp diff --git a/pascal/File.h b/Pascal/File.h similarity index 100% rename from pascal/File.h rename to Pascal/File.h diff --git a/pascal/FileEntry.cpp b/Pascal/FileEntry.cpp similarity index 100% rename from pascal/FileEntry.cpp rename to Pascal/FileEntry.cpp diff --git a/pascal/Makefile b/Pascal/Makefile similarity index 100% rename from pascal/Makefile rename to Pascal/Makefile diff --git a/pascal/TextFile.cpp b/Pascal/TextFile.cpp similarity index 100% rename from pascal/TextFile.cpp rename to Pascal/TextFile.cpp diff --git a/pascal/TextFile.h b/Pascal/TextFile.h similarity index 100% rename from pascal/TextFile.h rename to Pascal/TextFile.h diff --git a/pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp similarity index 100% rename from pascal/VolumeEntry.cpp rename to Pascal/VolumeEntry.cpp From 6400af5fc8588b3e1635eb4a7be697cb78254458 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 15 Dec 2009 22:07:45 +0000 Subject: [PATCH 061/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@180 aa027e90-d47c-11dd-86d7-074df07e0730 --- ProFUSE/Exception.cpp | 2 +- ProFUSE/Lock.cpp | 4 +++- ProFUSE/Lock.h | 7 ++++++- ProFUSE/auto.h | 3 +++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ProFUSE/Exception.cpp b/ProFUSE/Exception.cpp index ee0cbee..3dad581 100644 --- a/ProFUSE/Exception.cpp +++ b/ProFUSE/Exception.cpp @@ -1,5 +1,5 @@ -#include "Exception.h" +#include using namespace ProFUSE; diff --git a/ProFUSE/Lock.cpp b/ProFUSE/Lock.cpp index ddd9fa4..0b6013b 100644 --- a/ProFUSE/Lock.cpp +++ b/ProFUSE/Lock.cpp @@ -1,4 +1,6 @@ -#include "Lock.h" +#include + +using namespace ProFUSE; Lock::Lock() { diff --git a/ProFUSE/Lock.h b/ProFUSE/Lock.h index cbb3bc7..8e32a80 100644 --- a/ProFUSE/Lock.h +++ b/ProFUSE/Lock.h @@ -3,6 +3,8 @@ #include +namespace ProFUSE { + class Lock { public: Lock(); @@ -25,4 +27,7 @@ private: Lock &_lock; }; -#endif \ No newline at end of file + +} + +#endif diff --git a/ProFUSE/auto.h b/ProFUSE/auto.h index f23c3c2..1137687 100644 --- a/ProFUSE/auto.h +++ b/ProFUSE/auto.h @@ -1,6 +1,8 @@ #ifndef __AUTO_H__ #define __AUTO_H__ +namespace ProFUSE { + template class auto_array { @@ -94,6 +96,7 @@ private: }; #endif +} #endif From c127bd185c177cd1edbf3a2b0a5427905a4bb223 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 15 Dec 2009 22:09:07 +0000 Subject: [PATCH 062/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@181 aa027e90-d47c-11dd-86d7-074df07e0730 --- ProFUSE/auto.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ProFUSE/auto.h b/ProFUSE/auto.h index 1137687..e7c6876 100644 --- a/ProFUSE/auto.h +++ b/ProFUSE/auto.h @@ -1,6 +1,8 @@ #ifndef __AUTO_H__ #define __AUTO_H__ +#include + namespace ProFUSE { template From 70dfd5b48572d4c668efde148d0a12f66a7c081f Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 15 Dec 2009 22:11:14 +0000 Subject: [PATCH 063/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@182 aa027e90-d47c-11dd-86d7-074df07e0730 --- Endian/Endian.cpp | 2 +- Endian/IOBuffer.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Endian/Endian.cpp b/Endian/Endian.cpp index bf57534..5d21622 100644 --- a/Endian/Endian.cpp +++ b/Endian/Endian.cpp @@ -1,4 +1,4 @@ -#include "Endian.h" +#include namespace LittleEndian { diff --git a/Endian/IOBuffer.h b/Endian/IOBuffer.h index 77092c9..19d1e0b 100644 --- a/Endian/IOBuffer.h +++ b/Endian/IOBuffer.h @@ -1,7 +1,7 @@ #ifndef __IOBUFFER_H__ #define __IOBUFFER_H__ -#include "Endian.h" +#include #include namespace LittleEndian { @@ -9,7 +9,7 @@ namespace LittleEndian { } namespace BigEndian { -#inclue "IOBuffer.t.cpp" +#include "IOBuffer.t.cpp" } #endif \ No newline at end of file From bd063227e2325fd154def7ceddafa2577f2d87f2 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 16 Dec 2009 01:33:28 +0000 Subject: [PATCH 064/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@183 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/BlockCache.cpp | 16 ++++++----- Device/BlockCache.h | 2 +- Device/BlockDevice.cpp | 17 ++++++++---- Device/BlockDevice.h | 4 +-- Device/DavexDiskImage.cpp | 51 ++++++++++++++++++++--------------- Device/DavexDiskImage.h | 12 ++++++--- Device/DiskCopy42Image.cpp | 41 +++++++++++++++++----------- Device/DiskCopy42Image.h | 4 +-- Device/MappedFile.cpp | 22 +++++++-------- Device/MappedFile.h | 2 +- Device/RawDevice.cpp | 13 +++++---- Device/RawDevice.h | 4 +-- Device/UniversalDiskImage.cpp | 38 +++++++++++++++----------- Device/UniversalDiskImage.h | 4 +-- 14 files changed, 136 insertions(+), 94 deletions(-) diff --git a/Device/BlockCache.cpp b/Device/BlockCache.cpp index 8971383..75f8b44 100644 --- a/Device/BlockCache.cpp +++ b/Device/BlockCache.cpp @@ -6,10 +6,11 @@ #include #include -#include "BlockDevice.h" -#include "BlockCache.h" -#include "Exception.h" -#include "auto.h" +#include +#include + +#include +#include /* @@ -19,7 +20,10 @@ -using namespace ProFUSE; +using namespace Device; + +using ProFUSE::Exception; +using ProFUSE::POSIXException; #pragma mark - #pragma mark AbstractBlockCache @@ -162,7 +166,7 @@ void *BlockCache::load(unsigned block) } - auto_array buffer(new uint8_t[512]); + ProFUSE::auto_array buffer(new uint8_t[512]); BlockDescriptor bd = { block, 1, _ts, false, buffer.get() }; _device->read(block, buffer.get()); diff --git a/Device/BlockCache.h b/Device/BlockCache.h index 36b4066..3983f1c 100644 --- a/Device/BlockCache.h +++ b/Device/BlockCache.h @@ -4,7 +4,7 @@ #include #include -namespace ProFUSE { +namespace Device { class BlockDevice; diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index df17519..1c556d6 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -1,7 +1,3 @@ -#include "BlockDevice.h" -#include "BlockCache.h" -#include "Exception.h" -#include "MappedFile.h" #include #include @@ -11,7 +7,18 @@ #include #include -using namespace ProFUSE; + +#include +#include +#include + +#include + + +using namespace Device; + +using ProFUSE::Exception; +using ProFUSE::POSIXException; #pragma mark - #pragma mark BlockDevice diff --git a/Device/BlockDevice.h b/Device/BlockDevice.h index c76a713..41d899e 100644 --- a/Device/BlockDevice.h +++ b/Device/BlockDevice.h @@ -4,9 +4,9 @@ #include #include -#include "Exception.h" +#include -namespace ProFUSE { +namespace Device { class MappedFile; class AbstractBlockCache; diff --git a/Device/DavexDiskImage.cpp b/Device/DavexDiskImage.cpp index fafb8a9..1e02e4b 100644 --- a/Device/DavexDiskImage.cpp +++ b/Device/DavexDiskImage.cpp @@ -1,7 +1,3 @@ -#include "DavexDiskImage.h" -#include "MappedFile.h" -#include "Buffer.h" -#include "Endian.h" #include #include @@ -11,9 +7,19 @@ #include #include -using namespace ProFUSE; +#include +#include + +#include +#include + + +using namespace Device; using namespace LittleEndian; +using ProFUSE::Exception; +using ProFUSE::POSIXException; + /* http://www.umich.edu/~archive/apple2/technotes/ftn/FTN.E0.8004 */ @@ -99,50 +105,51 @@ DavexDiskImage *DavexDiskImage::Create(const char *name, size_t blocks, const ch #define __METHOD__ "DavexDiskImage::Create" uint8_t *data; + uint8_t tmp[512]; + IOBuffer header(tmp,512); + MappedFile *file = new MappedFile(name, blocks * 512 + 512); data = (uint8_t *)file->fileData(); - - Buffer header(512); - - header.pushBytes(IdentityCheck, 16); + + header.writeBytes(IdentityCheck, 16); // file Format - header.push8(0); + header.write8(0); //version - header.push8(0); + header.write8(0); // version - header.push8(0x10); + header.write8(0x10); // reserved. - header.resize(32); + header.setOffset(32, true); //deviceNum - header.push8(1); + header.write8(1); // total blocks - header.push32le(blocks); + header.write32(blocks); // unused blocks - header.push32le(0); + header.write32(0); // volume Name if (!vname || !*vname) vname = "Untitled"; unsigned l = std::strlen(vname); - header.push8(std::min(l, 15u)); - header.pushBytes(vname, std::min(l, 15u)); + header.write8(std::min(l, 15u)); + header.writeBytes(vname, std::min(l, 15u)); // name + reserved. - header.resize(64); + header.setOffset(64, true); // file number - header.push8(1); + header.write8(1); //starting block - header.push32le(0); + header.write32(0); // reserved - header.resize(512); + header.setOffset(512, true); std::memcpy(file->fileData(), header.buffer(), 512); diff --git a/Device/DavexDiskImage.h b/Device/DavexDiskImage.h index 5f75934..1f7122b 100644 --- a/Device/DavexDiskImage.h +++ b/Device/DavexDiskImage.h @@ -1,9 +1,11 @@ +#ifndef __DAVEXDISKIMAGE_H__ +#define __DAVEXDISKIMAGE_H__ - -#include "BlockDevice.h" #include -namespace ProFUSE { +#include + +namespace Device { // only supports 1 file; may be split over multiple files. @@ -28,4 +30,6 @@ private: }; -} \ No newline at end of file +} + +#endif diff --git a/Device/DiskCopy42Image.cpp b/Device/DiskCopy42Image.cpp index 5502130..a3b441c 100644 --- a/Device/DiskCopy42Image.cpp +++ b/Device/DiskCopy42Image.cpp @@ -1,15 +1,22 @@ -#include "DiskCopy42Image.h" -#include "MappedFile.h" -#include "Buffer.h" -#include "Endian.h" + #include #include #include -using namespace ProFUSE; +#include +#include + +#include +#include + +using namespace Device; using namespace BigEndian; + +using ProFUSE::Exception; +using ProFUSE::POSIXException; + DiskCopy42Image::DiskCopy42Image(MappedFile *f) : DiskImage(f), _changed(false) @@ -97,30 +104,32 @@ DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks, const file->setOffset(84); file->setBlocks(blocks); - Buffer header(84); + uint8_t tmp[84]; + IOBuffer header(tmp, 84); // name -- 64byte pstring. if (vname == NULL) vname = "Untitled"; unsigned l = std::strlen(vname); - header.push8(std::min(l, 63u)); - header.pushBytes(vname, std::min(l, 63u)); + header.write8(std::min(l, 63u)); + header.writeBytes(vname, std::min(l, 63u)); - header.resize(64); + //header.resize(64); + header.setOffset(64, true); // data size -- number of bytes - header.push32be(blocks * 512); + header.write32(blocks * 512); // tag size - header.push32be(0); + header.write32(0); // data checksum // if data is 0, will be 0. //header.push32be(Checksum(file->fileData(), blocks * 512)); - header.push32be(0); + header.write32(0); // tag checksum - header.push32be(0); + header.write32(0); // disk format. /* @@ -130,7 +139,7 @@ DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks, const * 3 = 1440k * 0xff = other */ - header.push8(DiskFormat(blocks)); + header.write8(DiskFormat(blocks)); // formatbyte /* @@ -138,10 +147,10 @@ DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks, const * 0x22 = >400k mac * 0x24 = 800k appleII */ - header.push8(FormatByte(blocks)); + header.write8(FormatByte(blocks)); // private - header.push16be(0x100); + header.write16(0x100); std::memcpy(file->fileData(), header.buffer(), 84); file->sync(); diff --git a/Device/DiskCopy42Image.h b/Device/DiskCopy42Image.h index 7a80f87..8511c16 100644 --- a/Device/DiskCopy42Image.h +++ b/Device/DiskCopy42Image.h @@ -1,11 +1,11 @@ #ifndef __DISKCOPY42IMAGE_H__ #define __DISKCOPY42IMAGE_H__ -#include "BlockDevice.h" +#include #include -namespace ProFUSE { +namespace Device { class DiskCopy42Image : public DiskImage { public: diff --git a/Device/MappedFile.cpp b/Device/MappedFile.cpp index 3c16710..c0029da 100644 --- a/Device/MappedFile.cpp +++ b/Device/MappedFile.cpp @@ -1,6 +1,3 @@ -#include "MappedFile.h" -#include "Exception.h" - #include #include #include @@ -9,10 +6,14 @@ #include #include -#include "auto.h" +#include -using namespace ProFUSE; +#include +#include +using namespace Device; +using ProFUSE::POSIXException; +using ProFUSE::Exception; MappedFile::MappedFile(const char *name, bool readOnly) @@ -23,7 +24,7 @@ MappedFile::MappedFile(const char *name, bool readOnly) // if unable to open as read/write, open as read-only. - auto_fd fd; + ProFUSE::auto_fd fd; if (!readOnly) { @@ -61,7 +62,7 @@ MappedFile::MappedFile(const char *name, size_t size) _readOnly = false; _encoding = ProDOSOrder; - auto_fd fd(::open(name, O_CREAT | O_TRUNC | O_RDWR, 0644)); + ProFUSE::auto_fd fd(::open(name, O_CREAT | O_TRUNC | O_RDWR, 0644)); if (fd < 0) throw POSIXException(__METHOD__ ": Unable to create file.", errno); @@ -74,7 +75,7 @@ MappedFile::MappedFile(const char *name, size_t size) //_map = ::mmap(NULL, _size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, _fd, 0); - auto_map map( + ProFUSE::auto_map map( NULL, _size, PROT_READ | PROT_WRITE, @@ -101,8 +102,7 @@ void MappedFile::init(int f, bool readOnly) #undef __METHOD__ #define __METHOD__ "MappedFile::init" - //auto_fd fd(f); - + _fd = -1; _map = MAP_FAILED; _offset = 0; @@ -122,7 +122,7 @@ void MappedFile::init(int f, bool readOnly) ::lseek(f, 0, SEEK_SET); - auto_map map( + ProFUSE::auto_map map( NULL, _size, readOnly ? PROT_READ : PROT_READ | PROT_WRITE, diff --git a/Device/MappedFile.h b/Device/MappedFile.h index ce2c768..5f10984 100644 --- a/Device/MappedFile.h +++ b/Device/MappedFile.h @@ -5,7 +5,7 @@ #include #include -namespace ProFUSE { +namespace Device { class MappedFile { diff --git a/Device/RawDevice.cpp b/Device/RawDevice.cpp index bc19ce5..9047f17 100644 --- a/Device/RawDevice.cpp +++ b/Device/RawDevice.cpp @@ -20,12 +20,15 @@ #include #endif +#include -#include "RawDevice.h" -#include "auto.h" -#include "Exception.h" +#include +#include -using namespace ProFUSE; +using namespace Device; + +using ProFUSE::Exception; +using ProFUSE::POSIXException; #ifdef __SUN__ void RawDevice::devSize(int fd) @@ -100,7 +103,7 @@ RawDevice::RawDevice(const char *name, bool readOnly) // open read-only, verify if device is readable, and then try to upgrade to read/write? - auto_fd fd; + ProFUSE::auto_fd fd; if (!readOnly) fd.reset(::open(name, O_RDWR)); if (fd < 0) diff --git a/Device/RawDevice.h b/Device/RawDevice.h index b2bafe9..dfbeb8f 100644 --- a/Device/RawDevice.h +++ b/Device/RawDevice.h @@ -3,9 +3,9 @@ #include -#include "BlockDevice.h" +#include -namespace ProFUSE { +namespace Device { // /dev/xxx diff --git a/Device/UniversalDiskImage.cpp b/Device/UniversalDiskImage.cpp index 0e077c7..f624960 100644 --- a/Device/UniversalDiskImage.cpp +++ b/Device/UniversalDiskImage.cpp @@ -1,11 +1,17 @@ -#include "UniversalDiskImage.h" -#include "MappedFile.h" -#include "Buffer.h" -#include "Endian.h" +#include +#include -using namespace ProFUSE; +#include +#include + +#include + +using namespace Device; using namespace LittleEndian; +using ProFUSE::Exception; +using ProFUSE::POSIXException; + UniversalDiskImage::UniversalDiskImage(const char *name, bool readOnly) : DiskImage(name, readOnly) { @@ -27,35 +33,37 @@ UniversalDiskImage *UniversalDiskImage::Create(const char *name, size_t blocks) // 64-byte header. MappedFile *file = new MappedFile(name, blocks * 512 + 64); - Buffer header(64); + uint8_t tmp[64]; + + IOBuffer header(tmp, 64); // magic + creator - header.pushBytes("2IMGPRFS", 8); + header.writeBytes("2IMGPRFS", 8); // header size. - header.push16le(64); + header.write16(64); // version - header.push16le(1); + header.write16(1); //image format -- ProDOS order - header.push32le(1); + header.write32(1); // flags - header.push32le(0); + header.write32(0); // # blocks. s/b 0 unless prodos-order - header.push32le(blocks); + header.write32(blocks); // offset to disk data - header.push32le(64); + header.write32(64); // data length - header.push32le(512 * blocks); + header.write32(512 * blocks); // comment offset, creator, reserved -- 0. - header.resize(64); + header.setOffset(64, true); std::memcpy(file->fileData(), header.buffer(), 64); diff --git a/Device/UniversalDiskImage.h b/Device/UniversalDiskImage.h index 1bcac1b..875105b 100644 --- a/Device/UniversalDiskImage.h +++ b/Device/UniversalDiskImage.h @@ -2,10 +2,10 @@ #define __UNIVERSALDISKIMAGE_H__ -#include "BlockDevice.h" +#include #include -namespace ProFUSE { +namespace Device { class UniversalDiskImage : public DiskImage { public: From d10aacbe935af98e777dd0e244e095ae213a1466 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 16 Dec 2009 01:34:33 +0000 Subject: [PATCH 065/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@184 aa027e90-d47c-11dd-86d7-074df07e0730 --- Endian/IOBuffer.t.cpp | 18 +++++++++++++----- DateTime.cpp => ProDOS/DateTime.cpp | 0 DateTime.h => ProDOS/DateTime.h | 0 3 files changed, 13 insertions(+), 5 deletions(-) rename DateTime.cpp => ProDOS/DateTime.cpp (100%) rename DateTime.h => ProDOS/DateTime.h (100%) diff --git a/Endian/IOBuffer.t.cpp b/Endian/IOBuffer.t.cpp index dfd4e6a..54de16a 100644 --- a/Endian/IOBuffer.t.cpp +++ b/Endian/IOBuffer.t.cpp @@ -38,19 +38,27 @@ void writeZero(unsigned count) { - uint8_t *cp = _offset + (uint8_t *)_buffer; - for (unsigned i = 0; i < count; ++i) - { - cp[i] = 0; - } + std::memset(_offset + (uint8_t *)_buffer, 0, count); + _offset += count; } unsigned offset() const { return _offset; } void setOffset(unsigned offset) { _offset = offset; } + void setOffset(unsigned offset, bool zero) + { + if (zero && offset > _offset) + { + writeZero(offset - _offset); + } + else setOffset(offset); + } + unsigned size() const { return _size; } + void *buffer() const { return _buffer; } + private: void *_buffer; unsigned _size; diff --git a/DateTime.cpp b/ProDOS/DateTime.cpp similarity index 100% rename from DateTime.cpp rename to ProDOS/DateTime.cpp diff --git a/DateTime.h b/ProDOS/DateTime.h similarity index 100% rename from DateTime.h rename to ProDOS/DateTime.h From 7fa5712533fc142f1ac9ab4fae7400e169ca3d77 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 16 Dec 2009 01:35:42 +0000 Subject: [PATCH 066/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@185 aa027e90-d47c-11dd-86d7-074df07e0730 --- ProDOS/DateTime.cpp | 5 +++-- ProDOS/DateTime.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ProDOS/DateTime.cpp b/ProDOS/DateTime.cpp index bacf62b..7a8ce55 100644 --- a/ProDOS/DateTime.cpp +++ b/ProDOS/DateTime.cpp @@ -1,11 +1,12 @@ -#include "DateTime.h" #include #include #include -using namespace ProFUSE; +#include + +using namespace ProDOS; /* * date is a 16 bit value: diff --git a/ProDOS/DateTime.h b/ProDOS/DateTime.h index 24055d4..9f3aa78 100644 --- a/ProDOS/DateTime.h +++ b/ProDOS/DateTime.h @@ -4,7 +4,7 @@ #include #include -namespace ProFUSE { +namespace ProDOS { class DateTime { From 2e2d38e8c559995ab4e61178b3ccea4e751ea88e Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 19 Dec 2009 18:31:46 +0000 Subject: [PATCH 067/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@186 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal_fileman.cpp | 59 ++++++++++------------------------------------ 1 file changed, 12 insertions(+), 47 deletions(-) diff --git a/pascal_fileman.cpp b/pascal_fileman.cpp index f06ca52..f603df2 100644 --- a/pascal_fileman.cpp +++ b/pascal_fileman.cpp @@ -16,49 +16,12 @@ #include #include -#include "File.h" -#include "Date.h" -#include "../BlockDevice.h" -#include "../DiskCopy42Image.h" +#include +#include +#include +#include -unsigned parseFormat(const char *type, unsigned defv = 0) -{ - if (type == 0 || *type == 0) return defv; - - if (::strcasecmp(type, "2mg") == 0) - return '2IMG'; - if (::strcasecmp(type, "2img") == 0) - return '2IMG'; - if (::strcasecmp(type, "dc42") == 0) - return 'DC42'; - if (::strcasecmp(type, "po") == 0) - return 'PO__'; - if (::strcasecmp(type, "do") == 0) - return 'DO__'; - if (::strcasecmp(type, "dsk") == 0) - return 'DO__'; - if (::strcasecmp(type, "davex") == 0) - return 'DVX_'; - - return defv; -} - -// return the filename extension, NULL if none. -const char *extname(const char *src) -{ - if (!src) return NULL; - unsigned l = std::strlen(src); - - for (unsigned i = 0; i < l; ++i) - { - char c = src[l - 1 - i]; - if (c == '/') return NULL; - if (c == '.') return src + l - i; - } - - return NULL; -} const char *MonthName(unsigned m) @@ -218,7 +181,6 @@ int main(int argc, char **argv) std::auto_ptr volume; std::auto_ptr device; - const char *format = NULL; unsigned fmt = 0; int c; @@ -231,7 +193,12 @@ int main(int argc, char **argv) switch(c) { case 'f': - format = optarg; + fmt = Device::DiskImage::ImageType(optarg); + if (!fmt) + { + std::fprintf(stderr, "Error: Invalid file format: ``%s''.\n", + optarg); + } break; case 'h': @@ -255,10 +222,8 @@ int main(int argc, char **argv) const char *file = argv[1]; const char *action = argv[0]; - if (format == NULL) format = extname(file); - - fmt = parseFormat(format, 'PO__'); - + if (!fmt) fmt = Device::DiskImage::ImageType(optarg, 'PO__'); + try { From b18551dea9413bbd19933fc6d226b33e62c4ef65 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 19 Dec 2009 18:32:06 +0000 Subject: [PATCH 068/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@187 aa027e90-d47c-11dd-86d7-074df07e0730 --- pascal_fileman.cpp => apfm.cpp | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pascal_fileman.cpp => apfm.cpp (100%) diff --git a/pascal_fileman.cpp b/apfm.cpp similarity index 100% rename from pascal_fileman.cpp rename to apfm.cpp From 3a0871a158bb30ac4ce740b8492e3f0a75df7d01 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 19 Dec 2009 23:17:39 +0000 Subject: [PATCH 069/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@188 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/File.h | 2 +- ProFUSE/Makefile | 9 +++ apfm.cpp | 149 +++++++++++++++++++++++++++++++++++++------- fuse_pascal.cpp | 42 +++++++------ fuse_pascal_ops.cpp | 29 ++++++--- 5 files changed, 178 insertions(+), 53 deletions(-) create mode 100644 ProFUSE/Makefile diff --git a/Pascal/File.h b/Pascal/File.h index 5a3e389..8d34eca 100644 --- a/Pascal/File.h +++ b/Pascal/File.h @@ -5,7 +5,7 @@ #include -namespace ProFUSE { +namespace Device { class BlockDevice; class AbstractBlockCache; } diff --git a/ProFUSE/Makefile b/ProFUSE/Makefile new file mode 100644 index 0000000..657e89d --- /dev/null +++ b/ProFUSE/Makefile @@ -0,0 +1,9 @@ +CC = g++ +CPPFLAGS += -g -Wall -I../ + + +all : Exception.o Lock.o + +Exception.o : Exception.cpp Exception.h + +Lock.o : Lock.cpp Lock.h \ No newline at end of file diff --git a/apfm.cpp b/apfm.cpp index f603df2..8e1c984 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -23,7 +23,6 @@ - const char *MonthName(unsigned m) { static const char *months[] = { @@ -102,16 +101,35 @@ void printFileEntry(Pascal::FileEntry *e, bool extended) } -int list(Pascal::VolumeEntry *volume, bool extended) +int action_ls(int argc, char **argv, Pascal::VolumeEntry *volume) { + //TODO -- check for -l flag. + + bool extended = false; unsigned fileCount = volume->fileCount(); unsigned used = volume->blocks(); unsigned max = 0; unsigned volumeSize = volume->volumeBlocks(); unsigned lastBlock = volume->lastBlock(); + int ch; std::fprintf(stdout, "%s:\n", volume->name()); + argv[0] = "afpm ls"; + + while ((ch = ::getopt(argc, argv, "l")) != -1) + { + switch(ch) + { + case 'l': + extended = true; + break; + } + } + + argc -= optind; + argv += optind; + for (unsigned i = 0; i < fileCount; ++i) { Pascal::FileEntry *e = volume->fileAtIndex(i); @@ -158,20 +176,95 @@ int list(Pascal::VolumeEntry *volume, bool extended) } +int action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume) +{ + // cat file1, file2... + argv[0] = "afpm cat"; + + if (argc < 2) + { + std::fprintf(stderr, "apfm cat: Please specify one or more files."); + return 1; + } + + for (unsigned i = 0; i < argc; ++i) + { + const char *fname = argv[i]; + unsigned fileSize; + unsigned offset; + uint8_t buffer[512]; + Pascal::FileEntry *e = NULL; + // find it... + + for (unsigned i = 0, l = volume->fileCount(); i < l; ++i) + { + e = volume->fileAtIndex(i); + if (::strcasecmp(e->name(), fname) == 0) break; + e = NULL; + } + + if (!e) + { + std::fprintf(stderr, "apfm cat: %s: no such file.\n", fname); + continue; + } + + fileSize = e->fileSize(); + offset = 0; + while (offset < fileSize) + { + unsigned count = std::min(512u, fileSize - offset); + e->read(buffer, count, offset); + + std::fwrite(buffer, count, 1, stdout); + offset += count; + } + } + + return 0; +} + +int action_cp(int argc, char **argv, Pascal::VolumeEntry *volume) +{ + return 0; +} + +int action_mv(int argc, char **argv, Pascal::VolumeEntry *volume) +{ + return 0; +} + +int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume) +{ + return 0; +} + +int action_krunch(int argc, char **argv, Pascal::VolumeEntry *volume) +{ + return 0; +} + + + + void usage() { std::printf( "Pascal File Manager v 0.0\n\n" - "Usage: fileman [-h] [-f format] action diskimage\n" + "Usage: fileman [-h] [-f format] diskimage action ...\n" "Options:\n" " -h Show usage information.\n" " -f format Specify disk format. Valid values are:\n" - " po: ProDOS order disk image\n" - " do: DOS Order disk image\n" + " po: ProDOS order disk image\n" + " do: DOS Order disk image\n" "\n" "Actions:\n" - " L List files\n" - " E List files (extended)\n" + " cat\n" + " cp\n" + " krunch\n" + " ls\n" + " mv\n" + " rm\n" ); } @@ -179,14 +272,14 @@ void usage() int main(int argc, char **argv) { std::auto_ptr volume; - std::auto_ptr device; + std::auto_ptr device; unsigned fmt = 0; int c; - - + + // getop stops at first non '-' arg so it will not affect action flags. while ((c = ::getopt(argc, argv, "f:h")) != -1) { std::printf("%c\n", c); @@ -203,24 +296,27 @@ int main(int argc, char **argv) case 'h': case '?': + case ':': usage(); - std::exit(0); + return c == 'h' ? 0 : 1; } } argc -= optind; argv += optind; + optreset = 1; + optind = 1; if (argc != 2) { usage(); - std::exit(1); + return 0; } - const char *file = argv[1]; - const char *action = argv[0]; + const char *file = argv[0]; + const char *action = argv[1]; if (!fmt) fmt = Device::DiskImage::ImageType(optarg, 'PO__'); @@ -230,28 +326,35 @@ int main(int argc, char **argv) switch(fmt) { case 'DO__': - device.reset( new ProFUSE::DOSOrderDiskImage(file, true) ); + device.reset( new Device::DOSOrderDiskImage(file, true) ); break; case 'PO__': - device.reset( new ProFUSE::ProDOSOrderDiskImage(file, true) ); + device.reset( new Device::ProDOSOrderDiskImage(file, true) ); break; case 'DC42': - device.reset( new ProFUSE::DiskCopy42Image(file, true) ); + device.reset( new Device::DiskCopy42Image(file, true) ); break; default: std::fprintf(stderr, "Unable to determine format. Please use -f flag.\n"); - exit(2); + return 2; } volume.reset( new Pascal::VolumeEntry(device.get())); device.release(); - - if (!::strcasecmp("E", action)) return list(volume.get(), true); - if (!::strcasecmp("L", action)) return list(volume.get(), false); - + + + if (!::strcasecmp("cat", action)) return action_cat(argc - 1, argv + 1, volume.get()); + if (!::strcasecmp("cp", action)) return action_cp(argc - 1, argv + 1, volume.get()); + if (!::strcasecmp("krunch", action)) return action_krunch(argc - 1, argv + 1, volume.get()); + if (!::strcasecmp("ls", action)) return action_ls(argc - 1, argv + 1, volume.get()); + if (!::strcasecmp("mv", action)) return action_mv(argc - 1, argv + 1, volume.get()); + if (!::strcasecmp("rm", action)) return action_rm(argc - 1, argv + 1, volume.get()); + + usage(); + return 3; } catch (ProFUSE::Exception& e) { @@ -259,5 +362,5 @@ int main(int argc, char **argv) std::fprintf(stderr, "%s\n", strerror(e.error())); } - + return 0; } \ No newline at end of file diff --git a/fuse_pascal.cpp b/fuse_pascal.cpp index 1aed2ac..fa8a973 100644 --- a/fuse_pascal.cpp +++ b/fuse_pascal.cpp @@ -18,11 +18,12 @@ #include -#include "File.h" -#include "../BlockDevice.h" -#include "../Exception.h" -#include "../MappedFile.h" -#include "../DiskCopy42Image.h" +#include +#include + +#include +#include +#include Pascal::VolumeEntry *fVolume = NULL; std::string fDiskImage; @@ -102,6 +103,7 @@ static int pascal_option_proc(void *data, const char *arg, int key, struct fuse_ case FUSE_OPT_KEY_NONOPT: + // first arg is the disk image. if (fDiskImage.empty()) { fDiskImage = arg; @@ -120,9 +122,12 @@ bool make_mount_dir(std::string name, std::string &path) { path = ""; - if (name.find('/') != std::string::npos) return false; - if (name.find('\\') != std::string::npos) return false; - if (name.find(':') != std::string::npos) return false; + if (name.find('/') != std::string::npos + || name.find('\\') != std::string::npos + || name.find(':') != std::string::npos ) + { + name = "Pascal Volume"; + } path = ""; path = "/Volumes/" + name; @@ -134,10 +139,7 @@ bool make_mount_dir(std::string name, std::string &path) path = "/Volumes/" + name + " " + (char)('a' + i); rmdir(path.c_str()); - if (mkdir(path.c_str(), 0777) == 0) return true; - - - + if (mkdir(path.c_str(), 0777) == 0) return true; } path = ""; @@ -178,31 +180,31 @@ int main(int argc, char **argv) // default prodos-order disk image. if (options.format) { - format = ProFUSE::DiskImage::ImageType(options.format); + format = Device::DiskImage::ImageType(options.format); if (!format) std::fprintf(stderr, "Warning: Unknown image type ``%s''\n", options.format); } if (!format) - format = ProFUSE::DiskImage::ImageType(fDiskImage.c_str(), 'PO__'); + format = Device::DiskImage::ImageType(fDiskImage.c_str(), 'PO__'); bool readOnly = true; try { - std::auto_ptr device; + std::auto_ptr device; switch(format) { case 'DC42': - device.reset(new ProFUSE::DiskCopy42Image(fDiskImage.c_str(), readOnly)); + device.reset(new Device::DiskCopy42Image(fDiskImage.c_str(), readOnly)); break; case 'PO__': - device.reset(new ProFUSE::ProDOSOrderDiskImage(fDiskImage.c_str(), readOnly)); + device.reset(new Device::ProDOSOrderDiskImage(fDiskImage.c_str(), readOnly)); break; case 'DO__': - device.reset(new ProFUSE::DOSOrderDiskImage(fDiskImage.c_str(), readOnly)); + device.reset(new Device::DOSOrderDiskImage(fDiskImage.c_str(), readOnly)); break; @@ -278,8 +280,8 @@ int main(int argc, char **argv) se = fuse_lowlevel_new(&args, &pascal_ops, sizeof(pascal_ops), fVolume); if (se) do { - foreground = 1; - multithread = 0; + //foreground = 1; + //multithread = 0; err = fuse_daemonize(foreground); // todo if (err < 0 ) break; diff --git a/fuse_pascal_ops.cpp b/fuse_pascal_ops.cpp index 7ead116..d2d272d 100644 --- a/fuse_pascal_ops.cpp +++ b/fuse_pascal_ops.cpp @@ -8,11 +8,11 @@ #include #include -/* + #define __FreeBSD__ 10 #define __DARWIN_64_BIT_INO_T 1 #define _FILE_OFFSET_BITS 64 -*/ + #define FUSE_USE_VERSION 27 #include @@ -20,10 +20,9 @@ - -#include "File.h" -#include "../auto.h" -#include "../Exception.h" +#include +#include +#include #define NO_ATTR() \ { \ @@ -64,11 +63,21 @@ static void pascal_init(void *userdata, struct fuse_conn_info *conn) { std::printf("pascal_init\n"); // 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) + { + volume->fileAtIndex(i)->fileSize(); + } + } static void pascal_destroy(void *userdata) { std::printf("pascal_destroy\n"); + // nop } @@ -199,7 +208,7 @@ static void pascal_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t of std::printf("pascal_readdir %u, %u, %u\n", (unsigned)ino, (unsigned)size, (unsigned)off); VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); - auto_array buffer(new uint8_t[size]); + ProFUSE::auto_array buffer(new uint8_t[size]); unsigned count = volume->fileCount(); @@ -208,7 +217,7 @@ static void pascal_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t of std::memset(&st, 0, sizeof(st)); - // . && .. entries. + // . and .. need to be added in here but are handled by the fs elsewhere. do { if (off == 0) @@ -408,9 +417,11 @@ static void pascal_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, //VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); FileEntry *file = (FileEntry *)fi->fh; + + try { - auto_array buffer(new uint8_t[size]); + ProFUSE::auto_array buffer(new uint8_t[size]); unsigned rsize = file->read(buffer.get(), size, off); fuse_reply_buf(req, (char *)(buffer.get()), rsize); From 77d7021e907e53cf28ca3855e74b3dc637ac9bd0 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 19 Dec 2009 23:21:54 +0000 Subject: [PATCH 070/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@189 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/{Makefile => Makefile.old} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Pascal/{Makefile => Makefile.old} (100%) diff --git a/Pascal/Makefile b/Pascal/Makefile.old similarity index 100% rename from Pascal/Makefile rename to Pascal/Makefile.old From 21906f7b9be658da978d6fe89ae1d83c04208854 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 19 Dec 2009 23:27:39 +0000 Subject: [PATCH 071/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@190 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/FileEntry.cpp | 14 +++++++++----- Pascal/Makefile | 14 ++++++++++++++ Pascal/VolumeEntry.cpp | 7 +++++-- 3 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 Pascal/Makefile diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index 2889b56..8e367e4 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -1,17 +1,21 @@ + +#include +#include +#include +#include + #include #include #include #include +#include #include #include -#include -#include -#include -#include + using namespace LittleEndian; using namespace Pascal; @@ -197,7 +201,7 @@ int FileEntry::textRead(uint8_t *buffer, unsigned size, unsigned offset) unsigned l; unsigned count = 0; - auto_array tmp; + ProFUSE::auto_array tmp; unsigned tmpSize = 0; if (!_pageSize) textInit(); diff --git a/Pascal/Makefile b/Pascal/Makefile new file mode 100644 index 0000000..6889dc4 --- /dev/null +++ b/Pascal/Makefile @@ -0,0 +1,14 @@ +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 + diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index a4d3386..c666eef 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include #include @@ -12,6 +12,9 @@ #pragma mark - #pragma mark VolumeEntry +using namespace LittleEndian; +using namespace Pascal; + unsigned VolumeEntry::ValidName(const char *cp) { // 7 chars max. Legal values: ascii, printable, @@ -86,7 +89,7 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device) VolumeEntry::VolumeEntry(Device::BlockDevice *device) { - auto_array buffer(new uint8_t[512]); + ProFUSE::auto_array buffer(new uint8_t[512]); unsigned blockCount; // read the header block, then load up all the header From 07e7fef6767f72c2ca6c2165e2f26051b6fbc588 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 19 Dec 2009 23:46:18 +0000 Subject: [PATCH 072/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@191 aa027e90-d47c-11dd-86d7-074df07e0730 --- Endian/Makefile | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 Endian/Makefile diff --git a/Endian/Makefile b/Endian/Makefile new file mode 100644 index 0000000..ded39b8 --- /dev/null +++ b/Endian/Makefile @@ -0,0 +1,7 @@ +CC = g++ +CPPFLAGS += -g -Wall -I../ + + +all : Endian.o + +Endian.o : Endian.cpp Endian.h From ae52676bf2f0b85d8f2d4896aba59b34362264bd Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 19 Dec 2009 23:47:06 +0000 Subject: [PATCH 073/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@192 aa027e90-d47c-11dd-86d7-074df07e0730 --- ProDOS/Makefile | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 ProDOS/Makefile diff --git a/ProDOS/Makefile b/ProDOS/Makefile new file mode 100644 index 0000000..84af29e --- /dev/null +++ b/ProDOS/Makefile @@ -0,0 +1,7 @@ +CC = g++ +CPPFLAGS += -g -Wall -I../ + + +all : DateTime.o + +DateTime.o : DateTime.cpp DateTime.h From 616411809b5310d19df990523f0edafd64c106b9 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 19 Dec 2009 23:59:31 +0000 Subject: [PATCH 074/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@193 aa027e90-d47c-11dd-86d7-074df07e0730 --- Endian/Endian.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Endian/Endian.cpp b/Endian/Endian.cpp index 5d21622..c16a7be 100644 --- a/Endian/Endian.cpp +++ b/Endian/Endian.cpp @@ -57,34 +57,34 @@ namespace LittleEndian { namespace BigEndian { - inline uint16_t Read16(const void *vp) + uint16_t Read16(const void *vp) { const uint8_t *p = (const uint8_t *)vp; return (p[0] << 8) | (p[1]); } - inline uint32_t Read24(const void *vp) + uint32_t Read24(const void *vp) { const uint8_t *p = (const uint8_t *)vp; return (p[0] << 16) | (p[1] << 8) | (p[2]); } - inline uint32_t Read32(const void *vp) + uint32_t Read32(const void *vp) { const uint8_t *p = (const uint8_t *)vp; return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); } - inline void Write16(void *vp, uint16_t x) + void Write16(void *vp, uint16_t x) { uint8_t *p = (uint8_t *)vp; p[0] = (x >> 8) & 0xff; p[1] = (x) & 0xff; } - inline void Write24(void *vp, uint32_t x) + void Write24(void *vp, uint32_t x) { uint8_t *p = (uint8_t *)vp; p[0] = (x >> 16) & 0xff; @@ -92,7 +92,7 @@ namespace BigEndian { p[2] = (x) & 0xff; } - inline void Write32(void *vp, uint32_t x) + void Write32(void *vp, uint32_t x) { uint8_t *p = (uint8_t *)vp; p[0] = (x >> 24) & 0xff; From 525b69a333a7f021552bfa098bcb00c5d60cb526 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 20 Dec 2009 00:18:48 +0000 Subject: [PATCH 075/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@194 aa027e90-d47c-11dd-86d7-074df07e0730 --- fuse_pascal_ops.cpp | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/fuse_pascal_ops.cpp b/fuse_pascal_ops.cpp index d2d272d..40bf5b0 100644 --- a/fuse_pascal_ops.cpp +++ b/fuse_pascal_ops.cpp @@ -1,4 +1,9 @@ +#define __FreeBSD__ 10 +#define __DARWIN_64_BIT_INO_T 1 +#define _FILE_OFFSET_BITS 64 + +#define FUSE_USE_VERSION 27 #include #include @@ -9,12 +14,6 @@ #include -#define __FreeBSD__ 10 -#define __DARWIN_64_BIT_INO_T 1 -#define _FILE_OFFSET_BITS 64 - -#define FUSE_USE_VERSION 27 - #include #include @@ -61,7 +60,7 @@ static FileEntry *findChild(VolumeEntry *volume, unsigned inode) static void pascal_init(void *userdata, struct fuse_conn_info *conn) { - std::printf("pascal_init\n"); + //std::printf("pascal_init\n"); // nop // text files have a non-thread safe index. @@ -76,7 +75,7 @@ static void pascal_init(void *userdata, struct fuse_conn_info *conn) static void pascal_destroy(void *userdata) { - std::printf("pascal_destroy\n"); + //std::printf("pascal_destroy\n"); // nop } @@ -88,7 +87,7 @@ static void pascal_destroy(void *userdata) static void pascal_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) { - std::printf("pascal_listxattr\n"); + //std::printf("pascal_listxattr\n"); VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); FileEntry *file; @@ -131,7 +130,7 @@ static void pascal_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) static void pascal_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, size_t size) { - std::printf("pascal_getxattr\n"); + //std::printf("pascal_getxattr\n"); VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); @@ -186,7 +185,7 @@ static void pascal_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, si static void pascal_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { - std::printf("pascal_opendir\n"); + //std::printf("pascal_opendir\n"); ERROR(ino != 1, ENOTDIR) @@ -198,14 +197,14 @@ static void pascal_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info static void pascal_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { - std::printf("pascal_releasedir\n"); + //std::printf("pascal_releasedir\n"); 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) { - std::printf("pascal_readdir %u, %u, %u\n", (unsigned)ino, (unsigned)size, (unsigned)off); + //std::printf("pascal_readdir %u, %u, %u\n", (unsigned)ino, (unsigned)size, (unsigned)off); VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); ProFUSE::auto_array buffer(new uint8_t[size]); @@ -215,7 +214,7 @@ static void pascal_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t of struct stat st; unsigned currentSize = 0; - std::memset(&st, 0, sizeof(st)); + std::memset(&st, 0, sizeof(struct stat)); // . and .. need to be added in here but are handled by the fs elsewhere. @@ -284,7 +283,7 @@ static void pascal_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t of static void stat(FileEntry *file, struct stat *st) { - std::memset(st, 0, sizeof(st)); + std::memset(st, 0, sizeof(struct stat)); time_t t = file->modification(); @@ -303,7 +302,7 @@ static void stat(FileEntry *file, struct stat *st) static void stat(VolumeEntry *volume, struct stat *st) { - std::memset(st, 0, sizeof(st)); + std::memset(st, 0, sizeof(struct stat)); time_t t = volume->lastBoot(); @@ -322,7 +321,7 @@ static void stat(VolumeEntry *volume, struct stat *st) static void pascal_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) { - std::printf("pascal_lookup %u %s\n", (unsigned)parent, name); + //std::printf("pascal_lookup %u %s\n", (unsigned)parent, name); VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); struct fuse_entry_param entry; @@ -355,7 +354,7 @@ static void pascal_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) static void pascal_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { - std::printf("pascal_getattr %u\n", (unsigned)ino); + //std::printf("pascal_getattr %u\n", (unsigned)ino); struct stat st; VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); @@ -383,7 +382,7 @@ static void pascal_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info static void pascal_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { - std::printf("pascal_open\n"); + //std::printf("pascal_open\n"); VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); FileEntry *file; @@ -404,7 +403,7 @@ static void pascal_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *f static void pascal_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { - std::printf("pascal_release\n"); + //std::printf("pascal_release\n"); fuse_reply_err(req, 0); } @@ -412,7 +411,7 @@ static void pascal_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info static void pascal_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) { - std::printf("pascal_read %u %u %u\n", (unsigned)ino, (unsigned)size, (unsigned)off); + //std::printf("pascal_read %u %u %u\n", (unsigned)ino, (unsigned)size, (unsigned)off); //VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); FileEntry *file = (FileEntry *)fi->fh; From 9bca60e97762a5b5fedb0daf4b21e71d715089b4 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 20 Dec 2009 00:23:06 +0000 Subject: [PATCH 076/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@195 aa027e90-d47c-11dd-86d7-074df07e0730 --- fuse_pascal.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fuse_pascal.cpp b/fuse_pascal.cpp index fa8a973..aaa8e9a 100644 --- a/fuse_pascal.cpp +++ b/fuse_pascal.cpp @@ -277,8 +277,10 @@ int main(int argc, char **argv) { struct fuse_session* se; - se = fuse_lowlevel_new(&args, &pascal_ops, sizeof(pascal_ops), fVolume); + std::printf("Mounting ``%s'' on ``%s''\n", fVolume->name(), mountpoint); + se = fuse_lowlevel_new(&args, &pascal_ops, sizeof(pascal_ops), fVolume); + if (se) do { //foreground = 1; //multithread = 0; From 58ffa151e3cadafe96bfa39bd9b42f92541fc7d4 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 21 Dec 2009 13:57:48 +0000 Subject: [PATCH 077/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@196 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/BlockDevice.cpp | 24 +++++ Device/BlockDevice.h | 24 ++++- Device/DeviceReader.cpp | 204 ++++++++++++++++++++++++++++++++++++++++ Device/DeviceReader.h | 109 +++++++++++++++++++++ Device/RawDevice.cpp | 63 +++++++++++-- Device/RawDevice.h | 6 +- Device/TrackSector.h | 19 ++++ 7 files changed, 438 insertions(+), 11 deletions(-) create mode 100644 Device/DeviceReader.cpp create mode 100644 Device/DeviceReader.h create mode 100644 Device/TrackSector.h diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index 1c556d6..2c76f0d 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -54,6 +54,30 @@ AbstractBlockCache *BlockDevice::createBlockCache() return new BlockCache(this); } +bool BlockDevice::mapped() +{ + return false; +} + +void BlockDevice::sync(unsigned block) +{ + sync(); +} + +void BlockDevice::sync(TrackSector ts) +{ + sync(); +} + +void *BlockDevice::read(unsigned block) +{ + return NULL; +} + +void *BlockDevice::read(TrackSector ts) +{ + return NULL; +} #pragma mark - diff --git a/Device/BlockDevice.h b/Device/BlockDevice.h index 41d899e..7d8b262 100644 --- a/Device/BlockDevice.h +++ b/Device/BlockDevice.h @@ -6,25 +6,41 @@ #include +#include + namespace Device { class MappedFile; class AbstractBlockCache; + class BlockDevice { public: virtual ~BlockDevice(); virtual void read(unsigned block, void *bp) = 0; - virtual void write(unsigned block, const void *bp) = 0; - - virtual bool readOnly() = 0; - virtual void sync() = 0; + virtual void read(TrackSector ts, void *bp); + virtual void write(unsigned block, const void *bp) = 0; + virtual void write(TrackSector ts, const void *bp); + + // direct access to mapped memory (not always possible). + virtual void *read(unsigned block); + virtual void *read(TrackSector ts); + virtual unsigned blocks() = 0; + virtual bool mapped(); + + virtual bool readOnly() = 0; + + virtual void sync() = 0; + virtual void sync(unsigned block); + virtual void sync(TrackSector ts); + + void zeroBlock(unsigned block); AbstractBlockCache *blockCache(); diff --git a/Device/DeviceReader.cpp b/Device/DeviceReader.cpp new file mode 100644 index 0000000..fceb664 --- /dev/null +++ b/Device/DeviceReader.cpp @@ -0,0 +1,204 @@ + + +#include + +using namespace Device; + +DeviceReader::~DeviceReader() +{ +} + +void *DeviceReader::read(unsigned block) +{ + return NULL; +} + +void DeviceReader::read(TrackSector ts) +{ + return NULL; +} + +void DeviceReader::mapped() +{ + return false; +} + +#pragma mark - +#pragma mark ProDOS Order + +void ProDOSOrderDeviceReader::read(unsigned block, void *bp) +{ + std::memcpy(bp, read(block), 512); +} + +void ProDOSOrderDeviceReader::read(TrackSector ts, void *bp) +{ + std::memcpy(bp, read(ts), 256); +} + +void *ProDOSOrderDeviceReader::read(unsigned block) +{ + if (block > _blocks) + { + throw ProFUSE::Exception("Invalid block."); + } + return block * 512 + (uint8_t *)_data; +} + + +void *ProDOSOrderDeviceReader::read(TrackSector ts) +{ + unsigned block = (ts.track * 16 + ts.sector) / 2; + + if (block > _blocks) + { + throw ProFUSE::Exception("Invalid track/sector."); + } + + return (ts.track * 16 + ts.sector) * 256 + (uint8_t *)_data; +} + + +void ProDOSOrderDeviceReader::write(unsigned block, const void *bp) +{ + std::memcpy(read(block), bp, 512); +} + +void ProDOSOrderDeviceReader::write(TrackSector ts, const void *bp) +{ + std::memcpy(read(ts), bp, 256); +} + + +#pragma mark - +#pragma mark DOS Order + +const unsigned DOSMap[] = { + 0x00, 0x0e, 0x0d, 0x0c, + 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x0f +}; + +void *DOSOrderDeviceReader::read(TrackSector ts) +{ + if (ts.track > _tracks || ts.sector > 16) + { + throw ProFUSE::Exception("Invalid track/sector."); + } + + return (ts.track * 16 + ts.sector) * 256 + (uint8_t *)_data; +} + + +void DOSOrderDeviceReader::read(unsigned block, void *bp) +{ + TrackSector ts(block >> 3, 0); + unsigned sector = (block & 0x07) << 1; + + for (unsigned i = 0; i < 2; ++i) + { + ts.sector = DOSMap[sector]; + std::memcpy(bp, read(ts), 256); + bp = 256 + (uint8_t *)bp; + ++sector; + } +} + + +void DOSOrderDeviceReader::read(TrackSector ts, void *bp) +{ + std::memcpy(bp, read(ts), 256); +} + + +void DOSOrderDeviceReader::write(unsigned block, const void *bp) +{ + TrackSector ts(block >> 3, 0); + unsigned sector = (block & 0x07) << 1; + + for (unsigned i = 0; i < 2; ++i) + { + ts.sector = DOSMap[sector]; + std::memcpy(read(ts), bp, 256); + bp = 256 + (const uint8_t *)bp; + ++sector; + } +} + +void DOSOrderDeviceReader::write(TrackSector ts, const void *bp) +{ + std::memcpy(read(ts), bp, 256); +} + + +#pragma mark - +#pragma mark FileDeviceReader + +FileDeviceReader::FileDeviceReader(int fd, unsigned blocks, bool readOnly) +{ + _fd = fd; + _readOnly = readOnly; + _blocks = blocks; +} + +bool FileDeviceReader::readOnly() +{ + return _readOnly; +} + +void FileDeviceReader::write(unsigned block, const void *bp) +{ + + off_t offset = block * 512; + + size_t ok = ::pwrite(_fd, bp, 512, offset); + + if (ok != 512) + throw ok < 0 + ? POSIXException(__METHOD__ ": Error writing block.", errno) + : Exception(__METHOD__ ": Error writing block."); +} + + +void FileDeviceReader::write(TrackSector ts, const void *bp) +{ + off_t offset = (ts.track * 16 + ts.sector) * 256; + size_t ok = ::pwrite(_fd, bp, 256, offset); + + if (ok != 256) + throw ok < 0 + ? POSIXException(__METHOD__ ": Error writing block.", errno) + : Exception(__METHOD__ ": Error writing block."); +} + + + + + + + + +void FileDeviceReader::read(unsigned block, void *bp) +{ + + off_t offset = block * 512; + + size_t ok = ::pread(_fd, bp, 512, offset); + + if (ok != 512) + throw ok < 0 + ? POSIXException(__METHOD__ ": Error reading block.", errno) + : Exception(__METHOD__ ": Error reading block."); +} + +void FileDeviceReader::read(TrackSector ts, void *bp) +{ + off_t offset = (ts.track * 16 + ts.sector) * 256; + size_t ok = ::pread(_fd, bp, 256, offset); + + if (ok != 256) + throw ok < 0 + ? POSIXException(__METHOD__ ": Error reading block.", errno) + : Exception(__METHOD__ ": Error reading block."); +} diff --git a/Device/DeviceReader.h b/Device/DeviceReader.h new file mode 100644 index 0000000..e2e8c71 --- /dev/null +++ b/Device/DeviceReader.h @@ -0,0 +1,109 @@ +#ifndef __DEVICEREADER_H__ +#define __DEVICEREADER_H__ + +#include + +namespace Device { + + +class DeviceReader { + public: + + virtual ~DeviceReader(); + + virtual void read(unsigned block, void *bp) = 0; + virtual void read(TrackSector ts, void *bp) = 0; + + virtual void write(unsigned block, const void *bp) = 0; + virtual void write(TrackSector ts, const void *bp) = 0; + + // direct access -- not always available. + + virtual void *read(unsigned block); + virtual void *read(TrackSector ts); + + virtual bool readOnly() = 0; + virtual bool mapped(); + +}; + +class FileDeviceReader : public DeviceReader { + + // does not assume ownership of fd. + FileDeviceReader(int fd, unsigned blocks, bool readOnly); + //virtual ~FileDeviceReader(); + +public: + + virtual bool readOnly(); + + + virtual void read(unsigned block, void *bp); + virtual void read(TrackSector ts, void *bp); + + virtual void write(unsigned block, const void *bp); + virtual void write(TrackSector ts, const void *bp); + + private: + + int _fd; + unsigned _blocks; + bool _readOnly; +} + +class MappedFileDeviceReader : public DeviceReader { + + protected: + + MappedFileDeviceReader(MappedFile *f, unsigned offset); + + void *_data; + + private: + MappedFile *_file +}; + +class ProDOSOrderDeviceReader : public MappedFileDeviceReader { + public: + + virtual void read(unsigned block, void *bp); + virtual void read(TrackSector ts, void *bp); + + virtual void write(unsigned block, const void *bp); + virtual void write(TrackSector ts, const void *bp); + + virtual void *read(unsigned block); + virtual void *read(TrackSector ts); + + private: + unsigned blocks; +}; + +// 16 sectors only. +class DOSOrderDeviceReader : public MappedFileDeviceReader { + public: + + virtual void read(unsigned block, void *bp); + virtual void read(TrackSector ts, void *bp); + + virtual void write(unsigned block, const void *bp); + virtual void write(TrackSector ts, const void *bp); + + virtual void *read(TrackSector ts); + + private: + unsigned _tracks; +}; + + + +class NibbleDeviceReader : public MappedFileDeviceReader { + + private: + + std::vector _map; +}; + +} + +#endif \ No newline at end of file diff --git a/Device/RawDevice.cpp b/Device/RawDevice.cpp index 9047f17..1e9c6ca 100644 --- a/Device/RawDevice.cpp +++ b/Device/RawDevice.cpp @@ -146,17 +146,40 @@ void RawDevice::read(unsigned block, void *bp) // sun -- use pread // apple - read full native block(s) ? - size_t ok = ::pread(_fd, bp, 512, block * 512); + off_t offset = block * 512; + size_t ok = ::pread(_fd, bp, 512, offset); // TODO -- EINTR? if (ok != 512) throw ok < 0 ? POSIXException(__METHOD__ ": Error reading block.", errno) : Exception(__METHOD__ ": Error reading block."); - - - } + + +void RawDevice::read(TrackSector ts, void *bp) +{ +#undef __METHOD__ +#define __METHOD__ "RawDevice::read" + + unsigned block = ts.track * 8 + ts.sector / 2; + if (block >= _blocks) throw Exception(__METHOD__ ": Invalid block number."); + if (bp == 0) throw Exception(__METHOD__ ": Invalid address."); + + // sun -- use pread + // apple - read full native block(s) ? + + off_t offset = (ts.track * 16 + ts.sector) * 256; + size_t ok = ::pread(_fd, bp, 256, offset); + + // TODO -- EINTR? + if (ok != 256) + throw ok < 0 + ? POSIXException(__METHOD__ ": Error reading block.", errno) + : Exception(__METHOD__ ": Error reading block."); +} + + void RawDevice::write(unsigned block, const void *bp) { #undef __METHOD__ @@ -167,8 +190,9 @@ void RawDevice::write(unsigned block, const void *bp) if (_readOnly) throw Exception(__METHOD__ ": File is readonly."); - - size_t ok = ::pwrite(_fd, bp, 512, block * 512); + + off_t offset = block * 512; + size_t ok = ::pwrite(_fd, bp, 512, offset); if (ok != 512) throw ok < 0 @@ -177,11 +201,38 @@ void RawDevice::write(unsigned block, const void *bp) } +void RawDevice::write(TrackSector ts, const void *bp) +{ +#undef __METHOD__ +#define __METHOD__ "RawDevice::write" + + unsigned block = ts.track * 8 + ts.sector / 2; + if (block > _blocks) throw Exception(__METHOD__ ": Invalid block number."); + + if (_readOnly) + throw Exception(__METHOD__ ": File is readonly."); + + + off_t offset = (ts.track * 16 + ts.sector) * 256; + size_t ok = ::pwrite(_fd, bp, 256, offset); + + if (ok != 256) + throw ok < 0 + ? POSIXException(__METHOD__ ": Error writing block.", errno) + : Exception(__METHOD__ ": Error writing block."); +} + + bool RawDevice::readOnly() { return _readOnly; } +bool RawDevice::mapped() +{ + return false; +} + void RawDevice::sync() { #undef __METHOD__ diff --git a/Device/RawDevice.h b/Device/RawDevice.h index dfbeb8f..f39fa70 100644 --- a/Device/RawDevice.h +++ b/Device/RawDevice.h @@ -18,9 +18,13 @@ public: virtual ~RawDevice(); virtual void read(unsigned block, void *bp); + virtual void read(TrackSector ts, void *bp); + virtual void write(unsigned block, const void *bp); - + virtual void write(TrackSector ts, const void *bp); + virtual bool readOnly(); + virtual bool mapped(); virtual void sync(); private: diff --git a/Device/TrackSector.h b/Device/TrackSector.h new file mode 100644 index 0000000..dd96d7e --- /dev/null +++ b/Device/TrackSector.h @@ -0,0 +1,19 @@ +#ifndef __TRACKSECTOR_H__ +#define __TRACKSECTOR_H__ + +namespace Device { + + struct TrackSector { + TrackSector(unsigned, unsigned); + unsigned track; + unsigned sector; + }; + + inline TrackSector::TrackSector(unsigned t, unsigned s) + { + track = t; + sector = s; + } +} + +#endif \ No newline at end of file From fbc49a398ede324dcc1d51a0f9eadab1651cf973 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 1 Mar 2010 00:14:12 +0000 Subject: [PATCH 078/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@197 aa027e90-d47c-11dd-86d7-074df07e0730 --- BlockCache.cpp | 177 +++++++++++++++++++++++++++++++++++++++++++++++++ BlockCache.h | 81 ++++++++++++++++++++++ 2 files changed, 258 insertions(+) create mode 100644 BlockCache.cpp create mode 100644 BlockCache.h diff --git a/BlockCache.cpp b/BlockCache.cpp new file mode 100644 index 0000000..53edb5e --- /dev/null +++ b/BlockCache.cpp @@ -0,0 +1,177 @@ +#include "BlockCache.h" + +struct FileBlockCache::Entry { + FileBlockCache::Entry *next; + unsigned block; + unsigned count; + bool dirty; + uint8_t buffer[512]; +}; + +FileBlockCache::FileBlockCache(Device *device) +{ + _device = device; + + // allocate initial buffer. + for (unsigned i = 0; i < 10; ++i) + { + Entry *e = new Entry; + std::memset(e, 0, sizeof(Entry)); + + _pages.push_back(e); + _unused.push_back(e); + } +} + +FileBlockCache::~FileBlockCache() +{ + std::vector::iterator iter; + + // todo -- check if dirty. + + // deallocate everything that was allocated. + for (iter = _pages.begin(); iter != _pages.end(); ++iter) + { + Entrty *e = *iter; + if (e->dirty) sync(e); + delete e; + } +} + + + +uint8_t *FileBlockCache::acquire(unsigned block) +{ + Entry *e = findEntry(block); + + if (e) + { + if (++e->count == 1) + _unused.remove(e); + return e->buffer; + } + + if (_unused.empty()) + { + e = new Entry; + _pages.push_back(e); + } + else + { + e = _unused.pop_front(); + + removeEntry(e); + } + std::memset(e, 0, sizeof(Entry)); + unsigned hash = hashFunction(block); + + e->block = block; + e->count = 1; + e->dirty = 0; + + _device->read(block, e->buffer); + + _e->next = _hashMap[hash]; + _hashMap[hash] = e; + + return e->buffer; +} + + +void FileBlockCache::release(unsigned block, bool dirty) +{ + Entry *e = findEntry(block); + + // throw error? + if (!e) return; + + if (dirty) e->dirty = true; + + if (e->count == 0) return; + if (--e->count == 0) + { + _unused.push_back(e); + } + // sync if dirty?? +} + +void FileBlockCache::markDirty(unsigned block) +{ + Entry *e = findEntry(e); + + if (e && e->count) e->dirty = true; +} + +Entry *FileBlockCache::findEntry(unsigned block) +{ + unsigned hash = hashFunction(block); + Entry *e; + + e = _hashMap[hash]; + + while (e && e->block != block) + { + e = e->next; + } + + return e; +} + +void FileBlockCache::removeEntry(Entry *e) +{ + unsigned hash; + Entry *curr; + Entry *prev; + + if (!e) return; + + hash = hashFunction(e->block); + + curr = _hashMap[hash]; + + if (curr == e) + { + _hashMap[hash] = e->next; + return; + } + + for (;;) + { + prev = curr; + curr = curr->next; + + if (!curr) break; + + if (e == curr) + { + prev->next = e->next; + return; + } + } +} + +unsigned FileBlockCache::hashFunction(unsigned block) +{ + return block % HashEntries; +} + +void FileBlockCache::sync(Entry *e) +{ + if (!e) return; + if (!e->dirty) return; + + _device->write(e->block, e->buffer); + e->dirty = false; +} + +void FileBlockCache::sync() +{ + std::vector::iterator iter; + + for (iter = _pages.begin(); iter != _pages.end(); ++iter) + { + Entry *e = *iter; + + if (e && e->dirty) sync(e); + } +} diff --git a/BlockCache.h b/BlockCache.h new file mode 100644 index 0000000..978dd6f --- /dev/null +++ b/BlockCache.h @@ -0,0 +1,81 @@ +#ifndef __BLOCK_CACHE_H__ +#define __BLOCK_CACHE__ + +#include + +#include +#include + +//#include +//typedef std::__gnu_cxx::hash_map hash_map; + +namespace ProFUSE { + +class BlockCache { + public: + + virtual ~BlockCache(); + + virtual uint8_t *acquire(unsigned block) = 0; + virtual void release(unsigned block, bool dirty = false) = 0; + virtual void markDirty(unsigned block) = 0; + + virtual void sync() = 0; + +}; + + +class FileBlockCache : public BlockCache { + + + FileBlockCache(Device *); + virtual ~FileBlockCache(); + + virtual uint8_t *acquire(unsigned block); + virtual void release(unsigned block, bool dirty = false); + virtual void markDirty(unsigned block); + + virtual void sync(); + +private: + struct Entry; + + enum { HashEntries = 23 }; + + + unsigned hashFunction(unsigned); + + void removeEntry(Entry *); + Entry *findEntry(unsigned block); + void sync(Entry *); + + std::vector _pages; + std::list _unused; + + Entry *_hashMap[HashEntries]; + + Device *_device; + +}; + +class MappedBlockCache : public BlockCache +{ +public: + + MappedBlockCache(Device *); + virtual ~MappedBlockCache(); + + virtual uint8_t *acquire(unsigned block); + virtual void release(unsigned block, bool dirty = false); + virtual void markDirty(unsigned block); + + virtual void sync(); + + + private: + Device *_device; +}; + +} + +#endif From a750f2ff5fffac85d49ed9a9c39a6ed9d1a09395 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 13 Mar 2010 18:51:00 +0000 Subject: [PATCH 079/236] Improve block cache git-svn-id: https://profuse.googlecode.com/svn/branches/v2@198 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/BlockCache.cpp | 341 +++++++++++++++++++++++++++++------------- Device/BlockCache.h | 108 +++++++++---- 2 files changed, 318 insertions(+), 131 deletions(-) diff --git a/Device/BlockCache.cpp b/Device/BlockCache.cpp index 75f8b44..4e0c3c9 100644 --- a/Device/BlockCache.cpp +++ b/Device/BlockCache.cpp @@ -26,10 +26,18 @@ using ProFUSE::Exception; using ProFUSE::POSIXException; #pragma mark - -#pragma mark AbstractBlockCache +#pragma mark BlockCache -AbstractBlockCache::~AbstractBlockCache() +BlockCache::~BlockCache(BlockDevice *device) { + _device = _device; + _blocks = device->blocks(); + _readOnly = device->readOnly(); +} + +BlockCache::~BlockCache() +{ + delete _device; } #pragma mark - @@ -78,129 +86,258 @@ void MappedBlockCache::unload(unsigned block, bool dirty) #pragma mark - -#pragma mark BlockCache +#pragma mark ConcreteBlockCache -typedef std::vector::iterator BDIter; +typedef std::vector::iterator EntryIter; -BlockCache::BlockCache(BlockDevice *device, unsigned size) +ConcreteBlockCache::ConcreteBlockCache(BlockDevice *device, unsigned size) : + BlockCache(device) { - _device = device; - _ts = 0; - _cacheSize = std::max(16u, size); - _blocks.reserve(_cacheSize); -} - -BlockCache::~BlockCache() -{ - for (BDIter iter = _blocks.begin(); iter != _blocks.end(); ++iter) - { - if (iter->data) delete[] iter->data; - } -} - -void BlockCache::write() -{ - for (BDIter iter = _blocks.begin(); iter != _blocks.end(); ++iter) - { - if (iter->dirty) - { - _device->write(iter->block, iter->data); - iter->dirty = false; - } - } -} - - - -void *BlockCache::load(unsigned block) -{ - unsigned mints = -1; - unsigned freeCount = 0; + if (size < 16) size = 16; - BDIter oldest; - - - ++_ts; - - /* - * keep a pointer to the oldest free entry (according to ts). - * and re-use if >= 16 entries. - */ - + std::memset(_hashTable, 0, sizeof(Entry *) * HashTableSize); - for (BDIter iter = _blocks.begin(); iter != _blocks.end(); ++iter) + for (unsigned i = 0; i < size; ++i) { - if (iter->block == block) + Entry *e = new Entry; + + std::memset(e, 0, sizeof(Entry)); + _buffers.push_back(e); + } + _first = _last = NULL; + + _first = _buffers.front(); + _last = _buffers.back(); + // form a chain.... + for (unsigned i = 0; i < size; ++i) + { + Entry *e = _buffers[i]; + + if (i > 0) e->prev = _buffers[i - 1]; + + if (i < size - 1) e->next = _buffers[i + 1]; + } + +} + +ConcreteBlockCache::~ConcreteBlockCache() +{ + EntryIter iter; + for (iter = _buffers.begin(); iter != _buffers.end(); ++iter) + { + Entry *e = *iter; + + if (e->dirty) { - ++iter->count; - iter->ts = _ts; - - return iter->data; + _device->write(e->block, e->buffer); } - if (iter->count == 0) + delete e; + } + _device->sync(); +} + + +ConcreteBlockCache::sync() +{ + EntryIter iter; + for (iter = _buffers.begin(); iter != _buffers.end(); ++iter) + { + Entry *e = *iter; + + if (e->dirty) { - ++freeCount; - if (iter->ts < mints) + _device->write(e->block, e->buffer); + e->dirty = false; + } + } + _device->sync(); +} + + +void ConcreteBlockCache::markDirty(unsigned block) +{ + Entry *e = findEntry(block); + + if (e) e->dirty = true; + // error otherwise? +} + + +void ConcreteBlockCache::release(unsigned block, bool dirty) +{ + Entry *e = findEntry(block); + + if (e) + { + if (dirty) e->dirty = true; + + decrementCount(e); + } + // error otherwise? +} + +void *ConcreteBlockCache::acquire(unsigned block) +{ + Entry *e = findEntry(block); + + if (e) + { + incrementCount(e); + return e->buffer; + } + + unsigned hash = hashFunction(block); + + // returns a new entry, not in hash table, not in free list. + e = newEntry(block); + + _device->read(block, e->buffer); + + e->nextHash = _hashTable[hash]; + _hashTable[hash] = e; + + return e->buffer; +} + +unsigned ConcreteBlockCache::hashFunction(unsigned block) +{ + return block % HashTableSize; +} + +/* + * remove a block from the hashtable + * and write to dick if dirty. + */ +void removeEntry(unsigned block) +{ + Entry *e; + Entry *prev; + unsigned hash = hashFunction(block); + + e = _hashTable[hash]; + if (!e) return; + + // head pointer, special case. + if (e->block == block) + { + _hashTable[hash] = e->nextHash; + e->nextHash = NULL; + + return; + } + + for(;;) + { + prev = e; + e = e->next; + + if (!e) break; + if (e->block == block) + { + prev->nextHash = e->nextHash; + e->nextHash = NULL; + + if (e->dirty) { - mints = iter->ts; - oldest = iter; + _device->write(e->block, e->buffer); + e->dirty = false; } - } + + break; + } } - - - if (freeCount && (_blocks.size() >= _cacheSize)) - { - // re-use old buffer. - - oldest->block = block; - oldest->count = 1; - oldest->ts = _ts; - oldest->dirty = false; - - _device->read(block, oldest->data); - return oldest->data; - } - - - ProFUSE::auto_array buffer(new uint8_t[512]); - BlockDescriptor bd = { block, 1, _ts, false, buffer.get() }; - - _device->read(block, buffer.get()); - - _blocks.push_back(bd); - - - return buffer.release(); } -void BlockCache::unload(unsigned block, bool dirty) +// increment the count and remove from the free list +// if necessary. +void ConcreteBlockCache::incrementCount(Entry *e) { - for (BDIter iter = _blocks.begin(); iter != _blocks.end(); ++iter) + if (e->count == 0) { - if (iter->block == block) + Entry *prev = e->prev; + Entry *next = e->next; + + e->prev = e->next = NULL; + + if (prev) prev->next = next; + if (next) next->prev = prev; + + if (_first == e) _first = next; + if (_last == e) _last = prev; + } + + e->count = e->count + 1; + +} + +// decrement the count. If it goes to 0, +// add it as the last block entry. +void ConcreteBlockCache::decrementCount(Entry *e) +{ + e->count = e->count - 1; + if (e->count == 0) + { + if (_last == NULL) { - iter->dirty = dirty || iter->dirty; - if (!--iter->count) - { - if (iter->dirty) - { - _device->write(block, iter->data); - iter->dirty = false; - } - // trim back if too many entries. - if (_blocks.size() > _cacheSize) - { - delete[] iter->data; - _blocks.erase(iter); - } - } + _first = _last = e; return; } + + e->prev = _last; + _last = e; } +} + +Entry *ConcreteBlockCache::newEntry(unsigned block) +{ + Entry *e; + + if (_first) + { + e = _first; + if (_first == _last) + { + _first = _last = NULL; + } + else + { + _first = e->next; + _first->prev = NULL; + } + + removeEntry(e->block); + } + else + { + e = new Entry; + _buffers.push_back(e); + } + + e->next = NULL; + e->prev= NULL; + e->nextHash = NULL; + e->count = 1; + e->block = block; + e->dirty = false; + + return e; +} + + +void ConcreteBlockCache::setLast(Entry *e) +{ + if (_last == NULL) + { + _first = _last = e; + return; + } + + e->prev = _last; + _last->next = e; + _last = e; } \ No newline at end of file diff --git a/Device/BlockCache.h b/Device/BlockCache.h index 3983f1c..1d84c5a 100644 --- a/Device/BlockCache.h +++ b/Device/BlockCache.h @@ -7,65 +7,115 @@ namespace Device { class BlockDevice; +class MappedFile; - -class AbstractBlockCache { +class BlockCache { public: - virtual ~AbstractBlockCache(); + + BlockCache *Create(BlockDevice *device, unsigned size = 16); + + virtual ~BlockCache(); + + bool readOnly() { return _readOnly; } + unsigned blocks() { return _blocks; } + BlockDevice *device() { return _device; } - virtual void write() = 0; + + virtual void sync() = 0; + virtual void write(unsigned block, const void *vp) = 0; - virtual void *load(unsigned block) = 0; - virtual void unload(unsigned block, bool dirty) = 0; + + virtual void *acquire(unsigned block) = 0; + virtual void release(unsigned block, bool dirty) = 0; + virtual void markDirty(unsigned block) = 0; - void unload(unsigned block) { unload(block, false); } + void release(unsigned block) { release(block, false); } + +protected: + BlockCache(BlockDevice *device); + + BlockDevice *_device; +private + unsigned _blocks; + bool _readOnly; }; -class BlockCache : public AbstractBlockCache { +class ConcreteBlockCache : public BlockCache { public: - BlockCache(BlockDevice *device, unsigned size = 16); - ~BlockCache(); + ConcreteBlockCache(BlockDevice *device, unsigned size = 16); + virtual ~ConcreteBlockCache(); - virtual void write(); - - virtual void *load(unsigned block); - virtual void unload(unsigned block, bool dirty); + virtual void sync(); + virtual void write(unsigned block, const void *vp) = 0; + + + virtual void *acquire(unsigned block); + virtual void release(unsigned block, bool dirty); + virtual void markDirty(unsigned block); private: - - struct BlockDescriptor { + struct Entry { unsigned block; unsigned count; - unsigned ts; bool dirty; - uint8_t *data; + + struct Entry *next; + struct Entry *prev; + struct Entry *nextHash; + + uint8_t buffer[512]; + }; + + enum { HashTableSize = 23 }; + std::vector_buffers; + + Entry *_hashTable[HashTableSize]; + + Entry *_first; + Entry *_last; - std::vector _blocks; - BlockDevice *_device; - unsigned _ts; - unsigned _cacheSize; + unsigned hashFunction(unsigned block); + Entry *findEntry(unsigned block); + void removeEntry(unsigned block); + + Entry *newEntry(unsigned block); + + void pushEntry(Entry *); + + void setLast(Entry *); + + incrementCount(Entry *); + decrementCount(Entry *); }; -class MappedBlockCache : public AbstractBlockCache { +class MappedBlockCache : public BlockCache { public: - MappedBlockCache(void *data, unsigned blocks); + MappedBlockCache(BlockDevice *, void *data); + virtual ~MappedBlockCache(); - virtual void write(); + virtual void sync() = 0; + virtual void write(unsigned block, const void *vp) = 0; - virtual void *load(unsigned block); - virtual void unload(unsigned block, bool dirty); + virtual bool readOnly(); + virtual unsigned blocks(); + + + + virtual void *acquire(unsigned block) = 0; + virtual void release(unsigned block, bool dirty) = 0; + virtual void markDirty(unsigned block) = 0; private: - unsigned _blocks; - uint8_t * _data; + void *_data; + }; } // namespace From 2754cdd24a4fd3308b592df51365739c9d67c3bc Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 13 Mar 2010 19:24:00 +0000 Subject: [PATCH 080/236] Improve block cache git-svn-id: https://profuse.googlecode.com/svn/branches/v2@199 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/BlockCache.cpp | 91 ++++++++++++++++++++++++++++++++++++++----- Device/BlockCache.h | 17 ++++---- 2 files changed, 88 insertions(+), 20 deletions(-) diff --git a/Device/BlockCache.cpp b/Device/BlockCache.cpp index 4e0c3c9..1b071be 100644 --- a/Device/BlockCache.cpp +++ b/Device/BlockCache.cpp @@ -18,6 +18,34 @@ * */ +/* + * The primary purpose of the block cache is not as a cache + * (the OS probably does a decent job of that) but rather to + * simplify read/writes. Blocks will always be accessed by + * pointer, so any updates will be shared. + * For memory mapped prodos-order files, MappedBlockCache just + * returns a pointer to the memory. + * For dos-order, nibblized, or raw devices, ConcreteBlockCache + * uses an approach similar to minix (although the buffer pool will + * expand if needed). + * + * _buffers is a vector of all buffers and only exists to make + * freeing them easier. + * _hashTable is a simple hashtable of loaded blocks. + * _first and _last are a double-linked list of unused blocks, stored + * in lru order. + * + * The Entry struct contains the buffer, the block, a dirty flag, and an in-use + * count as well as pointer for the hashtable and lru list. + * When a block is loaded, it is stored in the _hashTable. It remains in the + * hash table when the in-use count goes to 0 (it will also be added to the + * end of the lru list). + * + * dirty buffers are only written to disk in 3 scenarios: + * a) sync() is called + * b) the cache is deleted + * c) a buffer is re-used from the lru list. + */ using namespace Device; @@ -40,6 +68,20 @@ BlockCache::~BlockCache() delete _device; } +void BlockCache::write(unsigned block, const void *bp) +{ + void *address = acquire(block); + std::memcpy(address, bp, 512); + release(block, true); +} + +void BlockCache::read(unsigned block, void *bp) +{ + void *address = acquire(block); + std::memcpy(bp, address, 512); + release(block, false); +} + #pragma mark - #pragma mark MappedBlockCache @@ -157,6 +199,30 @@ ConcreteBlockCache::sync() } +void ConcreteBlockCache::write(unsigned block, const void *bp) +{ + FileEntry *e = findEntry(); + + if (e) + { + e->dirty = true; + std::memcpy(e->buffer, bp, 512); + return; + } + + // returns a new entry not in the hashtable or the linked list. + // we add it to both. + e = newEntry(block); + + e->count = 0; + e->dirty = true; + + std::memcpy(e->buffer, bp, 512); + + addEntry(e); + setLast(e); +} + void ConcreteBlockCache::markDirty(unsigned block) { Entry *e = findEntry(block); @@ -188,16 +254,13 @@ void *ConcreteBlockCache::acquire(unsigned block) incrementCount(e); return e->buffer; } - - unsigned hash = hashFunction(block); // returns a new entry, not in hash table, not in free list. e = newEntry(block); _device->read(block, e->buffer); - e->nextHash = _hashTable[hash]; - _hashTable[hash] = e; + addEntry(e); return e->buffer; } @@ -240,18 +303,20 @@ void removeEntry(unsigned block) prev->nextHash = e->nextHash; e->nextHash = NULL; - if (e->dirty) - { - _device->write(e->block, e->buffer); - e->dirty = false; - } - break; } } } +void ConcreteBlockCache::addEntry(Entry *e) +{ + unsigned hash = hashFunction(e->block); + + e->nextHash = _hashTable[hash]; + _hashTable[hash] = e; +} + // increment the count and remove from the free list // if necessary. void ConcreteBlockCache::incrementCount(Entry *e) @@ -310,6 +375,12 @@ Entry *ConcreteBlockCache::newEntry(unsigned block) _first->prev = NULL; } + + if (e->dirty) + { + _device->write(e->block, e->buffer); + e->dirty = false; + } removeEntry(e->block); } else diff --git a/Device/BlockCache.h b/Device/BlockCache.h index 1d84c5a..ce629e4 100644 --- a/Device/BlockCache.h +++ b/Device/BlockCache.h @@ -23,8 +23,8 @@ public: virtual void sync() = 0; - virtual void write(unsigned block, const void *vp) = 0; - + virtual void write(unsigned block, const void *bp); + virtual void read(unsigned block, void *bp); virtual void *acquire(unsigned block) = 0; virtual void release(unsigned block, bool dirty) = 0; @@ -84,6 +84,7 @@ private: Entry *findEntry(unsigned block); void removeEntry(unsigned block); + void addEntry(Entry *); Entry *newEntry(unsigned block); @@ -102,16 +103,12 @@ class MappedBlockCache : public BlockCache { virtual ~MappedBlockCache(); virtual void sync() = 0; - virtual void write(unsigned block, const void *vp) = 0; - - virtual bool readOnly(); - virtual unsigned blocks(); - + virtual void write(unsigned block, const void *vp); - virtual void *acquire(unsigned block) = 0; - virtual void release(unsigned block, bool dirty) = 0; - virtual void markDirty(unsigned block) = 0; + virtual void *acquire(unsigned block); + virtual void release(unsigned block, bool dirty); + virtual void markDirty(unsigned block); private: void *_data; From 6d4e06b403051617aa749ce2af60190e9ecea7ee Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 14 Mar 2010 12:35:22 +0000 Subject: [PATCH 081/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@200 aa027e90-d47c-11dd-86d7-074df07e0730 --- MappedFile.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 MappedFile.cpp diff --git a/MappedFile.cpp b/MappedFile.cpp new file mode 100644 index 0000000..32d3e3a --- /dev/null +++ b/MappedFile.cpp @@ -0,0 +1,61 @@ +#include +#include + +#include + +class MappedFile +{ +public: + + MappedFile(int fd, bool readOnly) + { + _fd = fd; + _length = ::lseek(fd, 0, SEEK_END); + _address = MAP_FAILED; + if (_length > 0) + { + _address = ::mmap(0, _length, + readOnly ? PROT_READ : PROT_READ | PROT_WRITE, + MAP_FILE, fd, 0); + } + } + + MappedFile(void *address, size_t size) + { + _fd = -1; + _address = address; + _size = size; + } + + ~MappedFile() + { + if (_address != MAP_FAILED) ::munmap(_address, _length); + if (_fd != -1) ::close(_fd); + } + + void *address() const + { + return _address; + } + + size_t length() + { + return _length; + } + + int sync() + { + + if (::msync(_address, _length, MS_SYNC) == 0) + return 0; + return errno; + } + + + +private: + int _fd; + void *_address; + size_t _length; + +}; \ No newline at end of file From b83d2df14b544cac7db694c41b3c5f013146f57f Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 15 Mar 2010 03:05:48 +0000 Subject: [PATCH 082/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@201 aa027e90-d47c-11dd-86d7-074df07e0730 --- File/File.cpp | 43 +++++++++++++++++++++++++ File/File.h | 33 +++++++++++++++++++ File/MappedFile.cpp | 77 +++++++++++++++++++++++++++++++++++++++++++++ File/MappedFile.h | 33 +++++++++++++++++++ 4 files changed, 186 insertions(+) create mode 100644 File/File.cpp create mode 100644 File/File.h create mode 100644 File/MappedFile.cpp create mode 100644 File/MappedFile.h diff --git a/File/File.cpp b/File/File.cpp new file mode 100644 index 0000000..c036633 --- /dev/null +++ b/File/File.cpp @@ -0,0 +1,43 @@ +#include "File.h" + +#include + +using namespace File; + +File::File() +{ + _fd = -1; +} + +File::File(int fd) +{ + _fd = fd; +} + +File::File(File& f) +{ + _fd = f._fd; + f._fd = -1; +} + +File::File(const char *name, int flags) +{ + _fd = ::open(name, flags); + if (_fd < 0) + throw ProFUSE::PosixException(errno); +} + +File::~File() +{ + close(); +} + +File::close() +{ + int fd = _fd; + _fd = -1; + + if (fd >= 0 && ::close(fd) != 0) + throw ProFUSE::PosixException(errno); +} + diff --git a/File/File.h b/File/File.h new file mode 100644 index 0000000..4c766d2 --- /dev/null +++ b/File/File.h @@ -0,0 +1,33 @@ +#ifndef __FILE_H__ +#define __FILE_H__ + +#include +#include + +namespace File { + +enum Flags { + ReadOnly = O_RDONLY, + WriteOnly = O_WRONLY, + ReadWrite = O_RDWR +}; + +class File { + + public: + File(); + File(File &); + File(int fd); + File(const char *name, int flags); + ~File(); + + int fd() const { return _fd; } + + void close(); + + private: + int _fd; +}; + +} +#endif diff --git a/File/MappedFile.cpp b/File/MappedFile.cpp new file mode 100644 index 0000000..8fc4351 --- /dev/null +++ b/File/MappedFile.cpp @@ -0,0 +1,77 @@ +#include "MappedFile.h" + +#include +#include + +using namespace File; + + +MappedFile::MappedFile() +{ + _length = -1; + _address = MAP_FAILED; +} + +MappedFile::MappedFile(MappedFile &mf) +{ + _address = mf._address; + _length = mf._length; + + mf._address = MAP_FAILED; + mf._length = -1; +} + +MappedFile::MappedFile(File f, int flags) +{ + struct stat st; + + // close enough + if (f.fd() < 0) + throw ProFUSE::PosixException(EBADF); + + + if (::fstat(f.fd(), st) != 0) + throw ProFUSE::PosixException(errno); + + if (!S_ISREG(st.st_mode)) + throw ProFUSE::PosixException(ENODEV); + + _length = st.st_size; + _address = ::mmap(0, _length, + readOnly ? PROT_READ : PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED, f.fd(), 0); + + if (_address == MAP_FAILED) + throw ProFUSE::PosixException(errno); +} + +MappedFile::~MappedFile() +{ + close(); +} + + + +MappedFile::close() +{ + if (_address != MAP_FAILED) + { + void *address = _address; + size_t length = _length; + + _address = MAP_FAILED; + _length = -1; + + if (::munmap(address, length) != 0) + throw ProFUSE::PosixException(errno); + } +} + +MappedFile::sync() +{ + if (_address != MAP_FAILED) + { + if (::msync(_address, _length, MS_SYNC) != 0) + throw ProFUSE::PosixException(errno); + } +} \ No newline at end of file diff --git a/File/MappedFile.h b/File/MappedFile.h new file mode 100644 index 0000000..90852ec --- /dev/null +++ b/File/MappedFile.h @@ -0,0 +1,33 @@ +#ifndef __MAPPED_FILE_H__ +#define __MAPPED_FILE_H__ + +#include + +#include "File.h" + +namespace File { + +class MappedFile { + public: + + MappedFile(); + MappedFile(File f, int flags); + MappedFile(MappedFile&); + + ~MappedFile(); + + void sync(); + void close(); + + void *address() const { return _address; } + size_t length() const { return _length; } + + private: + + void *_address; + size_t _length; +}; + +} + +#endif \ No newline at end of file From 12385a19dcd22e3e8f36eefcc0d92a66f87032b8 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 17 Mar 2010 03:42:27 +0000 Subject: [PATCH 083/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@202 aa027e90-d47c-11dd-86d7-074df07e0730 --- File/File.cpp | 45 +++++++++++++++++++++++++++++-------- File/File.h | 17 +++++++------- File/MappedFile.cpp | 54 ++++++++++++++++++++++++++++++++++----------- File/MappedFile.h | 11 +++++---- 4 files changed, 92 insertions(+), 35 deletions(-) diff --git a/File/File.cpp b/File/File.cpp index c036633..4442b1b 100644 --- a/File/File.cpp +++ b/File/File.cpp @@ -1,8 +1,14 @@ -#include "File.h" - +#include #include -using namespace File; +#include +#include + + + +using ProFUSE::Exception; +using ProFUSE::POSIXException; + File::File() { @@ -22,9 +28,12 @@ File::File(File& f) File::File(const char *name, int flags) { + #undef __METHOD__ + #define __METHOD__ "File::File" + _fd = ::open(name, flags); if (_fd < 0) - throw ProFUSE::PosixException(errno); + throw POSIXException( __METHOD__ ": open", errno); } File::~File() @@ -32,12 +41,30 @@ File::~File() close(); } -File::close() +void File::close() { - int fd = _fd; - _fd = -1; + #undef __METHOD__ + #define __METHOD__ "File::close" + + if (_fd >= 0) + { + int fd = _fd; + _fd = -1; - if (fd >= 0 && ::close(fd) != 0) - throw ProFUSE::PosixException(errno); + if (::close(fd) != 0) + throw POSIXException(__METHOD__ ": close", errno); + } } + +void File::adopt(File &f) +{ + close(); + _fd = f._fd; + f._fd = -1; +} + +void File::swap(File &f) +{ + std::swap(_fd, f._fd); +} diff --git a/File/File.h b/File/File.h index 4c766d2..56763c5 100644 --- a/File/File.h +++ b/File/File.h @@ -1,17 +1,11 @@ #ifndef __FILE_H__ #define __FILE_H__ +#include #include #include -namespace File { - -enum Flags { - ReadOnly = O_RDONLY, - WriteOnly = O_WRONLY, - ReadWrite = O_RDWR -}; - + class File { public: @@ -24,10 +18,15 @@ class File { int fd() const { return _fd; } void close(); + + void adopt(File &f); + void swap(File &f); private: + + // could call dup() or something. + File& operator=(const File &f); int _fd; }; -} #endif diff --git a/File/MappedFile.cpp b/File/MappedFile.cpp index 8fc4351..a1f79f2 100644 --- a/File/MappedFile.cpp +++ b/File/MappedFile.cpp @@ -1,11 +1,14 @@ -#include "MappedFile.h" - +#include #include + #include -using namespace File; +#include +#include +using ProFUSE::POSIXException; + MappedFile::MappedFile() { _length = -1; @@ -21,20 +24,23 @@ MappedFile::MappedFile(MappedFile &mf) mf._length = -1; } -MappedFile::MappedFile(File f, int flags) +MappedFile::MappedFile(File f, bool readOnly) { + #undef __METHOD__ + #define __METHOD__ "MappedFile::MappedFile" + struct stat st; // close enough if (f.fd() < 0) - throw ProFUSE::PosixException(EBADF); + throw POSIXException( __METHOD__, EBADF); - if (::fstat(f.fd(), st) != 0) - throw ProFUSE::PosixException(errno); + if (::fstat(f.fd(), &st) != 0) + throw POSIXException(__METHOD__ ": fstat", errno); if (!S_ISREG(st.st_mode)) - throw ProFUSE::PosixException(ENODEV); + throw POSIXException(__METHOD__, ENODEV); _length = st.st_size; _address = ::mmap(0, _length, @@ -42,7 +48,7 @@ MappedFile::MappedFile(File f, int flags) MAP_FILE | MAP_SHARED, f.fd(), 0); if (_address == MAP_FAILED) - throw ProFUSE::PosixException(errno); + throw POSIXException(__METHOD__ ": mmap", errno); } MappedFile::~MappedFile() @@ -52,8 +58,11 @@ MappedFile::~MappedFile() -MappedFile::close() +void MappedFile::close() { + #undef __METHOD__ + #define __METHOD__ "MappedFile::close" + if (_address != MAP_FAILED) { void *address = _address; @@ -63,15 +72,34 @@ MappedFile::close() _length = -1; if (::munmap(address, length) != 0) - throw ProFUSE::PosixException(errno); + throw POSIXException(__METHOD__ ": munmap", errno); } } -MappedFile::sync() +void MappedFile::sync() { + #undef __METHOD__ + #define __METHOD__ "MappedFile::sync" + if (_address != MAP_FAILED) { if (::msync(_address, _length, MS_SYNC) != 0) - throw ProFUSE::PosixException(errno); + throw POSIXException(__METHOD__ ": msync", errno); } +} + +void MappedFile::adopt(MappedFile &mf) +{ + close(); + _address = mf._address; + _length = mf._length; + + mf._address = MAP_FAILED; + mf._length = -1; +} + +void MappedFile::swap(MappedFile &mf) +{ + std::swap(_address, mf._address); + std::swap(_length, mf._length); } \ No newline at end of file diff --git a/File/MappedFile.h b/File/MappedFile.h index 90852ec..bc8911c 100644 --- a/File/MappedFile.h +++ b/File/MappedFile.h @@ -3,15 +3,14 @@ #include -#include "File.h" +#include -namespace File { class MappedFile { public: MappedFile(); - MappedFile(File f, int flags); + MappedFile(File f, bool readOnly); MappedFile(MappedFile&); ~MappedFile(); @@ -22,12 +21,16 @@ class MappedFile { void *address() const { return _address; } size_t length() const { return _length; } + void swap(MappedFile &); + void adopt(MappedFile &); + private: + MappedFile& operator=(MappedFile &); + void *_address; size_t _length; }; -} #endif \ No newline at end of file From 1ac9b03e475c19550f35db2217db74d97ac6441e Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 19 Mar 2010 17:42:13 +0000 Subject: [PATCH 084/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@204 aa027e90-d47c-11dd-86d7-074df07e0730 --- {Device => Cache}/BlockCache.cpp | 0 {Device => Cache}/BlockCache.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {Device => Cache}/BlockCache.cpp (100%) rename {Device => Cache}/BlockCache.h (100%) diff --git a/Device/BlockCache.cpp b/Cache/BlockCache.cpp similarity index 100% rename from Device/BlockCache.cpp rename to Cache/BlockCache.cpp diff --git a/Device/BlockCache.h b/Cache/BlockCache.h similarity index 100% rename from Device/BlockCache.h rename to Cache/BlockCache.h From 07f1244834bcdfc724eefcb49142ad2aece73219 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 19 Mar 2010 18:12:22 +0000 Subject: [PATCH 085/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@205 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/BlockCache.h | 39 ++++++++--------------- Cache/ConcreteBlockCache.h | 64 +++++++++++++++++++++++++++++++++++++ Cache/MappedBlockCache.cpp | 65 ++++++++++++++++++++++++++++++++++++++ Cache/MappedBlockCache.h | 30 ++++++++++++++++++ 4 files changed, 173 insertions(+), 25 deletions(-) create mode 100644 Cache/ConcreteBlockCache.h create mode 100644 Cache/MappedBlockCache.cpp create mode 100644 Cache/MappedBlockCache.h diff --git a/Cache/BlockCache.h b/Cache/BlockCache.h index ce629e4..f740c32 100644 --- a/Cache/BlockCache.h +++ b/Cache/BlockCache.h @@ -4,12 +4,19 @@ #include #include +class MappedFile; +class Device::BlockDevice; + namespace Device { -class BlockDevice; -class MappedFile; +enum { + kBlockDirty = 1, + kBlockCommitNow = 2, + kBlockReuse = 3 +} BlockReleaseFlags; + class BlockCache { public: @@ -27,10 +34,11 @@ public: virtual void read(unsigned block, void *bp); virtual void *acquire(unsigned block) = 0; - virtual void release(unsigned block, bool dirty) = 0; + virtual void release(unsigned block, int flags) = 0 ; virtual void markDirty(unsigned block) = 0; - void release(unsigned block) { release(block, false); } + void release(unsigned block) { release(block, 0); } + void release(unsigned block, bool dirty) { release(block, dirty ? kBlockDirty : 0); } protected: BlockCache(BlockDevice *device); @@ -52,7 +60,7 @@ public: virtual void *acquire(unsigned block); - virtual void release(unsigned block, bool dirty); + virtual void release(unsigned block, int flags); virtual void markDirty(unsigned block); @@ -96,25 +104,6 @@ private: decrementCount(Entry *); }; -class MappedBlockCache : public BlockCache { - public: - - MappedBlockCache(BlockDevice *, void *data); - virtual ~MappedBlockCache(); - - virtual void sync() = 0; - virtual void write(unsigned block, const void *vp); - - - virtual void *acquire(unsigned block); - virtual void release(unsigned block, bool dirty); - virtual void markDirty(unsigned block); - - private: - void *_data; - -}; - } // namespace -#endif \ No newline at end of file +#endif diff --git a/Cache/ConcreteBlockCache.h b/Cache/ConcreteBlockCache.h new file mode 100644 index 0000000..2a97969 --- /dev/null +++ b/Cache/ConcreteBlockCache.h @@ -0,0 +1,64 @@ +#ifndef __CONCRETE_BLOCK_CACHE_H__ +#define __CONCRETE_BLOCK_CACHE_H__ + +#include + +#include + +namespace Device { + +class ConcreteBlockCache : public BlockCache { +public: + ConcreteBlockCache(BlockDevice *device, unsigned size = 16); + virtual ~ConcreteBlockCache(); + + virtual void sync(); + virtual void write(unsigned block, const void *vp) = 0; + + + virtual void *acquire(unsigned block); + virtual void release(unsigned block, int flags); + virtual void markDirty(unsigned block); + + +private: + struct Entry { + unsigned block; + unsigned count; + bool dirty; + + struct Entry *next; + struct Entry *prev; + struct Entry *nextHash; + + uint8_t buffer[512]; + + }; + + enum { HashTableSize = 23 }; + + std::vector_buffers; + + Entry *_hashTable[HashTableSize]; + + Entry *_first; + Entry *_last; + + + unsigned hashFunction(unsigned block); + + Entry *findEntry(unsigned block); + void removeEntry(unsigned block); + void addEntry(Entry *); + + Entry *newEntry(unsigned block); + + void pushEntry(Entry *); + + void setLast(Entry *); + + incrementCount(Entry *); + decrementCount(Entry *); +}; + +} diff --git a/Cache/MappedBlockCache.cpp b/Cache/MappedBlockCache.cpp new file mode 100644 index 0000000..d8a8da4 --- /dev/null +++ b/Cache/MappedBlockCache.cpp @@ -0,0 +1,65 @@ + +#include +#include + +#include +#include +#include + +#include +#include +#include + + + +using namespace Device; + +using ProFUSE::Exception; +using ProFUSE::POSIXException; + + +MappedBlockCache::MappedBlockCache(Device *device, void *data) : + BlockCache(device) +{ + _data = (uint8_t *)data; + _dirty = false; +} + +MappedBlockCache::~MappedBlockCache() +{ + if (_dirty) sync(); +} + + +void *MappedBlockCache::acquire(unsigned block) +{ +#undef __METHOD__ +#define __METHOD__ "MappedBlockCache::load" + + if (block >= blocks()) + throw Exception(__METHOD__ ": Invalid block."); + + + return _data + block * 512; +} + +void MappedBlockCache::unload(unsigned block, int flags) +{ +#undef __METHOD__ +#define __METHOD__ "MappedBlockCache::unload" + + if (flags & kBlockCommitNow) + { + _dirty = true; + sync(); + return; + } + + if (flags & kBlockDirty) _dirty = true; +} + +void MappedBlockCache::sync() +{ + _device->sync(); + _dirty = false; +} diff --git a/Cache/MappedBlockCache.h b/Cache/MappedBlockCache.h new file mode 100644 index 0000000..319a584 --- /dev/null +++ b/Cache/MappedBlockCache.h @@ -0,0 +1,30 @@ +#ifndef __MAPPED_BLOCK_CACHE_H__ +#define __MAPPED_BLOCK_CACHE_H__ + +#include + +namespace Device { + +class MappedBlockCache : public BlockCache { + public: + + MappedBlockCache(BlockDevice *, void *data); + virtual ~MappedBlockCache(); + + virtual void sync() = 0; + virtual void write(unsigned block, const void *vp); + + + virtual void *acquire(unsigned block); + virtual void release(unsigned block, int flags); + virtual void markDirty(unsigned block); + + private: + void *_data; + bool _dirty; + +}; + +} // namespace + + From 82167f07f96f2750ed6e054be8a9a45ad25d72db Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 21 Mar 2010 22:27:20 +0000 Subject: [PATCH 086/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@206 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/MappedBlockCache.cpp | 38 +++++++++++++++++++++++++++++++++++--- Cache/MappedBlockCache.h | 8 +++++--- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/Cache/MappedBlockCache.cpp b/Cache/MappedBlockCache.cpp index d8a8da4..103f846 100644 --- a/Cache/MappedBlockCache.cpp +++ b/Cache/MappedBlockCache.cpp @@ -8,7 +8,6 @@ #include #include -#include @@ -48,18 +47,51 @@ void MappedBlockCache::unload(unsigned block, int flags) #undef __METHOD__ #define __METHOD__ "MappedBlockCache::unload" + // kBlockCommitNow implies kBlockDirty. if (flags & kBlockCommitNow) { - _dirty = true; - sync(); + sync(block) return; } if (flags & kBlockDirty) _dirty = true; } +// sync everything. void MappedBlockCache::sync() { _device->sync(); _dirty = false; } + +/* + * + * sync an individual page. + * + */ +void MappedBlockCache::sync(unsigned block) +{ +#undef __METHOD__ +#define __METHOD__ "MappedBlockCache::sync" + + + int pageSize = ::getpagesize(); + + void *start = (_data + block * 512) % pagesize; + void *end = (_data + 512 + block * 512) % pagesize; + + if (::msync(start, pagesize, MS_SYNC) != 0) + throw POSIXException(__METHOD__ ": msync", errno); + + if (start != end) + { + if (::msync(end, pagesize, MS_SYNC) != 0) + throw POSIXException(__METHOD__ ": msync", errno); + } +} + +void MappedBlockCache::markDirty(unsigned block) +{ + _dirty = true; +} + diff --git a/Cache/MappedBlockCache.h b/Cache/MappedBlockCache.h index 319a584..c10a362 100644 --- a/Cache/MappedBlockCache.h +++ b/Cache/MappedBlockCache.h @@ -1,7 +1,7 @@ #ifndef __MAPPED_BLOCK_CACHE_H__ #define __MAPPED_BLOCK_CACHE_H__ -#include +#include namespace Device { @@ -11,7 +11,7 @@ class MappedBlockCache : public BlockCache { MappedBlockCache(BlockDevice *, void *data); virtual ~MappedBlockCache(); - virtual void sync() = 0; + virtual void sync(); virtual void write(unsigned block, const void *vp); @@ -20,7 +20,9 @@ class MappedBlockCache : public BlockCache { virtual void markDirty(unsigned block); private: - void *_data; + void sync(block); + + uint8_t *_data; bool _dirty; }; From e1d01c52986b1c9bfceba6a3bce97432a11f72b3 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 21 Mar 2010 22:33:16 +0000 Subject: [PATCH 087/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@207 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/ConcreteBlockCache.cpp | 353 +++++++++++++++++++++++++++++++++++ Cache/ConcreteBlockCache.h | 5 +- 2 files changed, 356 insertions(+), 2 deletions(-) create mode 100644 Cache/ConcreteBlockCache.cpp diff --git a/Cache/ConcreteBlockCache.cpp b/Cache/ConcreteBlockCache.cpp new file mode 100644 index 0000000..3b300a0 --- /dev/null +++ b/Cache/ConcreteBlockCache.cpp @@ -0,0 +1,353 @@ + +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + + +/* + * Note -- everything is assumed to be single-threaded. + * + */ + +/* + * The primary purpose of the block cache is not as a cache + * (the OS probably does a decent job of that) but rather to + * simplify read/writes. Blocks will always be accessed by + * pointer, so any updates will be shared. + * For memory mapped prodos-order files, MappedBlockCache just + * returns a pointer to the memory. + * For dos-order, nibblized, or raw devices, ConcreteBlockCache + * uses an approach similar to minix (although the buffer pool will + * expand if needed). + * + * _buffers is a vector of all buffers and only exists to make + * freeing them easier. + * _hashTable is a simple hashtable of loaded blocks. + * _first and _last are a double-linked list of unused blocks, stored + * in lru order. + * + * The Entry struct contains the buffer, the block, a dirty flag, and an in-use + * count as well as pointer for the hashtable and lru list. + * When a block is loaded, it is stored in the _hashTable. It remains in the + * hash table when the in-use count goes to 0 (it will also be added to the + * end of the lru list). + * + * dirty buffers are only written to disk in 3 scenarios: + * a) sync() is called + * b) the cache is deleted + * c) a buffer is re-used from the lru list. + */ + + +using namespace Device; + +using ProFUSE::Exception; +using ProFUSE::POSIXException; + + +typedef std::vector::iterator EntryIter; + + + +ConcreteBlockCache::ConcreteBlockCache(BlockDevice *device, unsigned size) : + BlockCache(device) +{ + if (size < 16) size = 16; + + std::memset(_hashTable, 0, sizeof(Entry *) * HashTableSize); + + for (unsigned i = 0; i < size; ++i) + { + Entry *e = new Entry; + + std::memset(e, 0, sizeof(Entry)); + _buffers.push_back(e); + } + _first = _last = NULL; + + _first = _buffers.front(); + _last = _buffers.back(); + // form a chain.... + for (unsigned i = 0; i < size; ++i) + { + Entry *e = _buffers[i]; + + if (i > 0) e->prev = _buffers[i - 1]; + + if (i < size - 1) e->next = _buffers[i + 1]; + } + +} + +ConcreteBlockCache::~ConcreteBlockCache() +{ + EntryIter iter; + for (iter = _buffers.begin(); iter != _buffers.end(); ++iter) + { + Entry *e = *iter; + + if (e->dirty) + { + _device->write(e->block, e->buffer); + } + + delete e; + } + _device->sync(); +} + + +ConcreteBlockCache::sync() +{ + EntryIter iter; + for (iter = _buffers.begin(); iter != _buffers.end(); ++iter) + { + Entry *e = *iter; + + if (e->dirty) + { + _device->write(e->block, e->buffer); + e->dirty = false; + } + } + _device->sync(); +} + + +void ConcreteBlockCache::write(unsigned block, const void *bp) +{ + FileEntry *e = findEntry(); + + if (e) + { + e->dirty = true; + std::memcpy(e->buffer, bp, 512); + return; + } + + // returns a new entry not in the hashtable or the linked list. + // we add it to both. + e = newEntry(block); + + e->count = 0; + e->dirty = true; + + std::memcpy(e->buffer, bp, 512); + + addEntry(e); + setLast(e); +} + +void ConcreteBlockCache::markDirty(unsigned block) +{ + Entry *e = findEntry(block); + + if (e) e->dirty = true; + // error otherwise? +} + + +void ConcreteBlockCache::release(unsigned block, int flags) +{ + Entry *e = findEntry(block); + bool dirty = flags & (kBlockDirty | kBlockCommitNow); + + if (e) + { + if (dirty) e->dirty = true; + + decrementCount(e); + + if (flags & kCommitNow) + { + _device->write(block, e->buffer); + e->dirty = false; + } + + } + // error otherwise? +} + +void *ConcreteBlockCache::acquire(unsigned block) +{ + Entry *e = findEntry(block); + + if (e) + { + incrementCount(e); + return e->buffer; + } + + // returns a new entry, not in hash table, not in free list. + e = newEntry(block); + + _device->read(block, e->buffer); + + addEntry(e); + + return e->buffer; +} + +unsigned ConcreteBlockCache::hashFunction(unsigned block) +{ + return block % HashTableSize; +} + +/* + * remove a block from the hashtable + * and write to dick if dirty. + */ +void removeEntry(unsigned block) +{ + Entry *e; + Entry *prev; + unsigned hash = hashFunction(block); + + e = _hashTable[hash]; + if (!e) return; + + // head pointer, special case. + if (e->block == block) + { + _hashTable[hash] = e->nextHash; + e->nextHash = NULL; + + return; + } + + for(;;) + { + prev = e; + e = e->next; + + if (!e) break; + if (e->block == block) + { + prev->nextHash = e->nextHash; + e->nextHash = NULL; + + break; + } + } +} + + +void ConcreteBlockCache::addEntry(Entry *e) +{ + unsigned hash = hashFunction(e->block); + + e->nextHash = _hashTable[hash]; + _hashTable[hash] = e; +} + +// increment the count and remove from the free list +// if necessary. +void ConcreteBlockCache::incrementCount(Entry *e) +{ + + if (e->count == 0) + { + Entry *prev = e->prev; + Entry *next = e->next; + + e->prev = e->next = NULL; + + if (prev) prev->next = next; + if (next) next->prev = prev; + + if (_first == e) _first = next; + if (_last == e) _last = prev; + } + + e->count = e->count + 1; + +} + +// decrement the count. If it goes to 0, +// add it as the last block entry. +void ConcreteBlockCache::decrementCount(Entry *e) +{ + e->count = e->count - 1; + if (e->count == 0) + { + setLast(e); + } +} + +Entry *ConcreteBlockCache::newEntry(unsigned block) +{ + Entry *e; + + if (_first) + { + e = _first; + if (_first == _last) + { + _first = _last = NULL; + } + else + { + _first = e->next; + _first->prev = NULL; + } + + + if (e->dirty) + { + _device->write(e->block, e->buffer); + e->dirty = false; + } + removeEntry(e->block); + } + else + { + e = new Entry; + _buffers.push_back(e); + } + + e->next = NULL; + e->prev= NULL; + e->nextHash = NULL; + e->count = 1; + e->block = block; + e->dirty = false; + + return e; +} + + +void ConcreteBlockCache::setLast(Entry *e) +{ + if (_last == NULL) + { + _first = _last = e; + return; + } + + e->prev = _last; + _last->next = e; + _last = e; +} + + +void ConcreteBlockCache::setFirst(Entry *e) +{ + if (_first == NULL) + { + _first = _last = e; + return; + } + + e->next = _first; + _first->prev = e; + _first = e; +} \ No newline at end of file diff --git a/Cache/ConcreteBlockCache.h b/Cache/ConcreteBlockCache.h index 2a97969..f430070 100644 --- a/Cache/ConcreteBlockCache.h +++ b/Cache/ConcreteBlockCache.h @@ -3,7 +3,7 @@ #include -#include +#include namespace Device { @@ -56,7 +56,8 @@ private: void pushEntry(Entry *); void setLast(Entry *); - + void setFirst(Entry *); + incrementCount(Entry *); decrementCount(Entry *); }; From 035d802d708f387bd986f81f22d149bc2f235472 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 22 Mar 2010 00:32:27 +0000 Subject: [PATCH 088/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@208 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/BlockCache.h | 65 ++++---------------------------------- Cache/MappedBlockCache.cpp | 18 +++++++---- Cache/MappedBlockCache.h | 3 +- 3 files changed, 20 insertions(+), 66 deletions(-) diff --git a/Cache/BlockCache.h b/Cache/BlockCache.h index f740c32..d613cf0 100644 --- a/Cache/BlockCache.h +++ b/Cache/BlockCache.h @@ -5,13 +5,12 @@ #include class MappedFile; -class Device::BlockDevice; namespace Device { +class BlockDevice; - -enum { +enum BlockReleaseFlags { kBlockDirty = 1, kBlockCommitNow = 2, kBlockReuse = 3 @@ -38,72 +37,20 @@ public: virtual void markDirty(unsigned block) = 0; void release(unsigned block) { release(block, 0); } - void release(unsigned block, bool dirty) { release(block, dirty ? kBlockDirty : 0); } + void release(unsigned block, bool dirty) + { release(block, dirty ? kBlockDirty : 0); } protected: BlockCache(BlockDevice *device); BlockDevice *_device; -private + +private: unsigned _blocks; bool _readOnly; }; -class ConcreteBlockCache : public BlockCache { -public: - ConcreteBlockCache(BlockDevice *device, unsigned size = 16); - virtual ~ConcreteBlockCache(); - - virtual void sync(); - virtual void write(unsigned block, const void *vp) = 0; - - - virtual void *acquire(unsigned block); - virtual void release(unsigned block, int flags); - virtual void markDirty(unsigned block); - - -private: - struct Entry { - unsigned block; - unsigned count; - bool dirty; - - struct Entry *next; - struct Entry *prev; - struct Entry *nextHash; - - uint8_t buffer[512]; - - }; - - enum { HashTableSize = 23 }; - - std::vector_buffers; - - Entry *_hashTable[HashTableSize]; - - Entry *_first; - Entry *_last; - - - unsigned hashFunction(unsigned block); - - Entry *findEntry(unsigned block); - void removeEntry(unsigned block); - void addEntry(Entry *); - - Entry *newEntry(unsigned block); - - void pushEntry(Entry *); - - void setLast(Entry *); - - incrementCount(Entry *); - decrementCount(Entry *); -}; - } // namespace #endif diff --git a/Cache/MappedBlockCache.cpp b/Cache/MappedBlockCache.cpp index 103f846..95df640 100644 --- a/Cache/MappedBlockCache.cpp +++ b/Cache/MappedBlockCache.cpp @@ -7,6 +7,8 @@ #include #include +#include + #include @@ -17,7 +19,7 @@ using ProFUSE::Exception; using ProFUSE::POSIXException; -MappedBlockCache::MappedBlockCache(Device *device, void *data) : +MappedBlockCache::MappedBlockCache(BlockDevice *device, void *data) : BlockCache(device) { _data = (uint8_t *)data; @@ -42,7 +44,7 @@ void *MappedBlockCache::acquire(unsigned block) return _data + block * 512; } -void MappedBlockCache::unload(unsigned block, int flags) +void MappedBlockCache::release(unsigned block, int flags) { #undef __METHOD__ #define __METHOD__ "MappedBlockCache::unload" @@ -50,7 +52,7 @@ void MappedBlockCache::unload(unsigned block, int flags) // kBlockCommitNow implies kBlockDirty. if (flags & kBlockCommitNow) { - sync(block) + sync(block); return; } @@ -75,10 +77,14 @@ void MappedBlockCache::sync(unsigned block) #define __METHOD__ "MappedBlockCache::sync" - int pageSize = ::getpagesize(); + int pagesize = ::getpagesize(); - void *start = (_data + block * 512) % pagesize; - void *end = (_data + 512 + block * 512) % pagesize; + void *start = _data + block * 512; + void *end = _data + 512 + block * 512; + + + start = (void *)((ptrdiff_t)start / pagesize * pagesize); + end = (void *)((ptrdiff_t)end / pagesize * pagesize); if (::msync(start, pagesize, MS_SYNC) != 0) throw POSIXException(__METHOD__ ": msync", errno); diff --git a/Cache/MappedBlockCache.h b/Cache/MappedBlockCache.h index c10a362..fac9504 100644 --- a/Cache/MappedBlockCache.h +++ b/Cache/MappedBlockCache.h @@ -20,7 +20,7 @@ class MappedBlockCache : public BlockCache { virtual void markDirty(unsigned block); private: - void sync(block); + void sync(unsigned block); uint8_t *_data; bool _dirty; @@ -29,4 +29,5 @@ class MappedBlockCache : public BlockCache { } // namespace +#endif From ea4f0c448581b3c52ce9ffb824e6e989ead96ff9 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 22 Mar 2010 01:12:51 +0000 Subject: [PATCH 089/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@209 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/BlockCache.cpp | 368 +---------------------------------- Cache/ConcreteBlockCache.cpp | 15 +- Cache/ConcreteBlockCache.h | 6 +- 3 files changed, 14 insertions(+), 375 deletions(-) diff --git a/Cache/BlockCache.cpp b/Cache/BlockCache.cpp index 1b071be..0467fa1 100644 --- a/Cache/BlockCache.cpp +++ b/Cache/BlockCache.cpp @@ -6,46 +6,13 @@ #include #include +#include #include -#include #include #include -/* - * Note -- everything is assumed to be single-threaded. - * - */ - -/* - * The primary purpose of the block cache is not as a cache - * (the OS probably does a decent job of that) but rather to - * simplify read/writes. Blocks will always be accessed by - * pointer, so any updates will be shared. - * For memory mapped prodos-order files, MappedBlockCache just - * returns a pointer to the memory. - * For dos-order, nibblized, or raw devices, ConcreteBlockCache - * uses an approach similar to minix (although the buffer pool will - * expand if needed). - * - * _buffers is a vector of all buffers and only exists to make - * freeing them easier. - * _hashTable is a simple hashtable of loaded blocks. - * _first and _last are a double-linked list of unused blocks, stored - * in lru order. - * - * The Entry struct contains the buffer, the block, a dirty flag, and an in-use - * count as well as pointer for the hashtable and lru list. - * When a block is loaded, it is stored in the _hashTable. It remains in the - * hash table when the in-use count goes to 0 (it will also be added to the - * end of the lru list). - * - * dirty buffers are only written to disk in 3 scenarios: - * a) sync() is called - * b) the cache is deleted - * c) a buffer is re-used from the lru list. - */ using namespace Device; @@ -56,7 +23,7 @@ using ProFUSE::POSIXException; #pragma mark - #pragma mark BlockCache -BlockCache::~BlockCache(BlockDevice *device) +BlockCache::BlockCache(BlockDevice *device) { _device = _device; _blocks = device->blocks(); @@ -81,334 +48,3 @@ void BlockCache::read(unsigned block, void *bp) std::memcpy(bp, address, 512); release(block, false); } - -#pragma mark - -#pragma mark MappedBlockCache - -MappedBlockCache::MappedBlockCache(void *data, unsigned blocks) -{ - _blocks = blocks; - _data = (uint8_t *)data; -} - -void MappedBlockCache::write() -{ - // TODO... -} - -void *MappedBlockCache::load(unsigned block) -{ -#undef __METHOD__ -#define __METHOD__ "MappedBlockCache::load" - - if (block >= _blocks) - throw Exception(__METHOD__ ": Invalid block."); - - - return _data + block * 512; -} -void MappedBlockCache::unload(unsigned block, bool dirty) -{ -#undef __METHOD__ -#define __METHOD__ "MappedBlockCache::unload" - - if (!dirty) return; - - // msync must be page-size aligned. - unsigned pagesize = ::getpagesize(); - unsigned offset = block * 512; - void *address = _data + offset / pagesize * pagesize; - unsigned length = offset % pagesize + 512; - - if (::msync(address, length, MS_ASYNC) < 0) - { - throw POSIXException(__METHOD__ ": msync failed.", errno); - } -} - - -#pragma mark - -#pragma mark ConcreteBlockCache - -typedef std::vector::iterator EntryIter; - - - -ConcreteBlockCache::ConcreteBlockCache(BlockDevice *device, unsigned size) : - BlockCache(device) -{ - if (size < 16) size = 16; - - std::memset(_hashTable, 0, sizeof(Entry *) * HashTableSize); - - for (unsigned i = 0; i < size; ++i) - { - Entry *e = new Entry; - - std::memset(e, 0, sizeof(Entry)); - _buffers.push_back(e); - } - _first = _last = NULL; - - _first = _buffers.front(); - _last = _buffers.back(); - // form a chain.... - for (unsigned i = 0; i < size; ++i) - { - Entry *e = _buffers[i]; - - if (i > 0) e->prev = _buffers[i - 1]; - - if (i < size - 1) e->next = _buffers[i + 1]; - } - -} - -ConcreteBlockCache::~ConcreteBlockCache() -{ - EntryIter iter; - for (iter = _buffers.begin(); iter != _buffers.end(); ++iter) - { - Entry *e = *iter; - - if (e->dirty) - { - _device->write(e->block, e->buffer); - } - - delete e; - } - _device->sync(); -} - - -ConcreteBlockCache::sync() -{ - EntryIter iter; - for (iter = _buffers.begin(); iter != _buffers.end(); ++iter) - { - Entry *e = *iter; - - if (e->dirty) - { - _device->write(e->block, e->buffer); - e->dirty = false; - } - } - _device->sync(); -} - - -void ConcreteBlockCache::write(unsigned block, const void *bp) -{ - FileEntry *e = findEntry(); - - if (e) - { - e->dirty = true; - std::memcpy(e->buffer, bp, 512); - return; - } - - // returns a new entry not in the hashtable or the linked list. - // we add it to both. - e = newEntry(block); - - e->count = 0; - e->dirty = true; - - std::memcpy(e->buffer, bp, 512); - - addEntry(e); - setLast(e); -} - -void ConcreteBlockCache::markDirty(unsigned block) -{ - Entry *e = findEntry(block); - - if (e) e->dirty = true; - // error otherwise? -} - - -void ConcreteBlockCache::release(unsigned block, bool dirty) -{ - Entry *e = findEntry(block); - - if (e) - { - if (dirty) e->dirty = true; - - decrementCount(e); - } - // error otherwise? -} - -void *ConcreteBlockCache::acquire(unsigned block) -{ - Entry *e = findEntry(block); - - if (e) - { - incrementCount(e); - return e->buffer; - } - - // returns a new entry, not in hash table, not in free list. - e = newEntry(block); - - _device->read(block, e->buffer); - - addEntry(e); - - return e->buffer; -} - -unsigned ConcreteBlockCache::hashFunction(unsigned block) -{ - return block % HashTableSize; -} - -/* - * remove a block from the hashtable - * and write to dick if dirty. - */ -void removeEntry(unsigned block) -{ - Entry *e; - Entry *prev; - unsigned hash = hashFunction(block); - - e = _hashTable[hash]; - if (!e) return; - - // head pointer, special case. - if (e->block == block) - { - _hashTable[hash] = e->nextHash; - e->nextHash = NULL; - - return; - } - - for(;;) - { - prev = e; - e = e->next; - - if (!e) break; - if (e->block == block) - { - prev->nextHash = e->nextHash; - e->nextHash = NULL; - - break; - } - } -} - - -void ConcreteBlockCache::addEntry(Entry *e) -{ - unsigned hash = hashFunction(e->block); - - e->nextHash = _hashTable[hash]; - _hashTable[hash] = e; -} - -// increment the count and remove from the free list -// if necessary. -void ConcreteBlockCache::incrementCount(Entry *e) -{ - - if (e->count == 0) - { - Entry *prev = e->prev; - Entry *next = e->next; - - e->prev = e->next = NULL; - - if (prev) prev->next = next; - if (next) next->prev = prev; - - if (_first == e) _first = next; - if (_last == e) _last = prev; - } - - e->count = e->count + 1; - -} - -// decrement the count. If it goes to 0, -// add it as the last block entry. -void ConcreteBlockCache::decrementCount(Entry *e) -{ - e->count = e->count - 1; - if (e->count == 0) - { - if (_last == NULL) - { - _first = _last = e; - return; - } - - e->prev = _last; - _last = e; - } -} - -Entry *ConcreteBlockCache::newEntry(unsigned block) -{ - Entry *e; - - if (_first) - { - e = _first; - if (_first == _last) - { - _first = _last = NULL; - } - else - { - _first = e->next; - _first->prev = NULL; - } - - - if (e->dirty) - { - _device->write(e->block, e->buffer); - e->dirty = false; - } - removeEntry(e->block); - } - else - { - e = new Entry; - _buffers.push_back(e); - } - - e->next = NULL; - e->prev= NULL; - e->nextHash = NULL; - e->count = 1; - e->block = block; - e->dirty = false; - - return e; -} - - -void ConcreteBlockCache::setLast(Entry *e) -{ - if (_last == NULL) - { - _first = _last = e; - return; - } - - e->prev = _last; - _last->next = e; - _last = e; -} \ No newline at end of file diff --git a/Cache/ConcreteBlockCache.cpp b/Cache/ConcreteBlockCache.cpp index 3b300a0..eb6474b 100644 --- a/Cache/ConcreteBlockCache.cpp +++ b/Cache/ConcreteBlockCache.cpp @@ -54,7 +54,7 @@ using ProFUSE::Exception; using ProFUSE::POSIXException; -typedef std::vector::iterator EntryIter; +typedef std::vector::iterator EntryIter; @@ -106,7 +106,7 @@ ConcreteBlockCache::~ConcreteBlockCache() } -ConcreteBlockCache::sync() +void ConcreteBlockCache::sync() { EntryIter iter; for (iter = _buffers.begin(); iter != _buffers.end(); ++iter) @@ -125,7 +125,7 @@ ConcreteBlockCache::sync() void ConcreteBlockCache::write(unsigned block, const void *bp) { - FileEntry *e = findEntry(); + Entry *e = findEntry(block); if (e) { @@ -167,7 +167,7 @@ void ConcreteBlockCache::release(unsigned block, int flags) decrementCount(e); - if (flags & kCommitNow) + if (flags & kBlockCommitNow) { _device->write(block, e->buffer); e->dirty = false; @@ -206,7 +206,7 @@ unsigned ConcreteBlockCache::hashFunction(unsigned block) * remove a block from the hashtable * and write to dick if dirty. */ -void removeEntry(unsigned block) +void ConcreteBlockCache::removeEntry(unsigned block) { Entry *e; Entry *prev; @@ -283,7 +283,7 @@ void ConcreteBlockCache::decrementCount(Entry *e) } } -Entry *ConcreteBlockCache::newEntry(unsigned block) +ConcreteBlockCache::Entry *ConcreteBlockCache::newEntry(unsigned block) { Entry *e; @@ -350,4 +350,5 @@ void ConcreteBlockCache::setFirst(Entry *e) e->next = _first; _first->prev = e; _first = e; -} \ No newline at end of file +} + diff --git a/Cache/ConcreteBlockCache.h b/Cache/ConcreteBlockCache.h index f430070..0665b08 100644 --- a/Cache/ConcreteBlockCache.h +++ b/Cache/ConcreteBlockCache.h @@ -58,8 +58,10 @@ private: void setLast(Entry *); void setFirst(Entry *); - incrementCount(Entry *); - decrementCount(Entry *); + void incrementCount(Entry *); + void decrementCount(Entry *); }; } + +#endif From 3b2bbb4e99aacd34079df35c9458878272ccceeb Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 23 Mar 2010 03:02:06 +0000 Subject: [PATCH 090/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@210 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/BlockDevice.cpp | 210 -------------------------------------- Device/BlockDevice.h | 76 +------------- Device/DiskImage.cpp | 226 +++++++++++++++++++++++++++++++++++++++++ Device/DiskImage.h | 92 +++++++++++++++++ 4 files changed, 322 insertions(+), 282 deletions(-) create mode 100644 Device/DiskImage.cpp create mode 100644 Device/DiskImage.h diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index 2c76f0d..43345ed 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -25,11 +25,9 @@ using ProFUSE::POSIXException; BlockDevice::BlockDevice() { - _cache = NULL; } BlockDevice::~BlockDevice() { - delete _cache; } void BlockDevice::zeroBlock(unsigned block) @@ -79,211 +77,3 @@ void *BlockDevice::read(TrackSector ts) return NULL; } - -#pragma mark - -#pragma mark DiskImage - -unsigned DiskImage::ImageType(const char *type, unsigned defv) -{ - const char *tmp; - - if (type == 0 || *type == 0) return defv; - - // type could be a filename, in which case we check the extension. - tmp = std::strrchr(type, '.'); - if (tmp) type = tmp + 1; - if (*type == 0) return defv; - - - if (::strcasecmp(type, "2mg") == 0) - return '2IMG'; - if (::strcasecmp(type, "2img") == 0) - return '2IMG'; - - if (::strcasecmp(type, "dc42") == 0) - return 'DC42'; - - if (::strcasecmp(type, "po") == 0) - return 'PO__'; - if (::strcasecmp(type, "dmg") == 0) - return 'PO__'; - - if (::strcasecmp(type, "dsk") == 0) - return 'DO__'; - if (::strcasecmp(type, "do") == 0) - return 'DO__'; - - if (::strcasecmp(type, "davex") == 0) - return 'DVX_'; - - /* - // not supported yet. - if (::strcasecmp(tmp, "sdk") == 0) - return 'SDK_'; - */ - return defv; -} - - - -DiskImage::DiskImage(const char *name, bool readOnly) : - _file(NULL) -{ - _file = new MappedFile(name, readOnly); -} - -DiskImage::DiskImage(MappedFile *file) : - _file(file) -{ -} - -DiskImage::~DiskImage() -{ - delete _file; -} - -bool DiskImage::readOnly() -{ - #undef __METHOD__ - #define __METHOD__ "DiskImage::readOnly" - - if (_file) return _file->readOnly(); - - throw Exception(__METHOD__ ": File not set."); -} - -unsigned DiskImage::blocks() -{ - #undef __METHOD__ - #define __METHOD__ "DiskImage::blocks" - - if (_file) return _file->blocks(); - - throw Exception(__METHOD__ ": File not set."); -} - -void DiskImage::read(unsigned block, void *bp) -{ - #undef __METHOD__ - #define __METHOD__ "DiskImage::read" - - - if (_file) return _file->readBlock(block, bp); - - throw Exception(__METHOD__ ": File not set."); -} - -void DiskImage::write(unsigned block, const void *bp) -{ - #undef __METHOD__ - #define __METHOD__ "DiskImage::write" - - if (_file) return _file->writeBlock(block, bp); - - throw Exception(__METHOD__ ": File not set."); -} - - - -void DiskImage::sync() -{ - #undef __METHOD__ - #define __METHOD__ "DiskImage::sync" - - if (_file) return _file->sync(); - - throw Exception(__METHOD__ ": File not set."); -} - - - -AbstractBlockCache *DiskImage::createBlockCache() -{ - if (_file->encoding() == MappedFile::ProDOSOrder) - return new MappedBlockCache(_file->imageData(), _file->blocks()); - - return BlockDevice::createBlockCache(); -} - - -ProDOSOrderDiskImage::ProDOSOrderDiskImage(const char *name, bool readOnly) : - DiskImage(name, readOnly) -{ - Validate(file()); -} - -ProDOSOrderDiskImage::ProDOSOrderDiskImage(MappedFile *file) : - DiskImage(file) -{ -} - -ProDOSOrderDiskImage *ProDOSOrderDiskImage::Create(const char *name, size_t blocks) -{ - MappedFile *file = new MappedFile(name, blocks * 512); - file->setBlocks(blocks); - return new ProDOSOrderDiskImage(file); -} - -ProDOSOrderDiskImage *ProDOSOrderDiskImage::Open(MappedFile *file) -{ - Validate(file); - return new ProDOSOrderDiskImage(file); -} - -void ProDOSOrderDiskImage::Validate(MappedFile *f) -{ - #undef __METHOD__ - #define __METHOD__ "ProDOSOrderDiskImage::Validate" - - if (!f) throw Exception(__METHOD__ ": File not set."); - - size_t size = f->fileSize(); - - if (size % 512) - throw Exception(__METHOD__ ": Invalid file format."); - - f->reset(); - f->setBlocks(size / 512); -} - -DOSOrderDiskImage::DOSOrderDiskImage(const char *name, bool readOnly) : - DiskImage(name, readOnly) -{ - Validate(file()); -} - -DOSOrderDiskImage::DOSOrderDiskImage(MappedFile *file) : - DiskImage(file) -{ -} - -DOSOrderDiskImage *DOSOrderDiskImage::Create(const char *name, size_t blocks) -{ - MappedFile *file = new MappedFile(name, blocks * 512); - file->setEncoding(MappedFile::DOSOrder); - file->setBlocks(blocks); - return new DOSOrderDiskImage(file); -} - -DOSOrderDiskImage *DOSOrderDiskImage::Open(MappedFile *file) -{ - Validate(file); - return new DOSOrderDiskImage(file); -} - -void DOSOrderDiskImage::Validate(MappedFile *f) -{ - #undef __METHOD__ - #define __METHOD__ "DOSOrderDiskImage::Validate" - - if (!f) throw Exception(__METHOD__ ": File not set."); - - size_t size = f->fileSize(); - - if (size % 512) - throw Exception(__METHOD__ ": Invalid file format."); - - f->reset(); - f->setEncoding(MappedFile::DOSOrder); - f->setBlocks(size / 512); -} diff --git a/Device/BlockDevice.h b/Device/BlockDevice.h index 7d8b262..17f6369 100644 --- a/Device/BlockDevice.h +++ b/Device/BlockDevice.h @@ -10,10 +10,7 @@ namespace Device { -class MappedFile; -class AbstractBlockCache; - - +class BlockCache; class BlockDevice { public: @@ -26,9 +23,6 @@ public: virtual void write(unsigned block, const void *bp) = 0; virtual void write(TrackSector ts, const void *bp); - // direct access to mapped memory (not always possible). - virtual void *read(unsigned block); - virtual void *read(TrackSector ts); virtual unsigned blocks() = 0; @@ -43,77 +37,15 @@ public: void zeroBlock(unsigned block); - AbstractBlockCache *blockCache(); - protected: BlockDevice(); - virtual AbstractBlockCache *createBlockCache(); - -private: - AbstractBlockCache *_cache; + + friend BlockCache; + virtual BlockCache *createBlockCache(); }; -class DiskImage : public BlockDevice { -public: - - static unsigned ImageType(const char *type, unsigned defv = 0); - - virtual ~DiskImage(); - - virtual void read(unsigned block, void *bp); - virtual void write(unsigned block, const void *bp); - virtual void sync(); - - virtual bool readOnly(); - virtual unsigned blocks(); - -protected: - - virtual AbstractBlockCache *createBlockCache(); - - DiskImage(MappedFile * = 0); - DiskImage(const char *name, bool readOnly); - - MappedFile *file() { return _file; } - void setFile(MappedFile *); - -private: - MappedFile *_file; -}; - - -class ProDOSOrderDiskImage : public DiskImage { -public: - - ProDOSOrderDiskImage(const char *name, bool readOnly); - - static ProDOSOrderDiskImage *Create(const char *name, size_t blocks); - static ProDOSOrderDiskImage *Open(MappedFile *); - -private: - ProDOSOrderDiskImage(MappedFile *); - static void Validate(MappedFile *); -}; - -class DOSOrderDiskImage : public DiskImage { -public: - - DOSOrderDiskImage(const char *name, bool readOnly); - - static DOSOrderDiskImage *Create(const char *name, size_t blocks); - static DOSOrderDiskImage *Open(MappedFile *); - -private: - DOSOrderDiskImage(MappedFile *); - static void Validate(MappedFile *); -}; - - - - - } #endif \ No newline at end of file diff --git a/Device/DiskImage.cpp b/Device/DiskImage.cpp new file mode 100644 index 0000000..7237c8f --- /dev/null +++ b/Device/DiskImage.cpp @@ -0,0 +1,226 @@ + +#include +#include +#include + +#include +#include +#include + + +#include +#include + +#include + + +using namespace Device; + +using ProFUSE::Exception; +using ProFUSE::POSIXException; + + +unsigned DiskImage::ImageType(const char *type, unsigned defv) +{ + const char *tmp; + + if (type == 0 || *type == 0) return defv; + + // type could be a filename, in which case we check the extension. + tmp = std::strrchr(type, '.'); + if (tmp) type = tmp + 1; + if (*type == 0) return defv; + + + if (::strcasecmp(type, "2mg") == 0) + return '2IMG'; + if (::strcasecmp(type, "2img") == 0) + return '2IMG'; + + if (::strcasecmp(type, "dc42") == 0) + return 'DC42'; + + if (::strcasecmp(type, "po") == 0) + return 'PO__'; + if (::strcasecmp(type, "dmg") == 0) + return 'PO__'; + + if (::strcasecmp(type, "dsk") == 0) + return 'DO__'; + if (::strcasecmp(type, "do") == 0) + return 'DO__'; + + if (::strcasecmp(type, "davex") == 0) + return 'DVX_'; + + /* + // not supported yet. + if (::strcasecmp(tmp, "sdk") == 0) + return 'SDK_'; + */ + return defv; +} + + + +DiskImage::DiskImage(const char *name, bool readOnly) : + _file(NULL) +{ + _file = new MappedFile(name, readOnly); +} + +DiskImage::DiskImage(MappedFile *file) : + _file(file) +{ +} + +DiskImage::~DiskImage() +{ + delete _file; +} + +bool DiskImage::readOnly() +{ + #undef __METHOD__ + #define __METHOD__ "DiskImage::readOnly" + + if (_file) return _file->readOnly(); + + throw Exception(__METHOD__ ": File not set."); +} + +unsigned DiskImage::blocks() +{ + #undef __METHOD__ + #define __METHOD__ "DiskImage::blocks" + + if (_file) return _file->blocks(); + + throw Exception(__METHOD__ ": File not set."); +} + +void DiskImage::read(unsigned block, void *bp) +{ + #undef __METHOD__ + #define __METHOD__ "DiskImage::read" + + + if (_file) return _file->readBlock(block, bp); + + throw Exception(__METHOD__ ": File not set."); +} + +void DiskImage::write(unsigned block, const void *bp) +{ + #undef __METHOD__ + #define __METHOD__ "DiskImage::write" + + if (_file) return _file->writeBlock(block, bp); + + throw Exception(__METHOD__ ": File not set."); +} + + + +void DiskImage::sync() +{ + #undef __METHOD__ + #define __METHOD__ "DiskImage::sync" + + if (_file) return _file->sync(); + + throw Exception(__METHOD__ ": File not set."); +} + + + +AbstractBlockCache *DiskImage::createBlockCache() +{ + if (_file->encoding() == MappedFile::ProDOSOrder) + return new MappedBlockCache(_file->imageData(), _file->blocks()); + + return BlockDevice::createBlockCache(); +} + + +ProDOSOrderDiskImage::ProDOSOrderDiskImage(const char *name, bool readOnly) : + DiskImage(name, readOnly) +{ + Validate(file()); +} + +ProDOSOrderDiskImage::ProDOSOrderDiskImage(MappedFile *file) : + DiskImage(file) +{ +} + +ProDOSOrderDiskImage *ProDOSOrderDiskImage::Create(const char *name, size_t blocks) +{ + MappedFile *file = new MappedFile(name, blocks * 512); + file->setBlocks(blocks); + return new ProDOSOrderDiskImage(file); +} + +ProDOSOrderDiskImage *ProDOSOrderDiskImage::Open(MappedFile *file) +{ + Validate(file); + return new ProDOSOrderDiskImage(file); +} + +void ProDOSOrderDiskImage::Validate(MappedFile *f) +{ + #undef __METHOD__ + #define __METHOD__ "ProDOSOrderDiskImage::Validate" + + if (!f) throw Exception(__METHOD__ ": File not set."); + + size_t size = f->fileSize(); + + if (size % 512) + throw Exception(__METHOD__ ": Invalid file format."); + + f->reset(); + f->setBlocks(size / 512); +} + +DOSOrderDiskImage::DOSOrderDiskImage(const char *name, bool readOnly) : + DiskImage(name, readOnly) +{ + Validate(file()); +} + +DOSOrderDiskImage::DOSOrderDiskImage(MappedFile *file) : + DiskImage(file) +{ +} + +DOSOrderDiskImage *DOSOrderDiskImage::Create(const char *name, size_t blocks) +{ + MappedFile *file = new MappedFile(name, blocks * 512); + file->setEncoding(MappedFile::DOSOrder); + file->setBlocks(blocks); + return new DOSOrderDiskImage(file); +} + +DOSOrderDiskImage *DOSOrderDiskImage::Open(MappedFile *file) +{ + Validate(file); + return new DOSOrderDiskImage(file); +} + +void DOSOrderDiskImage::Validate(MappedFile *f) +{ + #undef __METHOD__ + #define __METHOD__ "DOSOrderDiskImage::Validate" + + if (!f) throw Exception(__METHOD__ ": File not set."); + + size_t size = f->fileSize(); + + if (size % 512) + throw Exception(__METHOD__ ": Invalid file format."); + + f->reset(); + f->setEncoding(MappedFile::DOSOrder); + f->setBlocks(size / 512); +} diff --git a/Device/DiskImage.h b/Device/DiskImage.h new file mode 100644 index 0000000..ca93af7 --- /dev/null +++ b/Device/DiskImage.h @@ -0,0 +1,92 @@ +#ifndef __DISKIMAGE_H__ +#define __DISKIMAGE_H__ + +#include +#include + +#include + +#include + +#include + +namespace Device { + + +class DiskImage : public BlockDevice { +public: + + static unsigned ImageType(const char *type, unsigned defv = 0); + + virtual ~DiskImage(); + + virtual void read(unsigned block, void *bp); + virtual void write(unsigned block, const void *bp); + virtual void sync(); + + virtual bool readOnly(); + virtual unsigned blocks(); + +protected: + + + DiskImage(MappedFile * = 0); + DiskImage(const char *name, bool readOnly); + + void setOffset(uint32_t offset); + void *address() const { return _address; } + void *base() const { return _file.address(); } + + void readPO(unsigned block, void *bp); + void writePO(unsigned block, const void *bp); + + void readDO(unsigned block, void *bp); + void writeDO(unsigned block, const void *bp); + + // readNib + // writeNib + +private: + + MappedFile _file; + void *_address; + uint32_t _offset; + + bool _readOnly; + unsigned _blocks; +}; + + +class ProDOSOrderDiskImage : public DiskImage { +public: + + ProDOSOrderDiskImage(const char *name, bool readOnly); + + static ProDOSOrderDiskImage *Create(const char *name, size_t blocks); + static ProDOSOrderDiskImage *Open(MappedFile *); + +private: + ProDOSOrderDiskImage(MappedFile *); + static void Validate(MappedFile *); +}; + +class DOSOrderDiskImage : public DiskImage { +public: + + DOSOrderDiskImage(const char *name, bool readOnly); + + static DOSOrderDiskImage *Create(const char *name, size_t blocks); + static DOSOrderDiskImage *Open(MappedFile *); + +private: + DOSOrderDiskImage(MappedFile *); + static void Validate(MappedFile *); +}; + + + + + +} + +#endif \ No newline at end of file From 7b729f088fad5d3ff9b50d250c285ebb98351ebc Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 23 Mar 2010 04:15:12 +0000 Subject: [PATCH 091/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@211 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/DiskImage.cpp | 182 ++++++++++++++++++++++++++++++++----------- 1 file changed, 136 insertions(+), 46 deletions(-) diff --git a/Device/DiskImage.cpp b/Device/DiskImage.cpp index 7237c8f..e960070 100644 --- a/Device/DiskImage.cpp +++ b/Device/DiskImage.cpp @@ -20,6 +20,102 @@ using ProFUSE::Exception; using ProFUSE::POSIXException; +class Reader { + public: + virtual ~Reader(); + virtual void readBlock(unsigned block, void *bp) = 0; + virtual void writeBlock(unsigned block, const void *bp) = 0; +}; + +class POReader : public Reader { + public: + POReader(void *address); + void readBlock(unsigned block, void *bp); + void writeBlock(unsigned block, const void *bp); + private: + uint8_t *_address; +}; + +class DOReader : public Reader { + public + DOReader(void *address); + void readBlock(unsigned block, void *bp); + void writeBlock(unsigned block, const void *bp); + private: + uint8_t *_address; + + static unsigned Map[]; +} + +Reader::~Reader() +{ +} + + + +unsigned DOReader::Map[] = { + 0x00, 0x0e, 0x0d, 0x0c, + 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x0f +}; + +POReader::POReader(void *address) +{ + _address = (uint8_t *)address; +} + +void POReader::readBlock(unsigned block, void *bp) +{ + std::memcpy(bp, _address + block * 512, 512); +} + +void POReader::writeBlock(unsigned block, const void *bp) +{ + std::memcpy(_address + block * 512, bp, 512); +} + + +DOReader::DOReader(void *address) +{ + _address = (uint8_t *)address; +} + +void DOReader::readBlock(unsigned block, void *bp) +{ + + unsigned track = (block & ~0x07) << 9; + unsigned sector = (block & 0x07) << 1; + + for (unsigned i = 0; i < 2; ++i) + { + size_t offset = track | (Map[sector+i] << 8); + + std::memcpy(bp, _address + offset, 256); + + bp = (uint8_t *)bp + 256; + } +} + +void DOReader::writeBlock(unsigned block, const void *bp) +{ + unsigned track = (block & ~0x07) << 9; + unsigned sector = (block & 0x07) << 1; + + for (unsigned i = 0; i < 2; ++i) + { + size_t offset = track | (DOSMap[sector+i] << 8); + + std::memcpy(_address + offset, bp, 256); + bp = (uint8_t *)bp + 256; + } +} + + + + + + unsigned DiskImage::ImageType(const char *type, unsigned defv) { const char *tmp; @@ -49,7 +145,9 @@ unsigned DiskImage::ImageType(const char *type, unsigned defv) return 'DO__'; if (::strcasecmp(type, "do") == 0) return 'DO__'; - + + if (::strcasecmp(type, "dvx") == 0) + return 'DVX_'; if (::strcasecmp(type, "davex") == 0) return 'DVX_'; @@ -64,14 +162,23 @@ unsigned DiskImage::ImageType(const char *type, unsigned defv) DiskImage::DiskImage(const char *name, bool readOnly) : - _file(NULL) + _file(name, readOnly) { - _file = new MappedFile(name, readOnly); + _offset = 0; + _blocks = 0; + _readOnly = readOnly; + _address = file.address(); + } -DiskImage::DiskImage(MappedFile *file) : - _file(file) +DiskImage::DiskImage(MappedFile *file, bool readOnly) { + _file.adopt(file); + + _offset = 0; + _blocks = 0; + _readOnly = readOnly; + _address = file.address(); } DiskImage::~DiskImage() @@ -81,65 +188,48 @@ DiskImage::~DiskImage() bool DiskImage::readOnly() { - #undef __METHOD__ - #define __METHOD__ "DiskImage::readOnly" - - if (_file) return _file->readOnly(); - - throw Exception(__METHOD__ ": File not set."); + return _readOnly; } unsigned DiskImage::blocks() { - #undef __METHOD__ - #define __METHOD__ "DiskImage::blocks" - - if (_file) return _file->blocks(); - - throw Exception(__METHOD__ ": File not set."); + return _blocks; } -void DiskImage::read(unsigned block, void *bp) -{ - #undef __METHOD__ - #define __METHOD__ "DiskImage::read" - - - if (_file) return _file->readBlock(block, bp); - - throw Exception(__METHOD__ ": File not set."); -} - -void DiskImage::write(unsigned block, const void *bp) -{ - #undef __METHOD__ - #define __METHOD__ "DiskImage::write" - - if (_file) return _file->writeBlock(block, bp); - - throw Exception(__METHOD__ ": File not set."); -} - - void DiskImage::sync() { #undef __METHOD__ #define __METHOD__ "DiskImage::sync" - if (_file) return _file->sync(); + if (_file) return _file.sync(); throw Exception(__METHOD__ ": File not set."); } - -AbstractBlockCache *DiskImage::createBlockCache() +void DiskImage::readPO(unsigned block, void *bp) { - if (_file->encoding() == MappedFile::ProDOSOrder) - return new MappedBlockCache(_file->imageData(), _file->blocks()); - - return BlockDevice::createBlockCache(); + #undef __METHOD__ + #define __METHOD__ "DiskImage::readPO" + + if (block >= _blocks) + throw Exception(__METHOD__ ": Invalid block."); + + std::memcpy(bp, (uint8_t *)_address + block * 512, 512); +} + + +void DiskImage::writePO(unsigned block, const void *bp) +{ + #undef __METHOD__ + #define __METHOD__ "DiskImage::writePO" + + if (block >= _blocks) + throw Exception(__METHOD__ ": Invalid block."); + + std::memcpy((uint8_t *)_address + block * 512, bp, 512); + } From 33f209690ebe1d76fa59d4d063e08f084bbabf34 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 1 Apr 2010 14:38:39 +0000 Subject: [PATCH 092/236] linux warnings git-svn-id: https://profuse.googlecode.com/svn/branches/v2@212 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/BlockCache.cpp | 2 ++ Cache/ConcreteBlockCache.cpp | 1 + Device/BlockDevice.h | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Cache/BlockCache.cpp b/Cache/BlockCache.cpp index 0467fa1..e450797 100644 --- a/Cache/BlockCache.cpp +++ b/Cache/BlockCache.cpp @@ -1,11 +1,13 @@ #include #include +#include #include #include #include + #include #include diff --git a/Cache/ConcreteBlockCache.cpp b/Cache/ConcreteBlockCache.cpp index eb6474b..cc24971 100644 --- a/Cache/ConcreteBlockCache.cpp +++ b/Cache/ConcreteBlockCache.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include diff --git a/Device/BlockDevice.h b/Device/BlockDevice.h index 17f6369..592bea2 100644 --- a/Device/BlockDevice.h +++ b/Device/BlockDevice.h @@ -40,7 +40,7 @@ public: protected: BlockDevice(); - friend BlockCache; + friend class BlockCache; virtual BlockCache *createBlockCache(); }; @@ -48,4 +48,4 @@ protected: } -#endif \ No newline at end of file +#endif From bcf6cd3890606e69781507f176ad57466910d72e Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 18 May 2010 02:58:26 +0000 Subject: [PATCH 093/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@214 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/Adaptor.cpp | 77 +++++++++++++ Device/Adaptor.h | 45 ++++++++ Device/DavexDiskImage.cpp | 26 ++--- Device/DavexDiskImage.h | 5 +- Device/DiskCopy42Image.cpp | 58 ++++++---- Device/DiskCopy42Image.h | 4 +- Device/DiskImage.cpp | 203 ++++++++++------------------------ Device/DiskImage.h | 35 +++--- Device/UniversalDiskImage.cpp | 32 ++++-- Device/UniversalDiskImage.h | 6 +- File/File.h | 7 +- File/MappedFile.cpp | 99 ++++++++++++++--- File/MappedFile.h | 15 ++- 13 files changed, 381 insertions(+), 231 deletions(-) create mode 100644 Device/Adaptor.cpp create mode 100644 Device/Adaptor.h diff --git a/Device/Adaptor.cpp b/Device/Adaptor.cpp new file mode 100644 index 0000000..9ffe284 --- /dev/null +++ b/Device/Adaptor.cpp @@ -0,0 +1,77 @@ + + + +#include +#include + +using namespace Device; + + +Adaptor::~Adaptor() +{ +} + + + +POAdaptor::POAdaptor(void *address) +{ + _address = (uint8_t *)address; +} + +void POAdaptor::readBlock(unsigned block, void *bp) +{ + std::memcpy(bp, _address + block * 512, 512); +} + +void POAdaptor::writeBlock(unsigned block, const void *bp) +{ + std::memcpy(_address + block * 512, bp, 512); +} + + +unsigned DOAdaptor::Map[] = { + 0x00, 0x0e, 0x0d, 0x0c, + 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x0f +}; + +DOAdaptor::DOAdaptor(void *address) +{ + _address = (uint8_t *)address; +} + +void DOAdaptor::readBlock(unsigned block, void *bp) +{ + + unsigned track = (block & ~0x07) << 9; + unsigned sector = (block & 0x07) << 1; + + for (unsigned i = 0; i < 2; ++i) + { + size_t offset = track | (Map[sector+i] << 8); + + std::memcpy(bp, _address + offset, 256); + + bp = (uint8_t *)bp + 256; + } +} + +void DOAdaptor::writeBlock(unsigned block, const void *bp) +{ + unsigned track = (block & ~0x07) << 9; + unsigned sector = (block & 0x07) << 1; + + for (unsigned i = 0; i < 2; ++i) + { + size_t offset = track | (Map[sector+i] << 8); + + std::memcpy(_address + offset, bp, 256); + bp = (uint8_t *)bp + 256; + } +} + + + + + diff --git a/Device/Adaptor.h b/Device/Adaptor.h new file mode 100644 index 0000000..0e945db --- /dev/null +++ b/Device/Adaptor.h @@ -0,0 +1,45 @@ +#ifndef __DEVICE_ADAPTOR_H__ +#define __DEVICE_ADAPTOR_H__ + +#include + +namespace Device { + + class Adaptor + { + public: + virtual ~Adaptor(); + virtual void readBlock(unsigned block, void *bp) = 0; + virtual void writeBlock(unsigned block, const void *bp) = 0; + }; + + + class POAdaptor : public Adaptor + { + public: + POAdaptor(void *address); + void readBlock(unsigned block, void *bp); + void writeBlock(unsigned block, const void *bp); + private: + uint8_t *_address; + }; + + class DOAdaptor : public Adaptor + { + public: + DOAdaptor(void *address); + void readBlock(unsigned block, void *bp); + void writeBlock(unsigned block, const void *bp); + private: + uint8_t *_address; + + static unsigned Map[]; + }; + + // TODO -- nibble adaptor. + + +} + + +#endif diff --git a/Device/DavexDiskImage.cpp b/Device/DavexDiskImage.cpp index 1e02e4b..3ac452b 100644 --- a/Device/DavexDiskImage.cpp +++ b/Device/DavexDiskImage.cpp @@ -8,7 +8,8 @@ #include #include -#include +#include +#include #include #include @@ -26,16 +27,21 @@ using ProFUSE::POSIXException; static const char *IdentityCheck = "\x60VSTORE [Davex]\x00"; +/* DavexDiskImage::DavexDiskImage(const char *name, bool readOnly) : DiskImage(name, readOnly) { Validate(file()); } +*/ // private, validation already performed. -DavexDiskImage::DavexDiskImage(MappedFile *f) : - DiskImage(f) +DavexDiskImage::DavexDiskImage(MappedFile *file) : + DiskImage(file) { + // 512-bytes header + setBlocks((file->length() / 512) - 1); + setAdaptor(new POAdaptor(512 + (uint8_t *)file->address())); } @@ -49,8 +55,8 @@ void DavexDiskImage::Validate(MappedFile *f) #undef __METHOD__ #define __METHOD__ "DavexDiskImage::Validate" - size_t size = f->fileSize(); - const void * data = f->fileData(); + size_t size = f->length(); + const void * data = f->address(); bool ok = false; unsigned blocks = (size / 512) - 1; @@ -80,10 +86,6 @@ void DavexDiskImage::Validate(MappedFile *f) if (!ok) throw Exception(__METHOD__ ": Invalid file format."); - - f->reset(); - f->setBlocks(blocks); - f->setOffset(512); } DavexDiskImage *DavexDiskImage::Open(MappedFile *file) @@ -111,7 +113,7 @@ DavexDiskImage *DavexDiskImage::Create(const char *name, size_t blocks, const ch MappedFile *file = new MappedFile(name, blocks * 512 + 512); - data = (uint8_t *)file->fileData(); + data = (uint8_t *)file->address(); header.writeBytes(IdentityCheck, 16); // file Format @@ -152,10 +154,8 @@ DavexDiskImage *DavexDiskImage::Create(const char *name, size_t blocks, const ch header.setOffset(512, true); - std::memcpy(file->fileData(), header.buffer(), 512); + std::memcpy(file->address(), header.buffer(), 512); file->sync(); - file->setOffset(512); - file->setBlocks(blocks); return new DavexDiskImage(file); } diff --git a/Device/DavexDiskImage.h b/Device/DavexDiskImage.h index 1f7122b..9246ada 100644 --- a/Device/DavexDiskImage.h +++ b/Device/DavexDiskImage.h @@ -4,6 +4,8 @@ #include #include +#include + namespace Device { @@ -12,7 +14,6 @@ namespace Device { class DavexDiskImage : public DiskImage { public: - DavexDiskImage(const char *, bool readOnly); virtual ~DavexDiskImage(); static DavexDiskImage *Create(const char *name, size_t blocks); @@ -22,6 +23,8 @@ public: private: + DavexDiskImage(const char *, bool readOnly); + DavexDiskImage(MappedFile *); static void Validate(MappedFile *); diff --git a/Device/DiskCopy42Image.cpp b/Device/DiskCopy42Image.cpp index a3b441c..967af2b 100644 --- a/Device/DiskCopy42Image.cpp +++ b/Device/DiskCopy42Image.cpp @@ -5,7 +5,6 @@ #include #include -#include #include #include @@ -17,32 +16,45 @@ using namespace BigEndian; using ProFUSE::Exception; using ProFUSE::POSIXException; + +enum { + oDataSize = 64, + oDataChecksum = 72, + oPrivate = 82, + oUserData = 84 +}; + DiskCopy42Image::DiskCopy42Image(MappedFile *f) : DiskImage(f), _changed(false) { + setAdaptor(new POAdaptor(oUserData + (uint8_t *)f->address())); + setBlocks(Read32(f->address(), oDataSize) / 512); } + +/* DiskCopy42Image::DiskCopy42Image(const char *name, bool readOnly) : DiskImage(name, readOnly), _changed(false) { Validate(file()); } +*/ DiskCopy42Image::~DiskCopy42Image() { if (_changed) { MappedFile *f = file(); - void *data = f->fileData(); if (f) { - uint32_t cs = Checksum(f->offset() + (uint8_t *)data, - f->blocks() * 512); + void *data = f->address(); + + uint32_t cs = Checksum(oUserData + (uint8_t *)data, Read32(data, oDataSize)); - Write32(data, 72, cs); + Write32(data, oDataChecksum, cs); f->sync(); } // TODO -- checksum @@ -100,12 +112,12 @@ DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks) DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks, const char *vname) { - MappedFile *file = new MappedFile(name, blocks * 512 + 84); - file->setOffset(84); - file->setBlocks(blocks); + MappedFile *file = new MappedFile(name, blocks * 512 + oUserData); + - uint8_t tmp[84]; - IOBuffer header(tmp, 84); + + uint8_t tmp[oUserData]; + IOBuffer header(tmp, oUserData); // name -- 64byte pstring. @@ -115,7 +127,7 @@ DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks, const header.writeBytes(vname, std::min(l, 63u)); //header.resize(64); - header.setOffset(64, true); + header.setOffset(oDataSize, true); // data size -- number of bytes header.write32(blocks * 512); @@ -152,7 +164,7 @@ DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks, const // private header.write16(0x100); - std::memcpy(file->fileData(), header.buffer(), 84); + std::memcpy(file->address(), header.buffer(), oUserData); file->sync(); return new DiskCopy42Image(file); @@ -164,29 +176,29 @@ void DiskCopy42Image::Validate(MappedFile *file) #define __METHOD__ "DiskCopy42Image::Validate" size_t bytes = 0; - size_t size = file->fileSize(); - const void *data = file->fileData(); + size_t size = file->length(); + const void *data = file->address(); bool ok = false; uint32_t checksum = 0; do { - if (size < 84) break; + if (size < oUserData) break; // name must be < 64 if (Read8(data, 0) > 63) break; - if (Read32(data, 82) != 0x100) + if (Read32(data, oPrivate) != 0x100) break; // bytes, not blocks. - bytes = Read32(data, 64); + bytes = Read32(data, oDataSize); if (bytes % 512) break; - if (size < 84 + bytes) break; + if (size < oUserData + bytes) break; // todo -- checksum. - checksum = Read32(data, 72); + checksum = Read32(data, oDataChecksum); ok = true; } while (false); @@ -194,15 +206,13 @@ void DiskCopy42Image::Validate(MappedFile *file) if (!ok) throw Exception(__METHOD__ ": Invalid file format."); - uint32_t cs = Checksum(64 + (uint8_t *)data, bytes); + uint32_t cs = Checksum(oUserData + (uint8_t *)data, bytes); if (cs != checksum) { - fprintf(stderr, "Warning: checksum invalid.\n"); + fprintf(stderr, __METHOD__ ": Warning: checksum invalid.\n"); } - file->reset(); - file->setOffset(64); - file->setBlocks(bytes / 512); + } void DiskCopy42Image::write(unsigned block, const void *bp) diff --git a/Device/DiskCopy42Image.h b/Device/DiskCopy42Image.h index 8511c16..bdc7b0a 100644 --- a/Device/DiskCopy42Image.h +++ b/Device/DiskCopy42Image.h @@ -2,6 +2,7 @@ #define __DISKCOPY42IMAGE_H__ #include +#include #include @@ -9,7 +10,6 @@ namespace Device { class DiskCopy42Image : public DiskImage { public: - DiskCopy42Image(const char *name, bool readOnly); virtual ~DiskCopy42Image(); static DiskCopy42Image *Create(const char *name, size_t blocks); @@ -24,6 +24,8 @@ public: private: + DiskCopy42Image(const char *name, bool readOnly); + DiskCopy42Image(MappedFile *); static void Validate(MappedFile *); bool _changed; diff --git a/Device/DiskImage.cpp b/Device/DiskImage.cpp index e960070..8a2a032 100644 --- a/Device/DiskImage.cpp +++ b/Device/DiskImage.cpp @@ -9,7 +9,7 @@ #include -#include +#include #include @@ -20,96 +20,6 @@ using ProFUSE::Exception; using ProFUSE::POSIXException; -class Reader { - public: - virtual ~Reader(); - virtual void readBlock(unsigned block, void *bp) = 0; - virtual void writeBlock(unsigned block, const void *bp) = 0; -}; - -class POReader : public Reader { - public: - POReader(void *address); - void readBlock(unsigned block, void *bp); - void writeBlock(unsigned block, const void *bp); - private: - uint8_t *_address; -}; - -class DOReader : public Reader { - public - DOReader(void *address); - void readBlock(unsigned block, void *bp); - void writeBlock(unsigned block, const void *bp); - private: - uint8_t *_address; - - static unsigned Map[]; -} - -Reader::~Reader() -{ -} - - - -unsigned DOReader::Map[] = { - 0x00, 0x0e, 0x0d, 0x0c, - 0x0b, 0x0a, 0x09, 0x08, - 0x07, 0x06, 0x05, 0x04, - 0x03, 0x02, 0x01, 0x0f -}; - -POReader::POReader(void *address) -{ - _address = (uint8_t *)address; -} - -void POReader::readBlock(unsigned block, void *bp) -{ - std::memcpy(bp, _address + block * 512, 512); -} - -void POReader::writeBlock(unsigned block, const void *bp) -{ - std::memcpy(_address + block * 512, bp, 512); -} - - -DOReader::DOReader(void *address) -{ - _address = (uint8_t *)address; -} - -void DOReader::readBlock(unsigned block, void *bp) -{ - - unsigned track = (block & ~0x07) << 9; - unsigned sector = (block & 0x07) << 1; - - for (unsigned i = 0; i < 2; ++i) - { - size_t offset = track | (Map[sector+i] << 8); - - std::memcpy(bp, _address + offset, 256); - - bp = (uint8_t *)bp + 256; - } -} - -void DOReader::writeBlock(unsigned block, const void *bp) -{ - unsigned track = (block & ~0x07) << 9; - unsigned sector = (block & 0x07) << 1; - - for (unsigned i = 0; i < 2; ++i) - { - size_t offset = track | (DOSMap[sector+i] << 8); - - std::memcpy(_address + offset, bp, 256); - bp = (uint8_t *)bp + 256; - } -} @@ -161,29 +71,30 @@ unsigned DiskImage::ImageType(const char *type, unsigned defv) -DiskImage::DiskImage(const char *name, bool readOnly) : - _file(name, readOnly) +DiskImage::DiskImage(const char *name, bool readOnly) { - _offset = 0; + File fd(name, readOnly ? O_RDONLY : O_RDWR); + MappedFile mf(fd, readOnly); + _file.adopt(mf); + _blocks = 0; _readOnly = readOnly; - _address = file.address(); - + _adaptor = NULL; } -DiskImage::DiskImage(MappedFile *file, bool readOnly) -{ - _file.adopt(file); - _offset = 0; +DiskImage::DiskImage(MappedFile *file) +{ + _file.adopt(*file); + _blocks = 0; - _readOnly = readOnly; - _address = file.address(); + _readOnly = file->readOnly(); + _adaptor = NULL; } DiskImage::~DiskImage() { - delete _file; + delete _adaptor; } bool DiskImage::readOnly() @@ -197,57 +108,65 @@ unsigned DiskImage::blocks() } +void DiskImage::setAdaptor(Adaptor *adaptor) +{ + delete _adaptor; + _adaptor = adaptor; +} + + +void DiskImage::read(unsigned block, void *bp) +{ +#undef __METHOD__ +#define __METHOD__ "DiskImage::read" + + if (block >= _blocks) + throw Exception(__METHOD__ ": Invalid block."); + + _adaptor->readBlock(block, bp); +} + +void DiskImage::write(unsigned block, const void *bp) +{ +#undef __METHOD__ +#define __METHOD__ "DiskImage::write" + + if (block >= _blocks) + throw Exception(__METHOD__ ": Invalid block."); + + _adaptor->writeBlock(block, bp); +} + void DiskImage::sync() { #undef __METHOD__ #define __METHOD__ "DiskImage::sync" - if (_file) return _file.sync(); + if (_file.isValid()) return _file.sync(); throw Exception(__METHOD__ ": File not set."); } -void DiskImage::readPO(unsigned block, void *bp) -{ - #undef __METHOD__ - #define __METHOD__ "DiskImage::readPO" - - if (block >= _blocks) - throw Exception(__METHOD__ ": Invalid block."); - - std::memcpy(bp, (uint8_t *)_address + block * 512, 512); -} - - -void DiskImage::writePO(unsigned block, const void *bp) -{ - #undef __METHOD__ - #define __METHOD__ "DiskImage::writePO" - - if (block >= _blocks) - throw Exception(__METHOD__ ": Invalid block."); - - std::memcpy((uint8_t *)_address + block * 512, bp, 512); - -} - +/* ProDOSOrderDiskImage::ProDOSOrderDiskImage(const char *name, bool readOnly) : DiskImage(name, readOnly) { Validate(file()); } - +*/ + ProDOSOrderDiskImage::ProDOSOrderDiskImage(MappedFile *file) : DiskImage(file) { + setBlocks(file->length() / 512); + setAdaptor(new POAdaptor(file->address())); } ProDOSOrderDiskImage *ProDOSOrderDiskImage::Create(const char *name, size_t blocks) { - MappedFile *file = new MappedFile(name, blocks * 512); - file->setBlocks(blocks); + MappedFile *file = MappedFile::Create(name, blocks * 512); return new ProDOSOrderDiskImage(file); } @@ -262,33 +181,34 @@ void ProDOSOrderDiskImage::Validate(MappedFile *f) #undef __METHOD__ #define __METHOD__ "ProDOSOrderDiskImage::Validate" - if (!f) throw Exception(__METHOD__ ": File not set."); + if (!f || !f->isValid()) throw Exception(__METHOD__ ": File not set."); - size_t size = f->fileSize(); + size_t size = f->length(); if (size % 512) throw Exception(__METHOD__ ": Invalid file format."); - f->reset(); - f->setBlocks(size / 512); } +/* DOSOrderDiskImage::DOSOrderDiskImage(const char *name, bool readOnly) : DiskImage(name, readOnly) { Validate(file()); } +*/ DOSOrderDiskImage::DOSOrderDiskImage(MappedFile *file) : DiskImage(file) { + setBlocks(file->length() / 512); + setAdaptor(new DOAdaptor(file->address())); } + DOSOrderDiskImage *DOSOrderDiskImage::Create(const char *name, size_t blocks) { - MappedFile *file = new MappedFile(name, blocks * 512); - file->setEncoding(MappedFile::DOSOrder); - file->setBlocks(blocks); + MappedFile *file = MappedFile::Create(name, blocks * 512); return new DOSOrderDiskImage(file); } @@ -303,14 +223,11 @@ void DOSOrderDiskImage::Validate(MappedFile *f) #undef __METHOD__ #define __METHOD__ "DOSOrderDiskImage::Validate" - if (!f) throw Exception(__METHOD__ ": File not set."); + if (!f || !f->isValid()) throw Exception(__METHOD__ ": File not set."); - size_t size = f->fileSize(); + size_t size = f->length(); if (size % 512) throw Exception(__METHOD__ ": Invalid file format."); - f->reset(); - f->setEncoding(MappedFile::DOSOrder); - f->setBlocks(size / 512); } diff --git a/Device/DiskImage.h b/Device/DiskImage.h index ca93af7..6234c74 100644 --- a/Device/DiskImage.h +++ b/Device/DiskImage.h @@ -8,11 +8,13 @@ #include -#include +#include + +#include namespace Device { - + class DiskImage : public BlockDevice { public: @@ -30,27 +32,21 @@ public: protected: - DiskImage(MappedFile * = 0); + DiskImage(MappedFile *file = 0); DiskImage(const char *name, bool readOnly); - void setOffset(uint32_t offset); - void *address() const { return _address; } - void *base() const { return _file.address(); } - - void readPO(unsigned block, void *bp); - void writePO(unsigned block, const void *bp); - void readDO(unsigned block, void *bp); - void writeDO(unsigned block, const void *bp); - - // readNib - // writeNib + void setBlocks(unsigned blocks) { _blocks = blocks; } + + void setAdaptor(Adaptor *); + + void *address() const { return _file.address(); } + MappedFile *file() { return &_file; } private: MappedFile _file; - void *_address; - uint32_t _offset; + Adaptor *_adaptor; bool _readOnly; unsigned _blocks; @@ -60,12 +56,14 @@ private: class ProDOSOrderDiskImage : public DiskImage { public: - ProDOSOrderDiskImage(const char *name, bool readOnly); static ProDOSOrderDiskImage *Create(const char *name, size_t blocks); static ProDOSOrderDiskImage *Open(MappedFile *); private: + ProDOSOrderDiskImage(const char *name, bool readOnly); + + ProDOSOrderDiskImage(MappedFile *); static void Validate(MappedFile *); }; @@ -73,12 +71,13 @@ private: class DOSOrderDiskImage : public DiskImage { public: - DOSOrderDiskImage(const char *name, bool readOnly); static DOSOrderDiskImage *Create(const char *name, size_t blocks); static DOSOrderDiskImage *Open(MappedFile *); private: + DOSOrderDiskImage(const char *name, bool readOnly); + DOSOrderDiskImage(MappedFile *); static void Validate(MappedFile *); }; diff --git a/Device/UniversalDiskImage.cpp b/Device/UniversalDiskImage.cpp index f624960..c9487ab 100644 --- a/Device/UniversalDiskImage.cpp +++ b/Device/UniversalDiskImage.cpp @@ -1,5 +1,4 @@ #include -#include #include #include @@ -12,6 +11,7 @@ using namespace LittleEndian; using ProFUSE::Exception; using ProFUSE::POSIXException; +/* UniversalDiskImage::UniversalDiskImage(const char *name, bool readOnly) : DiskImage(name, readOnly) { @@ -21,11 +21,26 @@ UniversalDiskImage::UniversalDiskImage(const char *name, bool readOnly) : // flags. bit 31 = locked. _flags = Read32(data, 0x10); } +*/ UniversalDiskImage::UniversalDiskImage(MappedFile *file) : DiskImage(file) { - _flags = 0; + unsigned blocks; + unsigned offset; + + uint8_t * data = (uint8_t *)file->address(); + + + + _flags = Read32(data, 0x10); + + offset = Read32(data, 0x20); + blocks = Read32(data, 0x14); + + setBlocks(blocks); + // TODO -- DO, Nibble support. + setAdaptor(new POAdaptor(offset + data)); } UniversalDiskImage *UniversalDiskImage::Create(const char *name, size_t blocks) @@ -65,11 +80,9 @@ UniversalDiskImage *UniversalDiskImage::Create(const char *name, size_t blocks) // comment offset, creator, reserved -- 0. header.setOffset(64, true); - std::memcpy(file->fileData(), header.buffer(), 64); + std::memcpy(file->address(), header.buffer(), 64); - file->setOffset(64); - file->setBlocks(blocks); return new UniversalDiskImage(file); } @@ -90,8 +103,8 @@ void UniversalDiskImage::Validate(MappedFile *file) #undef __METHOD__ #define __METHOD__ "UniversalDiskImage::Validate" - const void *data = file->fileData(); - size_t size = file->fileSize(); + const void *data = file->address(); + size_t size = file->length(); bool ok = false; unsigned blocks = 0; unsigned offset = 0; @@ -103,6 +116,7 @@ void UniversalDiskImage::Validate(MappedFile *file) if (std::memcmp(data, "2IMG", 4)) break; // only prodos supported, for now... + // TODO -- Dos Order, Nibble support. if (Read32(data, 0x0c) != 1) break; offset = Read32(data, 0x20); @@ -119,9 +133,7 @@ void UniversalDiskImage::Validate(MappedFile *file) if (!ok) throw Exception(__METHOD__ ": Invalid file format."); - file->reset(); - file->setOffset(offset); - file->setBlocks(blocks); + } diff --git a/Device/UniversalDiskImage.h b/Device/UniversalDiskImage.h index 875105b..42f7cfe 100644 --- a/Device/UniversalDiskImage.h +++ b/Device/UniversalDiskImage.h @@ -3,13 +3,14 @@ #include +#include + #include namespace Device { class UniversalDiskImage : public DiskImage { public: - UniversalDiskImage(const char *name, bool readOnly); static UniversalDiskImage *Create(const char *name, size_t blocks); static UniversalDiskImage *Open(MappedFile *); @@ -17,6 +18,9 @@ public: virtual bool readOnly(); private: + + UniversalDiskImage(const char *name, bool readOnly); + UniversalDiskImage(MappedFile *); static void Validate(MappedFile *); diff --git a/File/File.h b/File/File.h index 56763c5..58609c5 100644 --- a/File/File.h +++ b/File/File.h @@ -15,8 +15,13 @@ class File { File(const char *name, int flags); ~File(); + bool isValid() const + { + return _fd >= 0; + } + int fd() const { return _fd; } - + void close(); void adopt(File &f); diff --git a/File/MappedFile.cpp b/File/MappedFile.cpp index a1f79f2..8f005a5 100644 --- a/File/MappedFile.cpp +++ b/File/MappedFile.cpp @@ -13,47 +13,83 @@ MappedFile::MappedFile() { _length = -1; _address = MAP_FAILED; + _readOnly = true; } MappedFile::MappedFile(MappedFile &mf) { _address = mf._address; _length = mf._length; + _readOnly = mf._readOnly; mf._address = MAP_FAILED; mf._length = -1; + mf._readOnly = true; } -MappedFile::MappedFile(File f, bool readOnly) +MappedFile::MappedFile(const File &f, bool readOnly, size_t size) { - #undef __METHOD__ - #define __METHOD__ "MappedFile::MappedFile" + _length = -1; + _address = MAP_FAILED; + _readOnly = readOnly; + + init(f, readOnly, size); +} + +MappedFile::MappedFile(const char *name, bool readOnly) +{ + File f(name, readOnly); + + _length = -1; + _address = MAP_FAILED; + _readOnly = readOnly; + + init(f, readOnly, -1); + +} + + + +MappedFile::~MappedFile() +{ + close(); +} + + + +void MappedFile::init(const File &f, bool readOnly, size_t size) +{ +#undef __METHOD__ +#define __METHOD__ "MappedFile::init" + struct stat st; // close enough if (f.fd() < 0) throw POSIXException( __METHOD__, EBADF); - - - if (::fstat(f.fd(), &st) != 0) - throw POSIXException(__METHOD__ ": fstat", errno); - if (!S_ISREG(st.st_mode)) - throw POSIXException(__METHOD__, ENODEV); + + if (size <= 0) + { + if (::fstat(f.fd(), &st) != 0) + throw POSIXException(__METHOD__ ": fstat", errno); - _length = st.st_size; + if (!S_ISREG(st.st_mode)) + throw POSIXException(__METHOD__, ENODEV); + + size = st.st_size; + } + + _length = size; _address = ::mmap(0, _length, - readOnly ? PROT_READ : PROT_READ | PROT_WRITE, - MAP_FILE | MAP_SHARED, f.fd(), 0); - + readOnly ? PROT_READ : PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED, f.fd(), 0); + if (_address == MAP_FAILED) throw POSIXException(__METHOD__ ": mmap", errno); -} - -MappedFile::~MappedFile() -{ - close(); + + _readOnly = readOnly; } @@ -70,6 +106,7 @@ void MappedFile::close() _address = MAP_FAILED; _length = -1; + _readOnly = true; if (::munmap(address, length) != 0) throw POSIXException(__METHOD__ ": munmap", errno); @@ -93,13 +130,39 @@ void MappedFile::adopt(MappedFile &mf) close(); _address = mf._address; _length = mf._length; + _readOnly = mf._readOnly; mf._address = MAP_FAILED; mf._length = -1; + mf._readOnly = true; } void MappedFile::swap(MappedFile &mf) { std::swap(_address, mf._address); std::swap(_length, mf._length); + std::swap(_readOnly, mf._readOnly); +} + + +static MappedFile *Create(const char *name, size_t size) +{ +#undef __METHOD__ +#define __METHOD__ "MappedFile::Create" + + File fd(::open(name, O_CREAT | O_TRUNC | O_RDWR, 0644)); + + if (!fd.isValid()) + { + throw POSIXException(__METHOD__ ": Unable to create file.", errno); + } + + // TODO -- is ftruncate portable? + if (::ftruncate(fd.fd(), size) < 0) + { + // TODO -- unlink? + throw POSIXException(__METHOD__ ": Unable to truncate file.", errno); + } + + return new MappedFile(fd, false, size); } \ No newline at end of file diff --git a/File/MappedFile.h b/File/MappedFile.h index bc8911c..3655d55 100644 --- a/File/MappedFile.h +++ b/File/MappedFile.h @@ -10,16 +10,26 @@ class MappedFile { public: MappedFile(); - MappedFile(File f, bool readOnly); MappedFile(MappedFile&); + MappedFile(const File &f, bool readOnly, size_t size = -1); + MappedFile(const char *name, bool readOnly); ~MappedFile(); + + static MappedFile *Create(const char *name, size_t size); + + bool isValid() const + { + return _address != MAP_FAILED; + } + void sync(); void close(); void *address() const { return _address; } size_t length() const { return _length; } + bool readOnly() const { return _readOnly; } void swap(MappedFile &); void adopt(MappedFile &); @@ -28,8 +38,11 @@ class MappedFile { MappedFile& operator=(MappedFile &); + void init(const File &f, bool readOnly, size_t size); + void *_address; size_t _length; + bool _readOnly; }; From 56ff80afcc94fb9d796d2d0cc0e8ee2c8348660a Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 18 May 2010 03:10:35 +0000 Subject: [PATCH 094/236] deleting dead code git-svn-id: https://profuse.googlecode.com/svn/branches/v2@215 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/MappedFile.cpp | 253 ------------------------------------------ Device/MappedFile.h | 70 ------------ 2 files changed, 323 deletions(-) delete mode 100644 Device/MappedFile.cpp delete mode 100644 Device/MappedFile.h diff --git a/Device/MappedFile.cpp b/Device/MappedFile.cpp deleted file mode 100644 index c0029da..0000000 --- a/Device/MappedFile.cpp +++ /dev/null @@ -1,253 +0,0 @@ -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include - -using namespace Device; -using ProFUSE::POSIXException; -using ProFUSE::Exception; - - -MappedFile::MappedFile(const char *name, bool readOnly) -{ - #undef __METHOD__ - #define __METHOD__ "MappedFile::MappedFile" - - - // if unable to open as read/write, open as read-only. - - ProFUSE::auto_fd fd; - - if (!readOnly) - { - fd.reset(::open(name, O_RDWR)); - } - if (fd < 0) - { - fd.reset(::open(name, O_RDONLY)); - readOnly = true; - } - - if (fd < 0) - { - throw POSIXException(__METHOD__ ": Unable to open file.", errno); - } - // init may throw; auto_fd guarantees the file will be closed if that happens. - init(fd, readOnly); - fd.release(); -} - -// does NOT close fd on failure. -MappedFile::MappedFile(int fd, bool readOnly) -{ - init(fd, readOnly); -} - -MappedFile::MappedFile(const char *name, size_t size) -{ - #undef __METHOD__ - #define __METHOD__ "MappedFile::MappedFile" - - _fd = -1; - _map = MAP_FAILED; - _size = size; - _readOnly = false; - _encoding = ProDOSOrder; - - ProFUSE::auto_fd fd(::open(name, O_CREAT | O_TRUNC | O_RDWR, 0644)); - - if (fd < 0) - throw POSIXException(__METHOD__ ": Unable to create file.", errno); - - // TODO -- is ftruncate portable? - if (::ftruncate(fd, _size) < 0) - { - throw POSIXException(__METHOD__ ": Unable to truncate file.", errno); - } - - //_map = ::mmap(NULL, _size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, _fd, 0); - - ProFUSE::auto_map map( - NULL, - _size, - PROT_READ | PROT_WRITE, - MAP_FILE | MAP_SHARED, - fd, - 0 - ); - - if (map == MAP_FAILED) throw POSIXException(__METHOD__ ": Unable to map file.", errno); - - _fd = fd.release(); - _map = map.release(); -} - -MappedFile::~MappedFile() -{ - if (_map != MAP_FAILED) ::munmap(_map, _size); - if (_fd >= 0) ::close(_fd); -} - -// does NOT close f on exception. -void MappedFile::init(int f, bool readOnly) -{ - #undef __METHOD__ - #define __METHOD__ "MappedFile::init" - - - _fd = -1; - _map = MAP_FAILED; - _offset = 0; - _blocks = 0; - _size = 0; - _readOnly = readOnly; - _encoding = ProDOSOrder; - _size = ::lseek(f, 0, SEEK_END); - - if (_size < 0) - throw POSIXException(__METHOD__ ": Unable to determine file size.", errno); - -/* - _map = ::mmap(NULL, _size, readOnly ? PROT_READ : PROT_READ | PROT_WRITE, - MAP_FILE | MAP_SHARED, fd, 0); -*/ - ::lseek(f, 0, SEEK_SET); - - - ProFUSE::auto_map map( - NULL, - _size, - readOnly ? PROT_READ : PROT_READ | PROT_WRITE, - MAP_FILE | MAP_SHARED, //readOnly ? MAP_FILE : MAP_FILE | MAP_SHARED, - f, - 0 - ); - - /* - _map = ::mmap(NULL, _size, readOnly ? PROT_READ : PROT_READ | PROT_WRITE, - MAP_FILE | MAP_SHARED, f, 0); - */ - if (map == MAP_FAILED) throw POSIXException(__METHOD__ ": Unable to map file.", errno); - - _fd = f; - _map = map.release(); -} - - -const unsigned MappedFile::DOSMap[] = { - 0x00, 0x0e, 0x0d, 0x0c, - 0x0b, 0x0a, 0x09, 0x08, - 0x07, 0x06, 0x05, 0x04, - 0x03, 0x02, 0x01, 0x0f -}; - - -void MappedFile::readBlock(unsigned block, void *bp) -{ - #undef __METHOD__ - #define __METHOD__ "MappedFile::readBlock" - - - if (block >= _blocks) throw Exception(__METHOD__ ": Invalid block number."); - if (bp == 0) throw Exception(__METHOD__ ": Invalid address."); - - - switch(_encoding) - { - case ProDOSOrder: - { - size_t address = block * 512; - std::memcpy(bp, (uint8_t *)_map + _offset + address, 512); - } - break; - - case DOSOrder: - { - unsigned track = (block & ~0x07) << 9; - unsigned sector = (block & 0x07) << 1; - - for (unsigned i = 0; i < 2; ++i) - { - size_t address = track | (DOSMap[sector+i] << 8); - - std::memcpy(bp, (uint8_t *)_map + _offset + address, 256); - - bp = (uint8_t *)bp + 256; - } - } - break; - - default: - throw Exception(__METHOD__ ": Unsupported Encoding."); - } - -} - -void MappedFile::writeBlock(unsigned block, const void *bp) -{ - #undef __METHOD__ - #define __METHOD__ "MappedFile::writeBlock" - - if (block > _blocks) throw Exception(__METHOD__ ": Invalid block number."); - - if (_readOnly) throw Exception(__METHOD__ ": File is readonly."); - - - switch(_encoding) - { - case ProDOSOrder: - { - size_t address = block * 512; - std::memcpy((uint8_t *)_map + _offset + address , bp, 512); - } - break; - - case DOSOrder: - { - unsigned track = (block & ~0x07) << 9; - unsigned sector = (block & 0x07) << 1; - - for (unsigned i = 0; i < 2; ++i) - { - size_t address = track | (DOSMap[sector+i] << 8); - - std::memcpy((uint8_t *)_map + _offset + address, bp, 256); - bp = (uint8_t *)bp + 256; - } - } - break; - - default: - throw Exception(__METHOD__ ": Unsupported Encoding."); - } - -} - -void MappedFile::sync() -{ - #undef __METHOD__ - #define __METHOD__ "MappedFile::sync" - - if (_readOnly) return; - - if (::msync(_map, _size, MS_SYNC) < 0) - throw POSIXException(__METHOD__ ": msync error.", errno); -} - -void MappedFile::reset() -{ - _offset = 0; - _blocks = 0; - _encoding = ProDOSOrder; -} - - - diff --git a/Device/MappedFile.h b/Device/MappedFile.h deleted file mode 100644 index 5f10984..0000000 --- a/Device/MappedFile.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef __MAPPED_FILE__ -#define __MAPPED_FILE__ - - -#include -#include - -namespace Device { - - -class MappedFile { -public: - - enum Encoding { - ProDOSOrder = 0, - DOSOrder, - Nibblized62, - Nibblized53 - }; - - MappedFile(const char *name, bool ReadOnly); - MappedFile(int fd, bool readOnly); - MappedFile(const char *name, size_t size); - - ~MappedFile(); - - void readBlock(unsigned block, void *bp); - void writeBlock(unsigned block, const void *bp); - - void sync(); - - void reset(); - - Encoding encoding() const { return _encoding; } - void setEncoding(Encoding e) { _encoding = e; } - - unsigned offset() const { return _offset; } - void setOffset(unsigned o) { _offset = o; } - - unsigned blocks() const { return _blocks; } - void setBlocks(unsigned b) { _blocks = b; } - - bool readOnly() const { return _readOnly; } - size_t fileSize() const { return _size; } - void *fileData() const { return _map; } - void *imageData() const { return _offset + (uint8_t *)_map; } - - -private: - - - MappedFile& operator=(const MappedFile& other); - - void init(int fd, bool readOnly); - - static const unsigned DOSMap[]; - - int _fd; - void *_map; - - size_t _size; - bool _readOnly; - - Encoding _encoding; - unsigned _offset; - unsigned _blocks; - -}; -} -#endif \ No newline at end of file From f13263d5ad475df7e0b18a8c5afd56bcb2706421 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 18 May 2010 03:30:45 +0000 Subject: [PATCH 095/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@216 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/BlockDevice.cpp | 25 +---- Device/BlockDevice.h | 4 - Device/DeviceReader.cpp | 204 ---------------------------------------- Device/DeviceReader.h | 109 --------------------- 4 files changed, 1 insertion(+), 341 deletions(-) delete mode 100644 Device/DeviceReader.cpp delete mode 100644 Device/DeviceReader.h diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index 43345ed..a9a12ba 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -9,8 +9,7 @@ #include -#include -#include + #include @@ -38,19 +37,7 @@ void BlockDevice::zeroBlock(unsigned block) write(block, bp); } -AbstractBlockCache *BlockDevice::blockCache() -{ - if (!_cache) - { - _cache = createBlockCache(); - } - return _cache; -} -AbstractBlockCache *BlockDevice::createBlockCache() -{ - return new BlockCache(this); -} bool BlockDevice::mapped() { @@ -67,13 +54,3 @@ void BlockDevice::sync(TrackSector ts) sync(); } -void *BlockDevice::read(unsigned block) -{ - return NULL; -} - -void *BlockDevice::read(TrackSector ts) -{ - return NULL; -} - diff --git a/Device/BlockDevice.h b/Device/BlockDevice.h index 592bea2..97cd438 100644 --- a/Device/BlockDevice.h +++ b/Device/BlockDevice.h @@ -10,8 +10,6 @@ namespace Device { -class BlockCache; - class BlockDevice { public: @@ -40,8 +38,6 @@ public: protected: BlockDevice(); - friend class BlockCache; - virtual BlockCache *createBlockCache(); }; diff --git a/Device/DeviceReader.cpp b/Device/DeviceReader.cpp deleted file mode 100644 index fceb664..0000000 --- a/Device/DeviceReader.cpp +++ /dev/null @@ -1,204 +0,0 @@ - - -#include - -using namespace Device; - -DeviceReader::~DeviceReader() -{ -} - -void *DeviceReader::read(unsigned block) -{ - return NULL; -} - -void DeviceReader::read(TrackSector ts) -{ - return NULL; -} - -void DeviceReader::mapped() -{ - return false; -} - -#pragma mark - -#pragma mark ProDOS Order - -void ProDOSOrderDeviceReader::read(unsigned block, void *bp) -{ - std::memcpy(bp, read(block), 512); -} - -void ProDOSOrderDeviceReader::read(TrackSector ts, void *bp) -{ - std::memcpy(bp, read(ts), 256); -} - -void *ProDOSOrderDeviceReader::read(unsigned block) -{ - if (block > _blocks) - { - throw ProFUSE::Exception("Invalid block."); - } - return block * 512 + (uint8_t *)_data; -} - - -void *ProDOSOrderDeviceReader::read(TrackSector ts) -{ - unsigned block = (ts.track * 16 + ts.sector) / 2; - - if (block > _blocks) - { - throw ProFUSE::Exception("Invalid track/sector."); - } - - return (ts.track * 16 + ts.sector) * 256 + (uint8_t *)_data; -} - - -void ProDOSOrderDeviceReader::write(unsigned block, const void *bp) -{ - std::memcpy(read(block), bp, 512); -} - -void ProDOSOrderDeviceReader::write(TrackSector ts, const void *bp) -{ - std::memcpy(read(ts), bp, 256); -} - - -#pragma mark - -#pragma mark DOS Order - -const unsigned DOSMap[] = { - 0x00, 0x0e, 0x0d, 0x0c, - 0x0b, 0x0a, 0x09, 0x08, - 0x07, 0x06, 0x05, 0x04, - 0x03, 0x02, 0x01, 0x0f -}; - -void *DOSOrderDeviceReader::read(TrackSector ts) -{ - if (ts.track > _tracks || ts.sector > 16) - { - throw ProFUSE::Exception("Invalid track/sector."); - } - - return (ts.track * 16 + ts.sector) * 256 + (uint8_t *)_data; -} - - -void DOSOrderDeviceReader::read(unsigned block, void *bp) -{ - TrackSector ts(block >> 3, 0); - unsigned sector = (block & 0x07) << 1; - - for (unsigned i = 0; i < 2; ++i) - { - ts.sector = DOSMap[sector]; - std::memcpy(bp, read(ts), 256); - bp = 256 + (uint8_t *)bp; - ++sector; - } -} - - -void DOSOrderDeviceReader::read(TrackSector ts, void *bp) -{ - std::memcpy(bp, read(ts), 256); -} - - -void DOSOrderDeviceReader::write(unsigned block, const void *bp) -{ - TrackSector ts(block >> 3, 0); - unsigned sector = (block & 0x07) << 1; - - for (unsigned i = 0; i < 2; ++i) - { - ts.sector = DOSMap[sector]; - std::memcpy(read(ts), bp, 256); - bp = 256 + (const uint8_t *)bp; - ++sector; - } -} - -void DOSOrderDeviceReader::write(TrackSector ts, const void *bp) -{ - std::memcpy(read(ts), bp, 256); -} - - -#pragma mark - -#pragma mark FileDeviceReader - -FileDeviceReader::FileDeviceReader(int fd, unsigned blocks, bool readOnly) -{ - _fd = fd; - _readOnly = readOnly; - _blocks = blocks; -} - -bool FileDeviceReader::readOnly() -{ - return _readOnly; -} - -void FileDeviceReader::write(unsigned block, const void *bp) -{ - - off_t offset = block * 512; - - size_t ok = ::pwrite(_fd, bp, 512, offset); - - if (ok != 512) - throw ok < 0 - ? POSIXException(__METHOD__ ": Error writing block.", errno) - : Exception(__METHOD__ ": Error writing block."); -} - - -void FileDeviceReader::write(TrackSector ts, const void *bp) -{ - off_t offset = (ts.track * 16 + ts.sector) * 256; - size_t ok = ::pwrite(_fd, bp, 256, offset); - - if (ok != 256) - throw ok < 0 - ? POSIXException(__METHOD__ ": Error writing block.", errno) - : Exception(__METHOD__ ": Error writing block."); -} - - - - - - - - -void FileDeviceReader::read(unsigned block, void *bp) -{ - - off_t offset = block * 512; - - size_t ok = ::pread(_fd, bp, 512, offset); - - if (ok != 512) - throw ok < 0 - ? POSIXException(__METHOD__ ": Error reading block.", errno) - : Exception(__METHOD__ ": Error reading block."); -} - -void FileDeviceReader::read(TrackSector ts, void *bp) -{ - off_t offset = (ts.track * 16 + ts.sector) * 256; - size_t ok = ::pread(_fd, bp, 256, offset); - - if (ok != 256) - throw ok < 0 - ? POSIXException(__METHOD__ ": Error reading block.", errno) - : Exception(__METHOD__ ": Error reading block."); -} diff --git a/Device/DeviceReader.h b/Device/DeviceReader.h deleted file mode 100644 index e2e8c71..0000000 --- a/Device/DeviceReader.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef __DEVICEREADER_H__ -#define __DEVICEREADER_H__ - -#include - -namespace Device { - - -class DeviceReader { - public: - - virtual ~DeviceReader(); - - virtual void read(unsigned block, void *bp) = 0; - virtual void read(TrackSector ts, void *bp) = 0; - - virtual void write(unsigned block, const void *bp) = 0; - virtual void write(TrackSector ts, const void *bp) = 0; - - // direct access -- not always available. - - virtual void *read(unsigned block); - virtual void *read(TrackSector ts); - - virtual bool readOnly() = 0; - virtual bool mapped(); - -}; - -class FileDeviceReader : public DeviceReader { - - // does not assume ownership of fd. - FileDeviceReader(int fd, unsigned blocks, bool readOnly); - //virtual ~FileDeviceReader(); - -public: - - virtual bool readOnly(); - - - virtual void read(unsigned block, void *bp); - virtual void read(TrackSector ts, void *bp); - - virtual void write(unsigned block, const void *bp); - virtual void write(TrackSector ts, const void *bp); - - private: - - int _fd; - unsigned _blocks; - bool _readOnly; -} - -class MappedFileDeviceReader : public DeviceReader { - - protected: - - MappedFileDeviceReader(MappedFile *f, unsigned offset); - - void *_data; - - private: - MappedFile *_file -}; - -class ProDOSOrderDeviceReader : public MappedFileDeviceReader { - public: - - virtual void read(unsigned block, void *bp); - virtual void read(TrackSector ts, void *bp); - - virtual void write(unsigned block, const void *bp); - virtual void write(TrackSector ts, const void *bp); - - virtual void *read(unsigned block); - virtual void *read(TrackSector ts); - - private: - unsigned blocks; -}; - -// 16 sectors only. -class DOSOrderDeviceReader : public MappedFileDeviceReader { - public: - - virtual void read(unsigned block, void *bp); - virtual void read(TrackSector ts, void *bp); - - virtual void write(unsigned block, const void *bp); - virtual void write(TrackSector ts, const void *bp); - - virtual void *read(TrackSector ts); - - private: - unsigned _tracks; -}; - - - -class NibbleDeviceReader : public MappedFileDeviceReader { - - private: - - std::vector _map; -}; - -} - -#endif \ No newline at end of file From 03c0e3420185f30bc04984b6dc4ec9852ab99abb Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 18 May 2010 18:38:22 +0000 Subject: [PATCH 096/236] add read support git-svn-id: https://profuse.googlecode.com/svn/branches/v2@217 aa027e90-d47c-11dd-86d7-074df07e0730 --- Endian/IOBuffer.t.cpp | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/Endian/IOBuffer.t.cpp b/Endian/IOBuffer.t.cpp index 54de16a..31bea42 100644 --- a/Endian/IOBuffer.t.cpp +++ b/Endian/IOBuffer.t.cpp @@ -30,9 +30,9 @@ _offset += 4; } - void writeBytes(const void *value, unsigned count) + void writeBytes(const void *src, unsigned count) { - std::memcpy(_offset + (uint8_t *)_buffer, value, count); + std::memcpy(_offset + (uint8_t *)_buffer, src, count); _offset += count; } @@ -43,6 +43,42 @@ _offset += count; } + + uint8_t read8() + { + uint8_t x = Read8(_buffer, _offset); + _offset += 1; + return x; + } + + uint16_t read16() + { + uint16_t x = Read16(_buffer, _offset); + _offset += 2; + return x; + } + + uint32_t read24() + { + uint32_t x = Read24(_buffer, _offset); + _offset += 3; + return x; + } + + uint32_t read32() + { + uint32_t x = Read32(_buffer, _offset); + _offset += 4; + return x; + } + + void readBytes(void *dest, unsigned count) + { + std::memcpy(dest, _offset + (uint8_t *)_buffer, count); + _offset += count; + } + + unsigned offset() const { return _offset; } void setOffset(unsigned offset) { _offset = offset; } From f606f8c0f538dd9d5c5deba52ecbcdf9428ca2a4 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 18 May 2010 18:39:40 +0000 Subject: [PATCH 097/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@218 aa027e90-d47c-11dd-86d7-074df07e0730 --- Endian/{IOBuffer.t.cpp => IOBuffer.cpp.h} | 0 Endian/IOBuffer.h | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename Endian/{IOBuffer.t.cpp => IOBuffer.cpp.h} (100%) diff --git a/Endian/IOBuffer.t.cpp b/Endian/IOBuffer.cpp.h similarity index 100% rename from Endian/IOBuffer.t.cpp rename to Endian/IOBuffer.cpp.h diff --git a/Endian/IOBuffer.h b/Endian/IOBuffer.h index 19d1e0b..bae6d11 100644 --- a/Endian/IOBuffer.h +++ b/Endian/IOBuffer.h @@ -5,11 +5,11 @@ #include namespace LittleEndian { -#include "IOBuffer.t.cpp" +#include "IOBuffer.cpp.h" } namespace BigEndian { -#include "IOBuffer.t.cpp" +#include "IOBuffer.cpp.h" } #endif \ No newline at end of file From be7a7bafc13b535212b7f786062602341e315e28 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 18 May 2010 19:59:00 +0000 Subject: [PATCH 098/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@219 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/BlockCache.cpp | 8 ++++++++ Cache/BlockCache.h | 4 +++- Cache/ConcreteBlockCache.h | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Cache/BlockCache.cpp b/Cache/BlockCache.cpp index e450797..4b51fc1 100644 --- a/Cache/BlockCache.cpp +++ b/Cache/BlockCache.cpp @@ -50,3 +50,11 @@ void BlockCache::read(unsigned block, void *bp) std::memcpy(bp, address, 512); release(block, false); } + + +BlockCache *BlockCache::Create(BlockDevice *device, unsigned size = 16) +{ + if (!device) return NULL; + + return device->createBlockCache(size); +} diff --git a/Cache/BlockCache.h b/Cache/BlockCache.h index d613cf0..acaa46e 100644 --- a/Cache/BlockCache.h +++ b/Cache/BlockCache.h @@ -38,7 +38,9 @@ public: void release(unsigned block) { release(block, 0); } void release(unsigned block, bool dirty) - { release(block, dirty ? kBlockDirty : 0); } + { + release(block, dirty ? kBlockDirty : 0); + } protected: BlockCache(BlockDevice *device); diff --git a/Cache/ConcreteBlockCache.h b/Cache/ConcreteBlockCache.h index 0665b08..2560b8e 100644 --- a/Cache/ConcreteBlockCache.h +++ b/Cache/ConcreteBlockCache.h @@ -13,7 +13,7 @@ public: virtual ~ConcreteBlockCache(); virtual void sync(); - virtual void write(unsigned block, const void *vp) = 0; + virtual void write(unsigned block, const void *vp); virtual void *acquire(unsigned block); From 629efe6da57cb577d83e997b5095be15bdaeffb5 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 18 May 2010 19:59:18 +0000 Subject: [PATCH 099/236] block cache support. git-svn-id: https://profuse.googlecode.com/svn/branches/v2@220 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/Adaptor.h | 8 ++++---- Device/BlockDevice.cpp | 7 ++++++- Device/BlockDevice.h | 5 +++++ Device/DavexDiskImage.cpp | 8 ++++++++ Device/DavexDiskImage.h | 1 + Device/DiskCopy42Image.cpp | 14 ++++++++++++++ Device/DiskCopy42Image.h | 4 +++- Device/DiskImage.cpp | 11 +++++++++++ Device/DiskImage.h | 3 +++ Device/UniversalDiskImage.cpp | 36 +++++++++++++++++++++++++++-------- Device/UniversalDiskImage.h | 9 +++++++++ 11 files changed, 92 insertions(+), 14 deletions(-) diff --git a/Device/Adaptor.h b/Device/Adaptor.h index 0e945db..311077f 100644 --- a/Device/Adaptor.h +++ b/Device/Adaptor.h @@ -18,8 +18,8 @@ namespace Device { { public: POAdaptor(void *address); - void readBlock(unsigned block, void *bp); - void writeBlock(unsigned block, const void *bp); + virtual void readBlock(unsigned block, void *bp); + virtual void writeBlock(unsigned block, const void *bp); private: uint8_t *_address; }; @@ -28,8 +28,8 @@ namespace Device { { public: DOAdaptor(void *address); - void readBlock(unsigned block, void *bp); - void writeBlock(unsigned block, const void *bp); + virtual void readBlock(unsigned block, void *bp); + virtual void writeBlock(unsigned block, const void *bp); private: uint8_t *_address; diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index a9a12ba..c17ddf3 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -9,7 +9,7 @@ #include - +#include #include @@ -54,3 +54,8 @@ void BlockDevice::sync(TrackSector ts) sync(); } + +BlockCache *BlockDevice::createBlockCache(unsigned size) +{ + return new ConcreteBlockCache(this, size); +} diff --git a/Device/BlockDevice.h b/Device/BlockDevice.h index 97cd438..d5e13dd 100644 --- a/Device/BlockDevice.h +++ b/Device/BlockDevice.h @@ -8,6 +8,8 @@ #include +#include + namespace Device { class BlockDevice { @@ -15,6 +17,9 @@ public: virtual ~BlockDevice(); + virtual BlockCache *createBlockCache(unsigned size); + + virtual void read(unsigned block, void *bp) = 0; virtual void read(TrackSector ts, void *bp); diff --git a/Device/DavexDiskImage.cpp b/Device/DavexDiskImage.cpp index 3ac452b..30fafc4 100644 --- a/Device/DavexDiskImage.cpp +++ b/Device/DavexDiskImage.cpp @@ -14,6 +14,7 @@ #include #include +#include using namespace Device; using namespace LittleEndian; @@ -159,3 +160,10 @@ DavexDiskImage *DavexDiskImage::Create(const char *name, size_t blocks, const ch return new DavexDiskImage(file); } + + +BlockCache *DavexDiskImage::createBlockCache(unsigned size) +{ + return new MappedBlockCache(this, 512 + (uint8_t *)address()); + +} diff --git a/Device/DavexDiskImage.h b/Device/DavexDiskImage.h index 9246ada..9977dee 100644 --- a/Device/DavexDiskImage.h +++ b/Device/DavexDiskImage.h @@ -20,6 +20,7 @@ public: static DavexDiskImage *Create(const char *name, size_t blocks, const char *vname); static DavexDiskImage *Open(MappedFile *); + virtual BlockCache *createBlockCache(unsigned size); private: diff --git a/Device/DiskCopy42Image.cpp b/Device/DiskCopy42Image.cpp index 967af2b..1a7d0cd 100644 --- a/Device/DiskCopy42Image.cpp +++ b/Device/DiskCopy42Image.cpp @@ -9,6 +9,9 @@ #include #include +#include + + using namespace Device; using namespace BigEndian; @@ -17,6 +20,7 @@ using ProFUSE::Exception; using ProFUSE::POSIXException; + enum { oDataSize = 64, oDataChecksum = 72, @@ -219,4 +223,14 @@ void DiskCopy42Image::write(unsigned block, const void *bp) { DiskImage::write(block, bp); _changed = true; +} + + +BlockCache *DiskCopy42Image::createBlockCache(unsigned size) +{ + // if not readonly, mark changed so crc will be updated at close. + + if (!readOnly()) _changed = true; + + return new MappedBlockCache(this, address()); } \ No newline at end of file diff --git a/Device/DiskCopy42Image.h b/Device/DiskCopy42Image.h index bdc7b0a..ba14b9e 100644 --- a/Device/DiskCopy42Image.h +++ b/Device/DiskCopy42Image.h @@ -21,7 +21,9 @@ public: virtual void write(unsigned block, const void *bp); - + + virtual BlockCache *createBlockCache(unsigned size); + private: DiskCopy42Image(const char *name, bool readOnly); diff --git a/Device/DiskImage.cpp b/Device/DiskImage.cpp index 8a2a032..fc515a1 100644 --- a/Device/DiskImage.cpp +++ b/Device/DiskImage.cpp @@ -11,6 +11,8 @@ #include #include +#include + #include @@ -190,6 +192,15 @@ void ProDOSOrderDiskImage::Validate(MappedFile *f) } +BlockCache *ProDOSOrderDiskImage::createBlockCache(unsigned size) +{ + return new MappedBlockCache(this, address()); +} + +#pragma mark - +#pragma mark DOS Order Disk Image + + /* DOSOrderDiskImage::DOSOrderDiskImage(const char *name, bool readOnly) : DiskImage(name, readOnly) diff --git a/Device/DiskImage.h b/Device/DiskImage.h index 6234c74..de891d6 100644 --- a/Device/DiskImage.h +++ b/Device/DiskImage.h @@ -59,6 +59,9 @@ public: static ProDOSOrderDiskImage *Create(const char *name, size_t blocks); static ProDOSOrderDiskImage *Open(MappedFile *); + + + virtual BlockCache *createBlockCache(unsigned size); private: ProDOSOrderDiskImage(const char *name, bool readOnly); diff --git a/Device/UniversalDiskImage.cpp b/Device/UniversalDiskImage.cpp index c9487ab..c23267f 100644 --- a/Device/UniversalDiskImage.cpp +++ b/Device/UniversalDiskImage.cpp @@ -5,12 +5,17 @@ #include +#include +#include + using namespace Device; using namespace LittleEndian; using ProFUSE::Exception; using ProFUSE::POSIXException; + + /* UniversalDiskImage::UniversalDiskImage(const char *name, bool readOnly) : DiskImage(name, readOnly) @@ -26,21 +31,23 @@ UniversalDiskImage::UniversalDiskImage(const char *name, bool readOnly) : UniversalDiskImage::UniversalDiskImage(MappedFile *file) : DiskImage(file) { - unsigned blocks; - unsigned offset; uint8_t * data = (uint8_t *)file->address(); + + _format = Read32(data, 0x0c); _flags = Read32(data, 0x10); + _blocks = Read32(data, 0x14); - offset = Read32(data, 0x20); - blocks = Read32(data, 0x14); + _dataOffset = Read32(data, 0x18); + _dataLength = Read32(data, 0x1c); - setBlocks(blocks); + + setBlocks(_blocks); // TODO -- DO, Nibble support. - setAdaptor(new POAdaptor(offset + data)); + setAdaptor(new POAdaptor(_dataOffset + data)); } UniversalDiskImage *UniversalDiskImage::Create(const char *name, size_t blocks) @@ -119,8 +126,8 @@ void UniversalDiskImage::Validate(MappedFile *file) // TODO -- Dos Order, Nibble support. if (Read32(data, 0x0c) != 1) break; - offset = Read32(data, 0x20); blocks = Read32(data, 0x14); + offset = Read32(data, 0x18); // file size == blocks * 512 if (Read32(data, 0x1c) != blocks * 512) break; @@ -140,4 +147,17 @@ void UniversalDiskImage::Validate(MappedFile *file) bool UniversalDiskImage::readOnly() { return (_flags & 0x8000000) || DiskImage::readOnly(); -} \ No newline at end of file +} + + +BlockCache *UniversalDiskImage::createBlockCache(unsigned size) +{ + if (_format == 1) + { + return new MappedBlockCache(this, _dataOffset + (uint8_t *)address()); + } + + return DiskImage::createBlockCache(size); +} + + diff --git a/Device/UniversalDiskImage.h b/Device/UniversalDiskImage.h index 42f7cfe..b70d0ed 100644 --- a/Device/UniversalDiskImage.h +++ b/Device/UniversalDiskImage.h @@ -12,11 +12,16 @@ namespace Device { class UniversalDiskImage : public DiskImage { public: + + static UniversalDiskImage *Create(const char *name, size_t blocks); static UniversalDiskImage *Open(MappedFile *); virtual bool readOnly(); + BlockCache *createBlockCache(unsigned size); + + private: UniversalDiskImage(const char *name, bool readOnly); @@ -24,7 +29,11 @@ private: UniversalDiskImage(MappedFile *); static void Validate(MappedFile *); + uint32_t _format; uint32_t _flags; + uint32_t _blocks; + uint32_t _dataOffset; + uint32_t _dataLength; }; } From 699a6e02fb8e0b2f4c9ceebcc059428472e5dc98 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 18 May 2010 20:16:57 +0000 Subject: [PATCH 100/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@221 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/Entry.cpp | 1 - Pascal/FileEntry.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/Pascal/Entry.cpp b/Pascal/Entry.cpp index b0b5e83..0b57e43 100644 --- a/Pascal/Entry.cpp +++ b/Pascal/Entry.cpp @@ -7,7 +7,6 @@ #include #include -#include #include diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index 8e367e4..f12cb72 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -13,7 +13,6 @@ #include #include -#include From 22afe5d128ca6369bc8f18959b032f9d2cf03b2b Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 18 May 2010 21:26:07 +0000 Subject: [PATCH 101/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@222 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/BlockCache.cpp | 4 ++-- Cache/BlockCache.h | 2 +- Device/BlockDevice.cpp | 4 +++- Device/BlockDevice.h | 2 +- Device/DavexDiskImage.cpp | 2 +- Device/DavexDiskImage.h | 2 +- Device/DiskCopy42Image.cpp | 2 +- Device/DiskCopy42Image.h | 2 +- Device/UniversalDiskImage.cpp | 4 ++-- Device/UniversalDiskImage.h | 2 +- Pascal/File.h | 4 ++-- Pascal/VolumeEntry.cpp | 25 ++++++++++++++----------- 12 files changed, 30 insertions(+), 25 deletions(-) diff --git a/Cache/BlockCache.cpp b/Cache/BlockCache.cpp index 4b51fc1..c56e5eb 100644 --- a/Cache/BlockCache.cpp +++ b/Cache/BlockCache.cpp @@ -52,9 +52,9 @@ void BlockCache::read(unsigned block, void *bp) } -BlockCache *BlockCache::Create(BlockDevice *device, unsigned size = 16) +BlockCache *BlockCache::Create(BlockDevice *device) { if (!device) return NULL; - return device->createBlockCache(size); + return device->createBlockCache(); } diff --git a/Cache/BlockCache.h b/Cache/BlockCache.h index acaa46e..75fabef 100644 --- a/Cache/BlockCache.h +++ b/Cache/BlockCache.h @@ -19,7 +19,7 @@ enum BlockReleaseFlags { class BlockCache { public: - BlockCache *Create(BlockDevice *device, unsigned size = 16); + static BlockCache *Create(BlockDevice *device); virtual ~BlockCache(); diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index c17ddf3..77cb671 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -55,7 +55,9 @@ void BlockDevice::sync(TrackSector ts) } -BlockCache *BlockDevice::createBlockCache(unsigned size) +BlockCache *BlockDevice::createBlockCache() { + unsigned b = blocks(); + unsigned size = std::max(16u, b / 16); return new ConcreteBlockCache(this, size); } diff --git a/Device/BlockDevice.h b/Device/BlockDevice.h index d5e13dd..6775da1 100644 --- a/Device/BlockDevice.h +++ b/Device/BlockDevice.h @@ -17,7 +17,7 @@ public: virtual ~BlockDevice(); - virtual BlockCache *createBlockCache(unsigned size); + virtual BlockCache *createBlockCache(); virtual void read(unsigned block, void *bp) = 0; diff --git a/Device/DavexDiskImage.cpp b/Device/DavexDiskImage.cpp index 30fafc4..f388567 100644 --- a/Device/DavexDiskImage.cpp +++ b/Device/DavexDiskImage.cpp @@ -162,7 +162,7 @@ DavexDiskImage *DavexDiskImage::Create(const char *name, size_t blocks, const ch } -BlockCache *DavexDiskImage::createBlockCache(unsigned size) +BlockCache *DavexDiskImage::createBlockCache() { return new MappedBlockCache(this, 512 + (uint8_t *)address()); diff --git a/Device/DavexDiskImage.h b/Device/DavexDiskImage.h index 9977dee..fa9a432 100644 --- a/Device/DavexDiskImage.h +++ b/Device/DavexDiskImage.h @@ -20,7 +20,7 @@ public: static DavexDiskImage *Create(const char *name, size_t blocks, const char *vname); static DavexDiskImage *Open(MappedFile *); - virtual BlockCache *createBlockCache(unsigned size); + virtual BlockCache *createBlockCache(); private: diff --git a/Device/DiskCopy42Image.cpp b/Device/DiskCopy42Image.cpp index 1a7d0cd..c8e22bb 100644 --- a/Device/DiskCopy42Image.cpp +++ b/Device/DiskCopy42Image.cpp @@ -226,7 +226,7 @@ void DiskCopy42Image::write(unsigned block, const void *bp) } -BlockCache *DiskCopy42Image::createBlockCache(unsigned size) +BlockCache *DiskCopy42Image::createBlockCache() { // if not readonly, mark changed so crc will be updated at close. diff --git a/Device/DiskCopy42Image.h b/Device/DiskCopy42Image.h index ba14b9e..2c43da8 100644 --- a/Device/DiskCopy42Image.h +++ b/Device/DiskCopy42Image.h @@ -22,7 +22,7 @@ public: virtual void write(unsigned block, const void *bp); - virtual BlockCache *createBlockCache(unsigned size); + virtual BlockCache *createBlockCache(); private: diff --git a/Device/UniversalDiskImage.cpp b/Device/UniversalDiskImage.cpp index c23267f..227f5f3 100644 --- a/Device/UniversalDiskImage.cpp +++ b/Device/UniversalDiskImage.cpp @@ -150,14 +150,14 @@ bool UniversalDiskImage::readOnly() } -BlockCache *UniversalDiskImage::createBlockCache(unsigned size) +BlockCache *UniversalDiskImage::createBlockCache() { if (_format == 1) { return new MappedBlockCache(this, _dataOffset + (uint8_t *)address()); } - return DiskImage::createBlockCache(size); + return DiskImage::createBlockCache(); } diff --git a/Device/UniversalDiskImage.h b/Device/UniversalDiskImage.h index b70d0ed..fbaccba 100644 --- a/Device/UniversalDiskImage.h +++ b/Device/UniversalDiskImage.h @@ -19,7 +19,7 @@ public: virtual bool readOnly(); - BlockCache *createBlockCache(unsigned size); + virtual BlockCache *createBlockCache(); private: diff --git a/Pascal/File.h b/Pascal/File.h index 8d34eca..39e408b 100644 --- a/Pascal/File.h +++ b/Pascal/File.h @@ -7,7 +7,7 @@ namespace Device { class BlockDevice; - class AbstractBlockCache; + class BlockCache; } namespace LittleEndian { @@ -125,7 +125,7 @@ private: unsigned _inodeGenerator; Device::BlockDevice *_device; - Device::AbstractBlockCache *_cache; + Device::BlockCache *_cache; }; diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index c666eef..c5924fe 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #pragma mark - #pragma mark VolumeEntry @@ -15,6 +15,8 @@ using namespace LittleEndian; using namespace Pascal; +using namespace Device; + unsigned VolumeEntry::ValidName(const char *cp) { // 7 chars max. Legal values: ascii, printable, @@ -69,7 +71,7 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device) _accessTime = 0; _lastBoot = Date::Today(); - _cache = device->blockCache(); + _cache = BlockCache::Create(device); _device = device; for (unsigned i = 2; i < 6; ++i) @@ -77,12 +79,12 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device) device->zeroBlock(i); } - void *vp = _cache->load(2); + void *vp = _cache->acquire(2); IOBuffer b(vp, 0x1a); writeDirectoryEntry(&b); - _cache->unload(2, true); + _cache->release(2, true); } @@ -96,7 +98,7 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device) // blocks. _device = device; - _cache = device->blockCache(); + _cache = BlockCache::Create(device); device->read(2, buffer.get()); @@ -160,8 +162,9 @@ VolumeEntry::~VolumeEntry() if (*iter) delete *iter; } - // _blockCache does not need deleting. - delete _device; + delete _cache; + // _device is deleted by _cache. + //delete _device; } @@ -194,20 +197,20 @@ FileEntry *VolumeEntry::fileAtIndex(unsigned i) const void *VolumeEntry::loadBlock(unsigned block) { - return _cache->load(block); + return _cache->acquire(block); } void VolumeEntry::unloadBlock(unsigned block, bool dirty) { - return _cache->unload(block, dirty); + return _cache->release(block, dirty); } void VolumeEntry::readBlock(unsigned block, void *buffer) { - _device->read(block, buffer); + _cache->read(block, buffer); } void VolumeEntry::writeBlock(unsigned block, void *buffer) { - _device->write(block, buffer); + _cache->write(block, buffer); } From 77fda944ae20b16c1f25c1872a1892aa34fee18c Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 19 May 2010 01:07:47 +0000 Subject: [PATCH 102/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@223 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/BlockCache.h | 2 +- Cache/ConcreteBlockCache.cpp | 19 +++++++++++++++++ Cache/MappedBlockCache.cpp | 9 ++++++++ Device/BlockDevice.cpp | 3 ++- Device/BlockDevice.h | 6 +++--- Device/DiskImage.cpp | 40 ++++++++++++++++++++++++++++++++++++ Device/DiskImage.h | 3 +++ File/MappedFile.cpp | 2 +- File/MappedFile.h | 1 + apfm.cpp | 28 ++++++++----------------- 10 files changed, 87 insertions(+), 26 deletions(-) diff --git a/Cache/BlockCache.h b/Cache/BlockCache.h index 75fabef..1ee6d40 100644 --- a/Cache/BlockCache.h +++ b/Cache/BlockCache.h @@ -14,7 +14,7 @@ enum BlockReleaseFlags { kBlockDirty = 1, kBlockCommitNow = 2, kBlockReuse = 3 -} BlockReleaseFlags; +}; class BlockCache { public: diff --git a/Cache/ConcreteBlockCache.cpp b/Cache/ConcreteBlockCache.cpp index cc24971..49eecec 100644 --- a/Cache/ConcreteBlockCache.cpp +++ b/Cache/ConcreteBlockCache.cpp @@ -203,6 +203,25 @@ unsigned ConcreteBlockCache::hashFunction(unsigned block) return block % HashTableSize; } + + + +ConcreteBlockCache::Entry *ConcreteBlockCache::findEntry(unsigned block) +{ + Entry *e; + unsigned hash = hashFunction(block); + + e = _hashTable[hash]; + + if (e) + { + while ((e) && (e->block != block)) e = e->nextHash; + } + + return e; +} + + /* * remove a block from the hashtable * and write to dick if dirty. diff --git a/Cache/MappedBlockCache.cpp b/Cache/MappedBlockCache.cpp index 95df640..74709be 100644 --- a/Cache/MappedBlockCache.cpp +++ b/Cache/MappedBlockCache.cpp @@ -59,6 +59,15 @@ void MappedBlockCache::release(unsigned block, int flags) if (flags & kBlockDirty) _dirty = true; } + + +void MappedBlockCache::write(unsigned block, const void *vp) +{ + _dirty = true; + std::memcpy(_data + block * 512, vp, 512); +} + + // sync everything. void MappedBlockCache::sync() { diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index 77cb671..8cb61af 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -49,11 +49,12 @@ void BlockDevice::sync(unsigned block) sync(); } +/* void BlockDevice::sync(TrackSector ts) { sync(); } - +*/ BlockCache *BlockDevice::createBlockCache() { diff --git a/Device/BlockDevice.h b/Device/BlockDevice.h index 6775da1..453958f 100644 --- a/Device/BlockDevice.h +++ b/Device/BlockDevice.h @@ -21,10 +21,10 @@ public: virtual void read(unsigned block, void *bp) = 0; - virtual void read(TrackSector ts, void *bp); + //virtual void read(TrackSector ts, void *bp) = 0 virtual void write(unsigned block, const void *bp) = 0; - virtual void write(TrackSector ts, const void *bp); + //virtual void write(TrackSector ts, const void *bp) = 0; virtual unsigned blocks() = 0; @@ -35,7 +35,7 @@ public: virtual void sync() = 0; virtual void sync(unsigned block); - virtual void sync(TrackSector ts); + //virtual void sync(TrackSector ts); void zeroBlock(unsigned block); diff --git a/Device/DiskImage.cpp b/Device/DiskImage.cpp index fc515a1..0bdd365 100644 --- a/Device/DiskImage.cpp +++ b/Device/DiskImage.cpp @@ -9,6 +9,11 @@ #include +#include +#include +#include + + #include #include @@ -71,6 +76,41 @@ unsigned DiskImage::ImageType(const char *type, unsigned defv) return defv; } +BlockDevice *DiskImage::Open(const char *name, bool readOnly, unsigned imageType) +{ + if (!imageType) imageType = ImageType(name, 'PO__'); + + // TODO -- if no image type, guess based on file size? + // TODO -- check for /dev/* ? + + MappedFile file(name, readOnly); + + + switch (imageType) + { + case '2IMG': + return UniversalDiskImage::Open(&file); + + case 'DC42': + return DiskCopy42Image::Open(&file); + + case 'DO__': + return DOSOrderDiskImage::Open(&file); + + case 'PO__': + return ProDOSOrderDiskImage::Open(&file); + + case 'DVX_': + return DavexDiskImage::Open(&file); + + } + + // throw an error? + return NULL; + +} + + DiskImage::DiskImage(const char *name, bool readOnly) diff --git a/Device/DiskImage.h b/Device/DiskImage.h index de891d6..2f1a909 100644 --- a/Device/DiskImage.h +++ b/Device/DiskImage.h @@ -20,6 +20,9 @@ public: static unsigned ImageType(const char *type, unsigned defv = 0); + + static BlockDevice *Open(const char *name, bool readOnly, unsigned imageType = 0); + virtual ~DiskImage(); virtual void read(unsigned block, void *bp); diff --git a/File/MappedFile.cpp b/File/MappedFile.cpp index 8f005a5..babaac5 100644 --- a/File/MappedFile.cpp +++ b/File/MappedFile.cpp @@ -145,7 +145,7 @@ void MappedFile::swap(MappedFile &mf) } -static MappedFile *Create(const char *name, size_t size) +MappedFile *MappedFile::Create(const char *name, size_t size) { #undef __METHOD__ #define __METHOD__ "MappedFile::Create" diff --git a/File/MappedFile.h b/File/MappedFile.h index 3655d55..014ef2c 100644 --- a/File/MappedFile.h +++ b/File/MappedFile.h @@ -5,6 +5,7 @@ #include +class File; class MappedFile { public: diff --git a/apfm.cpp b/apfm.cpp index 8e1c984..eb9d9f4 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -115,7 +115,7 @@ int action_ls(int argc, char **argv, Pascal::VolumeEntry *volume) std::fprintf(stdout, "%s:\n", volume->name()); - argv[0] = "afpm ls"; + //argv[0] = "afpm ls"; while ((ch = ::getopt(argc, argv, "l")) != -1) { @@ -179,7 +179,7 @@ int action_ls(int argc, char **argv, Pascal::VolumeEntry *volume) int action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume) { // cat file1, file2... - argv[0] = "afpm cat"; + //argv[0] = "afpm cat"; if (argc < 2) { @@ -318,28 +318,16 @@ int main(int argc, char **argv) const char *file = argv[0]; const char *action = argv[1]; - if (!fmt) fmt = Device::DiskImage::ImageType(optarg, 'PO__'); try { + + + device.reset( Device::DiskImage::Open(file, true, fmt) ); - switch(fmt) - { - case 'DO__': - device.reset( new Device::DOSOrderDiskImage(file, true) ); - break; - case 'PO__': - device.reset( new Device::ProDOSOrderDiskImage(file, true) ); - break; - case 'DC42': - device.reset( new Device::DiskCopy42Image(file, true) ); - break; - - default: - std::fprintf(stderr, "Unable to determine format. Please use -f flag.\n"); - return 2; - } - + + + volume.reset( new Pascal::VolumeEntry(device.get())); From e53674e01533524b573a9b955ae7945c052be7ff Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 19 May 2010 16:06:42 +0000 Subject: [PATCH 103/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@224 aa027e90-d47c-11dd-86d7-074df07e0730 --- File/File.cpp | 12 ++++++++++++ File/File.h | 1 + File/MappedFile.cpp | 10 +++++----- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/File/File.cpp b/File/File.cpp index 4442b1b..7ce27f0 100644 --- a/File/File.cpp +++ b/File/File.cpp @@ -36,6 +36,18 @@ File::File(const char *name, int flags) throw POSIXException( __METHOD__ ": open", errno); } + +File::File(const char *name, bool readOnly) +{ +#undef __METHOD__ +#define __METHOD__ "File::File" + + _fd = ::open(name, readOnly ? O_RDONLY : O_RDWR); + if (_fd < 0) + throw POSIXException( __METHOD__ ": open", errno); +} + + File::~File() { close(); diff --git a/File/File.h b/File/File.h index 58609c5..6278666 100644 --- a/File/File.h +++ b/File/File.h @@ -13,6 +13,7 @@ class File { File(File &); File(int fd); File(const char *name, int flags); + File(const char *name, bool readOnly); ~File(); bool isValid() const diff --git a/File/MappedFile.cpp b/File/MappedFile.cpp index babaac5..0ffd087 100644 --- a/File/MappedFile.cpp +++ b/File/MappedFile.cpp @@ -45,7 +45,7 @@ MappedFile::MappedFile(const char *name, bool readOnly) _address = MAP_FAILED; _readOnly = readOnly; - init(f, readOnly, -1); + init(f, readOnly, 0); } @@ -64,13 +64,15 @@ void MappedFile::init(const File &f, bool readOnly, size_t size) #define __METHOD__ "MappedFile::init" struct stat st; + int prot = readOnly ? PROT_READ : PROT_READ | PROT_WRITE; + int flags = MAP_FILE | MAP_SHARED; // close enough if (f.fd() < 0) throw POSIXException( __METHOD__, EBADF); - if (size <= 0) + if (!size) { if (::fstat(f.fd(), &st) != 0) throw POSIXException(__METHOD__ ": fstat", errno); @@ -82,9 +84,7 @@ void MappedFile::init(const File &f, bool readOnly, size_t size) } _length = size; - _address = ::mmap(0, _length, - readOnly ? PROT_READ : PROT_READ | PROT_WRITE, - MAP_FILE | MAP_SHARED, f.fd(), 0); + _address = ::mmap(0, _length, prot, flags, f.fd(), 0); if (_address == MAP_FAILED) throw POSIXException(__METHOD__ ": mmap", errno); From 545dd02842749b4e4c98b18690a2167f6846e43e Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 19 May 2010 17:50:18 +0000 Subject: [PATCH 104/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@225 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/BlockCache.cpp | 2 +- Device/DavexDiskImage.cpp | 7 +++++-- Device/DiskImage.cpp | 12 ++++++++---- Device/DiskImage.h | 2 ++ Device/UniversalDiskImage.cpp | 4 +++- Pascal/VolumeEntry.cpp | 5 ++--- 6 files changed, 21 insertions(+), 11 deletions(-) diff --git a/Cache/BlockCache.cpp b/Cache/BlockCache.cpp index c56e5eb..24f80d7 100644 --- a/Cache/BlockCache.cpp +++ b/Cache/BlockCache.cpp @@ -27,7 +27,7 @@ using ProFUSE::POSIXException; BlockCache::BlockCache(BlockDevice *device) { - _device = _device; + _device = device; _blocks = device->blocks(); _readOnly = device->readOnly(); } diff --git a/Device/DavexDiskImage.cpp b/Device/DavexDiskImage.cpp index f388567..c2e11d6 100644 --- a/Device/DavexDiskImage.cpp +++ b/Device/DavexDiskImage.cpp @@ -40,9 +40,12 @@ DavexDiskImage::DavexDiskImage(const char *name, bool readOnly) : DavexDiskImage::DavexDiskImage(MappedFile *file) : DiskImage(file) { + // at this point, file is no longer valid. + + // 512-bytes header - setBlocks((file->length() / 512) - 1); - setAdaptor(new POAdaptor(512 + (uint8_t *)file->address())); + setBlocks((length() / 512) - 1); + setAdaptor(new POAdaptor(512 + (uint8_t *)address())); } diff --git a/Device/DiskImage.cpp b/Device/DiskImage.cpp index 0bdd365..156cb36 100644 --- a/Device/DiskImage.cpp +++ b/Device/DiskImage.cpp @@ -202,8 +202,10 @@ ProDOSOrderDiskImage::ProDOSOrderDiskImage(const char *name, bool readOnly) : ProDOSOrderDiskImage::ProDOSOrderDiskImage(MappedFile *file) : DiskImage(file) { - setBlocks(file->length() / 512); - setAdaptor(new POAdaptor(file->address())); + // at this point, file is no longer valid. + + setBlocks(length() / 512); + setAdaptor(new POAdaptor(address())); } ProDOSOrderDiskImage *ProDOSOrderDiskImage::Create(const char *name, size_t blocks) @@ -252,8 +254,10 @@ DOSOrderDiskImage::DOSOrderDiskImage(const char *name, bool readOnly) : DOSOrderDiskImage::DOSOrderDiskImage(MappedFile *file) : DiskImage(file) { - setBlocks(file->length() / 512); - setAdaptor(new DOAdaptor(file->address())); + // at this point, file is no longer valid. + + setBlocks(length() / 512); + setAdaptor(new DOAdaptor(address())); } diff --git a/Device/DiskImage.h b/Device/DiskImage.h index 2f1a909..e5b9b55 100644 --- a/Device/DiskImage.h +++ b/Device/DiskImage.h @@ -44,6 +44,8 @@ protected: void setAdaptor(Adaptor *); void *address() const { return _file.address(); } + size_t length() const { return _file.length(); } + MappedFile *file() { return &_file; } private: diff --git a/Device/UniversalDiskImage.cpp b/Device/UniversalDiskImage.cpp index 227f5f3..b1162f0 100644 --- a/Device/UniversalDiskImage.cpp +++ b/Device/UniversalDiskImage.cpp @@ -32,7 +32,9 @@ UniversalDiskImage::UniversalDiskImage(MappedFile *file) : DiskImage(file) { - uint8_t * data = (uint8_t *)file->address(); + // at this point, file is no longer valid. + + uint8_t * data = (uint8_t *)address(); diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index c5924fe..524271f 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -100,7 +100,7 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device) _device = device; _cache = BlockCache::Create(device); - device->read(2, buffer.get()); + _cache->read(2, buffer.get()); init(buffer.get()); @@ -108,7 +108,6 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device) //printf("%u %u\n", blocks(), _lastBlock - _firstBlock); - // why the fuck didn't this work???? blockCount = blocks(); if (blockCount > 1) @@ -117,7 +116,7 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device) for (unsigned i = 0; i < blockCount; ++i) { - device->read(2 + i, buffer.get() + 512 * i); + _cache->read(2 + i, buffer.get() + 512 * i); } } From e8582d0edb47aa1eda2d668c0a085d069a815c99 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 19 May 2010 17:50:43 +0000 Subject: [PATCH 105/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@226 aa027e90-d47c-11dd-86d7-074df07e0730 --- apfm.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/apfm.cpp b/apfm.cpp index eb9d9f4..c21d049 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -153,11 +153,12 @@ int action_ls(int argc, char **argv, Pascal::VolumeEntry *volume) used += e->blocks(); } - if (extended && (lastBlock != volumeSize)) + if (lastBlock != volumeSize) { unsigned size = volumeSize - lastBlock; max = std::max(max, size); - printUnusedEntry(lastBlock, size); + if (extended) + printUnusedEntry(lastBlock, size); } @@ -269,7 +270,7 @@ void usage() } -int main(int argc, char **argv) +int main(/* int argc, char **argv */) { std::auto_ptr volume; std::auto_ptr device; @@ -279,6 +280,8 @@ int main(int argc, char **argv) int c; + + // getop stops at first non '-' arg so it will not affect action flags. while ((c = ::getopt(argc, argv, "f:h")) != -1) { @@ -308,7 +311,7 @@ int main(int argc, char **argv) optreset = 1; optind = 1; - if (argc != 2) + if (argc < 2) { usage(); return 0; From 1a27d76d67f3ffae727d61abaab9f89e369a60ae Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 19 May 2010 20:06:11 +0000 Subject: [PATCH 106/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@227 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/FileEntry.cpp | 2 +- apfm.cpp | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index f12cb72..23ba327 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -220,7 +220,7 @@ int FileEntry::textRead(uint8_t *buffer, unsigned size, unsigned offset) to += pageSize; } - + // first 2 pages are spare, for editor use, not actually text. block = _firstBlock + 2 + (page * 2); diff --git a/apfm.cpp b/apfm.cpp index c21d049..dbefc63 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -188,7 +188,7 @@ int action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume) return 1; } - for (unsigned i = 0; i < argc; ++i) + for (unsigned i = 1; i < argc; ++i) { const char *fname = argv[i]; unsigned fileSize; @@ -270,7 +270,7 @@ void usage() } -int main(/* int argc, char **argv */) +int main(int argc, char **argv) { std::auto_ptr volume; std::auto_ptr device; @@ -280,7 +280,18 @@ int main(/* int argc, char **argv */) int c; - + /* + char *argv2[] = { + (char *)"afpm", + //(char *)"/Users/kelvin/Desktop/ucsd/pascal.dsk", + (char *)"/Users/kelvin/Desktop/ucsd/UCSD Pascal 1.2_3.DSK", + (char *)"cat", + (char *)"SPIRODEMO.TEXT", + NULL + }; + char **argv = argv2; + int argc = 4; + */ // getop stops at first non '-' arg so it will not affect action flags. while ((c = ::getopt(argc, argv, "f:h")) != -1) From 6dd25c9be538ed3f42172e3fa97691a09c3b978a Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 19 May 2010 23:47:21 +0000 Subject: [PATCH 107/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@229 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/File.h | 4 ++-- Pascal/FileEntry.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Pascal/File.h b/Pascal/File.h index 39e408b..6b7608c 100644 --- a/Pascal/File.h +++ b/Pascal/File.h @@ -1,5 +1,5 @@ -#ifndef __FILE_H__ -#define __FILE_H__ +#ifndef __PASCAL_FILE_H__ +#define __PASCAL_FILE_H__ #include diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index 23ba327..3f89421 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -335,7 +335,7 @@ void FileEntry::textInit() for (unsigned block = _firstBlock + 2; block < _lastBlock; block += 2) { unsigned size = textDecodePage(block, NULL); - printf("%u: %u\n", block, size); + //printf("%u: %u\n", block, size); _fileSize += size; _pageSize->push_back(size); } From 4fe15a8e99893f785cbac62dca727f4f9c2bc6c7 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 19 May 2010 23:47:32 +0000 Subject: [PATCH 108/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@230 aa027e90-d47c-11dd-86d7-074df07e0730 --- File/File.cpp | 10 ++++++++++ File/File.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/File/File.cpp b/File/File.cpp index 7ce27f0..d1d3e49 100644 --- a/File/File.cpp +++ b/File/File.cpp @@ -71,11 +71,21 @@ void File::close() void File::adopt(File &f) { + if (&f == this) return; + close(); _fd = f._fd; f._fd = -1; } +void File::adopt(int fd) +{ + if (fd == _fd) return; + close(); + _fd = fd; +} + + void File::swap(File &f) { std::swap(_fd, f._fd); diff --git a/File/File.h b/File/File.h index 6278666..5ada61d 100644 --- a/File/File.h +++ b/File/File.h @@ -26,6 +26,8 @@ class File { void close(); void adopt(File &f); + void adopt(int fd); + void swap(File &f); private: From a2bea3d8f7a97c14909947889ee0bc426b031d36 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 19 May 2010 23:47:48 +0000 Subject: [PATCH 109/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@231 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/BlockDevice.cpp | 174 ++++++++++++++++++++++++++++++++++++++++- Device/BlockDevice.h | 11 +++ Device/DiskImage.cpp | 91 +-------------------- Device/DiskImage.h | 4 - Device/RawDevice.cpp | 68 ++++++++++------ Device/RawDevice.h | 13 ++- 6 files changed, 239 insertions(+), 122 deletions(-) diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index 8cb61af..4a326b1 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -13,14 +14,183 @@ #include +#include +#include +#include +#include +#include using namespace Device; using ProFUSE::Exception; using ProFUSE::POSIXException; -#pragma mark - -#pragma mark BlockDevice + + +unsigned BlockDevice::ImageType(const char *type, unsigned defv) +{ + const char *tmp; + + + if (type == 0 || *type == 0) return defv; + + // type could be a filename, in which case we check the extension. + tmp = std::strrchr(type, '.'); + if (tmp) type = tmp + 1; + if (*type == 0) return defv; + + + if (::strcasecmp(type, "2mg") == 0) + return '2IMG'; + if (::strcasecmp(type, "2img") == 0) + return '2IMG'; + + if (::strcasecmp(type, "dc42") == 0) + return 'DC42'; + + if (::strcasecmp(type, "po") == 0) + return 'PO__'; + if (::strcasecmp(type, "dmg") == 0) + return 'PO__'; + + if (::strcasecmp(type, "dsk") == 0) + return 'DO__'; + if (::strcasecmp(type, "do") == 0) + return 'DO__'; + + if (::strcasecmp(type, "dvx") == 0) + return 'DVX_'; + if (::strcasecmp(type, "davex") == 0) + return 'DVX_'; + + + // not supported yet. + if (::strcasecmp(tmp, "sdk") == 0) + return 'SDK_'; + + return defv; +} + +BlockDevice *BlockDevice::Open(const char *name, bool readOnly, unsigned imageType) +{ +#undef __METHOD__ +#define __METHOD__ "BlockDevice::Open" + + struct stat st; + + std::memset(&st, 0, sizeof(st)); + + if (::stat(name, &st) != 0) + { + throw POSIXException(__METHOD__ ": stat error", errno); + } + + if (!imageType) + { + // /dev/xxxx + if (S_ISBLK(st.st_mode)) + return RawDevice::Open(name, readOnly); + + + imageType = ImageType(name, 'PO__'); + } + + + // TODO -- if no image type, guess based on file size? + + MappedFile file(name, readOnly); + + + switch (imageType) + { + case '2IMG': + return UniversalDiskImage::Open(&file); + + case 'DC42': + return DiskCopy42Image::Open(&file); + + case 'DO__': + return DOSOrderDiskImage::Open(&file); + + case 'PO__': + return ProDOSOrderDiskImage::Open(&file); + + case 'DVX_': + return DavexDiskImage::Open(&file); + + } + + // throw an error? + return NULL; + +} + + +// return the basename, without an extension. +static std::string filename(const std::string& src) +{ + unsigned start; + unsigned end; + + + if (src.empty()) return std::string(""); + + start = end = 0; + + for(unsigned i = 0, l = src.length(); i < l; ++i) + { + char c = src[i]; + if (c == '/') start = end = i + 1; + if (c == '.') end = i; + } + + if (start == src.length()) return std::string(""); + + if (start == end) return src.substr(start); + return src.substr(start, end - start); +} + + +BlockDevice *BlockDevice::Create(const char *fname, const char *vname, unsigned blocks, unsigned imageType) +{ + std::string xname; + + if (!imageType) imageType = ImageType(fname, 'PO__'); + + if (vname == NULL) + { + xname = filename(std::string(fname)); + vname = xname.c_str(); + } + + + + + switch(imageType) + { + case '2IMG': + return UniversalDiskImage::Create(fname, blocks); + + case 'DC42': + return DiskCopy42Image::Create(fname, blocks, vname); + + case 'DO__': + return DOSOrderDiskImage::Create(fname, blocks); + + case 'PO__': + return ProDOSOrderDiskImage::Create(fname, blocks); + + case 'DVX_': + return DavexDiskImage::Create(fname, blocks, vname); + } + + return NULL; + +} + + + + BlockDevice::BlockDevice() { diff --git a/Device/BlockDevice.h b/Device/BlockDevice.h index 453958f..33680e3 100644 --- a/Device/BlockDevice.h +++ b/Device/BlockDevice.h @@ -15,6 +15,17 @@ namespace Device { class BlockDevice { public: + + // static methods. + static unsigned ImageType(const char *type, unsigned defv = 0); + + static BlockDevice *Open(const char *name, bool readOnly, unsigned imageType = 0); + static BlockDevice *Create(const char *fname, const char *vname, unsigned blocks, unsigned imageType = 0); + + + + + virtual ~BlockDevice(); virtual BlockCache *createBlockCache(); diff --git a/Device/DiskImage.cpp b/Device/DiskImage.cpp index 156cb36..3820534 100644 --- a/Device/DiskImage.cpp +++ b/Device/DiskImage.cpp @@ -5,13 +5,9 @@ #include #include -#include - #include -#include -#include -#include + #include @@ -28,91 +24,6 @@ using ProFUSE::POSIXException; - - - - - -unsigned DiskImage::ImageType(const char *type, unsigned defv) -{ - const char *tmp; - - if (type == 0 || *type == 0) return defv; - - // type could be a filename, in which case we check the extension. - tmp = std::strrchr(type, '.'); - if (tmp) type = tmp + 1; - if (*type == 0) return defv; - - - if (::strcasecmp(type, "2mg") == 0) - return '2IMG'; - if (::strcasecmp(type, "2img") == 0) - return '2IMG'; - - if (::strcasecmp(type, "dc42") == 0) - return 'DC42'; - - if (::strcasecmp(type, "po") == 0) - return 'PO__'; - if (::strcasecmp(type, "dmg") == 0) - return 'PO__'; - - if (::strcasecmp(type, "dsk") == 0) - return 'DO__'; - if (::strcasecmp(type, "do") == 0) - return 'DO__'; - - if (::strcasecmp(type, "dvx") == 0) - return 'DVX_'; - if (::strcasecmp(type, "davex") == 0) - return 'DVX_'; - - /* - // not supported yet. - if (::strcasecmp(tmp, "sdk") == 0) - return 'SDK_'; - */ - return defv; -} - -BlockDevice *DiskImage::Open(const char *name, bool readOnly, unsigned imageType) -{ - if (!imageType) imageType = ImageType(name, 'PO__'); - - // TODO -- if no image type, guess based on file size? - // TODO -- check for /dev/* ? - - MappedFile file(name, readOnly); - - - switch (imageType) - { - case '2IMG': - return UniversalDiskImage::Open(&file); - - case 'DC42': - return DiskCopy42Image::Open(&file); - - case 'DO__': - return DOSOrderDiskImage::Open(&file); - - case 'PO__': - return ProDOSOrderDiskImage::Open(&file); - - case 'DVX_': - return DavexDiskImage::Open(&file); - - } - - // throw an error? - return NULL; - -} - - - - DiskImage::DiskImage(const char *name, bool readOnly) { File fd(name, readOnly ? O_RDONLY : O_RDWR); diff --git a/Device/DiskImage.h b/Device/DiskImage.h index e5b9b55..2132c37 100644 --- a/Device/DiskImage.h +++ b/Device/DiskImage.h @@ -18,11 +18,7 @@ namespace Device { class DiskImage : public BlockDevice { public: - static unsigned ImageType(const char *type, unsigned defv = 0); - - static BlockDevice *Open(const char *name, bool readOnly, unsigned imageType = 0); - virtual ~DiskImage(); virtual void read(unsigned block, void *bp); diff --git a/Device/RawDevice.cpp b/Device/RawDevice.cpp index 1e9c6ca..2d29df7 100644 --- a/Device/RawDevice.cpp +++ b/Device/RawDevice.cpp @@ -22,7 +22,6 @@ #include -#include #include using namespace Device; @@ -95,43 +94,57 @@ void RawDevice::devSize(int fd) // TODO -- FreeBSD/NetBSD/OpenBSD -RawDevice::RawDevice(const char *name, bool readOnly) +RawDevice::RawDevice(const char *name, bool readOnly) : + _file(name, readOnly) { #undef __METHOD__ #define __METHOD__ "RawDevice::RawDevice" - // open read-only, verify if device is readable, and then try to upgrade to read/write? - - ProFUSE::auto_fd fd; - - if (!readOnly) fd.reset(::open(name, O_RDWR)); - if (fd < 0) + if (!_file.isValid()) { - readOnly = false; - fd.reset(::open(name, O_RDONLY)); + throw new Exception(__METHOD__ ": Invalid file handle."); } - - if (fd < 0) - throw POSIXException(__METHOD__ ": Unable to open device.", errno); - - _fd = -1; - + _readOnly = readOnly; _size = 0; _blocks = 0; _blockSize = 0; - devSize(fd); + devSize(_file.fd()); +} + +RawDevice::RawDevice(File& file, bool readOnly) : + _file(file) +{ +#undef __METHOD__ +#define __METHOD__ "RawDevice::RawDevice" - _fd = fd.release(); + + if (!_file.isValid()) + { + throw new Exception(__METHOD__ ": Invalid file handle."); + } + + _readOnly = readOnly; + _size = 0; + _blocks = 0; + _blockSize = 0; + + + devSize(_file.fd()); } RawDevice::~RawDevice() { - if (_fd >= 0) ::close(_fd); +} + + +RawDevice *RawDevice::Open(const char *name, bool readOnly) +{ + return new RawDevice(name, readOnly); } @@ -147,7 +160,7 @@ void RawDevice::read(unsigned block, void *bp) // apple - read full native block(s) ? off_t offset = block * 512; - size_t ok = ::pread(_fd, bp, 512, offset); + size_t ok = ::pread(_file.fd(), bp, 512, offset); // TODO -- EINTR? if (ok != 512) @@ -170,7 +183,7 @@ void RawDevice::read(TrackSector ts, void *bp) // apple - read full native block(s) ? off_t offset = (ts.track * 16 + ts.sector) * 256; - size_t ok = ::pread(_fd, bp, 256, offset); + size_t ok = ::pread(_file.fd(), bp, 256, offset); // TODO -- EINTR? if (ok != 256) @@ -192,7 +205,7 @@ void RawDevice::write(unsigned block, const void *bp) off_t offset = block * 512; - size_t ok = ::pwrite(_fd, bp, 512, offset); + size_t ok = ::pwrite(_file.fd(), bp, 512, offset); if (ok != 512) throw ok < 0 @@ -214,7 +227,7 @@ void RawDevice::write(TrackSector ts, const void *bp) off_t offset = (ts.track * 16 + ts.sector) * 256; - size_t ok = ::pwrite(_fd, bp, 256, offset); + size_t ok = ::pwrite(_file.fd(), bp, 256, offset); if (ok != 256) throw ok < 0 @@ -233,6 +246,13 @@ bool RawDevice::mapped() return false; } + +unsigned RawDevice::blocks() +{ + return _blocks; +} + + void RawDevice::sync() { #undef __METHOD__ @@ -240,6 +260,6 @@ void RawDevice::sync() if (_readOnly) return; - if (::fsync(_fd) < 0) + if (::fsync(_file.fd()) < 0) throw POSIXException(__METHOD__ ": fsync error.", errno); } \ No newline at end of file diff --git a/Device/RawDevice.h b/Device/RawDevice.h index f39fa70..df711ac 100644 --- a/Device/RawDevice.h +++ b/Device/RawDevice.h @@ -5,16 +5,23 @@ #include +#include + namespace Device { // /dev/xxx -class RawDevice : BlockDevice { +class RawDevice : public BlockDevice { public: RawDevice(const char *name, bool readOnly); + RawDevice(File& file, bool readOnly); + + static RawDevice *Open(const char *name, bool readOnly); + + virtual ~RawDevice(); virtual void read(unsigned block, void *bp); @@ -27,11 +34,13 @@ public: virtual bool mapped(); virtual void sync(); + virtual unsigned blocks(); + private: void devSize(int fd); - int _fd; + File _file; bool _readOnly; uint64_t _size; From ec9ac2052843f86c0b6e0852d4c2fa962dbafd86 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 19 May 2010 23:48:27 +0000 Subject: [PATCH 110/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@232 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/ConcreteBlockCache.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Cache/ConcreteBlockCache.cpp b/Cache/ConcreteBlockCache.cpp index 49eecec..7fdbba5 100644 --- a/Cache/ConcreteBlockCache.cpp +++ b/Cache/ConcreteBlockCache.cpp @@ -213,10 +213,9 @@ ConcreteBlockCache::Entry *ConcreteBlockCache::findEntry(unsigned block) e = _hashTable[hash]; - if (e) - { - while ((e) && (e->block != block)) e = e->nextHash; - } + while ((e) && (e->block != block)) + e = e->nextHash; + return e; } From fc7c205fe00c3719d672503c636326f10a450c0a Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 19 May 2010 23:48:33 +0000 Subject: [PATCH 111/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@233 aa027e90-d47c-11dd-86d7-074df07e0730 --- apfm.cpp | 14 ++++++--- newfs_pascal.cpp | 78 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 63 insertions(+), 29 deletions(-) diff --git a/apfm.cpp b/apfm.cpp index dbefc63..656e768 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -19,7 +19,6 @@ #include #include #include -#include @@ -184,7 +183,7 @@ int action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume) if (argc < 2) { - std::fprintf(stderr, "apfm cat: Please specify one or more files."); + std::fprintf(stderr, "apfm cat: Please specify one or more files.\n"); return 1; } @@ -227,21 +226,28 @@ int action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume) int action_cp(int argc, char **argv, Pascal::VolumeEntry *volume) { + // cp src dest + // first character of ':' indicates pascal file, otherwise, is native file? return 0; } int action_mv(int argc, char **argv, Pascal::VolumeEntry *volume) { + // mv src dest + // first character of ':' indicates pascal file, otherwise is native file? return 0; } int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume) { + // mv rm file [file ....] + // needs ':' as f return 0; } int action_krunch(int argc, char **argv, Pascal::VolumeEntry *volume) { + // compress file to remove gaps. return 0; } @@ -300,7 +306,7 @@ int main(int argc, char **argv) switch(c) { case 'f': - fmt = Device::DiskImage::ImageType(optarg); + fmt = Device::BlockDevice::ImageType(optarg); if (!fmt) { std::fprintf(stderr, "Error: Invalid file format: ``%s''.\n", @@ -337,7 +343,7 @@ int main(int argc, char **argv) try { - device.reset( Device::DiskImage::Open(file, true, fmt) ); + device.reset( Device::BlockDevice::Open(file, true, fmt) ); diff --git a/newfs_pascal.cpp b/newfs_pascal.cpp index 838a1c6..9a434aa 100644 --- a/newfs_pascal.cpp +++ b/newfs_pascal.cpp @@ -1,10 +1,10 @@ -#include "../BlockDevice.h" -#include "../Exception.h" -#include "../MappedFile.h" -#include "../DiskCopy42Image.h" +#include +#include -#include "File.h" +#include + +#include #include #include @@ -12,14 +12,26 @@ #include #include - +#include 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 @@ -149,7 +161,7 @@ int main(int argc, char **argv) case 'f': { - format = ProFUSE::DiskImage::ImageType(optarg); + format = Device::BlockDevice::ImageType(optarg); if (format == 0) { std::fprintf(stderr, "Error: `%s' is not a supported disk image format.\n", optarg); @@ -181,40 +193,56 @@ int main(int argc, char **argv) volumeName = "PASCAL"; } - if (format == 0) format = ProFUSE::DiskImage::ImageType(fname, 'PO__'); - + + try { - std::auto_ptr device; - std::auto_ptr volume; - // TODO -- check for raw device. + struct stat st; + bool rawDevice; + std::auto_ptr device; + std::auto_ptr volume; - switch(format) + // Check for block device. if so, verify. + // if file exists, verify before overwrite. + std::memset(&st, 0, sizeof(st)); + + if (::stat(fname, &st) == 0) { - case 'DC42': - device.reset(ProFUSE::DiskCopy42Image::Create(fname, blocks, volumeName.c_str())); - break; + 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.reset( RawDevice::Open(fname, false) ); + blocks = device->blocks(); + rawDevice = true; + } - case 'PO__': - device.reset(ProFUSE::ProDOSOrderDiskImage::Create(fname, blocks)); - break; + 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; + } - case 'DO__': - device.reset(ProFUSE::DOSOrderDiskImage::Create(fname, blocks)); - break; + } - - default: + if (!rawDevice) + device.reset( BlockDevice::Create(fname, volumeName.c_str(), blocks, format)); + + if (!device.get()) + { std::fprintf(stderr, "Error: Unsupported diskimage format.\n"); return -1; } volume.reset( - new Pascal::VolumeEntry(volumeName.c_str(), device.get()) + new VolumeEntry(volumeName.c_str(), device.get()) ); device.release(); From bc5ffeab0585386523d9543fb7fcb34fcf1ff3d5 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 20 May 2010 01:14:56 +0000 Subject: [PATCH 112/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@234 aa027e90-d47c-11dd-86d7-074df07e0730 --- BlockCache.cpp | 177 ------------------------------------------------- BlockCache.h | 81 ---------------------- 2 files changed, 258 deletions(-) delete mode 100644 BlockCache.cpp delete mode 100644 BlockCache.h diff --git a/BlockCache.cpp b/BlockCache.cpp deleted file mode 100644 index 53edb5e..0000000 --- a/BlockCache.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#include "BlockCache.h" - -struct FileBlockCache::Entry { - FileBlockCache::Entry *next; - unsigned block; - unsigned count; - bool dirty; - uint8_t buffer[512]; -}; - -FileBlockCache::FileBlockCache(Device *device) -{ - _device = device; - - // allocate initial buffer. - for (unsigned i = 0; i < 10; ++i) - { - Entry *e = new Entry; - std::memset(e, 0, sizeof(Entry)); - - _pages.push_back(e); - _unused.push_back(e); - } -} - -FileBlockCache::~FileBlockCache() -{ - std::vector::iterator iter; - - // todo -- check if dirty. - - // deallocate everything that was allocated. - for (iter = _pages.begin(); iter != _pages.end(); ++iter) - { - Entrty *e = *iter; - if (e->dirty) sync(e); - delete e; - } -} - - - -uint8_t *FileBlockCache::acquire(unsigned block) -{ - Entry *e = findEntry(block); - - if (e) - { - if (++e->count == 1) - _unused.remove(e); - return e->buffer; - } - - if (_unused.empty()) - { - e = new Entry; - _pages.push_back(e); - } - else - { - e = _unused.pop_front(); - - removeEntry(e); - } - std::memset(e, 0, sizeof(Entry)); - unsigned hash = hashFunction(block); - - e->block = block; - e->count = 1; - e->dirty = 0; - - _device->read(block, e->buffer); - - _e->next = _hashMap[hash]; - _hashMap[hash] = e; - - return e->buffer; -} - - -void FileBlockCache::release(unsigned block, bool dirty) -{ - Entry *e = findEntry(block); - - // throw error? - if (!e) return; - - if (dirty) e->dirty = true; - - if (e->count == 0) return; - if (--e->count == 0) - { - _unused.push_back(e); - } - // sync if dirty?? -} - -void FileBlockCache::markDirty(unsigned block) -{ - Entry *e = findEntry(e); - - if (e && e->count) e->dirty = true; -} - -Entry *FileBlockCache::findEntry(unsigned block) -{ - unsigned hash = hashFunction(block); - Entry *e; - - e = _hashMap[hash]; - - while (e && e->block != block) - { - e = e->next; - } - - return e; -} - -void FileBlockCache::removeEntry(Entry *e) -{ - unsigned hash; - Entry *curr; - Entry *prev; - - if (!e) return; - - hash = hashFunction(e->block); - - curr = _hashMap[hash]; - - if (curr == e) - { - _hashMap[hash] = e->next; - return; - } - - for (;;) - { - prev = curr; - curr = curr->next; - - if (!curr) break; - - if (e == curr) - { - prev->next = e->next; - return; - } - } -} - -unsigned FileBlockCache::hashFunction(unsigned block) -{ - return block % HashEntries; -} - -void FileBlockCache::sync(Entry *e) -{ - if (!e) return; - if (!e->dirty) return; - - _device->write(e->block, e->buffer); - e->dirty = false; -} - -void FileBlockCache::sync() -{ - std::vector::iterator iter; - - for (iter = _pages.begin(); iter != _pages.end(); ++iter) - { - Entry *e = *iter; - - if (e && e->dirty) sync(e); - } -} diff --git a/BlockCache.h b/BlockCache.h deleted file mode 100644 index 978dd6f..0000000 --- a/BlockCache.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef __BLOCK_CACHE_H__ -#define __BLOCK_CACHE__ - -#include - -#include -#include - -//#include -//typedef std::__gnu_cxx::hash_map hash_map; - -namespace ProFUSE { - -class BlockCache { - public: - - virtual ~BlockCache(); - - virtual uint8_t *acquire(unsigned block) = 0; - virtual void release(unsigned block, bool dirty = false) = 0; - virtual void markDirty(unsigned block) = 0; - - virtual void sync() = 0; - -}; - - -class FileBlockCache : public BlockCache { - - - FileBlockCache(Device *); - virtual ~FileBlockCache(); - - virtual uint8_t *acquire(unsigned block); - virtual void release(unsigned block, bool dirty = false); - virtual void markDirty(unsigned block); - - virtual void sync(); - -private: - struct Entry; - - enum { HashEntries = 23 }; - - - unsigned hashFunction(unsigned); - - void removeEntry(Entry *); - Entry *findEntry(unsigned block); - void sync(Entry *); - - std::vector _pages; - std::list _unused; - - Entry *_hashMap[HashEntries]; - - Device *_device; - -}; - -class MappedBlockCache : public BlockCache -{ -public: - - MappedBlockCache(Device *); - virtual ~MappedBlockCache(); - - virtual uint8_t *acquire(unsigned block); - virtual void release(unsigned block, bool dirty = false); - virtual void markDirty(unsigned block); - - virtual void sync(); - - - private: - Device *_device; -}; - -} - -#endif From f91009d870d4c6e382bf66b6125b85b587405291 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 20 May 2010 01:15:56 +0000 Subject: [PATCH 113/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@235 aa027e90-d47c-11dd-86d7-074df07e0730 --- DataWriter.cpp | 98 -------------------------------------------------- DataWriter.h | 72 ------------------------------------- 2 files changed, 170 deletions(-) delete mode 100644 DataWriter.cpp delete mode 100644 DataWriter.h diff --git a/DataWriter.cpp b/DataWriter.cpp deleted file mode 100644 index 9f7036b..0000000 --- a/DataWriter.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "DataWriter.h" -#include "Endian.h" - -#include - -using namespace ProFUSE; - -DataWriter::DataWriter(unsigned size) -{ - _size = size; - _release = true; - _offset = 0; - _buffer = new uint8_t[size]; -} - -DataWriter::DataWriter(unsigned size, void *buffer) -{ - _size = size; - _buffer = (uint8_t *)buffer; - _release = false; - _offset = 0; -} - -DataWriter::~DataWriter() -{ - if (_release && _buffer) delete[] _buffer; -} - -void DataWriter::write8(uint8_t data) -{ - _buffer[_offset] = data; - _offset += 1; -} - -void DataWriter::write(const void *data, unsigned size) -{ - std::memcpy(pointer(), data, size); - _offset += size; -} - - - -DataWriterLE::DataWriterLE(unsigned size) : - DataWriter(size) -{} - -DataWriterLE::DataWriterLE(unsigned size, void *buffer) : - DataWriter(size, buffer) -{} - - -void DataWriterLE::write16(uint16_t data) -{ - LittleEndian::Write16(pointer(), data); - _offset += 2; -} - -void DataWriterLE::write24(uint32_t data) -{ - LittleEndian::Write24(pointer(), data); - _offset += 3; -} - -void DataWriterLE::write32(uint32_t data) -{ - LittleEndian::Write32(pointer(), data); - _offset += 4; -} - - - -DataWriterBE::DataWriterBE(unsigned size) : - DataWriter(size) -{} - -DataWriterBE::DataWriterBE(unsigned size, void *buffer) : - DataWriter(size, buffer) -{} - - -void DataWriterBE::write16(uint16_t data) -{ - BigEndian::Write16(pointer(), data); - _offset += 2; -} - -void DataWriterBE::write24(uint32_t data) -{ - BigEndian::Write24(pointer(), data); - _offset += 3; -} - -void DataWriterBE::write32(uint32_t data) -{ - BigEndian::Write32(pointer(), data); - _offset += 4; -} - diff --git a/DataWriter.h b/DataWriter.h deleted file mode 100644 index 5323842..0000000 --- a/DataWriter.h +++ /dev/null @@ -1,72 +0,0 @@ - -#ifndef __DATAWRITER_H__ -#define __DATAWRITER_H__ - -#include - -namespace ProFUSE { - -class DataWriter { - -public: - - DataWriter(unsigned size); - DataWriter(unsigned size, void *data); - virtual ~DataWriter(); - - void write8(uint8_t); - virtual void write16(uint16_t) = 0; - virtual void write24(uint32_t) = 0; - virtual void write32(uint32_t) = 0; - - void write(const void *data, unsigned size); - - - void setOffset(unsigned o) { _offset = o; } - unsigned offset() const { return _offset; } - - void forward(unsigned count) { _offset += count; } - void rewind(unsigned count) { _offset -= count; } - - void *data() const { return _buffer; } - unsigned size() const { return _size; } - -protected: - - uint8_t *pointer() const { return _offset + _buffer; } - - bool _release; - unsigned _size; - - unsigned _offset; - uint8_t *_buffer; - - -}; - -class DataWriterLE : public DataWriter { -public: - DataWriterLE(unsigned); - DataWriterLE(unsigned, void *); - - virtual void write8(uint8_t); - virtual void write16(uint16_t); - virtual void write24(uint32_t); - virtual void write32(uint32_t); -}; - - -class DataWriterBE : public DataWriter { -public: - DataWriterBE(unsigned); - DataWriterBE(unsigned, void *); - - virtual void write8(uint8_t); - virtual void write16(uint16_t); - virtual void write24(uint32_t); - virtual void write32(uint32_t); -}; - -} - -#endif \ No newline at end of file From 31e5f9091b4fc98dc8545c6e6a5b3559ffa24594 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 20 May 2010 01:17:59 +0000 Subject: [PATCH 114/236] fix cap. typo git-svn-id: https://profuse.googlecode.com/svn/branches/v2@236 aa027e90-d47c-11dd-86d7-074df07e0730 --- ProFUSE/Lock.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ProFUSE/Lock.cpp b/ProFUSE/Lock.cpp index 0b6013b..7f6130c 100644 --- a/ProFUSE/Lock.cpp +++ b/ProFUSE/Lock.cpp @@ -1,4 +1,4 @@ -#include +#include using namespace ProFUSE; @@ -25,4 +25,4 @@ void Lock::unlock() bool Lock::tryLock() { return pthread_mutex_trylock(&_mutex) == 0; -} \ No newline at end of file +} From 955986bec0268941cb7dcfe2da32a6c9828e3442 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 20 May 2010 01:21:55 +0000 Subject: [PATCH 115/236] add include git-svn-id: https://profuse.googlecode.com/svn/branches/v2@237 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/MappedBlockCache.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Cache/MappedBlockCache.cpp b/Cache/MappedBlockCache.cpp index 74709be..459e9fa 100644 --- a/Cache/MappedBlockCache.cpp +++ b/Cache/MappedBlockCache.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include From 9cd20f791fb5a5de78c1973606da357faca58753 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 20 May 2010 01:25:40 +0000 Subject: [PATCH 116/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@238 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/Entry.cpp | 1 - Pascal/FileEntry.cpp | 2 +- Pascal/VolumeEntry.cpp | 3 +++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Pascal/Entry.cpp b/Pascal/Entry.cpp index 0b57e43..4943ab5 100644 --- a/Pascal/Entry.cpp +++ b/Pascal/Entry.cpp @@ -1,6 +1,5 @@ #include -#include #include #include diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index 3f89421..b7f330d 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -6,7 +6,7 @@ #include -#include +#include #include #include diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index 524271f..4109212 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -1,3 +1,6 @@ + +#include + #include #include From d9bc18bdee84c37cbb3acdf2739295b3ecc82102 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 20 May 2010 01:27:48 +0000 Subject: [PATCH 117/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@239 aa027e90-d47c-11dd-86d7-074df07e0730 --- newfs_pascal.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/newfs_pascal.cpp b/newfs_pascal.cpp index 9a434aa..4aca6cd 100644 --- a/newfs_pascal.cpp +++ b/newfs_pascal.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -276,4 +277,4 @@ int main(int argc, char **argv) } return 0; -} \ No newline at end of file +} From e7b4c96984333ab918ea02ab31799569e8874fb1 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 20 May 2010 22:30:00 +0000 Subject: [PATCH 118/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@240 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/BlockCache.cpp | 15 +++++++++++++++ Cache/BlockCache.h | 3 +++ Cache/ConcreteBlockCache.cpp | 2 ++ Cache/ConcreteBlockCache.h | 1 + Cache/MappedBlockCache.cpp | 8 ++++++++ Cache/MappedBlockCache.h | 2 ++ Pascal/File.h | 7 +++++-- Pascal/VolumeEntry.cpp | 8 +++++++- 8 files changed, 43 insertions(+), 3 deletions(-) diff --git a/Cache/BlockCache.cpp b/Cache/BlockCache.cpp index 24f80d7..f9327fa 100644 --- a/Cache/BlockCache.cpp +++ b/Cache/BlockCache.cpp @@ -58,3 +58,18 @@ BlockCache *BlockCache::Create(BlockDevice *device) return device->createBlockCache(); } + + +void BlockCache::zeroBlock(unsigned block) +{ + /* + void *address = acquire(block); + std::memset(address, 0, 512); + release(block, true); + */ + + uint8_t buffer[512]; + + std::memset(buffer, 0, 512); + write(block, buffer); +} diff --git a/Cache/BlockCache.h b/Cache/BlockCache.h index 1ee6d40..c4587d1 100644 --- a/Cache/BlockCache.h +++ b/Cache/BlockCache.h @@ -36,6 +36,9 @@ public: virtual void release(unsigned block, int flags) = 0 ; virtual void markDirty(unsigned block) = 0; + + virtual void zeroBlock(unsigned block); + void release(unsigned block) { release(block, 0); } void release(unsigned block, bool dirty) { diff --git a/Cache/ConcreteBlockCache.cpp b/Cache/ConcreteBlockCache.cpp index 7fdbba5..a966117 100644 --- a/Cache/ConcreteBlockCache.cpp +++ b/Cache/ConcreteBlockCache.cpp @@ -148,6 +148,8 @@ void ConcreteBlockCache::write(unsigned block, const void *bp) setLast(e); } + + void ConcreteBlockCache::markDirty(unsigned block) { Entry *e = findEntry(block); diff --git a/Cache/ConcreteBlockCache.h b/Cache/ConcreteBlockCache.h index 2560b8e..de46b8b 100644 --- a/Cache/ConcreteBlockCache.h +++ b/Cache/ConcreteBlockCache.h @@ -20,6 +20,7 @@ public: virtual void release(unsigned block, int flags); virtual void markDirty(unsigned block); + private: struct Entry { diff --git a/Cache/MappedBlockCache.cpp b/Cache/MappedBlockCache.cpp index 459e9fa..ba17efe 100644 --- a/Cache/MappedBlockCache.cpp +++ b/Cache/MappedBlockCache.cpp @@ -69,6 +69,14 @@ void MappedBlockCache::write(unsigned block, const void *vp) } +void MappedBlockCache::zeroBlock(unsigned block) +{ + _dirty = true; + std::memset(_data + block * 512, 0, 512); +} + + + // sync everything. void MappedBlockCache::sync() { diff --git a/Cache/MappedBlockCache.h b/Cache/MappedBlockCache.h index fac9504..951a974 100644 --- a/Cache/MappedBlockCache.h +++ b/Cache/MappedBlockCache.h @@ -14,6 +14,8 @@ class MappedBlockCache : public BlockCache { virtual void sync(); virtual void write(unsigned block, const void *vp); + virtual void zeroBlock(unsigned block); + virtual void *acquire(unsigned block); virtual void release(unsigned block, int flags); diff --git a/Pascal/File.h b/Pascal/File.h index 6b7608c..a3c5b7c 100644 --- a/Pascal/File.h +++ b/Pascal/File.h @@ -78,6 +78,9 @@ class VolumeEntry : public Entry { public: + static unsigned ValidName(const char *); + + // create new VolumeEntry(const char *name, Device::BlockDevice *); @@ -103,8 +106,8 @@ public: void readBlock(unsigned block, void *); void writeBlock(unsigned block, void *); - - unsigned static ValidName(const char *); + void sync(); + protected: virtual void writeDirectoryEntry(LittleEndian::IOBuffer *); diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index 4109212..f76311a 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -77,9 +77,10 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device) _cache = BlockCache::Create(device); _device = device; + for (unsigned i = 2; i < 6; ++i) { - device->zeroBlock(i); + _cache->zeroBlock(i); } void *vp = _cache->acquire(2); @@ -89,6 +90,7 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device) _cache->release(2, true); + _cache->sync(); } @@ -216,6 +218,10 @@ void VolumeEntry::writeBlock(unsigned block, void *buffer) } +void VolumeEntry::sync() +{ + _cache->sync(); +} void VolumeEntry::writeDirectoryEntry(IOBuffer *b) { From f530a9d74883a2a00833b3ec92058c43de30ed70 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 20 May 2010 22:31:48 +0000 Subject: [PATCH 119/236] linux support. git-svn-id: https://profuse.googlecode.com/svn/branches/v2@241 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/RawDevice.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Device/RawDevice.cpp b/Device/RawDevice.cpp index 2d29df7..1a4d4ce 100644 --- a/Device/RawDevice.cpp +++ b/Device/RawDevice.cpp @@ -12,7 +12,7 @@ #include #endif -#ifdef __LINUX__ +#ifdef __linux__ #include #endif @@ -71,7 +71,7 @@ void RawDevice::devSize(int fd) #endif -#ifdef __LINUX__ +#ifdef __linux__ void RawDevice::devSize(int fd) { @@ -262,4 +262,5 @@ void RawDevice::sync() if (::fsync(_file.fd()) < 0) throw POSIXException(__METHOD__ ": fsync error.", errno); -} \ No newline at end of file +} + From 9c95d74cba0647f65175145b1d0b1ebb34b10f74 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 20 May 2010 22:43:42 +0000 Subject: [PATCH 120/236] compress/uncompress text git-svn-id: https://profuse.googlecode.com/svn/branches/v2@242 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/File.h | 4 ++ Pascal/FileEntry.cpp | 101 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/Pascal/File.h b/Pascal/File.h index a3c5b7c..1312068 100644 --- a/Pascal/File.h +++ b/Pascal/File.h @@ -51,6 +51,9 @@ public: VolumeEntry *parent() { return _parent; } + static bool Compress(std::string& text); + static bool Uncompress(std::string &text); + protected: static unsigned ValidName(const char *name, unsigned maxSize); @@ -188,3 +191,4 @@ class FileEntry : public Entry { } #endif + diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index b7f330d..e02838b 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -20,6 +20,10 @@ using namespace LittleEndian; using namespace Pascal; +enum { + kDLE = 16 +}; + #pragma mark - #pragma mark FileEntry @@ -289,7 +293,7 @@ unsigned FileEntry::textDecodePage(unsigned block, uint8_t *out) dle = false; continue; } - if (c == 16) { dle = true; continue; } + if (c == kDLE) { dle = true; continue; } //if (c & 0x80) continue; // ascii only. @@ -340,3 +344,98 @@ void FileEntry::textInit() _pageSize->push_back(size); } } + + +/* + * compress white space into a dle. + * returns true if altered. + * + */ +bool FileEntry::Compress(std::string& text) +{ + bool delta = false; + std::string out; + + size_t pos; + unsigned start; + + pos = start = 0; + for(;;) + { + size_t end; + unsigned count; + + pos = text.find_first_of(' ',pos); + if (pos == std::string::npos) break; + + end = text.find_first_not_of(' ',pos); + + count = end - pos; + + if (count < 3) continue; + + delta = true; + out.append(text.begin() + start, text.begin() + pos); + + while (count) + { + unsigned c = std::min(223u, count); + out.push_back(kDLE); // dle code. + out.push_back(32 + c); + count -= c; + } + + pos = start = end; + } + + if (delta) + { + out.append(text.begin() + start, text.end()); + text.swap(out); + } + + return delta; +} + +bool FileEntry::Uncompress(std::string& text) +{ + bool delta = false; + std::string out; + + size_t start; + size_t pos; + size_t length = text.length(); + + start = pos = 0; + + for(;;) + { + unsigned c; + + pos = text.find_first_of(kDLE, pos); + if (pos == std::string::npos) break; + if (pos == length - 1) break; // should not happen; + + c = text[pos + 1]; + + if (c <= 32) continue; + + delta = true; + + out.append(text.begin() + start, text.begin() + pos); + + out.append(c - 32, ' '); + + pos = pos + 1; + start = pos; + } + + if (delta) + { + out.append(text.begin() + start, text.end()); + text.swap(out); + } + + return delta; +} + From da84b5bca2e78c9c146978a86da5661113bf95a6 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 20 May 2010 22:44:12 +0000 Subject: [PATCH 121/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@243 aa027e90-d47c-11dd-86d7-074df07e0730 --- apfm.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/apfm.cpp b/apfm.cpp index 656e768..d180465 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -286,6 +286,10 @@ int main(int argc, char **argv) int c; + #ifdef __linux__ + putenv("POSIXLY_CORRECT=1"); // fix getopt to not mutate + #endif + /* char *argv2[] = { (char *)"afpm", @@ -325,8 +329,13 @@ int main(int argc, char **argv) argc -= optind; argv += optind; + + #ifdef __linux__ + optind = 0; + #else optreset = 1; optind = 1; + #endif if (argc < 2) { @@ -371,4 +380,4 @@ int main(int argc, char **argv) } return 0; -} \ No newline at end of file +} From 91e2aaac70098ff15b8adf26812cf6bbcf08e0d0 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 20 May 2010 23:22:30 +0000 Subject: [PATCH 122/236] BSD raw device support git-svn-id: https://profuse.googlecode.com/svn/branches/v2@244 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/RawDevice.cpp | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/Device/RawDevice.cpp b/Device/RawDevice.cpp index 1a4d4ce..cedb733 100644 --- a/Device/RawDevice.cpp +++ b/Device/RawDevice.cpp @@ -20,6 +20,11 @@ #include #endif + +#ifdef __FREEBSD__ +#include +#endif + #include #include @@ -89,11 +94,34 @@ void RawDevice::devSize(int fd) } - #endif // TODO -- FreeBSD/NetBSD/OpenBSD +#ifdef __FREEBSD__ + +void RawDevice::devSize(int fd) +{ +#undef __METHOD__ +#define __METHOD__ "RawDevice::devSize" + + unisgned blockSize; + off_t mediaSize; + + if (::ioctl(fd, DIOCGSECTORSIZE, &blockSize) + throw POSIXException(__METHOD__ ": Unable to determine block size.", errno); + + if (::ioctl(fd, DIOCGMEDIASIZE, &mediaSize) + throw POSIXException(__METHOD__ ": Unable to determine media size.", errno); + + _blockSize = blockSize; + _size = mediaSize; + _blocks = mediaSize / blockSize; + +} + +#endif + RawDevice::RawDevice(const char *name, bool readOnly) : _file(name, readOnly) { From cff29a473635f56048e3eb267e1b45a0a6ac7928 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 21 May 2010 01:18:39 +0000 Subject: [PATCH 123/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@245 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/File.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Pascal/File.h b/Pascal/File.h index 1312068..ec1ce91 100644 --- a/Pascal/File.h +++ b/Pascal/File.h @@ -152,8 +152,11 @@ class FileEntry : public Entry { const char *name() const { return _fileName; } Date modification() const { return _modification; } - unsigned static ValidName(const char *); + static unsigned ValidName(const char *); + static bool Compress(std::string& text); + static bool Uncompress(std::string& text); + protected: From 0af8ce500a0912d1272e86481a17112823e184fa Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 21 May 2010 01:29:06 +0000 Subject: [PATCH 124/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@246 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/File.h | 1 + apfm.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Pascal/File.h b/Pascal/File.h index ec1ce91..bf127d1 100644 --- a/Pascal/File.h +++ b/Pascal/File.h @@ -4,6 +4,7 @@ #include #include +#include namespace Device { class BlockDevice; diff --git a/apfm.cpp b/apfm.cpp index d180465..33b222e 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -287,7 +287,7 @@ int main(int argc, char **argv) #ifdef __linux__ - putenv("POSIXLY_CORRECT=1"); // fix getopt to not mutate + putenv((char *)"POSIXLY_CORRECT=1"); // fix getopt to not mutate #endif /* From c901f55b50088802e5e2169377e0e58b866ee6a1 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 21 May 2010 01:46:53 +0000 Subject: [PATCH 125/236] volume name for raw devices. git-svn-id: https://profuse.googlecode.com/svn/branches/v2@248 aa027e90-d47c-11dd-86d7-074df07e0730 --- newfs_pascal.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/newfs_pascal.cpp b/newfs_pascal.cpp index 4aca6cd..f2722b1 100644 --- a/newfs_pascal.cpp +++ b/newfs_pascal.cpp @@ -113,7 +113,9 @@ void usage() " -s size specify size in blocks.\n" " Default is 1600 blocks (800K)\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" ); @@ -186,17 +188,10 @@ int main(int argc, char **argv) fname = argv[0]; fileName = argv[0]; - // generate a filename. - if (volumeName.empty()) - { - volumeName = filename(fileName); - if (volumeName.empty() || !VolumeEntry::ValidName(volumeName.c_str())) - volumeName = "PASCAL"; - } - - + + try { @@ -223,7 +218,8 @@ int main(int argc, char **argv) } else - { + { + // file exists, verify we want to destroy it. fprintf(stderr, "`%s' already exists. Are you sure you want to overwrite it? ", fname); @@ -232,6 +228,15 @@ int main(int argc, char **argv) } + // generate a filename. + if (volumeName.empty()) + { + if (!rawDevice) + volumeName = filename(fileName); + if (volumeName.empty() || !VolumeEntry::ValidName(volumeName.c_str())) + volumeName = "PASCAL"; + } + if (!rawDevice) device.reset( BlockDevice::Create(fname, volumeName.c_str(), blocks, format)); From ca431e43f9414ab2c03064748780c25b5330480e Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 21 May 2010 16:12:55 +0000 Subject: [PATCH 126/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@249 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/File.h | 2 ++ Pascal/VolumeEntry.cpp | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/Pascal/File.h b/Pascal/File.h index bf127d1..9663c21 100644 --- a/Pascal/File.h +++ b/Pascal/File.h @@ -99,6 +99,7 @@ public: Pascal::Date lastBoot() const { return _lastBoot; } FileEntry *fileAtIndex(unsigned i) const; + FileEntry *fileByName(const char *name) const; void addChild(FileEntry *child, unsigned blocks); @@ -112,6 +113,7 @@ public: void sync(); + protected: virtual void writeDirectoryEntry(LittleEndian::IOBuffer *); diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index f76311a..71c5ff9 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -160,6 +160,7 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device) VolumeEntry::~VolumeEntry() { + std::vector::iterator iter; for(iter = _files.begin(); iter != _files.end(); ++iter) { @@ -197,6 +198,19 @@ FileEntry *VolumeEntry::fileAtIndex(unsigned i) const return i < _files.size() ? _files[i] : NULL; } +FileEntry *VolumeEntry::fileByName(const char *name) const +{ + + + std::vector::const_iterator iter; + for(iter = _files.begin(); iter != _files.end(); ++iter) + { + FileEntry *e = *iter; + if (::strcasecmp(name, e->name()) == 0) return e; + } + return NULL; +} + void *VolumeEntry::loadBlock(unsigned block) From a7a625dc3ff5b70967de8238ec01f0d2cede36dd Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 21 May 2010 18:51:00 +0000 Subject: [PATCH 127/236] no throw file open git-svn-id: https://profuse.googlecode.com/svn/branches/v2@250 aa027e90-d47c-11dd-86d7-074df07e0730 --- File/File.cpp | 10 ++++++++++ File/File.h | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/File/File.cpp b/File/File.cpp index d1d3e49..11e8604 100644 --- a/File/File.cpp +++ b/File/File.cpp @@ -26,6 +26,16 @@ File::File(File& f) f._fd = -1; } +File::File(const char *name, int flags, const std::nothrow_t&) +{ + _fd = ::open(name, flags); +} + +File::File(const char *name, bool readOnly, const std::nothrow_t&) +{ + _fd = ::open(name, readOnly ? O_RDONLY : O_RDWR); +} + File::File(const char *name, int flags) { #undef __METHOD__ diff --git a/File/File.h b/File/File.h index 5ada61d..2d83591 100644 --- a/File/File.h +++ b/File/File.h @@ -1,6 +1,8 @@ #ifndef __FILE_H__ #define __FILE_H__ +#include + #include #include #include @@ -12,8 +14,13 @@ class File { File(); File(File &); File(int fd); + File(const char *name, int flags); File(const char *name, bool readOnly); + + File(const char *name, int flags, const std::nothrow_t &); + File(const char *name, bool readOnly, const std::nothrow_t &); + ~File(); bool isValid() const From 433ed40922912a742090ec53d342ddb1b6e032f7 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 21 May 2010 21:22:30 +0000 Subject: [PATCH 128/236] unlink support git-svn-id: https://profuse.googlecode.com/svn/branches/v2@251 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/VolumeEntry.cpp | 46 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index 71c5ff9..0422a7c 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -200,8 +200,6 @@ FileEntry *VolumeEntry::fileAtIndex(unsigned i) const FileEntry *VolumeEntry::fileByName(const char *name) const { - - std::vector::const_iterator iter; for(iter = _files.begin(); iter != _files.end(); ++iter) { @@ -211,7 +209,51 @@ FileEntry *VolumeEntry::fileByName(const char *name) const return NULL; } +void VolumeEntry::unlink(const char *name) +{ + unsigned index; + for(index = 0; index < _fileCount; ++index) + { + FileEntry *e = _files[index]; + if (::strcasecmp(name, e->name()) == 0) + { + delete e; + _files[index] = NULL; + break; + } + } + if (index == _fileCount) return; // not found. + + _files.erase(files.begin() + index); + _fileCount--; + + // need to update the header blocks. + unsigned blockCount = blocks(); + auto_array buffer(new uint8_t[512 * blocks]); + + // load up blocks. + // since entries span blocks, we can't do this via pointer. + for (unsigned i = 0; i < blockCount; ++i) + { + _cache->read(2 + i, buffer.get() + 512 * i); + } + // update the filecount. + IOBuffer b(buffer.get()); + writeDirectoryEntry(b); + + // move up all the entries. + uint8_t *address = buffer.get() + 0x1a + 0x1a * index; + std::memmove(address, address + 0x1a, 0x1a * (_fileCount - index)); + // zero out the memory on the previous entry. + std::memset(buffer.get() + 0x1a + _fileCount * 0x1a, 0, 0x1a); + + // now write to disk. + for (unsigned i = 0; i < blockCount; ++i) + { + _cache->write(2 + i, buffer.get() + 512 * i); + } +} void *VolumeEntry::loadBlock(unsigned block) { From 949ed1e16ca31d86d44dfac51d273cbaf62dee99 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 21 May 2010 23:01:20 +0000 Subject: [PATCH 129/236] Prodos errors git-svn-id: https://profuse.googlecode.com/svn/branches/v2@252 aa027e90-d47c-11dd-86d7-074df07e0730 --- ProFUSE/Exception.h | 60 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/ProFUSE/Exception.h b/ProFUSE/Exception.h index a163ec9..043cd8c 100644 --- a/ProFUSE/Exception.h +++ b/ProFUSE/Exception.h @@ -5,6 +5,66 @@ #include namespace ProFUSE { + + +// ProDOS Errors +enum +{ + badSystemCall = 0x01, + invalidPcount = 0x04, + gsosActice = 0x07, + devNotFound = 0x10, + invalidDevNum = 0x11, + drvrBadReq = 0x20, + drvrBadCode = 0x21, + drvrBadParm = 0x22, + drvrNotOpen = 0x23, + drvrPriorOpen = 0x24, + irqTableFull = 0x25, + drvrNoResrc = 0x26, + drvrIOError = 0x27, + drvrNoDevice = 0x28, + drvrBusy = 0x29, + drvrWrtProt = 0x2b, + drvrBadCount = 0x2c, + drvrBadBlock = 0x2d, + drvrDiskSwitch = 0x2e, + drvrOffLine = 0x2f, + badPathSyntax = 0x40, + invalidRefNum = 0x43, + pathNotFound = 0x44, + volNotFound = 0x45, + fileNotFound = 0x46, + dupPathName = 0x47, + volumeFull = 0x48, + volDirFull = 0x49, + badFileFormat = 0x4a, + badStoreType = 0x4b, + eofEncountered = 0x4c, + outOfRange = 0x4d, + invalidAccess = 0x4e, + buffTooSmall = 0x4f, + fileBusy = 0x50, + dirError = 0x51, + unknownVol = 0x52, + paramRangeError = 0x53, + outOfMem = 0x54, + dupVolume = 0x57, + notBlockDev = 0x58, + damagedBitMap = 0x5a, + badPathNames = 0x5b, + notSystemFile = 0x5c, + osUnsupported = 0x5d, + stackOverflow = 0x5f, + dataUnavail = 0x60, + endOfDir = 0x61, + invalidClass = 0x62, + resForkNotFound = 0x63, + invalidFSTID = 0x64, + devNameErr = 0x67, + resExistsErr = 0x70, + resAddErr = 0x71 +}; class Exception : public std::exception { From deec48b72839a44396c667b0d9cab4ec4fef83c7 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 21 May 2010 23:01:32 +0000 Subject: [PATCH 130/236] krunch support git-svn-id: https://profuse.googlecode.com/svn/branches/v2@253 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/File.h | 19 ++++-- Pascal/VolumeEntry.cpp | 134 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 141 insertions(+), 12 deletions(-) diff --git a/Pascal/File.h b/Pascal/File.h index 9663c21..14e69e0 100644 --- a/Pascal/File.h +++ b/Pascal/File.h @@ -112,7 +112,11 @@ public: void writeBlock(unsigned block, void *); void sync(); + + unsigned unlink(const char *name); + unsigned rename(const char *oldName, const char *newName); + unsigned krunch(); protected: @@ -140,6 +144,13 @@ private: class FileEntry : public Entry { public: + + + static unsigned ValidName(const char *); + + static bool Compress(std::string& text); + static bool Uncompress(std::string& text); + FileEntry(const char *name, unsigned fileKind); FileEntry(void *vp); @@ -154,18 +165,14 @@ class FileEntry : public Entry { const char *name() const { return _fileName; } Date modification() const { return _modification; } - - static unsigned ValidName(const char *); - - static bool Compress(std::string& text); - static bool Uncompress(std::string& text); - + protected: virtual void writeDirectoryEntry(LittleEndian::IOBuffer *); private: + friend class VolumeEntry; unsigned _status; diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index 0422a7c..dab8c39 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -209,10 +209,13 @@ FileEntry *VolumeEntry::fileByName(const char *name) const return NULL; } -void VolumeEntry::unlink(const char *name) +unsigned VolumeEntry::unlink(const char *name) { unsigned index; + + if (_device->readOnly()) return 0x2b; // WRITE-PROTECTED DISK + for(index = 0; index < _fileCount; ++index) { FileEntry *e = _files[index]; @@ -223,14 +226,14 @@ void VolumeEntry::unlink(const char *name) break; } } - if (index == _fileCount) return; // not found. + if (index == _fileCount) return 0x46; // FILE NOT FOUND - _files.erase(files.begin() + index); + _files.erase(_files.begin() + index); _fileCount--; // need to update the header blocks. unsigned blockCount = blocks(); - auto_array buffer(new uint8_t[512 * blocks]); + ProFUSE::auto_array buffer(new uint8_t[512 * blockCount]); // load up blocks. // since entries span blocks, we can't do this via pointer. @@ -239,8 +242,8 @@ void VolumeEntry::unlink(const char *name) _cache->read(2 + i, buffer.get() + 512 * i); } // update the filecount. - IOBuffer b(buffer.get()); - writeDirectoryEntry(b); + IOBuffer b(buffer.get(), 512 * blockCount); + writeDirectoryEntry(&b); // move up all the entries. uint8_t *address = buffer.get() + 0x1a + 0x1a * index; @@ -253,8 +256,127 @@ void VolumeEntry::unlink(const char *name) { _cache->write(2 + i, buffer.get() + 512 * i); } + + _cache->sync(); + return 0; } + + +unsigned VolumeEntry::krunch() +{ + unsigned prevBlock; + + std::vector::const_iterator iter; + + bool gap = false; + + // sanity check to make sure no weird overlap issues. + + prevBlock = lastBlock(); + + for (iter = _files.begin(); iter != _files.end(); ++iter) + { + FileEntry *e = *iter; + + unsigned first = e->firstBlock(); + unsigned last = e->lastBlock(); + + if (first != prevBlock) gap = true; + + if (first < prevBlock) + return ProFUSE::damagedBitMap; + + if (last < first) + return ProFUSE::damagedBitMap; + + if (first < volumeBlocks()) + return ProFUSE::damagedBitMap; + + + prevBlock = last; + + } + + + if (!gap) return 0; + + + // need to update the header blocks. + unsigned blockCount = blocks(); + ProFUSE::auto_array buffer(new uint8_t[512 * blockCount]); + IOBuffer b(buffer.get(), 512 * blockCount); + + // load up the directory blocks. + for (unsigned i = 0; i < blocks(); ++i) + { + _cache->read(2 + i, buffer.get() + 512 * i); + } + + + prevBlock = lastBlock(); + + unsigned offset = 0; + for (iter = _files.begin(); iter != _files.end(); ++iter, ++offset) + { + FileEntry *e = *iter; + + b.setOffset(0x1a + 0x1a * offset); + + unsigned first = e->firstBlock(); + unsigned last = e->lastBlock(); + + unsigned blocks = last - first; + unsigned offset = first - prevBlock; + + if (offset == 0) + { + prevBlock = last; + continue; + } + + e->_firstBlock = first - offset; + e->_lastBlock = last - offset; + + e->writeDirectoryEntry(&b); + + for (unsigned i = 0; i < blocks; ++i) + { + uint8_t buffer[512]; + + _cache->read(first + i, buffer); + _cache->write(prevBlock +i, buffer); + _cache->zeroBlock(first + i); + } + } + + // now save the directory entries. + + // load up the directory blocks. + for (unsigned i = 0; i < blocks(); ++i) + { + _cache->write(2 + i, buffer.get() + 512 * i); + } + + + _cache->sync(); + + return 0; +} + + + + + + + + + + + + + + void *VolumeEntry::loadBlock(unsigned block) { return _cache->acquire(block); From 895bab385c302ef68e2e32e5bc5a1041abfeb61b Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 21 May 2010 23:35:12 +0000 Subject: [PATCH 131/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@254 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/File.h | 5 +++ Pascal/VolumeEntry.cpp | 69 ++++++++++++++++++++---------------------- 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/Pascal/File.h b/Pascal/File.h index 14e69e0..b093b3c 100644 --- a/Pascal/File.h +++ b/Pascal/File.h @@ -127,6 +127,11 @@ private: void init(void *); + + uint8_t *readDirectoryHeader(); + void writeDirectoryHeader(uint8_t *); + + unsigned _fileNameLength; char _fileName[8]; unsigned _lastVolumeBlock; diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index dab8c39..afe9f7c 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -96,8 +96,9 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device) VolumeEntry::VolumeEntry(Device::BlockDevice *device) { - ProFUSE::auto_array buffer(new uint8_t[512]); unsigned blockCount; + ProFUSE::auto_array buffer(new uint8_t[512]); + // read the header block, then load up all the header // blocks. @@ -117,12 +118,7 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device) if (blockCount > 1) { - buffer.reset(new uint8_t[512 * blockCount]); - - for (unsigned i = 0; i < blockCount; ++i) - { - _cache->read(2 + i, buffer.get() + 512 * i); - } + buffer.reset(readDirectoryHeader()); } // now load up all the children. @@ -214,7 +210,7 @@ unsigned VolumeEntry::unlink(const char *name) unsigned index; - if (_device->readOnly()) return 0x2b; // WRITE-PROTECTED DISK + if (_device->readOnly()) return ProFUSE::drvrWrtProt; // WRITE-PROTECTED DISK for(index = 0; index < _fileCount; ++index) { @@ -226,23 +222,17 @@ unsigned VolumeEntry::unlink(const char *name) break; } } - if (index == _fileCount) return 0x46; // FILE NOT FOUND + if (index == _fileCount) return ProFUSE::fileNotFound; // FILE NOT FOUND _files.erase(_files.begin() + index); _fileCount--; // need to update the header blocks. - unsigned blockCount = blocks(); - ProFUSE::auto_array buffer(new uint8_t[512 * blockCount]); + ProFUSE::auto_array buffer(readDirectoryHeader()); + - // load up blocks. - // since entries span blocks, we can't do this via pointer. - for (unsigned i = 0; i < blockCount; ++i) - { - _cache->read(2 + i, buffer.get() + 512 * i); - } // update the filecount. - IOBuffer b(buffer.get(), 512 * blockCount); + IOBuffer b(buffer.get(), 512 * blocks()); writeDirectoryEntry(&b); // move up all the entries. @@ -252,10 +242,7 @@ unsigned VolumeEntry::unlink(const char *name) std::memset(buffer.get() + 0x1a + _fileCount * 0x1a, 0, 0x1a); // now write to disk. - for (unsigned i = 0; i < blockCount; ++i) - { - _cache->write(2 + i, buffer.get() + 512 * i); - } + writeDirectoryHeader(buffer.get()); _cache->sync(); return 0; @@ -303,17 +290,10 @@ unsigned VolumeEntry::krunch() // need to update the header blocks. - unsigned blockCount = blocks(); - ProFUSE::auto_array buffer(new uint8_t[512 * blockCount]); - IOBuffer b(buffer.get(), 512 * blockCount); - - // load up the directory blocks. - for (unsigned i = 0; i < blocks(); ++i) - { - _cache->read(2 + i, buffer.get() + 512 * i); - } - + ProFUSE::auto_array buffer(readDirectoryHeader()); + IOBuffer b(buffer.get(), 512 * blocks()); + prevBlock = lastBlock(); unsigned offset = 0; @@ -353,10 +333,7 @@ unsigned VolumeEntry::krunch() // now save the directory entries. // load up the directory blocks. - for (unsigned i = 0; i < blocks(); ++i) - { - _cache->write(2 + i, buffer.get() + 512 * i); - } + writeDirectoryHeader(buffer.get()); _cache->sync(); @@ -418,3 +395,23 @@ void VolumeEntry::writeDirectoryEntry(IOBuffer *b) } + +uint8_t *VolumeEntry::readDirectoryHeader() +{ + ProFUSE::auto_array buffer(new uint8_t[512 * blocks()]); + + for (unsigned i = 0; i < blocks(); ++i) + { + _cache->read(2 + i, buffer.get() + i * 512); + } + + return buffer.release(); +} + +void VolumeEntry::writeDirectoryHeader(uint8_t *buffer) +{ + for (unsigned i = 0; i < blocks(); ++i) + { + _cache->write(2 + i, buffer + 512 * i); + } +} From 1e09c72abad16358297bc7817617932cb959155e Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 22 May 2010 00:51:09 +0000 Subject: [PATCH 132/236] rename files git-svn-id: https://profuse.googlecode.com/svn/branches/v2@255 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/Entry.cpp | 1 + Pascal/File.h | 11 +++- Pascal/FileEntry.cpp | 18 +++++++ Pascal/VolumeEntry.cpp | 116 ++++++++++++++++++++++++++++++++++++----- 4 files changed, 132 insertions(+), 14 deletions(-) diff --git a/Pascal/Entry.cpp b/Pascal/Entry.cpp index 4943ab5..9195dae 100644 --- a/Pascal/Entry.cpp +++ b/Pascal/Entry.cpp @@ -65,6 +65,7 @@ Entry::Entry() _fileKind = 0; _inode = 0; _parent = NULL; + _address = NULL; } Entry::Entry(void *vp) diff --git a/Pascal/File.h b/Pascal/File.h index b093b3c..0e0b709 100644 --- a/Pascal/File.h +++ b/Pascal/File.h @@ -74,6 +74,7 @@ protected: private: friend class VolumeEntry; VolumeEntry *_parent; + unsigned _address; }; @@ -129,7 +130,12 @@ private: uint8_t *readDirectoryHeader(); - void writeDirectoryHeader(uint8_t *); + void writeDirectoryHeader(void *); + + uint8_t *readBlocks(unsigned startingBlock, unsigned count); + void writeBlocks(void *buffer, unsigned startingBlock, unsigned count); + + void writeEntry(FileEntry *e); unsigned _fileNameLength; @@ -179,6 +185,9 @@ class FileEntry : public Entry { private: friend class VolumeEntry; + void setName(const char *name); + + unsigned _status; unsigned _fileNameLength; diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index e02838b..06a5eca 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -77,6 +77,24 @@ FileEntry::~FileEntry() } +void FileEntry::setName(const char *name) +{ +#undef __METHOD__ +#define __METHOD__ "FileEntry::setName" + + unsigned length = ValidName(name); + + if (!length) + throw ProFUSE::ProDOSException(__METHOD__ ": Invalid file name.", ProFUSE::badPathSyntax); + + _fileNameLength = length; + for (unsigned i = 0; i < length; ++i) + _fileName[i] = std::toupper(name[i]); + + // not sure if this is a good idea or not. + //_modification = Date::Today(); +} + unsigned FileEntry::fileSize() { switch(fileKind()) diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index afe9f7c..a4b41d1 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -77,6 +77,8 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device) _cache = BlockCache::Create(device); _device = device; + _address = 512 * 2; + for (unsigned i = 2; i < 6; ++i) { @@ -84,7 +86,7 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device) } void *vp = _cache->acquire(2); - IOBuffer b(vp, 0x1a); + IOBuffer b(vp, 512); writeDirectoryEntry(&b); @@ -106,6 +108,8 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device) _device = device; _cache = BlockCache::Create(device); + _address = 512 * 2; + _cache->read(2, buffer.get()); init(buffer.get()); @@ -137,6 +141,7 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device) child->setInode(++_inodeGenerator); child->_parent = this; + child->_address = 512 * 2 + i * 0x1a; _files.push_back(child.release()); } } @@ -226,6 +231,13 @@ unsigned VolumeEntry::unlink(const char *name) _files.erase(_files.begin() + index); _fileCount--; + + // reset addresses. + for (unsigned i = index; i < _fileCount; ++i) + { + FileEntry *e = _files[i]; + e->_address -= 0x1a; + } // need to update the header blocks. ProFUSE::auto_array buffer(readDirectoryHeader()); @@ -249,6 +261,42 @@ unsigned VolumeEntry::unlink(const char *name) } +unsigned VolumeEntry::rename(const char *oldName, const char *newName) +{ + FileEntry *e; + + + // 1. verify old name exists. + e = fileByName(oldName); + if (!e) + return ProFUSE::fileNotFound; + + + // 2. verify new name is valid + if (!FileEntry::ValidName(newName)) + return ProFUSE::badPathSyntax; + + + // 3. verify new name does not exist. + + if (fileByName(newName)) + return ProFUSE::dupPathName; + + + // 4. set the name (throws on error, which won't happen since + // we already verified the name is valid. + e->setName(newName); + + + // 5. write to disk. + + writeEntry(e); + _cache->sync(); + + return 0; +} + + unsigned VolumeEntry::krunch() { @@ -398,20 +446,62 @@ void VolumeEntry::writeDirectoryEntry(IOBuffer *b) uint8_t *VolumeEntry::readDirectoryHeader() { - ProFUSE::auto_array buffer(new uint8_t[512 * blocks()]); - - for (unsigned i = 0; i < blocks(); ++i) - { - _cache->read(2 + i, buffer.get() + i * 512); - } - + return readBlocks(2, blocks()); +} + +void VolumeEntry::writeDirectoryHeader(void *buffer) +{ + writeBlocks(buffer, 2, blocks()); +} + + +uint8_t *VolumeEntry::readBlocks(unsigned startingBlock, unsigned count) +{ + ProFUSE::auto_array buffer(new uint8_t[512 * count]); + + for (unsigned i = 0; i < count; ++i) + _cache->read(startingBlock + i, buffer.get() + 512 * i); + return buffer.release(); } -void VolumeEntry::writeDirectoryHeader(uint8_t *buffer) + +void VolumeEntry::writeBlocks(void *buffer, unsigned startingBlock, unsigned count) { - for (unsigned i = 0; i < blocks(); ++i) - { - _cache->write(2 + i, buffer + 512 * i); - } + for (unsigned i = 0; i < count; ++i) + _cache->write(startingBlock + i, (uint8_t *)buffer + 512 * i); } + + +// does not sync. +void VolumeEntry::writeEntry(FileEntry *e) +{ + unsigned address = e->_address; + unsigned startBlock = address / 512; + unsigned endBlock = (address + 0x1a - 1) / 512; + unsigned offset = address % 512; + + if (startBlock == endBlock) + { + void *buffer = _cache->acquire(startBlock); + + IOBuffer b((uint8_t *)buffer + offset, 0x1a); + + e->writeDirectoryEntry(&b); + + _cache->release(startBlock, true); + } + else + { + // crosses page boundaries. + ProFUSE::auto_array buffer(readBlocks(startBlock, 2)); + + IOBuffer b(buffer.get() + offset, 0x1a); + + e->writeDirectoryEntry(&b); + + writeBlocks(buffer.get(), startBlock, 2); + } + + +} \ No newline at end of file From 77653743ec54bebfa69733cb88bc39bd006beb9f Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 22 May 2010 00:51:34 +0000 Subject: [PATCH 133/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@256 aa027e90-d47c-11dd-86d7-074df07e0730 --- ProFUSE/Exception.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ProFUSE/Exception.h b/ProFUSE/Exception.h index 043cd8c..b4ce9ab 100644 --- a/ProFUSE/Exception.h +++ b/ProFUSE/Exception.h @@ -51,6 +51,7 @@ enum outOfMem = 0x54, dupVolume = 0x57, notBlockDev = 0x58, + invalidLevel = 0x59, damagedBitMap = 0x5a, badPathNames = 0x5b, notSystemFile = 0x5c, From defd397d1b8749d71d35a34e5e438dd7c771cf24 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 22 May 2010 00:51:55 +0000 Subject: [PATCH 134/236] fix typo git-svn-id: https://profuse.googlecode.com/svn/branches/v2@257 aa027e90-d47c-11dd-86d7-074df07e0730 --- apfm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apfm.cpp b/apfm.cpp index 33b222e..87adbd2 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -162,7 +162,7 @@ int action_ls(int argc, char **argv, Pascal::VolumeEntry *volume) std::fprintf(stdout, - "%u/%u files, " + "%u/%u files , " "%u blocks used, " "%u unused, " "%u in largest\n", From 4a98605123cc456ac7cac5260dd8b7d4a397846d Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 22 May 2010 16:10:59 +0000 Subject: [PATCH 135/236] fix null string error git-svn-id: https://profuse.googlecode.com/svn/branches/v2@258 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/BlockDevice.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index 4a326b1..e583165 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -34,6 +34,13 @@ unsigned BlockDevice::ImageType(const char *type, unsigned defv) if (type == 0 || *type == 0) return defv; + // type could be a path, eg images/file, disk.images/file + + // unix-specifix. + // basename alters the input string + tmp = std::strrchr(type, '/'); + if (tmp) type = tmp + 1; + // type could be a filename, in which case we check the extension. tmp = std::strrchr(type, '.'); if (tmp) type = tmp + 1; @@ -65,7 +72,7 @@ unsigned BlockDevice::ImageType(const char *type, unsigned defv) // not supported yet. - if (::strcasecmp(tmp, "sdk") == 0) + if (::strcasecmp(type, "sdk") == 0) return 'SDK_'; return defv; From ef4f906d702a56788ab5178ed7bf176965e926fb Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 22 May 2010 16:11:41 +0000 Subject: [PATCH 136/236] more block checking git-svn-id: https://profuse.googlecode.com/svn/branches/v2@259 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/MappedBlockCache.cpp | 13 +++++++++++++ Cache/MappedBlockCache.h | 8 ++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Cache/MappedBlockCache.cpp b/Cache/MappedBlockCache.cpp index ba17efe..1d1be58 100644 --- a/Cache/MappedBlockCache.cpp +++ b/Cache/MappedBlockCache.cpp @@ -64,6 +64,12 @@ void MappedBlockCache::release(unsigned block, int flags) void MappedBlockCache::write(unsigned block, const void *vp) { +#undef __METHOD__ +#define __METHOD__ "MappedBlockCache::write" + + if (block >= blocks()) + throw Exception(__METHOD__ ": Invalid block."); + _dirty = true; std::memcpy(_data + block * 512, vp, 512); } @@ -71,6 +77,13 @@ void MappedBlockCache::write(unsigned block, const void *vp) void MappedBlockCache::zeroBlock(unsigned block) { +#undef __METHOD__ +#define __METHOD__ "MappedBlockCache::zeroBlock" + + if (block >= blocks()) + throw Exception(__METHOD__ ": Invalid block."); + + _dirty = true; std::memset(_data + block * 512, 0, 512); } diff --git a/Cache/MappedBlockCache.h b/Cache/MappedBlockCache.h index 951a974..a3402ff 100644 --- a/Cache/MappedBlockCache.h +++ b/Cache/MappedBlockCache.h @@ -22,11 +22,11 @@ class MappedBlockCache : public BlockCache { virtual void markDirty(unsigned block); private: - void sync(unsigned block); + + void sync(unsigned block); - uint8_t *_data; - bool _dirty; - + uint8_t *_data; + bool _dirty; }; } // namespace From 2e4b2961ebf4750766d2e73c17d2b5584bef1006 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 22 May 2010 16:11:57 +0000 Subject: [PATCH 137/236] slight sanity checking git-svn-id: https://profuse.googlecode.com/svn/branches/v2@260 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/VolumeEntry.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index a4b41d1..f8c27b2 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -176,11 +176,21 @@ VolumeEntry::~VolumeEntry() void VolumeEntry::init(void *vp) { +#undef __METHOD__ +#define __METHOD__ "VolumeEntry::init" + Entry::init(vp); _fileNameLength = Read8(vp, 6); // verify filenamelength <= 7 + if (_fileNameLength > 7) + throw new ProFUSE::Exception(__METHOD__ ": invalid name length"); + // verify fileKind == 0 + // verify _fileCount reasonable + // verify _lastVolumeBlock reasonable + // verify _blocks reasonable. + std::memcpy(_fileName, 7 + (uint8_t *)vp, _fileNameLength); From 7b80e2e089bcf82f825ae9070109f939ea527cba Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 22 May 2010 17:36:47 +0000 Subject: [PATCH 138/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@261 aa027e90-d47c-11dd-86d7-074df07e0730 --- fuse_pascal.cpp | 57 +++++++++++++++++++----------------------------- newfs_pascal.cpp | 6 +++++ 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/fuse_pascal.cpp b/fuse_pascal.cpp index aaa8e9a..c5aebbf 100644 --- a/fuse_pascal.cpp +++ b/fuse_pascal.cpp @@ -22,10 +22,8 @@ #include #include -#include -#include -Pascal::VolumeEntry *fVolume = NULL; + std::string fDiskImage; @@ -42,6 +40,8 @@ void usage() " -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" " do DOS Order Disk Image\n" " po ProDOS Order Disk Image (default)\n" " -o opt1,opt2... other mount parameters.\n" @@ -163,6 +163,10 @@ int main(int argc, char **argv) int foreground = false; int multithread = false; + + + std::auto_ptr volume; + init_ops(&pascal_ops); @@ -180,44 +184,30 @@ int main(int argc, char **argv) // default prodos-order disk image. if (options.format) { - format = Device::DiskImage::ImageType(options.format); + format = Device::BlockDevice::ImageType(options.format); if (!format) std::fprintf(stderr, "Warning: Unknown image type ``%s''\n", options.format); } - if (!format) - format = Device::DiskImage::ImageType(fDiskImage.c_str(), 'PO__'); - + bool readOnly = true; - try { + try + { + std::auto_ptr device; + + device.reset( Device::BlockDevice::Open(fDiskImage.c_str(), readOnly, format) ); + - switch(format) + if (!device.get()) { - case 'DC42': - device.reset(new Device::DiskCopy42Image(fDiskImage.c_str(), readOnly)); - break; - - case 'PO__': - device.reset(new Device::ProDOSOrderDiskImage(fDiskImage.c_str(), readOnly)); - break; - - case 'DO__': - device.reset(new Device::DOSOrderDiskImage(fDiskImage.c_str(), readOnly)); - break; - - - default: std::fprintf(stderr, "Error: Unknown or unsupported device type.\n"); exit(1); } - - fVolume = new Pascal::VolumeEntry(device.get()); + volume.reset( new Pascal::VolumeEntry(device.get()) ); device.release(); - - } catch (ProFUSE::POSIXException &e) { @@ -237,7 +227,7 @@ int main(int argc, char **argv) { // Macfuse supports custom volume names (displayed in Finder) std::string str("-ovolname="); - str += fVolume->name(); + str += volume->name(); fuse_opt_add_arg(&args, str.c_str()); // 512 byte blocksize. @@ -266,7 +256,7 @@ int main(int argc, char **argv) if (mountpoint == NULL || *mountpoint == 0) { - if (make_mount_dir(fVolume->name(), mountPath)) + if (make_mount_dir(volume->name(), mountPath)) mountpoint = (char *)mountPath.c_str(); } @@ -277,13 +267,13 @@ int main(int argc, char **argv) { struct fuse_session* se; - std::printf("Mounting ``%s'' on ``%s''\n", fVolume->name(), mountpoint); + std::printf("Mounting ``%s'' on ``%s''\n", volume->name(), mountpoint); - se = fuse_lowlevel_new(&args, &pascal_ops, sizeof(pascal_ops), fVolume); + se = fuse_lowlevel_new(&args, &pascal_ops, sizeof(pascal_ops), volume.get()); if (se) do { - //foreground = 1; - //multithread = 0; + foreground = 1; + multithread = 0; err = fuse_daemonize(foreground); // todo if (err < 0 ) break; @@ -307,7 +297,6 @@ int main(int argc, char **argv) fuse_opt_free_args(&args); - delete fVolume; #ifdef __APPLE__ diff --git a/newfs_pascal.cpp b/newfs_pascal.cpp index f2722b1..72afee5 100644 --- a/newfs_pascal.cpp +++ b/newfs_pascal.cpp @@ -215,6 +215,12 @@ int main(int argc, char **argv) device.reset( RawDevice::Open(fname, false) ); blocks = device->blocks(); rawDevice = true; + + if (blocks > 0xffff) + { + std::fprintf(stderr, "Error: device is too large.\n"); + return 0x5a; + } } else From 8acc47bb87196a48c8f9517396841abf11b13642 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 22 May 2010 18:28:46 +0000 Subject: [PATCH 139/236] fix nasty bug git-svn-id: https://profuse.googlecode.com/svn/branches/v2@262 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/ConcreteBlockCache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cache/ConcreteBlockCache.cpp b/Cache/ConcreteBlockCache.cpp index a966117..5bd77b3 100644 --- a/Cache/ConcreteBlockCache.cpp +++ b/Cache/ConcreteBlockCache.cpp @@ -248,7 +248,7 @@ void ConcreteBlockCache::removeEntry(unsigned block) for(;;) { prev = e; - e = e->next; + e = e->nextHash; if (!e) break; if (e->block == block) From 06166c2d7252252be24d5261d76d475ce1b5356f Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 22 May 2010 18:28:52 +0000 Subject: [PATCH 140/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@263 aa027e90-d47c-11dd-86d7-074df07e0730 --- fuse_pascal_ops.cpp | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/fuse_pascal_ops.cpp b/fuse_pascal_ops.cpp index 40bf5b0..9721747 100644 --- a/fuse_pascal_ops.cpp +++ b/fuse_pascal_ops.cpp @@ -42,6 +42,9 @@ } +#define DEBUGNAME() \ + if (0) { std::fprintf(stderr, "%s\n", __func__); } + using namespace Pascal; @@ -52,6 +55,8 @@ static FileEntry *findChild(VolumeEntry *volume, unsigned inode) for (unsigned i = 0, l = volume->fileCount(); i < l; ++i) { FileEntry *child = volume->fileAtIndex(i); + if (!child) continue; + if (inode == child->inode()) return child; } @@ -60,22 +65,25 @@ static FileEntry *findChild(VolumeEntry *volume, unsigned inode) static void pascal_init(void *userdata, struct fuse_conn_info *conn) { - //std::printf("pascal_init\n"); + 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) { - volume->fileAtIndex(i)->fileSize(); + FileEntry *child = volume->fileAtIndex(i); + child->fileSize(); } } static void pascal_destroy(void *userdata) { - //std::printf("pascal_destroy\n"); + DEBUGNAME() // nop } @@ -87,7 +95,7 @@ static void pascal_destroy(void *userdata) static void pascal_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) { - //std::printf("pascal_listxattr\n"); + DEBUGNAME() VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); FileEntry *file; @@ -130,7 +138,7 @@ static void pascal_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) static void pascal_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, size_t size) { - //std::printf("pascal_getxattr\n"); + DEBUGNAME() VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); @@ -177,6 +185,8 @@ static void pascal_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, si // 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); } @@ -185,8 +195,7 @@ static void pascal_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, si static void pascal_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { - //std::printf("pascal_opendir\n"); - + DEBUGNAME() ERROR(ino != 1, ENOTDIR) @@ -197,14 +206,14 @@ static void pascal_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info static void pascal_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { - //std::printf("pascal_releasedir\n"); + 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) { - //std::printf("pascal_readdir %u, %u, %u\n", (unsigned)ino, (unsigned)size, (unsigned)off); + DEBUGNAME() VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); ProFUSE::auto_array buffer(new uint8_t[size]); @@ -283,6 +292,8 @@ static void pascal_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t of static void stat(FileEntry *file, struct stat *st) { + DEBUGNAME() + std::memset(st, 0, sizeof(struct stat)); time_t t = file->modification(); @@ -302,6 +313,8 @@ static void stat(FileEntry *file, struct stat *st) static void stat(VolumeEntry *volume, struct stat *st) { + DEBUGNAME() + std::memset(st, 0, sizeof(struct stat)); time_t t = volume->lastBoot(); @@ -321,7 +334,7 @@ static void stat(VolumeEntry *volume, struct stat *st) static void pascal_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) { - //std::printf("pascal_lookup %u %s\n", (unsigned)parent, name); + DEBUGNAME() VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); struct fuse_entry_param entry; @@ -354,7 +367,7 @@ static void pascal_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) static void pascal_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { - //std::printf("pascal_getattr %u\n", (unsigned)ino); + DEBUGNAME() struct stat st; VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); @@ -370,7 +383,7 @@ static void pascal_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info file = findChild(volume, ino); ERROR(file == NULL, ENOENT) - printf("\t%s\n", file->name()); + //printf("\t%s\n", file->name()); stat(file, &st); fuse_reply_attr(req, &st, 0.0); @@ -382,7 +395,7 @@ static void pascal_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info static void pascal_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { - //std::printf("pascal_open\n"); + DEBUGNAME() VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); FileEntry *file; @@ -403,7 +416,7 @@ static void pascal_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *f static void pascal_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { - //std::printf("pascal_release\n"); + DEBUGNAME() fuse_reply_err(req, 0); } @@ -411,7 +424,8 @@ static void pascal_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info static void pascal_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) { - //std::printf("pascal_read %u %u %u\n", (unsigned)ino, (unsigned)size, (unsigned)off); + DEBUGNAME() + //VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); FileEntry *file = (FileEntry *)fi->fh; @@ -442,6 +456,7 @@ static void pascal_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, void init_ops(fuse_lowlevel_ops *ops) { + DEBUGNAME() std::memset(ops, 0, sizeof(fuse_lowlevel_ops)); From 624af11ca193240a866d06c6329da8297f085533 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 23 May 2010 18:35:23 +0000 Subject: [PATCH 141/236] fix createBlockCache definition git-svn-id: https://profuse.googlecode.com/svn/branches/v2@264 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/DiskImage.cpp | 2 +- Device/DiskImage.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Device/DiskImage.cpp b/Device/DiskImage.cpp index 3820534..1c8d0cf 100644 --- a/Device/DiskImage.cpp +++ b/Device/DiskImage.cpp @@ -145,7 +145,7 @@ void ProDOSOrderDiskImage::Validate(MappedFile *f) } -BlockCache *ProDOSOrderDiskImage::createBlockCache(unsigned size) +BlockCache *ProDOSOrderDiskImage::createBlockCache() { return new MappedBlockCache(this, address()); } diff --git a/Device/DiskImage.h b/Device/DiskImage.h index 2132c37..9bd87d9 100644 --- a/Device/DiskImage.h +++ b/Device/DiskImage.h @@ -62,7 +62,7 @@ public: static ProDOSOrderDiskImage *Open(MappedFile *); - virtual BlockCache *createBlockCache(unsigned size); + virtual BlockCache *createBlockCache(); private: ProDOSOrderDiskImage(const char *name, bool readOnly); From 5f252e4dacd7d6c7c71e60b6defaa1741fd8dc36 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 23 May 2010 21:27:11 +0000 Subject: [PATCH 142/236] nibblizing git-svn-id: https://profuse.googlecode.com/svn/branches/v2@268 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/Adaptor.cpp | 389 +++++++++++++++++++++++++++++++++++++++++++++ Device/Adaptor.h | 33 ++++ 2 files changed, 422 insertions(+) diff --git a/Device/Adaptor.cpp b/Device/Adaptor.cpp index 9ffe284..bbef6ec 100644 --- a/Device/Adaptor.cpp +++ b/Device/Adaptor.cpp @@ -4,6 +4,8 @@ #include #include +#include + using namespace Device; @@ -73,5 +75,392 @@ void DOAdaptor::writeBlock(unsigned block, const void *bp) +#pragma mark - +#pragma mark NibbleAdaptor + + +uint8_t NibbleAdaptor::decode44(uint8_t x, uint8_t y) +{ + return ((x << 1) | 0x01) & y; +} + +std::pair NibbleAdaptor::encode44(uint8_t val) +{ + uint8_t x = (val >> 1) | 0xaa; + uint8_t y = val | 0xaa; + + return std::make_pair(x,y); +} + +uint8_t NibbleAdaptor::encode62(uint8_t val) +{ +#undef __METHOD__ +#define __METHOD__ "NibbleAdaptor::encode62" + + static uint8_t table[64] = { + 0x96, 0x97, 0x9a, 0x9b, 0x9d, 0x9e, 0x9f, 0xa6, + 0xa7, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb2, 0xb3, + + 0xb4, 0xb5, 0xb6, 0xb7, 0xb9, 0xba, 0xbb, 0xbc, + 0xbd, 0xbe, 0xbf, 0xcb, 0xcd, 0xce, 0xcf, 0xd3, + + 0xd6, 0xd7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, + 0xdf, 0xe5, 0xe6, 0xe7, 0xe9, 0xea, 0xeb, 0xec, + + 0xed, 0xee, 0xef, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, + 0xf7, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }; + + if (val > 0x3f) + throw ProFUSE::Exception(__METHOD__ ": Invalid 6-2 value."); + + return table[val]; +} + + +uint8_t NibbleAdaptor::decode62(uint8_t val) +{ +#undef __METHOD__ +#define __METHOD__ "decode62" + + // auto-generated via perl. + static uint8_t table[] = { + -1, -1, -1, -1, -1, -1, 0, 1, -1, -1, 2, 3, -1, 4, 5, 6, + -1, -1, -1, -1, -1, -1, 7, 8, -1, -1, -1, 9, 10, 11, 12, 13, + -1, -1, 14, 15, 16, 17, 18, 19, -1, 20, 21, 22, 23, 24, 25, 26, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, 28, 29, 30, + -1, -1, -1, 31, -1, -1, 32, 33, -1, 34, 35, 36, 37, 38, 39, 40, + -1, -1, -1, -1, -1, 41, 42, 43, -1, 44, 45, 46, 47, 48, 49, 50, + -1, -1, 51, 52, 53, 54, 55, 56, -1, 57, 58, 59, 60, 61, 62, 63 + }; + + if ((val < 0x90) || (table[val - 0x90] == 0xff)) + throw ProFUSE::Exception(__METHOD__ ": Invalid 6-2 encoding."); + + return table[val - 0x90]; +} + + + +static int FindByte(void *address, uint8_t c, unsigned length, unsigned offset = 0) +{ + + for (unsigned i = offset; i < length; ++i) + { + if ( *((uint8_t *)address) == c) return i; + } + + return -1; +} + +static void LoadBytes(void *src, unsigned length, unsigned offset, void *dest, unsigned count) +{ + // load with wrap-around. + + if (offset + count < length) + { + std::memcpy(dest, (uint8_t *)src + offset, count); + return; + } + + unsigned x = length - offset; + std::memcpy(dest, (uint8_t *)src + offset, x); + + std::memcpy((uint8_t *)dest + x, src, count - x); +} + + + +class CircleBuffer { + +public: + + CircleBuffer(void *address, unsigned length) + { + _address = (uint8_t *)address; + _length = length; + } + + uint8_t operator[](unsigned i) const + { + if (i >= _length) i %= _length; + return _address[i]; + } + + uint8_t& operator[](unsigned i) + { + if (i >= _length) i %= _length; + return _address[i]; + } + +private: + uint8_t *_address; + unsigned _length; + +}; + +/* + * Address Field: + * prologue volume track sector checksum epilogue + * D5 AA 96 XX YY XX YY XX YY XX YY DE AA EB + */ + +/* + * Data Field: + * prologue user data checksum epilogue + * D5 AA AD [6+2 encoded] XX DE AA EB + */ + + +/* + * 0x00 + *------------------------ + * A7 A6 A5 A4 A3 A2 A1 A0 + * B7 B6 B5 B4 B3 B2 B1 B0 + * C7 C6 C5 C4 C3 C2 C1 C0 + * D7 D6 D5 D4 D3 D2 D1 D0 + * E7 E6 E5 E4 E3 E2 E1 E0 + * F7 F6 F5 F4 F3 F2 F1 F0 + * ... + *------------------------ + * 0x100 + * || + * \/ + * 0x00 + * ----------------------- + * 0 0 A7 A6 A5 A4 A3 A2 + * 0 0 B7 B6 B5 B4 B3 B2 + * 0 0 C7 C6 C5 C4 C3 C2 + * 0 0 D7 D6 D5 D4 D3 D2 + * 0 0 E7 E6 E5 E4 E3 E2 + * 0 0 F7 F6 F5 F4 F3 F2 + * ... + * 0x100 (256): + * ----------------------- + * ... + * 0 0 x x x x F0 F1 + * 0 0 x x x x E0 E1 + * 0 0 x x x x D0 D1 + * 0 0 x x x x C0 C1 + * 0 0 x x x x B0 B1 + * 0 0 x x x x A0 A1 + * ----------------------- + * 0x156 (342) + * + * + * + * + * + * + * + */ + + +NibbleAdaptor::NibbleAdaptor(void *address, unsigned length) +{ +#undef __METHOD__ +#define __METHOD__ "NibbleAdaptor::NibbleAdaptor" + + _address = (uint8_t *)address; + _length = length; + + + // build a map of track/sectors. + + unsigned state = 0; + + + _index.resize(35 * 16, -1); + + int offset = 0; + + unsigned track = 0; + unsigned sector = 0; + unsigned volume = 0; + unsigned checksum = 0; + + + CircleBuffer buffer(_address, _length); + for (;;) + { + + offset = FindByte(address, 0xd5, length, offset); + if (offset < 0) break; + + if (buffer[offset + 1] == 0xaa && buffer[offset + 2] == 0x96) + { + state = 1; + + volume = decode44(buffer[offset + 3], buffer[offset + 4]); + track = decode44(buffer[offset + 5], buffer[offset + 6]); + sector = decode44(buffer[offset + 7], buffer[offset + 8]); + checksum = decode44(buffer[offset + 9], buffer[offset + 10]); + + if (volume ^ track ^ sector ^ checksum) + throw ProFUSE::Exception(__METHOD__ ": Invalid address checksum."); + + if (track > 35 || sector > 16) + throw ProFUSE::Exception(__METHOD__ ": Invalid track/sector."); + + // epilogue is not always de aa eb + continue; + + } + + if (buffer[offset + 1] == 0xaa && buffer[offset + 2] == 0xad && state == 1) + { + _index[track * 16 + sector] = (offset + 3) % _length; + + state = 0; + continue; + } + + // ???? + + } + + // possible wraparound. + if (state == 1) + { + offset = FindByte(address, 0xd5, length, 0); + + if (offset >= 0) + { + + if (buffer[offset + 1] == 0xaa && buffer[offset + 2] == 0xad) + { + _index[track * 16 + sector] = (offset + 3) % _length; + } + } + } + + + // now check _index for offset = -1, which means the sector/track wasn't found. + + for (std::vector::iterator iter = _index.begin(); iter != _index.end(); ++iter) + { + if (*iter == -1) + throw ProFUSE::Exception(__METHOD__ ": Sector missing."); + } + +} + + + +void NibbleAdaptor::readTrackSector(TrackSector ts, void *bp) +{ +#undef __METHOD__ +#define __METHOD__ "NibbleAdaptor::readTrackSector" + + if (ts.track > 35 || ts.sector > 16) + throw ProFUSE::Exception(__METHOD__ ": Invalid track/sector."); + + + CircleBuffer buffer(_address, _length); + uint8_t bits[86 * 3]; + + uint8_t checksum = 0; + + + unsigned offset = _index[ts.track * 16 + ts.sector]; + + + // first 86 bytes are in the auxbuffer, backwards. + for (unsigned i = 0; i < 86; ++i) + { + uint8_t x = buffer[offset + i]; + x = decode62(x); + + checksum ^= x; + + uint8_t y = checksum; + + for (unsigned j = 0; j < 3; ++i) + { + bits[i + j * 86] = ((y & 0x01) << 1) | ((y & 0x02) >> 1); + y >>= 2; + } + } + + for (unsigned i = 0; i < 256; ++i) + { + uint8_t x = buffer[offset + 86 + i]; + x = decode62(x); + + checksum ^= x; + + uint8_t y = (checksum << 2) | bits[i]; + + + + ((uint8_t *)bp)[i] = y; + } + + if (checksum != buffer[342]) + throw ProFUSE::Exception(__METHOD__ ": Invalid field checksum."); + +} + +void NibbleAdaptor::writeTrackSector(TrackSector ts, const void *bp) +{ +#undef __METHOD__ +#define __METHOD__ "NibbleAdaptor::readTrackSector" + + if (ts.track > 35 || ts.sector > 16) + throw ProFUSE::Exception(__METHOD__ ": Invalid track/sector."); + + uint8_t auxBuffer[86]; + uint8_t checksum = 0; + + // create the aux buffer. + + std::memset(auxBuffer, 0, sizeof(auxBuffer)); + + for (unsigned i = 0, j = 86, shift = 0; i < 256; ++i) + { + uint8_t x = ((const uint8_t *)bp)[i]; + + // grab the bottom 2 bytes and reverse them. + uint8_t y = ((x & 0x01) << 1) | ((x & 0x02) >> 1); + + auxBuffer[--j] |= (y << shift); + + if (j == 0) + { + j = 86; + shift += 2; + } + } + + unsigned offset = _index[ts.track * 16 + ts.sector]; + + CircleBuffer buffer(_address, _length); + // create the checksum while writing to disk.. + + // aux buffer + for (unsigned i = 0; i < 86; ++i) + { + uint8_t x = auxBuffer[i]; + + buffer[offset + i] = encode62(x ^ checksum); + + checksum = x; + } + + for (unsigned i = 0; i < 256; ++i) + { + uint8_t x = ((const uint8_t *)bp)[i]; + x >>= 2; + + buffer[offset + 86 + i] = encode62(x ^ checksum); + + checksum = x; + } + + + + buffer[offset + 342] = checksum; +} + diff --git a/Device/Adaptor.h b/Device/Adaptor.h index 311077f..e76f5d3 100644 --- a/Device/Adaptor.h +++ b/Device/Adaptor.h @@ -1,8 +1,13 @@ #ifndef __DEVICE_ADAPTOR_H__ #define __DEVICE_ADAPTOR_H__ +#include +#include + #include +#include + namespace Device { class Adaptor @@ -38,6 +43,34 @@ namespace Device { // TODO -- nibble adaptor. + + class NibbleAdaptor : public Adaptor + { + public: + + NibbleAdaptor(void *address, unsigned length); + virtual ~NibbleAdaptor(); + + virtual void readBlock(unsigned block, void *bp); + virtual void writeBlock(unsigned block, const void *bp); + + + virtual void readTrackSector(TrackSector ts, void *bp); + virtual void writeTrackSector(TrackSector ts, const void *bp); + + static std::pairencode44(uint8_t); + static uint8_t decode44(uint8_t, uint8_t); + + static uint8_t encode62(uint8_t); + static uint8_t decode62(uint8_t); + + + private: + uint8_t *_address; + unsigned _length; + + std::vector _index; + }; } From d1cf4ebfffbaba697b7f49e83acc5ca660c5c8d0 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 24 May 2010 11:37:48 +0000 Subject: [PATCH 143/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@269 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/Adaptor.cpp | 187 +++++++++++++++++++------------------------ Device/Adaptor.h | 5 +- Pascal/FileEntry.cpp | 117 +++++++++------------------ 3 files changed, 125 insertions(+), 184 deletions(-) diff --git a/Device/Adaptor.cpp b/Device/Adaptor.cpp index bbef6ec..39daaf1 100644 --- a/Device/Adaptor.cpp +++ b/Device/Adaptor.cpp @@ -78,6 +78,33 @@ void DOAdaptor::writeBlock(unsigned block, const void *bp) #pragma mark - #pragma mark NibbleAdaptor +class CircleBuffer { + +public: + + CircleBuffer(void *address, unsigned length) + { + _address = (uint8_t *)address; + _length = length; + } + + uint8_t operator[](unsigned i) const + { + if (i >= _length) i %= _length; + return _address[i]; + } + + uint8_t& operator[](unsigned i) + { + if (i >= _length) i %= _length; + return _address[i]; + } + +private: + uint8_t *_address; + unsigned _length; + +}; @@ -149,57 +176,13 @@ static int FindByte(void *address, uint8_t c, unsigned length, unsigned offset = for (unsigned i = offset; i < length; ++i) { - if ( *((uint8_t *)address) == c) return i; + if ( ((uint8_t *)address)[i] == c) return i; } return -1; } -static void LoadBytes(void *src, unsigned length, unsigned offset, void *dest, unsigned count) -{ - // load with wrap-around. - if (offset + count < length) - { - std::memcpy(dest, (uint8_t *)src + offset, count); - return; - } - - unsigned x = length - offset; - std::memcpy(dest, (uint8_t *)src + offset, x); - - std::memcpy((uint8_t *)dest + x, src, count - x); -} - - - -class CircleBuffer { - -public: - - CircleBuffer(void *address, unsigned length) - { - _address = (uint8_t *)address; - _length = length; - } - - uint8_t operator[](unsigned i) const - { - if (i >= _length) i %= _length; - return _address[i]; - } - - uint8_t& operator[](unsigned i) - { - if (i >= _length) i %= _length; - return _address[i]; - } - -private: - uint8_t *_address; - unsigned _length; - -}; /* * Address Field: @@ -214,49 +197,6 @@ private: */ -/* - * 0x00 - *------------------------ - * A7 A6 A5 A4 A3 A2 A1 A0 - * B7 B6 B5 B4 B3 B2 B1 B0 - * C7 C6 C5 C4 C3 C2 C1 C0 - * D7 D6 D5 D4 D3 D2 D1 D0 - * E7 E6 E5 E4 E3 E2 E1 E0 - * F7 F6 F5 F4 F3 F2 F1 F0 - * ... - *------------------------ - * 0x100 - * || - * \/ - * 0x00 - * ----------------------- - * 0 0 A7 A6 A5 A4 A3 A2 - * 0 0 B7 B6 B5 B4 B3 B2 - * 0 0 C7 C6 C5 C4 C3 C2 - * 0 0 D7 D6 D5 D4 D3 D2 - * 0 0 E7 E6 E5 E4 E3 E2 - * 0 0 F7 F6 F5 F4 F3 F2 - * ... - * 0x100 (256): - * ----------------------- - * ... - * 0 0 x x x x F0 F1 - * 0 0 x x x x E0 E1 - * 0 0 x x x x D0 D1 - * 0 0 x x x x C0 C1 - * 0 0 x x x x B0 B1 - * 0 0 x x x x A0 A1 - * ----------------------- - * 0x156 (342) - * - * - * - * - * - * - * - */ - NibbleAdaptor::NibbleAdaptor(void *address, unsigned length) { @@ -289,10 +229,8 @@ NibbleAdaptor::NibbleAdaptor(void *address, unsigned length) offset = FindByte(address, 0xd5, length, offset); if (offset < 0) break; - if (buffer[offset + 1] == 0xaa && buffer[offset + 2] == 0x96) - { - state = 1; - + if (buffer[offset + 1] == 0xaa && buffer[offset + 2] == 0x96 && buffer[offset + 11] == 0xde && buffer[offset + 12] == 0xaa) + { volume = decode44(buffer[offset + 3], buffer[offset + 4]); track = decode44(buffer[offset + 5], buffer[offset + 6]); sector = decode44(buffer[offset + 7], buffer[offset + 8]); @@ -304,7 +242,8 @@ NibbleAdaptor::NibbleAdaptor(void *address, unsigned length) if (track > 35 || sector > 16) throw ProFUSE::Exception(__METHOD__ ": Invalid track/sector."); - // epilogue is not always de aa eb + offset += 3 + 8 + 3; + state = 1; continue; } @@ -313,10 +252,12 @@ NibbleAdaptor::NibbleAdaptor(void *address, unsigned length) { _index[track * 16 + sector] = (offset + 3) % _length; + offset += 3 + 342 + 1 + 3; state = 0; continue; } + offset++; //??? // ???? } @@ -347,7 +288,31 @@ NibbleAdaptor::NibbleAdaptor(void *address, unsigned length) } +NibbleAdaptor::~NibbleAdaptor() +{ +} +void NibbleAdaptor::readBlock(unsigned block, void *bp) +{ + + unsigned track = (block & ~0x07) << 9; + unsigned sector = (block & 0x07) << 1; + + readTrackSector(TrackSector(track, sector), bp); + readTrackSector(TrackSector(track, sector + 1), (uint8_t *)bp + 256); + + +} + +void NibbleAdaptor::writeBlock(unsigned block, const void *bp) +{ + unsigned track = (block & ~0x07) << 9; + unsigned sector = (block & 0x07) << 1; + + writeTrackSector(TrackSector(track, sector), bp); + writeTrackSector(TrackSector(track, sector + 1), (const uint8_t *)bp + 256); + +} void NibbleAdaptor::readTrackSector(TrackSector ts, void *bp) { @@ -368,25 +333,33 @@ void NibbleAdaptor::readTrackSector(TrackSector ts, void *bp) // first 86 bytes are in the auxbuffer, backwards. + unsigned index = offset; for (unsigned i = 0; i < 86; ++i) { - uint8_t x = buffer[offset + i]; + uint8_t x = buffer[index++]; x = decode62(x); checksum ^= x; uint8_t y = checksum; - for (unsigned j = 0; j < 3; ++i) + /* + for (unsigned j = 0; j < 3; ++j) { - bits[i + j * 86] = ((y & 0x01) << 1) | ((y & 0x02) >> 1); + //bits[i + j * 86] = ((y & 0x01) << 1) | ((y & 0x02) >> 1); + bits[i + j * 86] = "\x00\x01\x02\x03"[y & 0x03]; y >>= 2; } + */ + bits[i + 86 * 0] = "\x00\x02\x01\x03"[y & 0x03]; + bits[i + 86 * 1] = "\x00\x02\x01\x03"[(y >> 2) & 0x03]; + bits[i + 86 * 2] = "\x00\x02\x01\x03"[(y >> 4) & 0x03]; + } for (unsigned i = 0; i < 256; ++i) { - uint8_t x = buffer[offset + 86 + i]; + uint8_t x = buffer[index++]; x = decode62(x); checksum ^= x; @@ -398,15 +371,16 @@ void NibbleAdaptor::readTrackSector(TrackSector ts, void *bp) ((uint8_t *)bp)[i] = y; } - if (checksum != buffer[342]) - throw ProFUSE::Exception(__METHOD__ ": Invalid field checksum."); + if (checksum != decode62(buffer[index++])) + std::fprintf(stderr, "Invalid checksum on track %u, sector %u\n", ts.track, ts.sector); + //throw ProFUSE::Exception(__METHOD__ ": Invalid field checksum."); } void NibbleAdaptor::writeTrackSector(TrackSector ts, const void *bp) { #undef __METHOD__ -#define __METHOD__ "NibbleAdaptor::readTrackSector" +#define __METHOD__ "NibbleAdaptor::writeTrackSector" if (ts.track > 35 || ts.sector > 16) throw ProFUSE::Exception(__METHOD__ ": Invalid track/sector."); @@ -418,18 +392,19 @@ void NibbleAdaptor::writeTrackSector(TrackSector ts, const void *bp) std::memset(auxBuffer, 0, sizeof(auxBuffer)); - for (unsigned i = 0, j = 86, shift = 0; i < 256; ++i) + for (unsigned i = 0, j = 0, shift = 0; i < 256; ++i) { uint8_t x = ((const uint8_t *)bp)[i]; // grab the bottom 2 bytes and reverse them. - uint8_t y = ((x & 0x01) << 1) | ((x & 0x02) >> 1); + //uint8_t y = ((x & 0x01) << 1) | ((x & 0x02) >> 1); + uint8_t y = "\x00\x02\x01\x03"[x & 0x03]; - auxBuffer[--j] |= (y << shift); + auxBuffer[j++] |= (y << shift); - if (j == 0) + if (j == 86) { - j = 86; + j = 0; shift += 2; } } @@ -461,6 +436,6 @@ void NibbleAdaptor::writeTrackSector(TrackSector ts, const void *bp) - buffer[offset + 342] = checksum; + buffer[offset + 342] = encode62(checksum); } diff --git a/Device/Adaptor.h b/Device/Adaptor.h index e76f5d3..00617ed 100644 --- a/Device/Adaptor.h +++ b/Device/Adaptor.h @@ -35,10 +35,13 @@ namespace Device { DOAdaptor(void *address); virtual void readBlock(unsigned block, void *bp); virtual void writeBlock(unsigned block, const void *bp); + + + static unsigned Map[]; + private: uint8_t *_address; - static unsigned Map[]; }; // TODO -- nibble adaptor. diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index 06a5eca..6e6f773 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -367,93 +367,56 @@ void FileEntry::textInit() /* * compress white space into a dle. * returns true if altered. - * + * nb -- only leading white space is compressed. */ bool FileEntry::Compress(std::string& text) { - bool delta = false; std::string out; - + size_t pos; - unsigned start; - - pos = start = 0; - for(;;) - { - size_t end; - unsigned count; - - pos = text.find_first_of(' ',pos); - if (pos == std::string::npos) break; - - end = text.find_first_not_of(' ',pos); - - count = end - pos; - - if (count < 3) continue; - - delta = true; - out.append(text.begin() + start, text.begin() + pos); - - while (count) - { - unsigned c = std::min(223u, count); - out.push_back(kDLE); // dle code. - out.push_back(32 + c); - count -= c; - } - - pos = start = end; - } - - if (delta) - { - out.append(text.begin() + start, text.end()); - text.swap(out); - } - - return delta; + 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::max((int)count, 255 - 32); + + out.push_back(kDLE); + out.push_back(32 + count); + out.append(text.begin() + count, text.end()); + + return true; } +/* + * dle will only occur at start. + * + */ bool FileEntry::Uncompress(std::string& text) { - bool delta = false; std::string out; - size_t start; - size_t pos; - size_t length = text.length(); - - start = pos = 0; - - for(;;) - { - unsigned c; - - pos = text.find_first_of(kDLE, pos); - if (pos == std::string::npos) break; - if (pos == length - 1) break; // should not happen; - - c = text[pos + 1]; - - if (c <= 32) continue; - - delta = true; - - out.append(text.begin() + start, text.begin() + pos); - - out.append(c - 32, ' '); - - pos = pos + 1; - start = pos; - } - - if (delta) - { - out.append(text.begin() + start, text.end()); - text.swap(out); - } - - return delta; + 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()); + + return true; } From d6f90048d16bcb41a51eeb2129a3c32c5b80b183 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 24 May 2010 13:26:22 +0000 Subject: [PATCH 144/236] remove dead code git-svn-id: https://profuse.googlecode.com/svn/branches/v2@270 aa027e90-d47c-11dd-86d7-074df07e0730 --- MappedFile.cpp | 61 -------------------------------------------------- 1 file changed, 61 deletions(-) delete mode 100644 MappedFile.cpp diff --git a/MappedFile.cpp b/MappedFile.cpp deleted file mode 100644 index 32d3e3a..0000000 --- a/MappedFile.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -#include - -class MappedFile -{ -public: - - MappedFile(int fd, bool readOnly) - { - _fd = fd; - _length = ::lseek(fd, 0, SEEK_END); - _address = MAP_FAILED; - if (_length > 0) - { - _address = ::mmap(0, _length, - readOnly ? PROT_READ : PROT_READ | PROT_WRITE, - MAP_FILE, fd, 0); - } - } - - MappedFile(void *address, size_t size) - { - _fd = -1; - _address = address; - _size = size; - } - - ~MappedFile() - { - if (_address != MAP_FAILED) ::munmap(_address, _length); - if (_fd != -1) ::close(_fd); - } - - void *address() const - { - return _address; - } - - size_t length() - { - return _length; - } - - int sync() - { - - if (::msync(_address, _length, MS_SYNC) == 0) - return 0; - return errno; - } - - - -private: - int _fd; - void *_address; - size_t _length; - -}; \ No newline at end of file From e59ebb4d5354f22423b6cabe7dfce1a512abb7e1 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 24 May 2010 16:04:54 +0000 Subject: [PATCH 145/236] unix makefile git-svn-id: https://profuse.googlecode.com/svn/branches/v2@271 aa027e90-d47c-11dd-86d7-074df07e0730 --- Makefile | 149 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 130 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index c0ae947..302fd5c 100644 --- a/Makefile +++ b/Makefile @@ -1,22 +1,133 @@ CC = g++ -CPPFLAGS += -Wall -O2 -g +CPPFLAGS += -Wall -W -I. -O2 -g +LDFLAGS += -lpthread +fuse_pascal_LDFLAGS += -lfuse + +newfs_pascal: newfs_pascal.o \ + Cache/BlockCache.o Cache/ConcreteBlockCache.o Cache/MappedBlockCache.o \ + Device/Adaptor.o Device/BlockDevice.o Device/DavexDiskImage.o \ + Device/DiskCopy42Image.o Device/DiskImage.o Device/RawDevice.o \ + Device/UniversalDiskImage.o \ + Endian/Endian.o \ + File/File.o File/MappedFile.o \ + ProFUSE/Exception.o ProFUSE/Lock.o \ + Pascal/Date.o Pascal/Entry.o Pascal/FileEntry.o Pascal/VolumeEntry.o + +apfm: apfm.o \ + Cache/BlockCache.o Cache/ConcreteBlockCache.o Cache/MappedBlockCache.o \ + Device/Adaptor.o Device/BlockDevice.o Device/DavexDiskImage.o \ + Device/DiskCopy42Image.o Device/DiskImage.o Device/RawDevice.o \ + Device/UniversalDiskImage.o \ + Endian/Endian.o \ + File/File.o File/MappedFile.o \ + ProFUSE/Exception.o ProFUSE/Lock.o \ + Pascal/Date.o Pascal/Entry.o Pascal/FileEntry.o Pascal/VolumeEntry.o + + +fuse_pascal: fuse_pascal.o fuse_pascal_ops.o \ + Cache/BlockCache.o Cache/ConcreteBlockCache.o Cache/MappedBlockCache.o \ + Device/Adaptor.o Device/BlockDevice.o Device/DavexDiskImage.o \ + Device/DiskCopy42Image.o Device/DiskImage.o Device/RawDevice.o \ + Device/UniversalDiskImage.o \ + Endian/Endian.o \ + File/File.o File/MappedFile.o \ + ProFUSE/Exception.o ProFUSE/Lock.o \ + Pascal/Date.o Pascal/Entry.o Pascal/FileEntry.o Pascal/VolumeEntry.o + $(CC) -lfuse $(LDFLAGS) $^ -o $@ -newfs_prodos: \ - newfs_prodos.o \ - Exception.o \ - BlockDevice.o \ - BlockCache.o \ - UniversalDiskImage.o \ - DiskCopy42Image.o \ - DavexDiskImage.o \ - RawDevice.o \ - MappedFile.o \ - Buffer.o \ - Entry.o \ - Directory.o \ - VolumeDirectory.o \ - Bitmap.o \ - DateTime.o - - \ No newline at end of file +newfs_pascal.o: newfs_pascal.cpp Device/BlockDevice.h ProFUSE/Exception.h \ + Device/TrackSector.h Cache/BlockCache.h Device/RawDevice.h File/File.h \ + Pascal/File.h Pascal/Date.h + +fuse_pascal.o: fuse_pascal.cpp Pascal/File.h Pascal/Date.h \ + ProFUSE/Exception.h Device/BlockDevice.h Device/TrackSector.h \ + Cache/BlockCache.h + +fuse_pascal_ops.o: fuse_pascal_ops.cpp Pascal/File.h Pascal/Date.h \ + ProFUSE/auto.h ProFUSE/Exception.h + +apfm.o: apfm.cpp Pascal/File.h Pascal/Date.h Device/BlockDevice.h \ + ProFUSE/Exception.h Device/TrackSector.h Cache/BlockCache.h + +File/File.o: File/File.cpp File/File.h ProFUSE/Exception.h + +File/MappedFile.o: File/MappedFile.cpp File/MappedFile.h File/File.h \ + ProFUSE/Exception.h + +Device/Adaptor.o: Device/Adaptor.cpp Device/Adaptor.h Device/TrackSector.h \ + ProFUSE/Exception.h + +Device/BlockDevice.o: Device/BlockDevice.cpp Device/BlockDevice.h \ + ProFUSE/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 ProFUSE/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 ProFUSE/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 \ + ProFUSE/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 \ + ProFUSE/Exception.h Device/TrackSector.h Cache/BlockCache.h File/File.h + +Device/UniversalDiskImage.o: Device/UniversalDiskImage.cpp \ + Device/UniversalDiskImage.h Device/BlockDevice.h ProFUSE/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 ProFUSE/Exception.h Device/TrackSector.h \ + ProFUSE/auto.h + +Cache/ConcreteBlockCache.o: Cache/ConcreteBlockCache.cpp \ + Device/BlockDevice.h \ + ProFUSE/Exception.h Device/TrackSector.h Cache/BlockCache.h \ + Cache/ConcreteBlockCache.h ProFUSE/auto.h + +Cache/MappedBlockCache.o: Cache/MappedBlockCache.cpp \ + Cache/MappedBlockCache.h \ + Cache/BlockCache.h Device/BlockDevice.h ProFUSE/Exception.h \ + Device/TrackSector.h + +ProFUSE/Exception.o: ProFUSE/Exception.cpp ProFUSE/Exception.h + +ProFUSE/Lock.o: ProFUSE/Lock.cpp ProFUSE/Lock.h + +Pascal/Date.o: Pascal/Date.cpp Pascal/Date.h + +Pascal/Entry.o: Pascal/Entry.cpp Pascal/File.h Pascal/Date.h \ + ProFUSE/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/File.h Pascal/Date.h \ + ProFUSE/auto.h ProFUSE/Exception.h Endian/Endian.h Endian/IOBuffer.h \ + Endian/IOBuffer.cpp.h Device/BlockDevice.h Device/TrackSector.h \ + Cache/BlockCache.h + +Pascal/VolumeEntry.o: Pascal/VolumeEntry.cpp Pascal/File.h Pascal/Date.h \ + ProFUSE/auto.h ProFUSE/Exception.h Endian/Endian.h Endian/IOBuffer.h \ + Endian/IOBuffer.cpp.h Device/BlockDevice.h Device/TrackSector.h \ + Cache/BlockCache.h + From 0db1d92287e03ea2f4ed54b8de7d5d01b8d78ed9 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 24 May 2010 16:05:11 +0000 Subject: [PATCH 146/236] linux fixes git-svn-id: https://profuse.googlecode.com/svn/branches/v2@272 aa027e90-d47c-11dd-86d7-074df07e0730 --- fuse_pascal.cpp | 18 ++++++++++-------- fuse_pascal_ops.cpp | 9 ++++++++- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/fuse_pascal.cpp b/fuse_pascal.cpp index c5aebbf..be11a50 100644 --- a/fuse_pascal.cpp +++ b/fuse_pascal.cpp @@ -152,14 +152,16 @@ bool make_mount_dir(std::string name, std::string &path) int main(int argc, char **argv) { extern void init_ops(fuse_lowlevel_ops *ops); - struct options options = { 0 }; + struct options 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; + 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; @@ -305,4 +307,4 @@ int main(int argc, char **argv) return err ? 1 : 0; -} \ No newline at end of file +} diff --git a/fuse_pascal_ops.cpp b/fuse_pascal_ops.cpp index 9721747..5eecbe7 100644 --- a/fuse_pascal_ops.cpp +++ b/fuse_pascal_ops.cpp @@ -1,14 +1,17 @@ +#ifdef __APPLE__ #define __FreeBSD__ 10 #define __DARWIN_64_BIT_INO_T 1 -#define _FILE_OFFSET_BITS 64 +#endif +#define _FILE_OFFSET_BITS 64 #define FUSE_USE_VERSION 27 #include #include #include #include +#include #include #include @@ -45,6 +48,10 @@ #define DEBUGNAME() \ if (0) { std::fprintf(stderr, "%s\n", __func__); } +// linux doesn't have ENOATTR. +#ifndef ENOATTR +#define ENOATTR ENOENT +#endif using namespace Pascal; From adab6265b80a81c504d39f735b61615a280fb72a Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 24 May 2010 21:30:03 +0000 Subject: [PATCH 147/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@273 aa027e90-d47c-11dd-86d7-074df07e0730 --- xattr.cpp | 321 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 321 insertions(+) create mode 100644 xattr.cpp diff --git a/xattr.cpp b/xattr.cpp new file mode 100644 index 0000000..05e1b19 --- /dev/null +++ b/xattr.cpp @@ -0,0 +1,321 @@ +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +typedef std::vector::iterator vsiter; + +#ifdef __APPLE__ +// apple has additional parameter for position and options. + +inline ssize_t getxattr(const char *path, const char *name, void *value, size_t size) +{ + return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW); +} + +// apple has additional parameter for options. +inline ssize_t listxattr(const char *path, char *namebuf, size_t size) +{ + return listxattr(path, namebuf, size, XATTR_NOFOLLOW); +} + +#endif + +void hexdump(const uint8_t *data, ssize_t size) +{ +const char *HexMap = "0123456789abcdef"; + + char buffer1[16 * 3 + 1 + 1]; + char buffer2[16 + 1]; + ssize_t offset = 0; + unsigned i, j; + + + while(size > 0) + { + std::memset(buffer1, ' ', sizeof(buffer1)); + std::memset(buffer2, ' ', sizeof(buffer2)); + + unsigned linelen = (unsigned)std::min(size, (ssize_t)16); + + + for (i = 0, j = 0; i < linelen; i++) + { + unsigned x = data[i]; + buffer1[j++] = HexMap[x >> 4]; + buffer1[j++] = HexMap[x & 0x0f]; + j++; + if (i == 7) j++; + + // isascii not part of std:: and may be a macro. + buffer2[i] = isascii(x) && std::isprint(x) ? x : '.'; + + } + + buffer1[sizeof(buffer1)-1] = 0; + buffer2[sizeof(buffer2)-1] = 0; + + + std::printf("%06x:\t%s\t%s\n", (unsigned)offset, buffer1, buffer2); + offset += 16; + data += 16; + size -= 16; + } + std::printf("\n"); +} + +/* + * build a list of attribute names for a file. + * returns -1 on failure + * otherwise, returns # of attributes. + * + */ +ssize_t get_attr_list(const char * fname, std::vector &out) +{ + ssize_t asize = listxattr(fname, NULL, 0); + if (asize < 0) return -1; + if (asize == 0) return 0; + + char *buffer = new char[asize]; + + if ((asize = listxattr(fname, buffer, asize)) < 0) + { + delete []buffer; + return -1; + } + + //hexdump((uint8_t *)buffer, asize); + + char *cp = buffer; + // buffer is null-terminated utf-8 strings + // eg: + // c a t 0 d o g 0 + // 0 1 2 3 4 5 6 7 + while (asize > 0) + { + ssize_t len = std::strlen(cp); + + out.push_back(std::string(cp, len)); + ++len; + asize -= len; + cp += len; + } + + delete []buffer; + + return out.size(); +} + + + + + +/* + * hexdump an individual attribute. + */ +void dumpxattr(const char *file, const char *attr) +{ +ssize_t asize; +char *buffer; + + asize = getxattr(file, attr, NULL, 0); + if (asize < 0) + { + std::perror(attr); + return; + } + + std::printf("%s: %u\n", attr, (unsigned)asize); + + buffer = new char[asize]; + //if (!buffer) return; + + asize = getxattr(file, attr, buffer, asize); + if (asize >= 0) + { + hexdump((uint8_t *)buffer, asize); + } + else + { + std::perror(attr); + } + + delete []buffer; +} + + +/* + * list a file's attributes (and size) + * + */ +int list(int argc, char **argv) +{ + + const char *fname = *argv; + + std::vectorattr; + + if (argc == 1) + { + get_attr_list(fname, attr); + std::sort(attr.begin(), attr.end()); + } + else + { + for (int i = 1; i < argc; ++i) + { + attr.push_back(argv[i]); + } + } + + + // find the max name length (not utf-8 happy) + unsigned maxname = 0; + for (vsiter i = attr.begin(); i != attr.end() ; ++i) + { + maxname = std::max(maxname, (unsigned)i->length()); + } + maxname += 2; + + for (vsiter i = attr.begin(); i != attr.end() ; ++i) + { + const char *attr_name = i->c_str(); + + ssize_t asize = getxattr(fname, attr_name, NULL, 0); + if (asize >= 0) + { + std::printf("%-*s %8u\n", maxname, attr_name, (unsigned)asize); + } + else + { + std::perror(attr_name); + } + } + + return 0; +} + + +/* + * hexdump a file's attributes. + * + */ +int dump(int argc, char **argv) +{ + + const char *fname = *argv; + + std::vectorattr; + + if (argc == 1) + { + get_attr_list(fname, attr); + std::sort(attr.begin(), attr.end()); + } + else + { + for (int i = 1; i < argc; ++i) + { + attr.push_back(argv[i]); + } + } + + + for (vsiter i = attr.begin(); i != attr.end() ; ++i) + { + const char *attr_name = i->c_str(); + + dumpxattr(fname, attr_name); + } + + return 0; +} + + +// must specify the xattr name. +int read(int argc, char **argv) +{ + + if (argc != 2) + { + std::fprintf(stderr, "Must specify attribute to be read.\n"); + return -1; + } + + const char *fname = argv[0]; + const char *attr_name = argv[1]; + + // get the attribute size and read it in. + ssize_t asize = getxattr(fname, attr_name, NULL, 0); + if (asize < 0) + { + std::perror(attr_name); + return -1; + } + if (asize == 0) return 0; + + uint8_t *buffer = new uint8_t[asize]; + asize = getxattr(fname, attr_name, buffer, asize); + + if (asize < 0) + { + std::perror(attr_name); + return -1; + } + + if (::write(STDOUT_FILENO, buffer, asize) != asize) + { + perror(NULL); + delete []buffer; + return -1; + } + + + delete []buffer; + return 0; + + +} + + + + + +void usage(const char *name) +{ + std::printf("usage:\n"); + std::printf("%s list file [attr ...]\n", name); + std::printf("%s dump file [attr ...]\n", name); + std::printf("%s read file attr\n", name); + + std::exit(0); +} + +/* + * xattr list file [xattr ...] + * xattr dump file [xattr ...] + * + */ +int main(int argc, char **argv) +{ + if (argc < 3) usage(*argv); + + if (std::strcmp(argv[1], "list") == 0) return list(argc - 2, argv + 2); + if (std::strcmp(argv[1], "dump") == 0) return dump(argc - 2, argv + 2); + + if (std::strcmp(argv[1], "read") == 0) return read(argc - 2, argv + 2); + + + usage(*argv); + + return 1; +} From 646872457359576542dcfe415d87e88d8f1eb170 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 24 May 2010 21:55:07 +0000 Subject: [PATCH 148/236] linux xattr git-svn-id: https://profuse.googlecode.com/svn/branches/v2@274 aa027e90-d47c-11dd-86d7-074df07e0730 --- Makefile | 5 +++ xattr.cpp | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 97 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 302fd5c..055ad60 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,9 @@ CPPFLAGS += -Wall -W -I. -O2 -g LDFLAGS += -lpthread fuse_pascal_LDFLAGS += -lfuse +xattr: xattr.o + $(CC) $^ -o $@ + newfs_pascal: newfs_pascal.o \ Cache/BlockCache.o Cache/ConcreteBlockCache.o Cache/MappedBlockCache.o \ Device/Adaptor.o Device/BlockDevice.o Device/DavexDiskImage.o \ @@ -35,6 +38,8 @@ fuse_pascal: fuse_pascal.o fuse_pascal_ops.o \ Pascal/Date.o Pascal/Entry.o Pascal/FileEntry.o Pascal/VolumeEntry.o $(CC) -lfuse $(LDFLAGS) $^ -o $@ + +xattr.o: xattr.cpp newfs_pascal.o: newfs_pascal.cpp Device/BlockDevice.h ProFUSE/Exception.h \ Device/TrackSector.h Cache/BlockCache.h Device/RawDevice.h File/File.h \ diff --git a/xattr.cpp b/xattr.cpp index 05e1b19..f180c46 100644 --- a/xattr.cpp +++ b/xattr.cpp @@ -1,16 +1,19 @@ +#include +#include +#include + #include #include #include #include +#include +#include #include #include - +#include #include -#include -#include -#include typedef std::vector::iterator vsiter; @@ -287,7 +290,90 @@ int read(int argc, char **argv) } +ssize_t read_all(int fd, std::vector &out) +{ + struct stat st; + ssize_t bsize; + + // stdin could be a file, a pipe, or a tty. + if (fstat(fd, &st) < 0) + { + std::perror("stdin"); + return -1; + } + + bsize = std::max(st.st_blksize, (blksize_t)512); + out.reserve(std::max(st.st_size, (off_t)512)); + + uint8_t *buffer = new uint8_t[bsize]; + + for(;;) + { + ssize_t size = ::read(fd, buffer, bsize); + + if (size == 0) break; + if (size == -1) + { + if (errno == EINTR) continue; + delete[] buffer; + std::perror(NULL); + return -1; + } + + // force reserve? + out.insert(out.end(), buffer, buffer + size); + } + + + delete []buffer; + + return out.size(); +} + + +// xattr write filename attrname +// stdin -> filename:attrname +int write(int argc, char **argv) +{ + + std::vector buffer; + int flags = 0; + + if (argc != 2) + { + std::fprintf(stderr, "Must specify attribute to be read.\n"); + return -1; + } + + const char *fname = argv[0]; + const char *attr_name = argv[1]; + + if (read_all(STDIN_FILENO, buffer) < 0) + { + return -1; + } + + // Flag options: + // XATTR_CREATE : fails if attr already exists. + // XATTR_REPLACE : fails if attr does not exist. + // if neither of the above is specified, will create and replace. + // XATTR_NOFOLLOW : do not follow symbolic links (Apple only) + + #ifdef __APPLE__ + flags = XATTR_NOFOLLOW; + #endif + + ssize_t asize = setxattr(fname, attr_name, &buffer[0], buffer.size(), flags); + + if (asize < 0) + { + std::perror(attr_name); + return -1; + } + + return 0; +} void usage(const char *name) @@ -296,6 +382,7 @@ void usage(const char *name) std::printf("%s list file [attr ...]\n", name); std::printf("%s dump file [attr ...]\n", name); std::printf("%s read file attr\n", name); + std::printf("%s write file attr\n", name); std::exit(0); } @@ -313,6 +400,7 @@ int main(int argc, char **argv) if (std::strcmp(argv[1], "dump") == 0) return dump(argc - 2, argv + 2); if (std::strcmp(argv[1], "read") == 0) return read(argc - 2, argv + 2); + if (std::strcmp(argv[1], "write") == 0) return write(argc - 2, argv + 2); usage(*argv); From 0d8ca19a1a9dbac6c40493a4b8b1a1536fd0006a Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 24 May 2010 22:02:31 +0000 Subject: [PATCH 149/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@275 aa027e90-d47c-11dd-86d7-074df07e0730 --- xattr.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xattr.cpp b/xattr.cpp index f180c46..89a0b3a 100644 --- a/xattr.cpp +++ b/xattr.cpp @@ -31,6 +31,11 @@ inline ssize_t listxattr(const char *path, char *namebuf, size_t size) return listxattr(path, namebuf, size, XATTR_NOFOLLOW); } +// apple has additional parameter for offset . +inline int setxattr(const char *path, const char *name, void *value, size_t size, int flags) +{ + return setxattr(path, name, value, size, 0, flags); +} #endif void hexdump(const uint8_t *data, ssize_t size) From fdd622535b8b5b4d0323cb51287da2fa6b9306ce Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 24 May 2010 22:40:28 +0000 Subject: [PATCH 150/236] daemonize git-svn-id: https://profuse.googlecode.com/svn/branches/v2@276 aa027e90-d47c-11dd-86d7-074df07e0730 --- fuse_pascal.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fuse_pascal.cpp b/fuse_pascal.cpp index be11a50..4e7631c 100644 --- a/fuse_pascal.cpp +++ b/fuse_pascal.cpp @@ -274,10 +274,9 @@ int main(int argc, char **argv) se = fuse_lowlevel_new(&args, &pascal_ops, sizeof(pascal_ops), volume.get()); if (se) do { - foreground = 1; - multithread = 0; + - err = fuse_daemonize(foreground); // todo + err = fuse_daemonize(foreground); if (err < 0 ) break; err = fuse_set_signal_handlers(se); From 724d3c5ac3b21b2a4b4776bf113bcadc417b451f Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 24 May 2010 22:40:51 +0000 Subject: [PATCH 151/236] add xcode project git-svn-id: https://profuse.googlecode.com/svn/branches/v2@277 aa027e90-d47c-11dd-86d7-074df07e0730 --- PROFuseX.xcodeproj/kelvin.pbxuser | 1322 ++++++++++++++++++++ PROFuseX.xcodeproj/kelvin.perspectivev3 | 1525 +++++++++++++++++++++++ PROFuseX.xcodeproj/project.pbxproj | 868 +++++++++++++ 3 files changed, 3715 insertions(+) create mode 100644 PROFuseX.xcodeproj/kelvin.pbxuser create mode 100644 PROFuseX.xcodeproj/kelvin.perspectivev3 create mode 100644 PROFuseX.xcodeproj/project.pbxproj diff --git a/PROFuseX.xcodeproj/kelvin.pbxuser b/PROFuseX.xcodeproj/kelvin.pbxuser new file mode 100644 index 0000000..7038c28 --- /dev/null +++ b/PROFuseX.xcodeproj/kelvin.pbxuser @@ -0,0 +1,1322 @@ +// !$*UTF8*$! +{ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + activeBuildConfigurationName = Debug; + activeExecutable = B656AF0411AA105500AB578A /* NibbleTest */; + activeTarget = B656AF0211AA105500AB578A /* NibbleTest */; + addToTargets = ( + ); + breakpoints = ( + B63EFD8911A4455A00C90DCE /* apfm.cpp:346 */, + B63EFE0E11A451C600C90DCE /* VolumeEntry.cpp:105 */, + B63EFE3B11A4799800C90DCE /* apfm.cpp:184 */, + B6F3642F11AA1E150045E114 /* NibbleTest.cpp:74 */, + ); + codeSenseManager = B63EFA6811A093C200C90DCE /* Code sense */; + executables = ( + B63EFCCF11A36C7300C90DCE /* apfm */, + B63EFE8211A4886C00C90DCE /* newfs_pascal */, + B656AE0411A84F5800AB578A /* fuse_pascal */, + B656AF0411AA105500AB578A /* NibbleTest */, + B6F3648111AB36260045E114 /* xattr */, + ); + perUserDictionary = { + "PBXConfiguration.PBXBreakpointsDataSource.v1:1CA1AED706398EBD00589147" = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXBreakpointsDataSource_BreakpointID; + PBXFileTableDataSourceColumnWidthsKey = ( + 20, + 20, + 198, + 20, + 99, + 99, + 29, + 20, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXBreakpointsDataSource_ActionID, + PBXBreakpointsDataSource_TypeID, + PBXBreakpointsDataSource_BreakpointID, + PBXBreakpointsDataSource_UseID, + PBXBreakpointsDataSource_LocationID, + PBXBreakpointsDataSource_ConditionID, + PBXBreakpointsDataSource_IgnoreCountID, + PBXBreakpointsDataSource_ContinueID, + ); + }; + PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_ObjectSize_ColumnID; + PBXFileTableDataSourceColumnWidthsKey = ( + 20, + 660, + 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.PBXTargetDataSource.PBXTargetDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; + PBXFileTableDataSourceColumnWidthsKey = ( + 20, + 620, + 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 = 296433132; + PBXWorkspaceStateSaveDate = 296433132; + }; + perUserProjectItems = { + B63EFC2611A2D5A400C90DCE = B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */; + B63EFC2B11A2D5A400C90DCE = B63EFC2B11A2D5A400C90DCE /* PBXTextBookmark */; + B63EFC3211A2D5A400C90DCE = B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */; + B63EFCB211A3639400C90DCE = B63EFCB211A3639400C90DCE /* PBXTextBookmark */; + B63EFCB611A3639400C90DCE = B63EFCB611A3639400C90DCE /* PBXTextBookmark */; + B63EFD7F11A4436B00C90DCE = B63EFD7F11A4436B00C90DCE /* PBXTextBookmark */; + B63EFDA011A4488200C90DCE = B63EFDA011A4488200C90DCE /* PBXTextBookmark */; + B63EFDA511A4488200C90DCE = B63EFDA511A4488200C90DCE /* PBXTextBookmark */; + B63EFDA711A4488200C90DCE = B63EFDA711A4488200C90DCE /* PBXTextBookmark */; + B63EFDA911A4488200C90DCE = B63EFDA911A4488200C90DCE /* PBXTextBookmark */; + B63EFDAB11A4488200C90DCE = B63EFDAB11A4488200C90DCE /* PBXTextBookmark */; + B63EFDAD11A4488200C90DCE = B63EFDAD11A4488200C90DCE /* PBXTextBookmark */; + B63EFDAF11A4488200C90DCE = B63EFDAF11A4488200C90DCE /* PBXTextBookmark */; + B63EFDB111A4488200C90DCE = B63EFDB111A4488200C90DCE /* PBXTextBookmark */; + B63EFDB311A4488200C90DCE = B63EFDB311A4488200C90DCE /* PBXTextBookmark */; + B63EFDB711A4488200C90DCE = B63EFDB711A4488200C90DCE /* PBXTextBookmark */; + B63EFDC711A4494C00C90DCE = B63EFDC711A4494C00C90DCE /* PBXTextBookmark */; + B63EFDE611A44E9300C90DCE = B63EFDE611A44E9300C90DCE /* PBXTextBookmark */; + B63EFDF211A4504200C90DCE = B63EFDF211A4504200C90DCE /* PBXTextBookmark */; + B63EFEA011A488C200C90DCE = B63EFEA011A488C200C90DCE /* PBXTextBookmark */; + B63EFEA111A488C200C90DCE = B63EFEA111A488C200C90DCE /* PBXTextBookmark */; + B63EFEA211A488C200C90DCE = B63EFEA211A488C200C90DCE /* PBXTextBookmark */; + B63EFEA311A488C200C90DCE = B63EFEA311A488C200C90DCE /* PBXTextBookmark */; + B63EFEA711A488C200C90DCE = B63EFEA711A488C200C90DCE /* PBXTextBookmark */; + B63EFEA811A488C200C90DCE = B63EFEA811A488C200C90DCE /* PBXTextBookmark */; + B63EFEA911A488C200C90DCE = B63EFEA911A488C200C90DCE /* PBXTextBookmark */; + B63EFEEC11A4A70400C90DCE = B63EFEEC11A4A70400C90DCE /* PBXTextBookmark */; + B656AE2311A84FA400AB578A = B656AE2311A84FA400AB578A /* PBXTextBookmark */; + B656AE2411A84FA400AB578A = B656AE2411A84FA400AB578A /* PBXTextBookmark */; + B656AE2611A84FA400AB578A = B656AE2611A84FA400AB578A /* PBXTextBookmark */; + B656AE2711A84FA400AB578A = B656AE2711A84FA400AB578A /* PBXTextBookmark */; + B656AE6511A8591F00AB578A = B656AE6511A8591F00AB578A /* PBXTextBookmark */; + B656AEA711A9C91600AB578A = B656AEA711A9C91600AB578A /* PBXTextBookmark */; + B656AEA811A9C91600AB578A = B656AEA811A9C91600AB578A /* PBXTextBookmark */; + B656AF2711AA10C900AB578A = B656AF2711AA10C900AB578A /* PBXTextBookmark */; + B656AF2811AA10C900AB578A = B656AF2811AA10C900AB578A /* PBXTextBookmark */; + B656AF2A11AA10C900AB578A = B656AF2A11AA10C900AB578A /* PBXTextBookmark */; + B6E5F0DD11A60726000AD141 = B6E5F0DD11A60726000AD141 /* PBXTextBookmark */; + B6E5F0F211A73144000AD141 = B6E5F0F211A73144000AD141 /* PBXTextBookmark */; + B6E5F11211A73340000AD141 = B6E5F11211A73340000AD141 /* PBXTextBookmark */; + B6E5F13A11A74F2B000AD141 = B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */; + B6E5F18111A76B74000AD141 = B6E5F18111A76B74000AD141 /* PBXTextBookmark */; + B6E5F18211A76B74000AD141 = B6E5F18211A76B74000AD141 /* PBXTextBookmark */; + B6F3642811AA1DC80045E114 = B6F3642811AA1DC80045E114 /* PBXTextBookmark */; + B6F3642D11AA1E070045E114 = B6F3642D11AA1E070045E114 /* PBXTextBookmark */; + B6F3646211AA26810045E114 = B6F3646211AA26810045E114 /* PBXTextBookmark */; + B6F3646E11AB35F00045E114 /* PBXTextBookmark */ = B6F3646E11AB35F00045E114 /* PBXTextBookmark */; + B6F3646F11AB35F00045E114 /* PBXBookmark */ = B6F3646F11AB35F00045E114 /* PBXBookmark */; + B6F3647011AB35F00045E114 /* PBXTextBookmark */ = B6F3647011AB35F00045E114 /* PBXTextBookmark */; + B6F3647111AB35FE0045E114 /* PBXTextBookmark */ = B6F3647111AB35FE0045E114 /* PBXTextBookmark */; + B6F3647211AB35FE0045E114 /* PBXTextBookmark */ = B6F3647211AB35FE0045E114 /* PBXTextBookmark */; + }; + sourceControlManager = B63EFA6711A093C200C90DCE /* Source Control */; + userBuildSettings = { + }; + }; + B63EFA6711A093C200C90DCE /* Source Control */ = { + isa = PBXSourceControlManager; + fallbackIsa = XCSourceControlManager; + isSCMEnabled = 0; + scmConfiguration = { + repositoryNamesForRoots = { + "" = ""; + }; + }; + }; + B63EFA6811A093C200C90DCE /* Code sense */ = { + isa = PBXCodeSenseManager; + indexTemplatePath = ""; + }; + B63EFA7511A0948500C90DCE /* Endian.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 1339}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 907}"; + }; + }; + B63EFA7611A0948500C90DCE /* Endian.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {409, 2080}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 97}"; + }; + }; + B63EFA7711A0948500C90DCE /* IOBuffer.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 562}}"; + sepNavSelRange = "{190, 0}"; + sepNavVisRange = "{0, 206}"; + }; + }; + B63EFA9511A094E000C90DCE /* BlockDevice.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 3055}}"; + sepNavSelRange = "{843, 0}"; + sepNavVisRange = "{0, 1634}"; + }; + }; + B63EFA9611A094E000C90DCE /* BlockDevice.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 932}}"; + sepNavSelRange = "{470, 0}"; + sepNavVisRange = "{0, 1202}"; + }; + }; + B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 2262}}"; + sepNavSelRange = "{974, 0}"; + sepNavVisRange = "{114, 1526}"; + }; + }; + B63EFA9811A094E000C90DCE /* DavexDiskImage.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 948}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 763}"; + }; + }; + B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 2951}}"; + sepNavSelRange = "{4587, 0}"; + sepNavVisRange = "{3132, 1628}"; + }; + }; + B63EFA9C11A094E000C90DCE /* DiskCopy42Image.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 570}}"; + sepNavSelRange = "{459, 0}"; + sepNavVisRange = "{0, 803}"; + }; + }; + B63EFA9D11A094E000C90DCE /* DiskImage.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 2444}}"; + sepNavSelRange = "{2704, 0}"; + sepNavVisRange = "{2264, 894}"; + }; + }; + B63EFA9E11A094E000C90DCE /* DiskImage.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 1027}}"; + sepNavSelRange = "{652, 0}"; + sepNavVisRange = "{0, 1529}"; + }; + }; + B63EFAA111A094E000C90DCE /* RawDevice.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 3445}}"; + sepNavSelRange = "{5280, 138}"; + sepNavVisRange = "{4005, 1546}"; + }; + }; + B63EFAA211A094E000C90DCE /* RawDevice.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 715}}"; + sepNavSelRange = "{186, 0}"; + sepNavVisRange = "{126, 781}"; + }; + }; + B63EFAA311A094E000C90DCE /* TrackSector.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1178, 341}}"; + sepNavSelRange = "{262, 0}"; + sepNavVisRange = "{0, 316}"; + }; + }; + B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 2158}}"; + sepNavSelRange = "{3362, 0}"; + sepNavVisRange = "{1890, 1479}"; + }; + }; + B63EFAA511A094E000C90DCE /* UniversalDiskImage.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 570}}"; + sepNavSelRange = "{403, 0}"; + sepNavVisRange = "{0, 723}"; + }; + }; + B63EFAB611A098C400C90DCE /* BlockCache.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 988}}"; + sepNavSelRange = "{1253, 0}"; + sepNavVisRange = "{0, 1191}"; + }; + }; + B63EFAB711A098C400C90DCE /* BlockCache.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 932}}"; + sepNavSelRange = "{795, 44}"; + sepNavVisRange = "{0, 1167}"; + }; + }; + B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 5070}}"; + sepNavSelRange = "{5248, 0}"; + sepNavVisRange = "{4735, 1303}"; + }; + }; + B63EFAB911A098C400C90DCE /* ConcreteBlockCache.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 932}}"; + sepNavSelRange = "{526, 0}"; + sepNavVisRange = "{0, 1257}"; + }; + }; + B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 1846}}"; + sepNavSelRange = "{1292, 0}"; + sepNavVisRange = "{0, 1315}"; + }; + }; + B63EFABB11A098C400C90DCE /* MappedBlockCache.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 948}}"; + sepNavSelRange = "{630, 0}"; + sepNavVisRange = "{0, 659}"; + }; + }; + B63EFAC911A09DAA00C90DCE /* File.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 1209}}"; + sepNavSelRange = "{1210, 0}"; + sepNavVisRange = "{0, 1046}"; + }; + }; + B63EFACA11A09DAA00C90DCE /* File.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 932}}"; + sepNavSelRange = "{457, 0}"; + sepNavVisRange = "{0, 611}"; + }; + }; + B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 2301}}"; + sepNavSelRange = "{723, 0}"; + sepNavVisRange = "{293, 1426}"; + }; + }; + B63EFACC11A09DAA00C90DCE /* MappedFile.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 932}}"; + sepNavSelRange = "{211, 0}"; + sepNavVisRange = "{0, 927}"; + }; + }; + B63EFAD011A09DB500C90DCE /* auto.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 1365}}"; + sepNavSelRange = "{287, 0}"; + sepNavVisRange = "{517, 1036}"; + }; + }; + B63EFAD111A09DB500C90DCE /* Exception.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 562}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 157}"; + }; + }; + B63EFAD211A09DB500C90DCE /* Exception.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 1898}}"; + sepNavSelRange = "{734, 12}"; + sepNavVisRange = "{434, 1049}"; + }; + }; + B63EFAD311A09DB500C90DCE /* Lock.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1207, 914}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 353}"; + }; + }; + B63EFB0611A0AC4800C90DCE /* Adaptor.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 1066}}"; + sepNavSelRange = "{1806, 0}"; + sepNavVisRange = "{442, 1126}"; + }; + }; + B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {929, 5577}}"; + sepNavSelRange = "{9724, 0}"; + sepNavVisRange = "{8739, 1774}"; + }; + }; + B63EFB8811A1FB2500C90DCE /* DiskImage.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = DiskImage.h; + path = ./Device/DiskImage.h; + sourceTree = ""; + }; + B63EFBE811A244EE00C90DCE /* Date.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 611}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 834}"; + }; + }; + B63EFBE911A244EE00C90DCE /* Date.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 637}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 706}"; + }; + }; + B63EFBEA11A244EE00C90DCE /* Entry.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 1274}}"; + sepNavSelRange = "{1176, 0}"; + sepNavVisRange = "{382, 1153}"; + }; + }; + B63EFBEB11A244EE00C90DCE /* File.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 2964}}"; + sepNavSelRange = "{2767, 0}"; + sepNavVisRange = "{1820, 1622}"; + }; + }; + B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 5330}}"; + sepNavSelRange = "{7404, 0}"; + sepNavVisRange = "{6413, 938}"; + }; + }; + B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 3094}}"; + sepNavSelRange = "{275, 24}"; + sepNavVisRange = "{0, 832}"; + }; + }; + B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA7611A0948500C90DCE /* Endian.h */; + name = "Endian.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 97; + vrLoc = 0; + }; + B63EFC2B11A2D5A400C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; + name = "BlockDevice.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 186; + vrLoc = 0; + }; + B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAB911A098C400C90DCE /* ConcreteBlockCache.h */; + name = "ConcreteBlockCache.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 297; + vrLoc = 0; + }; + B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 1339}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{1363, 1056}"; + }; + }; + B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 4004}}"; + sepNavSelRange = "{7036, 0}"; + sepNavVisRange = "{5446, 1697}"; + }; + }; + B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 3601}}"; + sepNavSelRange = "{5059, 0}"; + sepNavVisRange = "{4987, 1307}"; + }; + }; + B63EFC9D11A35F8200C90DCE /* fuse_pascal_ops.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 6071}}"; + sepNavSelRange = "{855, 6}"; + sepNavVisRange = "{25, 1403}"; + }; + }; + B63EFC9F11A35F8F00C90DCE /* apfm.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 5187}}"; + sepNavSelRange = "{1814, 0}"; + sepNavVisRange = "{2880, 875}"; + }; + }; + B63EFCB211A3639400C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; + name = "DavexDiskImage.cpp: 160"; + rLen = 0; + rLoc = 3409; + rType = 0; + vrLen = 270; + vrLoc = 3136; + }; + B63EFCB611A3639400C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; + name = "Entry.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 233; + vrLoc = 0; + }; + B63EFCC811A366C800C90DCE /* MappedFile.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = MappedFile.h; + path = ./File/MappedFile.h; + sourceTree = ""; + }; + B63EFCCD11A36C7300C90DCE /* apfm */ = { + activeExec = 0; + executables = ( + B63EFCCF11A36C7300C90DCE /* apfm */, + ); + }; + B63EFCCF11A36C7300C90DCE /* apfm */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 1; + configStateDict = { + }; + customDataFormattersEnabled = 1; + dataTipCustomDataFormattersEnabled = 1; + dataTipShowTypeColumn = 1; + dataTipSortType = 0; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + dylibVariantSuffix = ""; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + libgmallocEnabled = 0; + name = apfm; + savedGlobals = { + }; + showTypeColumn = 0; + sourceDirectories = ( + ); + variableFormatDictionary = { + "_length-size_t-Device::DOSOrderDiskImage::DOSOrderDiskImage" = 1; + "size-size_t-MappedFile::init" = 1; + }; + }; + B63EFD7F11A4436B00C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; + name = "File.cpp: 34"; + rLen = 0; + rLoc = 385; + rType = 0; + vrLen = 225; + vrLoc = 284; + }; + B63EFD8911A4455A00C90DCE /* apfm.cpp:346 */ = { + isa = PBXFileBreakpoint; + actions = ( + ); + breakpointStyle = 0; + continueAfterActions = 0; + countType = 0; + delayBeforeContinue = 0; + fileReference = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + functionName = "main(/* int argc, char **argv */)"; + hitCount = 0; + ignoreCount = 0; + lineNumber = 346; + modificationTime = 296363159.802434; + originalNumberOfMultipleMatches = 1; + state = 0; + }; + B63EFDA011A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDA111A4488200C90DCE /* memory */; + name = "memory: 300"; + rLen = 0; + rLoc = 10169; + rType = 0; + vrLen = 348; + vrLoc = 9980; + }; + B63EFDA111A4488200C90DCE /* memory */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.h; + name = memory; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/memory"; + sourceTree = ""; + }; + B63EFDA511A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDA611A4488200C90DCE /* new */; + name = "new: 105"; + rLen = 0; + rLoc = 3667; + rType = 0; + vrLen = 1002; + vrLoc = 3039; + }; + B63EFDA611A4488200C90DCE /* new */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.h; + name = new; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/new"; + sourceTree = ""; + }; + B63EFDA711A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDA811A4488200C90DCE /* new_allocator.h */; + name = "new_allocator.h: 70"; + rLen = 0; + rLoc = 2448; + rType = 0; + vrLen = 768; + vrLoc = 2080; + }; + B63EFDA811A4488200C90DCE /* new_allocator.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = new_allocator.h; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/ext/new_allocator.h"; + sourceTree = ""; + }; + B63EFDA911A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDAA11A4488200C90DCE /* allocator.h */; + name = "allocator.h: 103"; + rLen = 0; + rLoc = 3498; + rType = 0; + vrLen = 729; + vrLoc = 3092; + }; + B63EFDAA11A4488200C90DCE /* allocator.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = allocator.h; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/allocator.h"; + sourceTree = ""; + }; + B63EFDAB11A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDAC11A4488200C90DCE /* stl_iterator.h */; + name = "stl_iterator.h: 718"; + rLen = 0; + rLoc = 22590; + rType = 0; + vrLen = 1056; + vrLoc = 22176; + }; + B63EFDAC11A4488200C90DCE /* stl_iterator.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = stl_iterator.h; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_iterator.h"; + sourceTree = ""; + }; + B63EFDAD11A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDAE11A4488200C90DCE /* stl_algobase.h */; + name = "stl_algobase.h: 398"; + rLen = 0; + rLoc = 13483; + rType = 0; + vrLen = 1046; + vrLoc = 13073; + }; + B63EFDAE11A4488200C90DCE /* stl_algobase.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = stl_algobase.h; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_algobase.h"; + sourceTree = ""; + }; + B63EFDAF11A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDB011A4488200C90DCE /* stl_uninitialized.h */; + name = "stl_uninitialized.h: 75"; + rLen = 0; + rLoc = 3073; + rType = 0; + vrLen = 804; + vrLoc = 8199; + }; + B63EFDB011A4488200C90DCE /* stl_uninitialized.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = stl_uninitialized.h; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_uninitialized.h"; + sourceTree = ""; + }; + B63EFDB111A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDB211A4488200C90DCE /* vector.tcc */; + name = "vector.tcc: 293"; + rLen = 0; + rLoc = 9731; + rType = 0; + vrLen = 818; + vrLoc = 9315; + }; + B63EFDB211A4488200C90DCE /* vector.tcc */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + name = vector.tcc; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/vector.tcc"; + sourceTree = ""; + }; + B63EFDB311A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDB411A4488200C90DCE /* stl_vector.h */; + name = "stl_vector.h: 608"; + rLen = 0; + rLoc = 20940; + rType = 0; + vrLen = 779; + vrLoc = 20537; + }; + B63EFDB411A4488200C90DCE /* stl_vector.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = stl_vector.h; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_vector.h"; + sourceTree = ""; + }; + B63EFDB711A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; + name = "BlockCache.cpp: 60"; + rLen = 0; + rLoc = 1001; + rType = 0; + vrLen = 490; + vrLoc = 514; + }; + B63EFDC711A4494C00C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAB711A098C400C90DCE /* BlockCache.h */; + name = "BlockCache.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 954; + vrLoc = 0; + }; + B63EFDE611A44E9300C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; + name = "MappedFile.cpp: 42"; + rLen = 0; + rLoc = 723; + rType = 0; + vrLen = 791; + vrLoc = 576; + }; + B63EFDF211A4504200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAD011A09DB500C90DCE /* auto.h */; + name = "auto.h: 20"; + rLen = 0; + rLoc = 287; + rType = 0; + vrLen = 479; + vrLoc = 0; + }; + B63EFE0E11A451C600C90DCE /* VolumeEntry.cpp:105 */ = { + isa = PBXFileBreakpoint; + actions = ( + ); + breakpointStyle = 0; + continueAfterActions = 0; + countType = 0; + delayBeforeContinue = 0; + fileReference = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; + functionName = "VolumeEntry::VolumeEntry(Device::BlockDevice *device)"; + hitCount = 0; + ignoreCount = 0; + lineNumber = 105; + location = NibbleTest; + modificationTime = 296363160.018; + originalNumberOfMultipleMatches = 1; + state = 1; + }; + B63EFE3B11A4799800C90DCE /* apfm.cpp:184 */ = { + isa = PBXFileBreakpoint; + actions = ( + ); + breakpointStyle = 0; + continueAfterActions = 0; + countType = 0; + delayBeforeContinue = 0; + fileReference = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + functionName = "action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume)"; + hitCount = 0; + ignoreCount = 0; + lineNumber = 184; + modificationTime = 296363159.805745; + originalNumberOfMultipleMatches = 1; + state = 0; + }; + B63EFE8011A4886C00C90DCE /* newfs_pascal */ = { + activeExec = 0; + executables = ( + B63EFE8211A4886C00C90DCE /* newfs_pascal */, + ); + }; + B63EFE8211A4886C00C90DCE /* newfs_pascal */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 0; + configStateDict = { + }; + customDataFormattersEnabled = 1; + dataTipCustomDataFormattersEnabled = 1; + dataTipShowTypeColumn = 1; + dataTipSortType = 0; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + libgmallocEnabled = 0; + name = newfs_pascal; + showTypeColumn = 0; + sourceDirectories = ( + ); + }; + B63EFEA011A488C200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9C11A094E000C90DCE /* DiskCopy42Image.h */; + name = "DiskCopy42Image.h: 19"; + rLen = 0; + rLoc = 459; + rType = 0; + vrLen = 803; + vrLoc = 0; + }; + B63EFEA111A488C200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9811A094E000C90DCE /* DavexDiskImage.h */; + name = "DavexDiskImage.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 763; + vrLoc = 0; + }; + B63EFEA211A488C200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; + name = "UniversalDiskImage.cpp: 162"; + rLen = 0; + rLoc = 3362; + rType = 0; + vrLen = 1007; + vrLoc = 2311; + }; + B63EFEA311A488C200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAA511A094E000C90DCE /* UniversalDiskImage.h */; + name = "UniversalDiskImage.h: 22"; + rLen = 0; + rLoc = 403; + rType = 0; + vrLen = 723; + vrLoc = 0; + }; + B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + name = VolumeEntry.cpp; + path = ./Pascal/VolumeEntry.cpp; + sourceTree = ""; + }; + B63EFEA711A488C200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBEB11A244EE00C90DCE /* File.h */; + name = "File.h: 2"; + rLen = 0; + rLoc = 43; + rType = 0; + vrLen = 901; + vrLoc = 2858; + }; + B63EFEA811A488C200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; + name = "Date.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 834; + vrLoc = 0; + }; + B63EFEA911A488C200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBE911A244EE00C90DCE /* Date.h */; + name = "Date.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 706; + vrLoc = 0; + }; + B63EFEEC11A4A70400C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; + name = "RawDevice.cpp: 147"; + rLen = 0; + rLoc = 2650; + rType = 0; + vrLen = 865; + vrLoc = 2190; + }; + B656AE0211A84F5800AB578A /* fuse_pascal */ = { + activeExec = 0; + executables = ( + B656AE0411A84F5800AB578A /* fuse_pascal */, + ); + }; + B656AE0411A84F5800AB578A /* fuse_pascal */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 0; + configStateDict = { + }; + customDataFormattersEnabled = 1; + dataTipCustomDataFormattersEnabled = 1; + dataTipShowTypeColumn = 1; + dataTipSortType = 0; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + libgmallocEnabled = 0; + name = fuse_pascal; + showTypeColumn = 0; + sourceDirectories = ( + ); + }; + B656AE2311A84FA400AB578A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAD211A09DB500C90DCE /* Exception.h */; + name = "Exception.h: 37"; + rLen = 12; + rLoc = 734; + rType = 0; + vrLen = 1049; + vrLoc = 434; + }; + B656AE2411A84FA400AB578A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9D11A35F8200C90DCE /* fuse_pascal_ops.cpp */; + name = "fuse_pascal_ops.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 813; + vrLoc = 0; + }; + B656AE2611A84FA400AB578A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAA211A094E000C90DCE /* RawDevice.h */; + name = "RawDevice.h: 15"; + rLen = 0; + rLoc = 186; + rType = 0; + vrLen = 781; + vrLoc = 126; + }; + B656AE2711A84FA400AB578A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; + name = "newfs_pascal.cpp: 221"; + rLen = 0; + rLoc = 5059; + rType = 0; + vrLen = 1307; + vrLoc = 4987; + }; + B656AE6511A8591F00AB578A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */; + name = "fuse_pascal.cpp: 187"; + rLen = 0; + rLoc = 4176; + rType = 0; + vrLen = 1001; + vrLoc = 3697; + }; + B656AEA711A9C91600AB578A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; + name = "DiskImage.cpp: 148"; + rLen = 0; + rLoc = 2704; + rType = 0; + vrLen = 894; + vrLoc = 2264; + }; + B656AEA811A9C91600AB578A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB8811A1FB2500C90DCE /* DiskImage.h */; + name = "DiskImage.h: 65"; + rLen = 0; + rLoc = 1236; + rType = 0; + vrLen = 898; + vrLoc = 788; + }; + B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 1079}}"; + sepNavSelRange = "{1570, 0}"; + sepNavVisRange = "{917, 940}"; + }; + }; + B656AF0211AA105500AB578A /* NibbleTest */ = { + activeExec = 0; + executables = ( + B656AF0411AA105500AB578A /* NibbleTest */, + ); + }; + B656AF0411AA105500AB578A /* NibbleTest */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 1; + configStateDict = { + }; + customDataFormattersEnabled = 1; + dataTipCustomDataFormattersEnabled = 1; + dataTipShowTypeColumn = 1; + dataTipSortType = 0; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + dylibVariantSuffix = ""; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + libgmallocEnabled = 0; + name = NibbleTest; + savedGlobals = { + }; + showTypeColumn = 0; + sourceDirectories = ( + ); + variableFormatDictionary = { + "87-unsigned int-Device::NibbleAdaptor::NibbleAdaptor" = 1; + "checksum-uint8_t-Device::NibbleAdaptor::readTrackSector" = 1; + "offset-int-Device::NibbleAdaptor::NibbleAdaptor" = 1; + "val-uint8_t-Device::NibbleAdaptor::decode62" = 1; + "x-uint8_t-Device::NibbleAdaptor::readTrackSector" = 1; + "y-uint8_t-Device::NibbleAdaptor::readTrackSector" = 1; + }; + }; + B656AF2711AA10C900AB578A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; + name = "FileEntry.cpp: 372"; + rLen = 0; + rLoc = 7404; + rType = 0; + vrLen = 938; + vrLoc = 6413; + }; + B656AF2811AA10C900AB578A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 107"; + rLen = 0; + rLoc = 1814; + rType = 0; + vrLen = 875; + vrLoc = 2880; + }; + B656AF2A11AA10C900AB578A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFCC811A366C800C90DCE /* MappedFile.h */; + name = "MappedFile.h: 15"; + rLen = 64; + rLoc = 196; + rType = 0; + vrLen = 863; + vrLoc = 0; + }; + B6E5F0DD11A60726000AD141 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; + name = "ConcreteBlockCache.cpp: 185"; + rLen = 0; + rLoc = 4102; + rType = 0; + vrLen = 885; + vrLoc = 3468; + }; + B6E5F0F211A73144000AD141 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFABB11A098C400C90DCE /* MappedBlockCache.h */; + name = "MappedBlockCache.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 667; + vrLoc = 0; + }; + B6E5F11211A73340000AD141 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA7711A0948500C90DCE /* IOBuffer.h */; + name = "IOBuffer.h: 12"; + rLen = 0; + rLoc = 190; + rType = 0; + vrLen = 206; + vrLoc = 0; + }; + B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */; + name = "IOBuffer.cpp.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1056; + vrLoc = 1363; + }; + B6E5F18111A76B74000AD141 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 460"; + rLen = 0; + rLoc = 9665; + rType = 0; + vrLen = 797; + vrLoc = 8547; + }; + B6E5F18211A76B74000AD141 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAD111A09DB500C90DCE /* Exception.cpp */; + name = "Exception.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 157; + vrLoc = 0; + }; + B6F3642811AA1DC80045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB0611A0AC4800C90DCE /* Adaptor.h */; + name = "Adaptor.h: 82"; + rLen = 0; + rLoc = 1806; + rType = 0; + vrLen = 606; + vrLoc = 688; + }; + B6F3642D11AA1E070045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; + name = "Endian.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 907; + vrLoc = 0; + }; + B6F3642F11AA1E150045E114 /* NibbleTest.cpp:74 */ = { + isa = PBXFileBreakpoint; + actions = ( + ); + breakpointStyle = 0; + continueAfterActions = 0; + countType = 0; + delayBeforeContinue = 0; + fileReference = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + functionName = "main(int argc, char **argv)"; + hitCount = 1; + ignoreCount = 0; + lineNumber = 74; + location = NibbleTest; + modificationTime = 296363160.221059; + originalNumberOfMultipleMatches = 1; + state = 1; + }; + B6F3646211AA26810045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB0611A0AC4800C90DCE /* Adaptor.h */; + name = "Adaptor.h: 82"; + rLen = 0; + rLoc = 1806; + rType = 0; + vrLen = 1168; + vrLoc = 442; + }; + B6F3646E11AB35F00045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB0611A0AC4800C90DCE /* Adaptor.h */; + name = "Adaptor.h: 82"; + rLen = 0; + rLoc = 1806; + rType = 0; + vrLen = 660; + vrLoc = 950; + }; + B6F3646F11AB35F00045E114 /* PBXBookmark */ = { + isa = PBXBookmark; + fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + }; + B6F3647011AB35F00045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + name = "NibbleTest.cpp: 70"; + rLen = 0; + rLoc = 1570; + rType = 0; + vrLen = 470; + vrLoc = 1269; + }; + B6F3647111AB35FE0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB0611A0AC4800C90DCE /* Adaptor.h */; + name = "Adaptor.h: 82"; + rLen = 0; + rLoc = 1806; + rType = 0; + vrLen = 1126; + vrLoc = 442; + }; + B6F3647211AB35FE0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + name = "NibbleTest.cpp: 70"; + rLen = 0; + rLoc = 1570; + rType = 0; + vrLen = 940; + vrLoc = 917; + }; + B6F3647B11AB361D0045E114 /* xattr.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 5434}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 985}"; + }; + }; + B6F3647F11AB36260045E114 /* xattr */ = { + activeExec = 0; + executables = ( + B6F3648111AB36260045E114 /* xattr */, + ); + }; + B6F3648111AB36260045E114 /* xattr */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 0; + configStateDict = { + }; + customDataFormattersEnabled = 1; + dataTipCustomDataFormattersEnabled = 1; + dataTipShowTypeColumn = 1; + dataTipSortType = 0; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + libgmallocEnabled = 0; + name = xattr; + showTypeColumn = 0; + sourceDirectories = ( + ); + }; +} diff --git a/PROFuseX.xcodeproj/kelvin.perspectivev3 b/PROFuseX.xcodeproj/kelvin.perspectivev3 new file mode 100644 index 0000000..7a90b8e --- /dev/null +++ b/PROFuseX.xcodeproj/kelvin.perspectivev3 @@ -0,0 +1,1525 @@ + + + + + ActivePerspectiveName + Project + AllowedModules + + + BundleLoadPath + + MaxInstances + n + Module + PBXSmartGroupTreeModule + Name + Groups and Files Outline View + + + BundleLoadPath + + MaxInstances + n + Module + PBXNavigatorGroup + Name + Editor + + + BundleLoadPath + + MaxInstances + n + Module + XCTaskListModule + Name + Task List + + + BundleLoadPath + + MaxInstances + n + Module + XCDetailModule + Name + File and Smart Group Detail Viewer + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXBuildResultsModule + Name + Detailed Build Results Viewer + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXProjectFindModule + Name + Project Batch Find Tool + + + BundleLoadPath + + MaxInstances + n + Module + XCProjectFormatConflictsModule + Name + Project Format Conflicts List + + + BundleLoadPath + + MaxInstances + n + Module + PBXBookmarksModule + Name + Bookmarks Tool + + + BundleLoadPath + + MaxInstances + n + Module + PBXClassBrowserModule + Name + Class Browser + + + BundleLoadPath + + MaxInstances + n + Module + PBXCVSModule + Name + Source Code Control Tool + + + BundleLoadPath + + MaxInstances + n + Module + PBXDebugBreakpointsModule + Name + Debug Breakpoints Tool + + + BundleLoadPath + + MaxInstances + n + Module + XCDockableInspector + Name + Inspector + + + BundleLoadPath + + MaxInstances + n + Module + PBXOpenQuicklyModule + Name + Open Quickly Tool + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXDebugSessionModule + Name + Debugger + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXDebugCLIModule + Name + Debug Console + + + BundleLoadPath + + MaxInstances + n + Module + XCSnapshotModule + Name + Snapshots Tool + + + BundlePath + /Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources + Description + AIODescriptionKey + DockingSystemVisible + + Extension + perspectivev3 + FavBarConfig + + PBXProjectModuleGUID + B63EFA6611A093C200C90DCE + XCBarModuleItemNames + + XCBarModuleItems + + + FirstTimeWindowDisplayed + + Identifier + com.apple.perspectives.project.defaultV3 + MajorVersion + 34 + MinorVersion + 0 + Name + All-In-One + Notifications + + OpenEditors + + PerspectiveWidths + + 1239 + 1239 + + Perspectives + + + ChosenToolbarItems + + XCToolbarPerspectiveControl + NSToolbarSeparatorItem + active-combo-popup + action + NSToolbarFlexibleSpaceItem + debugger-enable-breakpoints + build-and-go + com.apple.ide.PBXToolbarStopButton + get-info + NSToolbarFlexibleSpaceItem + com.apple.pbx.toolbar.searchfield + + ControllerClassBaseName + + IconName + WindowOfProject + Identifier + perspective.project + IsVertical + + Layout + + + BecomeActive + + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C37FBAC04509CD000000102 + 1C37FAAC04509CD000000102 + 1C37FABC05509CD000000102 + 1C37FABC05539CD112110102 + E2644B35053B69B200211256 + 1C37FABC04509CD000100104 + 1CC0EA4004350EF90044410B + 1CC0EA4004350EF90041110B + 1C77FABC04509CD000000102 + + PBXProjectModuleGUID + 1CA23ED40692098700951B8B + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + yes + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 318 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 08FB7794FE84155DC02AAC07 + B656ADED11A84D3200AB578A + 1C37FBAC04509CD000000102 + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 2 + 0 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {318, 941}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + + + GeometryConfiguration + + Frame + {{0, 0}, {335, 959}} + GroupTreeTableConfiguration + + MainColumn + 318 + + RubberWindowFrame + 394 69 1239 1000 0 0 1920 1178 + + Module + PBXSmartGroupTreeModule + Proportion + 335pt + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + B63EFA6111A093C200C90DCE + PBXProjectModuleLabel + NibbleTest.cpp + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + B63EFA6211A093C200C90DCE + PBXProjectModuleLabel + NibbleTest.cpp + _historyCapacity + 0 + bookmark + B6F3647211AB35FE0045E114 + history + + B63EFC2611A2D5A400C90DCE + B63EFC2B11A2D5A400C90DCE + B63EFC3211A2D5A400C90DCE + B63EFCB211A3639400C90DCE + B63EFCB611A3639400C90DCE + B63EFD7F11A4436B00C90DCE + B63EFDA011A4488200C90DCE + B63EFDA511A4488200C90DCE + B63EFDA711A4488200C90DCE + B63EFDA911A4488200C90DCE + B63EFDAB11A4488200C90DCE + B63EFDAD11A4488200C90DCE + B63EFDAF11A4488200C90DCE + B63EFDB111A4488200C90DCE + B63EFDB311A4488200C90DCE + B63EFDB711A4488200C90DCE + B63EFDC711A4494C00C90DCE + B63EFDE611A44E9300C90DCE + B63EFDF211A4504200C90DCE + B63EFEA011A488C200C90DCE + B63EFEA111A488C200C90DCE + B63EFEA211A488C200C90DCE + B63EFEA311A488C200C90DCE + B63EFEA711A488C200C90DCE + B63EFEA811A488C200C90DCE + B63EFEA911A488C200C90DCE + B63EFEEC11A4A70400C90DCE + B6E5F0DD11A60726000AD141 + B6E5F0F211A73144000AD141 + B6E5F11211A73340000AD141 + B6E5F13A11A74F2B000AD141 + B6E5F18111A76B74000AD141 + B6E5F18211A76B74000AD141 + B656AE2311A84FA400AB578A + B656AE2411A84FA400AB578A + B656AE2611A84FA400AB578A + B656AE2711A84FA400AB578A + B656AE6511A8591F00AB578A + B656AEA711A9C91600AB578A + B656AEA811A9C91600AB578A + B656AF2711AA10C900AB578A + B656AF2811AA10C900AB578A + B656AF2A11AA10C900AB578A + B6F3642D11AA1E070045E114 + B6F3647111AB35FE0045E114 + B6F3647011AB35F00045E114 + + + SplitCount + 1 + + StatusBarVisibility + + XCSharingToken + com.apple.Xcode.CommonNavigatorGroupSharingToken + + GeometryConfiguration + + Frame + {{0, 0}, {899, 562}} + RubberWindowFrame + 394 69 1239 1000 0 0 1920 1178 + + Module + PBXNavigatorGroup + Proportion + 562pt + + + Proportion + 392pt + Tabs + + + ContentConfiguration + + PBXProjectModuleGUID + 1CA23EDF0692099D00951B8B + PBXProjectModuleLabel + Detail + + GeometryConfiguration + + Frame + {{10, 27}, {899, 365}} + RubberWindowFrame + 394 69 1239 1000 0 0 1920 1178 + + Module + XCDetailModule + + + ContentConfiguration + + PBXProjectModuleGUID + 1CA23EE00692099D00951B8B + PBXProjectModuleLabel + Project Find + + GeometryConfiguration + + Frame + {{10, 27}, {899, 341}} + + Module + PBXProjectFindModule + + + ContentConfiguration + + PBXCVSModuleFilterTypeKey + 1032 + PBXProjectModuleGUID + 1CA23EE10692099D00951B8B + PBXProjectModuleLabel + SCM Results + + GeometryConfiguration + + Frame + {{10, 31}, {603, 297}} + + Module + PBXCVSModule + + + ContentConfiguration + + PBXProjectModuleGUID + XCMainBuildResultsModuleGUID + PBXProjectModuleLabel + Build Results + XCBuildResultsTrigger_Collapse + 1021 + XCBuildResultsTrigger_Open + 1011 + + GeometryConfiguration + + Frame + {{10, 27}, {899, 349}} + + Module + PBXBuildResultsModule + + + + + Proportion + 899pt + + + Name + Project + ServiceClasses + + XCModuleDock + PBXSmartGroupTreeModule + XCModuleDock + PBXNavigatorGroup + XCDockableTabModule + XCDetailModule + PBXProjectFindModule + PBXCVSModule + PBXBuildResultsModule + + TableOfContents + + B6F3647311AB35FE0045E114 + 1CA23ED40692098700951B8B + B6F3647411AB35FE0045E114 + B63EFA6111A093C200C90DCE + B6F3647511AB35FE0045E114 + 1CA23EDF0692099D00951B8B + 1CA23EE00692099D00951B8B + 1CA23EE10692099D00951B8B + XCMainBuildResultsModuleGUID + + ToolbarConfigUserDefaultsMinorVersion + 2 + ToolbarConfiguration + xcode.toolbar.config.defaultV3 + + + ChosenToolbarItems + + XCToolbarPerspectiveControl + NSToolbarSeparatorItem + active-combo-popup + NSToolbarFlexibleSpaceItem + debugger-enable-breakpoints + build-and-go + com.apple.ide.PBXToolbarStopButton + debugger-restart-executable + debugger-pause + debugger-step-over + debugger-step-into + debugger-step-out + NSToolbarFlexibleSpaceItem + servicesModulebreakpoints + debugger-show-console-window + + ControllerClassBaseName + PBXDebugSessionModule + IconName + DebugTabIcon + Identifier + perspective.debug + IsVertical + + Layout + + + ContentConfiguration + + PBXProjectModuleGUID + 1CCC7628064C1048000F2A68 + PBXProjectModuleLabel + Debugger Console + + GeometryConfiguration + + Frame + {{0, 0}, {1239, 320}} + + Module + PBXDebugCLIModule + Proportion + 320pt + + + ContentConfiguration + + Debugger + + HorizontalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {605, 308}} + {{605, 0}, {634, 308}} + + + VerticalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {1239, 308}} + {{0, 308}, {1239, 326}} + + + + LauncherConfigVersion + 8 + PBXProjectModuleGUID + 1CCC7629064C1048000F2A68 + PBXProjectModuleLabel + Debug + + GeometryConfiguration + + DebugConsoleVisible + None + DebugConsoleWindowFrame + {{200, 200}, {500, 300}} + DebugSTDIOWindowFrame + {{200, 200}, {500, 300}} + Frame + {{0, 325}, {1239, 634}} + PBXDebugSessionStackFrameViewKey + + DebugVariablesTableConfiguration + + Name + 193 + Value + 126 + Summary + 290 + + Frame + {{605, 0}, {634, 308}} + + + Module + PBXDebugSessionModule + Proportion + 634pt + + + Name + Debug + ServiceClasses + + XCModuleDock + PBXDebugCLIModule + PBXDebugSessionModule + PBXDebugProcessAndThreadModule + PBXDebugProcessViewModule + PBXDebugThreadViewModule + PBXDebugStackFrameViewModule + PBXNavigatorGroup + + TableOfContents + + B6F3647611AB35FE0045E114 + 1CCC7628064C1048000F2A68 + 1CCC7629064C1048000F2A68 + B6F3647711AB35FE0045E114 + B6F3647811AB35FE0045E114 + B6F3647911AB35FE0045E114 + B6F3647A11AB35FE0045E114 + B63EFA6111A093C200C90DCE + + ToolbarConfigUserDefaultsMinorVersion + 2 + ToolbarConfiguration + xcode.toolbar.config.debugV3 + + + PerspectivesBarVisible + + ShelfIsVisible + + SourceDescription + file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecification.xcperspec' + StatusbarIsVisible + + TimeStamp + 0.0 + ToolbarConfigUserDefaultsMinorVersion + 2 + ToolbarDisplayMode + 1 + ToolbarIsVisible + + ToolbarSizeMode + 1 + Type + Perspectives + UpdateMessage + + WindowJustification + 5 + WindowOrderList + + /Users/kelvin/Projects/PROFuseX/PROFuseX.xcodeproj + + WindowString + 394 69 1239 1000 0 0 1920 1178 + WindowToolsV3 + + + Identifier + windowTool.debugger + Layout + + + Dock + + + ContentConfiguration + + Debugger + + HorizontalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {317, 164}} + {{317, 0}, {377, 164}} + + + VerticalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {694, 164}} + {{0, 164}, {694, 216}} + + + + LauncherConfigVersion + 8 + PBXProjectModuleGUID + 1C162984064C10D400B95A72 + PBXProjectModuleLabel + Debug - GLUTExamples (Underwater) + + GeometryConfiguration + + DebugConsoleDrawerSize + {100, 120} + DebugConsoleVisible + None + DebugConsoleWindowFrame + {{200, 200}, {500, 300}} + DebugSTDIOWindowFrame + {{200, 200}, {500, 300}} + Frame + {{0, 0}, {694, 380}} + RubberWindowFrame + 321 238 694 422 0 0 1440 878 + + Module + PBXDebugSessionModule + Proportion + 100% + + + Proportion + 100% + + + Name + Debugger + ServiceClasses + + PBXDebugSessionModule + + StatusbarIsVisible + 1 + TableOfContents + + 1CD10A99069EF8BA00B06720 + 1C0AD2AB069F1E9B00FABCE6 + 1C162984064C10D400B95A72 + 1C0AD2AC069F1E9B00FABCE6 + + ToolbarConfiguration + xcode.toolbar.config.debugV3 + WindowString + 321 238 694 422 0 0 1440 878 + WindowToolGUID + 1CD10A99069EF8BA00B06720 + WindowToolIsVisible + 0 + + + Identifier + windowTool.build + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1CD0528F0623707200166675 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1CD052900623707200166675 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {500, 215}} + RubberWindowFrame + 192 257 500 500 0 0 1280 1002 + + Module + PBXNavigatorGroup + Proportion + 218pt + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + XCMainBuildResultsModuleGUID + PBXProjectModuleLabel + Build Results + + GeometryConfiguration + + Frame + {{0, 222}, {500, 236}} + RubberWindowFrame + 192 257 500 500 0 0 1280 1002 + + Module + PBXBuildResultsModule + Proportion + 236pt + + + Proportion + 458pt + + + Name + Build Results + ServiceClasses + + PBXBuildResultsModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C78EAA5065D492600B07095 + 1C78EAA6065D492600B07095 + 1CD0528F0623707200166675 + XCMainBuildResultsModuleGUID + + ToolbarConfiguration + xcode.toolbar.config.buildV3 + WindowString + 192 257 500 500 0 0 1280 1002 + + + Identifier + windowTool.find + Layout + + + Dock + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1CDD528C0622207200134675 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1CD0528D0623707200166675 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {781, 167}} + RubberWindowFrame + 62 385 781 470 0 0 1440 878 + + Module + PBXNavigatorGroup + Proportion + 781pt + + + Proportion + 50% + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1CD0528E0623707200166675 + PBXProjectModuleLabel + Project Find + + GeometryConfiguration + + Frame + {{8, 0}, {773, 254}} + RubberWindowFrame + 62 385 781 470 0 0 1440 878 + + Module + PBXProjectFindModule + Proportion + 50% + + + Proportion + 428pt + + + Name + Project Find + ServiceClasses + + PBXProjectFindModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C530D57069F1CE1000CFCEE + 1C530D58069F1CE1000CFCEE + 1C530D59069F1CE1000CFCEE + 1CDD528C0622207200134675 + 1C530D5A069F1CE1000CFCEE + 1CE0B1FE06471DED0097A5F4 + 1CD0528E0623707200166675 + + WindowString + 62 385 781 470 0 0 1440 878 + WindowToolGUID + 1C530D57069F1CE1000CFCEE + WindowToolIsVisible + 0 + + + Identifier + windowTool.snapshots + Layout + + + Dock + + + Module + XCSnapshotModule + Proportion + 100% + + + Proportion + 100% + + + Name + Snapshots + ServiceClasses + + XCSnapshotModule + + StatusbarIsVisible + Yes + ToolbarConfiguration + xcode.toolbar.config.snapshots + WindowString + 315 824 300 550 0 0 1440 878 + WindowToolIsVisible + Yes + + + FirstTimeWindowDisplayed + + Identifier + windowTool.debuggerConsole + IsVertical + + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1C78EAAC065D492600B07095 + PBXProjectModuleLabel + Debugger Console + + GeometryConfiguration + + Frame + {{0, 0}, {440, 359}} + RubberWindowFrame + 98 717 440 400 0 0 1920 1178 + + Module + PBXDebugCLIModule + Proportion + 359pt + + + Proportion + 359pt + + + Name + Debugger Console + ServiceClasses + + PBXDebugCLIModule + + StatusbarIsVisible + + TableOfContents + + 1C530D5B069F1CE1000CFCEE + B656AF7911AA19CD00AB578A + 1C78EAAC065D492600B07095 + + ToolbarConfiguration + xcode.toolbar.config.consoleV3 + WindowString + 98 717 440 400 0 0 1920 1178 + WindowToolGUID + 1C530D5B069F1CE1000CFCEE + WindowToolIsVisible + + + + Identifier + windowTool.scm + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1C78EAB2065D492600B07095 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1C78EAB3065D492600B07095 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {452, 0}} + RubberWindowFrame + 743 379 452 308 0 0 1280 1002 + + Module + PBXNavigatorGroup + Proportion + 0pt + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1CD052920623707200166675 + PBXProjectModuleLabel + SCM + + GeometryConfiguration + + ConsoleFrame + {{0, 259}, {452, 0}} + Frame + {{0, 7}, {452, 259}} + RubberWindowFrame + 743 379 452 308 0 0 1280 1002 + TableConfiguration + + Status + 30 + FileName + 199 + Path + 197.09500122070312 + + TableFrame + {{0, 0}, {452, 250}} + + Module + PBXCVSModule + Proportion + 262pt + + + Proportion + 266pt + + + Name + SCM + ServiceClasses + + PBXCVSModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C78EAB4065D492600B07095 + 1C78EAB5065D492600B07095 + 1C78EAB2065D492600B07095 + 1CD052920623707200166675 + + ToolbarConfiguration + xcode.toolbar.config.scmV3 + WindowString + 743 379 452 308 0 0 1280 1002 + + + FirstTimeWindowDisplayed + + Identifier + windowTool.breakpoints + IsVertical + + Layout + + + Dock + + + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C77FABC04509CD000000102 + + PBXProjectModuleGUID + 1CE0B1FE06471DED0097A5F4 + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + no + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 168 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 1C77FABC04509CD000000102 + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 0 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {168, 350}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + + + GeometryConfiguration + + Frame + {{0, 0}, {185, 368}} + GroupTreeTableConfiguration + + MainColumn + 168 + + RubberWindowFrame + 215 685 744 409 0 0 1920 1178 + + Module + PBXSmartGroupTreeModule + Proportion + 185pt + + + BecomeActive + + ContentConfiguration + + PBXProjectModuleGUID + 1CA1AED706398EBD00589147 + PBXProjectModuleLabel + Detail + + GeometryConfiguration + + Frame + {{190, 0}, {554, 368}} + RubberWindowFrame + 215 685 744 409 0 0 1920 1178 + + Module + XCDetailModule + Proportion + 554pt + + + Proportion + 368pt + + + MajorVersion + 3 + MinorVersion + 0 + Name + Breakpoints + ServiceClasses + + PBXSmartGroupTreeModule + XCDetailModule + + StatusbarIsVisible + + TableOfContents + + B656AF4511AA12DA00AB578A + B656AF4611AA12DA00AB578A + 1CE0B1FE06471DED0097A5F4 + 1CA1AED706398EBD00589147 + + ToolbarConfiguration + xcode.toolbar.config.breakpointsV3 + WindowString + 215 685 744 409 0 0 1920 1178 + WindowToolGUID + B656AF4511AA12DA00AB578A + WindowToolIsVisible + + + + Identifier + windowTool.debugAnimator + Layout + + + Dock + + + Module + PBXNavigatorGroup + Proportion + 100% + + + Proportion + 100% + + + Name + Debug Visualizer + ServiceClasses + + PBXNavigatorGroup + + StatusbarIsVisible + 1 + ToolbarConfiguration + xcode.toolbar.config.debugAnimatorV3 + WindowString + 100 100 700 500 0 0 1280 1002 + + + Identifier + windowTool.bookmarks + Layout + + + Dock + + + Module + PBXBookmarksModule + Proportion + 166pt + + + Proportion + 166pt + + + Name + Bookmarks + ServiceClasses + + PBXBookmarksModule + + StatusbarIsVisible + 0 + WindowString + 538 42 401 187 0 0 1280 1002 + + + Identifier + windowTool.projectFormatConflicts + Layout + + + Dock + + + Module + XCProjectFormatConflictsModule + Proportion + 100% + + + Proportion + 100% + + + Name + Project Format Conflicts + ServiceClasses + + XCProjectFormatConflictsModule + + StatusbarIsVisible + 0 + WindowContentMinSize + 450 300 + WindowString + 50 850 472 307 0 0 1440 877 + + + Identifier + windowTool.classBrowser + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + OptionsSetName + Hierarchy, all classes + PBXProjectModuleGUID + 1CA6456E063B45B4001379D8 + PBXProjectModuleLabel + Class Browser - NSObject + + GeometryConfiguration + + ClassesFrame + {{0, 0}, {369, 96}} + ClassesTreeTableConfiguration + + PBXClassNameColumnIdentifier + 208 + PBXClassBookColumnIdentifier + 22 + + Frame + {{0, 0}, {616, 353}} + MembersFrame + {{0, 105}, {369, 395}} + MembersTreeTableConfiguration + + PBXMemberTypeIconColumnIdentifier + 22 + PBXMemberNameColumnIdentifier + 216 + PBXMemberTypeColumnIdentifier + 94 + PBXMemberBookColumnIdentifier + 22 + + PBXModuleWindowStatusBarHidden2 + 1 + RubberWindowFrame + 597 125 616 374 0 0 1280 1002 + + Module + PBXClassBrowserModule + Proportion + 354pt + + + Proportion + 354pt + + + Name + Class Browser + ServiceClasses + + PBXClassBrowserModule + + StatusbarIsVisible + 0 + TableOfContents + + 1C78EABA065D492600B07095 + 1C78EABB065D492600B07095 + 1CA6456E063B45B4001379D8 + + ToolbarConfiguration + xcode.toolbar.config.classbrowser + WindowString + 597 125 616 374 0 0 1280 1002 + + + Identifier + windowTool.refactoring + IncludeInToolsMenu + 0 + Layout + + + Dock + + + BecomeActive + 1 + GeometryConfiguration + + Frame + {0, 0}, {500, 335} + RubberWindowFrame + {0, 0}, {500, 335} + + Module + XCRefactoringModule + Proportion + 100% + + + Proportion + 100% + + + Name + Refactoring + ServiceClasses + + XCRefactoringModule + + WindowString + 200 200 500 356 0 0 1920 1200 + + + + diff --git a/PROFuseX.xcodeproj/project.pbxproj b/PROFuseX.xcodeproj/project.pbxproj new file mode 100644 index 0000000..f1fbefc --- /dev/null +++ b/PROFuseX.xcodeproj/project.pbxproj @@ -0,0 +1,868 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + B63EFCD211A36C8B00C90DCE /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; + B63EFCD311A36C8B00C90DCE /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; + B63EFCD411A36C8B00C90DCE /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; + B63EFCD511A36C8B00C90DCE /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; + B63EFCD611A36C8B00C90DCE /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; + B63EFCD711A36C8B00C90DCE /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; + B63EFCD811A36C8B00C90DCE /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; + B63EFCD911A36C8B00C90DCE /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; + B63EFCDA11A36C8B00C90DCE /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; + B63EFCDB11A36C8B00C90DCE /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; + B63EFCDC11A36C8B00C90DCE /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; + B63EFCDD11A36C8B00C90DCE /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; + B63EFCDE11A36C8B00C90DCE /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD111A09DB500C90DCE /* Exception.cpp */; }; + B63EFCDF11A36C8B00C90DCE /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD311A09DB500C90DCE /* Lock.cpp */; }; + B63EFCE011A36C8B00C90DCE /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; + B63EFCE111A36C8B00C90DCE /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; }; + B63EFCE211A36C8B00C90DCE /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; + B63EFCE311A36C8B00C90DCE /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; + B63EFCE511A36C8B00C90DCE /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; + B63EFCE911A36C8B00C90DCE /* apfm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; }; + B63EFE8511A4888500C90DCE /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; + B63EFE8611A4888500C90DCE /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; + B63EFE8711A4888500C90DCE /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; + B63EFE8811A4888500C90DCE /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; + B63EFE8911A4888500C90DCE /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; + B63EFE8A11A4888500C90DCE /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; + B63EFE8B11A4888500C90DCE /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; + B63EFE8C11A4888500C90DCE /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; + B63EFE8D11A4888500C90DCE /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; + B63EFE8E11A4888500C90DCE /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; + B63EFE8F11A4888500C90DCE /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; + B63EFE9011A4888500C90DCE /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; + B63EFE9111A4888500C90DCE /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD111A09DB500C90DCE /* Exception.cpp */; }; + B63EFE9211A4888500C90DCE /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD311A09DB500C90DCE /* Lock.cpp */; }; + B63EFE9311A4888500C90DCE /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; + B63EFE9411A4888500C90DCE /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; }; + B63EFE9511A4888500C90DCE /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; + B63EFE9611A4888500C90DCE /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; + B63EFE9711A4888500C90DCE /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; + B63EFE9911A4888500C90DCE /* newfs_pascal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; }; + B656AE0811A84F6C00AB578A /* libfuse_ino64.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */; }; + B656AE0911A84F7700AB578A /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; + B656AE0A11A84F7700AB578A /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; + B656AE0B11A84F7700AB578A /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; + B656AE0C11A84F7700AB578A /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; + B656AE0D11A84F7700AB578A /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; + B656AE0E11A84F7700AB578A /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; + B656AE0F11A84F7700AB578A /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; + B656AE1011A84F7700AB578A /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; + B656AE1111A84F7700AB578A /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; + B656AE1211A84F7700AB578A /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; + B656AE1311A84F7700AB578A /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; + B656AE1411A84F7700AB578A /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; + B656AE1511A84F7700AB578A /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD111A09DB500C90DCE /* Exception.cpp */; }; + B656AE1611A84F7700AB578A /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD311A09DB500C90DCE /* Lock.cpp */; }; + B656AE1711A84F7700AB578A /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; + B656AE1811A84F7700AB578A /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; }; + B656AE1911A84F7700AB578A /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; + B656AE1A11A84F7700AB578A /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; + B656AE1B11A84F7700AB578A /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; + B656AE1D11A84F9300AB578A /* fuse_pascal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */; }; + B656AE1E11A84F9300AB578A /* fuse_pascal_ops.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFC9D11A35F8200C90DCE /* fuse_pascal_ops.cpp */; }; + B656AF0811AA106400AB578A /* NibbleTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; }; + B656AF0911AA106C00AB578A /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; + B656AF0A11AA106C00AB578A /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; + B656AF0B11AA106C00AB578A /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; + B656AF0C11AA106C00AB578A /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; + B656AF0D11AA106C00AB578A /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; + B656AF0E11AA106C00AB578A /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; + B656AF0F11AA106C00AB578A /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; + B656AF1011AA106C00AB578A /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; + B656AF1111AA106C00AB578A /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; + B656AF1211AA106C00AB578A /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; + B656AF1311AA106C00AB578A /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; + B656AF1411AA106C00AB578A /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; + B656AF1511AA106C00AB578A /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD111A09DB500C90DCE /* Exception.cpp */; }; + B656AF1611AA106C00AB578A /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD311A09DB500C90DCE /* Lock.cpp */; }; + B656AF1711AA106C00AB578A /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; + B656AF1811AA106C00AB578A /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; }; + B656AF1911AA106C00AB578A /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; + B656AF1A11AA106C00AB578A /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; + B656AF1B11AA106C00AB578A /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; + B6F3648511AB363B0045E114 /* xattr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3647B11AB361D0045E114 /* xattr.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + B63EFA7511A0948500C90DCE /* Endian.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Endian.cpp; sourceTree = ""; }; + B63EFA7611A0948500C90DCE /* Endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Endian.h; sourceTree = ""; }; + B63EFA7711A0948500C90DCE /* IOBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOBuffer.h; sourceTree = ""; }; + B63EFA9511A094E000C90DCE /* BlockDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BlockDevice.cpp; sourceTree = ""; }; + B63EFA9611A094E000C90DCE /* BlockDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockDevice.h; sourceTree = ""; }; + B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DavexDiskImage.cpp; sourceTree = ""; }; + B63EFA9811A094E000C90DCE /* DavexDiskImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DavexDiskImage.h; sourceTree = ""; }; + B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DiskCopy42Image.cpp; sourceTree = ""; }; + B63EFA9C11A094E000C90DCE /* DiskCopy42Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiskCopy42Image.h; sourceTree = ""; }; + B63EFA9D11A094E000C90DCE /* DiskImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DiskImage.cpp; sourceTree = ""; }; + B63EFA9E11A094E000C90DCE /* DiskImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiskImage.h; sourceTree = ""; }; + B63EFAA111A094E000C90DCE /* RawDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RawDevice.cpp; sourceTree = ""; }; + B63EFAA211A094E000C90DCE /* RawDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RawDevice.h; sourceTree = ""; }; + B63EFAA311A094E000C90DCE /* TrackSector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackSector.h; sourceTree = ""; }; + B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UniversalDiskImage.cpp; sourceTree = ""; }; + B63EFAA511A094E000C90DCE /* UniversalDiskImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UniversalDiskImage.h; sourceTree = ""; }; + B63EFAB611A098C400C90DCE /* BlockCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BlockCache.cpp; sourceTree = ""; }; + B63EFAB711A098C400C90DCE /* BlockCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockCache.h; sourceTree = ""; }; + B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConcreteBlockCache.cpp; sourceTree = ""; }; + B63EFAB911A098C400C90DCE /* ConcreteBlockCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConcreteBlockCache.h; sourceTree = ""; }; + B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MappedBlockCache.cpp; sourceTree = ""; }; + B63EFABB11A098C400C90DCE /* MappedBlockCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MappedBlockCache.h; sourceTree = ""; }; + B63EFAC911A09DAA00C90DCE /* File.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = File.cpp; sourceTree = ""; }; + B63EFACA11A09DAA00C90DCE /* File.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = File.h; sourceTree = ""; }; + B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MappedFile.cpp; sourceTree = ""; }; + B63EFACC11A09DAA00C90DCE /* MappedFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MappedFile.h; sourceTree = ""; }; + B63EFAD011A09DB500C90DCE /* auto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = auto.h; sourceTree = ""; }; + B63EFAD111A09DB500C90DCE /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = ""; }; + B63EFAD211A09DB500C90DCE /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; + B63EFAD311A09DB500C90DCE /* Lock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Lock.cpp; sourceTree = ""; }; + B63EFAD411A09DB500C90DCE /* Lock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Lock.h; sourceTree = ""; }; + B63EFB0611A0AC4800C90DCE /* Adaptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Adaptor.h; sourceTree = ""; }; + B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Adaptor.cpp; sourceTree = ""; }; + B63EFBE811A244EE00C90DCE /* Date.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Date.cpp; sourceTree = ""; }; + B63EFBE911A244EE00C90DCE /* Date.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Date.h; sourceTree = ""; }; + B63EFBEA11A244EE00C90DCE /* Entry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Entry.cpp; sourceTree = ""; }; + B63EFBEB11A244EE00C90DCE /* File.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = File.h; sourceTree = ""; }; + B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileEntry.cpp; sourceTree = ""; }; + B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VolumeEntry.cpp; sourceTree = ""; }; + B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOBuffer.cpp.h; sourceTree = ""; }; + B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fuse_pascal.cpp; sourceTree = ""; }; + B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = newfs_pascal.cpp; sourceTree = ""; }; + B63EFC9D11A35F8200C90DCE /* fuse_pascal_ops.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fuse_pascal_ops.cpp; sourceTree = ""; }; + B63EFC9F11A35F8F00C90DCE /* apfm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = apfm.cpp; sourceTree = ""; }; + B63EFCCE11A36C7300C90DCE /* apfpm */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = apfpm; sourceTree = BUILT_PRODUCTS_DIR; }; + B63EFE8111A4886C00C90DCE /* newfs_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = newfs_pascal; sourceTree = BUILT_PRODUCTS_DIR; }; + B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libfuse_ino64.dylib; path = /usr/local/lib/libfuse_ino64.dylib; sourceTree = ""; }; + B656AE0311A84F5800AB578A /* fuse_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fuse_pascal; sourceTree = BUILT_PRODUCTS_DIR; }; + B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NibbleTest.cpp; sourceTree = ""; }; + B656AF0311AA105500AB578A /* NibbleTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NibbleTest; sourceTree = BUILT_PRODUCTS_DIR; }; + B6F3647B11AB361D0045E114 /* xattr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xattr.cpp; sourceTree = ""; }; + B6F3648011AB36260045E114 /* xattr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = xattr; path = build/Debug/xattr; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + B63EFCCC11A36C7300C90DCE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B63EFE7F11A4886C00C90DCE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B656AE0111A84F5800AB578A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B656AE0811A84F6C00AB578A /* libfuse_ino64.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B656AF0111AA105500AB578A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B6F3647E11AB36260045E114 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* PROFuseX */ = { + isa = PBXGroup; + children = ( + B6F3647B11AB361D0045E114 /* xattr.cpp */, + B63EFC9F11A35F8F00C90DCE /* apfm.cpp */, + B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */, + B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */, + B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */, + B63EFC9D11A35F8200C90DCE /* fuse_pascal_ops.cpp */, + B63EFBE711A244EE00C90DCE /* Pascal */, + B63EFACF11A09DB500C90DCE /* ProFUSE */, + B63EFAC811A09DAA00C90DCE /* File */, + B63EFAB511A098C400C90DCE /* Cache */, + B63EFA9411A094E000C90DCE /* Device */, + B63EFA7411A0948500C90DCE /* Endian */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + B656ADED11A84D3200AB578A /* Libraries */, + ); + name = PROFuseX; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + B63EFCCE11A36C7300C90DCE /* apfpm */, + B63EFE8111A4886C00C90DCE /* newfs_pascal */, + B656AE0311A84F5800AB578A /* fuse_pascal */, + B656AF0311AA105500AB578A /* NibbleTest */, + B6F3648011AB36260045E114 /* xattr */, + ); + name = Products; + sourceTree = ""; + }; + B63EFA7411A0948500C90DCE /* Endian */ = { + isa = PBXGroup; + children = ( + B63EFA7511A0948500C90DCE /* Endian.cpp */, + B63EFA7611A0948500C90DCE /* Endian.h */, + B63EFA7711A0948500C90DCE /* IOBuffer.h */, + B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */, + ); + path = Endian; + sourceTree = ""; + }; + B63EFA9411A094E000C90DCE /* Device */ = { + isa = PBXGroup; + children = ( + B63EFA9511A094E000C90DCE /* BlockDevice.cpp */, + B63EFA9611A094E000C90DCE /* BlockDevice.h */, + B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */, + B63EFA9811A094E000C90DCE /* DavexDiskImage.h */, + B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */, + B63EFA9C11A094E000C90DCE /* DiskCopy42Image.h */, + B63EFA9D11A094E000C90DCE /* DiskImage.cpp */, + B63EFA9E11A094E000C90DCE /* DiskImage.h */, + B63EFAA111A094E000C90DCE /* RawDevice.cpp */, + B63EFAA211A094E000C90DCE /* RawDevice.h */, + B63EFAA311A094E000C90DCE /* TrackSector.h */, + B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */, + B63EFAA511A094E000C90DCE /* UniversalDiskImage.h */, + B63EFB0611A0AC4800C90DCE /* Adaptor.h */, + B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */, + ); + path = Device; + sourceTree = ""; + }; + B63EFAB511A098C400C90DCE /* Cache */ = { + isa = PBXGroup; + children = ( + B63EFAB611A098C400C90DCE /* BlockCache.cpp */, + B63EFAB711A098C400C90DCE /* BlockCache.h */, + B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */, + B63EFAB911A098C400C90DCE /* ConcreteBlockCache.h */, + B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */, + B63EFABB11A098C400C90DCE /* MappedBlockCache.h */, + ); + path = Cache; + sourceTree = ""; + }; + B63EFAC811A09DAA00C90DCE /* File */ = { + isa = PBXGroup; + children = ( + B63EFAC911A09DAA00C90DCE /* File.cpp */, + B63EFACA11A09DAA00C90DCE /* File.h */, + B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */, + B63EFACC11A09DAA00C90DCE /* MappedFile.h */, + ); + path = File; + sourceTree = ""; + }; + B63EFACF11A09DB500C90DCE /* ProFUSE */ = { + isa = PBXGroup; + children = ( + B63EFAD011A09DB500C90DCE /* auto.h */, + B63EFAD111A09DB500C90DCE /* Exception.cpp */, + B63EFAD211A09DB500C90DCE /* Exception.h */, + B63EFAD311A09DB500C90DCE /* Lock.cpp */, + B63EFAD411A09DB500C90DCE /* Lock.h */, + ); + path = ProFUSE; + sourceTree = ""; + }; + B63EFBE711A244EE00C90DCE /* Pascal */ = { + isa = PBXGroup; + children = ( + B63EFBE811A244EE00C90DCE /* Date.cpp */, + B63EFBE911A244EE00C90DCE /* Date.h */, + B63EFBEA11A244EE00C90DCE /* Entry.cpp */, + B63EFBEB11A244EE00C90DCE /* File.h */, + B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */, + B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */, + ); + path = Pascal; + sourceTree = ""; + }; + B656ADED11A84D3200AB578A /* Libraries */ = { + isa = PBXGroup; + children = ( + B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */, + ); + name = Libraries; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + B63EFCCD11A36C7300C90DCE /* apfm */ = { + isa = PBXNativeTarget; + buildConfigurationList = B63EFCEC11A36CB800C90DCE /* Build configuration list for PBXNativeTarget "apfm" */; + buildPhases = ( + B63EFCCB11A36C7300C90DCE /* Sources */, + B63EFCCC11A36C7300C90DCE /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = apfm; + productName = apfpm; + productReference = B63EFCCE11A36C7300C90DCE /* apfpm */; + productType = "com.apple.product-type.tool"; + }; + B63EFE8011A4886C00C90DCE /* newfs_pascal */ = { + isa = PBXNativeTarget; + buildConfigurationList = B63EFEB311A488C200C90DCE /* Build configuration list for PBXNativeTarget "newfs_pascal" */; + buildPhases = ( + B63EFE7E11A4886C00C90DCE /* Sources */, + B63EFE7F11A4886C00C90DCE /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = newfs_pascal; + productName = newfs_pascal; + productReference = B63EFE8111A4886C00C90DCE /* newfs_pascal */; + productType = "com.apple.product-type.tool"; + }; + B656AE0211A84F5800AB578A /* fuse_pascal */ = { + isa = PBXNativeTarget; + buildConfigurationList = B656AE3411A84FA400AB578A /* Build configuration list for PBXNativeTarget "fuse_pascal" */; + buildPhases = ( + B656AE0011A84F5800AB578A /* Sources */, + B656AE0111A84F5800AB578A /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = fuse_pascal; + productName = fuse_pascal; + productReference = B656AE0311A84F5800AB578A /* fuse_pascal */; + productType = "com.apple.product-type.tool"; + }; + B656AF0211AA105500AB578A /* NibbleTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = B656AF2111AA10A100AB578A /* Build configuration list for PBXNativeTarget "NibbleTest" */; + buildPhases = ( + B656AF0011AA105500AB578A /* Sources */, + B656AF0111AA105500AB578A /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = NibbleTest; + productName = NibbleTest; + productReference = B656AF0311AA105500AB578A /* NibbleTest */; + productType = "com.apple.product-type.tool"; + }; + B6F3647F11AB36260045E114 /* xattr */ = { + isa = PBXNativeTarget; + buildConfigurationList = B6F3648911AB36590045E114 /* Build configuration list for PBXNativeTarget "xattr" */; + buildPhases = ( + B6F3647D11AB36260045E114 /* Sources */, + B6F3647E11AB36260045E114 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = xattr; + productName = xattr; + productReference = B6F3648011AB36260045E114 /* xattr */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "PROFuseX" */; + compatibilityVersion = "Xcode 3.1"; + hasScannedForEncodings = 1; + mainGroup = 08FB7794FE84155DC02AAC07 /* PROFuseX */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + B63EFCCD11A36C7300C90DCE /* apfm */, + B63EFE8011A4886C00C90DCE /* newfs_pascal */, + B656AE0211A84F5800AB578A /* fuse_pascal */, + B656AF0211AA105500AB578A /* NibbleTest */, + B6F3647F11AB36260045E114 /* xattr */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + B63EFCCB11A36C7300C90DCE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B63EFCD211A36C8B00C90DCE /* Endian.cpp in Sources */, + B63EFCD311A36C8B00C90DCE /* BlockDevice.cpp in Sources */, + B63EFCD411A36C8B00C90DCE /* DavexDiskImage.cpp in Sources */, + B63EFCD511A36C8B00C90DCE /* DiskCopy42Image.cpp in Sources */, + B63EFCD611A36C8B00C90DCE /* DiskImage.cpp in Sources */, + B63EFCD711A36C8B00C90DCE /* RawDevice.cpp in Sources */, + B63EFCD811A36C8B00C90DCE /* UniversalDiskImage.cpp in Sources */, + B63EFCD911A36C8B00C90DCE /* BlockCache.cpp in Sources */, + B63EFCDA11A36C8B00C90DCE /* ConcreteBlockCache.cpp in Sources */, + B63EFCDB11A36C8B00C90DCE /* MappedBlockCache.cpp in Sources */, + B63EFCDC11A36C8B00C90DCE /* File.cpp in Sources */, + B63EFCDD11A36C8B00C90DCE /* MappedFile.cpp in Sources */, + B63EFCDE11A36C8B00C90DCE /* Exception.cpp in Sources */, + B63EFCDF11A36C8B00C90DCE /* Lock.cpp in Sources */, + B63EFCE011A36C8B00C90DCE /* Adaptor.cpp in Sources */, + B63EFCE111A36C8B00C90DCE /* Date.cpp in Sources */, + B63EFCE211A36C8B00C90DCE /* Entry.cpp in Sources */, + B63EFCE311A36C8B00C90DCE /* FileEntry.cpp in Sources */, + B63EFCE511A36C8B00C90DCE /* VolumeEntry.cpp in Sources */, + B63EFCE911A36C8B00C90DCE /* apfm.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B63EFE7E11A4886C00C90DCE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B63EFE8511A4888500C90DCE /* Endian.cpp in Sources */, + B63EFE8611A4888500C90DCE /* BlockDevice.cpp in Sources */, + B63EFE8711A4888500C90DCE /* DavexDiskImage.cpp in Sources */, + B63EFE8811A4888500C90DCE /* DiskCopy42Image.cpp in Sources */, + B63EFE8911A4888500C90DCE /* DiskImage.cpp in Sources */, + B63EFE8A11A4888500C90DCE /* RawDevice.cpp in Sources */, + B63EFE8B11A4888500C90DCE /* UniversalDiskImage.cpp in Sources */, + B63EFE8C11A4888500C90DCE /* BlockCache.cpp in Sources */, + B63EFE8D11A4888500C90DCE /* ConcreteBlockCache.cpp in Sources */, + B63EFE8E11A4888500C90DCE /* MappedBlockCache.cpp in Sources */, + B63EFE8F11A4888500C90DCE /* File.cpp in Sources */, + B63EFE9011A4888500C90DCE /* MappedFile.cpp in Sources */, + B63EFE9111A4888500C90DCE /* Exception.cpp in Sources */, + B63EFE9211A4888500C90DCE /* Lock.cpp in Sources */, + B63EFE9311A4888500C90DCE /* Adaptor.cpp in Sources */, + B63EFE9411A4888500C90DCE /* Date.cpp in Sources */, + B63EFE9511A4888500C90DCE /* Entry.cpp in Sources */, + B63EFE9611A4888500C90DCE /* FileEntry.cpp in Sources */, + B63EFE9711A4888500C90DCE /* VolumeEntry.cpp in Sources */, + B63EFE9911A4888500C90DCE /* newfs_pascal.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B656AE0011A84F5800AB578A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B656AE1D11A84F9300AB578A /* fuse_pascal.cpp in Sources */, + B656AE1E11A84F9300AB578A /* fuse_pascal_ops.cpp in Sources */, + B656AE0911A84F7700AB578A /* Endian.cpp in Sources */, + B656AE0A11A84F7700AB578A /* BlockDevice.cpp in Sources */, + B656AE0B11A84F7700AB578A /* DavexDiskImage.cpp in Sources */, + B656AE0C11A84F7700AB578A /* DiskCopy42Image.cpp in Sources */, + B656AE0D11A84F7700AB578A /* DiskImage.cpp in Sources */, + B656AE0E11A84F7700AB578A /* RawDevice.cpp in Sources */, + B656AE0F11A84F7700AB578A /* UniversalDiskImage.cpp in Sources */, + B656AE1011A84F7700AB578A /* BlockCache.cpp in Sources */, + B656AE1111A84F7700AB578A /* ConcreteBlockCache.cpp in Sources */, + B656AE1211A84F7700AB578A /* MappedBlockCache.cpp in Sources */, + B656AE1311A84F7700AB578A /* File.cpp in Sources */, + B656AE1411A84F7700AB578A /* MappedFile.cpp in Sources */, + B656AE1511A84F7700AB578A /* Exception.cpp in Sources */, + B656AE1611A84F7700AB578A /* Lock.cpp in Sources */, + B656AE1711A84F7700AB578A /* Adaptor.cpp in Sources */, + B656AE1811A84F7700AB578A /* Date.cpp in Sources */, + B656AE1911A84F7700AB578A /* Entry.cpp in Sources */, + B656AE1A11A84F7700AB578A /* FileEntry.cpp in Sources */, + B656AE1B11A84F7700AB578A /* VolumeEntry.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B656AF0011AA105500AB578A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B656AF0911AA106C00AB578A /* Endian.cpp in Sources */, + B656AF0A11AA106C00AB578A /* BlockDevice.cpp in Sources */, + B656AF0B11AA106C00AB578A /* DavexDiskImage.cpp in Sources */, + B656AF0C11AA106C00AB578A /* DiskCopy42Image.cpp in Sources */, + B656AF0D11AA106C00AB578A /* DiskImage.cpp in Sources */, + B656AF0E11AA106C00AB578A /* RawDevice.cpp in Sources */, + B656AF0F11AA106C00AB578A /* UniversalDiskImage.cpp in Sources */, + B656AF1011AA106C00AB578A /* BlockCache.cpp in Sources */, + B656AF1111AA106C00AB578A /* ConcreteBlockCache.cpp in Sources */, + B656AF1211AA106C00AB578A /* MappedBlockCache.cpp in Sources */, + B656AF1311AA106C00AB578A /* File.cpp in Sources */, + B656AF1411AA106C00AB578A /* MappedFile.cpp in Sources */, + B656AF1511AA106C00AB578A /* Exception.cpp in Sources */, + B656AF1611AA106C00AB578A /* Lock.cpp in Sources */, + B656AF1711AA106C00AB578A /* Adaptor.cpp in Sources */, + B656AF1811AA106C00AB578A /* Date.cpp in Sources */, + B656AF1911AA106C00AB578A /* Entry.cpp in Sources */, + B656AF1A11AA106C00AB578A /* FileEntry.cpp in Sources */, + B656AF1B11AA106C00AB578A /* VolumeEntry.cpp in Sources */, + B656AF0811AA106400AB578A /* NibbleTest.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B6F3647D11AB36260045E114 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B6F3648511AB363B0045E114 /* xattr.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB923608733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + /usr/local/include/, + ., + ); + ONLY_ACTIVE_ARCH = YES; + PREBINDING = NO; + SDKROOT = macosx10.6; + }; + name = Debug; + }; + 1DEB923708733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = macosx10.6; + }; + name = Release; + }; + B63EFCD011A36C7300C90DCE /* 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; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = apfpm; + }; + name = Debug; + }; + B63EFCD111A36C7300C90DCE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = apfpm; + ZERO_LINK = NO; + }; + name = Release; + }; + B63EFE8311A4886C00C90DCE /* 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; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = newfs_pascal; + }; + name = Debug; + }; + B63EFE8411A4886C00C90DCE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = newfs_pascal; + ZERO_LINK = NO; + }; + name = Release; + }; + B656AD7A11A84B5D00AB578A /* Debug fuse */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + /usr/local/include/, + ., + ); + ONLY_ACTIVE_ARCH = YES; + PREBINDING = NO; + SDKROOT = macosx10.6; + }; + name = "Debug fuse"; + }; + B656AD7C11A84B5D00AB578A /* Debug fuse */ = { + 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; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = apfpm; + }; + name = "Debug fuse"; + }; + B656AD7D11A84B5D00AB578A /* Debug fuse */ = { + 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; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = newfs_pascal; + }; + name = "Debug fuse"; + }; + B656AE0511A84F5900AB578A /* 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; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = fuse_pascal; + }; + name = Debug; + }; + B656AE0611A84F5900AB578A /* Debug fuse */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = fuse_pascal; + }; + name = "Debug fuse"; + }; + B656AE0711A84F5900AB578A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = fuse_pascal; + ZERO_LINK = NO; + }; + name = Release; + }; + B656AF0511AA105600AB578A /* 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; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = NibbleTest; + }; + name = Debug; + }; + B656AF0611AA105600AB578A /* Debug fuse */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = NibbleTest; + }; + name = "Debug fuse"; + }; + B656AF0711AA105600AB578A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = NibbleTest; + ZERO_LINK = NO; + }; + name = Release; + }; + B6F3648211AB36260045E114 /* 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; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = xattr; + }; + name = Debug; + }; + B6F3648311AB36260045E114 /* Debug fuse */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = xattr; + }; + name = "Debug fuse"; + }; + B6F3648411AB36260045E114 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = xattr; + ZERO_LINK = NO; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "PROFuseX" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923608733DC60010E9CD /* Debug */, + B656AD7A11A84B5D00AB578A /* Debug fuse */, + 1DEB923708733DC60010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B63EFCEC11A36CB800C90DCE /* Build configuration list for PBXNativeTarget "apfm" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B63EFCD011A36C7300C90DCE /* Debug */, + B656AD7C11A84B5D00AB578A /* Debug fuse */, + B63EFCD111A36C7300C90DCE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B63EFEB311A488C200C90DCE /* Build configuration list for PBXNativeTarget "newfs_pascal" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B63EFE8311A4886C00C90DCE /* Debug */, + B656AD7D11A84B5D00AB578A /* Debug fuse */, + B63EFE8411A4886C00C90DCE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B656AE3411A84FA400AB578A /* Build configuration list for PBXNativeTarget "fuse_pascal" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B656AE0511A84F5900AB578A /* Debug */, + B656AE0611A84F5900AB578A /* Debug fuse */, + B656AE0711A84F5900AB578A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B656AF2111AA10A100AB578A /* Build configuration list for PBXNativeTarget "NibbleTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B656AF0511AA105600AB578A /* Debug */, + B656AF0611AA105600AB578A /* Debug fuse */, + B656AF0711AA105600AB578A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B6F3648911AB36590045E114 /* Build configuration list for PBXNativeTarget "xattr" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B6F3648211AB36260045E114 /* Debug */, + B6F3648311AB36260045E114 /* Debug fuse */, + B6F3648411AB36260045E114 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} From 4de285c9e13292b7900520e98b7b88f46087920a Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 26 May 2010 02:03:29 +0000 Subject: [PATCH 152/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@279 aa027e90-d47c-11dd-86d7-074df07e0730 --- File/File.cpp | 16 + File/File.h | 2 + PROFuseX.xcodeproj/kelvin.pbxuser | 383 +++++++++++++++++++++--- PROFuseX.xcodeproj/kelvin.perspectivev3 | 50 ++-- PROFuseX.xcodeproj/project.pbxproj | 2 +- Pascal/File.h | 25 +- Pascal/FileEntry.cpp | 169 +++++++++++ Pascal/VolumeEntry.cpp | 21 +- apfm.cpp | 153 +++++++++- 9 files changed, 757 insertions(+), 64 deletions(-) diff --git a/File/File.cpp b/File/File.cpp index 11e8604..ee9b81d 100644 --- a/File/File.cpp +++ b/File/File.cpp @@ -31,6 +31,12 @@ File::File(const char *name, int flags, const std::nothrow_t&) _fd = ::open(name, flags); } + +File::File(const char *name, int flags, mode_t mode, const std::nothrow_t&) +{ + _fd = ::open(name, flags, mode); +} + File::File(const char *name, bool readOnly, const std::nothrow_t&) { _fd = ::open(name, readOnly ? O_RDONLY : O_RDWR); @@ -46,6 +52,16 @@ File::File(const char *name, int flags) throw POSIXException( __METHOD__ ": open", errno); } +File::File(const char *name, int flags, mode_t mode) +{ +#undef __METHOD__ +#define __METHOD__ "File::File" + + _fd = ::open(name, flags, mode); + if (_fd < 0) + throw POSIXException( __METHOD__ ": open", errno); +} + File::File(const char *name, bool readOnly) { diff --git a/File/File.h b/File/File.h index 2d83591..1bc5e5d 100644 --- a/File/File.h +++ b/File/File.h @@ -16,9 +16,11 @@ class File { File(int fd); File(const char *name, int flags); + File(const char *name, int flags, mode_t mode); File(const char *name, bool readOnly); File(const char *name, int flags, const std::nothrow_t &); + File(const char *name, int flags, mode_t mode, const std::nothrow_t &); File(const char *name, bool readOnly, const std::nothrow_t &); ~File(); diff --git a/PROFuseX.xcodeproj/kelvin.pbxuser b/PROFuseX.xcodeproj/kelvin.pbxuser index 7038c28..81ced93 100644 --- a/PROFuseX.xcodeproj/kelvin.pbxuser +++ b/PROFuseX.xcodeproj/kelvin.pbxuser @@ -2,14 +2,14 @@ { 08FB7793FE84155DC02AAC07 /* Project object */ = { activeBuildConfigurationName = Debug; - activeExecutable = B656AF0411AA105500AB578A /* NibbleTest */; - activeTarget = B656AF0211AA105500AB578A /* NibbleTest */; + activeExecutable = B63EFCCF11A36C7300C90DCE /* apfm */; + activeTarget = B63EFCCD11A36C7300C90DCE /* apfm */; addToTargets = ( ); breakpoints = ( - B63EFD8911A4455A00C90DCE /* apfm.cpp:346 */, + B63EFD8911A4455A00C90DCE /* apfm.cpp:487 */, B63EFE0E11A451C600C90DCE /* VolumeEntry.cpp:105 */, - B63EFE3B11A4799800C90DCE /* apfm.cpp:184 */, + B63EFE3B11A4799800C90DCE /* apfm.cpp:183 */, B6F3642F11AA1E150045E114 /* NibbleTest.cpp:74 */, ); codeSenseManager = B63EFA6811A093C200C90DCE /* Code sense */; @@ -144,6 +144,34 @@ B6F3647011AB35F00045E114 /* PBXTextBookmark */ = B6F3647011AB35F00045E114 /* PBXTextBookmark */; B6F3647111AB35FE0045E114 /* PBXTextBookmark */ = B6F3647111AB35FE0045E114 /* PBXTextBookmark */; B6F3647211AB35FE0045E114 /* PBXTextBookmark */ = B6F3647211AB35FE0045E114 /* PBXTextBookmark */; + B6F3649411AB58E80045E114 /* PBXTextBookmark */ = B6F3649411AB58E80045E114 /* PBXTextBookmark */; + B6F3649511AB58E80045E114 /* PBXTextBookmark */ = B6F3649511AB58E80045E114 /* PBXTextBookmark */; + B6F3649611AB58E80045E114 /* PBXTextBookmark */ = B6F3649611AB58E80045E114 /* PBXTextBookmark */; + B6F3649711AB58E80045E114 /* XCBuildMessageTextBookmark */ = B6F3649711AB58E80045E114 /* XCBuildMessageTextBookmark */; + B6F3649811AB58E80045E114 /* PBXTextBookmark */ = B6F3649811AB58E80045E114 /* PBXTextBookmark */; + B6F3649E11AB59190045E114 /* PBXTextBookmark */ = B6F3649E11AB59190045E114 /* PBXTextBookmark */; + B6F3649F11AB59190045E114 /* XCBuildMessageTextBookmark */ = B6F3649F11AB59190045E114 /* XCBuildMessageTextBookmark */; + B6F364A011AB59190045E114 /* PBXTextBookmark */ = B6F364A011AB59190045E114 /* PBXTextBookmark */; + B6F364A511AB593E0045E114 /* PBXTextBookmark */ = B6F364A511AB593E0045E114 /* PBXTextBookmark */; + B6F364A911AB5EBD0045E114 /* PBXTextBookmark */ = B6F364A911AB5EBD0045E114 /* PBXTextBookmark */; + B6F364B111AB74F40045E114 /* XCBuildMessageTextBookmark */ = B6F364B111AB74F40045E114 /* XCBuildMessageTextBookmark */; + B6F364B211AB74F40045E114 /* PBXTextBookmark */ = B6F364B211AB74F40045E114 /* PBXTextBookmark */; + B6F364B611AB84840045E114 /* PBXTextBookmark */ = B6F364B611AB84840045E114 /* PBXTextBookmark */; + B6F364B711AB84840045E114 /* PBXTextBookmark */ = B6F364B711AB84840045E114 /* PBXTextBookmark */; + B6F364B811AB84840045E114 /* PBXTextBookmark */ = B6F364B811AB84840045E114 /* PBXTextBookmark */; + B6F364B911AB84840045E114 /* PBXTextBookmark */ = B6F364B911AB84840045E114 /* PBXTextBookmark */; + B6F364BE11AC92730045E114 /* PBXTextBookmark */ = B6F364BE11AC92730045E114 /* PBXTextBookmark */; + B6F364BF11AC92730045E114 /* XCBuildMessageTextBookmark */ = B6F364BF11AC92730045E114 /* XCBuildMessageTextBookmark */; + B6F364C011AC92730045E114 /* PBXTextBookmark */ = B6F364C011AC92730045E114 /* PBXTextBookmark */; + B6F364C811ACAB370045E114 /* PBXTextBookmark */ = B6F364C811ACAB370045E114 /* PBXTextBookmark */; + B6F364C911ACAB370045E114 /* PBXTextBookmark */ = B6F364C911ACAB370045E114 /* PBXTextBookmark */; + B6F364CA11ACAB370045E114 /* PBXTextBookmark */ = B6F364CA11ACAB370045E114 /* PBXTextBookmark */; + B6F364E811ACB5790045E114 /* PBXTextBookmark */ = B6F364E811ACB5790045E114 /* PBXTextBookmark */; + B6F364E911ACB5790045E114 /* XCBuildMessageTextBookmark */ = B6F364E911ACB5790045E114 /* XCBuildMessageTextBookmark */; + B6F364EB11ACB5790045E114 /* PBXTextBookmark */ = B6F364EB11ACB5790045E114 /* PBXTextBookmark */; + B6F364EC11ACB5790045E114 /* XCBuildMessageTextBookmark */ = B6F364EC11ACB5790045E114 /* XCBuildMessageTextBookmark */; + B6F364ED11ACB5790045E114 /* PBXTextBookmark */ = B6F364ED11ACB5790045E114 /* PBXTextBookmark */; + B6F364F511ACB5B60045E114 /* PBXTextBookmark */ = B6F364F511ACB5B60045E114 /* PBXTextBookmark */; }; sourceControlManager = B63EFA6711A093C200C90DCE /* Source Control */; userBuildSettings = { @@ -319,16 +347,16 @@ }; B63EFAC911A09DAA00C90DCE /* File.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1264, 1209}}"; - sepNavSelRange = "{1210, 0}"; - sepNavVisRange = "{0, 1046}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 1534}}"; + sepNavSelRange = "{384, 0}"; + sepNavVisRange = "{0, 571}"; }; }; B63EFACA11A09DAA00C90DCE /* File.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1264, 932}}"; - sepNavSelRange = "{457, 0}"; - sepNavVisRange = "{0, 611}"; + sepNavIntBoundsRect = "{{0, 0}, {701, 948}}"; + sepNavSelRange = "{423, 0}"; + sepNavVisRange = "{0, 888}"; }; }; B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */ = { @@ -361,9 +389,9 @@ }; B63EFAD211A09DB500C90DCE /* Exception.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 1898}}"; - sepNavSelRange = "{734, 12}"; - sepNavVisRange = "{434, 1049}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 1885}}"; + sepNavSelRange = "{783, 10}"; + sepNavVisRange = "{434, 1003}"; }; }; B63EFAD311A09DB500C90DCE /* Lock.cpp */ = { @@ -417,16 +445,16 @@ }; B63EFBEB11A244EE00C90DCE /* File.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1264, 2964}}"; - sepNavSelRange = "{2767, 0}"; - sepNavVisRange = "{1820, 1622}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 3029}}"; + sepNavSelRange = "{2795, 35}"; + sepNavVisRange = "{2292, 855}"; }; }; B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 5330}}"; - sepNavSelRange = "{7404, 0}"; - sepNavVisRange = "{6413, 938}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 7683}}"; + sepNavSelRange = "{1582, 0}"; + sepNavVisRange = "{1039, 851}"; }; }; B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */ = { @@ -475,9 +503,9 @@ }; B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 4004}}"; - sepNavSelRange = "{7036, 0}"; - sepNavVisRange = "{5446, 1697}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 4121}}"; + sepNavSelRange = "{4176, 0}"; + sepNavVisRange = "{3759, 970}"; }; }; B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */ = { @@ -496,9 +524,9 @@ }; B63EFC9F11A35F8F00C90DCE /* apfm.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 5187}}"; - sepNavSelRange = "{1814, 0}"; - sepNavVisRange = "{2880, 875}"; + sepNavIntBoundsRect = "{{0, 0}, {701, 7228}}"; + sepNavSelRange = "{916, 0}"; + sepNavVisRange = "{800, 1552}"; }; }; B63EFCB211A3639400C90DCE /* PBXTextBookmark */ = { @@ -573,12 +601,12 @@ fRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; name = "File.cpp: 34"; rLen = 0; - rLoc = 385; + rLoc = 504; rType = 0; vrLen = 225; vrLoc = 284; }; - B63EFD8911A4455A00C90DCE /* apfm.cpp:346 */ = { + B63EFD8911A4455A00C90DCE /* apfm.cpp:487 */ = { isa = PBXFileBreakpoint; actions = ( ); @@ -590,7 +618,7 @@ functionName = "main(/* int argc, char **argv */)"; hitCount = 0; ignoreCount = 0; - lineNumber = 346; + lineNumber = 487; modificationTime = 296363159.802434; originalNumberOfMultipleMatches = 1; state = 0; @@ -806,7 +834,7 @@ originalNumberOfMultipleMatches = 1; state = 1; }; - B63EFE3B11A4799800C90DCE /* apfm.cpp:184 */ = { + B63EFE3B11A4799800C90DCE /* apfm.cpp:183 */ = { isa = PBXFileBreakpoint; actions = ( ); @@ -818,7 +846,7 @@ functionName = "action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume)"; hitCount = 0; ignoreCount = 0; - lineNumber = 184; + lineNumber = 183; modificationTime = 296363159.805745; originalNumberOfMultipleMatches = 1; state = 0; @@ -902,6 +930,11 @@ name = VolumeEntry.cpp; path = ./Pascal/VolumeEntry.cpp; sourceTree = ""; + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 7085}}"; + sepNavSelRange = "{3256, 0}"; + sepNavVisRange = "{2568, 1113}"; + }; }; B63EFEA711A488C200C90DCE /* PBXTextBookmark */ = { isa = PBXTextBookmark; @@ -1048,9 +1081,9 @@ }; B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 1079}}"; + sepNavIntBoundsRect = "{{0, 0}, {701, 1079}}"; sepNavSelRange = "{1570, 0}"; - sepNavVisRange = "{917, 940}"; + sepNavVisRange = "{173, 1684}"; }; }; B656AF0211AA105500AB578A /* NibbleTest */ = { @@ -1102,7 +1135,7 @@ fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; name = "FileEntry.cpp: 372"; rLen = 0; - rLoc = 7404; + rLoc = 11357; rType = 0; vrLen = 938; vrLoc = 6413; @@ -1112,7 +1145,7 @@ fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; name = "apfm.cpp: 107"; rLen = 0; - rLoc = 1814; + rLoc = 1824; rType = 0; vrLen = 875; vrLoc = 2880; @@ -1172,7 +1205,7 @@ fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; name = "VolumeEntry.cpp: 460"; rLen = 0; - rLoc = 9665; + rLoc = 10173; rType = 0; vrLen = 797; vrLoc = 8547; @@ -1319,4 +1352,284 @@ sourceDirectories = ( ); }; + B6F3649411AB58E80045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + name = "NibbleTest.cpp: 70"; + rLen = 0; + rLoc = 1570; + rType = 0; + vrLen = 940; + vrLoc = 917; + }; + B6F3649511AB58E80045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F3647B11AB361D0045E114 /* xattr.cpp */; + name = "xattr.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 985; + vrLoc = 0; + }; + B6F3649611AB58E80045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */; + name = "fuse_pascal.cpp: 187"; + rLen = 0; + rLoc = 4176; + rType = 0; + vrLen = 970; + vrLoc = 3759; + }; + B6F3649711AB58E80045E114 /* XCBuildMessageTextBookmark */ = { + isa = PBXTextBookmark; + comments = "Prototype for 'File::File(const char*, int, mode_t, const std::nothrow_t&)' does not match any in class 'File'"; + fRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; + fallbackIsa = XCBuildMessageTextBookmark; + rLen = 1; + rLoc = 34; + rType = 1; + }; + B6F3649811AB58E80045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; + name = "File.cpp: 35"; + rLen = 0; + rLoc = 384; + rType = 0; + vrLen = 571; + vrLoc = 0; + }; + B6F3649E11AB59190045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; + name = "File.cpp: 35"; + rLen = 0; + rLoc = 384; + rType = 0; + vrLen = 571; + vrLoc = 0; + }; + B6F3649F11AB59190045E114 /* XCBuildMessageTextBookmark */ = { + isa = PBXTextBookmark; + comments = "'File' has not been declared"; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + fallbackIsa = XCBuildMessageTextBookmark; + rLen = 1; + rLoc = 279; + rType = 1; + }; + B6F364A011AB59190045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 281"; + rLen = 66; + rLoc = 5764; + rType = 0; + vrLen = 849; + vrLoc = 5157; + }; + B6F364A511AB593E0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 281"; + rLen = 66; + rLoc = 5764; + rType = 0; + vrLen = 855; + vrLoc = 5157; + }; + B6F364A911AB5EBD0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 281"; + rLen = 66; + rLoc = 5764; + rType = 0; + vrLen = 855; + vrLoc = 5157; + }; + B6F364B111AB74F40045E114 /* XCBuildMessageTextBookmark */ = { + isa = PBXTextBookmark; + comments = "'kTextFile' was not declared in this scope"; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + fallbackIsa = XCBuildMessageTextBookmark; + rLen = 1; + rLoc = 382; + rType = 1; + }; + B6F364B211AB74F40045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 385"; + rLen = 0; + rLoc = 8425; + rType = 0; + vrLen = 715; + vrLoc = 8003; + }; + B6F364B611AB84840045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 385"; + rLen = 0; + rLoc = 8425; + rType = 0; + vrLen = 715; + vrLoc = 8003; + }; + B6F364B711AB84840045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAD211A09DB500C90DCE /* Exception.h */; + name = "Exception.h: 39"; + rLen = 10; + rLoc = 783; + rType = 0; + vrLen = 1003; + vrLoc = 434; + }; + B6F364B811AB84840045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 464"; + rLen = 0; + rLoc = 10173; + rType = 0; + vrLen = 563; + vrLoc = 8511; + }; + B6F364B911AB84840045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 473"; + rLen = 0; + rLoc = 10173; + rType = 0; + vrLen = 546; + vrLoc = 8717; + }; + B6F364BE11AC92730045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 473"; + rLen = 0; + rLoc = 10173; + rType = 0; + vrLen = 546; + vrLoc = 8717; + }; + B6F364BF11AC92730045E114 /* XCBuildMessageTextBookmark */ = { + isa = PBXTextBookmark; + comments = "'volume' is not a class or namespace"; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + fallbackIsa = XCBuildMessageTextBookmark; + rLen = 1; + rLoc = 378; + rType = 1; + }; + B6F364C011AC92730045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 381"; + rLen = 0; + rLoc = 8337; + rType = 0; + vrLen = 667; + vrLoc = 7907; + }; + B6F364C811ACAB370045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 381"; + rLen = 0; + rLoc = 8337; + rType = 0; + vrLen = 667; + vrLoc = 7907; + }; + B6F364C911ACAB370045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 473"; + rLen = 0; + rLoc = 10173; + rType = 0; + vrLen = 546; + vrLoc = 8717; + }; + B6F364CA11ACAB370045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 475"; + rLen = 0; + rLoc = 10173; + rType = 0; + vrLen = 490; + vrLoc = 8968; + }; + B6F364E811ACB5790045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; + name = "FileEntry.cpp: 86"; + rLen = 0; + rLoc = 1582; + rType = 0; + vrLen = 851; + vrLoc = 1039; + }; + B6F364E911ACB5790045E114 /* XCBuildMessageTextBookmark */ = { + isa = PBXTextBookmark; + comments = "'void Pascal::VolumeEntry::writeEntry(Pascal::FileEntry*)' is private"; + fRef = B6F364EA11ACB5790045E114 /* File.h */; + fallbackIsa = XCBuildMessageTextBookmark; + rLen = 1; + rLoc = 137; + rType = 1; + }; + B6F364EA11ACB5790045E114 /* File.h */ = { + isa = PBXFileReference; + name = File.h; + path = ./Pascal/File.h; + sourceTree = ""; + }; + B6F364EB11ACB5790045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBEB11A244EE00C90DCE /* File.h */; + name = "File.h: 141"; + rLen = 35; + rLoc = 2795; + rType = 0; + vrLen = 855; + vrLoc = 2292; + }; + B6F364EC11ACB5790045E114 /* XCBuildMessageTextBookmark */ = { + isa = PBXTextBookmark; + comments = "'_file' was not declared in this scope"; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + fallbackIsa = XCBuildMessageTextBookmark; + rLen = 1; + rLoc = 154; + rType = 1; + }; + B6F364ED11ACB5790045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 154"; + rLen = 0; + rLoc = 3256; + rType = 0; + vrLen = 1019; + vrLoc = 2603; + }; + B6F364F511ACB5B60045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 155"; + rLen = 0; + rLoc = 3256; + rType = 0; + vrLen = 1113; + vrLoc = 2568; + }; } diff --git a/PROFuseX.xcodeproj/kelvin.perspectivev3 b/PROFuseX.xcodeproj/kelvin.perspectivev3 index 7a90b8e..35372d2 100644 --- a/PROFuseX.xcodeproj/kelvin.perspectivev3 +++ b/PROFuseX.xcodeproj/kelvin.perspectivev3 @@ -231,8 +231,6 @@ Layout - BecomeActive - ContentConfiguration PBXBottomSmartGroupGIDs @@ -269,13 +267,17 @@ PBXSmartGroupTreeModuleOutlineStateExpansionKey 08FB7794FE84155DC02AAC07 + B63EFBE711A244EE00C90DCE + B63EFACF11A09DB500C90DCE + B63EFAC811A09DAA00C90DCE B656ADED11A84D3200AB578A 1C37FBAC04509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey - 2 + 10 + 7 0 @@ -297,7 +299,7 @@ 318 RubberWindowFrame - 394 69 1239 1000 0 0 1920 1178 + 489 -24 1239 1000 0 0 1920 1178 Module PBXSmartGroupTreeModule @@ -308,12 +310,14 @@ Dock + BecomeActive + ContentConfiguration PBXProjectModuleGUID B63EFA6111A093C200C90DCE PBXProjectModuleLabel - NibbleTest.cpp + VolumeEntry.cpp PBXSplitModuleInNavigatorKey Split0 @@ -321,11 +325,11 @@ PBXProjectModuleGUID B63EFA6211A093C200C90DCE PBXProjectModuleLabel - NibbleTest.cpp + VolumeEntry.cpp _historyCapacity 0 bookmark - B6F3647211AB35FE0045E114 + B6F364F511ACB5B60045E114 history B63EFC2611A2D5A400C90DCE @@ -333,7 +337,6 @@ B63EFC3211A2D5A400C90DCE B63EFCB211A3639400C90DCE B63EFCB611A3639400C90DCE - B63EFD7F11A4436B00C90DCE B63EFDA011A4488200C90DCE B63EFDA511A4488200C90DCE B63EFDA711A4488200C90DCE @@ -351,7 +354,6 @@ B63EFEA111A488C200C90DCE B63EFEA211A488C200C90DCE B63EFEA311A488C200C90DCE - B63EFEA711A488C200C90DCE B63EFEA811A488C200C90DCE B63EFEA911A488C200C90DCE B63EFEEC11A4A70400C90DCE @@ -359,21 +361,25 @@ B6E5F0F211A73144000AD141 B6E5F11211A73340000AD141 B6E5F13A11A74F2B000AD141 - B6E5F18111A76B74000AD141 B6E5F18211A76B74000AD141 - B656AE2311A84FA400AB578A B656AE2411A84FA400AB578A B656AE2611A84FA400AB578A B656AE2711A84FA400AB578A - B656AE6511A8591F00AB578A B656AEA711A9C91600AB578A B656AEA811A9C91600AB578A - B656AF2711AA10C900AB578A - B656AF2811AA10C900AB578A B656AF2A11AA10C900AB578A B6F3642D11AA1E070045E114 B6F3647111AB35FE0045E114 - B6F3647011AB35F00045E114 + B6F3649411AB58E80045E114 + B6F3649511AB58E80045E114 + B6F3649611AB58E80045E114 + B6F3649E11AB59190045E114 + B6F364B711AB84840045E114 + B6F364C811ACAB370045E114 + B6F364E811ACB5790045E114 + B6F364E911ACB5790045E114 + B6F364EB11ACB5790045E114 + B6F364EC11ACB5790045E114 SplitCount @@ -389,7 +395,7 @@ Frame {{0, 0}, {899, 562}} RubberWindowFrame - 394 69 1239 1000 0 0 1920 1178 + 489 -24 1239 1000 0 0 1920 1178 Module PBXNavigatorGroup @@ -413,8 +419,6 @@ Frame {{10, 27}, {899, 365}} - RubberWindowFrame - 394 69 1239 1000 0 0 1920 1178 Module XCDetailModule @@ -468,7 +472,9 @@ GeometryConfiguration Frame - {{10, 27}, {899, 349}} + {{10, 27}, {899, 365}} + RubberWindowFrame + 489 -24 1239 1000 0 0 1920 1178 Module PBXBuildResultsModule @@ -690,10 +696,14 @@ 5 WindowOrderList + B6F364EE11ACB5790045E114 + B6F364C211AC92730045E114 + B6F364C111AC92730045E114 /Users/kelvin/Projects/PROFuseX/PROFuseX.xcodeproj + B6F364CC11ACAB370045E114 WindowString - 394 69 1239 1000 0 0 1920 1178 + 489 -24 1239 1000 0 0 1920 1178 WindowToolsV3 diff --git a/PROFuseX.xcodeproj/project.pbxproj b/PROFuseX.xcodeproj/project.pbxproj index f1fbefc..d87bd80 100644 --- a/PROFuseX.xcodeproj/project.pbxproj +++ b/PROFuseX.xcodeproj/project.pbxproj @@ -144,7 +144,7 @@ B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NibbleTest.cpp; sourceTree = ""; }; B656AF0311AA105500AB578A /* NibbleTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NibbleTest; sourceTree = BUILT_PRODUCTS_DIR; }; B6F3647B11AB361D0045E114 /* xattr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xattr.cpp; sourceTree = ""; }; - B6F3648011AB36260045E114 /* xattr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = xattr; path = build/Debug/xattr; sourceTree = ""; }; + B6F3648011AB36260045E114 /* xattr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xattr; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ diff --git a/Pascal/File.h b/Pascal/File.h index 0e0b709..70a2476 100644 --- a/Pascal/File.h +++ b/Pascal/File.h @@ -45,7 +45,7 @@ public: unsigned lastBlock() const { return _lastBlock; } unsigned fileKind() const { return _fileKind; } - + unsigned inode() const { return _inode; } void setInode(unsigned inode) { _inode = inode; } @@ -124,6 +124,9 @@ protected: virtual void writeDirectoryEntry(LittleEndian::IOBuffer *); private: + + friend class FileEntry; + VolumeEntry(); void init(void *); @@ -174,19 +177,31 @@ class FileEntry : public Entry { int read(uint8_t *buffer, unsigned size, unsigned offset); int write(uint8_t *buffer, unsigned size, unsigned offset); + int truncate(unsigned newSize); + + const char *name() const { return _fileName; } Date modification() const { return _modification; } + void setFileKind(unsigned kind); + + + protected: virtual void writeDirectoryEntry(LittleEndian::IOBuffer *); - private: + private: + + friend class VolumeEntry; void setName(const char *name); + void extend(unsigned newSize); + + unsigned _status; @@ -196,6 +211,12 @@ class FileEntry : public Entry { unsigned _lastByte; Date _modification; + + unsigned _maxFileSize; // maximum file size. + + + + // non-text files unsigned dataFileSize(); int dataRead(uint8_t *buffer, unsigned size, unsigned offset); diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index 6e6f773..7b2f7ae 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -44,6 +45,7 @@ FileEntry::FileEntry(void *vp) : _fileSize = 0; _pageSize = NULL; + _maxFileSize = 0; } FileEntry::FileEntry(const char *name, unsigned fileKind) @@ -69,6 +71,7 @@ FileEntry::FileEntry(const char *name, unsigned fileKind) _fileSize = 0; _pageSize = NULL; + _maxFileSize = 0; } FileEntry::~FileEntry() @@ -77,6 +80,13 @@ FileEntry::~FileEntry() } +void FileEntry::setFileKind(unsigned kind) +{ + _fileKind = kind; + parent()->writeEntry(this); +} + + void FileEntry::setName(const char *name) { #undef __METHOD__ @@ -93,6 +103,8 @@ void FileEntry::setName(const char *name) // not sure if this is a good idea or not. //_modification = Date::Today(); + + parent()->writeEntry(this); } unsigned FileEntry::fileSize() @@ -138,6 +150,163 @@ int FileEntry::read(uint8_t *buffer, unsigned size, unsigned offset) } +int FileEntry::truncate(unsigned newSize) +{ +#undef __METHOD__ +#define __METHOD__ "FileEntry::truncate" + + unsigned currentSize = fileSize(); + + if (currentSize == newSize) return 0; + + if (fileKind() == kTextFile) + { + if (newSize) + throw ProFUSE::Exception(__METHOD__ ": unable to truncate text file."); + + if (_pageSize) _pageSize->clear(); + } + + extend(newSize); + + _modification = Date::Today(); + parent()->writeEntry(this); + + return 0; +} + +/* + * extend -- common truncation code. + * updates _lastByte and _lastBlock but does + * not update _modification or commit to disk. + */ +void FileEntry::extend(unsigned newSize) +{ +#undef __METHOD__ +#define __METHOD__ "FileEntry::extend" + + unsigned currentSize = fileSize(); + + if (newSize == currentSize) return; + if (newSize > currentSize) + { + + if (newSize > _maxFileSize) + throw ProFUSE::POSIXException(__METHOD__ ": Unable to extend file.", ENOSPC); + + unsigned remainder = newSize - currentSize; + unsigned block = _lastBlock; + + if (_lastByte != 512) + { + // last page not full + unsigned count = std::min(512 - _lastByte, remainder); + uint8_t *address = (uint8_t *)parent()->loadBlock(block); + + std::memset(address + _lastByte, 0, count); + + parent()->unloadBlock(block, true); + + remainder -= count; + } + block++; + + while (remainder) + { + unsigned count = std::min(512u, remainder); + uint8_t *address = (uint8_t *)parent()->loadBlock(block); + + std::memset(address, 0, count); + + parent()->unloadBlock(block, true); + + remainder -= count; + block++; + } + + + } + + _lastBlock = _firstBlock + newSize / 512; + _lastByte = newSize % 512; + if (_lastByte = 0) _lastByte = 512; + +} + + +int FileEntry::write(uint8_t *buffer, unsigned size, unsigned offset) +{ +#undef __METHOD__ +#define __METHOD__ "FileEntry::write" + + if (fileKind() == kTextFile) + { + throw ProFUSE::Exception(__METHOD__ ": Text Files are too weird."); + } + + unsigned currentSize = fileSize(); + + unsigned newSize = std::max(offset + size, currentSize); + + + if (newSize > _maxFileSize) + { + throw ProFUSE::POSIXException(__METHOD__ ": Unable to extend file.", ENOSPC); + } + + if (offset > currentSize) + { + extend(offset); + } + + // 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 *)parent()->loadBlock(block); + + std::memcpy(address + start, buffer, count); + parent()->unloadBlock(block, true); + + remainder -= count; + buffer += count; + block++; + } + + while (remainder) + { + uint8_t *address = (uint8_t *)parent()->loadBlock(block); + + unsigned count = std::min(512u, size); + + std::memcpy(address, buffer, count); + parent()->unloadBlock(block, true); + + remainder -= count; + buffer += count; + block++; + } + + if (newSize > currentSize) + { + _lastBlock = _firstBlock + currentSize / 512; + _lastByte = currentSize % 512; + if (_lastByte == 0) _lastByte = 512; + + } + + _modification = Date::Today(); + parent()->writeEntry(this); + + return size; +} + + unsigned FileEntry::dataFileSize() { return blocks() * 512 - 512 + _lastByte; diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index f8c27b2..d6f12be 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -132,6 +132,8 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device) try { + std::vector::reverse_iterator iter; + for (unsigned i = 1; i <= _fileCount; ++i) { std::auto_ptr child; @@ -142,12 +144,26 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device) child->setInode(++_inodeGenerator); child->_parent = this; child->_address = 512 * 2 + i * 0x1a; + _files.push_back(child.release()); - } + } + + // sanity check _firstBlock, _lastBlock? + + // set up _maxBlocks; + unsigned lastBlock = _lastVolumeBlock; + for (iter = _files.rbegin(); iter != _files.rend(); ++iter) + { + FileEntry *e = *iter; + e->_maxFileSize = (lastBlock - e->_firstBlock) * 512; + lastBlock = e->_firstBlock - 1; + } + } catch (...) { std::vector::iterator iter; + for(iter = _files.begin(); iter != _files.end(); ++iter) { if (*iter) delete *iter; @@ -155,7 +171,7 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device) throw; } - + } @@ -224,6 +240,7 @@ unsigned VolumeEntry::unlink(const char *name) { unsigned index; + // TODO -- update _maxFileSize. if (_device->readOnly()) return ProFUSE::drvrWrtProt; // WRITE-PROTECTED DISK diff --git a/apfm.cpp b/apfm.cpp index 87adbd2..2d316c2 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -15,12 +15,13 @@ #include #include +#include #include #include #include - +#include const char *MonthName(unsigned m) { @@ -101,9 +102,7 @@ void printFileEntry(Pascal::FileEntry *e, bool extended) } int action_ls(int argc, char **argv, Pascal::VolumeEntry *volume) -{ - //TODO -- check for -l flag. - +{ bool extended = false; unsigned fileCount = volume->fileCount(); unsigned used = volume->blocks(); @@ -253,6 +252,148 @@ int action_krunch(int argc, char **argv, Pascal::VolumeEntry *volume) +int action_get(int argc, char **argv, Pascal::VolumeEntry *volume) +{ + // get pascal_file [native file]; + + char *infile; + char *outfile; + + Pascal::FileEntry *entry; + + switch(argc) + { + case 1: + infile = outfile = argv[0]; + break; + case 2: + infile = argv[0]; + outfile = argv[1]; + break; + default: + std::fprintf(stderr, "apfm cat: Please specify an infile (and an optional outfile)\n"); + } + + entry = volume->fileByName(infile); + + + File::File file(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); + + if (!entry) + { + std::fprintf(stderr, "apfm get: %s: no such file.\n", infile); + return 1; + } + + unsigned fileSize = entry->fileSize(); + unsigned offset = 0; + + while (offset < fileSize) + { + uint8_t buffer[512]; + + unsigned count = std::min(512u, fileSize - offset); + entry->read(buffer, count, offset); + + ::write(file.fd(), buffer, count); + offset += count; + } + + return 0; +} + +#if 0 +int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) +{ + // put [-t type] native_file [pascal_file] + + unsigned type = Pascal::kUntypedFile; + + struct stat st; + int c; + + char *infile; + char *outfile; + char *tmp; + + while ((c = getopt(argc, argv, "t:")) != -1) + { + switch (c) + { + case 't': + if (!::strcasecmp("text", optarg)) + type = Pascal::kTextFile; + else if (!::strcasecmp("txt", optarg)) + type = Pascal::kTextFile; + else if (!::strcasecmp("code", optarg)) + type = Pascal::kCodeFile; + else if (!::strcasecmp("info", optarg)) + type = Pascal::kInfoFile; + else if (!::strcasecmp("data", optarg)) + type = Pascal::kDataFile; + else if (!::strcasecmp("graf", optarg)) + type = Pascal::kGrafFile; + else if (!::strcasecmp("foto", optarg)) + type = Pascal::kFotoFile; + else type = Pascal::kUntypedFile; + + break; + } + + } + + // TODO -- if file is named .txt or .text, default to kTextFile. + + argc -= optind; + argv += optind; + + switch (argc) + { + case 1: + infile = outfile = argv[0]; + + // need to run basename on outfile. + tmp = strrchr(outfile, '/'); + if (tmp) outfile = tmp + 1; + break; + case 2: + infile = argv[0]; + outfile = argv[1]; + break; + } + + if (!Pascal::FileEntry::ValidName(outfile)) + { + std::fprintf(stderr, "apfm put: `%s' is not a valid pascal name.\n", outfile); + } + + ::stat(infile, &st); + + File::File file(infile, O_RDONLY); + + + unsigned blocks = (st.st_size + 511) / 511; + + // TODO -- if text file, .. + + Pascal::FileEntry *entry = volume.createFile(infile, blocks); + + entry->setType(type); + + if (type == Pascal::kTextFile) + { + //... + } + else + { + // ... + + } + + return 0; + +} +#endif void usage() { @@ -370,6 +511,10 @@ int main(int argc, char **argv) if (!::strcasecmp("mv", action)) return action_mv(argc - 1, argv + 1, volume.get()); if (!::strcasecmp("rm", action)) return action_rm(argc - 1, argv + 1, volume.get()); + if (!::strcasecmp("get", action)) return action_get(argc -1, argv + 1, volume.get()); + //if (!::strcasecmp("put", action)) return action_put(argc -1, argv + 1, volume.get()); + + usage(); return 3; } From c4849f78e5cfd2672964d6815336669a75c572d7 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 26 May 2010 13:22:46 +0000 Subject: [PATCH 153/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@280 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/File.h | 2 +- Pascal/FileEntry.cpp | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Pascal/File.h b/Pascal/File.h index 70a2476..6e51c4f 100644 --- a/Pascal/File.h +++ b/Pascal/File.h @@ -199,7 +199,7 @@ class FileEntry : public Entry { void setName(const char *name); - void extend(unsigned newSize); + void truncateCommon(unsigned newSize); diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index 7b2f7ae..58aefc9 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -167,7 +167,7 @@ int FileEntry::truncate(unsigned newSize) if (_pageSize) _pageSize->clear(); } - extend(newSize); + truncateCommon(newSize); _modification = Date::Today(); parent()->writeEntry(this); @@ -176,14 +176,14 @@ int FileEntry::truncate(unsigned newSize) } /* - * extend -- common truncation code. + * truncateCommon -- common truncation code. * updates _lastByte and _lastBlock but does * not update _modification or commit to disk. */ -void FileEntry::extend(unsigned newSize) +void FileEntry::truncateCommon(unsigned newSize) { #undef __METHOD__ -#define __METHOD__ "FileEntry::extend" +#define __METHOD__ "FileEntry::truncateCommon" unsigned currentSize = fileSize(); @@ -192,7 +192,7 @@ void FileEntry::extend(unsigned newSize) { if (newSize > _maxFileSize) - throw ProFUSE::POSIXException(__METHOD__ ": Unable to extend file.", ENOSPC); + throw ProFUSE::POSIXException(__METHOD__ ": Unable to expand file.", ENOSPC); unsigned remainder = newSize - currentSize; unsigned block = _lastBlock; @@ -251,12 +251,12 @@ int FileEntry::write(uint8_t *buffer, unsigned size, unsigned offset) if (newSize > _maxFileSize) { - throw ProFUSE::POSIXException(__METHOD__ ": Unable to extend file.", ENOSPC); + throw ProFUSE::POSIXException(__METHOD__ ": Unable to expand file.", ENOSPC); } if (offset > currentSize) { - extend(offset); + truncateCommon(offset); } // now write the data... From 42c6839fcb0d6c440ccb260680f056a6e5aee613 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 26 May 2010 22:15:44 +0000 Subject: [PATCH 154/236] split out pascal header files. git-svn-id: https://profuse.googlecode.com/svn/branches/v2@281 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/Entry.cpp | 2 +- Pascal/Entry.h | 81 +++++++++++++++ Pascal/File.h | 242 ------------------------------------------- Pascal/FileEntry.h | 94 +++++++++++++++++ Pascal/Pascal.h | 9 ++ Pascal/VolumeEntry.h | 96 +++++++++++++++++ 6 files changed, 281 insertions(+), 243 deletions(-) create mode 100644 Pascal/Entry.h delete mode 100644 Pascal/File.h create mode 100644 Pascal/FileEntry.h create mode 100644 Pascal/Pascal.h create mode 100644 Pascal/VolumeEntry.h diff --git a/Pascal/Entry.cpp b/Pascal/Entry.cpp index 9195dae..e7bd872 100644 --- a/Pascal/Entry.cpp +++ b/Pascal/Entry.cpp @@ -1,4 +1,4 @@ -#include +#include #include diff --git a/Pascal/Entry.h b/Pascal/Entry.h new file mode 100644 index 0000000..0de413d --- /dev/null +++ b/Pascal/Entry.h @@ -0,0 +1,81 @@ +#ifndef __PASCAL_ENTRY_H__ +#define __PASCAL_ENTRY_H__ + +#include + + +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; + + class 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; } + + VolumeEntry *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; + VolumeEntry *_parent; + unsigned _address; + + }; + + +} + +#endif + diff --git a/Pascal/File.h b/Pascal/File.h deleted file mode 100644 index 6e51c4f..0000000 --- a/Pascal/File.h +++ /dev/null @@ -1,242 +0,0 @@ -#ifndef __PASCAL_FILE_H__ -#define __PASCAL_FILE_H__ - -#include - -#include -#include - -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; - -class 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; } - - VolumeEntry *parent() { return _parent; } - - - static bool Compress(std::string& text); - static bool Uncompress(std::string &text); - -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; - VolumeEntry *_parent; - unsigned _address; - -}; - - -class VolumeEntry : public Entry { - -public: - - static unsigned ValidName(const char *); - - - // create new - VolumeEntry(const char *name, Device::BlockDevice *); - - // open existing - VolumeEntry(Device::BlockDevice *); - virtual ~VolumeEntry(); - - const char *name() const { return _fileName; } - unsigned fileCount() const { return _fileCount; } - unsigned volumeBlocks() const { return _lastVolumeBlock; } - - Pascal::Date lastBoot() const { return _lastBoot; } - - FileEntry *fileAtIndex(unsigned i) const; - FileEntry *fileByName(const char *name) const; - - void addChild(FileEntry *child, unsigned blocks); - - - - void *loadBlock(unsigned block); - void unloadBlock(unsigned block, bool dirty = false); - - void readBlock(unsigned block, void *); - void writeBlock(unsigned block, void *); - - void sync(); - - unsigned unlink(const char *name); - unsigned rename(const char *oldName, const char *newName); - - unsigned krunch(); - - -protected: - virtual void writeDirectoryEntry(LittleEndian::IOBuffer *); - -private: - - friend class FileEntry; - - VolumeEntry(); - - void init(void *); - - - 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); - - - unsigned _fileNameLength; - char _fileName[8]; - unsigned _lastVolumeBlock; - unsigned _fileCount; - unsigned _accessTime; - Pascal::Date _lastBoot; - - std::vector _files; - unsigned _inodeGenerator; - - Device::BlockDevice *_device; - Device::BlockCache *_cache; -}; - - -class FileEntry : public Entry { - public: - - - static unsigned ValidName(const char *); - - static bool Compress(std::string& text); - static bool Uncompress(std::string& text); - - - FileEntry(const char *name, unsigned fileKind); - FileEntry(void *vp); - virtual ~FileEntry(); - - unsigned fileSize(); - - unsigned lastByte() const { return _lastByte; } - - int read(uint8_t *buffer, unsigned size, unsigned offset); - int write(uint8_t *buffer, unsigned size, unsigned offset); - - int truncate(unsigned newSize); - - - const char *name() const { return _fileName; } - Date modification() const { return _modification; } - - void setFileKind(unsigned kind); - - - - - protected: - - virtual void writeDirectoryEntry(LittleEndian::IOBuffer *); - - private: - - - friend class VolumeEntry; - - void setName(const char *name); - - void truncateCommon(unsigned newSize); - - - - 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 *_pageSize; - unsigned _fileSize; - -}; - - - -} - -#endif - diff --git a/Pascal/FileEntry.h b/Pascal/FileEntry.h new file mode 100644 index 0000000..8774398 --- /dev/null +++ b/Pascal/FileEntry.h @@ -0,0 +1,94 @@ +#ifndef __PASCAL_FILEENTRY_H__ +#define __PASCAL_FILEENTRY_H__ + +#include + +#include +#include + +namespace Pascal { + + class FileEntry : public Entry { + + public: + + + + static unsigned ValidName(const char *); + + static bool Compress(std::string& text); + static bool Uncompress(std::string& text); + + + FileEntry(const char *name, unsigned fileKind); + FileEntry(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(uint8_t *buffer, unsigned size, unsigned offset); + + int truncate(unsigned newSize); + + + protected: + + virtual void writeDirectoryEntry(LittleEndian::IOBuffer *); + + private: + + + friend class VolumeEntry; + + void setName(const char *name); + + void truncateCommon(unsigned newSize); + + + + 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 *_pageSize; + unsigned _fileSize; + + }; + + +} + +#endif + diff --git a/Pascal/Pascal.h b/Pascal/Pascal.h new file mode 100644 index 0000000..edfbcd4 --- /dev/null +++ b/Pascal/Pascal.h @@ -0,0 +1,9 @@ +#ifndef __PASCAL_FILE_H__ +#define __PASCAL_FILE_H__ + +#include +#include +#include +#include + +#endif \ No newline at end of file diff --git a/Pascal/VolumeEntry.h b/Pascal/VolumeEntry.h new file mode 100644 index 0000000..470ea10 --- /dev/null +++ b/Pascal/VolumeEntry.h @@ -0,0 +1,96 @@ +#ifndef __PASCAL_VOLUMEENTRY_H__ +#define __PASCAL_VOLUMEENTRY_H__ + +#include + +#include + + +namespace Pascal { + + class FileEntry; + + class VolumeEntry : public Entry { + + public: + + static unsigned ValidName(const char *); + + + // create new + VolumeEntry(const char *name, Device::BlockDevice *); + + // open existing + VolumeEntry(Device::BlockDevice *); + virtual ~VolumeEntry(); + + const char *name() const { return _fileName; } + unsigned fileCount() const { return _fileCount; } + unsigned volumeBlocks() const { return _lastVolumeBlock; } + + Pascal::Date lastBoot() const { return _lastBoot; } + + FileEntry *fileAtIndex(unsigned i) const; + FileEntry *fileByName(const char *name) const; + + void addChild(FileEntry *child, unsigned blocks); + + + + void *loadBlock(unsigned block); + void unloadBlock(unsigned block, bool dirty = false); + + void readBlock(unsigned block, void *); + void writeBlock(unsigned block, void *); + + void sync(); + + unsigned unlink(const char *name); + unsigned rename(const char *oldName, const char *newName); + + unsigned krunch(); + + + protected: + virtual void writeDirectoryEntry(LittleEndian::IOBuffer *); + + private: + + friend class FileEntry; + + VolumeEntry(); + + void init(void *); + + + 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); + + + unsigned _fileNameLength; + char _fileName[8]; + unsigned _lastVolumeBlock; + unsigned _fileCount; + unsigned _accessTime; + Pascal::Date _lastBoot; + + std::vector _files; + unsigned _inodeGenerator; + + Device::BlockDevice *_device; + Device::BlockCache *_cache; + }; + + + + + +} + +#endif + From 776475f33e25652df69feca0ede598f52f7ac363 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 26 May 2010 22:19:43 +0000 Subject: [PATCH 155/236] pascal headers git-svn-id: https://profuse.googlecode.com/svn/branches/v2@282 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/Entry.h | 1 + Pascal/FileEntry.cpp | 2 +- Pascal/VolumeEntry.cpp | 2 +- apfm.cpp | 2 +- fuse_pascal.cpp | 2 +- fuse_pascal_ops.cpp | 2 +- newfs_pascal.cpp | 2 +- 7 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Pascal/Entry.h b/Pascal/Entry.h index 0de413d..c4438d9 100644 --- a/Pascal/Entry.h +++ b/Pascal/Entry.h @@ -69,6 +69,7 @@ namespace Pascal { private: friend class VolumeEntry; + VolumeEntry *_parent; unsigned _address; diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index 58aefc9..72bdb4a 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include #include diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index d6f12be..c7d0ed4 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -1,7 +1,7 @@ #include -#include +#include #include #include diff --git a/apfm.cpp b/apfm.cpp index 2d316c2..e186ba2 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include diff --git a/fuse_pascal.cpp b/fuse_pascal.cpp index 4e7631c..40bfd39 100644 --- a/fuse_pascal.cpp +++ b/fuse_pascal.cpp @@ -18,7 +18,7 @@ #include -#include +#include #include #include diff --git a/fuse_pascal_ops.cpp b/fuse_pascal_ops.cpp index 5eecbe7..a111191 100644 --- a/fuse_pascal_ops.cpp +++ b/fuse_pascal_ops.cpp @@ -22,7 +22,7 @@ -#include +#include #include #include diff --git a/newfs_pascal.cpp b/newfs_pascal.cpp index 72afee5..d768ceb 100644 --- a/newfs_pascal.cpp +++ b/newfs_pascal.cpp @@ -4,7 +4,7 @@ #include -#include +#include #include #include From 9cf52398a2dcb32352c0348a7057ac0f3a39af0c Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 27 May 2010 04:15:11 +0000 Subject: [PATCH 156/236] typo git-svn-id: https://profuse.googlecode.com/svn/branches/v2@283 aa027e90-d47c-11dd-86d7-074df07e0730 --- ProFUSE/Exception.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ProFUSE/Exception.h b/ProFUSE/Exception.h index b4ce9ab..3216081 100644 --- a/ProFUSE/Exception.h +++ b/ProFUSE/Exception.h @@ -12,7 +12,7 @@ enum { badSystemCall = 0x01, invalidPcount = 0x04, - gsosActice = 0x07, + gsosActive = 0x07, devNotFound = 0x10, invalidDevNum = 0x11, drvrBadReq = 0x20, From 0fda850b94e50cae7d6df2f06c2c26179a66928f Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 27 May 2010 04:15:39 +0000 Subject: [PATCH 157/236] readOnly not corerctly set git-svn-id: https://profuse.googlecode.com/svn/branches/v2@284 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/DiskImage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Device/DiskImage.cpp b/Device/DiskImage.cpp index 1c8d0cf..024bf15 100644 --- a/Device/DiskImage.cpp +++ b/Device/DiskImage.cpp @@ -41,7 +41,7 @@ DiskImage::DiskImage(MappedFile *file) _file.adopt(*file); _blocks = 0; - _readOnly = file->readOnly(); + _readOnly = _file.readOnly(); _adaptor = NULL; } From 10190d13a2137b5f2bd1501e546f66f6bdb05d39 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 27 May 2010 04:16:04 +0000 Subject: [PATCH 158/236] unlink git-svn-id: https://profuse.googlecode.com/svn/branches/v2@285 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/FileEntry.cpp | 18 ++++++--- Pascal/VolumeEntry.cpp | 91 +++++++++++++++++++++++++++++++++--------- apfm.cpp | 14 +++++-- 3 files changed, 97 insertions(+), 26 deletions(-) diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index 72bdb4a..ffbf206 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -25,8 +25,16 @@ enum { kDLE = 16 }; -#pragma mark - -#pragma mark FileEntry + +/* + * _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) { @@ -195,7 +203,7 @@ void FileEntry::truncateCommon(unsigned newSize) throw ProFUSE::POSIXException(__METHOD__ ": Unable to expand file.", ENOSPC); unsigned remainder = newSize - currentSize; - unsigned block = _lastBlock; + unsigned block = _lastBlock - 1; if (_lastByte != 512) { @@ -227,7 +235,7 @@ void FileEntry::truncateCommon(unsigned newSize) } - _lastBlock = _firstBlock + newSize / 512; + _lastBlock = 1 + _firstBlock + newSize / 512; _lastByte = newSize % 512; if (_lastByte = 0) _lastByte = 512; @@ -294,7 +302,7 @@ int FileEntry::write(uint8_t *buffer, unsigned size, unsigned offset) if (newSize > currentSize) { - _lastBlock = _firstBlock + currentSize / 512; + _lastBlock = 1 + _firstBlock + currentSize / 512; _lastByte = currentSize % 512; if (_lastByte == 0) _lastByte = 512; diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index c7d0ed4..66afc9e 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -1,5 +1,6 @@ #include +#include #include @@ -12,14 +13,17 @@ #include #include -#pragma mark - -#pragma mark VolumeEntry + using namespace LittleEndian; using namespace Pascal; using namespace Device; +using ProFUSE::Exception; +using ProFUSE::ProDOSException; +using ProFUSE::POSIXException; + unsigned VolumeEntry::ValidName(const char *cp) { // 7 chars max. Legal values: ascii, printable, @@ -50,10 +54,18 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device) #define __METHOD__ "VolumeEntry::VolumeEntry" unsigned length; + unsigned deviceBlocks = device->blocks(); + + + deviceBlocks = std::min(0xffffu, deviceBlocks); + if (deviceBlocks < 6) + throw Exception(__METHOD__ ": device too small."); + + length = ValidName(name); if (!length) - throw ProFUSE::Exception(__METHOD__ ": Invalid volume name."); + throw ProDOSException(__METHOD__ ": Invalid volume name.", ProFUSE::badPathSyntax); _firstBlock = 0; _lastBlock = 6; @@ -69,7 +81,7 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device) _fileName[i] = std::toupper(name[i]); } - _lastVolumeBlock = device->blocks(); + _lastVolumeBlock = deviceBlocks; _fileCount = 0; _accessTime = 0; _lastBoot = Date::Today(); @@ -99,6 +111,7 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device) VolumeEntry::VolumeEntry(Device::BlockDevice *device) { unsigned blockCount; + unsigned deviceBlocks = device->blocks(); ProFUSE::auto_array buffer(new uint8_t[512]); @@ -132,8 +145,11 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device) try { - std::vector::reverse_iterator iter; + std::vector::reverse_iterator riter; + std::vector::iterator iter; + unsigned block; + for (unsigned i = 1; i <= _fileCount; ++i) { std::auto_ptr child; @@ -150,13 +166,40 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device) // sanity check _firstBlock, _lastBlock? - // set up _maxBlocks; - unsigned lastBlock = _lastVolumeBlock; - for (iter = _files.rbegin(); iter != _files.rend(); ++iter) + block = _lastBlock; + + for (iter = _files.begin(); iter != _files.end(); ++iter) { FileEntry *e = *iter; - e->_maxFileSize = (lastBlock - e->_firstBlock) * 512; - lastBlock = e->_firstBlock - 1; + bool error = false; + if (e->_firstBlock > e->_lastBlock) + error = true; + + if (e->_firstBlock >= _lastVolumeBlock) + error = true; + + if (e->_lastBlock > _lastVolumeBlock) + error = true; + + if (e->_firstBlock < block) + error = true; + + if (error) + throw ProDOSException(__METHOD__ ": Invalid file entry.", ProFUSE::dirError); + + block = e->_lastBlock; + + } + + + + // set up _maxFileSize; + block= _lastVolumeBlock; + for (riter = _files.rbegin(); riter != _files.rend(); ++riter) + { + FileEntry *e = *riter; + e->_maxFileSize = (block - e->_firstBlock) * 512; + block = e->_firstBlock; } } @@ -200,7 +243,7 @@ void VolumeEntry::init(void *vp) // verify filenamelength <= 7 if (_fileNameLength > 7) - throw new ProFUSE::Exception(__METHOD__ ": invalid name length"); + throw new ProDOSException(__METHOD__ ": invalid name length", ProFUSE::badPathSyntax); // verify fileKind == 0 // verify _fileCount reasonable @@ -240,29 +283,41 @@ unsigned VolumeEntry::unlink(const char *name) { unsigned index; + std::vector::iterator iter; + // TODO -- update _maxFileSize. if (_device->readOnly()) return ProFUSE::drvrWrtProt; // WRITE-PROTECTED DISK - for(index = 0; index < _fileCount; ++index) + for (index = 0, iter = _files.begin(); iter != _files.end(); ++iter, ++index) { - FileEntry *e = _files[index]; + FileEntry *e = *iter; if (::strcasecmp(name, e->name()) == 0) { + + // if not the first entry, update the previous entry's + // _maxFileSize. + if (iter != _files.begin()) + { + FileEntry *prev = iter[-1]; + prev->_maxFileSize += e->_maxFileSize; + } + delete e; - _files[index] = NULL; + *iter = NULL; break; } } - if (index == _fileCount) return ProFUSE::fileNotFound; // FILE NOT FOUND + if (iter == _files.end()) return ProFUSE::fileNotFound; // FILE NOT FOUND - _files.erase(_files.begin() + index); + + _files.erase(iter); _fileCount--; // reset addresses. - for (unsigned i = index; i < _fileCount; ++i) + for ( ; iter != _files.end(); ++iter) { - FileEntry *e = _files[i]; + FileEntry *e = *iter; e->_address -= 0x1a; } diff --git a/apfm.cpp b/apfm.cpp index e186ba2..8fcca3f 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -239,9 +239,16 @@ int action_mv(int argc, char **argv, Pascal::VolumeEntry *volume) int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume) { - // mv rm file [file ....] - // needs ':' as f + // rm file [file ....] + + + // TODO -- catch errors. + for (unsigned i = 1; i < argc; ++i) + { + volume->unlink(argv[i]); + } return 0; + } int action_krunch(int argc, char **argv, Pascal::VolumeEntry *volume) @@ -492,8 +499,9 @@ int main(int argc, char **argv) try { + // should we peek at the action to determine if read only? - device.reset( Device::BlockDevice::Open(file, true, fmt) ); + device.reset( Device::BlockDevice::Open(file, false, fmt) ); From 7be0fc5c56dae15f91eb00ed7c11828c525871b0 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 27 May 2010 16:18:53 +0000 Subject: [PATCH 159/236] update makefile git-svn-id: https://profuse.googlecode.com/svn/branches/v2@286 aa027e90-d47c-11dd-86d7-074df07e0730 --- Makefile | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 055ad60..6787fbd 100644 --- a/Makefile +++ b/Makefile @@ -119,20 +119,23 @@ ProFUSE/Exception.o: ProFUSE/Exception.cpp ProFUSE/Exception.h ProFUSE/Lock.o: ProFUSE/Lock.cpp ProFUSE/Lock.h + Pascal/Date.o: Pascal/Date.cpp Pascal/Date.h -Pascal/Entry.o: Pascal/Entry.cpp Pascal/File.h Pascal/Date.h \ - ProFUSE/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/File.h Pascal/Date.h \ - ProFUSE/auto.h ProFUSE/Exception.h Endian/Endian.h Endian/IOBuffer.h \ +Pascal/Entry.o: Pascal/Entry.cpp Pascal/Entry.h Pascal/Date.h \ + ProFUSE/Exception.h Endian/Endian.h Endian/IOBuffer.h \ Endian/IOBuffer.cpp.h Device/BlockDevice.h Device/TrackSector.h \ Cache/BlockCache.h -Pascal/VolumeEntry.o: Pascal/VolumeEntry.cpp Pascal/File.h Pascal/Date.h \ - ProFUSE/auto.h ProFUSE/Exception.h Endian/Endian.h Endian/IOBuffer.h \ +Pascal/FileEntry.o: Pascal/FileEntry.cpp Pascal/Pascal.h Pascal/Date.h \ + Pascal/Entry.h Pascal/FileEntry.h Pascal/VolumeEntry.h ProFUSE/auto.h \ + ProFUSE/Exception.h Endian/Endian.h Endian/IOBuffer.h \ + Endian/IOBuffer.cpp.h Device/BlockDevice.h Device/TrackSector.h \ + Cache/BlockCache.h + +Pascal/VolumeEntry.o: Pascal/VolumeEntry.cpp Pascal/Pascal.h Pascal/Date.h \ + Pascal/Entry.h Pascal/FileEntry.h Pascal/VolumeEntry.h ProFUSE/auto.h \ + ProFUSE/Exception.h Endian/Endian.h Endian/IOBuffer.h \ Endian/IOBuffer.cpp.h Device/BlockDevice.h Device/TrackSector.h \ Cache/BlockCache.h From 54a75af101683d2855397235a0a31c8dbbefa07c Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 27 May 2010 16:22:12 +0000 Subject: [PATCH 160/236] update makefile git-svn-id: https://profuse.googlecode.com/svn/branches/v2@287 aa027e90-d47c-11dd-86d7-074df07e0730 --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 6787fbd..dfb097f 100644 --- a/Makefile +++ b/Makefile @@ -43,16 +43,16 @@ xattr.o: xattr.cpp newfs_pascal.o: newfs_pascal.cpp Device/BlockDevice.h ProFUSE/Exception.h \ Device/TrackSector.h Cache/BlockCache.h Device/RawDevice.h File/File.h \ - Pascal/File.h Pascal/Date.h + Pascal/Pascal.h Pascal/Date.h -fuse_pascal.o: fuse_pascal.cpp Pascal/File.h Pascal/Date.h \ +fuse_pascal.o: fuse_pascal.cpp Pascal/Pascal.h Pascal/Date.h \ ProFUSE/Exception.h Device/BlockDevice.h Device/TrackSector.h \ Cache/BlockCache.h -fuse_pascal_ops.o: fuse_pascal_ops.cpp Pascal/File.h Pascal/Date.h \ +fuse_pascal_ops.o: fuse_pascal_ops.cpp Pascal/Pascal.h Pascal/Date.h \ ProFUSE/auto.h ProFUSE/Exception.h -apfm.o: apfm.cpp Pascal/File.h Pascal/Date.h Device/BlockDevice.h \ +apfm.o: apfm.cpp Pascal/Pascal.h Pascal/Date.h Device/BlockDevice.h \ ProFUSE/Exception.h Device/TrackSector.h Cache/BlockCache.h File/File.o: File/File.cpp File/File.h ProFUSE/Exception.h From e4efb135edf02cf600c1aa51b220d95169febb83 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 27 May 2010 16:23:24 +0000 Subject: [PATCH 161/236] =/== issue git-svn-id: https://profuse.googlecode.com/svn/branches/v2@288 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/FileEntry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index ffbf206..20ed478 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -237,7 +237,7 @@ void FileEntry::truncateCommon(unsigned newSize) _lastBlock = 1 + _firstBlock + newSize / 512; _lastByte = newSize % 512; - if (_lastByte = 0) _lastByte = 512; + if (_lastByte == 0) _lastByte = 512; } From d4a8391650b12f98be80749ee8a7c60bf3c37db8 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 28 May 2010 03:13:20 +0000 Subject: [PATCH 162/236] create() git-svn-id: https://profuse.googlecode.com/svn/branches/v2@289 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/VolumeEntry.cpp | 130 +++++++++++++++++++++++++++++++++++------ Pascal/VolumeEntry.h | 9 +++ 2 files changed, 120 insertions(+), 19 deletions(-) diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index 66afc9e..46637d8 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -1,6 +1,7 @@ #include #include +#include #include @@ -24,6 +25,10 @@ using ProFUSE::Exception; using ProFUSE::ProDOSException; using ProFUSE::POSIXException; +enum { + kMaxFiles = 77 +}; + unsigned VolumeEntry::ValidName(const char *cp) { // 7 chars max. Legal values: ascii, printable, @@ -145,7 +150,6 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device) try { - std::vector::reverse_iterator riter; std::vector::iterator iter; unsigned block; @@ -192,15 +196,7 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device) } - - // set up _maxFileSize; - block= _lastVolumeBlock; - for (riter = _files.rbegin(); riter != _files.rend(); ++riter) - { - FileEntry *e = *riter; - e->_maxFileSize = (block - e->_firstBlock) * 512; - block = e->_firstBlock; - } + calcMaxFileSize(); } catch (...) @@ -379,6 +375,94 @@ unsigned VolumeEntry::rename(const char *oldName, const char *newName) } +/* + * create a file. if blocks is defined, verifies the file could + * expand to fit. + * + */ +FileEntry *VolumeEntry::create(const char *name, unsigned blocks) +{ + // 0. check read only access. + // 1. verify < 77 file names. + // 2. verify space at end of disk. + // 3. make sure it's a legal file name. + // 4. verify it's not a duplicate file name. + // 6. create the file entry. + // 7. insert into _files, write to disk, update _maxFileSize + + unsigned lastBlock; + unsigned maxBlocks; + + std::auto_ptrentry; + FileEntry *prev = NULL; + FileEntry *curr = NULL; + + if (readOnly()) + { + errno = EACCES; + return NULL; + } + + if (_fileCount == kMaxFiles) + { + errno = ENOSPC; + return NULL; + } + + if (_fileCount) + { + prev = _files.back(); + lastBlock = prev->_lastBlock; + } + else { + lastBlock = _lastBlock; + } + + maxBlocks = _lastVolumeBlock - lastBlock; + + if (maxBlocks < blocks || maxBlocks == 0) + { + errno = ENOSPC; + return NULL; + } + + if (!FileEntry::ValidName(name)) + { + errno = ENAMETOOLONG; // or invalid. + return NULL; + } + + if (fileByName(name)) + { + errno = EEXIST; + return NULL; + } + + + entry.reset(new FileEntry(name, kUntypedFile)); + + _files.push_back(entry.get()); + + curr = entry.release(); + + curr->_firstBlock = lastBlock; + curr->_lastBlock = lastBlock + 1; + curr->_lastByte = 0; + curr->_maxFileSize = maxBlocks * 512; + + if (prev) + { + prev->_maxFileSize = prev->blocks() * 512; + } + + writeEntry(curr); + + return curr; + +} + + + unsigned VolumeEntry::krunch() { @@ -468,6 +552,9 @@ unsigned VolumeEntry::krunch() _cache->sync(); + + calcMaxFileSize(); + return 0; } @@ -476,14 +563,6 @@ unsigned VolumeEntry::krunch() - - - - - - - - void *VolumeEntry::loadBlock(unsigned block) { return _cache->acquire(block); @@ -584,6 +663,19 @@ void VolumeEntry::writeEntry(FileEntry *e) writeBlocks(buffer.get(), startBlock, 2); } +} -} \ No newline at end of file +// set _maxFileSize for all entries. +void VolumeEntry::calcMaxFileSize() +{ + std::vector::reverse_iterator riter; + unsigned block = _lastVolumeBlock; + for (riter = _files.rbegin(); riter != _files.rend(); ++riter) + { + FileEntry *e = *riter; + e->_maxFileSize = (block - e->_firstBlock) * 512; + block = e->_firstBlock; + } + +} diff --git a/Pascal/VolumeEntry.h b/Pascal/VolumeEntry.h index 470ea10..5bf52dd 100644 --- a/Pascal/VolumeEntry.h +++ b/Pascal/VolumeEntry.h @@ -5,6 +5,7 @@ #include +#include namespace Pascal { @@ -44,10 +45,16 @@ namespace Pascal { void writeBlock(unsigned block, void *); void sync(); + + bool readOnly() { return _device->readOnly(); } unsigned unlink(const char *name); unsigned rename(const char *oldName, const char *newName); + + FileEntry *create(const char *name, unsigned blocks); + + unsigned krunch(); @@ -71,6 +78,8 @@ namespace Pascal { void writeEntry(FileEntry *e); + void calcMaxFileSize(); + unsigned _fileNameLength; char _fileName[8]; From 7cb873bfcf85605aede5ac094395e881f284663f Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 28 May 2010 03:13:41 +0000 Subject: [PATCH 163/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@290 aa027e90-d47c-11dd-86d7-074df07e0730 --- apfm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apfm.cpp b/apfm.cpp index 8fcca3f..1fb91a9 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -241,7 +241,7 @@ int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume) { // rm file [file ....] - + // TODO -- -f flag to prompt for each file. // TODO -- catch errors. for (unsigned i = 1; i < argc; ++i) { From 525fe7810af975f648b9c134e6c70bd74a735201 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 29 May 2010 01:03:20 +0000 Subject: [PATCH 164/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@291 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/VolumeEntry.cpp | 37 +++++++++++++++++++++++++++++++++++++ Pascal/VolumeEntry.h | 10 +++++----- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index 46637d8..5ee5031 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -339,6 +339,7 @@ unsigned VolumeEntry::unlink(const char *name) } +// TODO -- if newName exists, atomically remove it. unsigned VolumeEntry::rename(const char *oldName, const char *newName) { FileEntry *e; @@ -561,6 +562,42 @@ unsigned VolumeEntry::krunch() +/* + * return the number of free blocks. + * if krunched is true, returns sum of all free blocks + * if krunched is false, returns free blocks at end. + * + */ +unsigned VolumeEntry::freeBlocks(bool krunched) const +{ + unsigned freeBlocks = 0; + unsigned lastBlock = 0; + + if (krunched) + { + std::vector::const_iterator iter; + + lastBlock = _lastBlock; + + for (iter = _files.begin(); iter != _files.end(); ++iter) + { + const FileEntry *e = *iter; + freeBlocks += e->_firstBlock - lastBlock; + lastBlock = e->_lastBlock; + } + } + else + { + lastBlock = _fileCount ? _files.back()->_lastBlock : _lastBlock; + } + + + freeBlocks += _lastVolumeBlock - lastBlock; + return freeBlocks; +} + + + void *VolumeEntry::loadBlock(unsigned block) diff --git a/Pascal/VolumeEntry.h b/Pascal/VolumeEntry.h index 5bf52dd..fd40240 100644 --- a/Pascal/VolumeEntry.h +++ b/Pascal/VolumeEntry.h @@ -31,12 +31,12 @@ namespace Pascal { Pascal::Date lastBoot() const { return _lastBoot; } + unsigned freeBlocks(bool krunched = false) const; + + FileEntry *fileAtIndex(unsigned i) const; FileEntry *fileByName(const char *name) const; - void addChild(FileEntry *child, unsigned blocks); - - void *loadBlock(unsigned block); void unloadBlock(unsigned block, bool dirty = false); @@ -50,11 +50,11 @@ namespace Pascal { unsigned unlink(const char *name); unsigned rename(const char *oldName, const char *newName); - - FileEntry *create(const char *name, unsigned blocks); + + unsigned krunch(); From 80a0061d9206a7203ab9ee3faedafd6a29a52c41 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 29 May 2010 01:04:14 +0000 Subject: [PATCH 165/236] add more help git-svn-id: https://profuse.googlecode.com/svn/branches/v2@292 aa027e90-d47c-11dd-86d7-074df07e0730 --- apfm.cpp | 353 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 280 insertions(+), 73 deletions(-) diff --git a/apfm.cpp b/apfm.cpp index 1fb91a9..357feeb 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -23,6 +23,143 @@ #include + +enum commands { + kCommandLS = 1, + kCommandCAT, + kCommandCP, + kCommandMV, + kCommandRM, + kCommandGET, + kCommandPUT, + kCommandKRUNCH +}; + + +void usage() +{ + std::fputs( + "Pascal File Manager v 0.0\n\n" + "Usage: apfm [-h] [-f format] diskimage action ...\n" + "Options:\n" + " -h Show usage information.\n" + " -f format Specify disk format. Valid values are:\n" + " po: ProDOS order disk image\n" + " do: DOS Order disk image\n" + "\n" + "Actions:\n" + " cat\n" + " krunch\n" + " ls\n" + " cp\n" + " mv\n" + " rm\n" + " get\n" + " put\n", + stdout + ); + +} + +void commandUsage(unsigned command) +{ + const char *text = ""; + + switch(command) + { + case kCommandLS: + text = + "List the volume contents.\n\n" + "apfm file ls [-l]\n" + "Options:\n" + " -l Extended listing\n" + ; + break; + + + case kCommandKRUNCH: + text = + "Move free blocks to the end of the volume.\n\n" + "apfm krunch [-fi]\n" + "Options:\n" + " -f Force\n" + " -i Interactive\n" + ; + break; + + case kCommandCAT: + text = + "Print the contents of a file to stdout.\n\n" + "apfm cat file ...\n" + ; + break; + + case kCommandCP: + text = + "Copy a file.\n\n" + "apfm cp [-fi] source target\n" + "Options:\n" + " -f Force\n" + " -i Interactive\n" + ; + break; + + case kCommandMV: + text = + "Rename a file.\n\n" + "apfm mv [-fi] source target\n" + "Options:\n" + " -f Force\n" + " -i Interactive\n" + ; + break; + + case kCommandGET: + text = + "Copy a file from the Pascal volume to the native file system.\n\n" + "apfm get [-fi] source [target]\n" + "Options:\n" + " -f Force\n" + " -i Interactive\n" + ; + break; + + case kCommandPUT: + text = + "Copy a file from the native file system to the Pascal volume.\n\n" + "apfm put [-fi] source [target]\n" + "Options:\n" + " -f Force\n" + " -i Interactive\n" + " -t type Set the file type. Valid values:\n" + " code\n" + " data\n" + " foto\n" + " graf\n" + " info\n" + " text\n" + ; + break; + } + + std::fputs(text, stdout); +} + + + +// from BSD rm, prompt question on stderr. +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'); +} + + const char *MonthName(unsigned m) { static const char *months[] = { @@ -109,24 +246,30 @@ int action_ls(int argc, char **argv, Pascal::VolumeEntry *volume) unsigned max = 0; unsigned volumeSize = volume->volumeBlocks(); unsigned lastBlock = volume->lastBlock(); - int ch; + int c; std::fprintf(stdout, "%s:\n", volume->name()); //argv[0] = "afpm ls"; - while ((ch = ::getopt(argc, argv, "l")) != -1) + while ((c = ::getopt(argc, argv, "lh")) != -1) { - switch(ch) + switch(c) { - case 'l': - extended = true; - break; + case 'l': + extended = true; + break; + case 'h': + default: + commandUsage(kCommandLS); + return c == 'h' ? 0 : 1; + break; } } argc -= optind; argv += optind; + // only print listed files? for (unsigned i = 0; i < fileCount; ++i) { @@ -180,13 +323,31 @@ int action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume) // cat file1, file2... //argv[0] = "afpm cat"; - if (argc < 2) + int c; + + while ((c = ::getopt(argc, argv, "h")) != -1) { - std::fprintf(stderr, "apfm cat: Please specify one or more files.\n"); + switch(c) + { + case 'h': + default: + commandUsage(kCommandRM); + return c == 'h' ? 0 : 1; + break; + } + } + + + argc += optind; + argv -= optind; + + if (argc < 1) + { + commandUsage(kCommandCAT); return 1; } - for (unsigned i = 1; i < argc; ++i) + for (unsigned i = 0; i < argc; ++i) { const char *fname = argv[i]; unsigned fileSize; @@ -195,12 +356,7 @@ int action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume) Pascal::FileEntry *e = NULL; // find it... - for (unsigned i = 0, l = volume->fileCount(); i < l; ++i) - { - e = volume->fileAtIndex(i); - if (::strcasecmp(e->name(), fname) == 0) break; - e = NULL; - } + e = volume->fileByName(argv[i]); if (!e) { @@ -223,27 +379,52 @@ int action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume) return 0; } -int action_cp(int argc, char **argv, Pascal::VolumeEntry *volume) -{ - // cp src dest - // first character of ':' indicates pascal file, otherwise, is native file? - return 0; -} + int action_mv(int argc, char **argv, Pascal::VolumeEntry *volume) { // mv src dest - // first character of ':' indicates pascal file, otherwise is native file? + return 0; +} + +int action_cp(int argc, char **argv, Pascal::VolumeEntry *volume) +{ + // mv src dest return 0; } int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume) { // rm file [file ....] - - // TODO -- -f flag to prompt for each file. + + bool tty = ::isatty(STDIN_FILENO); + bool fFlag = !tty; + int c; + + while ((c = ::getopt(argc, argv, "fih")) != -1) + { + switch(c) + { + case 'f': + fFlag = true; + break; + case 'i': + fFlag = false; + + case 'h': + default: + commandUsage(kCommandRM); + return c == 'h' ? 0 : 1; + break; + } + } + + argc += optind; + argv -= optind; + + // TODO -- honor fFlag // TODO -- catch errors. - for (unsigned i = 1; i < argc; ++i) + for (unsigned i = 0; i < argc; ++i) { volume->unlink(argv[i]); } @@ -254,6 +435,34 @@ int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume) int action_krunch(int argc, char **argv, Pascal::VolumeEntry *volume) { // compress file to remove gaps. + + bool tty = ::isatty(STDIN_FILENO); + bool fFlag = !tty; + int c; + + while ((c = ::getopt(argc, argv, "fih")) != -1) + { + switch(c) + { + case 'f': + fFlag = true; + break; + case 'i': + fFlag = false; + + case 'h': + default: + commandUsage(kCommandKRUNCH); + return c == 'h' ? 0 : 1; + break; + } + } + + argc += optind; + argv -= optind; + + //check if it needs krunching, volume->krunch(); + return 0; } @@ -261,11 +470,36 @@ int action_krunch(int argc, char **argv, Pascal::VolumeEntry *volume) int action_get(int argc, char **argv, Pascal::VolumeEntry *volume) { - // get pascal_file [native file]; + // get [-f] pascal_file [native file]; char *infile; char *outfile; + bool tty = ::isatty(STDIN_FILENO); + bool fFlag = !tty; + int c; + + while ((c = ::getopt(argc, argv, "fih")) != -1) + { + switch(c) + { + case 'f': + fFlag = true; + break; + case 'i': + fFlag = false; + + case 'h': + default: + commandUsage(kCommandKRUNCH); + return c == 'h' ? 0 : 1; + break; + } + } + + argc += optind; + argv -= optind; + Pascal::FileEntry *entry; switch(argc) @@ -278,12 +512,16 @@ int action_get(int argc, char **argv, Pascal::VolumeEntry *volume) outfile = argv[1]; break; default: - std::fprintf(stderr, "apfm cat: Please specify an infile (and an optional outfile)\n"); + commandUsage(kCommandKRUNCH); + return 1; + break; } entry = volume->fileByName(infile); + // if outfile exists, !fFlag, prompt before overwriting. + File::File file(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (!entry) @@ -402,27 +640,8 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) } #endif -void usage() -{ - std::printf( - "Pascal File Manager v 0.0\n\n" - "Usage: fileman [-h] [-f format] diskimage action ...\n" - "Options:\n" - " -h Show usage information.\n" - " -f format Specify disk format. Valid values are:\n" - " po: ProDOS order disk image\n" - " do: DOS Order disk image\n" - "\n" - "Actions:\n" - " cat\n" - " cp\n" - " krunch\n" - " ls\n" - " mv\n" - " rm\n" - ); -} + int main(int argc, char **argv) { @@ -438,18 +657,7 @@ int main(int argc, char **argv) putenv((char *)"POSIXLY_CORRECT=1"); // fix getopt to not mutate #endif - /* - char *argv2[] = { - (char *)"afpm", - //(char *)"/Users/kelvin/Desktop/ucsd/pascal.dsk", - (char *)"/Users/kelvin/Desktop/ucsd/UCSD Pascal 1.2_3.DSK", - (char *)"cat", - (char *)"SPIRODEMO.TEXT", - NULL - }; - char **argv = argv2; - int argc = 4; - */ + // getop stops at first non '-' arg so it will not affect action flags. while ((c = ::getopt(argc, argv, "f:h")) != -1) @@ -457,20 +665,19 @@ int main(int argc, char **argv) std::printf("%c\n", c); switch(c) { - case 'f': - fmt = Device::BlockDevice::ImageType(optarg); - if (!fmt) - { - std::fprintf(stderr, "Error: Invalid file format: ``%s''.\n", - optarg); - } - break; - - case 'h': - case '?': - case ':': - usage(); - return c == 'h' ? 0 : 1; + case 'f': + fmt = Device::BlockDevice::ImageType(optarg); + if (!fmt) + { + std::fprintf(stderr, "Error: Invalid file format: ``%s''.\n", + optarg); + } + break; + + case 'h': + default: + usage(); + return c == 'h' ? 0 : 1; } } From 56ee715e01606fc18cbfb65bcdc20cf920dbb026 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 29 May 2010 18:11:34 +0000 Subject: [PATCH 166/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@293 aa027e90-d47c-11dd-86d7-074df07e0730 --- apfm.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/apfm.cpp b/apfm.cpp index 357feeb..76b249c 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -146,6 +146,17 @@ void commandUsage(unsigned command) } +bool isReadOnly(const char *command) +{ + if (!::strcasecmp(command, "mv")) return false; + if (!::strcasecmp(command, "rm")) return false; + if (!::strcasecmp(command, "cp")) return false; + if (!::strcasecmp(command, "put")) return false; + if (!::strcasecmp(command, "krunch")) return false; + + return true; +} + // from BSD rm, prompt question on stderr. bool yes_or_no() @@ -708,7 +719,7 @@ int main(int argc, char **argv) // should we peek at the action to determine if read only? - device.reset( Device::BlockDevice::Open(file, false, fmt) ); + device.reset( Device::BlockDevice::Open(file, isReadOnly(action), fmt) ); From 9098a442c96eef8ed75eeffa577d00acf293b128 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 29 May 2010 18:12:14 +0000 Subject: [PATCH 167/236] fix nibble block reading. git-svn-id: https://profuse.googlecode.com/svn/branches/v2@294 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/Adaptor.cpp | 58 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/Device/Adaptor.cpp b/Device/Adaptor.cpp index 39daaf1..75b3846 100644 --- a/Device/Adaptor.cpp +++ b/Device/Adaptor.cpp @@ -243,6 +243,7 @@ NibbleAdaptor::NibbleAdaptor(void *address, unsigned length) throw ProFUSE::Exception(__METHOD__ ": Invalid track/sector."); offset += 3 + 8 + 3; + state = 1; continue; @@ -250,9 +251,15 @@ NibbleAdaptor::NibbleAdaptor(void *address, unsigned length) if (buffer[offset + 1] == 0xaa && buffer[offset + 2] == 0xad && state == 1) { + if (_index[track * 16 + sector] != -1) + { + std::fprintf(stderr, "track %u sector %u duplicated.\n", track, sector); + } _index[track * 16 + sector] = (offset + 3) % _length; - offset += 3 + 342 + 1 + 3; + //offset += 3 + 342 + 1 + 3; + offset++; + state = 0; continue; } @@ -283,7 +290,11 @@ NibbleAdaptor::NibbleAdaptor(void *address, unsigned length) for (std::vector::iterator iter = _index.begin(); iter != _index.end(); ++iter) { if (*iter == -1) - throw ProFUSE::Exception(__METHOD__ ": Sector missing."); + { + int offset = distance(_index.begin(), iter); + std::fprintf(stderr, "Error: track %u sector %u missing.\n", offset / 16, offset % 16); + //throw ProFUSE::Exception(__METHOD__ ": Sector missing."); + } } } @@ -296,22 +307,51 @@ void NibbleAdaptor::readBlock(unsigned block, void *bp) { unsigned track = (block & ~0x07) << 9; - unsigned sector = (block & 0x07) << 1; + unsigned b = (block & 0x07) << 1; + /* + * block sectors + * 0 0, 2 + * 1 4, 6 + * 2 8, 10 + * 3 12,14 + * 4 1, 3 + * 5 5, 7 + * 6 9, 11 + * 7 13, 15 + */ + + unsigned sector = b >> 2; + if (sector >= 16) sector -= 15; + + readTrackSector(TrackSector(track, sector), bp); readTrackSector(TrackSector(track, sector + 1), (uint8_t *)bp + 256); - - } void NibbleAdaptor::writeBlock(unsigned block, const void *bp) { unsigned track = (block & ~0x07) << 9; - unsigned sector = (block & 0x07) << 1; + unsigned b = (block & 0x07) << 1; + + /* + * block sectors + * 0 0, 2 + * 1 4, 6 + * 2 8, 10 + * 3 12,14 + * 4 1, 3 + * 5 5, 7 + * 6 9, 11 + * 7 13, 15 + */ + + unsigned sector = b >> 2; + if (sector >= 16) sector -= 15; + writeTrackSector(TrackSector(track, sector), bp); writeTrackSector(TrackSector(track, sector + 1), (const uint8_t *)bp + 256); - } void NibbleAdaptor::readTrackSector(TrackSector ts, void *bp) @@ -331,6 +371,10 @@ void NibbleAdaptor::readTrackSector(TrackSector ts, void *bp) unsigned offset = _index[ts.track * 16 + ts.sector]; + if (offset == -1) + { + throw ProFUSE::Exception(__METHOD__ ": Missing track/sector."); + } // first 86 bytes are in the auxbuffer, backwards. unsigned index = offset; From 126327d0191fe31d2289148b79a9cd19e8f2143e Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 29 May 2010 18:12:32 +0000 Subject: [PATCH 168/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@295 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/VolumeEntry.cpp | 24 +++++++++++++++++++++++- Pascal/VolumeEntry.h | 2 +- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index 5ee5031..044744c 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -376,11 +376,29 @@ unsigned VolumeEntry::rename(const char *oldName, const char *newName) } +/* + * copy a file (here to simplify copying text files). + * if newName exists, delete it. + * + */ +unsigned VolumeEntry::copy(const char *oldName, const char *newName) +{ + + + return 0; +} + /* * create a file. if blocks is defined, verifies the file could * expand to fit. * */ +/* + * TODO -- if blocks is defined, try to fit in a gap rather than putting at the end. + * + * + * + */ FileEntry *VolumeEntry::create(const char *name, unsigned blocks) { // 0. check read only access. @@ -464,7 +482,11 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks) - +/* + * TODO -- consider trying to move files from the end to fill gaps + * if it would reduce the number of blocks that need to be re-arranged. + * + */ unsigned VolumeEntry::krunch() { unsigned prevBlock; diff --git a/Pascal/VolumeEntry.h b/Pascal/VolumeEntry.h index fd40240..689e081 100644 --- a/Pascal/VolumeEntry.h +++ b/Pascal/VolumeEntry.h @@ -50,11 +50,11 @@ namespace Pascal { unsigned unlink(const char *name); unsigned rename(const char *oldName, const char *newName); + unsigned copy(const char *oldName, const char *newName); FileEntry *create(const char *name, unsigned blocks); - unsigned krunch(); From 7df4d4840e2b325f88a8a9820376597e70ffe2a0 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 29 May 2010 19:29:31 +0000 Subject: [PATCH 169/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@296 aa027e90-d47c-11dd-86d7-074df07e0730 --- PROFuseX.xcodeproj/kelvin.pbxuser | 1711 ++++++++++++++++++++--- PROFuseX.xcodeproj/kelvin.perspectivev3 | 73 +- PROFuseX.xcodeproj/project.pbxproj | 12 +- 3 files changed, 1598 insertions(+), 198 deletions(-) diff --git a/PROFuseX.xcodeproj/kelvin.pbxuser b/PROFuseX.xcodeproj/kelvin.pbxuser index 81ced93..4461775 100644 --- a/PROFuseX.xcodeproj/kelvin.pbxuser +++ b/PROFuseX.xcodeproj/kelvin.pbxuser @@ -2,15 +2,20 @@ { 08FB7793FE84155DC02AAC07 /* Project object */ = { activeBuildConfigurationName = Debug; - activeExecutable = B63EFCCF11A36C7300C90DCE /* apfm */; - activeTarget = B63EFCCD11A36C7300C90DCE /* apfm */; + activeExecutable = B63EFE8211A4886C00C90DCE /* newfs_pascal */; + activeTarget = B63EFE8011A4886C00C90DCE /* newfs_pascal */; addToTargets = ( + B63EFCCD11A36C7300C90DCE /* apfm */, + B63EFE8011A4886C00C90DCE /* newfs_pascal */, + B656AE0211A84F5800AB578A /* fuse_pascal */, + B656AF0211AA105500AB578A /* NibbleTest */, ); breakpoints = ( - B63EFD8911A4455A00C90DCE /* apfm.cpp:487 */, - B63EFE0E11A451C600C90DCE /* VolumeEntry.cpp:105 */, - B63EFE3B11A4799800C90DCE /* apfm.cpp:183 */, - B6F3642F11AA1E150045E114 /* NibbleTest.cpp:74 */, + B6F3642F11AA1E150045E114 /* NibbleTest.cpp:76 */, + B6F3657711AE24C40045E114 /* apfm.cpp:470 */, + B6F3659B11AE27760045E114 /* VolumeEntry.cpp:300 */, + B6F3659E11AE27790045E114 /* VolumeEntry.cpp:311 */, + B6F3663D11B1809A0045E114 /* Adaptor.cpp:167 */, ); codeSenseManager = B63EFA6811A093C200C90DCE /* Code sense */; executables = ( @@ -45,6 +50,20 @@ PBXBreakpointsDataSource_ContinueID, ); }; + PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; + PBXFileTableDataSourceColumnWidthsKey = ( + 22, + 300, + 548, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXExecutablesDataSource_ActiveFlagID, + PBXExecutablesDataSource_NameID, + PBXExecutablesDataSource_CommentsID, + ); + }; PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_ObjectSize_ColumnID; @@ -172,6 +191,124 @@ B6F364EC11ACB5790045E114 /* XCBuildMessageTextBookmark */ = B6F364EC11ACB5790045E114 /* XCBuildMessageTextBookmark */; B6F364ED11ACB5790045E114 /* PBXTextBookmark */ = B6F364ED11ACB5790045E114 /* PBXTextBookmark */; B6F364F511ACB5B60045E114 /* PBXTextBookmark */ = B6F364F511ACB5B60045E114 /* PBXTextBookmark */; + B6F364F811ACBA8E0045E114 /* PBXTextBookmark */ = B6F364F811ACBA8E0045E114 /* PBXTextBookmark */; + B6F364FD11ACBC470045E114 /* PBXTextBookmark */ = B6F364FD11ACBC470045E114 /* PBXTextBookmark */; + B6F3650011ACBC790045E114 /* PBXTextBookmark */ = B6F3650011ACBC790045E114 /* PBXTextBookmark */; + B6F3650111ACBC790045E114 /* PBXTextBookmark */ = B6F3650111ACBC790045E114 /* PBXTextBookmark */; + B6F3650211ACBC790045E114 /* PBXTextBookmark */ = B6F3650211ACBC790045E114 /* PBXTextBookmark */; + B6F3650511ACBCA40045E114 /* PBXTextBookmark */ = B6F3650511ACBCA40045E114 /* PBXTextBookmark */; + B6F3650611ACBCA40045E114 /* PBXTextBookmark */ = B6F3650611ACBCA40045E114 /* PBXTextBookmark */; + B6F3650911ACBCB30045E114 /* PBXTextBookmark */ = B6F3650911ACBCB30045E114 /* PBXTextBookmark */; + B6F3650E11ADC40E0045E114 /* PBXTextBookmark */ = B6F3650E11ADC40E0045E114 /* PBXTextBookmark */; + B6F3651111ADCA570045E114 /* PBXTextBookmark */ = B6F3651111ADCA570045E114 /* PBXTextBookmark */; + B6F3651211ADCA570045E114 /* PBXTextBookmark */ = B6F3651211ADCA570045E114 /* PBXTextBookmark */; + B6F3651311ADCA570045E114 /* PBXTextBookmark */ = B6F3651311ADCA570045E114 /* PBXTextBookmark */; + B6F3651511ADCA6C0045E114 /* PBXTextBookmark */ = B6F3651511ADCA6C0045E114 /* PBXTextBookmark */; + B6F3651611ADCA6C0045E114 /* PBXTextBookmark */ = B6F3651611ADCA6C0045E114 /* PBXTextBookmark */; + B6F3651711ADCA6C0045E114 /* PBXTextBookmark */ = B6F3651711ADCA6C0045E114 /* PBXTextBookmark */; + B6F3651811ADCA6C0045E114 /* PBXTextBookmark */ = B6F3651811ADCA6C0045E114 /* PBXTextBookmark */; + B6F3652E11ADD5D20045E114 /* PBXTextBookmark */ = B6F3652E11ADD5D20045E114 /* PBXTextBookmark */; + B6F3652F11ADD5D20045E114 /* PBXTextBookmark */ = B6F3652F11ADD5D20045E114 /* PBXTextBookmark */; + B6F3653011ADD5D20045E114 /* PBXTextBookmark */ = B6F3653011ADD5D20045E114 /* PBXTextBookmark */; + B6F3653111ADD5D20045E114 /* PBXTextBookmark */ = B6F3653111ADD5D20045E114 /* PBXTextBookmark */; + B6F3653211ADD5D20045E114 /* PBXTextBookmark */ = B6F3653211ADD5D20045E114 /* PBXTextBookmark */; + B6F3653311ADD5D20045E114 /* PBXTextBookmark */ = B6F3653311ADD5D20045E114 /* PBXTextBookmark */; + B6F3653411ADD5D20045E114 /* PBXTextBookmark */ = B6F3653411ADD5D20045E114 /* PBXTextBookmark */; + B6F3654311ADE1C20045E114 /* PBXTextBookmark */ = B6F3654311ADE1C20045E114 /* PBXTextBookmark */; + B6F3654411ADE1C20045E114 /* PBXTextBookmark */ = B6F3654411ADE1C20045E114 /* PBXTextBookmark */; + B6F3654511ADE1C20045E114 /* PBXTextBookmark */ = B6F3654511ADE1C20045E114 /* PBXTextBookmark */; + B6F3654711ADE3680045E114 /* PBXTextBookmark */ = B6F3654711ADE3680045E114 /* PBXTextBookmark */; + B6F3654C11AE03E00045E114 /* PBXTextBookmark */ = B6F3654C11AE03E00045E114 /* PBXTextBookmark */; + B6F3654F11AE060D0045E114 /* PBXTextBookmark */ = B6F3654F11AE060D0045E114 /* PBXTextBookmark */; + B6F3655011AE060D0045E114 /* PBXTextBookmark */ = B6F3655011AE060D0045E114 /* PBXTextBookmark */; + B6F3655111AE060D0045E114 /* PBXTextBookmark */ = B6F3655111AE060D0045E114 /* PBXTextBookmark */; + B6F3655511AE06710045E114 /* PBXTextBookmark */ = B6F3655511AE06710045E114 /* PBXTextBookmark */; + B6F3655B11AE09D60045E114 /* PBXTextBookmark */ = B6F3655B11AE09D60045E114 /* PBXTextBookmark */; + B6F3655C11AE09D60045E114 /* PBXTextBookmark */ = B6F3655C11AE09D60045E114 /* PBXTextBookmark */; + B6F3655D11AE09D60045E114 /* PBXTextBookmark */ = B6F3655D11AE09D60045E114 /* PBXTextBookmark */; + B6F3656611AE142B0045E114 /* PBXTextBookmark */ = B6F3656611AE142B0045E114 /* PBXTextBookmark */; + B6F3656711AE142B0045E114 /* PBXTextBookmark */ = B6F3656711AE142B0045E114 /* PBXTextBookmark */; + B6F3656811AE142F0045E114 /* PBXTextBookmark */ = B6F3656811AE142F0045E114 /* PBXTextBookmark */; + B6F3657511AE24680045E114 /* PBXTextBookmark */ = B6F3657511AE24680045E114 /* PBXTextBookmark */; + B6F3657911AE24CC0045E114 /* PBXTextBookmark */ = B6F3657911AE24CC0045E114 /* PBXTextBookmark */; + B6F3657D11AE255B0045E114 /* PBXTextBookmark */ = B6F3657D11AE255B0045E114 /* PBXTextBookmark */; + B6F3657E11AE255B0045E114 /* PBXTextBookmark */ = B6F3657E11AE255B0045E114 /* PBXTextBookmark */; + B6F3657F11AE255B0045E114 /* PBXTextBookmark */ = B6F3657F11AE255B0045E114 /* PBXTextBookmark */; + B6F3658011AE255B0045E114 /* PBXTextBookmark */ = B6F3658011AE255B0045E114 /* PBXTextBookmark */; + B6F3658111AE256A0045E114 /* PBXTextBookmark */ = B6F3658111AE256A0045E114 /* PBXTextBookmark */; + B6F3658211AE256A0045E114 /* PBXTextBookmark */ = B6F3658211AE256A0045E114 /* PBXTextBookmark */; + B6F3658311AE25700045E114 /* PBXTextBookmark */ = B6F3658311AE25700045E114 /* PBXTextBookmark */; + B6F3658611AE25830045E114 /* PBXTextBookmark */ = B6F3658611AE25830045E114 /* PBXTextBookmark */; + B6F365A211AE27A80045E114 /* PBXTextBookmark */ = B6F365A211AE27A80045E114 /* PBXTextBookmark */; + B6F365A411AE27BE0045E114 /* PBXTextBookmark */ = B6F365A411AE27BE0045E114 /* PBXTextBookmark */; + B6F365A511AE27BE0045E114 /* PBXTextBookmark */ = B6F365A511AE27BE0045E114 /* PBXTextBookmark */; + B6F365A611AE27BE0045E114 /* PBXTextBookmark */ = B6F365A611AE27BE0045E114 /* PBXTextBookmark */; + B6F365A711AE27BE0045E114 /* PBXTextBookmark */ = B6F365A711AE27BE0045E114 /* PBXTextBookmark */; + B6F365A811AE27BE0045E114 /* PBXTextBookmark */ = B6F365A811AE27BE0045E114 /* PBXTextBookmark */; + B6F365A911AE27BE0045E114 /* PBXTextBookmark */ = B6F365A911AE27BE0045E114 /* PBXTextBookmark */; + B6F365AA11AE27BE0045E114 /* PBXTextBookmark */ = B6F365AA11AE27BE0045E114 /* PBXTextBookmark */; + B6F365AD11AE27CC0045E114 /* PBXTextBookmark */ = B6F365AD11AE27CC0045E114 /* PBXTextBookmark */; + B6F365AE11AE27CC0045E114 /* PBXTextBookmark */ = B6F365AE11AE27CC0045E114 /* PBXTextBookmark */; + B6F365AF11AE27CC0045E114 /* PBXTextBookmark */ = B6F365AF11AE27CC0045E114 /* PBXTextBookmark */; + B6F365B111AE28340045E114 /* PBXTextBookmark */ = B6F365B111AE28340045E114 /* PBXTextBookmark */; + B6F365B411AF40320045E114 /* PBXTextBookmark */ = B6F365B411AF40320045E114 /* PBXTextBookmark */; + B6F365B711AF62E00045E114 /* PBXTextBookmark */ = B6F365B711AF62E00045E114 /* PBXTextBookmark */; + B6F365B811AF62E00045E114 /* PBXTextBookmark */ = B6F365B811AF62E00045E114 /* PBXTextBookmark */; + B6F365CA11B08AE30045E114 /* PBXTextBookmark */ = B6F365CA11B08AE30045E114 /* PBXTextBookmark */; + B6F365CB11B08AE30045E114 /* XCBuildMessageTextBookmark */ = B6F365CB11B08AE30045E114 /* XCBuildMessageTextBookmark */; + B6F365CD11B08AE30045E114 /* PBXTextBookmark */ = B6F365CD11B08AE30045E114 /* PBXTextBookmark */; + B6F365CE11B08AE30045E114 /* PBXTextBookmark */ = B6F365CE11B08AE30045E114 /* PBXTextBookmark */; + B6F365CF11B08AE30045E114 /* PBXTextBookmark */ = B6F365CF11B08AE30045E114 /* PBXTextBookmark */; + B6F365E511B09E510045E114 /* PBXTextBookmark */ = B6F365E511B09E510045E114 /* PBXTextBookmark */; + B6F365E811B09EFD0045E114 /* PBXTextBookmark */ = B6F365E811B09EFD0045E114 /* PBXTextBookmark */; + B6F365EB11B09F2A0045E114 /* PBXTextBookmark */ = B6F365EB11B09F2A0045E114 /* PBXTextBookmark */; + B6F365EE11B0A6010045E114 /* PBXTextBookmark */ = B6F365EE11B0A6010045E114 /* PBXTextBookmark */; + B6F365F111B0A6BE0045E114 /* PBXTextBookmark */ = B6F365F111B0A6BE0045E114 /* PBXTextBookmark */; + B6F365F411B169C00045E114 /* PBXTextBookmark */ = B6F365F411B169C00045E114 /* PBXTextBookmark */; + B6F365F611B169D40045E114 /* PBXTextBookmark */ = B6F365F611B169D40045E114 /* PBXTextBookmark */; + B6F365F711B169D40045E114 /* PBXTextBookmark */ = B6F365F711B169D40045E114 /* PBXTextBookmark */; + B6F365F811B169D40045E114 /* PBXTextBookmark */ = B6F365F811B169D40045E114 /* PBXTextBookmark */; + B6F365FA11B16A690045E114 /* PBXTextBookmark */ = B6F365FA11B16A690045E114 /* PBXTextBookmark */; + B6F3660311B16D9F0045E114 /* PBXTextBookmark */ = B6F3660311B16D9F0045E114 /* PBXTextBookmark */; + B6F3660411B16D9F0045E114 /* XCBuildMessageTextBookmark */ = B6F3660411B16D9F0045E114 /* XCBuildMessageTextBookmark */; + B6F3660511B16D9F0045E114 /* PBXTextBookmark */ = B6F3660511B16D9F0045E114 /* PBXTextBookmark */; + B6F3660A11B174830045E114 /* PBXTextBookmark */ = B6F3660A11B174830045E114 /* PBXTextBookmark */; + B6F3660E11B175EA0045E114 /* PBXTextBookmark */ = B6F3660E11B175EA0045E114 /* PBXTextBookmark */; + B6F3661511B1762C0045E114 /* PBXTextBookmark */ = B6F3661511B1762C0045E114 /* PBXTextBookmark */; + B6F3661A11B176960045E114 /* PBXTextBookmark */ = B6F3661A11B176960045E114 /* PBXTextBookmark */; + B6F3662011B177B60045E114 /* PBXTextBookmark */ = B6F3662011B177B60045E114 /* PBXTextBookmark */; + B6F3662111B177B60045E114 /* PBXTextBookmark */ = B6F3662111B177B60045E114 /* PBXTextBookmark */; + B6F3662211B177B60045E114 /* PBXTextBookmark */ = B6F3662211B177B60045E114 /* PBXTextBookmark */; + B6F3662311B177B60045E114 /* PBXTextBookmark */ = B6F3662311B177B60045E114 /* PBXTextBookmark */; + B6F3662D11B178720045E114 /* PBXTextBookmark */ = B6F3662D11B178720045E114 /* PBXTextBookmark */; + B6F3662E11B178720045E114 /* PBXTextBookmark */ = B6F3662E11B178720045E114 /* PBXTextBookmark */; + B6F3662F11B178720045E114 /* PBXTextBookmark */ = B6F3662F11B178720045E114 /* PBXTextBookmark */; + B6F3663411B178EB0045E114 /* PBXTextBookmark */ = B6F3663411B178EB0045E114 /* PBXTextBookmark */; + B6F3663811B179290045E114 /* PBXTextBookmark */ = B6F3663811B179290045E114 /* PBXTextBookmark */; + B6F3664111B181C10045E114 /* PBXTextBookmark */ = B6F3664111B181C10045E114 /* PBXTextBookmark */; + B6F3665011B189490045E114 /* PBXTextBookmark */ = B6F3665011B189490045E114 /* PBXTextBookmark */; + B6F3665111B190300045E114 /* PBXTextBookmark */ = B6F3665111B190300045E114 /* PBXTextBookmark */; + B6F3665211B190300045E114 /* PBXTextBookmark */ = B6F3665211B190300045E114 /* PBXTextBookmark */; + B6F3665311B190300045E114 /* PBXTextBookmark */ = B6F3665311B190300045E114 /* PBXTextBookmark */; + B6F3665411B190370045E114 /* PBXTextBookmark */ = B6F3665411B190370045E114 /* PBXTextBookmark */; + B6F3665511B190370045E114 /* PBXTextBookmark */ = B6F3665511B190370045E114 /* PBXTextBookmark */; + B6F3665911B191C90045E114 /* PBXTextBookmark */ = B6F3665911B191C90045E114 /* PBXTextBookmark */; + B6F3665C11B194AC0045E114 /* PBXTextBookmark */ = B6F3665C11B194AC0045E114 /* PBXTextBookmark */; + B6F3665D11B194AC0045E114 /* PBXTextBookmark */ = B6F3665D11B194AC0045E114 /* PBXTextBookmark */; + B6F3665E11B194AC0045E114 /* PBXTextBookmark */ = B6F3665E11B194AC0045E114 /* PBXTextBookmark */; + B6F366C211B1A28C0045E114 /* PBXTextBookmark */ = B6F366C211B1A28C0045E114 /* PBXTextBookmark */; + B6F366C311B1A28C0045E114 /* PBXTextBookmark */ = B6F366C311B1A28C0045E114 /* PBXTextBookmark */; + B6F366C411B1A28C0045E114 /* PBXTextBookmark */ = B6F366C411B1A28C0045E114 /* PBXTextBookmark */; + B6F366C511B1A28C0045E114 /* PBXTextBookmark */ = B6F366C511B1A28C0045E114 /* PBXTextBookmark */; + B6F366C611B1A28C0045E114 /* PBXTextBookmark */ = B6F366C611B1A28C0045E114 /* PBXTextBookmark */; + B6F366C711B1A28C0045E114 /* PBXTextBookmark */ = B6F366C711B1A28C0045E114 /* PBXTextBookmark */; + B6F366C811B1A28C0045E114 /* PBXTextBookmark */ = B6F366C811B1A28C0045E114 /* PBXTextBookmark */; + B6F366C911B1A28C0045E114 /* PBXTextBookmark */ = B6F366C911B1A28C0045E114 /* PBXTextBookmark */; + B6F366CA11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CA11B1A28C0045E114 /* PBXTextBookmark */; + B6F366CB11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CB11B1A28C0045E114 /* PBXTextBookmark */; + B6F366CC11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CC11B1A28C0045E114 /* PBXTextBookmark */; + B6F366CD11B1A28C0045E114 /* XCBuildMessageTextBookmark */ = B6F366CD11B1A28C0045E114 /* XCBuildMessageTextBookmark */; + B6F366CE11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CE11B1A28C0045E114 /* PBXTextBookmark */; }; sourceControlManager = B63EFA6711A093C200C90DCE /* Source Control */; userBuildSettings = { @@ -214,51 +351,51 @@ }; B63EFA9511A094E000C90DCE /* BlockDevice.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 3055}}"; - sepNavSelRange = "{843, 0}"; - sepNavVisRange = "{0, 1634}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 3198}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 815}"; }; }; B63EFA9611A094E000C90DCE /* BlockDevice.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1264, 932}}"; - sepNavSelRange = "{470, 0}"; - sepNavVisRange = "{0, 1202}"; + sepNavIntBoundsRect = "{{0, 0}, {1015, 944}}"; + sepNavSelRange = "{431, 0}"; + sepNavVisRange = "{0, 1234}"; }; }; B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1264, 2262}}"; - sepNavSelRange = "{974, 0}"; - sepNavVisRange = "{114, 1526}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 2119}}"; + sepNavSelRange = "{2355, 0}"; + sepNavVisRange = "{1920, 875}"; }; }; B63EFA9811A094E000C90DCE /* DavexDiskImage.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 948}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 763}"; + sepNavIntBoundsRect = "{{0, 0}, {1015, 944}}"; + sepNavSelRange = "{597, 0}"; + sepNavVisRange = "{0, 740}"; }; }; B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1264, 2951}}"; - sepNavSelRange = "{4587, 0}"; - sepNavVisRange = "{3132, 1628}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 2938}}"; + sepNavSelRange = "{2053, 0}"; + sepNavVisRange = "{1629, 925}"; }; }; B63EFA9C11A094E000C90DCE /* DiskCopy42Image.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 570}}"; - sepNavSelRange = "{459, 0}"; - sepNavVisRange = "{0, 803}"; + sepNavIntBoundsRect = "{{0, 0}, {1015, 944}}"; + sepNavSelRange = "{661, 0}"; + sepNavVisRange = "{0, 772}"; }; }; B63EFA9D11A094E000C90DCE /* DiskImage.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 2444}}"; - sepNavSelRange = "{2704, 0}"; - sepNavVisRange = "{2264, 894}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 2769}}"; + sepNavSelRange = "{423, 0}"; + sepNavVisRange = "{128, 613}"; }; }; B63EFA9E11A094E000C90DCE /* DiskImage.h */ = { @@ -270,16 +407,16 @@ }; B63EFAA111A094E000C90DCE /* RawDevice.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1264, 3445}}"; - sepNavSelRange = "{5280, 138}"; - sepNavVisRange = "{4005, 1546}"; + sepNavIntBoundsRect = "{{0, 0}, {1015, 4043}}"; + sepNavSelRange = "{2481, 0}"; + sepNavVisRange = "{2076, 1431}"; }; }; B63EFAA211A094E000C90DCE /* RawDevice.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 715}}"; - sepNavSelRange = "{186, 0}"; - sepNavVisRange = "{126, 781}"; + sepNavIntBoundsRect = "{{0, 0}, {1015, 944}}"; + sepNavSelRange = "{735, 0}"; + sepNavVisRange = "{0, 952}"; }; }; B63EFAA311A094E000C90DCE /* TrackSector.h */ = { @@ -291,16 +428,16 @@ }; B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1264, 2158}}"; - sepNavSelRange = "{3362, 0}"; - sepNavVisRange = "{1890, 1479}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 2067}}"; + sepNavSelRange = "{956, 0}"; + sepNavVisRange = "{497, 808}"; }; }; B63EFAA511A094E000C90DCE /* UniversalDiskImage.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 570}}"; - sepNavSelRange = "{403, 0}"; - sepNavVisRange = "{0, 723}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 546}}"; + sepNavSelRange = "{507, 4}"; + sepNavVisRange = "{0, 692}"; }; }; B63EFAB611A098C400C90DCE /* BlockCache.cpp */ = { @@ -347,23 +484,23 @@ }; B63EFAC911A09DAA00C90DCE /* File.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 1534}}"; - sepNavSelRange = "{384, 0}"; - sepNavVisRange = "{0, 571}"; + sepNavIntBoundsRect = "{{0, 0}, {701, 1534}}"; + sepNavSelRange = "{1503, 0}"; + sepNavVisRange = "{347, 1384}"; }; }; B63EFACA11A09DAA00C90DCE /* File.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {701, 948}}"; - sepNavSelRange = "{423, 0}"; - sepNavVisRange = "{0, 888}"; + sepNavSelRange = "{244, 0}"; + sepNavVisRange = "{0, 979}"; }; }; B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 2301}}"; - sepNavSelRange = "{723, 0}"; - sepNavVisRange = "{293, 1426}"; + sepNavIntBoundsRect = "{{0, 0}, {701, 2574}}"; + sepNavSelRange = "{1115, 0}"; + sepNavVisRange = "{0, 1267}"; }; }; B63EFACC11A09DAA00C90DCE /* MappedFile.h */ = { @@ -389,9 +526,9 @@ }; B63EFAD211A09DB500C90DCE /* Exception.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 1885}}"; - sepNavSelRange = "{783, 10}"; - sepNavVisRange = "{434, 1003}"; + sepNavIntBoundsRect = "{{0, 0}, {701, 1911}}"; + sepNavSelRange = "{633, 13}"; + sepNavVisRange = "{0, 1568}"; }; }; B63EFAD311A09DB500C90DCE /* Lock.cpp */ = { @@ -410,9 +547,9 @@ }; B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {929, 5577}}"; - sepNavSelRange = "{9724, 0}"; - sepNavVisRange = "{8739, 1774}"; + sepNavIntBoundsRect = "{{0, 0}, {701, 6448}}"; + sepNavSelRange = "{8303, 0}"; + sepNavVisRange = "{2730, 1774}"; }; }; B63EFB8811A1FB2500C90DCE /* DiskImage.h */ = { @@ -421,6 +558,11 @@ name = DiskImage.h; path = ./Device/DiskImage.h; sourceTree = ""; + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1009, 1144}}"; + sepNavSelRange = "{596, 0}"; + sepNavVisRange = "{124, 1430}"; + }; }; B63EFBE811A244EE00C90DCE /* Date.cpp */ = { uiCtxt = { @@ -431,19 +573,25 @@ }; B63EFBE911A244EE00C90DCE /* Date.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 637}}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 585}}"; sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 706}"; + sepNavVisRange = "{0, 654}"; }; }; B63EFBEA11A244EE00C90DCE /* Entry.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 1274}}"; - sepNavSelRange = "{1176, 0}"; - sepNavVisRange = "{382, 1153}"; + sepNavIntBoundsRect = "{{0, 0}, {701, 1248}}"; + sepNavSelRange = "{22, 0}"; + sepNavVisRange = "{0, 1220}"; }; }; B63EFBEB11A244EE00C90DCE /* File.h */ = { + isa = PBXFileReference; + fileEncoding = 4; + lastKnownFileType = sourcecode.c.h; + name = File.h; + path = /Users/kelvin/Projects/PROFuseX/Pascal/File.h; + sourceTree = ""; uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 3029}}"; sepNavSelRange = "{2795, 35}"; @@ -452,9 +600,9 @@ }; B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 7683}}"; - sepNavSelRange = "{1582, 0}"; - sepNavVisRange = "{1039, 851}"; + sepNavIntBoundsRect = "{{0, 0}, {701, 7813}}"; + sepNavSelRange = "{1130, 0}"; + sepNavVisRange = "{1, 1360}"; }; }; B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */ = { @@ -503,30 +651,30 @@ }; B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 4121}}"; - sepNavSelRange = "{4176, 0}"; - sepNavVisRange = "{3759, 970}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 4082}}"; + sepNavSelRange = "{4414, 0}"; + sepNavVisRange = "{3977, 1077}"; }; }; B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 3601}}"; - sepNavSelRange = "{5059, 0}"; - sepNavVisRange = "{4987, 1307}"; + sepNavIntBoundsRect = "{{0, 0}, {768, 4004}}"; + sepNavSelRange = "{6507, 0}"; + sepNavVisRange = "{4525, 2059}"; }; }; B63EFC9D11A35F8200C90DCE /* fuse_pascal_ops.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 6071}}"; + sepNavIntBoundsRect = "{{0, 0}, {701, 6448}}"; sepNavSelRange = "{855, 6}"; - sepNavVisRange = "{25, 1403}"; + sepNavVisRange = "{18, 1415}"; }; }; B63EFC9F11A35F8F00C90DCE /* apfm.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 7228}}"; - sepNavSelRange = "{916, 0}"; - sepNavVisRange = "{800, 1552}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 10855}}"; + sepNavSelRange = "{16564, 0}"; + sepNavVisRange = "{15404, 884}"; }; }; B63EFCB211A3639400C90DCE /* PBXTextBookmark */ = { @@ -534,7 +682,7 @@ fRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; name = "DavexDiskImage.cpp: 160"; rLen = 0; - rLoc = 3409; + rLoc = 3285; rType = 0; vrLen = 270; vrLoc = 3136; @@ -555,6 +703,11 @@ name = MappedFile.h; path = ./File/MappedFile.h; sourceTree = ""; + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 663}}"; + sepNavSelRange = "{263, 0}"; + sepNavVisRange = "{0, 874}"; + }; }; B63EFCCD11A36C7300C90DCE /* apfm */ = { activeExec = 0; @@ -565,8 +718,14 @@ B63EFCCF11A36C7300C90DCE /* apfm */ = { isa = PBXExecutable; activeArgIndices = ( + YES, + YES, + YES, ); argumentStrings = ( + /Users/kelvin/Projects/PROFuseX/pascaltest.DSK, + rm, + LINEFEED.CODE, ); autoAttachOnCrash = 1; breakpointsEnabled = 1; @@ -606,23 +765,6 @@ vrLen = 225; vrLoc = 284; }; - B63EFD8911A4455A00C90DCE /* apfm.cpp:487 */ = { - isa = PBXFileBreakpoint; - actions = ( - ); - breakpointStyle = 0; - continueAfterActions = 0; - countType = 0; - delayBeforeContinue = 0; - fileReference = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - functionName = "main(/* int argc, char **argv */)"; - hitCount = 0; - ignoreCount = 0; - lineNumber = 487; - modificationTime = 296363159.802434; - originalNumberOfMultipleMatches = 1; - state = 0; - }; B63EFDA011A4488200C90DCE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFDA111A4488200C90DCE /* memory */; @@ -801,7 +943,7 @@ fRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; name = "MappedFile.cpp: 42"; rLen = 0; - rLoc = 723; + rLoc = 747; rType = 0; vrLen = 791; vrLoc = 576; @@ -816,41 +958,6 @@ vrLen = 479; vrLoc = 0; }; - B63EFE0E11A451C600C90DCE /* VolumeEntry.cpp:105 */ = { - isa = PBXFileBreakpoint; - actions = ( - ); - breakpointStyle = 0; - continueAfterActions = 0; - countType = 0; - delayBeforeContinue = 0; - fileReference = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; - functionName = "VolumeEntry::VolumeEntry(Device::BlockDevice *device)"; - hitCount = 0; - ignoreCount = 0; - lineNumber = 105; - location = NibbleTest; - modificationTime = 296363160.018; - originalNumberOfMultipleMatches = 1; - state = 1; - }; - B63EFE3B11A4799800C90DCE /* apfm.cpp:183 */ = { - isa = PBXFileBreakpoint; - actions = ( - ); - breakpointStyle = 0; - continueAfterActions = 0; - countType = 0; - delayBeforeContinue = 0; - fileReference = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - functionName = "action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume)"; - hitCount = 0; - ignoreCount = 0; - lineNumber = 183; - modificationTime = 296363159.805745; - originalNumberOfMultipleMatches = 1; - state = 0; - }; B63EFE8011A4886C00C90DCE /* newfs_pascal */ = { activeExec = 0; executables = ( @@ -864,7 +971,7 @@ argumentStrings = ( ); autoAttachOnCrash = 1; - breakpointsEnabled = 0; + breakpointsEnabled = 1; configStateDict = { }; customDataFormattersEnabled = 1; @@ -909,7 +1016,7 @@ fRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; name = "UniversalDiskImage.cpp: 162"; rLen = 0; - rLoc = 3362; + rLoc = 3117; rType = 0; vrLen = 1007; vrLoc = 2311; @@ -931,9 +1038,9 @@ path = ./Pascal/VolumeEntry.cpp; sourceTree = ""; uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 7085}}"; - sepNavSelRange = "{3256, 0}"; - sepNavVisRange = "{2568, 1113}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 9542}}"; + sepNavSelRange = "{8503, 0}"; + sepNavVisRange = "{8131, 736}"; }; }; B63EFEA711A488C200C90DCE /* PBXTextBookmark */ = { @@ -971,7 +1078,7 @@ fRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; name = "RawDevice.cpp: 147"; rLen = 0; - rLoc = 2650; + rLoc = 2655; rType = 0; vrLen = 865; vrLoc = 2190; @@ -1044,7 +1151,7 @@ fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; name = "newfs_pascal.cpp: 221"; rLen = 0; - rLoc = 5059; + rLoc = 5494; rType = 0; vrLen = 1307; vrLoc = 4987; @@ -1054,7 +1161,7 @@ fRef = B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */; name = "fuse_pascal.cpp: 187"; rLen = 0; - rLoc = 4176; + rLoc = 4201; rType = 0; vrLen = 1001; vrLoc = 3697; @@ -1064,7 +1171,7 @@ fRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; name = "DiskImage.cpp: 148"; rLen = 0; - rLoc = 2704; + rLoc = 2568; rType = 0; vrLen = 894; vrLoc = 2264; @@ -1074,16 +1181,16 @@ fRef = B63EFB8811A1FB2500C90DCE /* DiskImage.h */; name = "DiskImage.h: 65"; rLen = 0; - rLoc = 1236; + rLoc = 1204; rType = 0; vrLen = 898; vrLoc = 788; }; B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 1079}}"; - sepNavSelRange = "{1570, 0}"; - sepNavVisRange = "{173, 1684}"; + sepNavIntBoundsRect = "{{0, 0}, {1178, 1248}}"; + sepNavSelRange = "{1680, 0}"; + sepNavVisRange = "{1472, 529}"; }; }; B656AF0211AA105500AB578A /* NibbleTest */ = { @@ -1124,7 +1231,9 @@ variableFormatDictionary = { "87-unsigned int-Device::NibbleAdaptor::NibbleAdaptor" = 1; "checksum-uint8_t-Device::NibbleAdaptor::readTrackSector" = 1; + "index-unsigned int-Device::NibbleAdaptor::readTrackSector" = 1; "offset-int-Device::NibbleAdaptor::NibbleAdaptor" = 1; + "offset-unsigned int-Device::NibbleAdaptor::readTrackSector" = 1; "val-uint8_t-Device::NibbleAdaptor::decode62" = 1; "x-uint8_t-Device::NibbleAdaptor::readTrackSector" = 1; "y-uint8_t-Device::NibbleAdaptor::readTrackSector" = 1; @@ -1135,7 +1244,7 @@ fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; name = "FileEntry.cpp: 372"; rLen = 0; - rLoc = 11357; + rLoc = 11565; rType = 0; vrLen = 938; vrLoc = 6413; @@ -1145,7 +1254,7 @@ fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; name = "apfm.cpp: 107"; rLen = 0; - rLoc = 1824; + rLoc = 6577; rType = 0; vrLen = 875; vrLoc = 2880; @@ -1240,7 +1349,7 @@ vrLen = 907; vrLoc = 0; }; - B6F3642F11AA1E150045E114 /* NibbleTest.cpp:74 */ = { + B6F3642F11AA1E150045E114 /* NibbleTest.cpp:76 */ = { isa = PBXFileBreakpoint; actions = ( ); @@ -1252,9 +1361,9 @@ functionName = "main(int argc, char **argv)"; hitCount = 1; ignoreCount = 0; - lineNumber = 74; + lineNumber = 76; location = NibbleTest; - modificationTime = 296363160.221059; + modificationTime = 296847682.098918; originalNumberOfMultipleMatches = 1; state = 1; }; @@ -1287,7 +1396,7 @@ fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; name = "NibbleTest.cpp: 70"; rLen = 0; - rLoc = 1570; + rLoc = 1607; rType = 0; vrLen = 470; vrLoc = 1269; @@ -1307,7 +1416,7 @@ fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; name = "NibbleTest.cpp: 70"; rLen = 0; - rLoc = 1570; + rLoc = 1607; rType = 0; vrLen = 940; vrLoc = 917; @@ -1357,7 +1466,7 @@ fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; name = "NibbleTest.cpp: 70"; rLen = 0; - rLoc = 1570; + rLoc = 1607; rType = 0; vrLen = 940; vrLoc = 917; @@ -1377,7 +1486,7 @@ fRef = B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */; name = "fuse_pascal.cpp: 187"; rLen = 0; - rLoc = 4176; + rLoc = 4201; rType = 0; vrLen = 970; vrLoc = 3759; @@ -1417,7 +1526,7 @@ fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; fallbackIsa = XCBuildMessageTextBookmark; rLen = 1; - rLoc = 279; + rLoc = 567; rType = 1; }; B6F364A011AB59190045E114 /* PBXTextBookmark */ = { @@ -1425,7 +1534,7 @@ fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; name = "apfm.cpp: 281"; rLen = 66; - rLoc = 5764; + rLoc = 12497; rType = 0; vrLen = 849; vrLoc = 5157; @@ -1435,7 +1544,7 @@ fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; name = "apfm.cpp: 281"; rLen = 66; - rLoc = 5764; + rLoc = 12497; rType = 0; vrLen = 855; vrLoc = 5157; @@ -1445,7 +1554,7 @@ fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; name = "apfm.cpp: 281"; rLen = 66; - rLoc = 5764; + rLoc = 12497; rType = 0; vrLen = 855; vrLoc = 5157; @@ -1456,7 +1565,7 @@ fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; fallbackIsa = XCBuildMessageTextBookmark; rLen = 1; - rLoc = 382; + rLoc = 670; rType = 1; }; B6F364B211AB74F40045E114 /* PBXTextBookmark */ = { @@ -1464,7 +1573,7 @@ fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; name = "apfm.cpp: 385"; rLen = 0; - rLoc = 8425; + rLoc = 15158; rType = 0; vrLen = 715; vrLoc = 8003; @@ -1474,7 +1583,7 @@ fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; name = "apfm.cpp: 385"; rLen = 0; - rLoc = 8425; + rLoc = 15158; rType = 0; vrLen = 715; vrLoc = 8003; @@ -1525,7 +1634,7 @@ fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; fallbackIsa = XCBuildMessageTextBookmark; rLen = 1; - rLoc = 378; + rLoc = 666; rType = 1; }; B6F364C011AC92730045E114 /* PBXTextBookmark */ = { @@ -1533,7 +1642,7 @@ fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; name = "apfm.cpp: 381"; rLen = 0; - rLoc = 8337; + rLoc = 15070; rType = 0; vrLen = 667; vrLoc = 7907; @@ -1543,7 +1652,7 @@ fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; name = "apfm.cpp: 381"; rLen = 0; - rLoc = 8337; + rLoc = 15070; rType = 0; vrLen = 667; vrLoc = 7907; @@ -1573,7 +1682,7 @@ fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; name = "FileEntry.cpp: 86"; rLen = 0; - rLoc = 1582; + rLoc = 1778; rType = 0; vrLen = 851; vrLoc = 1039; @@ -1583,22 +1692,28 @@ comments = "'void Pascal::VolumeEntry::writeEntry(Pascal::FileEntry*)' is private"; fRef = B6F364EA11ACB5790045E114 /* File.h */; fallbackIsa = XCBuildMessageTextBookmark; - rLen = 1; - rLoc = 137; + rLen = 0; + rLoc = 6; rType = 1; }; B6F364EA11ACB5790045E114 /* File.h */ = { isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; name = File.h; path = ./Pascal/File.h; sourceTree = ""; + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 948}}"; + sepNavSelRange = "{165, 0}"; + sepNavVisRange = "{0, 173}"; + }; }; B6F364EB11ACB5790045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFBEB11A244EE00C90DCE /* File.h */; name = "File.h: 141"; - rLen = 35; - rLoc = 2795; + rLen = 0; + rLoc = 165; rType = 0; vrLen = 855; vrLoc = 2292; @@ -1632,4 +1747,1274 @@ vrLen = 1113; vrLoc = 2568; }; + B6F364F811ACBA8E0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 155"; + rLen = 0; + rLoc = 3256; + rType = 0; + vrLen = 1113; + vrLoc = 2568; + }; + B6F364FD11ACBC470045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 155"; + rLen = 0; + rLoc = 3256; + rType = 0; + vrLen = 1113; + vrLoc = 2568; + }; + B6F3650011ACBC790045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 155"; + rLen = 0; + rLoc = 3256; + rType = 0; + vrLen = 1108; + vrLoc = 2568; + }; + B6F3650111ACBC790045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + rLen = 0; + rLoc = 744; + rType = 1; + }; + B6F3650211ACBC790045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 488"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 869; + vrLoc = 8980; + }; + B6F3650511ACBCA40045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + name = "NibbleTest.cpp: 70"; + rLen = 0; + rLoc = 1607; + rType = 0; + vrLen = 470; + vrLoc = 1269; + }; + B6F3650611ACBCA40045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 488"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 334; + vrLoc = 10364; + }; + B6F3650911ACBCB30045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 488"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 659; + vrLoc = 10264; + }; + B6F3650E11ADC40E0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 488"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 752; + vrLoc = 10264; + }; + B6F3651111ADCA570045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 488"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 334; + vrLoc = 10364; + }; + B6F3651211ADCA570045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + rLen = 0; + rLoc = 107; + rType = 1; + }; + B6F3651311ADCA570045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 108"; + rLen = 0; + rLoc = 2072; + rType = 0; + vrLen = 792; + vrLoc = 2635; + }; + B6F3651511ADCA6C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 488"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 752; + vrLoc = 10264; + }; + B6F3651611ADCA6C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 108"; + rLen = 0; + rLoc = 2072; + rType = 0; + vrLen = 1135; + vrLoc = 2455; + }; + B6F3651711ADCA6C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; + name = "Entry.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 711; + vrLoc = 0; + }; + B6F3651811ADCA6C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; + name = "Entry.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 711; + vrLoc = 0; + }; + B6F3651A11ADD0280045E114 /* VolumeEntry.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 1365}}"; + sepNavSelRange = "{145, 0}"; + sepNavVisRange = "{0, 974}"; + }; + }; + B6F3651B11ADD0280045E114 /* FileEntry.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 1248}}"; + sepNavSelRange = "{990, 0}"; + sepNavVisRange = "{0, 1602}"; + }; + }; + B6F3651C11ADD0280045E114 /* Entry.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 1079}}"; + sepNavSelRange = "{1399, 0}"; + sepNavVisRange = "{146, 1332}"; + }; + }; + B6F3652711ADD52B0045E114 /* Pascal.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 530}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 173}"; + }; + }; + B6F3652E11ADD5D20045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F3652711ADD52B0045E114 /* Pascal.h */; + name = "Pascal.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 173; + vrLoc = 0; + }; + B6F3652F11ADD5D20045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBE911A244EE00C90DCE /* Date.h */; + name = "Date.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 672; + vrLoc = 0; + }; + B6F3653011ADD5D20045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; + name = "Entry.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 712; + vrLoc = 0; + }; + B6F3653111ADD5D20045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F3651C11ADD0280045E114 /* Entry.h */; + name = "Entry.h: 72"; + rLen = 0; + rLoc = 1399; + rType = 0; + vrLen = 873; + vrLoc = 605; + }; + B6F3653211ADD5D20045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; + name = "FileEntry.cpp: 283"; + rLen = 0; + rLoc = 6452; + rType = 0; + vrLen = 1018; + vrLoc = 5738; + }; + B6F3653311ADD5D20045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 488"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 752; + vrLoc = 10266; + }; + B6F3653411ADD5D20045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 488"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 935; + vrLoc = 10277; + }; + B6F3654311ADE1C20045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 488"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 935; + vrLoc = 10277; + }; + B6F3654411ADE1C20045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 108"; + rLen = 0; + rLoc = 2074; + rType = 0; + vrLen = 1135; + vrLoc = 2457; + }; + B6F3654511ADE1C20045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 108"; + rLen = 0; + rLoc = 2074; + rType = 0; + vrLen = 1135; + vrLoc = 2457; + }; + B6F3654711ADE3680045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 108"; + rLen = 0; + rLoc = 2074; + rType = 0; + vrLen = 1135; + vrLoc = 2457; + }; + B6F3654C11AE03E00045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 159"; + rLen = 0; + rLoc = 3423; + rType = 0; + vrLen = 941; + vrLoc = 1990; + }; + B6F3654F11AE060D0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 159"; + rLen = 0; + rLoc = 3423; + rType = 0; + vrLen = 858; + vrLoc = 1990; + }; + B6F3655011AE060D0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + rLen = 0; + rLoc = 744; + rType = 1; + }; + B6F3655111AE060D0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 488"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 741; + vrLoc = 10277; + }; + B6F3655511AE06710045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 488"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 648; + vrLoc = 10277; + }; + B6F3655B11AE09D60045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 488"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 286; + vrLoc = 10318; + }; + B6F3655C11AE09D60045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + rLen = 0; + rLoc = 153; + rType = 1; + }; + B6F3655D11AE09D60045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 154"; + rLen = 0; + rLoc = 3160; + rType = 0; + vrLen = 788; + vrLoc = 2637; + }; + B6F3656611AE142B0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 488"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 935; + vrLoc = 10277; + }; + B6F3656711AE142B0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 188"; + rLen = 0; + rLoc = 4064; + rType = 0; + vrLen = 1097; + vrLoc = 2544; + }; + B6F3656811AE142F0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 188"; + rLen = 0; + rLoc = 4064; + rType = 0; + vrLen = 1097; + vrLoc = 2544; + }; + B6F3657511AE24680045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 197"; + rLen = 0; + rLoc = 4315; + rType = 0; + vrLen = 503; + vrLoc = 2616; + }; + B6F3657711AE24C40045E114 /* apfm.cpp:470 */ = { + isa = PBXFileBreakpoint; + actions = ( + ); + breakpointStyle = 0; + continueAfterActions = 0; + countType = 0; + delayBeforeContinue = 0; + fileReference = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + functionName = "action_rm(int argc, char **argv, Pascal::VolumeEntry *volume)"; + hitCount = 0; + ignoreCount = 0; + lineNumber = 470; + modificationTime = 296847686.349254; + originalNumberOfMultipleMatches = 1; + state = 1; + }; + B6F3657911AE24CC0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 197"; + rLen = 0; + rLoc = 4315; + rType = 0; + vrLen = 952; + vrLoc = 2475; + }; + B6F3657D11AE255B0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 197"; + rLen = 0; + rLoc = 4315; + rType = 0; + vrLen = 952; + vrLoc = 2475; + }; + B6F3657E11AE255B0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBE911A244EE00C90DCE /* Date.h */; + name = "Date.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 654; + vrLoc = 0; + }; + B6F3657F11AE255B0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + rLen = 0; + rLoc = 744; + rType = 1; + }; + B6F3658011AE255B0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 495"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 569; + vrLoc = 10265; + }; + B6F3658111AE256A0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 197"; + rLen = 0; + rLoc = 4315; + rType = 0; + vrLen = 503; + vrLoc = 2616; + }; + B6F3658211AE256A0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 495"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 450; + vrLoc = 10578; + }; + B6F3658311AE25700045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 495"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 1242; + vrLoc = 10459; + }; + B6F3658611AE25830045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 495"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 1233; + vrLoc = 10459; + }; + B6F3659B11AE27760045E114 /* VolumeEntry.cpp:300 */ = { + isa = PBXFileBreakpoint; + actions = ( + ); + breakpointStyle = 0; + continueAfterActions = 0; + countType = 0; + delayBeforeContinue = 0; + fileReference = B6F3659C11AE27760045E114 /* VolumeEntry.cpp */; + functionName = "VolumeEntry::unlink(const char *name)"; + hitCount = 0; + ignoreCount = 0; + lineNumber = 300; + location = NibbleTest; + modificationTime = 296847681.826089; + originalNumberOfMultipleMatches = 1; + state = 1; + }; + B6F3659C11AE27760045E114 /* VolumeEntry.cpp */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + name = VolumeEntry.cpp; + path = /Users/kelvin/Projects/PROFuseX/./Pascal/VolumeEntry.cpp; + sourceTree = ""; + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1178, 7501}}"; + sepNavSelRange = "{6306, 0}"; + sepNavVisRange = "{6660, 576}"; + }; + }; + B6F3659E11AE27790045E114 /* VolumeEntry.cpp:311 */ = { + isa = PBXFileBreakpoint; + actions = ( + ); + breakpointStyle = 0; + continueAfterActions = 0; + countType = 0; + delayBeforeContinue = 0; + fileReference = B6F3659C11AE27760045E114 /* VolumeEntry.cpp */; + functionName = "VolumeEntry::unlink(const char *name)"; + hitCount = 0; + ignoreCount = 0; + lineNumber = 311; + location = NibbleTest; + modificationTime = 296847681.868784; + originalNumberOfMultipleMatches = 1; + state = 1; + }; + B6F365A211AE27A80045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 495"; + rLen = 0; + rLoc = 16395; + rType = 0; + vrLen = 1317; + vrLoc = 10657; + }; + B6F365A411AE27BE0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 286"; + rLen = 0; + rLoc = 6306; + rType = 0; + vrLen = 600; + vrLoc = 7515; + }; + B6F365A511AE27BE0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; + name = "MappedFile.cpp: 42"; + rLen = 0; + rLoc = 725; + rType = 0; + vrLen = 315; + vrLoc = 639; + }; + B6F365A611AE27BE0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; + name = "BlockDevice.cpp: 111"; + rLen = 0; + rLoc = 2416; + rType = 0; + vrLen = 511; + vrLoc = 2414; + }; + B6F365A711AE27BE0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; + name = "DiskImage.cpp: 41"; + rLen = 0; + rLoc = 593; + rType = 0; + vrLen = 367; + vrLoc = 372; + }; + B6F365A811AE27BE0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 246"; + rLen = 0; + rLoc = 10518; + rType = 0; + vrLen = 475; + vrLoc = 4825; + }; + B6F365A911AE27BE0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F3659C11AE27760045E114 /* VolumeEntry.cpp */; + rLen = 0; + rLoc = 285; + rType = 1; + }; + B6F365AA11AE27BE0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F3659C11AE27760045E114 /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 286"; + rLen = 0; + rLoc = 6306; + rType = 0; + vrLen = 576; + vrLoc = 6660; + }; + B6F365AD11AE27CC0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 286"; + rLen = 0; + rLoc = 6306; + rType = 0; + vrLen = 1053; + vrLoc = 6356; + }; + B6F365AE11AE27CC0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + rLen = 0; + rLoc = 469; + rType = 1; + }; + B6F365AF11AE27CC0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 246"; + rLen = 0; + rLoc = 10518; + rType = 0; + vrLen = 794; + vrLoc = 4641; + }; + B6F365B111AE28340045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 246"; + rLen = 0; + rLoc = 10518; + rType = 0; + vrLen = 794; + vrLoc = 4641; + }; + B6F365B411AF40320045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 286"; + rLen = 0; + rLoc = 6306; + rType = 0; + vrLen = 1082; + vrLoc = 6356; + }; + B6F365B711AF62E00045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + rLen = 0; + rLoc = 285; + rType = 1; + }; + B6F365B811AF62E00045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 277"; + rLen = 0; + rLoc = 5977; + rType = 0; + vrLen = 446; + vrLoc = 7467; + }; + B6F365CA11B08AE30045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 282"; + rLen = 0; + rLoc = 6025; + rType = 0; + vrLen = 1001; + vrLoc = 7234; + }; + B6F365CB11B08AE30045E114 /* XCBuildMessageTextBookmark */ = { + isa = PBXTextBookmark; + comments = "Invalid use of incomplete type 'struct Device::BlockDevice'"; + fRef = B6F365CC11B08AE30045E114 /* VolumeEntry.h */; + fallbackIsa = XCBuildMessageTextBookmark; + rLen = 1; + rLoc = 47; + rType = 1; + }; + B6F365CC11B08AE30045E114 /* VolumeEntry.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = VolumeEntry.h; + path = ./Pascal/VolumeEntry.h; + sourceTree = ""; + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 1326}}"; + sepNavSelRange = "{1475, 0}"; + sepNavVisRange = "{0, 1803}"; + }; + }; + B6F365CD11B08AE30045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F3651A11ADD0280045E114 /* VolumeEntry.h */; + name = "VolumeEntry.h: 9"; + rLen = 0; + rLoc = 145; + rType = 0; + vrLen = 974; + vrLoc = 0; + }; + B6F365CE11B08AE30045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; + name = "newfs_pascal.cpp: 221"; + rLen = 0; + rLoc = 5494; + rType = 0; + vrLen = 1240; + vrLoc = 4971; + }; + B6F365CF11B08AE30045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; + name = "newfs_pascal.cpp: 221"; + rLen = 0; + rLoc = 5494; + rType = 0; + vrLen = 1240; + vrLoc = 4971; + }; + B6F365E511B09E510045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; + name = "newfs_pascal.cpp: 221"; + rLen = 0; + rLoc = 5494; + rType = 0; + vrLen = 1240; + vrLoc = 4971; + }; + B6F365E811B09EFD0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; + name = "newfs_pascal.cpp: 221"; + rLen = 0; + rLoc = 5494; + rType = 0; + vrLen = 1240; + vrLoc = 4971; + }; + B6F365EB11B09F2A0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; + name = "newfs_pascal.cpp: 221"; + rLen = 0; + rLoc = 5494; + rType = 0; + vrLen = 1240; + vrLoc = 4971; + }; + B6F365EE11B0A6010045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; + name = "newfs_pascal.cpp: 221"; + rLen = 0; + rLoc = 5494; + rType = 0; + vrLen = 1240; + vrLoc = 4971; + }; + B6F365F111B0A6BE0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; + name = "newfs_pascal.cpp: 221"; + rLen = 0; + rLoc = 5494; + rType = 0; + vrLen = 1240; + vrLoc = 4971; + }; + B6F365F411B169C00045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; + name = "newfs_pascal.cpp: 221"; + rLen = 0; + rLoc = 5494; + rType = 0; + vrLen = 1240; + vrLoc = 4971; + }; + B6F365F611B169D40045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; + name = "newfs_pascal.cpp: 221"; + rLen = 0; + rLoc = 5494; + rType = 0; + vrLen = 1240; + vrLoc = 4971; + }; + B6F365F711B169D40045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + name = "NibbleTest.cpp: 70"; + rLen = 0; + rLoc = 1607; + rType = 0; + vrLen = 983; + vrLoc = 874; + }; + B6F365F811B169D40045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + name = "NibbleTest.cpp: 70"; + rLen = 0; + rLoc = 1607; + rType = 0; + vrLen = 982; + vrLoc = 874; + }; + B6F365FA11B16A690045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + name = "NibbleTest.cpp: 70"; + rLen = 0; + rLoc = 1607; + rType = 0; + vrLen = 997; + vrLoc = 874; + }; + B6F3660311B16D9F0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + name = "NibbleTest.cpp: 70"; + rLen = 0; + rLoc = 1607; + rType = 0; + vrLen = 997; + vrLoc = 874; + }; + B6F3660411B16D9F0045E114 /* XCBuildMessageTextBookmark */ = { + isa = PBXTextBookmark; + comments = "Redefinition of 'unsigned int Pascal::VolumeEntry::rename(const char*, const char*)'"; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + fallbackIsa = XCBuildMessageTextBookmark; + rLen = 1; + rLoc = 383; + rType = 1; + }; + B6F3660511B16D9F0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 384"; + rLen = 0; + rLoc = 8503; + rType = 0; + vrLen = 702; + vrLoc = 8131; + }; + B6F3660A11B174830045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 384"; + rLen = 0; + rLoc = 8503; + rType = 0; + vrLen = 702; + vrLoc = 8131; + }; + B6F3660E11B175EA0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 384"; + rLen = 0; + rLoc = 8503; + rType = 0; + vrLen = 736; + vrLoc = 8131; + }; + B6F3661511B1762C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 384"; + rLen = 0; + rLoc = 8503; + rType = 0; + vrLen = 736; + vrLoc = 8131; + }; + B6F3661A11B176960045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 384"; + rLen = 0; + rLoc = 8503; + rType = 0; + vrLen = 736; + vrLoc = 8131; + }; + B6F3662011B177B60045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 384"; + rLen = 0; + rLoc = 8503; + rType = 0; + vrLen = 362; + vrLoc = 8206; + }; + B6F3662111B177B60045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + name = "NibbleTest.cpp: 74"; + rLen = 0; + rLoc = 1680; + rType = 0; + vrLen = 469; + vrLoc = 1396; + }; + B6F3662211B177B60045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; + rLen = 0; + rLoc = 166; + rType = 1; + }; + B6F3662311B177B60045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; + name = "Adaptor.cpp: 167"; + rLen = 0; + rLoc = 3653; + rType = 0; + vrLen = 533; + vrLoc = 8484; + }; + B6F3662D11B178720045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 384"; + rLen = 0; + rLoc = 8503; + rType = 0; + vrLen = 736; + vrLoc = 8131; + }; + B6F3662E11B178720045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; + name = "Adaptor.cpp: 167"; + rLen = 0; + rLoc = 3653; + rType = 0; + vrLen = 1182; + vrLoc = 8279; + }; + B6F3662F11B178720045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; + name = "Adaptor.cpp: 167"; + rLen = 0; + rLoc = 3653; + rType = 0; + vrLen = 1084; + vrLoc = 8365; + }; + B6F3663411B178EB0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; + name = "Adaptor.cpp: 167"; + rLen = 0; + rLoc = 3653; + rType = 0; + vrLen = 1125; + vrLoc = 8365; + }; + B6F3663811B179290045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; + name = "Adaptor.cpp: 167"; + rLen = 0; + rLoc = 3653; + rType = 0; + vrLen = 1125; + vrLoc = 8365; + }; + B6F3663D11B1809A0045E114 /* Adaptor.cpp:167 */ = { + isa = PBXFileBreakpoint; + actions = ( + ); + breakpointStyle = 0; + continueAfterActions = 0; + countType = 0; + delayBeforeContinue = 0; + fileReference = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; + functionName = "NibbleAdaptor::decode62(uint8_t val)"; + hitCount = 0; + ignoreCount = 0; + lineNumber = 167; + location = NibbleTest; + modificationTime = 296847681.921191; + originalNumberOfMultipleMatches = 1; + state = 1; + }; + B6F3664111B181C10045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; + name = "Adaptor.cpp: 167"; + rLen = 0; + rLoc = 3653; + rType = 0; + vrLen = 984; + vrLoc = 8112; + }; + B6F3665011B189490045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; + name = "Adaptor.cpp: 167"; + rLen = 0; + rLoc = 3653; + rType = 0; + vrLen = 933; + vrLoc = 7817; + }; + B6F3665111B190300045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; + name = "Adaptor.cpp: 262"; + rLen = 0; + rLoc = 6174; + rType = 0; + vrLen = 746; + vrLoc = 5474; + }; + B6F3665211B190300045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + rLen = 0; + rLoc = 75; + rType = 1; + }; + B6F3665311B190300045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + name = "NibbleTest.cpp: 76"; + rLen = 0; + rLoc = 1680; + rType = 0; + vrLen = 607; + vrLoc = 1479; + }; + B6F3665411B190370045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; + name = "Adaptor.cpp: 167"; + rLen = 0; + rLoc = 3653; + rType = 0; + vrLen = 933; + vrLoc = 7817; + }; + B6F3665511B190370045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + name = "NibbleTest.cpp: 76"; + rLen = 0; + rLoc = 1680; + rType = 0; + vrLen = 961; + vrLoc = 1203; + }; + B6F3665911B191C90045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + name = "NibbleTest.cpp: 76"; + rLen = 0; + rLoc = 1680; + rType = 0; + vrLen = 951; + vrLoc = 1203; + }; + B6F3665C11B194AC0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + name = "NibbleTest.cpp: 76"; + rLen = 0; + rLoc = 1680; + rType = 0; + vrLen = 951; + vrLoc = 1203; + }; + B6F3665D11B194AC0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; + name = "newfs_pascal.cpp: 221"; + rLen = 0; + rLoc = 5494; + rType = 0; + vrLen = 1277; + vrLoc = 4934; + }; + B6F3665E11B194AC0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; + name = "newfs_pascal.cpp: 224"; + rLen = 0; + rLoc = 5494; + rType = 0; + vrLen = 1267; + vrLoc = 5050; + }; + B6F366C211B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; + name = "newfs_pascal.cpp: 227"; + rLen = 0; + rLoc = 5494; + rType = 0; + vrLen = 1282; + vrLoc = 4530; + }; + B6F366C311B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFCC811A366C800C90DCE /* MappedFile.h */; + name = "MappedFile.h: 17"; + rLen = 0; + rLoc = 263; + rType = 0; + vrLen = 874; + vrLoc = 0; + }; + B6F366C411B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; + name = "MappedFile.cpp: 53"; + rLen = 0; + rLoc = 970; + rType = 0; + vrLen = 737; + vrLoc = 463; + }; + B6F366C511B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; + name = "BlockDevice.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 815; + vrLoc = 0; + }; + B6F366C611B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB8811A1FB2500C90DCE /* DiskImage.h */; + name = "DiskImage.h: 66"; + rLen = 0; + rLoc = 1204; + rType = 0; + vrLen = 809; + vrLoc = 709; + }; + B6F366C711B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAA511A094E000C90DCE /* UniversalDiskImage.h */; + name = "UniversalDiskImage.h: 29"; + rLen = 4; + rLoc = 507; + rType = 0; + vrLen = 692; + vrLoc = 0; + }; + B6F366C811B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; + name = "DavexDiskImage.cpp: 111"; + rLen = 0; + rLoc = 2355; + rType = 0; + vrLen = 875; + vrLoc = 1920; + }; + B6F366C911B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; + name = "DiskCopy42Image.cpp: 111"; + rLen = 0; + rLoc = 2053; + rType = 0; + vrLen = 925; + vrLoc = 1629; + }; + B6F366CA11B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; + name = "UniversalDiskImage.cpp: 47"; + rLen = 0; + rLoc = 956; + rType = 0; + vrLen = 808; + vrLoc = 497; + }; + B6F366CB11B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; + name = "DiskImage.cpp: 30"; + rLen = 0; + rLoc = 423; + rType = 0; + vrLen = 613; + vrLoc = 128; + }; + B6F366CC11B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + name = "apfm.cpp: 755"; + rLen = 0; + rLoc = 16564; + rType = 0; + vrLen = 884; + vrLoc = 15404; + }; + B6F366CD11B1A28C0045E114 /* XCBuildMessageTextBookmark */ = { + isa = PBXTextBookmark; + comments = "Unused variable 'readOnly'"; + fRef = B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */; + fallbackIsa = XCBuildMessageTextBookmark; + rLen = 0; + rLoc = 194; + rType = 1; + }; + B6F366CE11B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */; + name = "fuse_pascal.cpp: 195"; + rLen = 0; + rLoc = 4414; + rType = 0; + vrLen = 1077; + vrLoc = 3977; + }; } diff --git a/PROFuseX.xcodeproj/kelvin.perspectivev3 b/PROFuseX.xcodeproj/kelvin.perspectivev3 index 35372d2..58876dd 100644 --- a/PROFuseX.xcodeproj/kelvin.perspectivev3 +++ b/PROFuseX.xcodeproj/kelvin.perspectivev3 @@ -270,14 +270,17 @@ B63EFBE711A244EE00C90DCE B63EFACF11A09DB500C90DCE B63EFAC811A09DAA00C90DCE + B63EFA9411A094E000C90DCE + 1AB674ADFE9D54B511CA2CBB B656ADED11A84D3200AB578A 1C37FBAC04509CD000000102 + 1C37FAAC04509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey - 10 - 7 + 42 + 29 0 @@ -299,7 +302,7 @@ 318 RubberWindowFrame - 489 -24 1239 1000 0 0 1920 1178 + 547 105 1239 1000 0 0 1920 1178 Module PBXSmartGroupTreeModule @@ -317,7 +320,7 @@ PBXProjectModuleGUID B63EFA6111A093C200C90DCE PBXProjectModuleLabel - VolumeEntry.cpp + fuse_pascal.cpp PBXSplitModuleInNavigatorKey Split0 @@ -325,18 +328,15 @@ PBXProjectModuleGUID B63EFA6211A093C200C90DCE PBXProjectModuleLabel - VolumeEntry.cpp + fuse_pascal.cpp _historyCapacity 0 bookmark - B6F364F511ACB5B60045E114 + B6F366CE11B1A28C0045E114 history B63EFC2611A2D5A400C90DCE - B63EFC2B11A2D5A400C90DCE B63EFC3211A2D5A400C90DCE - B63EFCB211A3639400C90DCE - B63EFCB611A3639400C90DCE B63EFDA011A4488200C90DCE B63EFDA511A4488200C90DCE B63EFDA711A4488200C90DCE @@ -348,14 +348,10 @@ B63EFDB311A4488200C90DCE B63EFDB711A4488200C90DCE B63EFDC711A4494C00C90DCE - B63EFDE611A44E9300C90DCE B63EFDF211A4504200C90DCE B63EFEA011A488C200C90DCE B63EFEA111A488C200C90DCE - B63EFEA211A488C200C90DCE - B63EFEA311A488C200C90DCE B63EFEA811A488C200C90DCE - B63EFEA911A488C200C90DCE B63EFEEC11A4A70400C90DCE B6E5F0DD11A60726000AD141 B6E5F0F211A73144000AD141 @@ -364,22 +360,32 @@ B6E5F18211A76B74000AD141 B656AE2411A84FA400AB578A B656AE2611A84FA400AB578A - B656AE2711A84FA400AB578A - B656AEA711A9C91600AB578A - B656AEA811A9C91600AB578A - B656AF2A11AA10C900AB578A B6F3642D11AA1E070045E114 B6F3647111AB35FE0045E114 - B6F3649411AB58E80045E114 B6F3649511AB58E80045E114 - B6F3649611AB58E80045E114 B6F3649E11AB59190045E114 B6F364B711AB84840045E114 - B6F364C811ACAB370045E114 - B6F364E811ACB5790045E114 - B6F364E911ACB5790045E114 - B6F364EB11ACB5790045E114 - B6F364EC11ACB5790045E114 + B6F3652E11ADD5D20045E114 + B6F3653011ADD5D20045E114 + B6F3653111ADD5D20045E114 + B6F3657E11AE255B0045E114 + B6F365CB11B08AE30045E114 + B6F365CD11B08AE30045E114 + B6F3662D11B178720045E114 + B6F3665411B190370045E114 + B6F3665C11B194AC0045E114 + B6F366C211B1A28C0045E114 + B6F366C311B1A28C0045E114 + B6F366C411B1A28C0045E114 + B6F366C511B1A28C0045E114 + B6F366C611B1A28C0045E114 + B6F366C711B1A28C0045E114 + B6F366C811B1A28C0045E114 + B6F366C911B1A28C0045E114 + B6F366CA11B1A28C0045E114 + B6F366CB11B1A28C0045E114 + B6F366CC11B1A28C0045E114 + B6F366CD11B1A28C0045E114 SplitCount @@ -395,7 +401,7 @@ Frame {{0, 0}, {899, 562}} RubberWindowFrame - 489 -24 1239 1000 0 0 1920 1178 + 547 105 1239 1000 0 0 1920 1178 Module PBXNavigatorGroup @@ -434,7 +440,7 @@ GeometryConfiguration Frame - {{10, 27}, {899, 341}} + {{10, 27}, {899, 365}} Module PBXProjectFindModule @@ -474,7 +480,7 @@ Frame {{10, 27}, {899, 365}} RubberWindowFrame - 489 -24 1239 1000 0 0 1920 1178 + 547 105 1239 1000 0 0 1920 1178 Module PBXBuildResultsModule @@ -696,14 +702,17 @@ 5 WindowOrderList - B6F364EE11ACB5790045E114 - B6F364C211AC92730045E114 - B6F364C111AC92730045E114 + B6F3650F11ADC40E0045E114 + B6F3651011ADC40E0045E114 + B6F366CF11B1A28C0045E114 + B6F3665F11B194AC0045E114 + B6F366D011B1A28C0045E114 + B6F366D111B1A28C0045E114 + B6F366D211B1A28C0045E114 /Users/kelvin/Projects/PROFuseX/PROFuseX.xcodeproj - B6F364CC11ACAB370045E114 WindowString - 489 -24 1239 1000 0 0 1920 1178 + 547 105 1239 1000 0 0 1920 1178 WindowToolsV3 diff --git a/PROFuseX.xcodeproj/project.pbxproj b/PROFuseX.xcodeproj/project.pbxproj index d87bd80..0177646 100644 --- a/PROFuseX.xcodeproj/project.pbxproj +++ b/PROFuseX.xcodeproj/project.pbxproj @@ -129,9 +129,8 @@ B63EFBE811A244EE00C90DCE /* Date.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Date.cpp; sourceTree = ""; }; B63EFBE911A244EE00C90DCE /* Date.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Date.h; sourceTree = ""; }; B63EFBEA11A244EE00C90DCE /* Entry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Entry.cpp; sourceTree = ""; }; - B63EFBEB11A244EE00C90DCE /* File.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = File.h; sourceTree = ""; }; B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileEntry.cpp; sourceTree = ""; }; - B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VolumeEntry.cpp; sourceTree = ""; }; + B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = VolumeEntry.cpp; sourceTree = ""; }; B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOBuffer.cpp.h; sourceTree = ""; }; B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fuse_pascal.cpp; sourceTree = ""; }; B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = newfs_pascal.cpp; sourceTree = ""; }; @@ -145,6 +144,10 @@ B656AF0311AA105500AB578A /* NibbleTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NibbleTest; sourceTree = BUILT_PRODUCTS_DIR; }; B6F3647B11AB361D0045E114 /* xattr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xattr.cpp; sourceTree = ""; }; B6F3648011AB36260045E114 /* xattr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xattr; sourceTree = BUILT_PRODUCTS_DIR; }; + B6F3651A11ADD0280045E114 /* VolumeEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VolumeEntry.h; sourceTree = ""; }; + B6F3651B11ADD0280045E114 /* FileEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileEntry.h; sourceTree = ""; }; + B6F3651C11ADD0280045E114 /* Entry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Entry.h; sourceTree = ""; }; + B6F3652711ADD52B0045E114 /* Pascal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Pascal.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -292,12 +295,15 @@ B63EFBE711A244EE00C90DCE /* Pascal */ = { isa = PBXGroup; children = ( + B6F3652711ADD52B0045E114 /* Pascal.h */, B63EFBE811A244EE00C90DCE /* Date.cpp */, B63EFBE911A244EE00C90DCE /* Date.h */, B63EFBEA11A244EE00C90DCE /* Entry.cpp */, - B63EFBEB11A244EE00C90DCE /* File.h */, B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */, B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */, + B6F3651A11ADD0280045E114 /* VolumeEntry.h */, + B6F3651B11ADD0280045E114 /* FileEntry.h */, + B6F3651C11ADD0280045E114 /* Entry.h */, ); path = Pascal; sourceTree = ""; From d46406ff843999327784aeca42712f36da750c53 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 29 May 2010 19:29:59 +0000 Subject: [PATCH 170/236] Add Read/Write flags for File::, etc instead of using bool git-svn-id: https://profuse.googlecode.com/svn/branches/v2@297 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/BlockDevice.cpp | 6 +- Device/BlockDevice.h | 4 +- Device/DavexDiskImage.cpp | 9 +-- Device/DavexDiskImage.h | 4 +- Device/DiskCopy42Image.cpp | 10 +-- Device/DiskCopy42Image.h | 2 +- Device/DiskImage.cpp | 11 +--- Device/DiskImage.h | 7 +- Device/RawDevice.cpp | 14 ++-- Device/RawDevice.h | 11 ++-- Device/UniversalDiskImage.cpp | 13 +--- Device/UniversalDiskImage.h | 2 +- File/File.cpp | 15 +++-- File/File.h | 11 +++- File/MappedFile.cpp | 35 +++++++--- File/MappedFile.h | 7 +- apfm.cpp | 92 ++++++++++++++++++++------ fuse_pascal.cpp | 7 +- newfs_pascal.cpp | 121 ++++++++++++++++++++++------------ 19 files changed, 235 insertions(+), 146 deletions(-) diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index e583165..d86f4d7 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -78,7 +78,7 @@ unsigned BlockDevice::ImageType(const char *type, unsigned defv) return defv; } -BlockDevice *BlockDevice::Open(const char *name, bool readOnly, unsigned imageType) +BlockDevice *BlockDevice::Open(const char *name, File::FileFlags flags, unsigned imageType) { #undef __METHOD__ #define __METHOD__ "BlockDevice::Open" @@ -96,7 +96,7 @@ BlockDevice *BlockDevice::Open(const char *name, bool readOnly, unsigned imageTy { // /dev/xxxx if (S_ISBLK(st.st_mode)) - return RawDevice::Open(name, readOnly); + return RawDevice::Open(name, flags); imageType = ImageType(name, 'PO__'); @@ -105,7 +105,7 @@ BlockDevice *BlockDevice::Open(const char *name, bool readOnly, unsigned imageTy // TODO -- if no image type, guess based on file size? - MappedFile file(name, readOnly); + MappedFile file(name, flags); switch (imageType) diff --git a/Device/BlockDevice.h b/Device/BlockDevice.h index 33680e3..8e8feb5 100644 --- a/Device/BlockDevice.h +++ b/Device/BlockDevice.h @@ -10,6 +10,8 @@ #include +#include + namespace Device { class BlockDevice { @@ -19,7 +21,7 @@ public: // static methods. static unsigned ImageType(const char *type, unsigned defv = 0); - static BlockDevice *Open(const char *name, bool readOnly, unsigned imageType = 0); + static BlockDevice *Open(const char *name, File::FileFlags flags, unsigned imageType = 0); static BlockDevice *Create(const char *fname, const char *vname, unsigned blocks, unsigned imageType = 0); diff --git a/Device/DavexDiskImage.cpp b/Device/DavexDiskImage.cpp index c2e11d6..e63a04f 100644 --- a/Device/DavexDiskImage.cpp +++ b/Device/DavexDiskImage.cpp @@ -28,13 +28,6 @@ using ProFUSE::POSIXException; static const char *IdentityCheck = "\x60VSTORE [Davex]\x00"; -/* -DavexDiskImage::DavexDiskImage(const char *name, bool readOnly) : - DiskImage(name, readOnly) -{ - Validate(file()); -} -*/ // private, validation already performed. DavexDiskImage::DavexDiskImage(MappedFile *file) : @@ -115,7 +108,7 @@ DavexDiskImage *DavexDiskImage::Create(const char *name, size_t blocks, const ch IOBuffer header(tmp,512); - MappedFile *file = new MappedFile(name, blocks * 512 + 512); + MappedFile *file = MappedFile::Create(name, blocks * 512 + 512); data = (uint8_t *)file->address(); diff --git a/Device/DavexDiskImage.h b/Device/DavexDiskImage.h index fa9a432..ff659e0 100644 --- a/Device/DavexDiskImage.h +++ b/Device/DavexDiskImage.h @@ -24,8 +24,8 @@ public: private: - DavexDiskImage(const char *, bool readOnly); - + DavexDiskImage(); + DavexDiskImage(MappedFile *); static void Validate(MappedFile *); diff --git a/Device/DiskCopy42Image.cpp b/Device/DiskCopy42Image.cpp index c8e22bb..9af488b 100644 --- a/Device/DiskCopy42Image.cpp +++ b/Device/DiskCopy42Image.cpp @@ -37,14 +37,6 @@ DiskCopy42Image::DiskCopy42Image(MappedFile *f) : } -/* -DiskCopy42Image::DiskCopy42Image(const char *name, bool readOnly) : - DiskImage(name, readOnly), - _changed(false) -{ - Validate(file()); -} -*/ DiskCopy42Image::~DiskCopy42Image() { @@ -116,7 +108,7 @@ DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks) DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks, const char *vname) { - MappedFile *file = new MappedFile(name, blocks * 512 + oUserData); + MappedFile *file = MappedFile::Create(name, blocks * 512 + oUserData); diff --git a/Device/DiskCopy42Image.h b/Device/DiskCopy42Image.h index 2c43da8..f4ce443 100644 --- a/Device/DiskCopy42Image.h +++ b/Device/DiskCopy42Image.h @@ -26,7 +26,7 @@ public: private: - DiskCopy42Image(const char *name, bool readOnly); + DiskCopy42Image(); DiskCopy42Image(MappedFile *); static void Validate(MappedFile *); diff --git a/Device/DiskImage.cpp b/Device/DiskImage.cpp index 024bf15..113eb22 100644 --- a/Device/DiskImage.cpp +++ b/Device/DiskImage.cpp @@ -23,7 +23,7 @@ using ProFUSE::Exception; using ProFUSE::POSIXException; - +/* DiskImage::DiskImage(const char *name, bool readOnly) { File fd(name, readOnly ? O_RDONLY : O_RDWR); @@ -34,7 +34,7 @@ DiskImage::DiskImage(const char *name, bool readOnly) _readOnly = readOnly; _adaptor = NULL; } - +*/ DiskImage::DiskImage(MappedFile *file) { @@ -102,13 +102,6 @@ void DiskImage::sync() -/* -ProDOSOrderDiskImage::ProDOSOrderDiskImage(const char *name, bool readOnly) : - DiskImage(name, readOnly) -{ - Validate(file()); -} -*/ ProDOSOrderDiskImage::ProDOSOrderDiskImage(MappedFile *file) : DiskImage(file) diff --git a/Device/DiskImage.h b/Device/DiskImage.h index 9bd87d9..52a7303 100644 --- a/Device/DiskImage.h +++ b/Device/DiskImage.h @@ -30,10 +30,9 @@ public: protected: + DiskImage(); DiskImage(MappedFile *file = 0); - DiskImage(const char *name, bool readOnly); - void setBlocks(unsigned blocks) { _blocks = blocks; } @@ -65,7 +64,7 @@ public: virtual BlockCache *createBlockCache(); private: - ProDOSOrderDiskImage(const char *name, bool readOnly); + ProDOSOrderDiskImage(); ProDOSOrderDiskImage(MappedFile *); @@ -80,7 +79,7 @@ public: static DOSOrderDiskImage *Open(MappedFile *); private: - DOSOrderDiskImage(const char *name, bool readOnly); + DOSOrderDiskImage(); DOSOrderDiskImage(MappedFile *); static void Validate(MappedFile *); diff --git a/Device/RawDevice.cpp b/Device/RawDevice.cpp index cedb733..7c9dbc4 100644 --- a/Device/RawDevice.cpp +++ b/Device/RawDevice.cpp @@ -122,8 +122,8 @@ void RawDevice::devSize(int fd) #endif -RawDevice::RawDevice(const char *name, bool readOnly) : - _file(name, readOnly) +RawDevice::RawDevice(const char *name, File::FileFlags flags) : + _file(name, flags) { #undef __METHOD__ #define __METHOD__ "RawDevice::RawDevice" @@ -134,7 +134,7 @@ RawDevice::RawDevice(const char *name, bool readOnly) : throw new Exception(__METHOD__ ": Invalid file handle."); } - _readOnly = readOnly; + _readOnly = flags == File::ReadOnly; _size = 0; _blocks = 0; _blockSize = 0; @@ -143,7 +143,7 @@ RawDevice::RawDevice(const char *name, bool readOnly) : devSize(_file.fd()); } -RawDevice::RawDevice(File& file, bool readOnly) : +RawDevice::RawDevice(File& file, File::FileFlags flags) : _file(file) { #undef __METHOD__ @@ -155,7 +155,7 @@ RawDevice::RawDevice(File& file, bool readOnly) : throw new Exception(__METHOD__ ": Invalid file handle."); } - _readOnly = readOnly; + _readOnly = flags == File::ReadOnly; _size = 0; _blocks = 0; _blockSize = 0; @@ -170,9 +170,9 @@ RawDevice::~RawDevice() } -RawDevice *RawDevice::Open(const char *name, bool readOnly) +RawDevice *RawDevice::Open(const char *name, File::FileFlags flags) { - return new RawDevice(name, readOnly); + return new RawDevice(name, flags); } diff --git a/Device/RawDevice.h b/Device/RawDevice.h index df711ac..573ab94 100644 --- a/Device/RawDevice.h +++ b/Device/RawDevice.h @@ -15,11 +15,9 @@ namespace Device { class RawDevice : public BlockDevice { public: - RawDevice(const char *name, bool readOnly); + - RawDevice(File& file, bool readOnly); - - static RawDevice *Open(const char *name, bool readOnly); + static RawDevice *Open(const char *name, File::FileFlags flags); virtual ~RawDevice(); @@ -38,6 +36,11 @@ public: private: + + RawDevice(const char *name, File::FileFlags flags); + + RawDevice(File& file, File::FileFlags flags); + void devSize(int fd); File _file; diff --git a/Device/UniversalDiskImage.cpp b/Device/UniversalDiskImage.cpp index b1162f0..dedb9c9 100644 --- a/Device/UniversalDiskImage.cpp +++ b/Device/UniversalDiskImage.cpp @@ -16,17 +16,6 @@ using ProFUSE::POSIXException; -/* -UniversalDiskImage::UniversalDiskImage(const char *name, bool readOnly) : - DiskImage(name, readOnly) -{ - Validate(file()); - const void *data = file()->fileData(); - - // flags. bit 31 = locked. - _flags = Read32(data, 0x10); -} -*/ UniversalDiskImage::UniversalDiskImage(MappedFile *file) : DiskImage(file) @@ -55,7 +44,7 @@ UniversalDiskImage::UniversalDiskImage(MappedFile *file) : UniversalDiskImage *UniversalDiskImage::Create(const char *name, size_t blocks) { // 64-byte header. - MappedFile *file = new MappedFile(name, blocks * 512 + 64); + MappedFile *file = MappedFile::Create(name, blocks * 512 + 64); uint8_t tmp[64]; diff --git a/Device/UniversalDiskImage.h b/Device/UniversalDiskImage.h index fbaccba..e552af5 100644 --- a/Device/UniversalDiskImage.h +++ b/Device/UniversalDiskImage.h @@ -24,7 +24,7 @@ public: private: - UniversalDiskImage(const char *name, bool readOnly); + UniversalDiskImage(); UniversalDiskImage(MappedFile *); static void Validate(MappedFile *); diff --git a/File/File.cpp b/File/File.cpp index ee9b81d..251ea72 100644 --- a/File/File.cpp +++ b/File/File.cpp @@ -37,9 +37,9 @@ File::File(const char *name, int flags, mode_t mode, const std::nothrow_t&) _fd = ::open(name, flags, mode); } -File::File(const char *name, bool readOnly, const std::nothrow_t&) +File::File(const char *name, FileFlags flags, const std::nothrow_t&) { - _fd = ::open(name, readOnly ? O_RDONLY : O_RDWR); + _fd = ::open(name, flags == ReadOnly ? O_RDONLY : O_RDWR); } File::File(const char *name, int flags) @@ -63,12 +63,12 @@ File::File(const char *name, int flags, mode_t mode) } -File::File(const char *name, bool readOnly) +File::File(const char *name, FileFlags flags) { #undef __METHOD__ #define __METHOD__ "File::File" - _fd = ::open(name, readOnly ? O_RDONLY : O_RDWR); + _fd = ::open(name, flags == ReadOnly ? O_RDONLY : O_RDWR); if (_fd < 0) throw POSIXException( __METHOD__ ": open", errno); } @@ -86,11 +86,14 @@ void File::close() if (_fd >= 0) { - int fd = _fd; + ::close(_fd); _fd = -1; - if (::close(fd) != 0) + // destructor shouldn't throw. + /* + if (::close(fd) != 0) throw POSIXException(__METHOD__ ": close", errno); + */ } } diff --git a/File/File.h b/File/File.h index 1bc5e5d..72bb532 100644 --- a/File/File.h +++ b/File/File.h @@ -7,21 +7,28 @@ #include #include + class File { public: + + enum FileFlags { + ReadOnly = 1, + ReadWrite = 2 + }; + File(); File(File &); File(int fd); File(const char *name, int flags); File(const char *name, int flags, mode_t mode); - File(const char *name, bool readOnly); + File(const char *name, FileFlags flags); File(const char *name, int flags, const std::nothrow_t &); File(const char *name, int flags, mode_t mode, const std::nothrow_t &); - File(const char *name, bool readOnly, const std::nothrow_t &); + File(const char *name, FileFlags flags, const std::nothrow_t &); ~File(); diff --git a/File/MappedFile.cpp b/File/MappedFile.cpp index 0ffd087..2b8eb91 100644 --- a/File/MappedFile.cpp +++ b/File/MappedFile.cpp @@ -27,29 +27,41 @@ MappedFile::MappedFile(MappedFile &mf) mf._readOnly = true; } -MappedFile::MappedFile(const File &f, bool readOnly, size_t size) +MappedFile::MappedFile(const File &f, File::FileFlags flags, size_t size) { _length = -1; _address = MAP_FAILED; - _readOnly = readOnly; + _readOnly = true; - init(f, readOnly, size); + init(f, flags == File::ReadOnly, size); } -MappedFile::MappedFile(const char *name, bool readOnly) +MappedFile::MappedFile(const char *name, File::FileFlags flags) { - File f(name, readOnly); + File f(name, flags); _length = -1; _address = MAP_FAILED; - _readOnly = readOnly; + _readOnly = true; - init(f, readOnly, 0); + init(f, flags == File::ReadOnly, 0); } +MappedFile::MappedFile(const char *name, File::FileFlags flags, const std::nothrow_t ¬hrow) +{ + File f(name, flags, nothrow); + + _length = -1; + _address = MAP_FAILED; + _readOnly = true; + + if (f.isValid()) + init(f, flags == File::ReadOnly, 0); +} + MappedFile::~MappedFile() { @@ -101,15 +113,22 @@ void MappedFile::close() if (_address != MAP_FAILED) { + /* void *address = _address; size_t length = _length; + */ + + ::munmap(_address, _length); _address = MAP_FAILED; _length = -1; _readOnly = true; + // destructor shouldn't throw. + /* if (::munmap(address, length) != 0) throw POSIXException(__METHOD__ ": munmap", errno); + */ } } @@ -164,5 +183,5 @@ MappedFile *MappedFile::Create(const char *name, size_t size) throw POSIXException(__METHOD__ ": Unable to truncate file.", errno); } - return new MappedFile(fd, false, size); + return new MappedFile(fd, File::ReadWrite, size); } \ No newline at end of file diff --git a/File/MappedFile.h b/File/MappedFile.h index 014ef2c..cec519d 100644 --- a/File/MappedFile.h +++ b/File/MappedFile.h @@ -1,6 +1,8 @@ #ifndef __MAPPED_FILE_H__ #define __MAPPED_FILE_H__ + +#include #include #include @@ -12,8 +14,9 @@ class MappedFile { MappedFile(); MappedFile(MappedFile&); - MappedFile(const File &f, bool readOnly, size_t size = -1); - MappedFile(const char *name, bool readOnly); + MappedFile(const File &f, File::FileFlags flags, size_t size = -1); + MappedFile(const char *name, File::FileFlags flags); + MappedFile(const char *name, File::FileFlags flags, const std::nothrow_t ¬hrow); ~MappedFile(); diff --git a/apfm.cpp b/apfm.cpp index 76b249c..ef1c2de 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -146,17 +146,49 @@ void commandUsage(unsigned command) } -bool isReadOnly(const char *command) +unsigned command(const char *command) { - if (!::strcasecmp(command, "mv")) return false; - if (!::strcasecmp(command, "rm")) return false; - if (!::strcasecmp(command, "cp")) return false; - if (!::strcasecmp(command, "put")) return false; - if (!::strcasecmp(command, "krunch")) return false; + if (!::strcasecmp(command, "ls")) return kCommandLS; + if (!::strcasecmp(command, "list")) return kCommandLS; - return true; + if (!::strcasecmp(command, "cat")) return kCommandCAT; + + if (!::strcasecmp(command, "get")) return kCommandGET; + + if (!::strcasecmp(command, "put")) return kCommandPUT; + + if (!::strcasecmp(command, "cp")) return kCommandCP; + if (!::strcasecmp(command, "copy")) return kCommandCP; + + if (!::strcasecmp(command, "rm")) return kCommandRM; + if (!::strcasecmp(command, "remove")) return kCommandRM; + if (!::strcasecmp(command, "del")) return kCommandRM; + if (!::strcasecmp(command, "delete")) return kCommandRM; + + if (!::strcasecmp(command, "mv")) return kCommandMV; + if (!::strcasecmp(command, "move")) return kCommandMV; + if (!::strcasecmp(command, "rename")) return kCommandMV; + + if (!::strcasecmp(command, "krunch")) return kCommandKRUNCH; + + + return -1; } +File::FileFlags commandFlags(unsigned command) +{ + switch (command) + { + case kCommandPUT: + case kCommandKRUNCH: + case kCommandRM: + case kCommandMV: + case kCommandCP: + return File::ReadWrite; + default: + return File::ReadOnly; + } +} // from BSD rm, prompt question on stderr. bool yes_or_no() @@ -717,9 +749,10 @@ int main(int argc, char **argv) try { - // should we peek at the action to determine if read only? + unsigned actionCode = command(action); - device.reset( Device::BlockDevice::Open(file, isReadOnly(action), fmt) ); + + device.reset( Device::BlockDevice::Open(file, commandFlags(actionCode), fmt) ); @@ -729,18 +762,35 @@ int main(int argc, char **argv) device.release(); - - if (!::strcasecmp("cat", action)) return action_cat(argc - 1, argv + 1, volume.get()); - if (!::strcasecmp("cp", action)) return action_cp(argc - 1, argv + 1, volume.get()); - if (!::strcasecmp("krunch", action)) return action_krunch(argc - 1, argv + 1, volume.get()); - if (!::strcasecmp("ls", action)) return action_ls(argc - 1, argv + 1, volume.get()); - if (!::strcasecmp("mv", action)) return action_mv(argc - 1, argv + 1, volume.get()); - if (!::strcasecmp("rm", action)) return action_rm(argc - 1, argv + 1, volume.get()); - - if (!::strcasecmp("get", action)) return action_get(argc -1, argv + 1, volume.get()); - //if (!::strcasecmp("put", action)) return action_put(argc -1, argv + 1, volume.get()); - - + switch (actionCode) + { + case kCommandCAT: + return action_cat(argc - 1, argv + 1, volume.get()); + break; + case kCommandCP: + return action_cp(argc - 1, argv + 1, volume.get()); + break; + case kCommandKRUNCH: + return action_krunch(argc - 1, argv + 1, volume.get()); + break; + case kCommandLS: + return action_ls(argc - 1, argv + 1, volume.get()); + break; + case kCommandMV: + return action_mv(argc - 1, argv + 1, volume.get()); + break; + case kCommandRM: + return action_rm(argc - 1, argv + 1, volume.get()); + break; + case kCommandGET: + return action_get(argc -1, argv + 1, volume.get()); + break; + /* + case kCommandPUT: + return action_put(argc -1, argv + 1, volume.get()); + break; + */ + } usage(); return 3; } diff --git a/fuse_pascal.cpp b/fuse_pascal.cpp index 40bfd39..876c865 100644 --- a/fuse_pascal.cpp +++ b/fuse_pascal.cpp @@ -23,6 +23,7 @@ #include +#include std::string fDiskImage; @@ -191,15 +192,13 @@ int main(int argc, char **argv) std::fprintf(stderr, "Warning: Unknown image type ``%s''\n", options.format); } - - bool readOnly = true; - + try { std::auto_ptr device; - device.reset( Device::BlockDevice::Open(fDiskImage.c_str(), readOnly, format) ); + device.reset( Device::BlockDevice::Open(fDiskImage.c_str(), File::ReadOnly, format) ); if (!device.get()) diff --git a/newfs_pascal.cpp b/newfs_pascal.cpp index d768ceb..79635a3 100644 --- a/newfs_pascal.cpp +++ b/newfs_pascal.cpp @@ -1,3 +1,15 @@ + +#include +#include +#include +#include +#include +#include + +#include +#include + + #include #include @@ -6,14 +18,12 @@ #include -#include -#include -#include -#include -#include +#include +#include + + + -#include -#include using namespace Pascal; using namespace Device; @@ -108,11 +118,12 @@ void usage() 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" + std::printf(" -v volume_name Specify the volume name.\n" " Default is Untitled.\n" - " -s size specify size in blocks.\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" + " -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" @@ -128,6 +139,8 @@ 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; @@ -137,40 +150,43 @@ int main(int argc, char **argv) { switch(c) { - case '?': - case 'h': - usage(); - return 0; - 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 'h': + default: + usage(); + return c == 'h' ? 0 : 1; + 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) + case 'v': + volumeName = optarg; + // make sure it's legal. + if (!VolumeEntry::ValidName(optarg)) { - std::fprintf(stderr, "Error: `%s' is not a supported disk image format.\n", optarg); - return -1; + 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; + } + } + case 'b': + bootFile = optarg; + break; } } @@ -212,7 +228,7 @@ int main(int argc, char **argv) fprintf(stderr, "`%s' is a raw device. Are you sure you want to initialize it? ", fname); if (!yes_or_no()) return -1; - device.reset( RawDevice::Open(fname, false) ); + device.reset( RawDevice::Open(fname, File::ReadWrite) ); blocks = device->blocks(); rawDevice = true; @@ -253,6 +269,27 @@ int main(int argc, char **argv) } + 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(); + + } + + + + + + } + + volume.reset( new VolumeEntry(volumeName.c_str(), device.get()) ); From 2f307b3f198385548e9f780ad728b8cbfccf3d10 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 29 May 2010 20:41:07 +0000 Subject: [PATCH 171/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@298 aa027e90-d47c-11dd-86d7-074df07e0730 --- apfm.cpp | 61 +++++++++++++++++++++++++++++++++++------------- newfs_pascal.cpp | 35 +++++++++++---------------- 2 files changed, 59 insertions(+), 37 deletions(-) diff --git a/apfm.cpp b/apfm.cpp index ef1c2de..479c457 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -191,10 +192,18 @@ File::FileFlags commandFlags(unsigned command) } // from BSD rm, prompt question on stderr. -bool yes_or_no() + +bool yes_or_no(const char *format, ...) { int ch, first; - (void)fflush(stderr); + va_list va; + + va_start(va, format); + std::vfprintf(stderr, format, va); + va_end(va); + + std::fputc(' ', stderr); + std::fflush(stderr); first = ch = getchar(); while (ch != '\n' && ch != EOF) @@ -381,8 +390,8 @@ int action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume) } - argc += optind; - argv -= optind; + argc -= optind; + argv += optind; if (argc < 1) { @@ -453,6 +462,7 @@ int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume) break; case 'i': fFlag = false; + break; case 'h': default: @@ -462,8 +472,8 @@ int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume) } } - argc += optind; - argv -= optind; + argc -= optind; + argv += optind; // TODO -- honor fFlag // TODO -- catch errors. @@ -492,6 +502,7 @@ int action_krunch(int argc, char **argv, Pascal::VolumeEntry *volume) break; case 'i': fFlag = false; + break; case 'h': default: @@ -501,8 +512,8 @@ int action_krunch(int argc, char **argv, Pascal::VolumeEntry *volume) } } - argc += optind; - argv -= optind; + argc -= optind; + argv += optind; //check if it needs krunching, volume->krunch(); @@ -531,17 +542,18 @@ int action_get(int argc, char **argv, Pascal::VolumeEntry *volume) break; case 'i': fFlag = false; + break; case 'h': default: - commandUsage(kCommandKRUNCH); + commandUsage(kCommandGET); return c == 'h' ? 0 : 1; break; } } - argc += optind; - argv -= optind; + argc -= optind; + argv += optind; Pascal::FileEntry *entry; @@ -555,7 +567,7 @@ int action_get(int argc, char **argv, Pascal::VolumeEntry *volume) outfile = argv[1]; break; default: - commandUsage(kCommandKRUNCH); + commandUsage(kCommandGET); return 1; break; } @@ -563,16 +575,33 @@ int action_get(int argc, char **argv, Pascal::VolumeEntry *volume) entry = volume->fileByName(infile); - // if outfile exists, !fFlag, prompt before overwriting. - - File::File file(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); - if (!entry) { std::fprintf(stderr, "apfm get: %s: no such file.\n", infile); return 1; } + + // if not -f, check before overwriting file. + if (!fFlag) + { + struct stat st; + if (::stat(outfile, &st) == 0) + { + bool ok = yes_or_no("Overwrite %s?", outfile); + if (!ok) + { + std::fprintf(stderr, "Not overwritten.\n"); + return 1; + } + + } + } + + + + File::File file(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); + unsigned fileSize = entry->fileSize(); unsigned offset = 0; diff --git a/newfs_pascal.cpp b/newfs_pascal.cpp index 79635a3..3829f69 100644 --- a/newfs_pascal.cpp +++ b/newfs_pascal.cpp @@ -280,13 +280,21 @@ int main(int argc, char **argv) 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"); + } } - - - - - } @@ -295,21 +303,6 @@ int main(int argc, char **argv) ); device.release(); - /* - ProFUSE::MappedFile bootBlock("pascal.bootblock", true); - - if (bootBlock.fileSize() == 1024) - { - uint8_t buffer[512]; - bootBlock.setBlocks(2); - - for (unsigned block = 0; block < 2; ++block) - { - bootBlock.readBlock(block, buffer); - volume->writeBlock(block, buffer); - } - } - */ } catch (ProFUSE::POSIXException& e) From 2a87b480a187da73d39ea2120a13076a1d2f45c5 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 30 May 2010 20:16:57 +0000 Subject: [PATCH 172/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@299 aa027e90-d47c-11dd-86d7-074df07e0730 --- apfm.cpp | 193 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 163 insertions(+), 30 deletions(-) diff --git a/apfm.cpp b/apfm.cpp index 479c457..9ac29a1 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -383,7 +384,7 @@ int action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume) { case 'h': default: - commandUsage(kCommandRM); + commandUsage(kCommandCAT); return c == 'h' ? 0 : 1; break; } @@ -436,21 +437,7 @@ int action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume) int action_mv(int argc, char **argv, Pascal::VolumeEntry *volume) { // mv src dest - return 0; -} - -int action_cp(int argc, char **argv, Pascal::VolumeEntry *volume) -{ - // mv src dest - return 0; -} - -int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume) -{ - // rm file [file ....] - - bool tty = ::isatty(STDIN_FILENO); - bool fFlag = !tty; + bool iFlag = ::isatty(STDIN_FILENO); int c; while ((c = ::getopt(argc, argv, "fih")) != -1) @@ -458,10 +445,130 @@ int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume) switch(c) { case 'f': - fFlag = true; + iFlag = false; break; case 'i': - fFlag = false; + iFlag = true; + break; + + case 'h': + default: + commandUsage(kCommandMV); + return c == 'h' ? 0 : 1; + break; + } + } + + argc -= optind; + argv += optind; + + if (argc != 2) + { + commandUsage(kCommandMV); + return 1; + } + + const char *source = argv[0]; + const char *dest = argv[1]; + + if (!volume->fileByName(source)) + { + std::fprintf(stderr, "apfm mv: %s: no such file.\n", source); + return 1; + } + + // if -i and destination file exists, confirm overwritting it. + if (iFlag && volume->fileByName(dest)) + { + bool ok = yes_or_no("Overwrite %s?", dest); + if (!ok) + { + std::fprintf(stderr, "Not overwritten.\n"); + return 1; + } + } + + volume->rename(source, dest); + + return 0; +} + +int action_cp(int argc, char **argv, Pascal::VolumeEntry *volume) +{ + // cp src dest + + bool iFlag = ::isatty(STDIN_FILENO); + int c; + + while ((c = ::getopt(argc, argv, "fih")) != -1) + { + switch(c) + { + case 'f': + iFlag = false; + break; + case 'i': + iFlag = true; + break; + + case 'h': + default: + commandUsage(kCommandCP); + return c == 'h' ? 0 : 1; + break; + } + } + + argc -= optind; + argv += optind; + + if (argc != 2) + { + commandUsage(kCommandCP); + return 1; + } + + const char *source = argv[0]; + const char *dest = argv[1]; + + if (!volume->fileByName(source)) + { + std::fprintf(stderr, "apfm cp: %s: no such file.\n", source); + return 1; + } + + // if -i and destination file exists, confirm overwritting it. + if (iFlag && volume->fileByName(dest)) + { + bool ok = yes_or_no("Overwrite %s?", dest); + if (!ok) + { + std::fprintf(stderr, "Not overwritten.\n"); + return 1; + } + } + + volume->copy(source, dest); + + return 0; +} + +int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume) +{ + // rm file [file ....] + + bool iFlag = ::isatty(STDIN_FILENO); + int c; + + while ((c = ::getopt(argc, argv, "fih")) != -1) + { + switch(c) + { + case 'f': + iFlag = false; + break; + case 'i': + iFlag = true; break; case 'h': @@ -475,10 +582,23 @@ int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume) argc -= optind; argv += optind; - // TODO -- honor fFlag - // TODO -- catch errors. + // TODO -- catch errors ? for (unsigned i = 0; i < argc; ++i) { + Pascal::FileEntry *e = volume->fileByName(argv[i]); + + if (!e) + { + if (iFlag) std::fprintf(stderr, "apfm rm: %s: No such file.\n", argv[i]); + continue; + } + + if (iFlag) + { + bool ok = yes_or_no("Remove %s?", argv[i]); + if (!ok) continue; + } + volume->unlink(argv[i]); } return 0; @@ -489,8 +609,7 @@ int action_krunch(int argc, char **argv, Pascal::VolumeEntry *volume) { // compress file to remove gaps. - bool tty = ::isatty(STDIN_FILENO); - bool fFlag = !tty; + bool iFlag = ::isatty(STDIN_FILENO); int c; while ((c = ::getopt(argc, argv, "fih")) != -1) @@ -498,10 +617,10 @@ int action_krunch(int argc, char **argv, Pascal::VolumeEntry *volume) switch(c) { case 'f': - fFlag = true; + iFlag = false; break; case 'i': - fFlag = false; + iFlag = true; break; case 'h': @@ -515,8 +634,23 @@ int action_krunch(int argc, char **argv, Pascal::VolumeEntry *volume) argc -= optind; argv += optind; - //check if it needs krunching, volume->krunch(); + + if (!volume->canKrunch()) + { + if (iFlag) + std::fprintf(stderr, "apfm krunch: Volume already optimized.\n"); + + return 0; + } + + if (iFlag) + { + bool ok = yes_or_no("Are you sure you want to krunch this volume?"); + if (!ok) return 1; + } + + volume->krunch(); return 0; } @@ -529,8 +663,7 @@ int action_get(int argc, char **argv, Pascal::VolumeEntry *volume) char *infile; char *outfile; - bool tty = ::isatty(STDIN_FILENO); - bool fFlag = !tty; + bool iFlag = ::isatty(STDIN_FILENO); int c; while ((c = ::getopt(argc, argv, "fih")) != -1) @@ -538,10 +671,10 @@ int action_get(int argc, char **argv, Pascal::VolumeEntry *volume) switch(c) { case 'f': - fFlag = true; + iFlag = false; break; case 'i': - fFlag = false; + iFlag = true; break; case 'h': @@ -583,7 +716,7 @@ int action_get(int argc, char **argv, Pascal::VolumeEntry *volume) // if not -f, check before overwriting file. - if (!fFlag) + if (iFlag) { struct stat st; if (::stat(outfile, &st) == 0) From c4ea7cc0f8c38202acd96ea0b874762f91c3089f Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 30 May 2010 20:18:24 +0000 Subject: [PATCH 173/236] improve create(), rename(), unlink() git-svn-id: https://profuse.googlecode.com/svn/branches/v2@300 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/FileEntry.cpp | 5 +- Pascal/VolumeEntry.cpp | 307 +++++++++++++++++++++++++++++++++-------- Pascal/VolumeEntry.h | 12 +- 3 files changed, 257 insertions(+), 67 deletions(-) diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index 20ed478..590cb25 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -109,10 +109,9 @@ void FileEntry::setName(const char *name) for (unsigned i = 0; i < length; ++i) _fileName[i] = std::toupper(name[i]); - // not sure if this is a good idea or not. - //_modification = Date::Today(); - parent()->writeEntry(this); + // parent's responsibility. + //parent()->writeEntry(this); } unsigned FileEntry::fileSize() diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index 044744c..c221cc8 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -275,17 +275,26 @@ FileEntry *VolumeEntry::fileByName(const char *name) const return NULL; } -unsigned VolumeEntry::unlink(const char *name) +/* + * Remove a file. + * Returns 0 on succes, -1 (and errno) on failure. + * May also throw a device error. + */ +int VolumeEntry::unlink(const char *name) { unsigned index; std::vector::iterator iter; + + if (_device->readOnly()) + { + errno = EROFS; + return -1; + } - // TODO -- update _maxFileSize. + // TODO -- consider having an unordered_map of file names. - if (_device->readOnly()) return ProFUSE::drvrWrtProt; // WRITE-PROTECTED DISK - - for (index = 0, iter = _files.begin(); iter != _files.end(); ++iter, ++index) + for (iter = _files.begin(); iter != _files.end(); ++iter) { FileEntry *e = *iter; if (::strcasecmp(name, e->name()) == 0) @@ -304,12 +313,18 @@ unsigned VolumeEntry::unlink(const char *name) break; } } - if (iter == _files.end()) return ProFUSE::fileNotFound; // FILE NOT FOUND + if (iter == _files.end()) + { + errno = ENOENT; + return -1; + } _files.erase(iter); _fileCount--; + index = distance(_files.begin(), iter); + // reset addresses. for ( ; iter != _files.end(); ++iter) { @@ -339,35 +354,49 @@ unsigned VolumeEntry::unlink(const char *name) } -// TODO -- if newName exists, atomically remove it. -unsigned VolumeEntry::rename(const char *oldName, const char *newName) +/* + * Renames a file, removing any other file with newName (if present) + * Returns 0 on success, -1 on error (and sets errno) + * May also throw an error of some sort. + */ +int VolumeEntry::rename(const char *oldName, const char *newName) { FileEntry *e; - // 1. verify old name exists. + // check if read only. + if (_device->readOnly()) + { + errno = EROFS; + return -1; + } + + // verify file exists. e = fileByName(oldName); if (!e) - return ProFUSE::fileNotFound; + { + errno = ENOENT; + return -1; + } - // 2. verify new name is valid + // verify new name is valid. if (!FileEntry::ValidName(newName)) - return ProFUSE::badPathSyntax; + { + errno = EINVAL; // invalid name, at least. + return -1; + } + // delete the new file + if (unlink(newName) != 0) + { + if (errno != ENOENT) return -1; + } - // 3. verify new name does not exist. - - if (fileByName(newName)) - return ProFUSE::dupPathName; - - - // 4. set the name (throws on error, which won't happen since - // we already verified the name is valid. + // update with the new name. e->setName(newName); - - // 5. write to disk. + // and commit to disk. writeEntry(e); _cache->sync(); @@ -381,9 +410,36 @@ unsigned VolumeEntry::rename(const char *oldName, const char *newName) * if newName exists, delete it. * */ -unsigned VolumeEntry::copy(const char *oldName, const char *newName) +int VolumeEntry::copy(const char *oldName, const char *newName) { - + FileEntry * e; + // check if read only. + if (_device->readOnly()) + { + errno = EROFS; + return -1; + } + + // verify file exists. + e = fileByName(oldName); + if (!e) + { + errno = ENOENT; + return -1; + } + + + // verify new name is valid. + if (!FileEntry::ValidName(newName)) + { + errno = EINVAL; // invalid name, at least. + return -1; + } + + // if newName does not exist, call create w/ block size and write everything. + // if newName does exist, overwrite it if it will fit. Otherwise, remove it, create a file, etc. + + return 0; } @@ -391,6 +447,7 @@ unsigned VolumeEntry::copy(const char *oldName, const char *newName) /* * create a file. if blocks is defined, verifies the file could * expand to fit. + * returns FileEntry on success, NULL (and errno) on failure. * */ /* @@ -409,16 +466,18 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks) // 6. create the file entry. // 7. insert into _files, write to disk, update _maxFileSize - unsigned lastBlock; - unsigned maxBlocks; + unsigned lastBlock = _lastBlock; + std::auto_ptrentry; FileEntry *prev = NULL; FileEntry *curr = NULL; + std::vector::iterator iter; + if (readOnly()) { - errno = EACCES; + errno = EROFS; return NULL; } @@ -428,26 +487,10 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks) return NULL; } - if (_fileCount) - { - prev = _files.back(); - lastBlock = prev->_lastBlock; - } - else { - lastBlock = _lastBlock; - } - - maxBlocks = _lastVolumeBlock - lastBlock; - - if (maxBlocks < blocks || maxBlocks == 0) - { - errno = ENOSPC; - return NULL; - } if (!FileEntry::ValidName(name)) { - errno = ENAMETOOLONG; // or invalid. + errno = EINVAL; return NULL; } @@ -460,24 +503,107 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks) entry.reset(new FileEntry(name, kUntypedFile)); - _files.push_back(entry.get()); - - curr = entry.release(); - curr->_firstBlock = lastBlock; - curr->_lastBlock = lastBlock + 1; - curr->_lastByte = 0; - curr->_maxFileSize = maxBlocks * 512; - - if (prev) - { - prev->_maxFileSize = prev->blocks() * 512; + std::auto_ptr buffer(readDirectoryHeader()); + + for (iter = _files.begin(); iter != _files.end(); ++iter) + { + FileEntry *e = *iter; + + unsigned freeSpace = e->_firstBlock - _lastBlock; + // this could do something stupid like selecting a slot with only 1 free block but too bad. + + if (freeSpace < blocks) + { + lastBlock = e->_lastBlock; + prev = e; + continue; + } + + // update previous entry max file size. + if (prev) + { + prev->_maxFileSize = prev->blocks() * 512; + } + + // insert() inserts an item *before* the current item. + // afterwards, iter will point to curr+1 + + // keep track of the index *before* the insert. + unsigned index = distance(_files.begin(), iter); // current index. + + _files.insert(iter, entry.get()); + _fileCount++; + curr = entry.release(); + + curr->_firstBlock = lastBlock; + curr->_lastBlock = lastBlock + 1; + curr->_lastByte = 0; + curr->_maxFileSize = freeSpace * 512; + //curr->_address = 2 * 512 + 0x1a + 0x1a * index; + + // move all entries after this one up by 0x1a bytes, then write this header. + unsigned count = _fileCount - index - 1; + unsigned offset = index * 0x1a + 0x1a; + std::memmove(buffer.get() + offset + 0x1a, buffer.get() + offset, count * 0x1a); + break; } - writeEntry(curr); - + if (iter == _files.end()) + { + + // check if we can append + unsigned freeSpace = _lastVolumeBlock - lastBlock; + if (freeSpace < blocks) + { + errno = ENOSPC; + return NULL; + } + + _files.push_back(entry.get()); + _fileCount++; + + curr = entry.release(); + + curr->_firstBlock = lastBlock; + curr->_lastBlock = lastBlock + 1; + curr->_lastByte = 0; + curr->_maxFileSize = freeSpace * 512; + curr->_address = 2 * 512 + 0x1a * _fileCount; // s/b +1 since entry 0 is the header. + + if (prev) + { + prev->_maxFileSize = prev->blocks() * 512; + } + + writeEntry(curr); + writeEntry(); // header. + + } + else + { + + + // update all addresses to make life easier. + unsigned address = 2 * 512 + 0x1a; + for (iter = _files.begin(); iter != _files.end(); ++iter, address += 0x1a) + { + FileEntry *e = *iter; + e->_address = address; + } + + IOBuffer b(buffer.get(), 4 * 512); + writeDirectoryEntry(&b); + + b.setOffset(curr->_address - 2 * 512); + curr->writeDirectoryEntry(&b); + + writeDirectoryHeader(buffer.get()); + + } + + _cache->sync(); return curr; - } @@ -486,8 +612,15 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks) * TODO -- consider trying to move files from the end to fill gaps * if it would reduce the number of blocks that need to be re-arranged. * + * build a list of gaps, reverse iterate and move last file to first gap + * only 77 files, so can consider all options. + * + * + * + * + * */ -unsigned VolumeEntry::krunch() +int VolumeEntry::krunch() { unsigned prevBlock; @@ -619,6 +752,54 @@ unsigned VolumeEntry::freeBlocks(bool krunched) const } +/* + * return true if there are any gaps, false otherwise. + * + * + */ +bool VolumeEntry::canKrunch() const +{ + + std::vector::const_iterator iter; + + unsigned lastBlock = _lastBlock; + + for (iter = _files.begin(); iter != _files.end(); ++iter) + { + const FileEntry *e = *iter; + if (e->_lastBlock != lastBlock) return true; + lastBlock = e->_lastBlock; + } + + return false; +} + +/* + * returns the largest free block. + * + */ +unsigned VolumeEntry::maxContiguousBlocks() const +{ + unsigned max = 0; + + std::vector::const_iterator iter; + + unsigned lastBlock = _lastBlock; + + for (iter = _files.begin(); iter != _files.end(); ++iter) + { + const FileEntry *e = *iter; + unsigned free = e->_firstBlock - lastBlock; + max = std::max(max, free); + + lastBlock = e->_lastBlock; + } + + max = std::max(max, _lastVolumeBlock - lastBlock); + + return max; + +} @@ -693,6 +874,14 @@ void VolumeEntry::writeBlocks(void *buffer, unsigned startingBlock, unsigned cou } +// write directory entry, does not sync. +void VolumeEntry::writeEntry() +{ + IOBuffer iob(loadBlock(2),512); + writeDirectoryEntry(&iob); + unloadBlock(2, true); +} + // does not sync. void VolumeEntry::writeEntry(FileEntry *e) { diff --git a/Pascal/VolumeEntry.h b/Pascal/VolumeEntry.h index 689e081..8789841 100644 --- a/Pascal/VolumeEntry.h +++ b/Pascal/VolumeEntry.h @@ -32,6 +32,8 @@ namespace Pascal { Pascal::Date lastBoot() const { return _lastBoot; } unsigned freeBlocks(bool krunched = false) const; + unsigned maxContiguousBlocks() const; + bool canKrunch() const; FileEntry *fileAtIndex(unsigned i) const; @@ -48,14 +50,13 @@ namespace Pascal { bool readOnly() { return _device->readOnly(); } - unsigned unlink(const char *name); - unsigned rename(const char *oldName, const char *newName); - unsigned copy(const char *oldName, const char *newName); + int unlink(const char *name); + int rename(const char *oldName, const char *newName); + int copy(const char *oldName, const char *newName); FileEntry *create(const char *name, unsigned blocks); - - unsigned krunch(); + int krunch(); protected: @@ -77,6 +78,7 @@ namespace Pascal { void writeBlocks(void *buffer, unsigned startingBlock, unsigned count); void writeEntry(FileEntry *e); + void writeEntry(); void calcMaxFileSize(); From e2b20ccfbadbfdcdd808a64449568505d55031a5 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 30 May 2010 21:16:06 +0000 Subject: [PATCH 174/236] copy() git-svn-id: https://profuse.googlecode.com/svn/branches/v2@301 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/VolumeEntry.cpp | 65 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index c221cc8..b2cb768 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -412,7 +412,8 @@ int VolumeEntry::rename(const char *oldName, const char *newName) */ int VolumeEntry::copy(const char *oldName, const char *newName) { - FileEntry * e; + FileEntry *oldEntry; + FileEntry *newEntry; // check if read only. if (_device->readOnly()) { @@ -421,8 +422,8 @@ int VolumeEntry::copy(const char *oldName, const char *newName) } // verify file exists. - e = fileByName(oldName); - if (!e) + oldEntry = fileByName(oldName); + if (!oldEntry) { errno = ENOENT; return -1; @@ -439,6 +440,64 @@ int VolumeEntry::copy(const char *oldName, const char *newName) // if newName does not exist, call create w/ block size and write everything. // if newName does exist, overwrite it if it will fit. Otherwise, remove it, create a file, etc. + unsigned blocks = oldEntry->blocks(); + newEntry = fileByName(newName); + + if (newEntry) + { + // if newEntry is large enough, overwrite it. + if (newEntry->_maxFileSize >= blocks * 512) + { + if (newEntry->_pageSize) + { + delete newEntry->_pageSize; + newEntry->_pageSize = NULL; + newEntry->_fileSize = 0; + } + } + else + { + if (maxContiguousBlocks() < blocks) + { + errno = ENOSPC; + return -1; + } + + newEntry = NULL; + + if (unlink(newName) != 0) return -1; + } + } + + + if (newEntry == NULL) + { + // newName does not exist (or was just deleted), so create a new file (if possible) and write to it. + if (maxContiguousBlocks() < blocks) + { + errno = ENOSPC; + return -1; + } + + newEntry = create(newName, blocks); + + if (!newEntry) return -1; // create() sets errno. + + } + + newEntry->_fileKind = oldEntry->fileKind(); + newEntry->_lastByte = oldEntry->lastByte(); + newEntry->_lastBlock = newEntry->firstBlock() + blocks; + newEntry->_modification = Date::Today(); + + for (unsigned i = 0; i < blocks; i++) + { + void *src = loadBlock(oldEntry->firstBlock() + i); + _cache->write(newEntry->firstBlock() + i, src); + unloadBlock(oldEntry->firstBlock() + i, false); + } + + _cache->sync(); return 0; From e66058320fc3ed3a162b389ba382170a7b3fa821 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 30 May 2010 21:57:55 +0000 Subject: [PATCH 175/236] put git-svn-id: https://profuse.googlecode.com/svn/branches/v2@302 aa027e90-d47c-11dd-86d7-074df07e0730 --- apfm.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 8 deletions(-) diff --git a/apfm.cpp b/apfm.cpp index 9ac29a1..23402e6 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -752,7 +752,6 @@ int action_get(int argc, char **argv, Pascal::VolumeEntry *volume) return 0; } -#if 0 int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) { // put [-t type] native_file [pascal_file] @@ -765,12 +764,16 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) char *infile; char *outfile; char *tmp; + bool iFlag = ::isatty(STDIN_FILENO); + bool tFlag = false; - while ((c = getopt(argc, argv, "t:")) != -1) + while ((c = getopt(argc, argv, "fhit:")) != -1) { switch (c) { case 't': + tFlag = true; + if (!::strcasecmp("text", optarg)) type = Pascal::kTextFile; else if (!::strcasecmp("txt", optarg)) @@ -788,11 +791,21 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) else type = Pascal::kUntypedFile; break; + + case 'i': + iFlag = true; + break; + case 'f': + iFlag = false; + break; + case 'h': + default: + commandUsage(kCommandPUT); + return c == 'h' ? 0 : -1; } } - // TODO -- if file is named .txt or .text, default to kTextFile. argc -= optind; argv += optind; @@ -812,13 +825,35 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) break; } + + // if no tFlag specified, check .text/.txt + if (!tFlag) + { + tmp = strrchr(outfile, '.'); + if (tmp) + { + if (::strcasecmp(tmp, ".text") == 0 || strcasecmp(tmp, ".txt") == 0) + type = Pascal::kTextFile; + } + } + if (!Pascal::FileEntry::ValidName(outfile)) { std::fprintf(stderr, "apfm put: `%s' is not a valid pascal name.\n", outfile); } - ::stat(infile, &st); + if (::stat(infile, &st) != 0) + { + std::fprintf(stderr, "apfm put: %s: no such file.\n", infile); + return 1; + } + if (!S_ISREG(st.st_mode)) + { + std::fprintf(stderr, "apfm put: %s: not a regular file.\n", infile); + return -1; + } + File::File file(infile, O_RDONLY); @@ -826,9 +861,14 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) // TODO -- if text file, .. - Pascal::FileEntry *entry = volume.createFile(infile, blocks); + Pascal::FileEntry *entry = volume->create(infile, blocks); + if (!entry) + { + perror(NULL); + return -1; + } - entry->setType(type); + entry->setFileKind(type); if (type == Pascal::kTextFile) { @@ -836,14 +876,30 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) } else { - // ... + uint8_t buffer[512]; + unsigned remaining = st.st_size; + unsigned offset = 0; + while (remaining) + { + int rv; + unsigned count = std::min(512u, remaining); + ::read(file.fd(), buffer, count); + rv = entry->write(buffer, count, offset); + if (rv == -1) + { + perror(NULL); + return -1; + } + offset += count; + remaining -= count; + } } + volume->sync(); return 0; } -#endif From e3d0514c85703c3a789c62d4386629ab5fc7a3bd Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 30 May 2010 21:58:06 +0000 Subject: [PATCH 176/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@303 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/FileEntry.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index 590cb25..5bf9bef 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -91,6 +91,13 @@ FileEntry::~FileEntry() void FileEntry::setFileKind(unsigned kind) { _fileKind = kind; + if (_pageSize) + { + delete _pageSize; + _fileSize = 0; + _pageSize = NULL; + } + parent()->writeEntry(this); } From f07a6ecd8b1262cec8772e49ea89c20a908e98ad Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 31 May 2010 00:06:51 +0000 Subject: [PATCH 177/236] text writing git-svn-id: https://profuse.googlecode.com/svn/branches/v2@304 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/FileEntry.cpp | 82 ++++++++++++++++++++++++++++----- Pascal/FileEntry.h | 6 ++- Pascal/TextWriter.cpp | 102 ++++++++++++++++++++++++++++++++++++++++++ Pascal/TextWriter.h | 37 +++++++++++++++ 4 files changed, 216 insertions(+), 11 deletions(-) create mode 100644 Pascal/TextWriter.cpp create mode 100644 Pascal/TextWriter.h diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index 5bf9bef..546bb5b 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -176,12 +177,21 @@ int FileEntry::truncate(unsigned newSize) if (fileKind() == kTextFile) { if (newSize) - throw ProFUSE::Exception(__METHOD__ ": unable to truncate text file."); + { + errno = EINVAL; + return -1; + } + newSize = 2; // text files have a 2-page scratch buffer for the editor. - if (_pageSize) _pageSize->clear(); + if (_pageSize) + { + _pageSize->clear(); + _fileSize = 0; + } } - truncateCommon(newSize); + if (truncateCommon(newSize) != 0) + return -1; _modification = Date::Today(); parent()->writeEntry(this); @@ -194,19 +204,22 @@ int FileEntry::truncate(unsigned newSize) * updates _lastByte and _lastBlock but does * not update _modification or commit to disk. */ -void FileEntry::truncateCommon(unsigned newSize) +int FileEntry::truncateCommon(unsigned newSize) { #undef __METHOD__ #define __METHOD__ "FileEntry::truncateCommon" unsigned currentSize = fileSize(); - if (newSize == currentSize) return; + if (newSize == currentSize) return 0; if (newSize > currentSize) { if (newSize > _maxFileSize) - throw ProFUSE::POSIXException(__METHOD__ ": Unable to expand file.", ENOSPC); + { + errno = ENOSPC; + return -1; + } unsigned remainder = newSize - currentSize; unsigned block = _lastBlock - 1; @@ -245,17 +258,65 @@ void FileEntry::truncateCommon(unsigned newSize) _lastByte = newSize % 512; if (_lastByte == 0) _lastByte = 512; + return 0; } +int FileEntry::write(TextWriter &text) +{ + unsigned blocks = text.blocks(); + + if (parent()->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); + parent()->writeBlock(_firstBlock + i, buffer); + + } + + _modification = Date::Today(); + _lastBlock = 1 + firstBlock() + blocks; + _lastByte = 512; + + parent()->writeEntry(this); + parent()->sync(); + + return blocks * 512; +} + int FileEntry::write(uint8_t *buffer, unsigned size, unsigned offset) { #undef __METHOD__ #define __METHOD__ "FileEntry::write" + if (parent()->readOnly()) + { + errno = EROFS; + return -1; + } + if (fileKind() == kTextFile) { - throw ProFUSE::Exception(__METHOD__ ": Text Files are too weird."); + errno = EINVAL; + return -1; } unsigned currentSize = fileSize(); @@ -265,17 +326,18 @@ int FileEntry::write(uint8_t *buffer, unsigned size, unsigned offset) if (newSize > _maxFileSize) { - throw ProFUSE::POSIXException(__METHOD__ ": Unable to expand file.", ENOSPC); + errno = ENOSPC; + return -1; } if (offset > currentSize) { - truncateCommon(offset); + if (truncateCommon(offset) != 0) return -1; } // now write the data... - unsigned block = _firstBlock + offset / 512; + unsigned block = firstBlock() + offset / 512; unsigned start = offset % 512; unsigned remainder = size; diff --git a/Pascal/FileEntry.h b/Pascal/FileEntry.h index 8774398..d5b0eab 100644 --- a/Pascal/FileEntry.h +++ b/Pascal/FileEntry.h @@ -8,6 +8,8 @@ namespace Pascal { + class TextWriter; + class FileEntry : public Entry { public: @@ -38,6 +40,8 @@ namespace Pascal { int read(uint8_t *buffer, unsigned size, unsigned offset); int write(uint8_t *buffer, unsigned size, unsigned offset); + int write(TextWriter& text); + int truncate(unsigned newSize); @@ -52,7 +56,7 @@ namespace Pascal { void setName(const char *name); - void truncateCommon(unsigned newSize); + int truncateCommon(unsigned newSize); diff --git a/Pascal/TextWriter.cpp b/Pascal/TextWriter.cpp new file mode 100644 index 0000000..dff4a79 --- /dev/null +++ b/Pascal/TextWriter.cpp @@ -0,0 +1,102 @@ + +#include +#include + +#include + +#include +#include + +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::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; + if (( block >> 1 ) < _blocks.size()) + { + return _blocks[block >> 1] + offset; + } + if (block == _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 ProFUSE::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; +} \ No newline at end of file diff --git a/Pascal/TextWriter.h b/Pascal/TextWriter.h new file mode 100644 index 0000000..23d0902 --- /dev/null +++ b/Pascal/TextWriter.h @@ -0,0 +1,37 @@ + +#ifndef __PASCAL_TEXTWRITER_H__ +#define __PASCAL_TEXTWRITER_H__ + +#include +#include + +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 _blocks; + unsigned _offset; + + uint8_t *_current; + + }; + +} + + +#endif \ No newline at end of file From 756dd6b7699eb4f46bc22fc5ed1c26dda7ecdee0 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 31 May 2010 00:07:02 +0000 Subject: [PATCH 178/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@305 aa027e90-d47c-11dd-86d7-074df07e0730 --- File/File.cpp | 7 +++++++ File/File.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/File/File.cpp b/File/File.cpp index 251ea72..4cc41db 100644 --- a/File/File.cpp +++ b/File/File.cpp @@ -79,6 +79,13 @@ File::~File() close(); } +int File::release() +{ + int tmp = _fd; + _fd = -1; + return tmp; +} + void File::close() { #undef __METHOD__ diff --git a/File/File.h b/File/File.h index 72bb532..c926c3a 100644 --- a/File/File.h +++ b/File/File.h @@ -39,6 +39,8 @@ class File { int fd() const { return _fd; } + int release(); + void close(); void adopt(File &f); From 3d8bed44b3feb23128c3522af0443243753624a9 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 31 May 2010 00:07:17 +0000 Subject: [PATCH 179/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@306 aa027e90-d47c-11dd-86d7-074df07e0730 --- apfm.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/apfm.cpp b/apfm.cpp index 23402e6..05f81fe 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -21,9 +21,12 @@ #include #include +#include + #include #include +#include enum commands { @@ -854,28 +857,68 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) return -1; } - File::File file(infile, O_RDONLY); + File file(infile, File::ReadOnly); unsigned blocks = (st.st_size + 511) / 511; - // TODO -- if text file, .. - - Pascal::FileEntry *entry = volume->create(infile, blocks); - if (!entry) - { - perror(NULL); - return -1; - } - - entry->setFileKind(type); + if (type == Pascal::kTextFile) { - //... + Pascal::TextWriter text; + + MappedFile mf(file, File::ReadOnly, st.st_size); + + const char *address = (const char *)mf.address(); + + unsigned start = 0; + unsigned length = st.st_size; + + for (unsigned i = 0; i < length; ++i) + { + char c = address[i]; + if (c == 0x0d || c == 0x0a) + { + text.writeLine(address + start, i - start); + start = i + 1; + + if (c == 0x0a && i < length && address[i +1 ] == 0x0d) + { + ++start; + ++i; + } + } + } + + //any remainder. + if (start != length) text.writeLine(address + start, length - start); + + blocks = text.blocks(); + + Pascal::FileEntry *entry = volume->create(infile, blocks); + if (!entry) + { + perror(NULL); + return -1; + } + + entry->setFileKind(type); + entry->write(text); + } else { + Pascal::FileEntry *entry = volume->create(infile, blocks); + if (!entry) + { + perror(NULL); + return -1; + } + + entry->setFileKind(type); + + uint8_t buffer[512]; unsigned remaining = st.st_size; unsigned offset = 0; From 1b0f3ba4f5b9ba9b5edb07abc303cec7496f3a4c Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 31 May 2010 00:13:56 +0000 Subject: [PATCH 180/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@307 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/BlockCache.cpp | 2 -- Device/RawDevice.cpp | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Cache/BlockCache.cpp b/Cache/BlockCache.cpp index f9327fa..b6670b5 100644 --- a/Cache/BlockCache.cpp +++ b/Cache/BlockCache.cpp @@ -22,8 +22,6 @@ using namespace Device; using ProFUSE::Exception; using ProFUSE::POSIXException; -#pragma mark - -#pragma mark BlockCache BlockCache::BlockCache(BlockDevice *device) { diff --git a/Device/RawDevice.cpp b/Device/RawDevice.cpp index 7c9dbc4..11c1494 100644 --- a/Device/RawDevice.cpp +++ b/Device/RawDevice.cpp @@ -188,7 +188,7 @@ void RawDevice::read(unsigned block, void *bp) // apple - read full native block(s) ? off_t offset = block * 512; - size_t ok = ::pread(_file.fd(), bp, 512, offset); + ssize_t ok = ::pread(_file.fd(), bp, 512, offset); // TODO -- EINTR? if (ok != 512) @@ -211,7 +211,7 @@ void RawDevice::read(TrackSector ts, void *bp) // apple - read full native block(s) ? off_t offset = (ts.track * 16 + ts.sector) * 256; - size_t ok = ::pread(_file.fd(), bp, 256, offset); + ssize_t ok = ::pread(_file.fd(), bp, 256, offset); // TODO -- EINTR? if (ok != 256) @@ -233,7 +233,7 @@ void RawDevice::write(unsigned block, const void *bp) off_t offset = block * 512; - size_t ok = ::pwrite(_file.fd(), bp, 512, offset); + ssize_t ok = ::pwrite(_file.fd(), bp, 512, offset); if (ok != 512) throw ok < 0 @@ -255,7 +255,7 @@ void RawDevice::write(TrackSector ts, const void *bp) off_t offset = (ts.track * 16 + ts.sector) * 256; - size_t ok = ::pwrite(_file.fd(), bp, 256, offset); + ssize_t ok = ::pwrite(_file.fd(), bp, 256, offset); if (ok != 256) throw ok < 0 From 911ca8637d474d720ddb3a4a7ded4495c67f092f Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 31 May 2010 00:17:49 +0000 Subject: [PATCH 181/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@308 aa027e90-d47c-11dd-86d7-074df07e0730 --- apfm.cpp | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/apfm.cpp b/apfm.cpp index 05f81fe..0644ce0 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -400,7 +400,7 @@ int action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume) if (argc < 1) { commandUsage(kCommandCAT); - return 1; + return -1; } for (unsigned i = 0; i < argc; ++i) @@ -468,7 +468,7 @@ int action_mv(int argc, char **argv, Pascal::VolumeEntry *volume) if (argc != 2) { commandUsage(kCommandMV); - return 1; + return -1; } const char *source = argv[0]; @@ -477,7 +477,7 @@ int action_mv(int argc, char **argv, Pascal::VolumeEntry *volume) if (!volume->fileByName(source)) { std::fprintf(stderr, "apfm mv: %s: no such file.\n", source); - return 1; + return -1; } // if -i and destination file exists, confirm overwritting it. @@ -487,7 +487,7 @@ int action_mv(int argc, char **argv, Pascal::VolumeEntry *volume) if (!ok) { std::fprintf(stderr, "Not overwritten.\n"); - return 1; + return -1; } } @@ -528,7 +528,7 @@ int action_cp(int argc, char **argv, Pascal::VolumeEntry *volume) if (argc != 2) { commandUsage(kCommandCP); - return 1; + return -1; } const char *source = argv[0]; @@ -537,7 +537,7 @@ int action_cp(int argc, char **argv, Pascal::VolumeEntry *volume) if (!volume->fileByName(source)) { std::fprintf(stderr, "apfm cp: %s: no such file.\n", source); - return 1; + return -1; } // if -i and destination file exists, confirm overwritting it. @@ -547,7 +547,7 @@ int action_cp(int argc, char **argv, Pascal::VolumeEntry *volume) if (!ok) { std::fprintf(stderr, "Not overwritten.\n"); - return 1; + return -1; } } @@ -650,7 +650,7 @@ int action_krunch(int argc, char **argv, Pascal::VolumeEntry *volume) if (iFlag) { bool ok = yes_or_no("Are you sure you want to krunch this volume?"); - if (!ok) return 1; + if (!ok) return -1; } volume->krunch(); @@ -683,7 +683,7 @@ int action_get(int argc, char **argv, Pascal::VolumeEntry *volume) case 'h': default: commandUsage(kCommandGET); - return c == 'h' ? 0 : 1; + return c == 'h' ? 0 : -1; break; } } @@ -704,7 +704,7 @@ int action_get(int argc, char **argv, Pascal::VolumeEntry *volume) break; default: commandUsage(kCommandGET); - return 1; + return -1; break; } @@ -714,7 +714,7 @@ int action_get(int argc, char **argv, Pascal::VolumeEntry *volume) if (!entry) { std::fprintf(stderr, "apfm get: %s: no such file.\n", infile); - return 1; + return -1; } @@ -728,7 +728,7 @@ int action_get(int argc, char **argv, Pascal::VolumeEntry *volume) if (!ok) { std::fprintf(stderr, "Not overwritten.\n"); - return 1; + return -1; } } @@ -805,6 +805,7 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) default: commandUsage(kCommandPUT); return c == 'h' ? 0 : -1; + break; } } @@ -826,6 +827,10 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) infile = argv[0]; outfile = argv[1]; break; + default: + commandUsage(kCommandPUT); + return -1; + break; } @@ -848,7 +853,7 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) if (::stat(infile, &st) != 0) { std::fprintf(stderr, "apfm put: %s: no such file.\n", infile); - return 1; + return -1; } if (!S_ISREG(st.st_mode)) From 6a4e4f4f7fa9ecebcc8232fa276eb5d5340c4c61 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 31 May 2010 00:35:17 +0000 Subject: [PATCH 182/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@309 aa027e90-d47c-11dd-86d7-074df07e0730 --- apfm.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apfm.cpp b/apfm.cpp index 0644ce0..664f186 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -1051,11 +1051,10 @@ int main(int argc, char **argv) case kCommandGET: return action_get(argc -1, argv + 1, volume.get()); break; - /* case kCommandPUT: return action_put(argc -1, argv + 1, volume.get()); break; - */ + } usage(); return 3; From f81205b63f198cfc3073e2620d674913a3e2908d Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 31 May 2010 00:35:33 +0000 Subject: [PATCH 183/236] set _parent in create() git-svn-id: https://profuse.googlecode.com/svn/branches/v2@310 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/VolumeEntry.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index b2cb768..af04348 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -595,6 +595,7 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks) _fileCount++; curr = entry.release(); + curr->_parent = this; curr->_firstBlock = lastBlock; curr->_lastBlock = lastBlock + 1; curr->_lastByte = 0; @@ -624,6 +625,7 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks) curr = entry.release(); + curr->_parent = this; curr->_firstBlock = lastBlock; curr->_lastBlock = lastBlock + 1; curr->_lastByte = 0; From 96f1de72066316792fa239d20c9b78be623625a8 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 31 May 2010 15:26:03 +0000 Subject: [PATCH 184/236] fix compression, add setFileSize() git-svn-id: https://profuse.googlecode.com/svn/branches/v2@311 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/FileEntry.cpp | 45 ++++++++++++++++++++++++++++++-------------- Pascal/FileEntry.h | 4 ++-- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index 546bb5b..351214a 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -254,9 +254,7 @@ int FileEntry::truncateCommon(unsigned newSize) } - _lastBlock = 1 + _firstBlock + newSize / 512; - _lastByte = newSize % 512; - if (_lastByte == 0) _lastByte = 512; + setFileSize(newSize); return 0; } @@ -293,8 +291,8 @@ int FileEntry::write(TextWriter &text) } _modification = Date::Today(); - _lastBlock = 1 + firstBlock() + blocks; - _lastByte = 512; + + setFileSize(blocks * 512); parent()->writeEntry(this); parent()->sync(); @@ -302,7 +300,7 @@ int FileEntry::write(TextWriter &text) return blocks * 512; } -int FileEntry::write(uint8_t *buffer, unsigned size, unsigned offset) +int FileEntry::write(const uint8_t *buffer, unsigned size, unsigned offset) { #undef __METHOD__ #define __METHOD__ "FileEntry::write" @@ -368,13 +366,9 @@ int FileEntry::write(uint8_t *buffer, unsigned size, unsigned offset) block++; } - if (newSize > currentSize) - { - _lastBlock = 1 + _firstBlock + currentSize / 512; - _lastByte = currentSize % 512; - if (_lastByte == 0) _lastByte = 512; - - } + + if (newSize > currentSize) setFileSize(newSize); + _modification = Date::Today(); parent()->writeEntry(this); @@ -383,6 +377,26 @@ int FileEntry::write(uint8_t *buffer, unsigned size, unsigned offset) } +/* + * 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; @@ -633,12 +647,14 @@ bool FileEntry::Compress(std::string& text) if (count < 3) return false; - count = std::max((int)count, 255 - 32); + 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; } @@ -662,6 +678,7 @@ bool FileEntry::Uncompress(std::string& text) out.append(c - 32, ' '); out.append(text.begin() + 2, text.end()); + text.swap(out); return true; } diff --git a/Pascal/FileEntry.h b/Pascal/FileEntry.h index d5b0eab..721e80e 100644 --- a/Pascal/FileEntry.h +++ b/Pascal/FileEntry.h @@ -38,7 +38,7 @@ namespace Pascal { void setFileKind(unsigned kind); int read(uint8_t *buffer, unsigned size, unsigned offset); - int write(uint8_t *buffer, unsigned size, unsigned offset); + int write(const uint8_t *buffer, unsigned size, unsigned offset); int write(TextWriter& text); @@ -58,7 +58,7 @@ namespace Pascal { int truncateCommon(unsigned newSize); - + void setFileSize(unsigned size); unsigned _status; From 7a327fb0244f253050ec33ff3cb9977488139a7e Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 31 May 2010 15:27:26 +0000 Subject: [PATCH 185/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@312 aa027e90-d47c-11dd-86d7-074df07e0730 --- apfm.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/apfm.cpp b/apfm.cpp index 664f186..3254c17 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -861,11 +861,20 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) std::fprintf(stderr, "apfm put: %s: not a regular file.\n", infile); return -1; } - + + unsigned blocks = (st.st_size + 511) / 512; + if (blocks > (0xffff - 6)) + { + std::fprintf(stderr, "apfm put: %s: file is too large.\n", infile); + return -1; + } + + + File file(infile, File::ReadOnly); + MappedFile mf(file, File::ReadOnly, st.st_size); - unsigned blocks = (st.st_size + 511) / 511; @@ -873,7 +882,6 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) { Pascal::TextWriter text; - MappedFile mf(file, File::ReadOnly, st.st_size); const char *address = (const char *)mf.address(); @@ -901,7 +909,7 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) blocks = text.blocks(); - Pascal::FileEntry *entry = volume->create(infile, blocks); + Pascal::FileEntry *entry = volume->create(outfile, blocks); if (!entry) { perror(NULL); @@ -914,7 +922,7 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) } else { - Pascal::FileEntry *entry = volume->create(infile, blocks); + Pascal::FileEntry *entry = volume->create(outfile, blocks); if (!entry) { perror(NULL); @@ -922,17 +930,16 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) } entry->setFileKind(type); - - - uint8_t buffer[512]; + unsigned remaining = st.st_size; unsigned offset = 0; + const uint8_t *address = (const uint8_t *)mf.address(); while (remaining) { int rv; unsigned count = std::min(512u, remaining); - ::read(file.fd(), buffer, count); - rv = entry->write(buffer, count, offset); + + rv = entry->write(address + offset, count, offset); if (rv == -1) { perror(NULL); From 79d8352018fa0dcc6db4f14ee0bf91a68dbd18b1 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 31 May 2010 16:03:26 +0000 Subject: [PATCH 186/236] fix data() git-svn-id: https://profuse.googlecode.com/svn/branches/v2@313 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/TextWriter.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Pascal/TextWriter.cpp b/Pascal/TextWriter.cpp index dff4a79..309f4f4 100644 --- a/Pascal/TextWriter.cpp +++ b/Pascal/TextWriter.cpp @@ -42,11 +42,13 @@ unsigned TextWriter::blocks() const void *TextWriter::data(unsigned block) const { unsigned offset = (block & 0x01) * 512; - if (( block >> 1 ) < _blocks.size()) + unsigned halfBlock = block >> 1; + + if (halfBlock < _blocks.size()) { - return _blocks[block >> 1] + offset; + return _blocks[halfBlock] + offset; } - if (block == _blocks.size()) + if (halfBlock == _blocks.size()) { if (offset > _offset) return NULL; return _current + offset; @@ -83,8 +85,8 @@ void TextWriter::writeLine(const char *line, unsigned length) text.push_back(0x0d); } - length = text.length(); + if (length > 1024) { throw ProFUSE::Exception(__METHOD__ ": String is too long."); From fedcc06840e581d970b1bf9881fa1ba66114e3ea Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 31 May 2010 16:03:35 +0000 Subject: [PATCH 187/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@314 aa027e90-d47c-11dd-86d7-074df07e0730 --- apfm.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apfm.cpp b/apfm.cpp index 3254c17..77c3a3f 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -893,6 +893,7 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) char c = address[i]; if (c == 0x0d || c == 0x0a) { + //std::fprintf(stdout, "%.*s\n", i - start, address + start); text.writeLine(address + start, i - start); start = i + 1; From 345927d4b20cc7bcbc16ca9cf21b389019ebd371 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 31 May 2010 17:54:45 +0000 Subject: [PATCH 188/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@315 aa027e90-d47c-11dd-86d7-074df07e0730 --- apfm.cpp | 2 +- newfs_pascal.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apfm.cpp b/apfm.cpp index 77c3a3f..e8dad48 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -586,7 +586,7 @@ int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume) argv += optind; // TODO -- catch errors ? - for (unsigned i = 0; i < argc; ++i) + for (int i = 0; i < argc; ++i) { Pascal::FileEntry *e = volume->fileByName(argv[i]); diff --git a/newfs_pascal.cpp b/newfs_pascal.cpp index 3829f69..28f3736 100644 --- a/newfs_pascal.cpp +++ b/newfs_pascal.cpp @@ -176,14 +176,14 @@ int main(int argc, char **argv) break; case 'f': + format = Device::BlockDevice::ImageType(optarg); + if (format == 0) { - format = Device::BlockDevice::ImageType(optarg); - if (format == 0) - { - std::fprintf(stderr, "Error: `%s' is not a supported disk image format.\n", optarg); - return -1; - } + std::fprintf(stderr, "Error: `%s' is not a supported disk image format.\n", optarg); + return -1; } + break; + case 'b': bootFile = optarg; break; From 1894a178d156c802ab7638ecf0532ee42764268c Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 31 May 2010 19:51:50 +0000 Subject: [PATCH 189/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@316 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/RawDevice.cpp | 30 ++++++++++++++++++++++++++++-- Device/RawDevice.h | 6 +++--- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/Device/RawDevice.cpp b/Device/RawDevice.cpp index 11c1494..2056311 100644 --- a/Device/RawDevice.cpp +++ b/Device/RawDevice.cpp @@ -25,6 +25,10 @@ #include #endif +#ifdef __minix +#include +#endif + #include #include @@ -105,7 +109,7 @@ void RawDevice::devSize(int fd) #undef __METHOD__ #define __METHOD__ "RawDevice::devSize" - unisgned blockSize; + unsigned blockSize; off_t mediaSize; if (::ioctl(fd, DIOCGSECTORSIZE, &blockSize) @@ -116,11 +120,33 @@ void RawDevice::devSize(int fd) _blockSize = blockSize; _size = mediaSize; - _blocks = mediaSize / blockSize; + _blocks = mediaSize / 512; } #endif + + +#ifdef __minix + +void RawDevice::devSize(int fd) +{ +#undef __METHOD__ +#define __METHOD__ "RawDevice::devSize" + + struct partition entry; + + + if (::ioctl(fd, DIOCGETP, &entry) < 0) + throw POSIXException(__METHOD__ ": Unable to determine device size.", errno); + + _size = entry.size + _blockSize = 512; // not really but whatever. + _blocks = _size / 512; + +} + +#endif RawDevice::RawDevice(const char *name, File::FileFlags flags) : _file(name, flags) diff --git a/Device/RawDevice.h b/Device/RawDevice.h index 573ab94..2b036cc 100644 --- a/Device/RawDevice.h +++ b/Device/RawDevice.h @@ -46,10 +46,10 @@ private: File _file; bool _readOnly; - uint64_t _size; - unsigned _blocks; + uint64_t _size; // size of device in bytes. + unsigned _blocks; // # of 512k blocks i.e. _size / 512 - unsigned _blockSize; + unsigned _blockSize; // native block size. }; } From cd1e227fc5721e86b71e384a19ce021ad0a05b98 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 26 Jun 2010 03:31:16 +0000 Subject: [PATCH 190/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@317 aa027e90-d47c-11dd-86d7-074df07e0730 --- PROFuseX.xcodeproj/kelvin.pbxuser | 2127 +++-------------- PROFuseX.xcodeproj/kelvin.perspectivev3 | 76 +- PROFuseX.xcodeproj/project.pbxproj | 131 + Pascal/VolumeEntry.cpp | 31 +- apfm.cpp => bin/apfm.cpp | 0 fuse_pascal.cpp => bin/fuse_pascal.cpp | 0 .../fuse_pascal_ops.cpp | 0 newfs_pascal.cpp => bin/newfs_pascal.cpp | 0 xattr.cpp => bin/xattr.cpp | 0 newfs_prodos.cpp | 13 +- 10 files changed, 498 insertions(+), 1880 deletions(-) rename apfm.cpp => bin/apfm.cpp (100%) rename fuse_pascal.cpp => bin/fuse_pascal.cpp (100%) rename fuse_pascal_ops.cpp => bin/fuse_pascal_ops.cpp (100%) rename newfs_pascal.cpp => bin/newfs_pascal.cpp (100%) rename xattr.cpp => bin/xattr.cpp (100%) diff --git a/PROFuseX.xcodeproj/kelvin.pbxuser b/PROFuseX.xcodeproj/kelvin.pbxuser index 4461775..db35621 100644 --- a/PROFuseX.xcodeproj/kelvin.pbxuser +++ b/PROFuseX.xcodeproj/kelvin.pbxuser @@ -5,16 +5,10 @@ activeExecutable = B63EFE8211A4886C00C90DCE /* newfs_pascal */; activeTarget = B63EFE8011A4886C00C90DCE /* newfs_pascal */; addToTargets = ( - B63EFCCD11A36C7300C90DCE /* apfm */, - B63EFE8011A4886C00C90DCE /* newfs_pascal */, - B656AE0211A84F5800AB578A /* fuse_pascal */, - B656AF0211AA105500AB578A /* NibbleTest */, ); breakpoints = ( B6F3642F11AA1E150045E114 /* NibbleTest.cpp:76 */, - B6F3657711AE24C40045E114 /* apfm.cpp:470 */, - B6F3659B11AE27760045E114 /* VolumeEntry.cpp:300 */, - B6F3659E11AE27790045E114 /* VolumeEntry.cpp:311 */, + B6F3657711AE24C40045E114 /* apfm.cpp:589 */, B6F3663D11B1809A0045E114 /* Adaptor.cpp:167 */, ); codeSenseManager = B63EFA6811A093C200C90DCE /* Code sense */; @@ -24,6 +18,7 @@ B656AE0411A84F5800AB578A /* fuse_pascal */, B656AF0411AA105500AB578A /* NibbleTest */, B6F3648111AB36260045E114 /* xattr */, + B6F3682611B431AC0045E114 /* newfs_prodos */, ); perUserDictionary = { "PBXConfiguration.PBXBreakpointsDataSource.v1:1CA1AED706398EBD00589147" = { @@ -69,7 +64,7 @@ PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_ObjectSize_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, - 660, + 10, 20, 48, 43, @@ -108,16 +103,12 @@ PBXFileDataSource_Warnings_ColumnID, ); }; - PBXPerProjectTemplateStateSaveDate = 296433132; - PBXWorkspaceStateSaveDate = 296433132; + PBXPerProjectTemplateStateSaveDate = 299215102; + PBXWorkspaceStateSaveDate = 299215102; }; perUserProjectItems = { B63EFC2611A2D5A400C90DCE = B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */; - B63EFC2B11A2D5A400C90DCE = B63EFC2B11A2D5A400C90DCE /* PBXTextBookmark */; B63EFC3211A2D5A400C90DCE = B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */; - B63EFCB211A3639400C90DCE = B63EFCB211A3639400C90DCE /* PBXTextBookmark */; - B63EFCB611A3639400C90DCE = B63EFCB611A3639400C90DCE /* PBXTextBookmark */; - B63EFD7F11A4436B00C90DCE = B63EFD7F11A4436B00C90DCE /* PBXTextBookmark */; B63EFDA011A4488200C90DCE = B63EFDA011A4488200C90DCE /* PBXTextBookmark */; B63EFDA511A4488200C90DCE = B63EFDA511A4488200C90DCE /* PBXTextBookmark */; B63EFDA711A4488200C90DCE = B63EFDA711A4488200C90DCE /* PBXTextBookmark */; @@ -128,187 +119,52 @@ B63EFDB111A4488200C90DCE = B63EFDB111A4488200C90DCE /* PBXTextBookmark */; B63EFDB311A4488200C90DCE = B63EFDB311A4488200C90DCE /* PBXTextBookmark */; B63EFDB711A4488200C90DCE = B63EFDB711A4488200C90DCE /* PBXTextBookmark */; - B63EFDC711A4494C00C90DCE = B63EFDC711A4494C00C90DCE /* PBXTextBookmark */; - B63EFDE611A44E9300C90DCE = B63EFDE611A44E9300C90DCE /* PBXTextBookmark */; B63EFDF211A4504200C90DCE = B63EFDF211A4504200C90DCE /* PBXTextBookmark */; B63EFEA011A488C200C90DCE = B63EFEA011A488C200C90DCE /* PBXTextBookmark */; B63EFEA111A488C200C90DCE = B63EFEA111A488C200C90DCE /* PBXTextBookmark */; - B63EFEA211A488C200C90DCE = B63EFEA211A488C200C90DCE /* PBXTextBookmark */; - B63EFEA311A488C200C90DCE = B63EFEA311A488C200C90DCE /* PBXTextBookmark */; - B63EFEA711A488C200C90DCE = B63EFEA711A488C200C90DCE /* PBXTextBookmark */; B63EFEA811A488C200C90DCE = B63EFEA811A488C200C90DCE /* PBXTextBookmark */; - B63EFEA911A488C200C90DCE = B63EFEA911A488C200C90DCE /* PBXTextBookmark */; - B63EFEEC11A4A70400C90DCE = B63EFEEC11A4A70400C90DCE /* PBXTextBookmark */; - B656AE2311A84FA400AB578A = B656AE2311A84FA400AB578A /* PBXTextBookmark */; B656AE2411A84FA400AB578A = B656AE2411A84FA400AB578A /* PBXTextBookmark */; B656AE2611A84FA400AB578A = B656AE2611A84FA400AB578A /* PBXTextBookmark */; - B656AE2711A84FA400AB578A = B656AE2711A84FA400AB578A /* PBXTextBookmark */; - B656AE6511A8591F00AB578A = B656AE6511A8591F00AB578A /* PBXTextBookmark */; - B656AEA711A9C91600AB578A = B656AEA711A9C91600AB578A /* PBXTextBookmark */; - B656AEA811A9C91600AB578A = B656AEA811A9C91600AB578A /* PBXTextBookmark */; - B656AF2711AA10C900AB578A = B656AF2711AA10C900AB578A /* PBXTextBookmark */; - B656AF2811AA10C900AB578A = B656AF2811AA10C900AB578A /* PBXTextBookmark */; - B656AF2A11AA10C900AB578A = B656AF2A11AA10C900AB578A /* PBXTextBookmark */; + B65CFB6911B495790024A2D9 = B65CFB6911B495790024A2D9 /* PBXTextBookmark */; + B65CFB6A11B495790024A2D9 = B65CFB6A11B495790024A2D9 /* PBXTextBookmark */; + B65CFB6B11B495790024A2D9 = B65CFB6B11B495790024A2D9 /* PBXTextBookmark */; + B65CFB8811B5C8310024A2D9 = B65CFB8811B5C8310024A2D9 /* PBXTextBookmark */; B6E5F0DD11A60726000AD141 = B6E5F0DD11A60726000AD141 /* PBXTextBookmark */; B6E5F0F211A73144000AD141 = B6E5F0F211A73144000AD141 /* PBXTextBookmark */; B6E5F11211A73340000AD141 = B6E5F11211A73340000AD141 /* PBXTextBookmark */; B6E5F13A11A74F2B000AD141 = B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */; - B6E5F18111A76B74000AD141 = B6E5F18111A76B74000AD141 /* PBXTextBookmark */; B6E5F18211A76B74000AD141 = B6E5F18211A76B74000AD141 /* PBXTextBookmark */; - B6F3642811AA1DC80045E114 = B6F3642811AA1DC80045E114 /* PBXTextBookmark */; - B6F3642D11AA1E070045E114 = B6F3642D11AA1E070045E114 /* PBXTextBookmark */; - B6F3646211AA26810045E114 = B6F3646211AA26810045E114 /* PBXTextBookmark */; - B6F3646E11AB35F00045E114 /* PBXTextBookmark */ = B6F3646E11AB35F00045E114 /* PBXTextBookmark */; - B6F3646F11AB35F00045E114 /* PBXBookmark */ = B6F3646F11AB35F00045E114 /* PBXBookmark */; - B6F3647011AB35F00045E114 /* PBXTextBookmark */ = B6F3647011AB35F00045E114 /* PBXTextBookmark */; - B6F3647111AB35FE0045E114 /* PBXTextBookmark */ = B6F3647111AB35FE0045E114 /* PBXTextBookmark */; - B6F3647211AB35FE0045E114 /* PBXTextBookmark */ = B6F3647211AB35FE0045E114 /* PBXTextBookmark */; - B6F3649411AB58E80045E114 /* PBXTextBookmark */ = B6F3649411AB58E80045E114 /* PBXTextBookmark */; - B6F3649511AB58E80045E114 /* PBXTextBookmark */ = B6F3649511AB58E80045E114 /* PBXTextBookmark */; - B6F3649611AB58E80045E114 /* PBXTextBookmark */ = B6F3649611AB58E80045E114 /* PBXTextBookmark */; - B6F3649711AB58E80045E114 /* XCBuildMessageTextBookmark */ = B6F3649711AB58E80045E114 /* XCBuildMessageTextBookmark */; - B6F3649811AB58E80045E114 /* PBXTextBookmark */ = B6F3649811AB58E80045E114 /* PBXTextBookmark */; - B6F3649E11AB59190045E114 /* PBXTextBookmark */ = B6F3649E11AB59190045E114 /* PBXTextBookmark */; - B6F3649F11AB59190045E114 /* XCBuildMessageTextBookmark */ = B6F3649F11AB59190045E114 /* XCBuildMessageTextBookmark */; - B6F364A011AB59190045E114 /* PBXTextBookmark */ = B6F364A011AB59190045E114 /* PBXTextBookmark */; - B6F364A511AB593E0045E114 /* PBXTextBookmark */ = B6F364A511AB593E0045E114 /* PBXTextBookmark */; - B6F364A911AB5EBD0045E114 /* PBXTextBookmark */ = B6F364A911AB5EBD0045E114 /* PBXTextBookmark */; - B6F364B111AB74F40045E114 /* XCBuildMessageTextBookmark */ = B6F364B111AB74F40045E114 /* XCBuildMessageTextBookmark */; - B6F364B211AB74F40045E114 /* PBXTextBookmark */ = B6F364B211AB74F40045E114 /* PBXTextBookmark */; - B6F364B611AB84840045E114 /* PBXTextBookmark */ = B6F364B611AB84840045E114 /* PBXTextBookmark */; - B6F364B711AB84840045E114 /* PBXTextBookmark */ = B6F364B711AB84840045E114 /* PBXTextBookmark */; - B6F364B811AB84840045E114 /* PBXTextBookmark */ = B6F364B811AB84840045E114 /* PBXTextBookmark */; - B6F364B911AB84840045E114 /* PBXTextBookmark */ = B6F364B911AB84840045E114 /* PBXTextBookmark */; - B6F364BE11AC92730045E114 /* PBXTextBookmark */ = B6F364BE11AC92730045E114 /* PBXTextBookmark */; - B6F364BF11AC92730045E114 /* XCBuildMessageTextBookmark */ = B6F364BF11AC92730045E114 /* XCBuildMessageTextBookmark */; - B6F364C011AC92730045E114 /* PBXTextBookmark */ = B6F364C011AC92730045E114 /* PBXTextBookmark */; - B6F364C811ACAB370045E114 /* PBXTextBookmark */ = B6F364C811ACAB370045E114 /* PBXTextBookmark */; - B6F364C911ACAB370045E114 /* PBXTextBookmark */ = B6F364C911ACAB370045E114 /* PBXTextBookmark */; - B6F364CA11ACAB370045E114 /* PBXTextBookmark */ = B6F364CA11ACAB370045E114 /* PBXTextBookmark */; - B6F364E811ACB5790045E114 /* PBXTextBookmark */ = B6F364E811ACB5790045E114 /* PBXTextBookmark */; - B6F364E911ACB5790045E114 /* XCBuildMessageTextBookmark */ = B6F364E911ACB5790045E114 /* XCBuildMessageTextBookmark */; - B6F364EB11ACB5790045E114 /* PBXTextBookmark */ = B6F364EB11ACB5790045E114 /* PBXTextBookmark */; - B6F364EC11ACB5790045E114 /* XCBuildMessageTextBookmark */ = B6F364EC11ACB5790045E114 /* XCBuildMessageTextBookmark */; - B6F364ED11ACB5790045E114 /* PBXTextBookmark */ = B6F364ED11ACB5790045E114 /* PBXTextBookmark */; - B6F364F511ACB5B60045E114 /* PBXTextBookmark */ = B6F364F511ACB5B60045E114 /* PBXTextBookmark */; - B6F364F811ACBA8E0045E114 /* PBXTextBookmark */ = B6F364F811ACBA8E0045E114 /* PBXTextBookmark */; - B6F364FD11ACBC470045E114 /* PBXTextBookmark */ = B6F364FD11ACBC470045E114 /* PBXTextBookmark */; - B6F3650011ACBC790045E114 /* PBXTextBookmark */ = B6F3650011ACBC790045E114 /* PBXTextBookmark */; - B6F3650111ACBC790045E114 /* PBXTextBookmark */ = B6F3650111ACBC790045E114 /* PBXTextBookmark */; - B6F3650211ACBC790045E114 /* PBXTextBookmark */ = B6F3650211ACBC790045E114 /* PBXTextBookmark */; - B6F3650511ACBCA40045E114 /* PBXTextBookmark */ = B6F3650511ACBCA40045E114 /* PBXTextBookmark */; - B6F3650611ACBCA40045E114 /* PBXTextBookmark */ = B6F3650611ACBCA40045E114 /* PBXTextBookmark */; - B6F3650911ACBCB30045E114 /* PBXTextBookmark */ = B6F3650911ACBCB30045E114 /* PBXTextBookmark */; - B6F3650E11ADC40E0045E114 /* PBXTextBookmark */ = B6F3650E11ADC40E0045E114 /* PBXTextBookmark */; - B6F3651111ADCA570045E114 /* PBXTextBookmark */ = B6F3651111ADCA570045E114 /* PBXTextBookmark */; - B6F3651211ADCA570045E114 /* PBXTextBookmark */ = B6F3651211ADCA570045E114 /* PBXTextBookmark */; - B6F3651311ADCA570045E114 /* PBXTextBookmark */ = B6F3651311ADCA570045E114 /* PBXTextBookmark */; - B6F3651511ADCA6C0045E114 /* PBXTextBookmark */ = B6F3651511ADCA6C0045E114 /* PBXTextBookmark */; - B6F3651611ADCA6C0045E114 /* PBXTextBookmark */ = B6F3651611ADCA6C0045E114 /* PBXTextBookmark */; - B6F3651711ADCA6C0045E114 /* PBXTextBookmark */ = B6F3651711ADCA6C0045E114 /* PBXTextBookmark */; - B6F3651811ADCA6C0045E114 /* PBXTextBookmark */ = B6F3651811ADCA6C0045E114 /* PBXTextBookmark */; - B6F3652E11ADD5D20045E114 /* PBXTextBookmark */ = B6F3652E11ADD5D20045E114 /* PBXTextBookmark */; - B6F3652F11ADD5D20045E114 /* PBXTextBookmark */ = B6F3652F11ADD5D20045E114 /* PBXTextBookmark */; - B6F3653011ADD5D20045E114 /* PBXTextBookmark */ = B6F3653011ADD5D20045E114 /* PBXTextBookmark */; - B6F3653111ADD5D20045E114 /* PBXTextBookmark */ = B6F3653111ADD5D20045E114 /* PBXTextBookmark */; - B6F3653211ADD5D20045E114 /* PBXTextBookmark */ = B6F3653211ADD5D20045E114 /* PBXTextBookmark */; - B6F3653311ADD5D20045E114 /* PBXTextBookmark */ = B6F3653311ADD5D20045E114 /* PBXTextBookmark */; - B6F3653411ADD5D20045E114 /* PBXTextBookmark */ = B6F3653411ADD5D20045E114 /* PBXTextBookmark */; - B6F3654311ADE1C20045E114 /* PBXTextBookmark */ = B6F3654311ADE1C20045E114 /* PBXTextBookmark */; - B6F3654411ADE1C20045E114 /* PBXTextBookmark */ = B6F3654411ADE1C20045E114 /* PBXTextBookmark */; - B6F3654511ADE1C20045E114 /* PBXTextBookmark */ = B6F3654511ADE1C20045E114 /* PBXTextBookmark */; - B6F3654711ADE3680045E114 /* PBXTextBookmark */ = B6F3654711ADE3680045E114 /* PBXTextBookmark */; - B6F3654C11AE03E00045E114 /* PBXTextBookmark */ = B6F3654C11AE03E00045E114 /* PBXTextBookmark */; - B6F3654F11AE060D0045E114 /* PBXTextBookmark */ = B6F3654F11AE060D0045E114 /* PBXTextBookmark */; - B6F3655011AE060D0045E114 /* PBXTextBookmark */ = B6F3655011AE060D0045E114 /* PBXTextBookmark */; - B6F3655111AE060D0045E114 /* PBXTextBookmark */ = B6F3655111AE060D0045E114 /* PBXTextBookmark */; - B6F3655511AE06710045E114 /* PBXTextBookmark */ = B6F3655511AE06710045E114 /* PBXTextBookmark */; - B6F3655B11AE09D60045E114 /* PBXTextBookmark */ = B6F3655B11AE09D60045E114 /* PBXTextBookmark */; - B6F3655C11AE09D60045E114 /* PBXTextBookmark */ = B6F3655C11AE09D60045E114 /* PBXTextBookmark */; - B6F3655D11AE09D60045E114 /* PBXTextBookmark */ = B6F3655D11AE09D60045E114 /* PBXTextBookmark */; - B6F3656611AE142B0045E114 /* PBXTextBookmark */ = B6F3656611AE142B0045E114 /* PBXTextBookmark */; - B6F3656711AE142B0045E114 /* PBXTextBookmark */ = B6F3656711AE142B0045E114 /* PBXTextBookmark */; - B6F3656811AE142F0045E114 /* PBXTextBookmark */ = B6F3656811AE142F0045E114 /* PBXTextBookmark */; - B6F3657511AE24680045E114 /* PBXTextBookmark */ = B6F3657511AE24680045E114 /* PBXTextBookmark */; - B6F3657911AE24CC0045E114 /* PBXTextBookmark */ = B6F3657911AE24CC0045E114 /* PBXTextBookmark */; - B6F3657D11AE255B0045E114 /* PBXTextBookmark */ = B6F3657D11AE255B0045E114 /* PBXTextBookmark */; - B6F3657E11AE255B0045E114 /* PBXTextBookmark */ = B6F3657E11AE255B0045E114 /* PBXTextBookmark */; - B6F3657F11AE255B0045E114 /* PBXTextBookmark */ = B6F3657F11AE255B0045E114 /* PBXTextBookmark */; - B6F3658011AE255B0045E114 /* PBXTextBookmark */ = B6F3658011AE255B0045E114 /* PBXTextBookmark */; - B6F3658111AE256A0045E114 /* PBXTextBookmark */ = B6F3658111AE256A0045E114 /* PBXTextBookmark */; - B6F3658211AE256A0045E114 /* PBXTextBookmark */ = B6F3658211AE256A0045E114 /* PBXTextBookmark */; - B6F3658311AE25700045E114 /* PBXTextBookmark */ = B6F3658311AE25700045E114 /* PBXTextBookmark */; - B6F3658611AE25830045E114 /* PBXTextBookmark */ = B6F3658611AE25830045E114 /* PBXTextBookmark */; - B6F365A211AE27A80045E114 /* PBXTextBookmark */ = B6F365A211AE27A80045E114 /* PBXTextBookmark */; - B6F365A411AE27BE0045E114 /* PBXTextBookmark */ = B6F365A411AE27BE0045E114 /* PBXTextBookmark */; - B6F365A511AE27BE0045E114 /* PBXTextBookmark */ = B6F365A511AE27BE0045E114 /* PBXTextBookmark */; - B6F365A611AE27BE0045E114 /* PBXTextBookmark */ = B6F365A611AE27BE0045E114 /* PBXTextBookmark */; - B6F365A711AE27BE0045E114 /* PBXTextBookmark */ = B6F365A711AE27BE0045E114 /* PBXTextBookmark */; - B6F365A811AE27BE0045E114 /* PBXTextBookmark */ = B6F365A811AE27BE0045E114 /* PBXTextBookmark */; - B6F365A911AE27BE0045E114 /* PBXTextBookmark */ = B6F365A911AE27BE0045E114 /* PBXTextBookmark */; - B6F365AA11AE27BE0045E114 /* PBXTextBookmark */ = B6F365AA11AE27BE0045E114 /* PBXTextBookmark */; - B6F365AD11AE27CC0045E114 /* PBXTextBookmark */ = B6F365AD11AE27CC0045E114 /* PBXTextBookmark */; - B6F365AE11AE27CC0045E114 /* PBXTextBookmark */ = B6F365AE11AE27CC0045E114 /* PBXTextBookmark */; - B6F365AF11AE27CC0045E114 /* PBXTextBookmark */ = B6F365AF11AE27CC0045E114 /* PBXTextBookmark */; - B6F365B111AE28340045E114 /* PBXTextBookmark */ = B6F365B111AE28340045E114 /* PBXTextBookmark */; - B6F365B411AF40320045E114 /* PBXTextBookmark */ = B6F365B411AF40320045E114 /* PBXTextBookmark */; - B6F365B711AF62E00045E114 /* PBXTextBookmark */ = B6F365B711AF62E00045E114 /* PBXTextBookmark */; - B6F365B811AF62E00045E114 /* PBXTextBookmark */ = B6F365B811AF62E00045E114 /* PBXTextBookmark */; - B6F365CA11B08AE30045E114 /* PBXTextBookmark */ = B6F365CA11B08AE30045E114 /* PBXTextBookmark */; - B6F365CB11B08AE30045E114 /* XCBuildMessageTextBookmark */ = B6F365CB11B08AE30045E114 /* XCBuildMessageTextBookmark */; - B6F365CD11B08AE30045E114 /* PBXTextBookmark */ = B6F365CD11B08AE30045E114 /* PBXTextBookmark */; - B6F365CE11B08AE30045E114 /* PBXTextBookmark */ = B6F365CE11B08AE30045E114 /* PBXTextBookmark */; - B6F365CF11B08AE30045E114 /* PBXTextBookmark */ = B6F365CF11B08AE30045E114 /* PBXTextBookmark */; - B6F365E511B09E510045E114 /* PBXTextBookmark */ = B6F365E511B09E510045E114 /* PBXTextBookmark */; - B6F365E811B09EFD0045E114 /* PBXTextBookmark */ = B6F365E811B09EFD0045E114 /* PBXTextBookmark */; - B6F365EB11B09F2A0045E114 /* PBXTextBookmark */ = B6F365EB11B09F2A0045E114 /* PBXTextBookmark */; - B6F365EE11B0A6010045E114 /* PBXTextBookmark */ = B6F365EE11B0A6010045E114 /* PBXTextBookmark */; - B6F365F111B0A6BE0045E114 /* PBXTextBookmark */ = B6F365F111B0A6BE0045E114 /* PBXTextBookmark */; - B6F365F411B169C00045E114 /* PBXTextBookmark */ = B6F365F411B169C00045E114 /* PBXTextBookmark */; - B6F365F611B169D40045E114 /* PBXTextBookmark */ = B6F365F611B169D40045E114 /* PBXTextBookmark */; - B6F365F711B169D40045E114 /* PBXTextBookmark */ = B6F365F711B169D40045E114 /* PBXTextBookmark */; - B6F365F811B169D40045E114 /* PBXTextBookmark */ = B6F365F811B169D40045E114 /* PBXTextBookmark */; - B6F365FA11B16A690045E114 /* PBXTextBookmark */ = B6F365FA11B16A690045E114 /* PBXTextBookmark */; - B6F3660311B16D9F0045E114 /* PBXTextBookmark */ = B6F3660311B16D9F0045E114 /* PBXTextBookmark */; - B6F3660411B16D9F0045E114 /* XCBuildMessageTextBookmark */ = B6F3660411B16D9F0045E114 /* XCBuildMessageTextBookmark */; - B6F3660511B16D9F0045E114 /* PBXTextBookmark */ = B6F3660511B16D9F0045E114 /* PBXTextBookmark */; - B6F3660A11B174830045E114 /* PBXTextBookmark */ = B6F3660A11B174830045E114 /* PBXTextBookmark */; - B6F3660E11B175EA0045E114 /* PBXTextBookmark */ = B6F3660E11B175EA0045E114 /* PBXTextBookmark */; - B6F3661511B1762C0045E114 /* PBXTextBookmark */ = B6F3661511B1762C0045E114 /* PBXTextBookmark */; - B6F3661A11B176960045E114 /* PBXTextBookmark */ = B6F3661A11B176960045E114 /* PBXTextBookmark */; - B6F3662011B177B60045E114 /* PBXTextBookmark */ = B6F3662011B177B60045E114 /* PBXTextBookmark */; - B6F3662111B177B60045E114 /* PBXTextBookmark */ = B6F3662111B177B60045E114 /* PBXTextBookmark */; - B6F3662211B177B60045E114 /* PBXTextBookmark */ = B6F3662211B177B60045E114 /* PBXTextBookmark */; - B6F3662311B177B60045E114 /* PBXTextBookmark */ = B6F3662311B177B60045E114 /* PBXTextBookmark */; - B6F3662D11B178720045E114 /* PBXTextBookmark */ = B6F3662D11B178720045E114 /* PBXTextBookmark */; - B6F3662E11B178720045E114 /* PBXTextBookmark */ = B6F3662E11B178720045E114 /* PBXTextBookmark */; - B6F3662F11B178720045E114 /* PBXTextBookmark */ = B6F3662F11B178720045E114 /* PBXTextBookmark */; - B6F3663411B178EB0045E114 /* PBXTextBookmark */ = B6F3663411B178EB0045E114 /* PBXTextBookmark */; - B6F3663811B179290045E114 /* PBXTextBookmark */ = B6F3663811B179290045E114 /* PBXTextBookmark */; - B6F3664111B181C10045E114 /* PBXTextBookmark */ = B6F3664111B181C10045E114 /* PBXTextBookmark */; - B6F3665011B189490045E114 /* PBXTextBookmark */ = B6F3665011B189490045E114 /* PBXTextBookmark */; - B6F3665111B190300045E114 /* PBXTextBookmark */ = B6F3665111B190300045E114 /* PBXTextBookmark */; - B6F3665211B190300045E114 /* PBXTextBookmark */ = B6F3665211B190300045E114 /* PBXTextBookmark */; - B6F3665311B190300045E114 /* PBXTextBookmark */ = B6F3665311B190300045E114 /* PBXTextBookmark */; - B6F3665411B190370045E114 /* PBXTextBookmark */ = B6F3665411B190370045E114 /* PBXTextBookmark */; - B6F3665511B190370045E114 /* PBXTextBookmark */ = B6F3665511B190370045E114 /* PBXTextBookmark */; - B6F3665911B191C90045E114 /* PBXTextBookmark */ = B6F3665911B191C90045E114 /* PBXTextBookmark */; - B6F3665C11B194AC0045E114 /* PBXTextBookmark */ = B6F3665C11B194AC0045E114 /* PBXTextBookmark */; - B6F3665D11B194AC0045E114 /* PBXTextBookmark */ = B6F3665D11B194AC0045E114 /* PBXTextBookmark */; - B6F3665E11B194AC0045E114 /* PBXTextBookmark */ = B6F3665E11B194AC0045E114 /* PBXTextBookmark */; - B6F366C211B1A28C0045E114 /* PBXTextBookmark */ = B6F366C211B1A28C0045E114 /* PBXTextBookmark */; - B6F366C311B1A28C0045E114 /* PBXTextBookmark */ = B6F366C311B1A28C0045E114 /* PBXTextBookmark */; - B6F366C411B1A28C0045E114 /* PBXTextBookmark */ = B6F366C411B1A28C0045E114 /* PBXTextBookmark */; - B6F366C511B1A28C0045E114 /* PBXTextBookmark */ = B6F366C511B1A28C0045E114 /* PBXTextBookmark */; - B6F366C611B1A28C0045E114 /* PBXTextBookmark */ = B6F366C611B1A28C0045E114 /* PBXTextBookmark */; - B6F366C711B1A28C0045E114 /* PBXTextBookmark */ = B6F366C711B1A28C0045E114 /* PBXTextBookmark */; - B6F366C811B1A28C0045E114 /* PBXTextBookmark */ = B6F366C811B1A28C0045E114 /* PBXTextBookmark */; - B6F366C911B1A28C0045E114 /* PBXTextBookmark */ = B6F366C911B1A28C0045E114 /* PBXTextBookmark */; - B6F366CA11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CA11B1A28C0045E114 /* PBXTextBookmark */; - B6F366CB11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CB11B1A28C0045E114 /* PBXTextBookmark */; - B6F366CC11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CC11B1A28C0045E114 /* PBXTextBookmark */; - B6F366CD11B1A28C0045E114 /* XCBuildMessageTextBookmark */ = B6F366CD11B1A28C0045E114 /* XCBuildMessageTextBookmark */; - B6F366CE11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CE11B1A28C0045E114 /* PBXTextBookmark */; + B6F3647111AB35FE0045E114 = B6F3647111AB35FE0045E114 /* PBXTextBookmark */; + B6F3649E11AB59190045E114 = B6F3649E11AB59190045E114 /* PBXTextBookmark */; + B6F364B711AB84840045E114 = B6F364B711AB84840045E114 /* PBXTextBookmark */; + B6F3652E11ADD5D20045E114 = B6F3652E11ADD5D20045E114 /* PBXTextBookmark */; + B6F3653011ADD5D20045E114 = B6F3653011ADD5D20045E114 /* PBXTextBookmark */; + B6F3657E11AE255B0045E114 = B6F3657E11AE255B0045E114 /* PBXTextBookmark */; + B6F3665411B190370045E114 = B6F3665411B190370045E114 /* PBXTextBookmark */; + B6F3665C11B194AC0045E114 = B6F3665C11B194AC0045E114 /* PBXTextBookmark */; + B6F366C211B1A28C0045E114 = B6F366C211B1A28C0045E114 /* PBXTextBookmark */; + B6F366C411B1A28C0045E114 = B6F366C411B1A28C0045E114 /* PBXTextBookmark */; + B6F366C511B1A28C0045E114 = B6F366C511B1A28C0045E114 /* PBXTextBookmark */; + B6F366C611B1A28C0045E114 = B6F366C611B1A28C0045E114 /* PBXTextBookmark */; + B6F366C711B1A28C0045E114 = B6F366C711B1A28C0045E114 /* PBXTextBookmark */; + B6F366C811B1A28C0045E114 = B6F366C811B1A28C0045E114 /* PBXTextBookmark */; + B6F366C911B1A28C0045E114 = B6F366C911B1A28C0045E114 /* PBXTextBookmark */; + B6F366CA11B1A28C0045E114 = B6F366CA11B1A28C0045E114 /* PBXTextBookmark */; + B6F366CB11B1A28C0045E114 = B6F366CB11B1A28C0045E114 /* PBXTextBookmark */; + B6F366CC11B1A28C0045E114 = B6F366CC11B1A28C0045E114 /* PBXTextBookmark */; + B6F366D911B1A7A70045E114 = B6F366D911B1A7A70045E114 /* PBXTextBookmark */; + B6F3670611B2B47E0045E114 = B6F3670611B2B47E0045E114 /* PBXTextBookmark */; + B6F3675411B316D10045E114 = B6F3675411B316D10045E114 /* PBXTextBookmark */; + B6F3677C11B326580045E114 = B6F3677C11B326580045E114 /* PBXTextBookmark */; + B6F3677D11B326580045E114 = B6F3677D11B326580045E114 /* PBXTextBookmark */; + B6F3677E11B326580045E114 = B6F3677E11B326580045E114 /* PBXTextBookmark */; + B6F3677F11B326580045E114 = B6F3677F11B326580045E114 /* PBXTextBookmark */; + B6F367A011B330D10045E114 = B6F367A011B330D10045E114 /* PBXTextBookmark */; + B6F367AE11B337A70045E114 = B6F367AE11B337A70045E114 /* PBXTextBookmark */; + B6F367E911B40F650045E114 = B6F367E911B40F650045E114 /* PBXTextBookmark */; + B6F3684911B44D090045E114 = B6F3684911B44D090045E114 /* PBXTextBookmark */; + B6F3684A11B44D090045E114 = B6F3684A11B44D090045E114 /* PBXTextBookmark */; + B6F3684B11B44D090045E114 = B6F3684B11B44D090045E114 /* PBXTextBookmark */; }; sourceControlManager = B63EFA6711A093C200C90DCE /* Source Control */; userBuildSettings = { @@ -332,7 +188,7 @@ uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 1339}}"; sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 907}"; + sepNavVisRange = "{0, 868}"; }; }; B63EFA7611A0948500C90DCE /* Endian.h */ = { @@ -358,9 +214,9 @@ }; B63EFA9611A094E000C90DCE /* BlockDevice.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1015, 944}}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 858}}"; sepNavSelRange = "{431, 0}"; - sepNavVisRange = "{0, 1234}"; + sepNavVisRange = "{0, 917}"; }; }; B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */ = { @@ -393,9 +249,9 @@ }; B63EFA9D11A094E000C90DCE /* DiskImage.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 2769}}"; - sepNavSelRange = "{423, 0}"; - sepNavVisRange = "{128, 613}"; + sepNavIntBoundsRect = "{{0, 0}, {1009, 2743}}"; + sepNavSelRange = "{550, 0}"; + sepNavVisRange = "{0, 1053}"; }; }; B63EFA9E11A094E000C90DCE /* DiskImage.h */ = { @@ -407,16 +263,16 @@ }; B63EFAA111A094E000C90DCE /* RawDevice.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1015, 4043}}"; - sepNavSelRange = "{2481, 0}"; - sepNavVisRange = "{2076, 1431}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 4186}}"; + sepNavSelRange = "{2579, 0}"; + sepNavVisRange = "{2262, 800}"; }; }; B63EFAA211A094E000C90DCE /* RawDevice.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1015, 944}}"; - sepNavSelRange = "{735, 0}"; - sepNavVisRange = "{0, 952}"; + sepNavIntBoundsRect = "{{0, 0}, {1009, 958}}"; + sepNavSelRange = "{894, 0}"; + sepNavVisRange = "{0, 1056}"; }; }; B63EFAA311A094E000C90DCE /* TrackSector.h */ = { @@ -442,16 +298,16 @@ }; B63EFAB611A098C400C90DCE /* BlockCache.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1264, 988}}"; - sepNavSelRange = "{1253, 0}"; - sepNavVisRange = "{0, 1191}"; + sepNavIntBoundsRect = "{{0, 0}, {1009, 962}}"; + sepNavSelRange = "{334, 0}"; + sepNavVisRange = "{0, 1217}"; }; }; B63EFAB711A098C400C90DCE /* BlockCache.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1264, 932}}"; - sepNavSelRange = "{795, 44}"; - sepNavVisRange = "{0, 1167}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 754}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{148, 940}"; }; }; B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */ = { @@ -484,16 +340,16 @@ }; B63EFAC911A09DAA00C90DCE /* File.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 1534}}"; - sepNavSelRange = "{1503, 0}"; - sepNavVisRange = "{347, 1384}"; + sepNavIntBoundsRect = "{{0, 0}, {1009, 1599}}"; + sepNavSelRange = "{1429, 0}"; + sepNavVisRange = "{248, 1374}"; }; }; B63EFACA11A09DAA00C90DCE /* File.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 948}}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 754}}"; sepNavSelRange = "{244, 0}"; - sepNavVisRange = "{0, 979}"; + sepNavVisRange = "{0, 749}"; }; }; B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */ = { @@ -558,11 +414,6 @@ name = DiskImage.h; path = ./Device/DiskImage.h; sourceTree = ""; - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1009, 1144}}"; - sepNavSelRange = "{596, 0}"; - sepNavVisRange = "{124, 1430}"; - }; }; B63EFBE811A244EE00C90DCE /* Date.cpp */ = { uiCtxt = { @@ -585,31 +436,18 @@ sepNavVisRange = "{0, 1220}"; }; }; - B63EFBEB11A244EE00C90DCE /* File.h */ = { - isa = PBXFileReference; - fileEncoding = 4; - lastKnownFileType = sourcecode.c.h; - name = File.h; - path = /Users/kelvin/Projects/PROFuseX/Pascal/File.h; - sourceTree = ""; - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 3029}}"; - sepNavSelRange = "{2795, 35}"; - sepNavVisRange = "{2292, 855}"; - }; - }; B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 7813}}"; - sepNavSelRange = "{1130, 0}"; - sepNavVisRange = "{1, 1360}"; + sepNavIntBoundsRect = "{{0, 0}, {1009, 8775}}"; + sepNavSelRange = "{5793, 0}"; + sepNavVisRange = "{4945, 1395}"; }; }; B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 3094}}"; - sepNavSelRange = "{275, 24}"; - sepNavVisRange = "{0, 832}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 12779}}"; + sepNavSelRange = "{13761, 6}"; + sepNavVisRange = "{13015, 1389}"; }; }; B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */ = { @@ -622,16 +460,6 @@ vrLen = 97; vrLoc = 0; }; - B63EFC2B11A2D5A400C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; - name = "BlockDevice.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 186; - vrLoc = 0; - }; B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFAB911A098C400C90DCE /* ConcreteBlockCache.h */; @@ -644,9 +472,9 @@ }; B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 1339}}"; + sepNavIntBoundsRect = "{{0, 0}, {1009, 1339}}"; sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{1363, 1056}"; + sepNavVisRange = "{687, 1732}"; }; }; B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */ = { @@ -658,9 +486,9 @@ }; B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {768, 4004}}"; - sepNavSelRange = "{6507, 0}"; - sepNavVisRange = "{4525, 2059}"; + sepNavIntBoundsRect = "{{0, 0}, {1009, 4381}}"; + sepNavSelRange = "{4492, 0}"; + sepNavVisRange = "{2844, 1735}"; }; }; B63EFC9D11A35F8200C90DCE /* fuse_pascal_ops.cpp */ = { @@ -672,42 +500,17 @@ }; B63EFC9F11A35F8F00C90DCE /* apfm.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 10855}}"; - sepNavSelRange = "{16564, 0}"; - sepNavVisRange = "{15404, 884}"; + sepNavIntBoundsRect = "{{0, 0}, {1009, 14040}}"; + sepNavSelRange = "{13109, 0}"; + sepNavVisRange = "{11908, 1651}"; }; }; - B63EFCB211A3639400C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; - name = "DavexDiskImage.cpp: 160"; - rLen = 0; - rLoc = 3285; - rType = 0; - vrLen = 270; - vrLoc = 3136; - }; - B63EFCB611A3639400C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; - name = "Entry.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 233; - vrLoc = 0; - }; B63EFCC811A366C800C90DCE /* MappedFile.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MappedFile.h; path = ./File/MappedFile.h; sourceTree = ""; - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 663}}"; - sepNavSelRange = "{263, 0}"; - sepNavVisRange = "{0, 874}"; - }; }; B63EFCCD11A36C7300C90DCE /* apfm */ = { activeExec = 0; @@ -755,16 +558,6 @@ "size-size_t-MappedFile::init" = 1; }; }; - B63EFD7F11A4436B00C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; - name = "File.cpp: 34"; - rLen = 0; - rLoc = 504; - rType = 0; - vrLen = 225; - vrLoc = 284; - }; B63EFDA011A4488200C90DCE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFDA111A4488200C90DCE /* memory */; @@ -923,31 +716,11 @@ fRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; name = "BlockCache.cpp: 60"; rLen = 0; - rLoc = 1001; + rLoc = 962; rType = 0; vrLen = 490; vrLoc = 514; }; - B63EFDC711A4494C00C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAB711A098C400C90DCE /* BlockCache.h */; - name = "BlockCache.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 954; - vrLoc = 0; - }; - B63EFDE611A44E9300C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; - name = "MappedFile.cpp: 42"; - rLen = 0; - rLoc = 747; - rType = 0; - vrLen = 791; - vrLoc = 576; - }; B63EFDF211A4504200C90DCE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFAD011A09DB500C90DCE /* auto.h */; @@ -1011,48 +784,6 @@ vrLen = 763; vrLoc = 0; }; - B63EFEA211A488C200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; - name = "UniversalDiskImage.cpp: 162"; - rLen = 0; - rLoc = 3117; - rType = 0; - vrLen = 1007; - vrLoc = 2311; - }; - B63EFEA311A488C200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAA511A094E000C90DCE /* UniversalDiskImage.h */; - name = "UniversalDiskImage.h: 22"; - rLen = 0; - rLoc = 403; - rType = 0; - vrLen = 723; - vrLoc = 0; - }; - B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */ = { - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - name = VolumeEntry.cpp; - path = ./Pascal/VolumeEntry.cpp; - sourceTree = ""; - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 9542}}"; - sepNavSelRange = "{8503, 0}"; - sepNavVisRange = "{8131, 736}"; - }; - }; - B63EFEA711A488C200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBEB11A244EE00C90DCE /* File.h */; - name = "File.h: 2"; - rLen = 0; - rLoc = 43; - rType = 0; - vrLen = 901; - vrLoc = 2858; - }; B63EFEA811A488C200C90DCE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; @@ -1063,26 +794,6 @@ vrLen = 834; vrLoc = 0; }; - B63EFEA911A488C200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBE911A244EE00C90DCE /* Date.h */; - name = "Date.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 706; - vrLoc = 0; - }; - B63EFEEC11A4A70400C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; - name = "RawDevice.cpp: 147"; - rLen = 0; - rLoc = 2655; - rType = 0; - vrLen = 865; - vrLoc = 2190; - }; B656AE0211A84F5800AB578A /* fuse_pascal */ = { activeExec = 0; executables = ( @@ -1116,16 +827,6 @@ sourceDirectories = ( ); }; - B656AE2311A84FA400AB578A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAD211A09DB500C90DCE /* Exception.h */; - name = "Exception.h: 37"; - rLen = 12; - rLoc = 734; - rType = 0; - vrLen = 1049; - vrLoc = 434; - }; B656AE2411A84FA400AB578A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFC9D11A35F8200C90DCE /* fuse_pascal_ops.cpp */; @@ -1146,46 +847,6 @@ vrLen = 781; vrLoc = 126; }; - B656AE2711A84FA400AB578A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; - name = "newfs_pascal.cpp: 221"; - rLen = 0; - rLoc = 5494; - rType = 0; - vrLen = 1307; - vrLoc = 4987; - }; - B656AE6511A8591F00AB578A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */; - name = "fuse_pascal.cpp: 187"; - rLen = 0; - rLoc = 4201; - rType = 0; - vrLen = 1001; - vrLoc = 3697; - }; - B656AEA711A9C91600AB578A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; - name = "DiskImage.cpp: 148"; - rLen = 0; - rLoc = 2568; - rType = 0; - vrLen = 894; - vrLoc = 2264; - }; - B656AEA811A9C91600AB578A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFB8811A1FB2500C90DCE /* DiskImage.h */; - name = "DiskImage.h: 65"; - rLen = 0; - rLoc = 1204; - rType = 0; - vrLen = 898; - vrLoc = 788; - }; B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1178, 1248}}"; @@ -1239,35 +900,45 @@ "y-uint8_t-Device::NibbleAdaptor::readTrackSector" = 1; }; }; - B656AF2711AA10C900AB578A /* PBXTextBookmark */ = { + B65CFB6911B495790024A2D9 /* PBXTextBookmark */ = { isa = PBXTextBookmark; - fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; - name = "FileEntry.cpp: 372"; + fRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; + name = "RawDevice.cpp: 136"; rLen = 0; - rLoc = 11565; + rLoc = 2579; rType = 0; - vrLen = 938; - vrLoc = 6413; + vrLen = 800; + vrLoc = 2262; }; - B656AF2811AA10C900AB578A /* PBXTextBookmark */ = { + B65CFB6A11B495790024A2D9 /* PBXTextBookmark */ = { isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 107"; - rLen = 0; - rLoc = 6577; + fRef = B6F3647B11AB361D0045E114 /* xattr.cpp */; + name = "xattr.cpp: 330"; + rLen = 6; + rLoc = 6657; rType = 0; - vrLen = 875; - vrLoc = 2880; + vrLen = 829; + vrLoc = 5931; }; - B656AF2A11AA10C900AB578A /* PBXTextBookmark */ = { + B65CFB6B11B495790024A2D9 /* PBXTextBookmark */ = { isa = PBXTextBookmark; - fRef = B63EFCC811A366C800C90DCE /* MappedFile.h */; - name = "MappedFile.h: 15"; - rLen = 64; - rLoc = 196; + fRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 595"; + rLen = 6; + rLoc = 13761; rType = 0; - vrLen = 863; - vrLoc = 0; + vrLen = 1344; + vrLoc = 12874; + }; + B65CFB8811B5C8310024A2D9 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 618"; + rLen = 6; + rLoc = 13761; + rType = 0; + vrLen = 1389; + vrLoc = 13015; }; B6E5F0DD11A60726000AD141 /* PBXTextBookmark */ = { isa = PBXTextBookmark; @@ -1309,16 +980,6 @@ vrLen = 1056; vrLoc = 1363; }; - B6E5F18111A76B74000AD141 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 460"; - rLen = 0; - rLoc = 10173; - rType = 0; - vrLen = 797; - vrLoc = 8547; - }; B6E5F18211A76B74000AD141 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFAD111A09DB500C90DCE /* Exception.cpp */; @@ -1329,26 +990,6 @@ vrLen = 157; vrLoc = 0; }; - B6F3642811AA1DC80045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFB0611A0AC4800C90DCE /* Adaptor.h */; - name = "Adaptor.h: 82"; - rLen = 0; - rLoc = 1806; - rType = 0; - vrLen = 606; - vrLoc = 688; - }; - B6F3642D11AA1E070045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; - name = "Endian.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 907; - vrLoc = 0; - }; B6F3642F11AA1E150045E114 /* NibbleTest.cpp:76 */ = { isa = PBXFileBreakpoint; actions = ( @@ -1363,44 +1004,10 @@ ignoreCount = 0; lineNumber = 76; location = NibbleTest; - modificationTime = 296847682.098918; + modificationTime = 296847682.0989181; originalNumberOfMultipleMatches = 1; state = 1; }; - B6F3646211AA26810045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFB0611A0AC4800C90DCE /* Adaptor.h */; - name = "Adaptor.h: 82"; - rLen = 0; - rLoc = 1806; - rType = 0; - vrLen = 1168; - vrLoc = 442; - }; - B6F3646E11AB35F00045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFB0611A0AC4800C90DCE /* Adaptor.h */; - name = "Adaptor.h: 82"; - rLen = 0; - rLoc = 1806; - rType = 0; - vrLen = 660; - vrLoc = 950; - }; - B6F3646F11AB35F00045E114 /* PBXBookmark */ = { - isa = PBXBookmark; - fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; - }; - B6F3647011AB35F00045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; - name = "NibbleTest.cpp: 70"; - rLen = 0; - rLoc = 1607; - rType = 0; - vrLen = 470; - vrLoc = 1269; - }; B6F3647111AB35FE0045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFB0611A0AC4800C90DCE /* Adaptor.h */; @@ -1411,21 +1018,11 @@ vrLen = 1126; vrLoc = 442; }; - B6F3647211AB35FE0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; - name = "NibbleTest.cpp: 70"; - rLen = 0; - rLoc = 1607; - rType = 0; - vrLen = 940; - vrLoc = 917; - }; B6F3647B11AB361D0045E114 /* xattr.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 5434}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 985}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 5512}}"; + sepNavSelRange = "{6657, 6}"; + sepNavVisRange = "{5931, 829}"; }; }; B6F3647F11AB36260045E114 /* xattr */ = { @@ -1461,55 +1058,6 @@ sourceDirectories = ( ); }; - B6F3649411AB58E80045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; - name = "NibbleTest.cpp: 70"; - rLen = 0; - rLoc = 1607; - rType = 0; - vrLen = 940; - vrLoc = 917; - }; - B6F3649511AB58E80045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6F3647B11AB361D0045E114 /* xattr.cpp */; - name = "xattr.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 985; - vrLoc = 0; - }; - B6F3649611AB58E80045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */; - name = "fuse_pascal.cpp: 187"; - rLen = 0; - rLoc = 4201; - rType = 0; - vrLen = 970; - vrLoc = 3759; - }; - B6F3649711AB58E80045E114 /* XCBuildMessageTextBookmark */ = { - isa = PBXTextBookmark; - comments = "Prototype for 'File::File(const char*, int, mode_t, const std::nothrow_t&)' does not match any in class 'File'"; - fRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; - fallbackIsa = XCBuildMessageTextBookmark; - rLen = 1; - rLoc = 34; - rType = 1; - }; - B6F3649811AB58E80045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; - name = "File.cpp: 35"; - rLen = 0; - rLoc = 384; - rType = 0; - vrLen = 571; - vrLoc = 0; - }; B6F3649E11AB59190045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; @@ -1520,74 +1068,6 @@ vrLen = 571; vrLoc = 0; }; - B6F3649F11AB59190045E114 /* XCBuildMessageTextBookmark */ = { - isa = PBXTextBookmark; - comments = "'File' has not been declared"; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - fallbackIsa = XCBuildMessageTextBookmark; - rLen = 1; - rLoc = 567; - rType = 1; - }; - B6F364A011AB59190045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 281"; - rLen = 66; - rLoc = 12497; - rType = 0; - vrLen = 849; - vrLoc = 5157; - }; - B6F364A511AB593E0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 281"; - rLen = 66; - rLoc = 12497; - rType = 0; - vrLen = 855; - vrLoc = 5157; - }; - B6F364A911AB5EBD0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 281"; - rLen = 66; - rLoc = 12497; - rType = 0; - vrLen = 855; - vrLoc = 5157; - }; - B6F364B111AB74F40045E114 /* XCBuildMessageTextBookmark */ = { - isa = PBXTextBookmark; - comments = "'kTextFile' was not declared in this scope"; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - fallbackIsa = XCBuildMessageTextBookmark; - rLen = 1; - rLoc = 670; - rType = 1; - }; - B6F364B211AB74F40045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 385"; - rLen = 0; - rLoc = 15158; - rType = 0; - vrLen = 715; - vrLoc = 8003; - }; - B6F364B611AB84840045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 385"; - rLen = 0; - rLoc = 15158; - rType = 0; - vrLen = 715; - vrLoc = 8003; - }; B6F364B711AB84840045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFAD211A09DB500C90DCE /* Exception.h */; @@ -1598,309 +1078,6 @@ vrLen = 1003; vrLoc = 434; }; - B6F364B811AB84840045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 464"; - rLen = 0; - rLoc = 10173; - rType = 0; - vrLen = 563; - vrLoc = 8511; - }; - B6F364B911AB84840045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 473"; - rLen = 0; - rLoc = 10173; - rType = 0; - vrLen = 546; - vrLoc = 8717; - }; - B6F364BE11AC92730045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 473"; - rLen = 0; - rLoc = 10173; - rType = 0; - vrLen = 546; - vrLoc = 8717; - }; - B6F364BF11AC92730045E114 /* XCBuildMessageTextBookmark */ = { - isa = PBXTextBookmark; - comments = "'volume' is not a class or namespace"; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - fallbackIsa = XCBuildMessageTextBookmark; - rLen = 1; - rLoc = 666; - rType = 1; - }; - B6F364C011AC92730045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 381"; - rLen = 0; - rLoc = 15070; - rType = 0; - vrLen = 667; - vrLoc = 7907; - }; - B6F364C811ACAB370045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 381"; - rLen = 0; - rLoc = 15070; - rType = 0; - vrLen = 667; - vrLoc = 7907; - }; - B6F364C911ACAB370045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 473"; - rLen = 0; - rLoc = 10173; - rType = 0; - vrLen = 546; - vrLoc = 8717; - }; - B6F364CA11ACAB370045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 475"; - rLen = 0; - rLoc = 10173; - rType = 0; - vrLen = 490; - vrLoc = 8968; - }; - B6F364E811ACB5790045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; - name = "FileEntry.cpp: 86"; - rLen = 0; - rLoc = 1778; - rType = 0; - vrLen = 851; - vrLoc = 1039; - }; - B6F364E911ACB5790045E114 /* XCBuildMessageTextBookmark */ = { - isa = PBXTextBookmark; - comments = "'void Pascal::VolumeEntry::writeEntry(Pascal::FileEntry*)' is private"; - fRef = B6F364EA11ACB5790045E114 /* File.h */; - fallbackIsa = XCBuildMessageTextBookmark; - rLen = 0; - rLoc = 6; - rType = 1; - }; - B6F364EA11ACB5790045E114 /* File.h */ = { - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - name = File.h; - path = ./Pascal/File.h; - sourceTree = ""; - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 948}}"; - sepNavSelRange = "{165, 0}"; - sepNavVisRange = "{0, 173}"; - }; - }; - B6F364EB11ACB5790045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBEB11A244EE00C90DCE /* File.h */; - name = "File.h: 141"; - rLen = 0; - rLoc = 165; - rType = 0; - vrLen = 855; - vrLoc = 2292; - }; - B6F364EC11ACB5790045E114 /* XCBuildMessageTextBookmark */ = { - isa = PBXTextBookmark; - comments = "'_file' was not declared in this scope"; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - fallbackIsa = XCBuildMessageTextBookmark; - rLen = 1; - rLoc = 154; - rType = 1; - }; - B6F364ED11ACB5790045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 154"; - rLen = 0; - rLoc = 3256; - rType = 0; - vrLen = 1019; - vrLoc = 2603; - }; - B6F364F511ACB5B60045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 155"; - rLen = 0; - rLoc = 3256; - rType = 0; - vrLen = 1113; - vrLoc = 2568; - }; - B6F364F811ACBA8E0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 155"; - rLen = 0; - rLoc = 3256; - rType = 0; - vrLen = 1113; - vrLoc = 2568; - }; - B6F364FD11ACBC470045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 155"; - rLen = 0; - rLoc = 3256; - rType = 0; - vrLen = 1113; - vrLoc = 2568; - }; - B6F3650011ACBC790045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 155"; - rLen = 0; - rLoc = 3256; - rType = 0; - vrLen = 1108; - vrLoc = 2568; - }; - B6F3650111ACBC790045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - rLen = 0; - rLoc = 744; - rType = 1; - }; - B6F3650211ACBC790045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 488"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 869; - vrLoc = 8980; - }; - B6F3650511ACBCA40045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; - name = "NibbleTest.cpp: 70"; - rLen = 0; - rLoc = 1607; - rType = 0; - vrLen = 470; - vrLoc = 1269; - }; - B6F3650611ACBCA40045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 488"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 334; - vrLoc = 10364; - }; - B6F3650911ACBCB30045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 488"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 659; - vrLoc = 10264; - }; - B6F3650E11ADC40E0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 488"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 752; - vrLoc = 10264; - }; - B6F3651111ADCA570045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 488"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 334; - vrLoc = 10364; - }; - B6F3651211ADCA570045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - rLen = 0; - rLoc = 107; - rType = 1; - }; - B6F3651311ADCA570045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 108"; - rLen = 0; - rLoc = 2072; - rType = 0; - vrLen = 792; - vrLoc = 2635; - }; - B6F3651511ADCA6C0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 488"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 752; - vrLoc = 10264; - }; - B6F3651611ADCA6C0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 108"; - rLen = 0; - rLoc = 2072; - rType = 0; - vrLen = 1135; - vrLoc = 2455; - }; - B6F3651711ADCA6C0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; - name = "Entry.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 711; - vrLoc = 0; - }; - B6F3651811ADCA6C0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; - name = "Entry.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 711; - vrLoc = 0; - }; B6F3651A11ADD0280045E114 /* VolumeEntry.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 1365}}"; @@ -1910,16 +1087,16 @@ }; B6F3651B11ADD0280045E114 /* FileEntry.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 1248}}"; - sepNavSelRange = "{990, 0}"; - sepNavVisRange = "{0, 1602}"; + sepNavIntBoundsRect = "{{0, 0}, {1009, 1326}}"; + sepNavSelRange = "{1407, 0}"; + sepNavVisRange = "{0, 1668}"; }; }; B6F3651C11ADD0280045E114 /* Entry.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 1079}}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 1079}}"; sepNavSelRange = "{1399, 0}"; - sepNavVisRange = "{146, 1332}"; + sepNavVisRange = "{0, 605}"; }; }; B6F3652711ADD52B0045E114 /* Pascal.h */ = { @@ -1939,16 +1116,6 @@ vrLen = 173; vrLoc = 0; }; - B6F3652F11ADD5D20045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBE911A244EE00C90DCE /* Date.h */; - name = "Date.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 672; - vrLoc = 0; - }; B6F3653011ADD5D20045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; @@ -1959,201 +1126,7 @@ vrLen = 712; vrLoc = 0; }; - B6F3653111ADD5D20045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6F3651C11ADD0280045E114 /* Entry.h */; - name = "Entry.h: 72"; - rLen = 0; - rLoc = 1399; - rType = 0; - vrLen = 873; - vrLoc = 605; - }; - B6F3653211ADD5D20045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; - name = "FileEntry.cpp: 283"; - rLen = 0; - rLoc = 6452; - rType = 0; - vrLen = 1018; - vrLoc = 5738; - }; - B6F3653311ADD5D20045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 488"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 752; - vrLoc = 10266; - }; - B6F3653411ADD5D20045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 488"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 935; - vrLoc = 10277; - }; - B6F3654311ADE1C20045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 488"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 935; - vrLoc = 10277; - }; - B6F3654411ADE1C20045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 108"; - rLen = 0; - rLoc = 2074; - rType = 0; - vrLen = 1135; - vrLoc = 2457; - }; - B6F3654511ADE1C20045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 108"; - rLen = 0; - rLoc = 2074; - rType = 0; - vrLen = 1135; - vrLoc = 2457; - }; - B6F3654711ADE3680045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 108"; - rLen = 0; - rLoc = 2074; - rType = 0; - vrLen = 1135; - vrLoc = 2457; - }; - B6F3654C11AE03E00045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 159"; - rLen = 0; - rLoc = 3423; - rType = 0; - vrLen = 941; - vrLoc = 1990; - }; - B6F3654F11AE060D0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 159"; - rLen = 0; - rLoc = 3423; - rType = 0; - vrLen = 858; - vrLoc = 1990; - }; - B6F3655011AE060D0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - rLen = 0; - rLoc = 744; - rType = 1; - }; - B6F3655111AE060D0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 488"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 741; - vrLoc = 10277; - }; - B6F3655511AE06710045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 488"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 648; - vrLoc = 10277; - }; - B6F3655B11AE09D60045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 488"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 286; - vrLoc = 10318; - }; - B6F3655C11AE09D60045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - rLen = 0; - rLoc = 153; - rType = 1; - }; - B6F3655D11AE09D60045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 154"; - rLen = 0; - rLoc = 3160; - rType = 0; - vrLen = 788; - vrLoc = 2637; - }; - B6F3656611AE142B0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 488"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 935; - vrLoc = 10277; - }; - B6F3656711AE142B0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 188"; - rLen = 0; - rLoc = 4064; - rType = 0; - vrLen = 1097; - vrLoc = 2544; - }; - B6F3656811AE142F0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 188"; - rLen = 0; - rLoc = 4064; - rType = 0; - vrLen = 1097; - vrLoc = 2544; - }; - B6F3657511AE24680045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 197"; - rLen = 0; - rLoc = 4315; - rType = 0; - vrLen = 503; - vrLoc = 2616; - }; - B6F3657711AE24C40045E114 /* apfm.cpp:470 */ = { + B6F3657711AE24C40045E114 /* apfm.cpp:589 */ = { isa = PBXFileBreakpoint; actions = ( ); @@ -2165,31 +1138,11 @@ functionName = "action_rm(int argc, char **argv, Pascal::VolumeEntry *volume)"; hitCount = 0; ignoreCount = 0; - lineNumber = 470; + lineNumber = 589; modificationTime = 296847686.349254; originalNumberOfMultipleMatches = 1; state = 1; }; - B6F3657911AE24CC0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 197"; - rLen = 0; - rLoc = 4315; - rType = 0; - vrLen = 952; - vrLoc = 2475; - }; - B6F3657D11AE255B0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 197"; - rLen = 0; - rLoc = 4315; - rType = 0; - vrLen = 952; - vrLoc = 2475; - }; B6F3657E11AE255B0045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFBE911A244EE00C90DCE /* Date.h */; @@ -2200,568 +1153,12 @@ vrLen = 654; vrLoc = 0; }; - B6F3657F11AE255B0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - rLen = 0; - rLoc = 744; - rType = 1; - }; - B6F3658011AE255B0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 495"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 569; - vrLoc = 10265; - }; - B6F3658111AE256A0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 197"; - rLen = 0; - rLoc = 4315; - rType = 0; - vrLen = 503; - vrLoc = 2616; - }; - B6F3658211AE256A0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 495"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 450; - vrLoc = 10578; - }; - B6F3658311AE25700045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 495"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 1242; - vrLoc = 10459; - }; - B6F3658611AE25830045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 495"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 1233; - vrLoc = 10459; - }; - B6F3659B11AE27760045E114 /* VolumeEntry.cpp:300 */ = { - isa = PBXFileBreakpoint; - actions = ( - ); - breakpointStyle = 0; - continueAfterActions = 0; - countType = 0; - delayBeforeContinue = 0; - fileReference = B6F3659C11AE27760045E114 /* VolumeEntry.cpp */; - functionName = "VolumeEntry::unlink(const char *name)"; - hitCount = 0; - ignoreCount = 0; - lineNumber = 300; - location = NibbleTest; - modificationTime = 296847681.826089; - originalNumberOfMultipleMatches = 1; - state = 1; - }; - B6F3659C11AE27760045E114 /* VolumeEntry.cpp */ = { - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - name = VolumeEntry.cpp; - path = /Users/kelvin/Projects/PROFuseX/./Pascal/VolumeEntry.cpp; - sourceTree = ""; - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1178, 7501}}"; - sepNavSelRange = "{6306, 0}"; - sepNavVisRange = "{6660, 576}"; - }; - }; - B6F3659E11AE27790045E114 /* VolumeEntry.cpp:311 */ = { - isa = PBXFileBreakpoint; - actions = ( - ); - breakpointStyle = 0; - continueAfterActions = 0; - countType = 0; - delayBeforeContinue = 0; - fileReference = B6F3659C11AE27760045E114 /* VolumeEntry.cpp */; - functionName = "VolumeEntry::unlink(const char *name)"; - hitCount = 0; - ignoreCount = 0; - lineNumber = 311; - location = NibbleTest; - modificationTime = 296847681.868784; - originalNumberOfMultipleMatches = 1; - state = 1; - }; - B6F365A211AE27A80045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 495"; - rLen = 0; - rLoc = 16395; - rType = 0; - vrLen = 1317; - vrLoc = 10657; - }; - B6F365A411AE27BE0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 286"; - rLen = 0; - rLoc = 6306; - rType = 0; - vrLen = 600; - vrLoc = 7515; - }; - B6F365A511AE27BE0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; - name = "MappedFile.cpp: 42"; - rLen = 0; - rLoc = 725; - rType = 0; - vrLen = 315; - vrLoc = 639; - }; - B6F365A611AE27BE0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; - name = "BlockDevice.cpp: 111"; - rLen = 0; - rLoc = 2416; - rType = 0; - vrLen = 511; - vrLoc = 2414; - }; - B6F365A711AE27BE0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; - name = "DiskImage.cpp: 41"; - rLen = 0; - rLoc = 593; - rType = 0; - vrLen = 367; - vrLoc = 372; - }; - B6F365A811AE27BE0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 246"; - rLen = 0; - rLoc = 10518; - rType = 0; - vrLen = 475; - vrLoc = 4825; - }; - B6F365A911AE27BE0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6F3659C11AE27760045E114 /* VolumeEntry.cpp */; - rLen = 0; - rLoc = 285; - rType = 1; - }; - B6F365AA11AE27BE0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6F3659C11AE27760045E114 /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 286"; - rLen = 0; - rLoc = 6306; - rType = 0; - vrLen = 576; - vrLoc = 6660; - }; - B6F365AD11AE27CC0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 286"; - rLen = 0; - rLoc = 6306; - rType = 0; - vrLen = 1053; - vrLoc = 6356; - }; - B6F365AE11AE27CC0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - rLen = 0; - rLoc = 469; - rType = 1; - }; - B6F365AF11AE27CC0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 246"; - rLen = 0; - rLoc = 10518; - rType = 0; - vrLen = 794; - vrLoc = 4641; - }; - B6F365B111AE28340045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 246"; - rLen = 0; - rLoc = 10518; - rType = 0; - vrLen = 794; - vrLoc = 4641; - }; - B6F365B411AF40320045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 286"; - rLen = 0; - rLoc = 6306; - rType = 0; - vrLen = 1082; - vrLoc = 6356; - }; - B6F365B711AF62E00045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - rLen = 0; - rLoc = 285; - rType = 1; - }; - B6F365B811AF62E00045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 277"; - rLen = 0; - rLoc = 5977; - rType = 0; - vrLen = 446; - vrLoc = 7467; - }; - B6F365CA11B08AE30045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 282"; - rLen = 0; - rLoc = 6025; - rType = 0; - vrLen = 1001; - vrLoc = 7234; - }; - B6F365CB11B08AE30045E114 /* XCBuildMessageTextBookmark */ = { - isa = PBXTextBookmark; - comments = "Invalid use of incomplete type 'struct Device::BlockDevice'"; - fRef = B6F365CC11B08AE30045E114 /* VolumeEntry.h */; - fallbackIsa = XCBuildMessageTextBookmark; - rLen = 1; - rLoc = 47; - rType = 1; - }; B6F365CC11B08AE30045E114 /* VolumeEntry.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VolumeEntry.h; path = ./Pascal/VolumeEntry.h; sourceTree = ""; - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 1326}}"; - sepNavSelRange = "{1475, 0}"; - sepNavVisRange = "{0, 1803}"; - }; - }; - B6F365CD11B08AE30045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6F3651A11ADD0280045E114 /* VolumeEntry.h */; - name = "VolumeEntry.h: 9"; - rLen = 0; - rLoc = 145; - rType = 0; - vrLen = 974; - vrLoc = 0; - }; - B6F365CE11B08AE30045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; - name = "newfs_pascal.cpp: 221"; - rLen = 0; - rLoc = 5494; - rType = 0; - vrLen = 1240; - vrLoc = 4971; - }; - B6F365CF11B08AE30045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; - name = "newfs_pascal.cpp: 221"; - rLen = 0; - rLoc = 5494; - rType = 0; - vrLen = 1240; - vrLoc = 4971; - }; - B6F365E511B09E510045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; - name = "newfs_pascal.cpp: 221"; - rLen = 0; - rLoc = 5494; - rType = 0; - vrLen = 1240; - vrLoc = 4971; - }; - B6F365E811B09EFD0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; - name = "newfs_pascal.cpp: 221"; - rLen = 0; - rLoc = 5494; - rType = 0; - vrLen = 1240; - vrLoc = 4971; - }; - B6F365EB11B09F2A0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; - name = "newfs_pascal.cpp: 221"; - rLen = 0; - rLoc = 5494; - rType = 0; - vrLen = 1240; - vrLoc = 4971; - }; - B6F365EE11B0A6010045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; - name = "newfs_pascal.cpp: 221"; - rLen = 0; - rLoc = 5494; - rType = 0; - vrLen = 1240; - vrLoc = 4971; - }; - B6F365F111B0A6BE0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; - name = "newfs_pascal.cpp: 221"; - rLen = 0; - rLoc = 5494; - rType = 0; - vrLen = 1240; - vrLoc = 4971; - }; - B6F365F411B169C00045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; - name = "newfs_pascal.cpp: 221"; - rLen = 0; - rLoc = 5494; - rType = 0; - vrLen = 1240; - vrLoc = 4971; - }; - B6F365F611B169D40045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; - name = "newfs_pascal.cpp: 221"; - rLen = 0; - rLoc = 5494; - rType = 0; - vrLen = 1240; - vrLoc = 4971; - }; - B6F365F711B169D40045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; - name = "NibbleTest.cpp: 70"; - rLen = 0; - rLoc = 1607; - rType = 0; - vrLen = 983; - vrLoc = 874; - }; - B6F365F811B169D40045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; - name = "NibbleTest.cpp: 70"; - rLen = 0; - rLoc = 1607; - rType = 0; - vrLen = 982; - vrLoc = 874; - }; - B6F365FA11B16A690045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; - name = "NibbleTest.cpp: 70"; - rLen = 0; - rLoc = 1607; - rType = 0; - vrLen = 997; - vrLoc = 874; - }; - B6F3660311B16D9F0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; - name = "NibbleTest.cpp: 70"; - rLen = 0; - rLoc = 1607; - rType = 0; - vrLen = 997; - vrLoc = 874; - }; - B6F3660411B16D9F0045E114 /* XCBuildMessageTextBookmark */ = { - isa = PBXTextBookmark; - comments = "Redefinition of 'unsigned int Pascal::VolumeEntry::rename(const char*, const char*)'"; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - fallbackIsa = XCBuildMessageTextBookmark; - rLen = 1; - rLoc = 383; - rType = 1; - }; - B6F3660511B16D9F0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 384"; - rLen = 0; - rLoc = 8503; - rType = 0; - vrLen = 702; - vrLoc = 8131; - }; - B6F3660A11B174830045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 384"; - rLen = 0; - rLoc = 8503; - rType = 0; - vrLen = 702; - vrLoc = 8131; - }; - B6F3660E11B175EA0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 384"; - rLen = 0; - rLoc = 8503; - rType = 0; - vrLen = 736; - vrLoc = 8131; - }; - B6F3661511B1762C0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 384"; - rLen = 0; - rLoc = 8503; - rType = 0; - vrLen = 736; - vrLoc = 8131; - }; - B6F3661A11B176960045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 384"; - rLen = 0; - rLoc = 8503; - rType = 0; - vrLen = 736; - vrLoc = 8131; - }; - B6F3662011B177B60045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 384"; - rLen = 0; - rLoc = 8503; - rType = 0; - vrLen = 362; - vrLoc = 8206; - }; - B6F3662111B177B60045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; - name = "NibbleTest.cpp: 74"; - rLen = 0; - rLoc = 1680; - rType = 0; - vrLen = 469; - vrLoc = 1396; - }; - B6F3662211B177B60045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; - rLen = 0; - rLoc = 166; - rType = 1; - }; - B6F3662311B177B60045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; - name = "Adaptor.cpp: 167"; - rLen = 0; - rLoc = 3653; - rType = 0; - vrLen = 533; - vrLoc = 8484; - }; - B6F3662D11B178720045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFEA511A488C200C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 384"; - rLen = 0; - rLoc = 8503; - rType = 0; - vrLen = 736; - vrLoc = 8131; - }; - B6F3662E11B178720045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; - name = "Adaptor.cpp: 167"; - rLen = 0; - rLoc = 3653; - rType = 0; - vrLen = 1182; - vrLoc = 8279; - }; - B6F3662F11B178720045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; - name = "Adaptor.cpp: 167"; - rLen = 0; - rLoc = 3653; - rType = 0; - vrLen = 1084; - vrLoc = 8365; - }; - B6F3663411B178EB0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; - name = "Adaptor.cpp: 167"; - rLen = 0; - rLoc = 3653; - rType = 0; - vrLen = 1125; - vrLoc = 8365; - }; - B6F3663811B179290045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; - name = "Adaptor.cpp: 167"; - rLen = 0; - rLoc = 3653; - rType = 0; - vrLen = 1125; - vrLoc = 8365; }; B6F3663D11B1809A0045E114 /* Adaptor.cpp:167 */ = { isa = PBXFileBreakpoint; @@ -2781,53 +1178,6 @@ originalNumberOfMultipleMatches = 1; state = 1; }; - B6F3664111B181C10045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; - name = "Adaptor.cpp: 167"; - rLen = 0; - rLoc = 3653; - rType = 0; - vrLen = 984; - vrLoc = 8112; - }; - B6F3665011B189490045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; - name = "Adaptor.cpp: 167"; - rLen = 0; - rLoc = 3653; - rType = 0; - vrLen = 933; - vrLoc = 7817; - }; - B6F3665111B190300045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; - name = "Adaptor.cpp: 262"; - rLen = 0; - rLoc = 6174; - rType = 0; - vrLen = 746; - vrLoc = 5474; - }; - B6F3665211B190300045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; - rLen = 0; - rLoc = 75; - rType = 1; - }; - B6F3665311B190300045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; - name = "NibbleTest.cpp: 76"; - rLen = 0; - rLoc = 1680; - rType = 0; - vrLen = 607; - vrLoc = 1479; - }; B6F3665411B190370045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; @@ -2838,26 +1188,6 @@ vrLen = 933; vrLoc = 7817; }; - B6F3665511B190370045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; - name = "NibbleTest.cpp: 76"; - rLen = 0; - rLoc = 1680; - rType = 0; - vrLen = 961; - vrLoc = 1203; - }; - B6F3665911B191C90045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; - name = "NibbleTest.cpp: 76"; - rLen = 0; - rLoc = 1680; - rType = 0; - vrLen = 951; - vrLoc = 1203; - }; B6F3665C11B194AC0045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; @@ -2868,46 +1198,16 @@ vrLen = 951; vrLoc = 1203; }; - B6F3665D11B194AC0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; - name = "newfs_pascal.cpp: 221"; - rLen = 0; - rLoc = 5494; - rType = 0; - vrLen = 1277; - vrLoc = 4934; - }; - B6F3665E11B194AC0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; - name = "newfs_pascal.cpp: 224"; - rLen = 0; - rLoc = 5494; - rType = 0; - vrLen = 1267; - vrLoc = 5050; - }; B6F366C211B1A28C0045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; name = "newfs_pascal.cpp: 227"; rLen = 0; - rLoc = 5494; + rLoc = 5474; rType = 0; vrLen = 1282; vrLoc = 4530; }; - B6F366C311B1A28C0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFCC811A366C800C90DCE /* MappedFile.h */; - name = "MappedFile.h: 17"; - rLen = 0; - rLoc = 263; - rType = 0; - vrLen = 874; - vrLoc = 0; - }; B6F366C411B1A28C0045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; @@ -2993,21 +1293,12 @@ fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; name = "apfm.cpp: 755"; rLen = 0; - rLoc = 16564; + rLoc = 22959; rType = 0; vrLen = 884; vrLoc = 15404; }; - B6F366CD11B1A28C0045E114 /* XCBuildMessageTextBookmark */ = { - isa = PBXTextBookmark; - comments = "Unused variable 'readOnly'"; - fRef = B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */; - fallbackIsa = XCBuildMessageTextBookmark; - rLen = 0; - rLoc = 194; - rType = 1; - }; - B6F366CE11B1A28C0045E114 /* PBXTextBookmark */ = { + B6F366D911B1A7A70045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */; name = "fuse_pascal.cpp: 195"; @@ -3017,4 +1308,178 @@ vrLen = 1077; vrLoc = 3977; }; + B6F3670611B2B47E0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9611A094E000C90DCE /* BlockDevice.h */; + name = "BlockDevice.h: 24"; + rLen = 0; + rLoc = 431; + rType = 0; + vrLen = 917; + vrLoc = 0; + }; + B6F3675411B316D10045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; + name = "FileEntry.cpp: 113"; + rLen = 0; + rLoc = 2383; + rType = 0; + vrLen = 767; + vrLoc = 1707; + }; + B6F3676311B323680045E114 /* TextWriter.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1009, 958}}"; + sepNavSelRange = "{420, 0}"; + sepNavVisRange = "{0, 587}"; + }; + }; + B6F3676411B323680045E114 /* TextWriter.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 1352}}"; + sepNavSelRange = "{315, 0}"; + sepNavVisRange = "{0, 803}"; + }; + }; + B6F3677C11B326580045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F365CC11B08AE30045E114 /* VolumeEntry.h */; + name = "VolumeEntry.h: 51"; + rLen = 56; + rLoc = 1259; + rType = 0; + vrLen = 1094; + vrLoc = 758; + }; + B6F3677D11B326580045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F3651C11ADD0280045E114 /* Entry.h */; + name = "Entry.h: 72"; + rLen = 0; + rLoc = 1399; + rType = 0; + vrLen = 605; + vrLoc = 0; + }; + B6F3677E11B326580045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F3676311B323680045E114 /* TextWriter.h */; + name = "TextWriter.h: 36"; + rLen = 0; + rLoc = 587; + rType = 0; + vrLen = 532; + vrLoc = 0; + }; + B6F3677F11B326580045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F3651B11ADD0280045E114 /* FileEntry.h */; + name = "FileEntry.h: 41"; + rLen = 0; + rLoc = 1069; + rType = 0; + vrLen = 933; + vrLoc = 1184; + }; + B6F367A011B330D10045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFACA11A09DAA00C90DCE /* File.h */; + name = "File.h: 21"; + rLen = 0; + rLoc = 244; + rType = 0; + vrLen = 749; + vrLoc = 0; + }; + B6F367AE11B337A70045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFCC811A366C800C90DCE /* MappedFile.h */; + name = "MappedFile.h: 17"; + rLen = 0; + rLoc = 263; + rType = 0; + vrLen = 874; + vrLoc = 0; + }; + B6F367E911B40F650045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAB711A098C400C90DCE /* BlockCache.h */; + name = "BlockCache.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 940; + vrLoc = 148; + }; + B6F3682111B430870045E114 /* newfs_prodos.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1009, 3185}}"; + sepNavSelRange = "{266, 0}"; + sepNavVisRange = "{0, 1849}"; + }; + }; + B6F3682411B431AC0045E114 /* newfs_prodos */ = { + activeExec = 0; + executables = ( + B6F3682611B431AC0045E114 /* newfs_prodos */, + ); + }; + B6F3682611B431AC0045E114 /* newfs_prodos */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 0; + configStateDict = { + }; + customDataFormattersEnabled = 1; + dataTipCustomDataFormattersEnabled = 1; + dataTipShowTypeColumn = 1; + dataTipSortType = 0; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + libgmallocEnabled = 0; + name = newfs_prodos; + showTypeColumn = 0; + sourceDirectories = ( + ); + }; + B6F3684911B44D090045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; + name = "Endian.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 868; + vrLoc = 0; + }; + B6F3684A11B44D090045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F3676411B323680045E114 /* TextWriter.cpp */; + name = "TextWriter.cpp: 17"; + rLen = 0; + rLoc = 315; + rType = 0; + vrLen = 803; + vrLoc = 0; + }; + B6F3684B11B44D090045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F3682111B430870045E114 /* newfs_prodos.cpp */; + name = "newfs_prodos.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1184; + vrLoc = 0; + }; } diff --git a/PROFuseX.xcodeproj/kelvin.perspectivev3 b/PROFuseX.xcodeproj/kelvin.perspectivev3 index 58876dd..ff5f128 100644 --- a/PROFuseX.xcodeproj/kelvin.perspectivev3 +++ b/PROFuseX.xcodeproj/kelvin.perspectivev3 @@ -231,6 +231,8 @@ Layout + BecomeActive + ContentConfiguration PBXBottomSmartGroupGIDs @@ -270,7 +272,9 @@ B63EFBE711A244EE00C90DCE B63EFACF11A09DB500C90DCE B63EFAC811A09DAA00C90DCE + B63EFAB511A098C400C90DCE B63EFA9411A094E000C90DCE + B63EFA7411A0948500C90DCE 1AB674ADFE9D54B511CA2CBB B656ADED11A84D3200AB578A 1C37FBAC04509CD000000102 @@ -279,8 +283,8 @@ PBXSmartGroupTreeModuleOutlineStateSelectionKey - 42 - 29 + 14 + 8 0 @@ -302,7 +306,7 @@ 318 RubberWindowFrame - 547 105 1239 1000 0 0 1920 1178 + 303 109 1239 1000 0 0 1920 1178 Module PBXSmartGroupTreeModule @@ -313,14 +317,12 @@ Dock - BecomeActive - ContentConfiguration PBXProjectModuleGUID B63EFA6111A093C200C90DCE PBXProjectModuleLabel - fuse_pascal.cpp + VolumeEntry.cpp PBXSplitModuleInNavigatorKey Split0 @@ -328,11 +330,11 @@ PBXProjectModuleGUID B63EFA6211A093C200C90DCE PBXProjectModuleLabel - fuse_pascal.cpp + VolumeEntry.cpp _historyCapacity 0 bookmark - B6F366CE11B1A28C0045E114 + B65CFB8811B5C8310024A2D9 history B63EFC2611A2D5A400C90DCE @@ -347,12 +349,10 @@ B63EFDB111A4488200C90DCE B63EFDB311A4488200C90DCE B63EFDB711A4488200C90DCE - B63EFDC711A4494C00C90DCE B63EFDF211A4504200C90DCE B63EFEA011A488C200C90DCE B63EFEA111A488C200C90DCE B63EFEA811A488C200C90DCE - B63EFEEC11A4A70400C90DCE B6E5F0DD11A60726000AD141 B6E5F0F211A73144000AD141 B6E5F11211A73340000AD141 @@ -360,22 +360,15 @@ B6E5F18211A76B74000AD141 B656AE2411A84FA400AB578A B656AE2611A84FA400AB578A - B6F3642D11AA1E070045E114 B6F3647111AB35FE0045E114 - B6F3649511AB58E80045E114 B6F3649E11AB59190045E114 B6F364B711AB84840045E114 B6F3652E11ADD5D20045E114 B6F3653011ADD5D20045E114 - B6F3653111ADD5D20045E114 B6F3657E11AE255B0045E114 - B6F365CB11B08AE30045E114 - B6F365CD11B08AE30045E114 - B6F3662D11B178720045E114 B6F3665411B190370045E114 B6F3665C11B194AC0045E114 B6F366C211B1A28C0045E114 - B6F366C311B1A28C0045E114 B6F366C411B1A28C0045E114 B6F366C511B1A28C0045E114 B6F366C611B1A28C0045E114 @@ -385,7 +378,22 @@ B6F366CA11B1A28C0045E114 B6F366CB11B1A28C0045E114 B6F366CC11B1A28C0045E114 - B6F366CD11B1A28C0045E114 + B6F366D911B1A7A70045E114 + B6F3670611B2B47E0045E114 + B6F3675411B316D10045E114 + B6F3677C11B326580045E114 + B6F3677D11B326580045E114 + B6F3677E11B326580045E114 + B6F3677F11B326580045E114 + B6F367A011B330D10045E114 + B6F367AE11B337A70045E114 + B6F367E911B40F650045E114 + B6F3684911B44D090045E114 + B6F3684A11B44D090045E114 + B6F3684B11B44D090045E114 + B65CFB6911B495790024A2D9 + B65CFB6A11B495790024A2D9 + B65CFB6B11B495790024A2D9 SplitCount @@ -399,18 +407,18 @@ GeometryConfiguration Frame - {{0, 0}, {899, 562}} + {{0, 0}, {899, 544}} RubberWindowFrame - 547 105 1239 1000 0 0 1920 1178 + 303 109 1239 1000 0 0 1920 1178 Module PBXNavigatorGroup Proportion - 562pt + 544pt Proportion - 392pt + 410pt Tabs @@ -424,7 +432,7 @@ GeometryConfiguration Frame - {{10, 27}, {899, 365}} + {{10, 27}, {0, -27}} Module XCDetailModule @@ -440,7 +448,9 @@ GeometryConfiguration Frame - {{10, 27}, {899, 365}} + {{10, 27}, {899, 383}} + RubberWindowFrame + 303 109 1239 1000 0 0 1920 1178 Module PBXProjectFindModule @@ -479,8 +489,6 @@ Frame {{10, 27}, {899, 365}} - RubberWindowFrame - 547 105 1239 1000 0 0 1920 1178 Module PBXBuildResultsModule @@ -508,11 +516,11 @@ TableOfContents - B6F3647311AB35FE0045E114 + B65CFB8911B5C8310024A2D9 1CA23ED40692098700951B8B - B6F3647411AB35FE0045E114 + B65CFB8A11B5C8310024A2D9 B63EFA6111A093C200C90DCE - B6F3647511AB35FE0045E114 + B65CFB8B11B5C8310024A2D9 1CA23EDF0692099D00951B8B 1CA23EE00692099D00951B8B 1CA23EE10692099D00951B8B @@ -702,17 +710,11 @@ 5 WindowOrderList - B6F3650F11ADC40E0045E114 - B6F3651011ADC40E0045E114 - B6F366CF11B1A28C0045E114 - B6F3665F11B194AC0045E114 - B6F366D011B1A28C0045E114 - B6F366D111B1A28C0045E114 - B6F366D211B1A28C0045E114 + B65CFB8C11B5C8310024A2D9 /Users/kelvin/Projects/PROFuseX/PROFuseX.xcodeproj WindowString - 547 105 1239 1000 0 0 1920 1178 + 303 109 1239 1000 0 0 1920 1178 WindowToolsV3 diff --git a/PROFuseX.xcodeproj/project.pbxproj b/PROFuseX.xcodeproj/project.pbxproj index 0177646..be72592 100644 --- a/PROFuseX.xcodeproj/project.pbxproj +++ b/PROFuseX.xcodeproj/project.pbxproj @@ -90,6 +90,26 @@ B656AF1A11AA106C00AB578A /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; B656AF1B11AA106C00AB578A /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; B6F3648511AB363B0045E114 /* xattr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3647B11AB361D0045E114 /* xattr.cpp */; }; + B6F3676511B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; + B6F3676611B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; + B6F3676711B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; + B6F3676811B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; + B6F3682A11B431CC0045E114 /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; + B6F3682B11B431CC0045E114 /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; + B6F3682C11B431CC0045E114 /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; + B6F3682D11B431CC0045E114 /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; + B6F3682E11B431CC0045E114 /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; + B6F3682F11B431CC0045E114 /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; + B6F3683011B431CC0045E114 /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; + B6F3683111B431CC0045E114 /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; + B6F3683211B431CC0045E114 /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; + B6F3683311B431CC0045E114 /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; + B6F3683411B431CC0045E114 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; + B6F3683511B431CC0045E114 /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; + B6F3683611B431CC0045E114 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD111A09DB500C90DCE /* Exception.cpp */; }; + B6F3683711B431CC0045E114 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD311A09DB500C90DCE /* Lock.cpp */; }; + B6F3683811B431CC0045E114 /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; + B6F3683F11B431E20045E114 /* newfs_prodos.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3682111B430870045E114 /* newfs_prodos.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -148,6 +168,10 @@ B6F3651B11ADD0280045E114 /* FileEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileEntry.h; sourceTree = ""; }; B6F3651C11ADD0280045E114 /* Entry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Entry.h; sourceTree = ""; }; B6F3652711ADD52B0045E114 /* Pascal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Pascal.h; sourceTree = ""; }; + B6F3676311B323680045E114 /* TextWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextWriter.h; sourceTree = ""; }; + B6F3676411B323680045E114 /* TextWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextWriter.cpp; sourceTree = ""; }; + B6F3682111B430870045E114 /* newfs_prodos.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = newfs_prodos.cpp; sourceTree = ""; }; + B6F3682511B431AC0045E114 /* newfs_prodos */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = newfs_prodos; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -187,6 +211,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + B6F3682311B431AC0045E114 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -199,6 +230,7 @@ B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */, B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */, B63EFC9D11A35F8200C90DCE /* fuse_pascal_ops.cpp */, + B6F3682111B430870045E114 /* newfs_prodos.cpp */, B63EFBE711A244EE00C90DCE /* Pascal */, B63EFACF11A09DB500C90DCE /* ProFUSE */, B63EFAC811A09DAA00C90DCE /* File */, @@ -219,6 +251,7 @@ B656AE0311A84F5800AB578A /* fuse_pascal */, B656AF0311AA105500AB578A /* NibbleTest */, B6F3648011AB36260045E114 /* xattr */, + B6F3682511B431AC0045E114 /* newfs_prodos */, ); name = Products; sourceTree = ""; @@ -304,6 +337,8 @@ B6F3651A11ADD0280045E114 /* VolumeEntry.h */, B6F3651B11ADD0280045E114 /* FileEntry.h */, B6F3651C11ADD0280045E114 /* Entry.h */, + B6F3676311B323680045E114 /* TextWriter.h */, + B6F3676411B323680045E114 /* TextWriter.cpp */, ); path = Pascal; sourceTree = ""; @@ -399,6 +434,22 @@ productReference = B6F3648011AB36260045E114 /* xattr */; productType = "com.apple.product-type.tool"; }; + B6F3682411B431AC0045E114 /* newfs_prodos */ = { + isa = PBXNativeTarget; + buildConfigurationList = B6F3684111B432000045E114 /* Build configuration list for PBXNativeTarget "newfs_prodos" */; + buildPhases = ( + B6F3682211B431AC0045E114 /* Sources */, + B6F3682311B431AC0045E114 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = newfs_prodos; + productName = newfs_prodos; + productReference = B6F3682511B431AC0045E114 /* newfs_prodos */; + productType = "com.apple.product-type.tool"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -416,6 +467,7 @@ B656AE0211A84F5800AB578A /* fuse_pascal */, B656AF0211AA105500AB578A /* NibbleTest */, B6F3647F11AB36260045E114 /* xattr */, + B6F3682411B431AC0045E114 /* newfs_prodos */, ); }; /* End PBXProject section */ @@ -445,6 +497,7 @@ B63EFCE311A36C8B00C90DCE /* FileEntry.cpp in Sources */, B63EFCE511A36C8B00C90DCE /* VolumeEntry.cpp in Sources */, B63EFCE911A36C8B00C90DCE /* apfm.cpp in Sources */, + B6F3676711B323680045E114 /* TextWriter.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -472,6 +525,7 @@ B63EFE9611A4888500C90DCE /* FileEntry.cpp in Sources */, B63EFE9711A4888500C90DCE /* VolumeEntry.cpp in Sources */, B63EFE9911A4888500C90DCE /* newfs_pascal.cpp in Sources */, + B6F3676811B323680045E114 /* TextWriter.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -500,6 +554,7 @@ B656AE1911A84F7700AB578A /* Entry.cpp in Sources */, B656AE1A11A84F7700AB578A /* FileEntry.cpp in Sources */, B656AE1B11A84F7700AB578A /* VolumeEntry.cpp in Sources */, + B6F3676511B323680045E114 /* TextWriter.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -527,6 +582,7 @@ B656AF1A11AA106C00AB578A /* FileEntry.cpp in Sources */, B656AF1B11AA106C00AB578A /* VolumeEntry.cpp in Sources */, B656AF0811AA106400AB578A /* NibbleTest.cpp in Sources */, + B6F3676611B323680045E114 /* TextWriter.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -538,6 +594,29 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + B6F3682211B431AC0045E114 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B6F3682A11B431CC0045E114 /* Endian.cpp in Sources */, + B6F3682B11B431CC0045E114 /* BlockDevice.cpp in Sources */, + B6F3682C11B431CC0045E114 /* DavexDiskImage.cpp in Sources */, + B6F3682D11B431CC0045E114 /* DiskCopy42Image.cpp in Sources */, + B6F3682E11B431CC0045E114 /* DiskImage.cpp in Sources */, + B6F3682F11B431CC0045E114 /* RawDevice.cpp in Sources */, + B6F3683011B431CC0045E114 /* UniversalDiskImage.cpp in Sources */, + B6F3683111B431CC0045E114 /* BlockCache.cpp in Sources */, + B6F3683211B431CC0045E114 /* ConcreteBlockCache.cpp in Sources */, + B6F3683311B431CC0045E114 /* MappedBlockCache.cpp in Sources */, + B6F3683411B431CC0045E114 /* File.cpp in Sources */, + B6F3683511B431CC0045E114 /* MappedFile.cpp in Sources */, + B6F3683611B431CC0045E114 /* Exception.cpp in Sources */, + B6F3683711B431CC0045E114 /* Lock.cpp in Sources */, + B6F3683811B431CC0045E114 /* Adaptor.cpp in Sources */, + B6F3683F11B431E20045E114 /* newfs_prodos.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ @@ -805,6 +884,48 @@ }; name = Release; }; + B6F3682711B431AC0045E114 /* 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; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = newfs_prodos; + }; + name = Debug; + }; + B6F3682811B431AC0045E114 /* Debug fuse */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = newfs_prodos; + }; + name = "Debug fuse"; + }; + B6F3682911B431AC0045E114 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = newfs_prodos; + ZERO_LINK = NO; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -868,6 +989,16 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + B6F3684111B432000045E114 /* Build configuration list for PBXNativeTarget "newfs_prodos" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B6F3682711B431AC0045E114 /* Debug */, + B6F3682811B431AC0045E114 /* Debug fuse */, + B6F3682911B431AC0045E114 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index af04348..ec9f1aa 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -29,6 +29,29 @@ enum { kMaxFiles = 77 }; + + +// djb hash, case insensitive. +static unsigned NameHash(const char *cp) +{ + unsigned hash = 5381; + unsigned c; + while ((c = *cp++)) + { + c = std::toupper(c); + hash = ((hash << 5) + hash) + c; + } + + return hash & 0x7FFFFFFF; +} + +static bool NameEqual(const char *a, const char *b) +{ + return ::strcasecmp(a, b) == 0; +} + + + unsigned VolumeEntry::ValidName(const char *cp) { // 7 chars max. Legal values: ascii, printable, @@ -585,14 +608,16 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks) prev->_maxFileSize = prev->blocks() * 512; } - // insert() inserts an item *before* the current item. + // insert() inserts an item *before* the current item and returns an iterator to the + // element inserted. // afterwards, iter will point to curr+1 // keep track of the index *before* the insert. unsigned index = distance(_files.begin(), iter); // current index. - _files.insert(iter, entry.get()); - _fileCount++; + iter = _files.insert(iter, entry.get()); + ++_fileCount; + curr = entry.release(); curr->_parent = this; diff --git a/apfm.cpp b/bin/apfm.cpp similarity index 100% rename from apfm.cpp rename to bin/apfm.cpp diff --git a/fuse_pascal.cpp b/bin/fuse_pascal.cpp similarity index 100% rename from fuse_pascal.cpp rename to bin/fuse_pascal.cpp diff --git a/fuse_pascal_ops.cpp b/bin/fuse_pascal_ops.cpp similarity index 100% rename from fuse_pascal_ops.cpp rename to bin/fuse_pascal_ops.cpp diff --git a/newfs_pascal.cpp b/bin/newfs_pascal.cpp similarity index 100% rename from newfs_pascal.cpp rename to bin/newfs_pascal.cpp diff --git a/xattr.cpp b/bin/xattr.cpp similarity index 100% rename from xattr.cpp rename to bin/xattr.cpp diff --git a/newfs_prodos.cpp b/newfs_prodos.cpp index a7aaab0..7982c35 100644 --- a/newfs_prodos.cpp +++ b/newfs_prodos.cpp @@ -7,13 +7,8 @@ #include -#include "BlockDevice.h" -#include "DavexDiskImage.h" -#include "DiskCopy42Image.h" -#include "Entry.h" -#include "Exception.h" -#include "RawDevice.h" -#include "UniversalDiskImage.h" +#include +#include #define NEWFS_VERSION "0.1" @@ -173,7 +168,7 @@ int main(int argc, char **argv) case 'f': { - format = DiskImage::ImageType(optarg); + format = BlockDevice::ImageType(optarg); if (format == 0) { std::fprintf(stderr, "Error: `%s' is not a supported disk image format.\n", optarg); @@ -204,7 +199,7 @@ int main(int argc, char **argv) volumeName = "Untitled"; } - if (format == 0) format = DiskImage::ImageType(fname, '2IMG'); + if (format == 0) format = BlockDevice::ImageType(fname, '2IMG'); try From 670254034a158382788939ef1d8c8903f32c648a Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 26 Jun 2010 03:33:03 +0000 Subject: [PATCH 191/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@318 aa027e90-d47c-11dd-86d7-074df07e0730 --- PROFuseX.xcodeproj/kelvin.pbxuser | 142 ++++++++++++++++++++++- PROFuseX.xcodeproj/kelvin.perspectivev3 | 37 +++--- PROFuseX.xcodeproj/project.pbxproj | 48 ++++---- newfs_prodos.cpp => bin/newfs_prodos.cpp | 0 4 files changed, 188 insertions(+), 39 deletions(-) rename newfs_prodos.cpp => bin/newfs_prodos.cpp (100%) diff --git a/PROFuseX.xcodeproj/kelvin.pbxuser b/PROFuseX.xcodeproj/kelvin.pbxuser index db35621..3d99c21 100644 --- a/PROFuseX.xcodeproj/kelvin.pbxuser +++ b/PROFuseX.xcodeproj/kelvin.pbxuser @@ -64,7 +64,7 @@ PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_ObjectSize_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, - 10, + 660, 20, 48, 43, @@ -107,6 +107,13 @@ PBXWorkspaceStateSaveDate = 299215102; }; perUserProjectItems = { + B6272A9811D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9811D5AC5E0073C73A /* PBXTextBookmark */; + B6272A9911D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9911D5AC5E0073C73A /* PBXTextBookmark */; + B6272A9A11D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9A11D5AC5E0073C73A /* PBXTextBookmark */; + B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */; + B6272A9C11D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9C11D5AC5E0073C73A /* PBXTextBookmark */; + B6272A9D11D5AC5E0073C73A /* PBXBookmark */ = B6272A9D11D5AC5E0073C73A /* PBXBookmark */; + B6272A9E11D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9E11D5AC5E0073C73A /* PBXTextBookmark */; B63EFC2611A2D5A400C90DCE = B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */; B63EFC3211A2D5A400C90DCE = B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */; B63EFDA011A4488200C90DCE = B63EFDA011A4488200C90DCE /* PBXTextBookmark */; @@ -170,6 +177,105 @@ userBuildSettings = { }; }; + B6272A8E11D5AC3C0073C73A /* apfm.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 13975}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 562}"; + }; + }; + B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 4095}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 724}"; + }; + }; + B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 6396}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 643}"; + }; + }; + B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 4615}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 477}"; + }; + }; + B6272A9211D5AC3C0073C73A /* xattr.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 5434}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 936}"; + }; + }; + B6272A9811D5AC5E0073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 618"; + rLen = 6; + rLoc = 13761; + rType = 0; + vrLen = 1289; + vrLoc = 13115; + }; + B6272A9911D5AC5E0073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272A8E11D5AC3C0073C73A /* apfm.cpp */; + name = "apfm.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 562; + vrLoc = 0; + }; + B6272A9A11D5AC5E0073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */; + name = "fuse_pascal.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 724; + vrLoc = 0; + }; + B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */; + name = "fuse_pascal_ops.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 643; + vrLoc = 0; + }; + B6272A9C11D5AC5E0073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */; + name = "newfs_pascal.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 477; + vrLoc = 0; + }; + B6272A9D11D5AC5E0073C73A /* PBXBookmark */ = { + isa = PBXBookmark; + fRef = B6272A9211D5AC3C0073C73A /* xattr.cpp */; + }; + B6272A9E11D5AC5E0073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272A9211D5AC3C0073C73A /* xattr.cpp */; + name = "xattr.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 936; + vrLoc = 0; + }; B63EFA6711A093C200C90DCE /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; @@ -445,9 +551,9 @@ }; B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 12779}}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 13208}}"; sepNavSelRange = "{13761, 6}"; - sepNavVisRange = "{13015, 1389}"; + sepNavVisRange = "{13115, 1289}"; }; }; B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */ = { @@ -478,6 +584,12 @@ }; }; B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */ = { + isa = PBXFileReference; + fileEncoding = 4; + lastKnownFileType = sourcecode.cpp.cpp; + name = fuse_pascal.cpp; + path = /Users/kelvin/Projects/PROFuseX/fuse_pascal.cpp; + sourceTree = ""; uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 4082}}"; sepNavSelRange = "{4414, 0}"; @@ -485,6 +597,12 @@ }; }; B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */ = { + isa = PBXFileReference; + fileEncoding = 4; + lastKnownFileType = sourcecode.cpp.cpp; + name = newfs_pascal.cpp; + path = /Users/kelvin/Projects/PROFuseX/newfs_pascal.cpp; + sourceTree = ""; uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1009, 4381}}"; sepNavSelRange = "{4492, 0}"; @@ -492,6 +610,12 @@ }; }; B63EFC9D11A35F8200C90DCE /* fuse_pascal_ops.cpp */ = { + isa = PBXFileReference; + fileEncoding = 4; + lastKnownFileType = sourcecode.cpp.cpp; + name = fuse_pascal_ops.cpp; + path = /Users/kelvin/Projects/PROFuseX/fuse_pascal_ops.cpp; + sourceTree = ""; uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {701, 6448}}"; sepNavSelRange = "{855, 6}"; @@ -499,6 +623,12 @@ }; }; B63EFC9F11A35F8F00C90DCE /* apfm.cpp */ = { + isa = PBXFileReference; + fileEncoding = 4; + lastKnownFileType = sourcecode.cpp.cpp; + name = apfm.cpp; + path = /Users/kelvin/Projects/PROFuseX/apfm.cpp; + sourceTree = ""; uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1009, 14040}}"; sepNavSelRange = "{13109, 0}"; @@ -1019,6 +1149,12 @@ vrLoc = 442; }; B6F3647B11AB361D0045E114 /* xattr.cpp */ = { + isa = PBXFileReference; + fileEncoding = 4; + lastKnownFileType = sourcecode.cpp.cpp; + name = xattr.cpp; + path = /Users/kelvin/Projects/PROFuseX/xattr.cpp; + sourceTree = ""; uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 5512}}"; sepNavSelRange = "{6657, 6}"; diff --git a/PROFuseX.xcodeproj/kelvin.perspectivev3 b/PROFuseX.xcodeproj/kelvin.perspectivev3 index ff5f128..091e0f2 100644 --- a/PROFuseX.xcodeproj/kelvin.perspectivev3 +++ b/PROFuseX.xcodeproj/kelvin.perspectivev3 @@ -269,6 +269,7 @@ PBXSmartGroupTreeModuleOutlineStateExpansionKey 08FB7794FE84155DC02AAC07 + B6272A8D11D5AC3C0073C73A B63EFBE711A244EE00C90DCE B63EFACF11A09DB500C90DCE B63EFAC811A09DAA00C90DCE @@ -283,8 +284,8 @@ PBXSmartGroupTreeModuleOutlineStateSelectionKey - 14 - 8 + 6 + 1 0 @@ -322,7 +323,7 @@ PBXProjectModuleGUID B63EFA6111A093C200C90DCE PBXProjectModuleLabel - VolumeEntry.cpp + xattr.cpp PBXSplitModuleInNavigatorKey Split0 @@ -330,11 +331,11 @@ PBXProjectModuleGUID B63EFA6211A093C200C90DCE PBXProjectModuleLabel - VolumeEntry.cpp + xattr.cpp _historyCapacity 0 bookmark - B65CFB8811B5C8310024A2D9 + B6272A9E11D5AC5E0073C73A history B63EFC2611A2D5A400C90DCE @@ -393,7 +394,12 @@ B6F3684B11B44D090045E114 B65CFB6911B495790024A2D9 B65CFB6A11B495790024A2D9 - B65CFB6B11B495790024A2D9 + B6272A9811D5AC5E0073C73A + B6272A9911D5AC5E0073C73A + B6272A9A11D5AC5E0073C73A + B6272A9B11D5AC5E0073C73A + B6272A9C11D5AC5E0073C73A + B6272A9D11D5AC5E0073C73A SplitCount @@ -407,18 +413,18 @@ GeometryConfiguration Frame - {{0, 0}, {899, 544}} + {{0, 0}, {899, 535}} RubberWindowFrame 303 109 1239 1000 0 0 1920 1178 Module PBXNavigatorGroup Proportion - 544pt + 535pt Proportion - 410pt + 419pt Tabs @@ -432,7 +438,9 @@ GeometryConfiguration Frame - {{10, 27}, {0, -27}} + {{10, 27}, {899, 392}} + RubberWindowFrame + 303 109 1239 1000 0 0 1920 1178 Module XCDetailModule @@ -449,8 +457,6 @@ Frame {{10, 27}, {899, 383}} - RubberWindowFrame - 303 109 1239 1000 0 0 1920 1178 Module PBXProjectFindModule @@ -516,11 +522,11 @@ TableOfContents - B65CFB8911B5C8310024A2D9 + B6272A9F11D5AC5E0073C73A 1CA23ED40692098700951B8B - B65CFB8A11B5C8310024A2D9 + B6272AA011D5AC5E0073C73A B63EFA6111A093C200C90DCE - B65CFB8B11B5C8310024A2D9 + B6272AA111D5AC5E0073C73A 1CA23EDF0692099D00951B8B 1CA23EE00692099D00951B8B 1CA23EE10692099D00951B8B @@ -710,7 +716,6 @@ 5 WindowOrderList - B65CFB8C11B5C8310024A2D9 /Users/kelvin/Projects/PROFuseX/PROFuseX.xcodeproj WindowString diff --git a/PROFuseX.xcodeproj/project.pbxproj b/PROFuseX.xcodeproj/project.pbxproj index be72592..a29e1a9 100644 --- a/PROFuseX.xcodeproj/project.pbxproj +++ b/PROFuseX.xcodeproj/project.pbxproj @@ -7,6 +7,11 @@ objects = { /* Begin PBXBuildFile section */ + B6272A9311D5AC440073C73A /* apfm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A8E11D5AC3C0073C73A /* apfm.cpp */; }; + B6272A9411D5AC4C0073C73A /* fuse_pascal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */; }; + B6272A9511D5AC530073C73A /* fuse_pascal_ops.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */; }; + B6272A9611D5AC560073C73A /* newfs_pascal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */; }; + B6272A9711D5AC5B0073C73A /* xattr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A9211D5AC3C0073C73A /* xattr.cpp */; }; B63EFCD211A36C8B00C90DCE /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; B63EFCD311A36C8B00C90DCE /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; B63EFCD411A36C8B00C90DCE /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; @@ -26,7 +31,6 @@ B63EFCE211A36C8B00C90DCE /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; B63EFCE311A36C8B00C90DCE /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; B63EFCE511A36C8B00C90DCE /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; - B63EFCE911A36C8B00C90DCE /* apfm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; }; B63EFE8511A4888500C90DCE /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; B63EFE8611A4888500C90DCE /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; B63EFE8711A4888500C90DCE /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; @@ -46,7 +50,6 @@ B63EFE9511A4888500C90DCE /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; B63EFE9611A4888500C90DCE /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; B63EFE9711A4888500C90DCE /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; - B63EFE9911A4888500C90DCE /* newfs_pascal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; }; B656AE0811A84F6C00AB578A /* libfuse_ino64.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */; }; B656AE0911A84F7700AB578A /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; B656AE0A11A84F7700AB578A /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; @@ -67,8 +70,6 @@ B656AE1911A84F7700AB578A /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; B656AE1A11A84F7700AB578A /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; B656AE1B11A84F7700AB578A /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; - B656AE1D11A84F9300AB578A /* fuse_pascal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */; }; - B656AE1E11A84F9300AB578A /* fuse_pascal_ops.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFC9D11A35F8200C90DCE /* fuse_pascal_ops.cpp */; }; B656AF0811AA106400AB578A /* NibbleTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; }; B656AF0911AA106C00AB578A /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; B656AF0A11AA106C00AB578A /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; @@ -89,7 +90,6 @@ B656AF1911AA106C00AB578A /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; B656AF1A11AA106C00AB578A /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; B656AF1B11AA106C00AB578A /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; - B6F3648511AB363B0045E114 /* xattr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3647B11AB361D0045E114 /* xattr.cpp */; }; B6F3676511B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; B6F3676611B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; B6F3676711B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; @@ -113,6 +113,11 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + B6272A8E11D5AC3C0073C73A /* apfm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = apfm.cpp; sourceTree = ""; }; + B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fuse_pascal.cpp; sourceTree = ""; }; + B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fuse_pascal_ops.cpp; sourceTree = ""; }; + B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = newfs_pascal.cpp; sourceTree = ""; }; + B6272A9211D5AC3C0073C73A /* xattr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xattr.cpp; sourceTree = ""; }; B63EFA7511A0948500C90DCE /* Endian.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Endian.cpp; sourceTree = ""; }; B63EFA7611A0948500C90DCE /* Endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Endian.h; sourceTree = ""; }; B63EFA7711A0948500C90DCE /* IOBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOBuffer.h; sourceTree = ""; }; @@ -152,17 +157,12 @@ B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileEntry.cpp; sourceTree = ""; }; B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = VolumeEntry.cpp; sourceTree = ""; }; B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOBuffer.cpp.h; sourceTree = ""; }; - B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fuse_pascal.cpp; sourceTree = ""; }; - B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = newfs_pascal.cpp; sourceTree = ""; }; - B63EFC9D11A35F8200C90DCE /* fuse_pascal_ops.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fuse_pascal_ops.cpp; sourceTree = ""; }; - B63EFC9F11A35F8F00C90DCE /* apfm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = apfm.cpp; sourceTree = ""; }; B63EFCCE11A36C7300C90DCE /* apfpm */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = apfpm; sourceTree = BUILT_PRODUCTS_DIR; }; B63EFE8111A4886C00C90DCE /* newfs_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = newfs_pascal; sourceTree = BUILT_PRODUCTS_DIR; }; B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libfuse_ino64.dylib; path = /usr/local/lib/libfuse_ino64.dylib; sourceTree = ""; }; B656AE0311A84F5800AB578A /* fuse_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fuse_pascal; sourceTree = BUILT_PRODUCTS_DIR; }; B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NibbleTest.cpp; sourceTree = ""; }; B656AF0311AA105500AB578A /* NibbleTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NibbleTest; sourceTree = BUILT_PRODUCTS_DIR; }; - B6F3647B11AB361D0045E114 /* xattr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xattr.cpp; sourceTree = ""; }; B6F3648011AB36260045E114 /* xattr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xattr; sourceTree = BUILT_PRODUCTS_DIR; }; B6F3651A11ADD0280045E114 /* VolumeEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VolumeEntry.h; sourceTree = ""; }; B6F3651B11ADD0280045E114 /* FileEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileEntry.h; sourceTree = ""; }; @@ -224,12 +224,8 @@ 08FB7794FE84155DC02AAC07 /* PROFuseX */ = { isa = PBXGroup; children = ( - B6F3647B11AB361D0045E114 /* xattr.cpp */, - B63EFC9F11A35F8F00C90DCE /* apfm.cpp */, + B6272A8D11D5AC3C0073C73A /* bin */, B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */, - B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */, - B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */, - B63EFC9D11A35F8200C90DCE /* fuse_pascal_ops.cpp */, B6F3682111B430870045E114 /* newfs_prodos.cpp */, B63EFBE711A244EE00C90DCE /* Pascal */, B63EFACF11A09DB500C90DCE /* ProFUSE */, @@ -256,6 +252,18 @@ name = Products; sourceTree = ""; }; + B6272A8D11D5AC3C0073C73A /* bin */ = { + isa = PBXGroup; + children = ( + B6272A8E11D5AC3C0073C73A /* apfm.cpp */, + B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */, + B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */, + B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */, + B6272A9211D5AC3C0073C73A /* xattr.cpp */, + ); + path = bin; + sourceTree = ""; + }; B63EFA7411A0948500C90DCE /* Endian */ = { isa = PBXGroup; children = ( @@ -496,8 +504,8 @@ B63EFCE211A36C8B00C90DCE /* Entry.cpp in Sources */, B63EFCE311A36C8B00C90DCE /* FileEntry.cpp in Sources */, B63EFCE511A36C8B00C90DCE /* VolumeEntry.cpp in Sources */, - B63EFCE911A36C8B00C90DCE /* apfm.cpp in Sources */, B6F3676711B323680045E114 /* TextWriter.cpp in Sources */, + B6272A9311D5AC440073C73A /* apfm.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -524,8 +532,8 @@ B63EFE9511A4888500C90DCE /* Entry.cpp in Sources */, B63EFE9611A4888500C90DCE /* FileEntry.cpp in Sources */, B63EFE9711A4888500C90DCE /* VolumeEntry.cpp in Sources */, - B63EFE9911A4888500C90DCE /* newfs_pascal.cpp in Sources */, B6F3676811B323680045E114 /* TextWriter.cpp in Sources */, + B6272A9611D5AC560073C73A /* newfs_pascal.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -533,8 +541,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - B656AE1D11A84F9300AB578A /* fuse_pascal.cpp in Sources */, - B656AE1E11A84F9300AB578A /* fuse_pascal_ops.cpp in Sources */, B656AE0911A84F7700AB578A /* Endian.cpp in Sources */, B656AE0A11A84F7700AB578A /* BlockDevice.cpp in Sources */, B656AE0B11A84F7700AB578A /* DavexDiskImage.cpp in Sources */, @@ -555,6 +561,8 @@ B656AE1A11A84F7700AB578A /* FileEntry.cpp in Sources */, B656AE1B11A84F7700AB578A /* VolumeEntry.cpp in Sources */, B6F3676511B323680045E114 /* TextWriter.cpp in Sources */, + B6272A9411D5AC4C0073C73A /* fuse_pascal.cpp in Sources */, + B6272A9511D5AC530073C73A /* fuse_pascal_ops.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -590,7 +598,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - B6F3648511AB363B0045E114 /* xattr.cpp in Sources */, + B6272A9711D5AC5B0073C73A /* xattr.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/newfs_prodos.cpp b/bin/newfs_prodos.cpp similarity index 100% rename from newfs_prodos.cpp rename to bin/newfs_prodos.cpp From 98fd4a1af9a8a87e272914e2b6945c93dd75bcbd Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 26 Jun 2010 03:39:14 +0000 Subject: [PATCH 192/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@319 aa027e90-d47c-11dd-86d7-074df07e0730 --- Bitmap.cpp => ProDOS/Bitmap.cpp | 6 +++--- Bitmap.h => ProDOS/Bitmap.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) rename Bitmap.cpp => ProDOS/Bitmap.cpp (97%) rename Bitmap.h => ProDOS/Bitmap.h (90%) diff --git a/Bitmap.cpp b/ProDOS/Bitmap.cpp similarity index 97% rename from Bitmap.cpp rename to ProDOS/Bitmap.cpp index 1e3d246..57ed601 100644 --- a/Bitmap.cpp +++ b/ProDOS/Bitmap.cpp @@ -1,11 +1,11 @@ #include -#include "Bitmap.h" -#include "BlockDevice.h" +#include +#include #include "auto.h" -using namespace ProFUSE; +using namespace ProDOS; // returns # of 1-bits set (0-8) inline static unsigned popCount(uint8_t x) diff --git a/Bitmap.h b/ProDOS/Bitmap.h similarity index 90% rename from Bitmap.h rename to ProDOS/Bitmap.h index 243db9d..77388a6 100644 --- a/Bitmap.h +++ b/ProDOS/Bitmap.h @@ -5,7 +5,7 @@ -namespace ProFUSE { +namespace ProDOS { class BlockDevice; @@ -15,7 +15,7 @@ public: Bitmap(unsigned blocks); Bitmap(BlockDevice *device, unsigned keyPointer, unsigned blocks); - //todo -- constructor by loading fro, block device... + //todo -- constructor by loading from, block device... ~Bitmap(); int allocBlock(); From 70b921ffa4d8b6943b0c560d8a0bfdd031302469 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 13 Dec 2010 01:53:15 +0000 Subject: [PATCH 193/236] updated makefile git-svn-id: https://profuse.googlecode.com/svn/branches/v2@320 aa027e90-d47c-11dd-86d7-074df07e0730 --- Makefile | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index dfb097f..4eb4c0c 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = g++ -CPPFLAGS += -Wall -W -I. -O2 -g +CPPFLAGS += -Wall -W -Wno-multichar -I. -O2 -g LDFLAGS += -lpthread fuse_pascal_LDFLAGS += -lfuse @@ -14,7 +14,7 @@ newfs_pascal: newfs_pascal.o \ Endian/Endian.o \ File/File.o File/MappedFile.o \ ProFUSE/Exception.o ProFUSE/Lock.o \ - Pascal/Date.o Pascal/Entry.o Pascal/FileEntry.o Pascal/VolumeEntry.o + Pascal/Date.o Pascal/Entry.o Pascal/FileEntry.o Pascal/VolumeEntry.o Pascal/TextWriter.o apfm: apfm.o \ Cache/BlockCache.o Cache/ConcreteBlockCache.o Cache/MappedBlockCache.o \ @@ -24,7 +24,7 @@ apfm: apfm.o \ Endian/Endian.o \ File/File.o File/MappedFile.o \ ProFUSE/Exception.o ProFUSE/Lock.o \ - Pascal/Date.o Pascal/Entry.o Pascal/FileEntry.o Pascal/VolumeEntry.o + Pascal/Date.o Pascal/Entry.o Pascal/FileEntry.o Pascal/VolumeEntry.o Pascal/TextWriter.o fuse_pascal: fuse_pascal.o fuse_pascal_ops.o \ @@ -35,7 +35,7 @@ fuse_pascal: fuse_pascal.o fuse_pascal_ops.o \ Endian/Endian.o \ File/File.o File/MappedFile.o \ ProFUSE/Exception.o ProFUSE/Lock.o \ - Pascal/Date.o Pascal/Entry.o Pascal/FileEntry.o Pascal/VolumeEntry.o + Pascal/Date.o Pascal/Entry.o Pascal/FileEntry.o Pascal/VolumeEntry.o Pascal/TextWriter.o $(CC) -lfuse $(LDFLAGS) $^ -o $@ @@ -131,7 +131,7 @@ Pascal/FileEntry.o: Pascal/FileEntry.cpp Pascal/Pascal.h Pascal/Date.h \ Pascal/Entry.h Pascal/FileEntry.h Pascal/VolumeEntry.h ProFUSE/auto.h \ ProFUSE/Exception.h Endian/Endian.h Endian/IOBuffer.h \ Endian/IOBuffer.cpp.h Device/BlockDevice.h Device/TrackSector.h \ - Cache/BlockCache.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 ProFUSE/auto.h \ @@ -139,3 +139,5 @@ Pascal/VolumeEntry.o: Pascal/VolumeEntry.cpp Pascal/Pascal.h Pascal/Date.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 ProFUSE/Exception.h From d9c9d49872dc413813b3cd7b7ade234011f7f76d Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 14 Dec 2010 21:45:25 +0000 Subject: [PATCH 194/236] updated makefile git-svn-id: https://profuse.googlecode.com/svn/branches/v2@321 aa027e90-d47c-11dd-86d7-074df07e0730 --- Makefile | 113 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 79 insertions(+), 34 deletions(-) diff --git a/Makefile b/Makefile index 4eb4c0c..750cced 100644 --- a/Makefile +++ b/Makefile @@ -3,56 +3,101 @@ CPPFLAGS += -Wall -W -Wno-multichar -I. -O2 -g LDFLAGS += -lpthread fuse_pascal_LDFLAGS += -lfuse -xattr: xattr.o - $(CC) $^ -o $@ +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 ProFUSE/*.o} -newfs_pascal: newfs_pascal.o \ - Cache/BlockCache.o Cache/ConcreteBlockCache.o Cache/MappedBlockCache.o \ - Device/Adaptor.o Device/BlockDevice.o Device/DavexDiskImage.o \ - Device/DiskCopy42Image.o Device/DiskImage.o Device/RawDevice.o \ - Device/UniversalDiskImage.o \ - Endian/Endian.o \ - File/File.o File/MappedFile.o \ - ProFUSE/Exception.o ProFUSE/Lock.o \ - Pascal/Date.o Pascal/Entry.o Pascal/FileEntry.o Pascal/VolumeEntry.o Pascal/TextWriter.o +TARGETS = apfm newfs_pascal profuse_pascal xattr -apfm: apfm.o \ - Cache/BlockCache.o Cache/ConcreteBlockCache.o Cache/MappedBlockCache.o \ - Device/Adaptor.o Device/BlockDevice.o Device/DavexDiskImage.o \ - Device/DiskCopy42Image.o Device/DiskImage.o Device/RawDevice.o \ - Device/UniversalDiskImage.o \ - Endian/Endian.o \ - File/File.o File/MappedFile.o \ - ProFUSE/Exception.o ProFUSE/Lock.o \ - Pascal/Date.o Pascal/Entry.o Pascal/FileEntry.o Pascal/VolumeEntry.o Pascal/TextWriter.o +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 + +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 + +PROFUSE_OBJECTS += ProFUSE/Exception.o +PROFUSE_OBJECTS += ProFUSE/Lock.o -fuse_pascal: fuse_pascal.o fuse_pascal_ops.o \ - Cache/BlockCache.o Cache/ConcreteBlockCache.o Cache/MappedBlockCache.o \ - Device/Adaptor.o Device/BlockDevice.o Device/DavexDiskImage.o \ - Device/DiskCopy42Image.o Device/DiskImage.o Device/RawDevice.o \ - Device/UniversalDiskImage.o \ - Endian/Endian.o \ - File/File.o File/MappedFile.o \ - ProFUSE/Exception.o ProFUSE/Lock.o \ - Pascal/Date.o Pascal/Entry.o Pascal/FileEntry.o Pascal/VolumeEntry.o Pascal/TextWriter.o + +xattr: bin/xattr.o + $(CC) $(LDFLAGS) $^ -o $@ + +newfs_pascal: bin/newfs_pascal.o \ + ${CACHE_OBJECTS} \ + ${DEVICE_OBJECTS} \ + ${ENDIAN_OBJECTS} \ + ${FILE_OBJECTS} \ + ${PROFUSE_OBJECTS} \ + ${PASCAL_OBJECTS} + $(CC) $(LDFLAGS) $^ -o $@ + +apfm: bin/apfm.o \ + ${CACHE_OBJECTS} \ + ${DEVICE_OBJECTS} \ + ${ENDIAN_OBJECTS} \ + ${FILE_OBJECTS} \ + ${PROFUSE_OBJECTS} \ + ${PASCAL_OBJECTS} + $(CC) $(LDFLAGS) $^ -o $@ + + +fuse_pascal: bin/fuse_pascal.o bin/fuse_pascal_ops.o \ + ${CACHE_OBJECTS} \ + ${DEVICE_OBJECTS} \ + ${ENDIAN_OBJECTS} \ + ${FILE_OBJECTS} \ + ${PROFUSE_OBJECTS} \ + ${PASCAL_OBJECTS} $(CC) -lfuse $(LDFLAGS) $^ -o $@ -xattr.o: xattr.cpp +clean: + rm -f ${OBJECTS} ${TARGETS} + +xattr.o: bin/xattr.cpp -newfs_pascal.o: newfs_pascal.cpp Device/BlockDevice.h ProFUSE/Exception.h \ +newfs_pascal.o: bin/newfs_pascal.cpp Device/BlockDevice.h ProFUSE/Exception.h \ Device/TrackSector.h Cache/BlockCache.h Device/RawDevice.h File/File.h \ Pascal/Pascal.h Pascal/Date.h -fuse_pascal.o: fuse_pascal.cpp Pascal/Pascal.h Pascal/Date.h \ +fuse_pascal.o: bin/fuse_pascal.cpp Pascal/Pascal.h Pascal/Date.h \ ProFUSE/Exception.h Device/BlockDevice.h Device/TrackSector.h \ Cache/BlockCache.h -fuse_pascal_ops.o: fuse_pascal_ops.cpp Pascal/Pascal.h Pascal/Date.h \ +fuse_pascal_ops.o: bin/fuse_pascal_ops.cpp Pascal/Pascal.h Pascal/Date.h \ ProFUSE/auto.h ProFUSE/Exception.h -apfm.o: apfm.cpp Pascal/Pascal.h Pascal/Date.h Device/BlockDevice.h \ +apfm.o: bin/apfm.cpp Pascal/Pascal.h Pascal/Date.h Device/BlockDevice.h \ ProFUSE/Exception.h Device/TrackSector.h Cache/BlockCache.h File/File.o: File/File.cpp File/File.h ProFUSE/Exception.h From 8bda443e0eb903e7f0fb28c2e0ba4b7f3578ce59 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 15 Dec 2010 19:51:02 +0000 Subject: [PATCH 195/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@322 aa027e90-d47c-11dd-86d7-074df07e0730 --- {bin => bin_src}/apfm.cpp | 0 {bin => bin_src}/fuse_pascal.cpp | 0 {bin => bin_src}/fuse_pascal_ops.cpp | 0 {bin => bin_src}/newfs_pascal.cpp | 0 {bin => bin_src}/newfs_prodos.cpp | 0 {bin => bin_src}/xattr.cpp | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename {bin => bin_src}/apfm.cpp (100%) rename {bin => bin_src}/fuse_pascal.cpp (100%) rename {bin => bin_src}/fuse_pascal_ops.cpp (100%) rename {bin => bin_src}/newfs_pascal.cpp (100%) rename {bin => bin_src}/newfs_prodos.cpp (100%) rename {bin => bin_src}/xattr.cpp (100%) diff --git a/bin/apfm.cpp b/bin_src/apfm.cpp similarity index 100% rename from bin/apfm.cpp rename to bin_src/apfm.cpp diff --git a/bin/fuse_pascal.cpp b/bin_src/fuse_pascal.cpp similarity index 100% rename from bin/fuse_pascal.cpp rename to bin_src/fuse_pascal.cpp diff --git a/bin/fuse_pascal_ops.cpp b/bin_src/fuse_pascal_ops.cpp similarity index 100% rename from bin/fuse_pascal_ops.cpp rename to bin_src/fuse_pascal_ops.cpp diff --git a/bin/newfs_pascal.cpp b/bin_src/newfs_pascal.cpp similarity index 100% rename from bin/newfs_pascal.cpp rename to bin_src/newfs_pascal.cpp diff --git a/bin/newfs_prodos.cpp b/bin_src/newfs_prodos.cpp similarity index 100% rename from bin/newfs_prodos.cpp rename to bin_src/newfs_prodos.cpp diff --git a/bin/xattr.cpp b/bin_src/xattr.cpp similarity index 100% rename from bin/xattr.cpp rename to bin_src/xattr.cpp From 06bd252ebfa96a4d1ea2b3ea2123b5a28f494050 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 15 Dec 2010 19:56:46 +0000 Subject: [PATCH 196/236] move back git-svn-id: https://profuse.googlecode.com/svn/branches/v2@323 aa027e90-d47c-11dd-86d7-074df07e0730 --- {bin_src => bin}/apfm.cpp | 0 {bin_src => bin}/fuse_pascal.cpp | 0 {bin_src => bin}/fuse_pascal_ops.cpp | 0 {bin_src => bin}/newfs_pascal.cpp | 0 {bin_src => bin}/newfs_prodos.cpp | 0 {bin_src => bin}/xattr.cpp | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename {bin_src => bin}/apfm.cpp (100%) rename {bin_src => bin}/fuse_pascal.cpp (100%) rename {bin_src => bin}/fuse_pascal_ops.cpp (100%) rename {bin_src => bin}/newfs_pascal.cpp (100%) rename {bin_src => bin}/newfs_prodos.cpp (100%) rename {bin_src => bin}/xattr.cpp (100%) diff --git a/bin_src/apfm.cpp b/bin/apfm.cpp similarity index 100% rename from bin_src/apfm.cpp rename to bin/apfm.cpp diff --git a/bin_src/fuse_pascal.cpp b/bin/fuse_pascal.cpp similarity index 100% rename from bin_src/fuse_pascal.cpp rename to bin/fuse_pascal.cpp diff --git a/bin_src/fuse_pascal_ops.cpp b/bin/fuse_pascal_ops.cpp similarity index 100% rename from bin_src/fuse_pascal_ops.cpp rename to bin/fuse_pascal_ops.cpp diff --git a/bin_src/newfs_pascal.cpp b/bin/newfs_pascal.cpp similarity index 100% rename from bin_src/newfs_pascal.cpp rename to bin/newfs_pascal.cpp diff --git a/bin_src/newfs_prodos.cpp b/bin/newfs_prodos.cpp similarity index 100% rename from bin_src/newfs_prodos.cpp rename to bin/newfs_prodos.cpp diff --git a/bin_src/xattr.cpp b/bin/xattr.cpp similarity index 100% rename from bin_src/xattr.cpp rename to bin/xattr.cpp From 6b6ad10ba08f627cbddcb32f44e314e2088e21e6 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 15 Feb 2011 04:00:54 +0000 Subject: [PATCH 197/236] move typedef for clang compatibility. git-svn-id: https://profuse.googlecode.com/svn/branches/v2@324 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/ConcreteBlockCache.cpp | 2 +- Cache/ConcreteBlockCache.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Cache/ConcreteBlockCache.cpp b/Cache/ConcreteBlockCache.cpp index 5bd77b3..5e0bd69 100644 --- a/Cache/ConcreteBlockCache.cpp +++ b/Cache/ConcreteBlockCache.cpp @@ -55,7 +55,7 @@ using ProFUSE::Exception; using ProFUSE::POSIXException; -typedef std::vector::iterator EntryIter; +//typedef std::vector::iterator EntryIter; diff --git a/Cache/ConcreteBlockCache.h b/Cache/ConcreteBlockCache.h index de46b8b..2ca5698 100644 --- a/Cache/ConcreteBlockCache.h +++ b/Cache/ConcreteBlockCache.h @@ -36,6 +36,8 @@ private: }; + typedef std::vector::iterator EntryIter; + enum { HashTableSize = 23 }; std::vector_buffers; From 539aa1310c950897b1174803bdcb5c3c480f8f9b Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 15 Feb 2011 04:42:14 +0000 Subject: [PATCH 198/236] fix new Exception throwing. git-svn-id: https://profuse.googlecode.com/svn/branches/v2@325 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/RawDevice.cpp | 4 ++-- Pascal/VolumeEntry.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Device/RawDevice.cpp b/Device/RawDevice.cpp index 2056311..91a88b3 100644 --- a/Device/RawDevice.cpp +++ b/Device/RawDevice.cpp @@ -157,7 +157,7 @@ RawDevice::RawDevice(const char *name, File::FileFlags flags) : if (!_file.isValid()) { - throw new Exception(__METHOD__ ": Invalid file handle."); + throw Exception(__METHOD__ ": Invalid file handle."); } _readOnly = flags == File::ReadOnly; @@ -178,7 +178,7 @@ RawDevice::RawDevice(File& file, File::FileFlags flags) : if (!_file.isValid()) { - throw new Exception(__METHOD__ ": Invalid file handle."); + throw Exception(__METHOD__ ": Invalid file handle."); } _readOnly = flags == File::ReadOnly; diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index ec9f1aa..68f3cd3 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -262,7 +262,7 @@ void VolumeEntry::init(void *vp) // verify filenamelength <= 7 if (_fileNameLength > 7) - throw new ProDOSException(__METHOD__ ": invalid name length", ProFUSE::badPathSyntax); + throw ProDOSException(__METHOD__ ": invalid name length", ProFUSE::badPathSyntax); // verify fileKind == 0 // verify _fileCount reasonable From b07c64361d98f9a9df59193f2277126045a59f8c Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 16 Feb 2011 00:23:43 +0000 Subject: [PATCH 199/236] errorString() to return error as text. git-svn-id: https://profuse.googlecode.com/svn/branches/v2@326 aa027e90-d47c-11dd-86d7-074df07e0730 --- ProFUSE/Exception.cpp | 135 ++++++++++++++++++++++++++++++++++++++++++ ProFUSE/Exception.h | 5 ++ 2 files changed, 140 insertions(+) diff --git a/ProFUSE/Exception.cpp b/ProFUSE/Exception.cpp index 3dad581..a42b877 100644 --- a/ProFUSE/Exception.cpp +++ b/ProFUSE/Exception.cpp @@ -1,5 +1,6 @@ #include +#include using namespace ProFUSE; @@ -10,4 +11,138 @@ Exception::~Exception() throw() const char *Exception::what() { return _string.c_str(); +} + +const char *Exception::errorString() +{ + return ""; +} + + +const char *POSIXException::errorString() +{ + return strerror(error()); +} + +const char *ProDOSException::errorString() +{ + + + switch (error()) + { + case badSystemCall: + return "Bad System Call"; + case invalidPcount: + return "Invalid Parameter Count"; + case gsosActive: + return "GS/OS Active"; + case devNotFound: + return "Device Not Found"; + case invalidDevNum: + return "Invalid Device Number"; + case drvrBadReq: + return "Driver Bad Request"; + case drvrBadCode: + return "Driver Bad Code"; + case drvrBadParm: + return "Driver Bad Parameter"; + case drvrNotOpen: + return "Driver Not Open"; + case drvrPriorOpen: + return "Driver Prior Open"; + case irqTableFull: + return "IRQ Table Full"; + case drvrNoResrc: + return "Driver No Resource"; + case drvrIOError: + return "Driver IO Error"; + case drvrNoDevice: + return "Driver No Device"; + case drvrBusy: + return "Driver Busy"; + case drvrWrtProt: + return "Driver Write Protected"; + case drvrBadCount: + return "Driver Bad Count"; + case drvrBadBlock: + return "Driver Bad Block"; + case drvrDiskSwitch: + return "Driver Disk Switch"; + case drvrOffLine: + return "Driver Off Line"; + case badPathSyntax: + return "Bad Path Syntax"; + case invalidRefNum: + return "Invalid Ref Num"; + case pathNotFound: + return "Path Not Found"; + case volNotFound: + return "Volume Not Found"; + case fileNotFound: + return "File Not Found"; + case dupPathName: + return "Duplicate Path Name"; + case volumeFull: + return "Volume Full"; + case volDirFull: + return "Volume Directory Full"; + case badFileFormat: + return "Bad File Format"; + case badStoreType: + return "Bad Storage Type"; + case eofEncountered: + return "End of File"; + case outOfRange: + return "Out of Range"; + case invalidAccess: + return "Invalid Access"; + case buffTooSmall: + return "Buffer Too Small"; + case fileBusy: + return "File Busy"; + case dirError: + return "Directory Error"; + case unknownVol: + return "Unknown Volume"; + case paramRangeError: + return "Parameter Range Error"; + case outOfMem: + return "Out of Memory"; + case dupVolume: + return "Duplicate Volume"; + case notBlockDev: + return "Not a Block Device"; + case invalidLevel: + return "Invalid Level"; + case damagedBitMap: + return "Damaged Bit Map"; + case badPathNames: + return "Bad Path Names"; + case notSystemFile: + return "Not a System File"; + case osUnsupported: + return "OS Unsupported"; + case stackOverflow: + return "Stack Overflow"; + case dataUnavail: + return "Data Unavailable"; + case endOfDir: + return "End Of Directory"; + case invalidClass: + return "Invalid Class"; + case resForkNotFound: + return "Resource Fork Not Found"; + case invalidFSTID: + return "Invalid FST ID"; + case devNameErr: + return "Device Name Error"; + case resExistsErr: + return "Resource Exists Error"; + case resAddErr: + return "Resource Add Error"; + + default: + return ""; + } + return ""; } \ No newline at end of file diff --git a/ProFUSE/Exception.h b/ProFUSE/Exception.h index 3216081..caa9964 100644 --- a/ProFUSE/Exception.h +++ b/ProFUSE/Exception.h @@ -77,6 +77,7 @@ public: virtual ~Exception() throw (); virtual const char *what(); + virtual const char *errorString(); int error() const { return _error; } @@ -94,12 +95,16 @@ 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): From f373fa436e69111624ffc08f9e9c8b3b07b82ab6 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 16 Feb 2011 02:43:53 +0000 Subject: [PATCH 200/236] updated project for xcode 4 git-svn-id: https://profuse.googlecode.com/svn/branches/v2@327 aa027e90-d47c-11dd-86d7-074df07e0730 --- PROFuseX.xcodeproj/kelvin.pbxuser | 359 ++++++++++++++---------- PROFuseX.xcodeproj/kelvin.perspectivev3 | 46 +-- PROFuseX.xcodeproj/project.pbxproj | 42 ++- 3 files changed, 276 insertions(+), 171 deletions(-) diff --git a/PROFuseX.xcodeproj/kelvin.pbxuser b/PROFuseX.xcodeproj/kelvin.pbxuser index 3d99c21..a4ce6fe 100644 --- a/PROFuseX.xcodeproj/kelvin.pbxuser +++ b/PROFuseX.xcodeproj/kelvin.pbxuser @@ -2,9 +2,10 @@ { 08FB7793FE84155DC02AAC07 /* Project object */ = { activeBuildConfigurationName = Debug; - activeExecutable = B63EFE8211A4886C00C90DCE /* newfs_pascal */; - activeTarget = B63EFE8011A4886C00C90DCE /* newfs_pascal */; + activeExecutable = B6F3682611B431AC0045E114 /* newfs_prodos */; + activeTarget = B6F3682411B431AC0045E114 /* newfs_prodos */; addToTargets = ( + B6F3682411B431AC0045E114 /* newfs_prodos */, ); breakpoints = ( B6F3642F11AA1E150045E114 /* NibbleTest.cpp:76 */, @@ -112,66 +113,69 @@ B6272A9A11D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9A11D5AC5E0073C73A /* PBXTextBookmark */; B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */; B6272A9C11D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9C11D5AC5E0073C73A /* PBXTextBookmark */; - B6272A9D11D5AC5E0073C73A /* PBXBookmark */ = B6272A9D11D5AC5E0073C73A /* PBXBookmark */; - B6272A9E11D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9E11D5AC5E0073C73A /* PBXTextBookmark */; - B63EFC2611A2D5A400C90DCE = B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */; - B63EFC3211A2D5A400C90DCE = B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */; - B63EFDA011A4488200C90DCE = B63EFDA011A4488200C90DCE /* PBXTextBookmark */; - B63EFDA511A4488200C90DCE = B63EFDA511A4488200C90DCE /* PBXTextBookmark */; - B63EFDA711A4488200C90DCE = B63EFDA711A4488200C90DCE /* PBXTextBookmark */; - B63EFDA911A4488200C90DCE = B63EFDA911A4488200C90DCE /* PBXTextBookmark */; - B63EFDAB11A4488200C90DCE = B63EFDAB11A4488200C90DCE /* PBXTextBookmark */; - B63EFDAD11A4488200C90DCE = B63EFDAD11A4488200C90DCE /* PBXTextBookmark */; - B63EFDAF11A4488200C90DCE = B63EFDAF11A4488200C90DCE /* PBXTextBookmark */; - B63EFDB111A4488200C90DCE = B63EFDB111A4488200C90DCE /* PBXTextBookmark */; - B63EFDB311A4488200C90DCE = B63EFDB311A4488200C90DCE /* PBXTextBookmark */; - B63EFDB711A4488200C90DCE = B63EFDB711A4488200C90DCE /* PBXTextBookmark */; - B63EFDF211A4504200C90DCE = B63EFDF211A4504200C90DCE /* PBXTextBookmark */; - B63EFEA011A488C200C90DCE = B63EFEA011A488C200C90DCE /* PBXTextBookmark */; - B63EFEA111A488C200C90DCE = B63EFEA111A488C200C90DCE /* PBXTextBookmark */; - B63EFEA811A488C200C90DCE = B63EFEA811A488C200C90DCE /* PBXTextBookmark */; - B656AE2411A84FA400AB578A = B656AE2411A84FA400AB578A /* PBXTextBookmark */; - B656AE2611A84FA400AB578A = B656AE2611A84FA400AB578A /* PBXTextBookmark */; - B65CFB6911B495790024A2D9 = B65CFB6911B495790024A2D9 /* PBXTextBookmark */; - B65CFB6A11B495790024A2D9 = B65CFB6A11B495790024A2D9 /* PBXTextBookmark */; - B65CFB6B11B495790024A2D9 = B65CFB6B11B495790024A2D9 /* PBXTextBookmark */; - B65CFB8811B5C8310024A2D9 = B65CFB8811B5C8310024A2D9 /* PBXTextBookmark */; - B6E5F0DD11A60726000AD141 = B6E5F0DD11A60726000AD141 /* PBXTextBookmark */; - B6E5F0F211A73144000AD141 = B6E5F0F211A73144000AD141 /* PBXTextBookmark */; - B6E5F11211A73340000AD141 = B6E5F11211A73340000AD141 /* PBXTextBookmark */; - B6E5F13A11A74F2B000AD141 = B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */; - B6E5F18211A76B74000AD141 = B6E5F18211A76B74000AD141 /* PBXTextBookmark */; - B6F3647111AB35FE0045E114 = B6F3647111AB35FE0045E114 /* PBXTextBookmark */; - B6F3649E11AB59190045E114 = B6F3649E11AB59190045E114 /* PBXTextBookmark */; - B6F364B711AB84840045E114 = B6F364B711AB84840045E114 /* PBXTextBookmark */; - B6F3652E11ADD5D20045E114 = B6F3652E11ADD5D20045E114 /* PBXTextBookmark */; - B6F3653011ADD5D20045E114 = B6F3653011ADD5D20045E114 /* PBXTextBookmark */; - B6F3657E11AE255B0045E114 = B6F3657E11AE255B0045E114 /* PBXTextBookmark */; - B6F3665411B190370045E114 = B6F3665411B190370045E114 /* PBXTextBookmark */; - B6F3665C11B194AC0045E114 = B6F3665C11B194AC0045E114 /* PBXTextBookmark */; - B6F366C211B1A28C0045E114 = B6F366C211B1A28C0045E114 /* PBXTextBookmark */; - B6F366C411B1A28C0045E114 = B6F366C411B1A28C0045E114 /* PBXTextBookmark */; - B6F366C511B1A28C0045E114 = B6F366C511B1A28C0045E114 /* PBXTextBookmark */; - B6F366C611B1A28C0045E114 = B6F366C611B1A28C0045E114 /* PBXTextBookmark */; - B6F366C711B1A28C0045E114 = B6F366C711B1A28C0045E114 /* PBXTextBookmark */; - B6F366C811B1A28C0045E114 = B6F366C811B1A28C0045E114 /* PBXTextBookmark */; - B6F366C911B1A28C0045E114 = B6F366C911B1A28C0045E114 /* PBXTextBookmark */; - B6F366CA11B1A28C0045E114 = B6F366CA11B1A28C0045E114 /* PBXTextBookmark */; - B6F366CB11B1A28C0045E114 = B6F366CB11B1A28C0045E114 /* PBXTextBookmark */; - B6F366CC11B1A28C0045E114 = B6F366CC11B1A28C0045E114 /* PBXTextBookmark */; - B6F366D911B1A7A70045E114 = B6F366D911B1A7A70045E114 /* PBXTextBookmark */; - B6F3670611B2B47E0045E114 = B6F3670611B2B47E0045E114 /* PBXTextBookmark */; - B6F3675411B316D10045E114 = B6F3675411B316D10045E114 /* PBXTextBookmark */; - B6F3677C11B326580045E114 = B6F3677C11B326580045E114 /* PBXTextBookmark */; - B6F3677D11B326580045E114 = B6F3677D11B326580045E114 /* PBXTextBookmark */; - B6F3677E11B326580045E114 = B6F3677E11B326580045E114 /* PBXTextBookmark */; - B6F3677F11B326580045E114 = B6F3677F11B326580045E114 /* PBXTextBookmark */; - B6F367A011B330D10045E114 = B6F367A011B330D10045E114 /* PBXTextBookmark */; - B6F367AE11B337A70045E114 = B6F367AE11B337A70045E114 /* PBXTextBookmark */; - B6F367E911B40F650045E114 = B6F367E911B40F650045E114 /* PBXTextBookmark */; - B6F3684911B44D090045E114 = B6F3684911B44D090045E114 /* PBXTextBookmark */; - B6F3684A11B44D090045E114 = B6F3684A11B44D090045E114 /* PBXTextBookmark */; - B6F3684B11B44D090045E114 = B6F3684B11B44D090045E114 /* PBXTextBookmark */; + B6272B0D11D691320073C73A /* PBXTextBookmark */ = B6272B0D11D691320073C73A /* PBXTextBookmark */; + B6272B0E11D691320073C73A /* PBXTextBookmark */ = B6272B0E11D691320073C73A /* PBXTextBookmark */; + B6272B0F11D691320073C73A /* PBXTextBookmark */ = B6272B0F11D691320073C73A /* PBXTextBookmark */; + B6272B1011D691320073C73A /* PBXTextBookmark */ = B6272B1011D691320073C73A /* PBXTextBookmark */; + B6272B1111D691320073C73A /* XCBuildMessageTextBookmark */ = B6272B1111D691320073C73A /* XCBuildMessageTextBookmark */; + B6272B1311D691320073C73A /* PBXTextBookmark */ = B6272B1311D691320073C73A /* PBXTextBookmark */; + B6272B1411D691320073C73A /* PBXTextBookmark */ = B6272B1411D691320073C73A /* PBXTextBookmark */; + B6272B1511D691320073C73A /* PBXTextBookmark */ = B6272B1511D691320073C73A /* PBXTextBookmark */; + B6272B1611D691320073C73A /* PBXTextBookmark */ = B6272B1611D691320073C73A /* PBXTextBookmark */; + B6272B1711D691320073C73A /* PBXTextBookmark */ = B6272B1711D691320073C73A /* PBXTextBookmark */; + B6272B7711D6A3C30073C73A /* PBXTextBookmark */ = B6272B7711D6A3C30073C73A /* PBXTextBookmark */; + B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */ = B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */; + B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */ = B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */; + B63EFDA011A4488200C90DCE /* PBXTextBookmark */ = B63EFDA011A4488200C90DCE /* PBXTextBookmark */; + B63EFDA511A4488200C90DCE /* PBXTextBookmark */ = B63EFDA511A4488200C90DCE /* PBXTextBookmark */; + B63EFDA711A4488200C90DCE /* PBXTextBookmark */ = B63EFDA711A4488200C90DCE /* PBXTextBookmark */; + B63EFDA911A4488200C90DCE /* PBXTextBookmark */ = B63EFDA911A4488200C90DCE /* PBXTextBookmark */; + B63EFDAB11A4488200C90DCE /* PBXTextBookmark */ = B63EFDAB11A4488200C90DCE /* PBXTextBookmark */; + B63EFDAD11A4488200C90DCE /* PBXTextBookmark */ = B63EFDAD11A4488200C90DCE /* PBXTextBookmark */; + B63EFDAF11A4488200C90DCE /* PBXTextBookmark */ = B63EFDAF11A4488200C90DCE /* PBXTextBookmark */; + B63EFDB111A4488200C90DCE /* PBXTextBookmark */ = B63EFDB111A4488200C90DCE /* PBXTextBookmark */; + B63EFDB311A4488200C90DCE /* PBXTextBookmark */ = B63EFDB311A4488200C90DCE /* PBXTextBookmark */; + B63EFDF211A4504200C90DCE /* PBXTextBookmark */ = B63EFDF211A4504200C90DCE /* PBXTextBookmark */; + B63EFEA011A488C200C90DCE /* PBXTextBookmark */ = B63EFEA011A488C200C90DCE /* PBXTextBookmark */; + B63EFEA111A488C200C90DCE /* PBXTextBookmark */ = B63EFEA111A488C200C90DCE /* PBXTextBookmark */; + B63EFEA811A488C200C90DCE /* PBXTextBookmark */ = B63EFEA811A488C200C90DCE /* PBXTextBookmark */; + B656AE2411A84FA400AB578A /* PBXTextBookmark */ = B656AE2411A84FA400AB578A /* PBXTextBookmark */; + B656AE2611A84FA400AB578A /* PBXTextBookmark */ = B656AE2611A84FA400AB578A /* PBXTextBookmark */; + B65CFB6911B495790024A2D9 /* PBXTextBookmark */ = B65CFB6911B495790024A2D9 /* PBXTextBookmark */; + B65CFB6A11B495790024A2D9 /* PBXTextBookmark */ = B65CFB6A11B495790024A2D9 /* PBXTextBookmark */; + B6E5F0DD11A60726000AD141 /* PBXTextBookmark */ = B6E5F0DD11A60726000AD141 /* PBXTextBookmark */; + B6E5F0F211A73144000AD141 /* PBXTextBookmark */ = B6E5F0F211A73144000AD141 /* PBXTextBookmark */; + B6E5F11211A73340000AD141 /* PBXTextBookmark */ = B6E5F11211A73340000AD141 /* PBXTextBookmark */; + B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */ = B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */; + B6E5F18211A76B74000AD141 /* PBXTextBookmark */ = B6E5F18211A76B74000AD141 /* PBXTextBookmark */; + B6F3647111AB35FE0045E114 /* PBXTextBookmark */ = B6F3647111AB35FE0045E114 /* PBXTextBookmark */; + B6F3649E11AB59190045E114 /* PBXTextBookmark */ = B6F3649E11AB59190045E114 /* PBXTextBookmark */; + B6F364B711AB84840045E114 /* PBXTextBookmark */ = B6F364B711AB84840045E114 /* PBXTextBookmark */; + B6F3652E11ADD5D20045E114 /* PBXTextBookmark */ = B6F3652E11ADD5D20045E114 /* PBXTextBookmark */; + B6F3653011ADD5D20045E114 /* PBXTextBookmark */ = B6F3653011ADD5D20045E114 /* PBXTextBookmark */; + B6F3657E11AE255B0045E114 /* PBXTextBookmark */ = B6F3657E11AE255B0045E114 /* PBXTextBookmark */; + B6F3665411B190370045E114 /* PBXTextBookmark */ = B6F3665411B190370045E114 /* PBXTextBookmark */; + B6F3665C11B194AC0045E114 /* PBXTextBookmark */ = B6F3665C11B194AC0045E114 /* PBXTextBookmark */; + B6F366C211B1A28C0045E114 /* PBXTextBookmark */ = B6F366C211B1A28C0045E114 /* PBXTextBookmark */; + B6F366C411B1A28C0045E114 /* PBXTextBookmark */ = B6F366C411B1A28C0045E114 /* PBXTextBookmark */; + B6F366C611B1A28C0045E114 /* PBXTextBookmark */ = B6F366C611B1A28C0045E114 /* PBXTextBookmark */; + B6F366C711B1A28C0045E114 /* PBXTextBookmark */ = B6F366C711B1A28C0045E114 /* PBXTextBookmark */; + B6F366C811B1A28C0045E114 /* PBXTextBookmark */ = B6F366C811B1A28C0045E114 /* PBXTextBookmark */; + B6F366C911B1A28C0045E114 /* PBXTextBookmark */ = B6F366C911B1A28C0045E114 /* PBXTextBookmark */; + B6F366CA11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CA11B1A28C0045E114 /* PBXTextBookmark */; + B6F366CB11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CB11B1A28C0045E114 /* PBXTextBookmark */; + B6F366CC11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CC11B1A28C0045E114 /* PBXTextBookmark */; + B6F366D911B1A7A70045E114 /* PBXTextBookmark */ = B6F366D911B1A7A70045E114 /* PBXTextBookmark */; + B6F3675411B316D10045E114 /* PBXTextBookmark */ = B6F3675411B316D10045E114 /* PBXTextBookmark */; + B6F3677C11B326580045E114 /* PBXTextBookmark */ = B6F3677C11B326580045E114 /* PBXTextBookmark */; + B6F3677D11B326580045E114 /* PBXTextBookmark */ = B6F3677D11B326580045E114 /* PBXTextBookmark */; + B6F3677E11B326580045E114 /* PBXTextBookmark */ = B6F3677E11B326580045E114 /* PBXTextBookmark */; + B6F3677F11B326580045E114 /* PBXTextBookmark */ = B6F3677F11B326580045E114 /* PBXTextBookmark */; + B6F367A011B330D10045E114 /* PBXTextBookmark */ = B6F367A011B330D10045E114 /* PBXTextBookmark */; + B6F367AE11B337A70045E114 /* PBXTextBookmark */ = B6F367AE11B337A70045E114 /* PBXTextBookmark */; + B6F3684911B44D090045E114 /* PBXTextBookmark */ = B6F3684911B44D090045E114 /* PBXTextBookmark */; + B6F3684A11B44D090045E114 /* PBXTextBookmark */ = B6F3684A11B44D090045E114 /* PBXTextBookmark */; + B6F3684B11B44D090045E114 /* PBXTextBookmark */ = B6F3684B11B44D090045E114 /* PBXTextBookmark */; }; sourceControlManager = B63EFA6711A093C200C90DCE /* Source Control */; userBuildSettings = { @@ -262,11 +266,35 @@ vrLen = 477; vrLoc = 0; }; - B6272A9D11D5AC5E0073C73A /* PBXBookmark */ = { - isa = PBXBookmark; - fRef = B6272A9211D5AC3C0073C73A /* xattr.cpp */; + B6272AA211D5AC840073C73A /* newfs_prodos.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 3094}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 1145}"; + }; }; - B6272A9E11D5AC5E0073C73A /* PBXTextBookmark */ = { + B6272AA511D5AE0C0073C73A /* Bitmap.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1249, 2912}}"; + sepNavSelRange = "{108, 0}"; + sepNavVisRange = "{0, 1570}"; + }; + }; + B6272AA611D5AE0C0073C73A /* Bitmap.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1249, 978}}"; + sepNavSelRange = "{147, 0}"; + sepNavVisRange = "{0, 888}"; + }; + }; + B6272AA711D5AE0C0073C73A /* DateTime.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 1911}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 870}"; + }; + }; + B6272B0D11D691320073C73A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B6272A9211D5AC3C0073C73A /* xattr.cpp */; name = "xattr.cpp: 1"; @@ -276,6 +304,111 @@ vrLen = 936; vrLoc = 0; }; + B6272B0E11D691320073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272AA211D5AC840073C73A /* newfs_prodos.cpp */; + name = "newfs_prodos.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1145; + vrLoc = 0; + }; + B6272B0F11D691320073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272AA711D5AE0C0073C73A /* DateTime.cpp */; + name = "DateTime.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 870; + vrLoc = 0; + }; + B6272B1011D691320073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272AA511D5AE0C0073C73A /* Bitmap.cpp */; + name = "Bitmap.cpp: 29"; + rLen = 0; + rLoc = 456; + rType = 0; + vrLen = 679; + vrLoc = 0; + }; + B6272B1111D691320073C73A /* XCBuildMessageTextBookmark */ = { + isa = PBXTextBookmark; + comments = "'Device' has not been declared"; + fRef = B6272B1211D691320073C73A /* Bitmap.h */; + fallbackIsa = XCBuildMessageTextBookmark; + rLen = 1; + rLoc = 21; + rType = 1; + }; + B6272B1211D691320073C73A /* Bitmap.h */ = { + isa = PBXFileReference; + name = Bitmap.h; + path = ./ProDOS/Bitmap.h; + sourceTree = ""; + }; + B6272B1311D691320073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9611A094E000C90DCE /* BlockDevice.h */; + name = "BlockDevice.h: 24"; + rLen = 0; + rLoc = 431; + rType = 0; + vrLen = 853; + vrLoc = 0; + }; + B6272B1411D691320073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; + name = "BlockDevice.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 740; + vrLoc = 0; + }; + B6272B1511D691320073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272AA611D5AE0C0073C73A /* Bitmap.h */; + name = "Bitmap.h: 21"; + rLen = 77; + rLoc = 226; + rType = 0; + vrLen = 735; + vrLoc = 0; + }; + B6272B1611D691320073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; + name = "BlockCache.cpp: 58"; + rLen = 0; + rLoc = 962; + rType = 0; + vrLen = 718; + vrLoc = 403; + }; + B6272B1711D691320073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAB711A098C400C90DCE /* BlockCache.h */; + name = "BlockCache.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 909; + vrLoc = 148; + }; + B6272B7711D6A3C30073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAB711A098C400C90DCE /* BlockCache.h */; + name = "BlockCache.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 928; + vrLoc = 129; + }; B63EFA6711A093C200C90DCE /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; @@ -315,14 +448,14 @@ uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 3198}}"; sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 815}"; + sepNavVisRange = "{0, 740}"; }; }; B63EFA9611A094E000C90DCE /* BlockDevice.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 858}}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 780}}"; sepNavSelRange = "{431, 0}"; - sepNavVisRange = "{0, 917}"; + sepNavVisRange = "{0, 853}"; }; }; B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */ = { @@ -404,16 +537,16 @@ }; B63EFAB611A098C400C90DCE /* BlockCache.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1009, 962}}"; - sepNavSelRange = "{334, 0}"; - sepNavVisRange = "{0, 1217}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 962}}"; + sepNavSelRange = "{962, 0}"; + sepNavVisRange = "{403, 718}"; }; }; B63EFAB711A098C400C90DCE /* BlockCache.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 754}}"; sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{148, 940}"; + sepNavVisRange = "{129, 928}"; }; }; B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */ = { @@ -841,16 +974,6 @@ path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_vector.h"; sourceTree = ""; }; - B63EFDB711A4488200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; - name = "BlockCache.cpp: 60"; - rLen = 0; - rLoc = 962; - rType = 0; - vrLen = 490; - vrLoc = 514; - }; B63EFDF211A4504200C90DCE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFAD011A09DB500C90DCE /* auto.h */; @@ -1050,26 +1173,6 @@ vrLen = 829; vrLoc = 5931; }; - B65CFB6B11B495790024A2D9 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 595"; - rLen = 6; - rLoc = 13761; - rType = 0; - vrLen = 1344; - vrLoc = 12874; - }; - B65CFB8811B5C8310024A2D9 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 618"; - rLen = 6; - rLoc = 13761; - rType = 0; - vrLen = 1389; - vrLoc = 13015; - }; B6E5F0DD11A60726000AD141 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; @@ -1130,13 +1233,12 @@ delayBeforeContinue = 0; fileReference = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; functionName = "main(int argc, char **argv)"; - hitCount = 1; + hitCount = 0; ignoreCount = 0; lineNumber = 76; - location = NibbleTest; - modificationTime = 296847682.0989181; + modificationTime = 299278551.142724; originalNumberOfMultipleMatches = 1; - state = 1; + state = 0; }; B6F3647111AB35FE0045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; @@ -1275,7 +1377,7 @@ hitCount = 0; ignoreCount = 0; lineNumber = 589; - modificationTime = 296847686.349254; + modificationTime = 299278551.143155; originalNumberOfMultipleMatches = 1; state = 1; }; @@ -1309,10 +1411,9 @@ hitCount = 0; ignoreCount = 0; lineNumber = 167; - location = NibbleTest; - modificationTime = 296847681.921191; + modificationTime = 299278551.143489; originalNumberOfMultipleMatches = 1; - state = 1; + state = 0; }; B6F3665411B190370045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; @@ -1354,16 +1455,6 @@ vrLen = 737; vrLoc = 463; }; - B6F366C511B1A28C0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; - name = "BlockDevice.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 815; - vrLoc = 0; - }; B6F366C611B1A28C0045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFB8811A1FB2500C90DCE /* DiskImage.h */; @@ -1444,16 +1535,6 @@ vrLen = 1077; vrLoc = 3977; }; - B6F3670611B2B47E0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA9611A094E000C90DCE /* BlockDevice.h */; - name = "BlockDevice.h: 24"; - rLen = 0; - rLoc = 431; - rType = 0; - vrLen = 917; - vrLoc = 0; - }; B6F3675411B316D10045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; @@ -1538,17 +1619,13 @@ vrLen = 874; vrLoc = 0; }; - B6F367E911B40F650045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAB711A098C400C90DCE /* BlockCache.h */; - name = "BlockCache.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 940; - vrLoc = 148; - }; B6F3682111B430870045E114 /* newfs_prodos.cpp */ = { + isa = PBXFileReference; + fileEncoding = 4; + lastKnownFileType = sourcecode.cpp.cpp; + name = newfs_prodos.cpp; + path = /Users/kelvin/Projects/PROFuseX/newfs_prodos.cpp; + sourceTree = ""; uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1009, 3185}}"; sepNavSelRange = "{266, 0}"; diff --git a/PROFuseX.xcodeproj/kelvin.perspectivev3 b/PROFuseX.xcodeproj/kelvin.perspectivev3 index 091e0f2..8a7e152 100644 --- a/PROFuseX.xcodeproj/kelvin.perspectivev3 +++ b/PROFuseX.xcodeproj/kelvin.perspectivev3 @@ -231,8 +231,6 @@ Layout - BecomeActive - ContentConfiguration PBXBottomSmartGroupGIDs @@ -270,13 +268,9 @@ 08FB7794FE84155DC02AAC07 B6272A8D11D5AC3C0073C73A - B63EFBE711A244EE00C90DCE - B63EFACF11A09DB500C90DCE - B63EFAC811A09DAA00C90DCE + B6272AA411D5AE0C0073C73A B63EFAB511A098C400C90DCE B63EFA9411A094E000C90DCE - B63EFA7411A0948500C90DCE - 1AB674ADFE9D54B511CA2CBB B656ADED11A84D3200AB578A 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 @@ -284,8 +278,8 @@ PBXSmartGroupTreeModuleOutlineStateSelectionKey - 6 - 1 + 19 + 17 0 @@ -307,7 +301,7 @@ 318 RubberWindowFrame - 303 109 1239 1000 0 0 1920 1178 + 182 101 1239 1000 0 0 1920 1178 Module PBXSmartGroupTreeModule @@ -323,7 +317,7 @@ PBXProjectModuleGUID B63EFA6111A093C200C90DCE PBXProjectModuleLabel - xattr.cpp + BlockCache.h PBXSplitModuleInNavigatorKey Split0 @@ -331,11 +325,11 @@ PBXProjectModuleGUID B63EFA6211A093C200C90DCE PBXProjectModuleLabel - xattr.cpp + BlockCache.h _historyCapacity 0 bookmark - B6272A9E11D5AC5E0073C73A + B6272B7711D6A3C30073C73A history B63EFC2611A2D5A400C90DCE @@ -349,7 +343,6 @@ B63EFDAF11A4488200C90DCE B63EFDB111A4488200C90DCE B63EFDB311A4488200C90DCE - B63EFDB711A4488200C90DCE B63EFDF211A4504200C90DCE B63EFEA011A488C200C90DCE B63EFEA111A488C200C90DCE @@ -371,7 +364,6 @@ B6F3665C11B194AC0045E114 B6F366C211B1A28C0045E114 B6F366C411B1A28C0045E114 - B6F366C511B1A28C0045E114 B6F366C611B1A28C0045E114 B6F366C711B1A28C0045E114 B6F366C811B1A28C0045E114 @@ -380,7 +372,6 @@ B6F366CB11B1A28C0045E114 B6F366CC11B1A28C0045E114 B6F366D911B1A7A70045E114 - B6F3670611B2B47E0045E114 B6F3675411B316D10045E114 B6F3677C11B326580045E114 B6F3677D11B326580045E114 @@ -388,7 +379,6 @@ B6F3677F11B326580045E114 B6F367A011B330D10045E114 B6F367AE11B337A70045E114 - B6F367E911B40F650045E114 B6F3684911B44D090045E114 B6F3684A11B44D090045E114 B6F3684B11B44D090045E114 @@ -399,7 +389,16 @@ B6272A9A11D5AC5E0073C73A B6272A9B11D5AC5E0073C73A B6272A9C11D5AC5E0073C73A - B6272A9D11D5AC5E0073C73A + B6272B0D11D691320073C73A + B6272B0E11D691320073C73A + B6272B0F11D691320073C73A + B6272B1011D691320073C73A + B6272B1111D691320073C73A + B6272B1311D691320073C73A + B6272B1411D691320073C73A + B6272B1511D691320073C73A + B6272B1611D691320073C73A + B6272B1711D691320073C73A SplitCount @@ -415,7 +414,7 @@ Frame {{0, 0}, {899, 535}} RubberWindowFrame - 303 109 1239 1000 0 0 1920 1178 + 182 101 1239 1000 0 0 1920 1178 Module PBXNavigatorGroup @@ -439,8 +438,6 @@ Frame {{10, 27}, {899, 392}} - RubberWindowFrame - 303 109 1239 1000 0 0 1920 1178 Module XCDetailModule @@ -494,7 +491,9 @@ GeometryConfiguration Frame - {{10, 27}, {899, 365}} + {{10, 27}, {899, 392}} + RubberWindowFrame + 182 101 1239 1000 0 0 1920 1178 Module PBXBuildResultsModule @@ -716,10 +715,11 @@ 5 WindowOrderList + B6272B1911D691320073C73A /Users/kelvin/Projects/PROFuseX/PROFuseX.xcodeproj WindowString - 303 109 1239 1000 0 0 1920 1178 + 182 101 1239 1000 0 0 1920 1178 WindowToolsV3 diff --git a/PROFuseX.xcodeproj/project.pbxproj b/PROFuseX.xcodeproj/project.pbxproj index a29e1a9..69606f7 100644 --- a/PROFuseX.xcodeproj/project.pbxproj +++ b/PROFuseX.xcodeproj/project.pbxproj @@ -12,6 +12,8 @@ B6272A9511D5AC530073C73A /* fuse_pascal_ops.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */; }; B6272A9611D5AC560073C73A /* newfs_pascal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */; }; B6272A9711D5AC5B0073C73A /* xattr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A9211D5AC3C0073C73A /* xattr.cpp */; }; + B6272AAA11D5AE0C0073C73A /* Bitmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272AA511D5AE0C0073C73A /* Bitmap.cpp */; }; + B6272AAB11D5AE0C0073C73A /* DateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272AA711D5AE0C0073C73A /* DateTime.cpp */; }; B63EFCD211A36C8B00C90DCE /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; B63EFCD311A36C8B00C90DCE /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; B63EFCD411A36C8B00C90DCE /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; @@ -109,7 +111,6 @@ B6F3683611B431CC0045E114 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD111A09DB500C90DCE /* Exception.cpp */; }; B6F3683711B431CC0045E114 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD311A09DB500C90DCE /* Lock.cpp */; }; B6F3683811B431CC0045E114 /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; - B6F3683F11B431E20045E114 /* newfs_prodos.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3682111B430870045E114 /* newfs_prodos.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -118,6 +119,11 @@ B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fuse_pascal_ops.cpp; sourceTree = ""; }; B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = newfs_pascal.cpp; sourceTree = ""; }; B6272A9211D5AC3C0073C73A /* xattr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xattr.cpp; sourceTree = ""; }; + B6272AA211D5AC840073C73A /* newfs_prodos.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = newfs_prodos.cpp; sourceTree = ""; }; + B6272AA511D5AE0C0073C73A /* Bitmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Bitmap.cpp; sourceTree = ""; }; + B6272AA611D5AE0C0073C73A /* Bitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bitmap.h; sourceTree = ""; }; + B6272AA711D5AE0C0073C73A /* DateTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DateTime.cpp; sourceTree = ""; }; + B6272AA811D5AE0C0073C73A /* DateTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DateTime.h; sourceTree = ""; }; B63EFA7511A0948500C90DCE /* Endian.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Endian.cpp; sourceTree = ""; }; B63EFA7611A0948500C90DCE /* Endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Endian.h; sourceTree = ""; }; B63EFA7711A0948500C90DCE /* IOBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOBuffer.h; sourceTree = ""; }; @@ -170,7 +176,6 @@ B6F3652711ADD52B0045E114 /* Pascal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Pascal.h; sourceTree = ""; }; B6F3676311B323680045E114 /* TextWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextWriter.h; sourceTree = ""; }; B6F3676411B323680045E114 /* TextWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextWriter.cpp; sourceTree = ""; }; - B6F3682111B430870045E114 /* newfs_prodos.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = newfs_prodos.cpp; sourceTree = ""; }; B6F3682511B431AC0045E114 /* newfs_prodos */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = newfs_prodos; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -226,7 +231,7 @@ children = ( B6272A8D11D5AC3C0073C73A /* bin */, B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */, - B6F3682111B430870045E114 /* newfs_prodos.cpp */, + B6272AA411D5AE0C0073C73A /* ProDOS */, B63EFBE711A244EE00C90DCE /* Pascal */, B63EFACF11A09DB500C90DCE /* ProFUSE */, B63EFAC811A09DAA00C90DCE /* File */, @@ -259,11 +264,23 @@ B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */, B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */, B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */, + B6272AA211D5AC840073C73A /* newfs_prodos.cpp */, B6272A9211D5AC3C0073C73A /* xattr.cpp */, ); path = bin; sourceTree = ""; }; + B6272AA411D5AE0C0073C73A /* ProDOS */ = { + isa = PBXGroup; + children = ( + B6272AA511D5AE0C0073C73A /* Bitmap.cpp */, + B6272AA611D5AE0C0073C73A /* Bitmap.h */, + B6272AA711D5AE0C0073C73A /* DateTime.cpp */, + B6272AA811D5AE0C0073C73A /* DateTime.h */, + ); + path = ProDOS; + sourceTree = ""; + }; B63EFA7411A0948500C90DCE /* Endian */ = { isa = PBXGroup; children = ( @@ -465,7 +482,11 @@ isa = PBXProject; buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "PROFuseX" */; compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; hasScannedForEncodings = 1; + knownRegions = ( + en, + ); mainGroup = 08FB7794FE84155DC02AAC07 /* PROFuseX */; projectDirPath = ""; projectRoot = ""; @@ -621,7 +642,8 @@ B6F3683611B431CC0045E114 /* Exception.cpp in Sources */, B6F3683711B431CC0045E114 /* Lock.cpp in Sources */, B6F3683811B431CC0045E114 /* Adaptor.cpp in Sources */, - B6F3683F11B431E20045E114 /* newfs_prodos.cpp in Sources */, + B6272AAA11D5AE0C0073C73A /* Bitmap.cpp in Sources */, + B6272AAB11D5AE0C0073C73A /* DateTime.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -634,6 +656,7 @@ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( @@ -642,7 +665,7 @@ ); ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; - SDKROOT = macosx10.6; + SDKROOT = macosx; }; name = Debug; }; @@ -651,10 +674,11 @@ buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; PREBINDING = NO; - SDKROOT = macosx10.6; + SDKROOT = macosx; }; name = Release; }; @@ -697,6 +721,7 @@ GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; INSTALL_PATH = /usr/local/bin; PREBINDING = NO; PRODUCT_NAME = newfs_pascal; @@ -711,6 +736,7 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_MODEL_TUNING = G5; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; INSTALL_PATH = /usr/local/bin; PREBINDING = NO; PRODUCT_NAME = newfs_pascal; @@ -724,6 +750,7 @@ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( @@ -732,7 +759,7 @@ ); ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; - SDKROOT = macosx10.6; + SDKROOT = macosx; }; name = "Debug fuse"; }; @@ -760,6 +787,7 @@ GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; INSTALL_PATH = /usr/local/bin; PREBINDING = NO; PRODUCT_NAME = newfs_pascal; From 8e259ef1f2703d6c54f2230a953213af0a800807 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 16 Feb 2011 03:25:34 +0000 Subject: [PATCH 201/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@328 aa027e90-d47c-11dd-86d7-074df07e0730 --- bin/apfm.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/bin/apfm.cpp b/bin/apfm.cpp index e8dad48..82f17a6 100644 --- a/bin/apfm.cpp +++ b/bin/apfm.cpp @@ -1025,15 +1025,9 @@ int main(int argc, char **argv) unsigned actionCode = command(action); - device.reset( Device::BlockDevice::Open(file, commandFlags(actionCode), fmt) ); - - - - volume.reset( new Pascal::VolumeEntry(device.get())); - device.release(); switch (actionCode) @@ -1070,7 +1064,7 @@ int main(int argc, char **argv) catch (ProFUSE::Exception& e) { std::fprintf(stderr, "%s\n", e.what()); - std::fprintf(stderr, "%s\n", strerror(e.error())); + std::fprintf(stderr, "%s\n", e.errorString()); } return 0; From 78d35bba08836c2eee12c8392c448d6092b72e8b Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 22 Feb 2011 02:59:33 +0000 Subject: [PATCH 202/236] use shared_ptr for device, cache git-svn-id: https://profuse.googlecode.com/svn/branches/v2@345 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/BlockCache.cpp | 9 ++++----- Cache/BlockCache.h | 13 +++++++------ Cache/ConcreteBlockCache.cpp | 6 +++++- Cache/ConcreteBlockCache.h | 9 +++++++-- Cache/MappedBlockCache.cpp | 7 ++++++- Cache/MappedBlockCache.h | 7 +++++-- Device/BlockDevice.cpp | 4 ++-- Device/BlockDevice.h | 10 +++++----- Device/DavexDiskImage.cpp | 5 +++-- Device/DavexDiskImage.h | 2 +- Device/Device.h | 26 ++++++++++++++++++++++++++ Device/DiskCopy42Image.cpp | 4 ++-- Device/DiskCopy42Image.h | 2 +- Device/DiskImage.cpp | 4 ++-- Device/DiskImage.h | 2 +- Device/UniversalDiskImage.cpp | 4 ++-- Device/UniversalDiskImage.h | 2 +- 17 files changed, 80 insertions(+), 36 deletions(-) create mode 100644 Device/Device.h diff --git a/Cache/BlockCache.cpp b/Cache/BlockCache.cpp index b6670b5..61462ed 100644 --- a/Cache/BlockCache.cpp +++ b/Cache/BlockCache.cpp @@ -23,16 +23,15 @@ using ProFUSE::Exception; using ProFUSE::POSIXException; -BlockCache::BlockCache(BlockDevice *device) +BlockCache::BlockCache(BlockDevicePointer device) : + _device(device) { - _device = device; _blocks = device->blocks(); _readOnly = device->readOnly(); } BlockCache::~BlockCache() { - delete _device; } void BlockCache::write(unsigned block, const void *bp) @@ -50,9 +49,9 @@ void BlockCache::read(unsigned block, void *bp) } -BlockCache *BlockCache::Create(BlockDevice *device) +BlockCachePointer BlockCache::Create(BlockDevicePointer device) { - if (!device) return NULL; + if (!device.get()) return BlockCachePointer(); return device->createBlockCache(); } diff --git a/Cache/BlockCache.h b/Cache/BlockCache.h index c4587d1..2b9e839 100644 --- a/Cache/BlockCache.h +++ b/Cache/BlockCache.h @@ -3,12 +3,13 @@ #include #include +#include + class MappedFile; namespace Device { -class BlockDevice; enum BlockReleaseFlags { kBlockDirty = 1, @@ -19,13 +20,13 @@ enum BlockReleaseFlags { class BlockCache { public: - static BlockCache *Create(BlockDevice *device); + static BlockCachePointer Create(BlockDevicePointer device); virtual ~BlockCache(); bool readOnly() { return _readOnly; } unsigned blocks() { return _blocks; } - BlockDevice *device() { return _device; } + BlockDevicePointer device() { return _device; } virtual void sync() = 0; @@ -46,16 +47,16 @@ public: } protected: - BlockCache(BlockDevice *device); + BlockCache(BlockDevicePointer device); - BlockDevice *_device; + BlockDevicePointer _device; private: unsigned _blocks; bool _readOnly; }; - + } // namespace #endif diff --git a/Cache/ConcreteBlockCache.cpp b/Cache/ConcreteBlockCache.cpp index 5e0bd69..5bf7ede 100644 --- a/Cache/ConcreteBlockCache.cpp +++ b/Cache/ConcreteBlockCache.cpp @@ -58,8 +58,12 @@ using ProFUSE::POSIXException; //typedef std::vector::iterator EntryIter; +BlockCachePointer ConcreteBlockCache::Create(BlockDevicePointer device, unsigned size) +{ + return BlockCachePointer(new ConcreteBlockCache(device, size)); +} -ConcreteBlockCache::ConcreteBlockCache(BlockDevice *device, unsigned size) : +ConcreteBlockCache::ConcreteBlockCache(BlockDevicePointer device, unsigned size) : BlockCache(device) { if (size < 16) size = 16; diff --git a/Cache/ConcreteBlockCache.h b/Cache/ConcreteBlockCache.h index 2ca5698..aead0e6 100644 --- a/Cache/ConcreteBlockCache.h +++ b/Cache/ConcreteBlockCache.h @@ -9,7 +9,9 @@ namespace Device { class ConcreteBlockCache : public BlockCache { public: - ConcreteBlockCache(BlockDevice *device, unsigned size = 16); + + static BlockCachePointer Create(BlockDevicePointer device, unsigned size = 16); + virtual ~ConcreteBlockCache(); virtual void sync(); @@ -21,8 +23,11 @@ public: virtual void markDirty(unsigned block); - private: + + + ConcreteBlockCache(BlockDevicePointer device, unsigned size); + struct Entry { unsigned block; unsigned count; diff --git a/Cache/MappedBlockCache.cpp b/Cache/MappedBlockCache.cpp index 1d1be58..4a65fb1 100644 --- a/Cache/MappedBlockCache.cpp +++ b/Cache/MappedBlockCache.cpp @@ -19,8 +19,13 @@ using namespace Device; using ProFUSE::Exception; using ProFUSE::POSIXException; +BlockCachePointer MappedBlockCache::Create(BlockDevicePointer device, void *data) +{ + return BlockCachePointer(new MappedBlockCache(device, data)); +} -MappedBlockCache::MappedBlockCache(BlockDevice *device, void *data) : + +MappedBlockCache::MappedBlockCache(BlockDevicePointer device, void *data) : BlockCache(device) { _data = (uint8_t *)data; diff --git a/Cache/MappedBlockCache.h b/Cache/MappedBlockCache.h index a3402ff..e02a854 100644 --- a/Cache/MappedBlockCache.h +++ b/Cache/MappedBlockCache.h @@ -8,7 +8,8 @@ namespace Device { class MappedBlockCache : public BlockCache { public: - MappedBlockCache(BlockDevice *, void *data); + static BlockCachePointer Create(BlockDevicePointer device, void *data); + virtual ~MappedBlockCache(); virtual void sync(); @@ -22,7 +23,9 @@ class MappedBlockCache : public BlockCache { virtual void markDirty(unsigned block); private: - + + MappedBlockCache(BlockDevicePointer device, void *data); + void sync(unsigned block); uint8_t *_data; diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index d86f4d7..d421746 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -233,9 +233,9 @@ void BlockDevice::sync(TrackSector ts) } */ -BlockCache *BlockDevice::createBlockCache() +BlockCachePointer BlockDevice::createBlockCache() { unsigned b = blocks(); unsigned size = std::max(16u, b / 16); - return new ConcreteBlockCache(this, size); + return ConcreteBlockCache::Create(shared_from_this(), size); } diff --git a/Device/BlockDevice.h b/Device/BlockDevice.h index 8e8feb5..08eea1d 100644 --- a/Device/BlockDevice.h +++ b/Device/BlockDevice.h @@ -4,17 +4,17 @@ #include #include -#include - +#include #include -#include +#include + #include namespace Device { -class BlockDevice { + class BlockDevice : public std::tr1::enable_shared_from_this { public: @@ -30,7 +30,7 @@ public: virtual ~BlockDevice(); - virtual BlockCache *createBlockCache(); + virtual BlockCachePointer createBlockCache(); virtual void read(unsigned block, void *bp) = 0; diff --git a/Device/DavexDiskImage.cpp b/Device/DavexDiskImage.cpp index e63a04f..7600d5b 100644 --- a/Device/DavexDiskImage.cpp +++ b/Device/DavexDiskImage.cpp @@ -158,8 +158,9 @@ DavexDiskImage *DavexDiskImage::Create(const char *name, size_t blocks, const ch } -BlockCache *DavexDiskImage::createBlockCache() +BlockCachePointer DavexDiskImage::createBlockCache() { - return new MappedBlockCache(this, 512 + (uint8_t *)address()); + // need a smart pointer, but only have this.... + return MappedBlockCache::Create(shared_from_this(), 512 + (uint8_t *)address()); } diff --git a/Device/DavexDiskImage.h b/Device/DavexDiskImage.h index ff659e0..1750897 100644 --- a/Device/DavexDiskImage.h +++ b/Device/DavexDiskImage.h @@ -20,7 +20,7 @@ public: static DavexDiskImage *Create(const char *name, size_t blocks, const char *vname); static DavexDiskImage *Open(MappedFile *); - virtual BlockCache *createBlockCache(); + virtual BlockCachePointer createBlockCache(); private: diff --git a/Device/Device.h b/Device/Device.h new file mode 100644 index 0000000..3c280d0 --- /dev/null +++ b/Device/Device.h @@ -0,0 +1,26 @@ +// +// Device.h +// profuse +// +// Created by Kelvin Sherlock on 2/19/2011. +// Copyright 2011 __MyCompanyName__. All rights reserved. +// + +#ifndef __DEVICE_DEVICE_H__ +#define __DEVICE_DEVICE_H__ + +#include + +namespace Device { + + class BlockDevice; + class BlockCache; + + typedef std::tr1::shared_ptr BlockDevicePointer; + typedef std::tr1::shared_ptr BlockCachePointer; + + +} + + +#endif diff --git a/Device/DiskCopy42Image.cpp b/Device/DiskCopy42Image.cpp index 9af488b..3d121f3 100644 --- a/Device/DiskCopy42Image.cpp +++ b/Device/DiskCopy42Image.cpp @@ -218,11 +218,11 @@ void DiskCopy42Image::write(unsigned block, const void *bp) } -BlockCache *DiskCopy42Image::createBlockCache() +BlockCachePointer DiskCopy42Image::createBlockCache() { // if not readonly, mark changed so crc will be updated at close. if (!readOnly()) _changed = true; - return new MappedBlockCache(this, address()); + return MappedBlockCache::Create(shared_from_this(), address()); } \ No newline at end of file diff --git a/Device/DiskCopy42Image.h b/Device/DiskCopy42Image.h index f4ce443..f807f78 100644 --- a/Device/DiskCopy42Image.h +++ b/Device/DiskCopy42Image.h @@ -22,7 +22,7 @@ public: virtual void write(unsigned block, const void *bp); - virtual BlockCache *createBlockCache(); + virtual BlockCachePointer createBlockCache(); private: diff --git a/Device/DiskImage.cpp b/Device/DiskImage.cpp index 113eb22..091d789 100644 --- a/Device/DiskImage.cpp +++ b/Device/DiskImage.cpp @@ -138,9 +138,9 @@ void ProDOSOrderDiskImage::Validate(MappedFile *f) } -BlockCache *ProDOSOrderDiskImage::createBlockCache() +BlockCachePointer ProDOSOrderDiskImage::createBlockCache() { - return new MappedBlockCache(this, address()); + return MappedBlockCache::Create(shared_from_this(), address()); } #pragma mark - diff --git a/Device/DiskImage.h b/Device/DiskImage.h index 52a7303..a560e3e 100644 --- a/Device/DiskImage.h +++ b/Device/DiskImage.h @@ -61,7 +61,7 @@ public: static ProDOSOrderDiskImage *Open(MappedFile *); - virtual BlockCache *createBlockCache(); + virtual BlockCachePointer createBlockCache(); private: ProDOSOrderDiskImage(); diff --git a/Device/UniversalDiskImage.cpp b/Device/UniversalDiskImage.cpp index dedb9c9..1d7014e 100644 --- a/Device/UniversalDiskImage.cpp +++ b/Device/UniversalDiskImage.cpp @@ -141,11 +141,11 @@ bool UniversalDiskImage::readOnly() } -BlockCache *UniversalDiskImage::createBlockCache() +BlockCachePointer UniversalDiskImage::createBlockCache() { if (_format == 1) { - return new MappedBlockCache(this, _dataOffset + (uint8_t *)address()); + return MappedBlockCache::Create(shared_from_this(), _dataOffset + (uint8_t *)address()); } return DiskImage::createBlockCache(); diff --git a/Device/UniversalDiskImage.h b/Device/UniversalDiskImage.h index e552af5..557e935 100644 --- a/Device/UniversalDiskImage.h +++ b/Device/UniversalDiskImage.h @@ -19,7 +19,7 @@ public: virtual bool readOnly(); - virtual BlockCache *createBlockCache(); + virtual BlockCachePointer createBlockCache(); private: From 2243d8d1364065685dded654a4d5848a2dc4f4e8 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 22 Feb 2011 04:57:50 +0000 Subject: [PATCH 203/236] shared_ptr changes. git-svn-id: https://profuse.googlecode.com/svn/branches/v2@346 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/BlockDevice.cpp | 8 ++++---- Device/BlockDevice.h | 4 ++-- Device/DavexDiskImage.cpp | 10 +++++----- Device/DavexDiskImage.h | 6 +++--- Device/Device.h | 1 + Device/DiskCopy42Image.cpp | 10 +++++----- Device/DiskCopy42Image.h | 6 +++--- Device/DiskImage.cpp | 16 ++++++++-------- Device/DiskImage.h | 8 ++++---- Device/RawDevice.cpp | 4 ++-- Device/RawDevice.h | 2 +- Device/UniversalDiskImage.cpp | 8 ++++---- Device/UniversalDiskImage.h | 4 ++-- Pascal/VolumeEntry.cpp | 18 +++++++----------- Pascal/VolumeEntry.h | 8 ++++---- bin/apfm.cpp | 10 +++++----- bin/fuse_pascal.cpp | 17 ++++++++++------- bin/newfs_pascal.cpp | 11 +++++------ bin/newfs_prodos.cpp | 1 + 19 files changed, 76 insertions(+), 76 deletions(-) diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index d421746..c114a00 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -78,7 +78,7 @@ unsigned BlockDevice::ImageType(const char *type, unsigned defv) return defv; } -BlockDevice *BlockDevice::Open(const char *name, File::FileFlags flags, unsigned imageType) +BlockDevicePointer BlockDevice::Open(const char *name, File::FileFlags flags, unsigned imageType) { #undef __METHOD__ #define __METHOD__ "BlockDevice::Open" @@ -128,7 +128,7 @@ BlockDevice *BlockDevice::Open(const char *name, File::FileFlags flags, unsigned } // throw an error? - return NULL; + return BlockDevicePointer(); } @@ -158,7 +158,7 @@ static std::string filename(const std::string& src) } -BlockDevice *BlockDevice::Create(const char *fname, const char *vname, unsigned blocks, unsigned imageType) +BlockDevicePointer BlockDevice::Create(const char *fname, const char *vname, unsigned blocks, unsigned imageType) { std::string xname; @@ -191,7 +191,7 @@ BlockDevice *BlockDevice::Create(const char *fname, const char *vname, unsigned return DavexDiskImage::Create(fname, blocks, vname); } - return NULL; + return BlockDevicePointer(); } diff --git a/Device/BlockDevice.h b/Device/BlockDevice.h index 08eea1d..8d4a021 100644 --- a/Device/BlockDevice.h +++ b/Device/BlockDevice.h @@ -21,8 +21,8 @@ public: // static methods. static unsigned ImageType(const char *type, unsigned defv = 0); - static BlockDevice *Open(const char *name, File::FileFlags flags, unsigned imageType = 0); - static BlockDevice *Create(const char *fname, const char *vname, unsigned blocks, unsigned imageType = 0); + static BlockDevicePointer Open(const char *name, File::FileFlags flags, unsigned imageType = 0); + static BlockDevicePointer Create(const char *fname, const char *vname, unsigned blocks, unsigned imageType = 0); diff --git a/Device/DavexDiskImage.cpp b/Device/DavexDiskImage.cpp index 7600d5b..54e6ad9 100644 --- a/Device/DavexDiskImage.cpp +++ b/Device/DavexDiskImage.cpp @@ -85,20 +85,20 @@ void DavexDiskImage::Validate(MappedFile *f) throw Exception(__METHOD__ ": Invalid file format."); } -DavexDiskImage *DavexDiskImage::Open(MappedFile *file) +BlockDevicePointer DavexDiskImage::Open(MappedFile *file) { #undef __METHOD__ #define __METHOD__ "DavexDiskImage::Open" Validate(file); - return new DavexDiskImage(file); + return BlockDevicePointer(new DavexDiskImage(file)); } -DavexDiskImage *DavexDiskImage::Create(const char *name, size_t blocks) +BlockDevicePointer DavexDiskImage::Create(const char *name, size_t blocks) { return Create(name, blocks, "Untitled"); } -DavexDiskImage *DavexDiskImage::Create(const char *name, size_t blocks, const char *vname) +BlockDevicePointer DavexDiskImage::Create(const char *name, size_t blocks, const char *vname) { #undef __METHOD__ #define __METHOD__ "DavexDiskImage::Create" @@ -154,7 +154,7 @@ DavexDiskImage *DavexDiskImage::Create(const char *name, size_t blocks, const ch std::memcpy(file->address(), header.buffer(), 512); file->sync(); - return new DavexDiskImage(file); + return BlockDevicePointer(new DavexDiskImage(file)); } diff --git a/Device/DavexDiskImage.h b/Device/DavexDiskImage.h index 1750897..b7a3d36 100644 --- a/Device/DavexDiskImage.h +++ b/Device/DavexDiskImage.h @@ -16,9 +16,9 @@ public: virtual ~DavexDiskImage(); - static DavexDiskImage *Create(const char *name, size_t blocks); - static DavexDiskImage *Create(const char *name, size_t blocks, const char *vname); - static DavexDiskImage *Open(MappedFile *); + static BlockDevicePointer Create(const char *name, size_t blocks); + static BlockDevicePointer Create(const char *name, size_t blocks, const char *vname); + static BlockDevicePointer Open(MappedFile *); virtual BlockCachePointer createBlockCache(); diff --git a/Device/Device.h b/Device/Device.h index 3c280d0..83c6f08 100644 --- a/Device/Device.h +++ b/Device/Device.h @@ -16,6 +16,7 @@ namespace Device { class BlockDevice; class BlockCache; + typedef std::tr1::shared_ptr BlockDevicePointer; typedef std::tr1::shared_ptr BlockCachePointer; diff --git a/Device/DiskCopy42Image.cpp b/Device/DiskCopy42Image.cpp index 3d121f3..040d0c1 100644 --- a/Device/DiskCopy42Image.cpp +++ b/Device/DiskCopy42Image.cpp @@ -75,10 +75,10 @@ uint32_t DiskCopy42Image::Checksum(void *data, size_t size) return rv; } -DiskCopy42Image *DiskCopy42Image::Open(MappedFile *f) +BlockDevicePointer DiskCopy42Image::Open(MappedFile *f) { Validate(f); - return new DiskCopy42Image(f); + return BlockDevicePointer(new DiskCopy42Image(f)); } static uint8_t DiskFormat(size_t blocks) @@ -101,12 +101,12 @@ static uint8_t FormatByte(size_t blocks) default: return 0x22; } } -DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks) +BlockDevicePointer DiskCopy42Image::Create(const char *name, size_t blocks) { return Create(name, blocks, "Untitled"); } -DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks, const char *vname) +BlockDevicePointer DiskCopy42Image::Create(const char *name, size_t blocks, const char *vname) { MappedFile *file = MappedFile::Create(name, blocks * 512 + oUserData); @@ -163,7 +163,7 @@ DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks, const std::memcpy(file->address(), header.buffer(), oUserData); file->sync(); - return new DiskCopy42Image(file); + return BlockDevicePointer(new DiskCopy42Image(file)); } void DiskCopy42Image::Validate(MappedFile *file) diff --git a/Device/DiskCopy42Image.h b/Device/DiskCopy42Image.h index f807f78..df5c95f 100644 --- a/Device/DiskCopy42Image.h +++ b/Device/DiskCopy42Image.h @@ -12,10 +12,10 @@ class DiskCopy42Image : public DiskImage { public: virtual ~DiskCopy42Image(); - static DiskCopy42Image *Create(const char *name, size_t blocks); - static DiskCopy42Image *Create(const char *name, size_t blocks, const char *vname); + static BlockDevicePointer Create(const char *name, size_t blocks); + static BlockDevicePointer Create(const char *name, size_t blocks, const char *vname); - static DiskCopy42Image *Open(MappedFile *); + static BlockDevicePointer Open(MappedFile *); static uint32_t Checksum(void *data, size_t size); diff --git a/Device/DiskImage.cpp b/Device/DiskImage.cpp index 091d789..0b83da5 100644 --- a/Device/DiskImage.cpp +++ b/Device/DiskImage.cpp @@ -112,16 +112,16 @@ ProDOSOrderDiskImage::ProDOSOrderDiskImage(MappedFile *file) : setAdaptor(new POAdaptor(address())); } -ProDOSOrderDiskImage *ProDOSOrderDiskImage::Create(const char *name, size_t blocks) +BlockDevicePointer ProDOSOrderDiskImage::Create(const char *name, size_t blocks) { MappedFile *file = MappedFile::Create(name, blocks * 512); - return new ProDOSOrderDiskImage(file); + return BlockDevicePointer(new ProDOSOrderDiskImage(file)); } -ProDOSOrderDiskImage *ProDOSOrderDiskImage::Open(MappedFile *file) +BlockDevicePointer ProDOSOrderDiskImage::Open(MappedFile *file) { Validate(file); - return new ProDOSOrderDiskImage(file); + return BlockDevicePointer(new ProDOSOrderDiskImage(file)); } void ProDOSOrderDiskImage::Validate(MappedFile *f) @@ -165,16 +165,16 @@ DOSOrderDiskImage::DOSOrderDiskImage(MappedFile *file) : } -DOSOrderDiskImage *DOSOrderDiskImage::Create(const char *name, size_t blocks) +BlockDevicePointer DOSOrderDiskImage::Create(const char *name, size_t blocks) { MappedFile *file = MappedFile::Create(name, blocks * 512); - return new DOSOrderDiskImage(file); + return BlockDevicePointer(new DOSOrderDiskImage(file)); } -DOSOrderDiskImage *DOSOrderDiskImage::Open(MappedFile *file) +BlockDevicePointer DOSOrderDiskImage::Open(MappedFile *file) { Validate(file); - return new DOSOrderDiskImage(file); + return BlockDevicePointer(new DOSOrderDiskImage(file)); } void DOSOrderDiskImage::Validate(MappedFile *f) diff --git a/Device/DiskImage.h b/Device/DiskImage.h index a560e3e..35034f5 100644 --- a/Device/DiskImage.h +++ b/Device/DiskImage.h @@ -57,8 +57,8 @@ class ProDOSOrderDiskImage : public DiskImage { public: - static ProDOSOrderDiskImage *Create(const char *name, size_t blocks); - static ProDOSOrderDiskImage *Open(MappedFile *); + static BlockDevicePointer Create(const char *name, size_t blocks); + static BlockDevicePointer Open(MappedFile *); virtual BlockCachePointer createBlockCache(); @@ -75,8 +75,8 @@ class DOSOrderDiskImage : public DiskImage { public: - static DOSOrderDiskImage *Create(const char *name, size_t blocks); - static DOSOrderDiskImage *Open(MappedFile *); + static BlockDevicePointer Create(const char *name, size_t blocks); + static BlockDevicePointer Open(MappedFile *); private: DOSOrderDiskImage(); diff --git a/Device/RawDevice.cpp b/Device/RawDevice.cpp index 91a88b3..1df2117 100644 --- a/Device/RawDevice.cpp +++ b/Device/RawDevice.cpp @@ -196,9 +196,9 @@ RawDevice::~RawDevice() } -RawDevice *RawDevice::Open(const char *name, File::FileFlags flags) +BlockDevicePointer RawDevice::Open(const char *name, File::FileFlags flags) { - return new RawDevice(name, flags); + return BlockDevicePointer(new RawDevice(name, flags)); } diff --git a/Device/RawDevice.h b/Device/RawDevice.h index 2b036cc..5f5507c 100644 --- a/Device/RawDevice.h +++ b/Device/RawDevice.h @@ -17,7 +17,7 @@ public: - static RawDevice *Open(const char *name, File::FileFlags flags); + static BlockDevicePointer Open(const char *name, File::FileFlags flags); virtual ~RawDevice(); diff --git a/Device/UniversalDiskImage.cpp b/Device/UniversalDiskImage.cpp index 1d7014e..82adafb 100644 --- a/Device/UniversalDiskImage.cpp +++ b/Device/UniversalDiskImage.cpp @@ -41,7 +41,7 @@ UniversalDiskImage::UniversalDiskImage(MappedFile *file) : setAdaptor(new POAdaptor(_dataOffset + data)); } -UniversalDiskImage *UniversalDiskImage::Create(const char *name, size_t blocks) +BlockDevicePointer UniversalDiskImage::Create(const char *name, size_t blocks) { // 64-byte header. MappedFile *file = MappedFile::Create(name, blocks * 512 + 64); @@ -81,13 +81,13 @@ UniversalDiskImage *UniversalDiskImage::Create(const char *name, size_t blocks) std::memcpy(file->address(), header.buffer(), 64); - return new UniversalDiskImage(file); + return BlockDevicePointer(new UniversalDiskImage(file)); } -UniversalDiskImage *UniversalDiskImage::Open(MappedFile *file) +BlockDevicePointer UniversalDiskImage::Open(MappedFile *file) { Validate(file); - return new UniversalDiskImage(file); + return BlockDevicePointer(new UniversalDiskImage(file)); } diff --git a/Device/UniversalDiskImage.h b/Device/UniversalDiskImage.h index 557e935..23b5b9d 100644 --- a/Device/UniversalDiskImage.h +++ b/Device/UniversalDiskImage.h @@ -14,8 +14,8 @@ public: - static UniversalDiskImage *Create(const char *name, size_t blocks); - static UniversalDiskImage *Open(MappedFile *); + static BlockDevicePointer Create(const char *name, size_t blocks); + static BlockDevicePointer Open(MappedFile *); virtual bool readOnly(); diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index 68f3cd3..03e2f52 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -71,12 +71,11 @@ VolumeEntry::VolumeEntry() setInode(1); - _inodeGenerator = 1; - _cache = NULL; - _device = NULL; + _inodeGenerator = 1; } -VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device) +VolumeEntry::VolumeEntry(const char *name, Device::BlockDevicePointer device) : + _device(device) { #undef __METHOD__ #define __METHOD__ "VolumeEntry::VolumeEntry" @@ -114,8 +113,8 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device) _accessTime = 0; _lastBoot = Date::Today(); - _cache = BlockCache::Create(device); _device = device; + _cache = BlockCache::Create(device); _address = 512 * 2; @@ -136,10 +135,10 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device) } -VolumeEntry::VolumeEntry(Device::BlockDevice *device) +VolumeEntry::VolumeEntry(Device::BlockDevicePointer device) { unsigned blockCount; - unsigned deviceBlocks = device->blocks(); + //unsigned deviceBlocks = device->blocks(); ProFUSE::auto_array buffer(new uint8_t[512]); @@ -245,10 +244,7 @@ VolumeEntry::~VolumeEntry() { if (*iter) delete *iter; } - - delete _cache; - // _device is deleted by _cache. - //delete _device; + } diff --git a/Pascal/VolumeEntry.h b/Pascal/VolumeEntry.h index 8789841..2dcc0ea 100644 --- a/Pascal/VolumeEntry.h +++ b/Pascal/VolumeEntry.h @@ -19,10 +19,10 @@ namespace Pascal { // create new - VolumeEntry(const char *name, Device::BlockDevice *); + VolumeEntry(const char *name, Device::BlockDevicePointer); // open existing - VolumeEntry(Device::BlockDevice *); + VolumeEntry(Device::BlockDevicePointer); virtual ~VolumeEntry(); const char *name() const { return _fileName; } @@ -93,8 +93,8 @@ namespace Pascal { std::vector _files; unsigned _inodeGenerator; - Device::BlockDevice *_device; - Device::BlockCache *_cache; + Device::BlockDevicePointer _device; + Device::BlockCachePointer _cache; }; diff --git a/bin/apfm.cpp b/bin/apfm.cpp index 82f17a6..cd65dae 100644 --- a/bin/apfm.cpp +++ b/bin/apfm.cpp @@ -5,7 +5,6 @@ * E - */ - #include #include #include @@ -23,6 +22,7 @@ #include #include +#include #include #include @@ -963,7 +963,7 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) int main(int argc, char **argv) { std::auto_ptr volume; - std::auto_ptr device; + Device::BlockDevicePointer device; unsigned fmt = 0; @@ -1025,10 +1025,10 @@ int main(int argc, char **argv) unsigned actionCode = command(action); - device.reset( Device::BlockDevice::Open(file, commandFlags(actionCode), fmt) ); + device = Device::BlockDevice::Open(file, commandFlags(actionCode), fmt); - volume.reset( new Pascal::VolumeEntry(device.get())); - device.release(); + volume.reset( new Pascal::VolumeEntry(device)); + device.reset(); switch (actionCode) { diff --git a/bin/fuse_pascal.cpp b/bin/fuse_pascal.cpp index 876c865..17f230c 100644 --- a/bin/fuse_pascal.cpp +++ b/bin/fuse_pascal.cpp @@ -17,17 +17,18 @@ #include #include - #include #include -#include - #include +#include +#include + std::string fDiskImage; + void usage() { std::printf("profuse_pascal 0.1\n\n"); @@ -196,9 +197,11 @@ int main(int argc, char **argv) try { - std::auto_ptr device; + //std::tr1::shared_ptr device; - device.reset( Device::BlockDevice::Open(fDiskImage.c_str(), File::ReadOnly, format) ); + Device::BlockDevicePointer device; + + device = Device::BlockDevice::Open(fDiskImage.c_str(), File::ReadOnly, format); if (!device.get()) @@ -207,8 +210,8 @@ int main(int argc, char **argv) exit(1); } - volume.reset( new Pascal::VolumeEntry(device.get()) ); - device.release(); + volume.reset( new Pascal::VolumeEntry(device) ); + device.reset(); } catch (ProFUSE::POSIXException &e) { diff --git a/bin/newfs_pascal.cpp b/bin/newfs_pascal.cpp index 28f3736..fe8b93a 100644 --- a/bin/newfs_pascal.cpp +++ b/bin/newfs_pascal.cpp @@ -214,7 +214,7 @@ int main(int argc, char **argv) struct stat st; bool rawDevice; - std::auto_ptr device; + BlockDevicePointer device; std::auto_ptr volume; // Check for block device. if so, verify. @@ -228,7 +228,7 @@ int main(int argc, char **argv) fprintf(stderr, "`%s' is a raw device. Are you sure you want to initialize it? ", fname); if (!yes_or_no()) return -1; - device.reset( RawDevice::Open(fname, File::ReadWrite) ); + device = RawDevice::Open(fname, File::ReadWrite); blocks = device->blocks(); rawDevice = true; @@ -260,7 +260,7 @@ int main(int argc, char **argv) } if (!rawDevice) - device.reset( BlockDevice::Create(fname, volumeName.c_str(), blocks, format)); + device = BlockDevice::Create(fname, volumeName.c_str(), blocks, format); if (!device.get()) { @@ -271,7 +271,7 @@ int main(int argc, char **argv) if (!bootFile.empty()) { - MappedFile bf(bootFile.c_str(), File::ReadOnly , std::nothrow); + MappedFile bf(bootFile.c_str(), File::ReadOnly, std::nothrow); if (!bf.isValid()) { @@ -299,9 +299,8 @@ int main(int argc, char **argv) volume.reset( - new VolumeEntry(volumeName.c_str(), device.get()) + new VolumeEntry(volumeName.c_str(), device) ); - device.release(); } diff --git a/bin/newfs_prodos.cpp b/bin/newfs_prodos.cpp index 7982c35..43ddc4f 100644 --- a/bin/newfs_prodos.cpp +++ b/bin/newfs_prodos.cpp @@ -14,6 +14,7 @@ #define NEWFS_VERSION "0.1" using namespace ProFUSE; +using namespace Device; void usage() { From 011c3b7b4484a2971b3cd287c66040f73e33fd26 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 22 Feb 2011 05:09:45 +0000 Subject: [PATCH 204/236] linux header fixes git-svn-id: https://profuse.googlecode.com/svn/branches/v2@347 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/Adaptor.cpp | 1 + ProFUSE/Exception.cpp | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Device/Adaptor.cpp b/Device/Adaptor.cpp index 75b3846..7410611 100644 --- a/Device/Adaptor.cpp +++ b/Device/Adaptor.cpp @@ -2,6 +2,7 @@ #include +#include #include #include diff --git a/ProFUSE/Exception.cpp b/ProFUSE/Exception.cpp index a42b877..512a4d2 100644 --- a/ProFUSE/Exception.cpp +++ b/ProFUSE/Exception.cpp @@ -1,6 +1,7 @@ #include -#include +#include +#include using namespace ProFUSE; @@ -145,4 +146,4 @@ const char *ProDOSException::errorString() return ""; } return ""; -} \ No newline at end of file +} From e71ab41481b3a23436c6184732eddf171eb79dba Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 22 Feb 2011 05:10:32 +0000 Subject: [PATCH 205/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@348 aa027e90-d47c-11dd-86d7-074df07e0730 --- PROFuseX.xcodeproj/kelvin.pbxuser | 215 ++++-------------------- PROFuseX.xcodeproj/kelvin.perspectivev3 | 38 ++--- PROFuseX.xcodeproj/project.pbxproj | 2 + 3 files changed, 47 insertions(+), 208 deletions(-) diff --git a/PROFuseX.xcodeproj/kelvin.pbxuser b/PROFuseX.xcodeproj/kelvin.pbxuser index a4ce6fe..0471ce8 100644 --- a/PROFuseX.xcodeproj/kelvin.pbxuser +++ b/PROFuseX.xcodeproj/kelvin.pbxuser @@ -104,8 +104,8 @@ PBXFileDataSource_Warnings_ColumnID, ); }; - PBXPerProjectTemplateStateSaveDate = 299215102; - PBXWorkspaceStateSaveDate = 299215102; + PBXPerProjectTemplateStateSaveDate = 319589426; + PBXWorkspaceStateSaveDate = 319589426; }; perUserProjectItems = { B6272A9811D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9811D5AC5E0073C73A /* PBXTextBookmark */; @@ -117,13 +117,10 @@ B6272B0E11D691320073C73A /* PBXTextBookmark */ = B6272B0E11D691320073C73A /* PBXTextBookmark */; B6272B0F11D691320073C73A /* PBXTextBookmark */ = B6272B0F11D691320073C73A /* PBXTextBookmark */; B6272B1011D691320073C73A /* PBXTextBookmark */ = B6272B1011D691320073C73A /* PBXTextBookmark */; - B6272B1111D691320073C73A /* XCBuildMessageTextBookmark */ = B6272B1111D691320073C73A /* XCBuildMessageTextBookmark */; + B6272B1111D691320073C73A /* PBXTextBookmark */ = B6272B1111D691320073C73A /* PBXTextBookmark */; B6272B1311D691320073C73A /* PBXTextBookmark */ = B6272B1311D691320073C73A /* PBXTextBookmark */; B6272B1411D691320073C73A /* PBXTextBookmark */ = B6272B1411D691320073C73A /* PBXTextBookmark */; - B6272B1511D691320073C73A /* PBXTextBookmark */ = B6272B1511D691320073C73A /* PBXTextBookmark */; B6272B1611D691320073C73A /* PBXTextBookmark */ = B6272B1611D691320073C73A /* PBXTextBookmark */; - B6272B1711D691320073C73A /* PBXTextBookmark */ = B6272B1711D691320073C73A /* PBXTextBookmark */; - B6272B7711D6A3C30073C73A /* PBXTextBookmark */ = B6272B7711D6A3C30073C73A /* PBXTextBookmark */; B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */ = B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */; B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */ = B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */; B63EFDA011A4488200C90DCE /* PBXTextBookmark */ = B63EFDA011A4488200C90DCE /* PBXTextBookmark */; @@ -139,10 +136,10 @@ B63EFEA011A488C200C90DCE /* PBXTextBookmark */ = B63EFEA011A488C200C90DCE /* PBXTextBookmark */; B63EFEA111A488C200C90DCE /* PBXTextBookmark */ = B63EFEA111A488C200C90DCE /* PBXTextBookmark */; B63EFEA811A488C200C90DCE /* PBXTextBookmark */ = B63EFEA811A488C200C90DCE /* PBXTextBookmark */; - B656AE2411A84FA400AB578A /* PBXTextBookmark */ = B656AE2411A84FA400AB578A /* PBXTextBookmark */; + B64E9723130C8C860072B07E /* PBXTextBookmark */ = B64E9723130C8C860072B07E /* PBXTextBookmark */; + B64E972813103CAF0072B07E /* PBXTextBookmark */ = B64E972813103CAF0072B07E /* PBXTextBookmark */; B656AE2611A84FA400AB578A /* PBXTextBookmark */ = B656AE2611A84FA400AB578A /* PBXTextBookmark */; B65CFB6911B495790024A2D9 /* PBXTextBookmark */ = B65CFB6911B495790024A2D9 /* PBXTextBookmark */; - B65CFB6A11B495790024A2D9 /* PBXTextBookmark */ = B65CFB6A11B495790024A2D9 /* PBXTextBookmark */; B6E5F0DD11A60726000AD141 /* PBXTextBookmark */ = B6E5F0DD11A60726000AD141 /* PBXTextBookmark */; B6E5F0F211A73144000AD141 /* PBXTextBookmark */ = B6E5F0F211A73144000AD141 /* PBXTextBookmark */; B6E5F11211A73340000AD141 /* PBXTextBookmark */ = B6E5F11211A73340000AD141 /* PBXTextBookmark */; @@ -156,7 +153,6 @@ B6F3657E11AE255B0045E114 /* PBXTextBookmark */ = B6F3657E11AE255B0045E114 /* PBXTextBookmark */; B6F3665411B190370045E114 /* PBXTextBookmark */ = B6F3665411B190370045E114 /* PBXTextBookmark */; B6F3665C11B194AC0045E114 /* PBXTextBookmark */ = B6F3665C11B194AC0045E114 /* PBXTextBookmark */; - B6F366C211B1A28C0045E114 /* PBXTextBookmark */ = B6F366C211B1A28C0045E114 /* PBXTextBookmark */; B6F366C411B1A28C0045E114 /* PBXTextBookmark */ = B6F366C411B1A28C0045E114 /* PBXTextBookmark */; B6F366C611B1A28C0045E114 /* PBXTextBookmark */ = B6F366C611B1A28C0045E114 /* PBXTextBookmark */; B6F366C711B1A28C0045E114 /* PBXTextBookmark */ = B6F366C711B1A28C0045E114 /* PBXTextBookmark */; @@ -164,8 +160,6 @@ B6F366C911B1A28C0045E114 /* PBXTextBookmark */ = B6F366C911B1A28C0045E114 /* PBXTextBookmark */; B6F366CA11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CA11B1A28C0045E114 /* PBXTextBookmark */; B6F366CB11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CB11B1A28C0045E114 /* PBXTextBookmark */; - B6F366CC11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CC11B1A28C0045E114 /* PBXTextBookmark */; - B6F366D911B1A7A70045E114 /* PBXTextBookmark */ = B6F366D911B1A7A70045E114 /* PBXTextBookmark */; B6F3675411B316D10045E114 /* PBXTextBookmark */ = B6F3675411B316D10045E114 /* PBXTextBookmark */; B6F3677C11B326580045E114 /* PBXTextBookmark */ = B6F3677C11B326580045E114 /* PBXTextBookmark */; B6F3677D11B326580045E114 /* PBXTextBookmark */ = B6F3677D11B326580045E114 /* PBXTextBookmark */; @@ -175,7 +169,6 @@ B6F367AE11B337A70045E114 /* PBXTextBookmark */ = B6F367AE11B337A70045E114 /* PBXTextBookmark */; B6F3684911B44D090045E114 /* PBXTextBookmark */ = B6F3684911B44D090045E114 /* PBXTextBookmark */; B6F3684A11B44D090045E114 /* PBXTextBookmark */ = B6F3684A11B44D090045E114 /* PBXTextBookmark */; - B6F3684B11B44D090045E114 /* PBXTextBookmark */ = B6F3684B11B44D090045E114 /* PBXTextBookmark */; }; sourceControlManager = B63EFA6711A093C200C90DCE /* Source Control */; userBuildSettings = { @@ -334,17 +327,17 @@ vrLen = 679; vrLoc = 0; }; - B6272B1111D691320073C73A /* XCBuildMessageTextBookmark */ = { + B6272B1111D691320073C73A /* PBXTextBookmark */ = { isa = PBXTextBookmark; comments = "'Device' has not been declared"; fRef = B6272B1211D691320073C73A /* Bitmap.h */; - fallbackIsa = XCBuildMessageTextBookmark; rLen = 1; rLoc = 21; rType = 1; }; B6272B1211D691320073C73A /* Bitmap.h */ = { isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; name = Bitmap.h; path = ./ProDOS/Bitmap.h; sourceTree = ""; @@ -369,16 +362,6 @@ vrLen = 740; vrLoc = 0; }; - B6272B1511D691320073C73A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6272AA611D5AE0C0073C73A /* Bitmap.h */; - name = "Bitmap.h: 21"; - rLen = 77; - rLoc = 226; - rType = 0; - vrLen = 735; - vrLoc = 0; - }; B6272B1611D691320073C73A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; @@ -389,26 +372,6 @@ vrLen = 718; vrLoc = 403; }; - B6272B1711D691320073C73A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAB711A098C400C90DCE /* BlockCache.h */; - name = "BlockCache.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 909; - vrLoc = 148; - }; - B6272B7711D6A3C30073C73A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAB711A098C400C90DCE /* BlockCache.h */; - name = "BlockCache.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 928; - vrLoc = 129; - }; B63EFA6711A093C200C90DCE /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; @@ -544,9 +507,9 @@ }; B63EFAB711A098C400C90DCE /* BlockCache.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 754}}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 741}}"; sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{129, 928}"; + sepNavVisRange = "{129, 890}"; }; }; B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */ = { @@ -716,58 +679,6 @@ sepNavVisRange = "{687, 1732}"; }; }; - B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */ = { - isa = PBXFileReference; - fileEncoding = 4; - lastKnownFileType = sourcecode.cpp.cpp; - name = fuse_pascal.cpp; - path = /Users/kelvin/Projects/PROFuseX/fuse_pascal.cpp; - sourceTree = ""; - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 4082}}"; - sepNavSelRange = "{4414, 0}"; - sepNavVisRange = "{3977, 1077}"; - }; - }; - B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */ = { - isa = PBXFileReference; - fileEncoding = 4; - lastKnownFileType = sourcecode.cpp.cpp; - name = newfs_pascal.cpp; - path = /Users/kelvin/Projects/PROFuseX/newfs_pascal.cpp; - sourceTree = ""; - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1009, 4381}}"; - sepNavSelRange = "{4492, 0}"; - sepNavVisRange = "{2844, 1735}"; - }; - }; - B63EFC9D11A35F8200C90DCE /* fuse_pascal_ops.cpp */ = { - isa = PBXFileReference; - fileEncoding = 4; - lastKnownFileType = sourcecode.cpp.cpp; - name = fuse_pascal_ops.cpp; - path = /Users/kelvin/Projects/PROFuseX/fuse_pascal_ops.cpp; - sourceTree = ""; - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 6448}}"; - sepNavSelRange = "{855, 6}"; - sepNavVisRange = "{18, 1415}"; - }; - }; - B63EFC9F11A35F8F00C90DCE /* apfm.cpp */ = { - isa = PBXFileReference; - fileEncoding = 4; - lastKnownFileType = sourcecode.cpp.cpp; - name = apfm.cpp; - path = /Users/kelvin/Projects/PROFuseX/apfm.cpp; - sourceTree = ""; - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1009, 14040}}"; - sepNavSelRange = "{13109, 0}"; - sepNavVisRange = "{11908, 1651}"; - }; - }; B63EFCC811A366C800C90DCE /* MappedFile.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; @@ -1047,6 +958,26 @@ vrLen = 834; vrLoc = 0; }; + B64E9723130C8C860072B07E /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAB711A098C400C90DCE /* BlockCache.h */; + name = "BlockCache.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 890; + vrLoc = 129; + }; + B64E972813103CAF0072B07E /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAB711A098C400C90DCE /* BlockCache.h */; + name = "BlockCache.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 890; + vrLoc = 129; + }; B656AE0211A84F5800AB578A /* fuse_pascal */ = { activeExec = 0; executables = ( @@ -1080,16 +1011,6 @@ sourceDirectories = ( ); }; - B656AE2411A84FA400AB578A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9D11A35F8200C90DCE /* fuse_pascal_ops.cpp */; - name = "fuse_pascal_ops.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 813; - vrLoc = 0; - }; B656AE2611A84FA400AB578A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFAA211A094E000C90DCE /* RawDevice.h */; @@ -1163,16 +1084,6 @@ vrLen = 800; vrLoc = 2262; }; - B65CFB6A11B495790024A2D9 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6F3647B11AB361D0045E114 /* xattr.cpp */; - name = "xattr.cpp: 330"; - rLen = 6; - rLoc = 6657; - rType = 0; - vrLen = 829; - vrLoc = 5931; - }; B6E5F0DD11A60726000AD141 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; @@ -1250,19 +1161,6 @@ vrLen = 1126; vrLoc = 442; }; - B6F3647B11AB361D0045E114 /* xattr.cpp */ = { - isa = PBXFileReference; - fileEncoding = 4; - lastKnownFileType = sourcecode.cpp.cpp; - name = xattr.cpp; - path = /Users/kelvin/Projects/PROFuseX/xattr.cpp; - sourceTree = ""; - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 5512}}"; - sepNavSelRange = "{6657, 6}"; - sepNavVisRange = "{5931, 829}"; - }; - }; B6F3647F11AB36260045E114 /* xattr */ = { activeExec = 0; executables = ( @@ -1372,7 +1270,7 @@ continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; - fileReference = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; + fileReference = B6272A8E11D5AC3C0073C73A /* apfm.cpp */; functionName = "action_rm(int argc, char **argv, Pascal::VolumeEntry *volume)"; hitCount = 0; ignoreCount = 0; @@ -1435,16 +1333,6 @@ vrLen = 951; vrLoc = 1203; }; - B6F366C211B1A28C0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9B11A35F7B00C90DCE /* newfs_pascal.cpp */; - name = "newfs_pascal.cpp: 227"; - rLen = 0; - rLoc = 5474; - rType = 0; - vrLen = 1282; - vrLoc = 4530; - }; B6F366C411B1A28C0045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; @@ -1515,26 +1403,6 @@ vrLen = 613; vrLoc = 128; }; - B6F366CC11B1A28C0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9F11A35F8F00C90DCE /* apfm.cpp */; - name = "apfm.cpp: 755"; - rLen = 0; - rLoc = 22959; - rType = 0; - vrLen = 884; - vrLoc = 15404; - }; - B6F366D911B1A7A70045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC9911A35F7200C90DCE /* fuse_pascal.cpp */; - name = "fuse_pascal.cpp: 195"; - rLen = 0; - rLoc = 4414; - rType = 0; - vrLen = 1077; - vrLoc = 3977; - }; B6F3675411B316D10045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; @@ -1619,19 +1487,6 @@ vrLen = 874; vrLoc = 0; }; - B6F3682111B430870045E114 /* newfs_prodos.cpp */ = { - isa = PBXFileReference; - fileEncoding = 4; - lastKnownFileType = sourcecode.cpp.cpp; - name = newfs_prodos.cpp; - path = /Users/kelvin/Projects/PROFuseX/newfs_prodos.cpp; - sourceTree = ""; - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1009, 3185}}"; - sepNavSelRange = "{266, 0}"; - sepNavVisRange = "{0, 1849}"; - }; - }; B6F3682411B431AC0045E114 /* newfs_prodos */ = { activeExec = 0; executables = ( @@ -1685,14 +1540,4 @@ vrLen = 803; vrLoc = 0; }; - B6F3684B11B44D090045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6F3682111B430870045E114 /* newfs_prodos.cpp */; - name = "newfs_prodos.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 1184; - vrLoc = 0; - }; } diff --git a/PROFuseX.xcodeproj/kelvin.perspectivev3 b/PROFuseX.xcodeproj/kelvin.perspectivev3 index 8a7e152..c78c1ec 100644 --- a/PROFuseX.xcodeproj/kelvin.perspectivev3 +++ b/PROFuseX.xcodeproj/kelvin.perspectivev3 @@ -278,13 +278,13 @@ PBXSmartGroupTreeModuleOutlineStateSelectionKey - 19 - 17 + 39 + 24 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey - {{0, 0}, {318, 941}} + {{0, 164}, {318, 941}} PBXTopSmartGroupGIDs @@ -329,7 +329,7 @@ _historyCapacity 0 bookmark - B6272B7711D6A3C30073C73A + B64E972813103CAF0072B07E history B63EFC2611A2D5A400C90DCE @@ -352,7 +352,6 @@ B6E5F11211A73340000AD141 B6E5F13A11A74F2B000AD141 B6E5F18211A76B74000AD141 - B656AE2411A84FA400AB578A B656AE2611A84FA400AB578A B6F3647111AB35FE0045E114 B6F3649E11AB59190045E114 @@ -362,7 +361,6 @@ B6F3657E11AE255B0045E114 B6F3665411B190370045E114 B6F3665C11B194AC0045E114 - B6F366C211B1A28C0045E114 B6F366C411B1A28C0045E114 B6F366C611B1A28C0045E114 B6F366C711B1A28C0045E114 @@ -370,8 +368,6 @@ B6F366C911B1A28C0045E114 B6F366CA11B1A28C0045E114 B6F366CB11B1A28C0045E114 - B6F366CC11B1A28C0045E114 - B6F366D911B1A7A70045E114 B6F3675411B316D10045E114 B6F3677C11B326580045E114 B6F3677D11B326580045E114 @@ -381,9 +377,7 @@ B6F367AE11B337A70045E114 B6F3684911B44D090045E114 B6F3684A11B44D090045E114 - B6F3684B11B44D090045E114 B65CFB6911B495790024A2D9 - B65CFB6A11B495790024A2D9 B6272A9811D5AC5E0073C73A B6272A9911D5AC5E0073C73A B6272A9A11D5AC5E0073C73A @@ -396,9 +390,8 @@ B6272B1111D691320073C73A B6272B1311D691320073C73A B6272B1411D691320073C73A - B6272B1511D691320073C73A B6272B1611D691320073C73A - B6272B1711D691320073C73A + B64E9723130C8C860072B07E SplitCount @@ -412,18 +405,18 @@ GeometryConfiguration Frame - {{0, 0}, {899, 535}} + {{0, 0}, {899, 526}} RubberWindowFrame 182 101 1239 1000 0 0 1920 1178 Module PBXNavigatorGroup Proportion - 535pt + 526pt Proportion - 419pt + 428pt Tabs @@ -437,7 +430,9 @@ GeometryConfiguration Frame - {{10, 27}, {899, 392}} + {{10, 27}, {899, 401}} + RubberWindowFrame + 182 101 1239 1000 0 0 1920 1178 Module XCDetailModule @@ -491,9 +486,7 @@ GeometryConfiguration Frame - {{10, 27}, {899, 392}} - RubberWindowFrame - 182 101 1239 1000 0 0 1920 1178 + {{10, 27}, {899, 401}} Module PBXBuildResultsModule @@ -521,11 +514,11 @@ TableOfContents - B6272A9F11D5AC5E0073C73A + B64E9725130C8C860072B07E 1CA23ED40692098700951B8B - B6272AA011D5AC5E0073C73A + B64E9726130C8C860072B07E B63EFA6111A093C200C90DCE - B6272AA111D5AC5E0073C73A + B64E9727130C8C860072B07E 1CA23EDF0692099D00951B8B 1CA23EE00692099D00951B8B 1CA23EE10692099D00951B8B @@ -715,7 +708,6 @@ 5 WindowOrderList - B6272B1911D691320073C73A /Users/kelvin/Projects/PROFuseX/PROFuseX.xcodeproj WindowString diff --git a/PROFuseX.xcodeproj/project.pbxproj b/PROFuseX.xcodeproj/project.pbxproj index 69606f7..944545d 100644 --- a/PROFuseX.xcodeproj/project.pbxproj +++ b/PROFuseX.xcodeproj/project.pbxproj @@ -169,6 +169,7 @@ B656AE0311A84F5800AB578A /* fuse_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fuse_pascal; sourceTree = BUILT_PRODUCTS_DIR; }; B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NibbleTest.cpp; sourceTree = ""; }; B656AF0311AA105500AB578A /* NibbleTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NibbleTest; sourceTree = BUILT_PRODUCTS_DIR; }; + B659C142131368BA0058DC9C /* Device.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Device.h; sourceTree = ""; }; B6F3648011AB36260045E114 /* xattr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xattr; sourceTree = BUILT_PRODUCTS_DIR; }; B6F3651A11ADD0280045E114 /* VolumeEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VolumeEntry.h; sourceTree = ""; }; B6F3651B11ADD0280045E114 /* FileEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileEntry.h; sourceTree = ""; }; @@ -295,6 +296,7 @@ B63EFA9411A094E000C90DCE /* Device */ = { isa = PBXGroup; children = ( + B659C142131368BA0058DC9C /* Device.h */, B63EFA9511A094E000C90DCE /* BlockDevice.cpp */, B63EFA9611A094E000C90DCE /* BlockDevice.h */, B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */, From 89e80dcc10429c78c707fb6ae9c74984ac154fa4 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 26 Feb 2011 02:11:46 +0000 Subject: [PATCH 206/236] use smart pointer for everything (not yet tested) git-svn-id: https://profuse.googlecode.com/svn/branches/v2@350 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/Entry.cpp | 1 - Pascal/Entry.h | 15 ++- Pascal/FileEntry.cpp | 105 ++++++++++++----- Pascal/FileEntry.h | 15 ++- Pascal/VolumeEntry.cpp | 251 +++++++++++++++++++++------------------- Pascal/VolumeEntry.h | 33 ++++-- bin/apfm.cpp | 18 +-- bin/fuse_pascal.cpp | 5 +- bin/fuse_pascal_ops.cpp | 53 ++++++--- bin/newfs_pascal.cpp | 6 +- 10 files changed, 305 insertions(+), 197 deletions(-) diff --git a/Pascal/Entry.cpp b/Pascal/Entry.cpp index e7bd872..6cb406e 100644 --- a/Pascal/Entry.cpp +++ b/Pascal/Entry.cpp @@ -64,7 +64,6 @@ Entry::Entry() _lastBlock = 0; _fileKind = 0; _inode = 0; - _parent = NULL; _address = NULL; } diff --git a/Pascal/Entry.h b/Pascal/Entry.h index c4438d9..c122951 100644 --- a/Pascal/Entry.h +++ b/Pascal/Entry.h @@ -1,6 +1,8 @@ #ifndef __PASCAL_ENTRY_H__ #define __PASCAL_ENTRY_H__ +#include + #include @@ -31,7 +33,14 @@ namespace Pascal { class FileEntry; class VolumeEntry; - class Entry { + + typedef std::tr1::shared_ptr FileEntryPointer; + typedef std::tr1::shared_ptr VolumeEntryPointer; + + typedef std::tr1::weak_ptr FileEntryWeakPointer; + typedef std::tr1::weak_ptr VolumeEntryWeakPointer; + + class Entry : public std::tr1::enable_shared_from_this { public: @@ -47,7 +56,7 @@ namespace Pascal { unsigned inode() const { return _inode; } void setInode(unsigned inode) { _inode = inode; } - VolumeEntry *parent() { return _parent; } + VolumeEntryWeakPointer parent() { return _parent; } protected: @@ -70,7 +79,7 @@ namespace Pascal { friend class VolumeEntry; - VolumeEntry *_parent; + VolumeEntryWeakPointer _parent; unsigned _address; }; diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index 351214a..f4a1c18 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -42,6 +42,16 @@ unsigned FileEntry::ValidName(const char *cp) return Entry::ValidName(cp, 15); } +FileEntryPointer FileEntry::Open(void *vp) +{ + return FileEntryPointer(new FileEntry(vp)); +} + +FileEntryPointer FileEntry::Create(const char *name, unsigned fileKind) +{ + return FileEntryPointer(new FileEntry(name, fileKind)); +} + FileEntry::FileEntry(void *vp) : Entry(vp) { @@ -99,7 +109,10 @@ void FileEntry::setFileKind(unsigned kind) _pageSize = NULL; } - parent()->writeEntry(this); + VolumeEntryPointer v = parent().lock(); + + // throw if expired? + if (v) v->writeEntry(this); } @@ -194,7 +207,9 @@ int FileEntry::truncate(unsigned newSize) return -1; _modification = Date::Today(); - parent()->writeEntry(this); + + VolumeEntryPointer v = parent().lock(); + if (v) v->writeEntry(this); return 0; } @@ -211,6 +226,8 @@ int FileEntry::truncateCommon(unsigned newSize) unsigned currentSize = fileSize(); + VolumeEntryPointer v = parent().lock(); + if (newSize == currentSize) return 0; if (newSize > currentSize) { @@ -228,12 +245,13 @@ int FileEntry::truncateCommon(unsigned newSize) { // last page not full unsigned count = std::min(512 - _lastByte, remainder); - uint8_t *address = (uint8_t *)parent()->loadBlock(block); - - std::memset(address + _lastByte, 0, count); - - parent()->unloadBlock(block, true); + if (v) + { + uint8_t *address = (uint8_t *)v->loadBlock(block); + std::memset(address + _lastByte, 0, count); + v->unloadBlock(block, true); + } remainder -= count; } block++; @@ -241,12 +259,12 @@ int FileEntry::truncateCommon(unsigned newSize) while (remainder) { unsigned count = std::min(512u, remainder); - uint8_t *address = (uint8_t *)parent()->loadBlock(block); - - std::memset(address, 0, count); - - parent()->unloadBlock(block, true); - + if (v) + { + uint8_t *address = (uint8_t *)v->loadBlock(block); + std::memset(address, 0, count); + v->unloadBlock(block, true); + } remainder -= count; block++; } @@ -264,7 +282,15 @@ int FileEntry::write(TextWriter &text) { unsigned blocks = text.blocks(); - if (parent()->readOnly()) + VolumeEntryPointer v = parent().lock(); + if (!v) + { + errno = EROFS; + return -1; + } + + + if (v->readOnly()) { errno = EROFS; return -1; @@ -286,7 +312,7 @@ int FileEntry::write(TextWriter &text) for (unsigned i = 0; i < blocks; ++i) { void *buffer = text.data(i); - parent()->writeBlock(_firstBlock + i, buffer); + v->writeBlock(_firstBlock + i, buffer); } @@ -294,8 +320,8 @@ int FileEntry::write(TextWriter &text) setFileSize(blocks * 512); - parent()->writeEntry(this); - parent()->sync(); + v->writeEntry(this); + v->sync(); return blocks * 512; } @@ -304,8 +330,15 @@ int FileEntry::write(const uint8_t *buffer, unsigned size, unsigned offset) { #undef __METHOD__ #define __METHOD__ "FileEntry::write" - - if (parent()->readOnly()) + + VolumeEntryPointer v = parent().lock(); + if (!v) + { + errno = EROFS; + return -1; + } + + if (v->readOnly()) { errno = EROFS; return -1; @@ -342,10 +375,10 @@ int FileEntry::write(const uint8_t *buffer, unsigned size, unsigned offset) if (start) { unsigned count = std::min(512 - start, remainder); - uint8_t *address = (uint8_t *)parent()->loadBlock(block); + uint8_t *address = (uint8_t *)v->loadBlock(block); std::memcpy(address + start, buffer, count); - parent()->unloadBlock(block, true); + v->unloadBlock(block, true); remainder -= count; buffer += count; @@ -354,12 +387,12 @@ int FileEntry::write(const uint8_t *buffer, unsigned size, unsigned offset) while (remainder) { - uint8_t *address = (uint8_t *)parent()->loadBlock(block); + uint8_t *address = (uint8_t *)v->loadBlock(block); unsigned count = std::min(512u, size); std::memcpy(address, buffer, count); - parent()->unloadBlock(block, true); + v->unloadBlock(block, true); remainder -= count; buffer += count; @@ -371,7 +404,7 @@ int FileEntry::write(const uint8_t *buffer, unsigned size, unsigned offset) _modification = Date::Today(); - parent()->writeEntry(this); + v->writeEntry(this); return size; } @@ -419,6 +452,13 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset) unsigned count = 0; unsigned block = 0; + + VolumeEntryPointer v = parent().lock(); + if (!v) + { + errno = EROFS; + return 0; + } block = _firstBlock + (offset / 512); @@ -433,7 +473,7 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset) { unsigned bytes = std::min(offset % 512, size); - parent()->readBlock(block++, tmp); + v->readBlock(block++, tmp); std::memcpy(buffer, tmp + 512 - bytes, bytes); @@ -448,7 +488,7 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset) while (size >= 512) { - parent()->readBlock(block++, buffer); + v->readBlock(block++, buffer); buffer += 512; count += 512; @@ -460,7 +500,7 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset) */ if (size) { - parent()->readBlock(block, tmp); + v->readBlock(block, tmp); std::memcpy(buffer, tmp, size); count += size; @@ -589,13 +629,20 @@ unsigned FileEntry::textReadPage(unsigned block, uint8_t *in) // reads up to 2 blocks. // assumes block within _startBlock ... _lastBlock - 1 - parent()->readBlock(block, in); + VolumeEntryPointer v = parent().lock(); + if (!v) + { + errno = EROFS; + return 0; + } + + v->readBlock(block, in); if (block + 1 == _lastBlock) { return _lastByte; } - parent()->readBlock(block + 1, in + 512); + v->readBlock(block + 1, in + 512); if (block +2 == _lastBlock) { return 512 + _lastByte; diff --git a/Pascal/FileEntry.h b/Pascal/FileEntry.h index 721e80e..7bec9ac 100644 --- a/Pascal/FileEntry.h +++ b/Pascal/FileEntry.h @@ -22,8 +22,10 @@ namespace Pascal { static bool Uncompress(std::string& text); - FileEntry(const char *name, unsigned fileKind); - FileEntry(void *vp); + static FileEntryPointer Create(const char *name, unsigned fileKind); + static FileEntryPointer Open(void *vp); + + virtual ~FileEntry(); @@ -54,6 +56,15 @@ namespace Pascal { friend class VolumeEntry; + FileEntry(const char *name, unsigned fileKind); + FileEntry(void *vp); + + FileEntryPointer thisPointer() + { + return std::tr1::static_pointer_cast(shared_from_this()); + } + + void setName(const char *name); int truncateCommon(unsigned newSize); diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index 03e2f52..a4eff36 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -61,6 +61,26 @@ unsigned VolumeEntry::ValidName(const char *cp) return Entry::ValidName(cp, 7); } + +VolumeEntryPointer VolumeEntry::Open(Device::BlockDevicePointer device) +{ + VolumeEntryPointer ptr(new VolumeEntry(device)); + + return ptr; +} + +VolumeEntryPointer VolumeEntry::Create(Device::BlockDevicePointer device, const char *name) +{ + VolumeEntryPointer ptr(new VolumeEntry(device, name)); + + + // set up the weak references from the file entry to this. + if (ptr) ptr->setParents(); + + return ptr; +} + + VolumeEntry::VolumeEntry() { _fileNameLength = 0; @@ -74,7 +94,7 @@ VolumeEntry::VolumeEntry() _inodeGenerator = 1; } -VolumeEntry::VolumeEntry(const char *name, Device::BlockDevicePointer device) : +VolumeEntry::VolumeEntry(Device::BlockDevicePointer device, const char *name) : _device(device) { #undef __METHOD__ @@ -166,88 +186,79 @@ VolumeEntry::VolumeEntry(Device::BlockDevicePointer device) } // now load up all the children. - // if this throws, memory could be lost... - + // the parent cannot be set (yet), since we need a shared_ptr to create a weak_ptr. - try - { - - std::vector::iterator iter; - unsigned block; - - for (unsigned i = 1; i <= _fileCount; ++i) - { - std::auto_ptr child; - - // - child.reset(new FileEntry(buffer.get() + i * 0x1a)); - - child->setInode(++_inodeGenerator); - child->_parent = this; - child->_address = 512 * 2 + i * 0x1a; - - _files.push_back(child.release()); - } - - // sanity check _firstBlock, _lastBlock? - - block = _lastBlock; - - for (iter = _files.begin(); iter != _files.end(); ++iter) - { - FileEntry *e = *iter; - bool error = false; - if (e->_firstBlock > e->_lastBlock) - error = true; + std::vector::iterator iter; - if (e->_firstBlock >= _lastVolumeBlock) - error = true; - - if (e->_lastBlock > _lastVolumeBlock) - error = true; - - if (e->_firstBlock < block) - error = true; - - if (error) - throw ProDOSException(__METHOD__ ": Invalid file entry.", ProFUSE::dirError); - - block = e->_lastBlock; - - } - - - calcMaxFileSize(); - - } - catch (...) + unsigned block; + + for (unsigned i = 1; i <= _fileCount; ++i) { - std::vector::iterator iter; - - for(iter = _files.begin(); iter != _files.end(); ++iter) - { - if (*iter) delete *iter; - } - - throw; + FileEntryPointer child; + + // + child = FileEntry::Open(buffer.get() + i * 0x1a); + + child->setInode(++_inodeGenerator); + // need to set later.... + //child->_parent = this; + child->_address = 512 * 2 + i * 0x1a; + + _files.push_back(child); } + // sanity check _firstBlock, _lastBlock? + + block = _lastBlock; + + for (iter = _files.begin(); iter != _files.end(); ++iter) + { + FileEntryPointer e = *iter; + bool error = false; + if (e->_firstBlock > e->_lastBlock) + error = true; + if (e->_firstBlock >= _lastVolumeBlock) + error = true; + + if (e->_lastBlock > _lastVolumeBlock) + error = true; + + if (e->_firstBlock < block) + error = true; + + if (error) + throw ProDOSException(__METHOD__ ": Invalid file entry.", ProFUSE::dirError); + + block = e->_lastBlock; + + } + + + calcMaxFileSize(); } VolumeEntry::~VolumeEntry() { - - std::vector::iterator iter; - for(iter = _files.begin(); iter != _files.end(); ++iter) - { - if (*iter) delete *iter; - } - } +void VolumeEntry::setParents() +{ + // parent is this.... + + VolumeEntryWeakPointer parent(thisPointer()); + std::vector::iterator iter; + + for (iter = _files.begin(); iter != _files.end(); ++iter) + { + FileEntryPointer e = *iter; + + e->_parent = parent; + } +} + void VolumeEntry::init(void *vp) { #undef __METHOD__ @@ -278,20 +289,20 @@ void VolumeEntry::init(void *vp) } -FileEntry *VolumeEntry::fileAtIndex(unsigned i) const +FileEntryPointer VolumeEntry::fileAtIndex(unsigned i) const { - return i < _files.size() ? _files[i] : NULL; + return i < _files.size() ? _files[i] : FileEntryPointer(); } -FileEntry *VolumeEntry::fileByName(const char *name) const +FileEntryPointer VolumeEntry::fileByName(const char *name) const { - std::vector::const_iterator iter; + std::vector::const_iterator iter; for(iter = _files.begin(); iter != _files.end(); ++iter) { - FileEntry *e = *iter; + FileEntryPointer e = *iter; if (::strcasecmp(name, e->name()) == 0) return e; } - return NULL; + return FileEntryPointer(); } /* @@ -303,7 +314,7 @@ int VolumeEntry::unlink(const char *name) { unsigned index; - std::vector::iterator iter; + std::vector::iterator iter; if (_device->readOnly()) { @@ -315,7 +326,7 @@ int VolumeEntry::unlink(const char *name) for (iter = _files.begin(); iter != _files.end(); ++iter) { - FileEntry *e = *iter; + FileEntryPointer e = *iter; if (::strcasecmp(name, e->name()) == 0) { @@ -323,12 +334,11 @@ int VolumeEntry::unlink(const char *name) // _maxFileSize. if (iter != _files.begin()) { - FileEntry *prev = iter[-1]; + FileEntryPointer prev = iter[-1]; prev->_maxFileSize += e->_maxFileSize; } - delete e; - *iter = NULL; + iter->reset(); break; } } @@ -347,7 +357,7 @@ int VolumeEntry::unlink(const char *name) // reset addresses. for ( ; iter != _files.end(); ++iter) { - FileEntry *e = *iter; + FileEntryPointer e = *iter; e->_address -= 0x1a; } @@ -380,7 +390,7 @@ int VolumeEntry::unlink(const char *name) */ int VolumeEntry::rename(const char *oldName, const char *newName) { - FileEntry *e; + FileEntryPointer e; // check if read only. @@ -417,7 +427,7 @@ int VolumeEntry::rename(const char *oldName, const char *newName) // and commit to disk. - writeEntry(e); + writeEntry(e.get()); _cache->sync(); return 0; @@ -431,8 +441,8 @@ int VolumeEntry::rename(const char *oldName, const char *newName) */ int VolumeEntry::copy(const char *oldName, const char *newName) { - FileEntry *oldEntry; - FileEntry *newEntry; + FileEntryPointer oldEntry; + FileEntryPointer newEntry; // check if read only. if (_device->readOnly()) { @@ -482,14 +492,14 @@ int VolumeEntry::copy(const char *oldName, const char *newName) return -1; } - newEntry = NULL; + newEntry.reset(); if (unlink(newName) != 0) return -1; } } - if (newEntry == NULL) + if (!newEntry) { // newName does not exist (or was just deleted), so create a new file (if possible) and write to it. if (maxContiguousBlocks() < blocks) @@ -534,7 +544,7 @@ int VolumeEntry::copy(const char *oldName, const char *newName) * * */ -FileEntry *VolumeEntry::create(const char *name, unsigned blocks) +FileEntryPointer VolumeEntry::create(const char *name, unsigned blocks) { // 0. check read only access. // 1. verify < 77 file names. @@ -547,46 +557,45 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks) unsigned lastBlock = _lastBlock; - std::auto_ptrentry; - FileEntry *prev = NULL; - FileEntry *curr = NULL; - std::vector::iterator iter; + FileEntryPointer entry; + FileEntryPointer prev; + FileEntryPointer curr; + std::vector::iterator iter; if (readOnly()) { errno = EROFS; - return NULL; + return FileEntryPointer(); } if (_fileCount == kMaxFiles) { errno = ENOSPC; - return NULL; + return FileEntryPointer(); } if (!FileEntry::ValidName(name)) { errno = EINVAL; - return NULL; + return FileEntryPointer(); } if (fileByName(name)) { errno = EEXIST; - return NULL; + return FileEntryPointer(); } - entry.reset(new FileEntry(name, kUntypedFile)); + entry = FileEntry::Create(name, kUntypedFile); - - std::auto_ptr buffer(readDirectoryHeader()); + ProFUSE::auto_array buffer(readDirectoryHeader()); for (iter = _files.begin(); iter != _files.end(); ++iter) { - FileEntry *e = *iter; + FileEntryPointer e = *iter; unsigned freeSpace = e->_firstBlock - _lastBlock; // this could do something stupid like selecting a slot with only 1 free block but too bad. @@ -611,12 +620,13 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks) // keep track of the index *before* the insert. unsigned index = distance(_files.begin(), iter); // current index. - iter = _files.insert(iter, entry.get()); + iter = _files.insert(iter, entry); ++_fileCount; - curr = entry.release(); + curr = entry; - curr->_parent = this; + //curr->_parent = this; + curr->_parent = VolumeEntryWeakPointer(thisPointer()); curr->_firstBlock = lastBlock; curr->_lastBlock = lastBlock + 1; curr->_lastByte = 0; @@ -638,15 +648,16 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks) if (freeSpace < blocks) { errno = ENOSPC; - return NULL; + return FileEntryPointer(); } - _files.push_back(entry.get()); + _files.push_back(entry); _fileCount++; - curr = entry.release(); + curr = entry; - curr->_parent = this; + //curr->_parent = this; + curr->_parent = VolumeEntryWeakPointer(thisPointer()); curr->_firstBlock = lastBlock; curr->_lastBlock = lastBlock + 1; curr->_lastByte = 0; @@ -658,7 +669,7 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks) prev->_maxFileSize = prev->blocks() * 512; } - writeEntry(curr); + writeEntry(curr.get()); writeEntry(); // header. } @@ -670,7 +681,7 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks) unsigned address = 2 * 512 + 0x1a; for (iter = _files.begin(); iter != _files.end(); ++iter, address += 0x1a) { - FileEntry *e = *iter; + FileEntryPointer e = *iter; e->_address = address; } @@ -706,7 +717,7 @@ int VolumeEntry::krunch() { unsigned prevBlock; - std::vector::const_iterator iter; + std::vector::const_iterator iter; bool gap = false; @@ -716,7 +727,7 @@ int VolumeEntry::krunch() for (iter = _files.begin(); iter != _files.end(); ++iter) { - FileEntry *e = *iter; + FileEntryPointer e = *iter; unsigned first = e->firstBlock(); unsigned last = e->lastBlock(); @@ -751,7 +762,7 @@ int VolumeEntry::krunch() unsigned offset = 0; for (iter = _files.begin(); iter != _files.end(); ++iter, ++offset) { - FileEntry *e = *iter; + FileEntryPointer e = *iter; b.setOffset(0x1a + 0x1a * offset); @@ -812,13 +823,13 @@ unsigned VolumeEntry::freeBlocks(bool krunched) const if (krunched) { - std::vector::const_iterator iter; + std::vector::const_iterator iter; lastBlock = _lastBlock; for (iter = _files.begin(); iter != _files.end(); ++iter) { - const FileEntry *e = *iter; + const FileEntryPointer e = *iter; freeBlocks += e->_firstBlock - lastBlock; lastBlock = e->_lastBlock; } @@ -842,13 +853,13 @@ unsigned VolumeEntry::freeBlocks(bool krunched) const bool VolumeEntry::canKrunch() const { - std::vector::const_iterator iter; + std::vector::const_iterator iter; unsigned lastBlock = _lastBlock; for (iter = _files.begin(); iter != _files.end(); ++iter) { - const FileEntry *e = *iter; + const FileEntryPointer e = *iter; if (e->_lastBlock != lastBlock) return true; lastBlock = e->_lastBlock; } @@ -864,13 +875,13 @@ unsigned VolumeEntry::maxContiguousBlocks() const { unsigned max = 0; - std::vector::const_iterator iter; + std::vector::const_iterator iter; unsigned lastBlock = _lastBlock; for (iter = _files.begin(); iter != _files.end(); ++iter) { - const FileEntry *e = *iter; + const FileEntryPointer e = *iter; unsigned free = e->_firstBlock - lastBlock; max = std::max(max, free); @@ -999,11 +1010,11 @@ void VolumeEntry::writeEntry(FileEntry *e) // set _maxFileSize for all entries. void VolumeEntry::calcMaxFileSize() { - std::vector::reverse_iterator riter; + std::vector::reverse_iterator riter; unsigned block = _lastVolumeBlock; for (riter = _files.rbegin(); riter != _files.rend(); ++riter) { - FileEntry *e = *riter; + FileEntryPointer e = *riter; e->_maxFileSize = (block - e->_firstBlock) * 512; block = e->_firstBlock; } diff --git a/Pascal/VolumeEntry.h b/Pascal/VolumeEntry.h index 2dcc0ea..4b3f8a4 100644 --- a/Pascal/VolumeEntry.h +++ b/Pascal/VolumeEntry.h @@ -9,20 +9,18 @@ namespace Pascal { - class FileEntry; class VolumeEntry : public Entry { public: - + static unsigned ValidName(const char *); + + static VolumeEntryPointer Open(Device::BlockDevicePointer); + static VolumeEntryPointer Create(Device::BlockDevicePointer, const char *name); + // - // create new - VolumeEntry(const char *name, Device::BlockDevicePointer); - - // open existing - VolumeEntry(Device::BlockDevicePointer); virtual ~VolumeEntry(); const char *name() const { return _fileName; } @@ -36,8 +34,8 @@ namespace Pascal { bool canKrunch() const; - FileEntry *fileAtIndex(unsigned i) const; - FileEntry *fileByName(const char *name) const; + FileEntryPointer fileAtIndex(unsigned i) const; + FileEntryPointer fileByName(const char *name) const; void *loadBlock(unsigned block); @@ -53,7 +51,7 @@ namespace Pascal { int unlink(const char *name); int rename(const char *oldName, const char *newName); int copy(const char *oldName, const char *newName); - FileEntry *create(const char *name, unsigned blocks); + FileEntryPointer create(const char *name, unsigned blocks); int krunch(); @@ -65,10 +63,21 @@ namespace Pascal { private: friend class FileEntry; + VolumeEntry(); - + VolumeEntry(Device::BlockDevicePointer, const char *name); + VolumeEntry(Device::BlockDevicePointer); + + VolumeEntryPointer thisPointer() + { + return std::tr1::static_pointer_cast(shared_from_this()); + } + void init(void *); + void setParents(); + + uint8_t *readDirectoryHeader(); @@ -90,7 +99,7 @@ namespace Pascal { unsigned _accessTime; Pascal::Date _lastBoot; - std::vector _files; + std::vector _files; unsigned _inodeGenerator; Device::BlockDevicePointer _device; diff --git a/bin/apfm.cpp b/bin/apfm.cpp index cd65dae..c81885f 100644 --- a/bin/apfm.cpp +++ b/bin/apfm.cpp @@ -263,7 +263,7 @@ void printUnusedEntry(unsigned block, unsigned size) std::printf("< UNUSED > %4u %4u\n", size, block); } -void printFileEntry(Pascal::FileEntry *e, bool extended) +void printFileEntry(Pascal::FileEntryPointer e, bool extended) { Pascal::Date dt = e->modification(); @@ -329,7 +329,7 @@ int action_ls(int argc, char **argv, Pascal::VolumeEntry *volume) for (unsigned i = 0; i < fileCount; ++i) { - Pascal::FileEntry *e = volume->fileAtIndex(i); + Pascal::FileEntryPointer e = volume->fileAtIndex(i); if (!e) continue; @@ -409,7 +409,7 @@ int action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume) unsigned fileSize; unsigned offset; uint8_t buffer[512]; - Pascal::FileEntry *e = NULL; + Pascal::FileEntryPointer e; // find it... e = volume->fileByName(argv[i]); @@ -588,7 +588,7 @@ int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume) // TODO -- catch errors ? for (int i = 0; i < argc; ++i) { - Pascal::FileEntry *e = volume->fileByName(argv[i]); + Pascal::FileEntryPointer e = volume->fileByName(argv[i]); if (!e) { @@ -691,7 +691,7 @@ int action_get(int argc, char **argv, Pascal::VolumeEntry *volume) argc -= optind; argv += optind; - Pascal::FileEntry *entry; + Pascal::FileEntryPointer entry; switch(argc) { @@ -910,7 +910,7 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) blocks = text.blocks(); - Pascal::FileEntry *entry = volume->create(outfile, blocks); + Pascal::FileEntryPointer entry = volume->create(outfile, blocks); if (!entry) { perror(NULL); @@ -923,7 +923,7 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) } else { - Pascal::FileEntry *entry = volume->create(outfile, blocks); + Pascal::FileEntryPointer entry = volume->create(outfile, blocks); if (!entry) { perror(NULL); @@ -962,7 +962,7 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume) int main(int argc, char **argv) { - std::auto_ptr volume; + Pascal::VolumeEntryPointer volume; Device::BlockDevicePointer device; unsigned fmt = 0; @@ -1027,7 +1027,7 @@ int main(int argc, char **argv) device = Device::BlockDevice::Open(file, commandFlags(actionCode), fmt); - volume.reset( new Pascal::VolumeEntry(device)); + volume = Pascal::VolumeEntry::Open(device); device.reset(); switch (actionCode) diff --git a/bin/fuse_pascal.cpp b/bin/fuse_pascal.cpp index 17f230c..e19edf8 100644 --- a/bin/fuse_pascal.cpp +++ b/bin/fuse_pascal.cpp @@ -169,7 +169,7 @@ int main(int argc, char **argv) int multithread = false; - std::auto_ptr volume; + Pascal::VolumeEntryPointer volume; init_ops(&pascal_ops); @@ -210,8 +210,7 @@ int main(int argc, char **argv) exit(1); } - volume.reset( new Pascal::VolumeEntry(device) ); - device.reset(); + volume = Pascal::VolumeEntry::Open(device); } catch (ProFUSE::POSIXException &e) { diff --git a/bin/fuse_pascal_ops.cpp b/bin/fuse_pascal_ops.cpp index a111191..fe966b0 100644 --- a/bin/fuse_pascal_ops.cpp +++ b/bin/fuse_pascal_ops.cpp @@ -56,18 +56,23 @@ using namespace Pascal; -static FileEntry *findChild(VolumeEntry *volume, unsigned inode) +// 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 fd_table; +static std::vector fd_table_available; + +static FileEntryPointer findChild(VolumeEntry *volume, unsigned inode) { for (unsigned i = 0, l = volume->fileCount(); i < l; ++i) { - FileEntry *child = volume->fileAtIndex(i); + FileEntryPointer child = volume->fileAtIndex(i); if (!child) continue; if (inode == child->inode()) return child; } - return NULL; + return FileEntryPointer(); } static void pascal_init(void *userdata, struct fuse_conn_info *conn) @@ -82,7 +87,7 @@ static void pascal_init(void *userdata, struct fuse_conn_info *conn) for (unsigned i = 0, l = volume->fileCount(); i < l; ++i) { - FileEntry *child = volume->fileAtIndex(i); + FileEntryPointer child = volume->fileAtIndex(i); child->fileSize(); } @@ -105,7 +110,7 @@ static void pascal_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) DEBUGNAME() VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); - FileEntry *file; + FileEntryPointer file; std::string attr; unsigned attrSize; @@ -149,7 +154,7 @@ static void pascal_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, si VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); - FileEntry *file; + FileEntryPointer file; std::string attr(name); ERROR(ino == 1, ENOATTR) @@ -269,7 +274,7 @@ static void pascal_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t of { unsigned tmp; - FileEntry *file = volume->fileAtIndex(i); + FileEntryPointer file = volume->fileAtIndex(i); if (file == NULL) break; //? // only these fields are used. @@ -352,7 +357,7 @@ static void pascal_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) for (unsigned i = 0, l = volume->fileCount(); i < l; ++i) { - FileEntry *file = volume->fileAtIndex(i); + FileEntryPointer file = volume->fileAtIndex(i); if (file == NULL) break; if (::strcasecmp(file->name(), name)) continue; @@ -363,7 +368,7 @@ static void pascal_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) entry.entry_timeout = 0.0; entry.ino = file->inode(); - stat(file, &entry.attr); + stat(file.get(), &entry.attr); fuse_reply_entry(req, &entry); return; } @@ -378,7 +383,7 @@ static void pascal_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info struct stat st; VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); - FileEntry *file; + FileEntryPointer file; if (ino == 1) { @@ -392,7 +397,7 @@ static void pascal_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info ERROR(file == NULL, ENOENT) //printf("\t%s\n", file->name()); - stat(file, &st); + stat(file.get(), &st); fuse_reply_attr(req, &st, 0.0); } @@ -402,10 +407,11 @@ static void pascal_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info 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); - FileEntry *file; + FileEntryPointer file; ERROR(ino == 1, EISDIR) @@ -415,7 +421,20 @@ static void pascal_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *f ERROR((fi->flags & O_ACCMODE) != O_RDONLY, EACCES) - fi->fh = (uint64_t)file; + // 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); } @@ -423,19 +442,25 @@ static void pascal_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *f 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); - FileEntry *file = (FileEntry *)fi->fh; + FileEntryPointer file = fd_table[index]; diff --git a/bin/newfs_pascal.cpp b/bin/newfs_pascal.cpp index fe8b93a..7b1bbb0 100644 --- a/bin/newfs_pascal.cpp +++ b/bin/newfs_pascal.cpp @@ -215,7 +215,7 @@ int main(int argc, char **argv) bool rawDevice; BlockDevicePointer device; - std::auto_ptr volume; + VolumeEntryPointer volume; // Check for block device. if so, verify. // if file exists, verify before overwrite. @@ -298,9 +298,7 @@ int main(int argc, char **argv) } - volume.reset( - new VolumeEntry(volumeName.c_str(), device) - ); + volume = VolumeEntry::Create(device, volumeName.c_str()); } From 9746117f711e89504d19d58777690d66f6b1f3c3 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 26 Feb 2011 03:52:54 +0000 Subject: [PATCH 207/236] use smart macros to make the future easier git-svn-id: https://profuse.googlecode.com/svn/branches/v2@351 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/BlockCache.cpp | 3 ++- Cache/ConcreteBlockCache.cpp | 4 +++- Cache/MappedBlockCache.cpp | 3 ++- Device/BlockDevice.h | 4 ++-- Device/DavexDiskImage.cpp | 8 ++++++-- Device/Device.h | 9 +++------ Device/DiskCopy42Image.cpp | 8 ++++++-- Device/DiskImage.cpp | 13 +++++++++---- Device/RawDevice.cpp | 3 ++- Device/UniversalDiskImage.cpp | 8 ++++++-- Pascal/Entry.h | 14 ++++++-------- Pascal/FileEntry.cpp | 6 ++++-- Pascal/FileEntry.h | 3 ++- Pascal/VolumeEntry.cpp | 10 +++++++--- Pascal/VolumeEntry.h | 2 +- ProFUSE/smart_pointers.h | 35 +++++++++++++++++++++++++++++++++++ 16 files changed, 96 insertions(+), 37 deletions(-) create mode 100644 ProFUSE/smart_pointers.h diff --git a/Cache/BlockCache.cpp b/Cache/BlockCache.cpp index 61462ed..3c24d2a 100644 --- a/Cache/BlockCache.cpp +++ b/Cache/BlockCache.cpp @@ -51,7 +51,8 @@ void BlockCache::read(unsigned block, void *bp) BlockCachePointer BlockCache::Create(BlockDevicePointer device) { - if (!device.get()) return BlockCachePointer(); + // this just calls the device virtual function to create a cache. + if (!device) return BlockCachePointer(); return device->createBlockCache(); } diff --git a/Cache/ConcreteBlockCache.cpp b/Cache/ConcreteBlockCache.cpp index 5bf7ede..6987ad4 100644 --- a/Cache/ConcreteBlockCache.cpp +++ b/Cache/ConcreteBlockCache.cpp @@ -60,7 +60,9 @@ using ProFUSE::POSIXException; BlockCachePointer ConcreteBlockCache::Create(BlockDevicePointer device, unsigned size) { - return BlockCachePointer(new ConcreteBlockCache(device, size)); + //return BlockCachePointer(new ConcreteBlockCache(device, size)); + + return MAKE_SHARED(ConcreteBlockCache, device, size); } ConcreteBlockCache::ConcreteBlockCache(BlockDevicePointer device, unsigned size) : diff --git a/Cache/MappedBlockCache.cpp b/Cache/MappedBlockCache.cpp index 4a65fb1..bf0892b 100644 --- a/Cache/MappedBlockCache.cpp +++ b/Cache/MappedBlockCache.cpp @@ -21,7 +21,8 @@ using ProFUSE::POSIXException; BlockCachePointer MappedBlockCache::Create(BlockDevicePointer device, void *data) { - return BlockCachePointer(new MappedBlockCache(device, data)); + //return BlockCachePointer(new MappedBlockCache(device, data)); + return MAKE_SHARED(MappedBlockCache, device, data); } diff --git a/Device/BlockDevice.h b/Device/BlockDevice.h index 8d4a021..c047912 100644 --- a/Device/BlockDevice.h +++ b/Device/BlockDevice.h @@ -8,13 +8,13 @@ #include #include - +#include #include namespace Device { - class BlockDevice : public std::tr1::enable_shared_from_this { + class BlockDevice : public ENABLE_SHARED_FROM_THIS(BlockDevice) { public: diff --git a/Device/DavexDiskImage.cpp b/Device/DavexDiskImage.cpp index 54e6ad9..51270bc 100644 --- a/Device/DavexDiskImage.cpp +++ b/Device/DavexDiskImage.cpp @@ -91,7 +91,9 @@ BlockDevicePointer DavexDiskImage::Open(MappedFile *file) #define __METHOD__ "DavexDiskImage::Open" Validate(file); - return BlockDevicePointer(new DavexDiskImage(file)); + //return BlockDevicePointer(new DavexDiskImage(file)); + + return MAKE_SHARED(DavexDiskImage, file); } BlockDevicePointer DavexDiskImage::Create(const char *name, size_t blocks) @@ -154,7 +156,9 @@ BlockDevicePointer DavexDiskImage::Create(const char *name, size_t blocks, const std::memcpy(file->address(), header.buffer(), 512); file->sync(); - return BlockDevicePointer(new DavexDiskImage(file)); + //return BlockDevicePointer(new DavexDiskImage(file)); + + return MAKE_SHARED(DavexDiskImage, file); } diff --git a/Device/Device.h b/Device/Device.h index 83c6f08..458320c 100644 --- a/Device/Device.h +++ b/Device/Device.h @@ -9,18 +9,15 @@ #ifndef __DEVICE_DEVICE_H__ #define __DEVICE_DEVICE_H__ -#include +#include namespace Device { class BlockDevice; class BlockCache; - - typedef std::tr1::shared_ptr BlockDevicePointer; - typedef std::tr1::shared_ptr BlockCachePointer; - - + typedef SHARED_PTR(BlockDevice) BlockDevicePointer; + typedef SHARED_PTR(BlockCache) BlockCachePointer; } diff --git a/Device/DiskCopy42Image.cpp b/Device/DiskCopy42Image.cpp index 040d0c1..d6c6d59 100644 --- a/Device/DiskCopy42Image.cpp +++ b/Device/DiskCopy42Image.cpp @@ -78,7 +78,9 @@ uint32_t DiskCopy42Image::Checksum(void *data, size_t size) BlockDevicePointer DiskCopy42Image::Open(MappedFile *f) { Validate(f); - return BlockDevicePointer(new DiskCopy42Image(f)); + //return BlockDevicePointer(new DiskCopy42Image(f)); + + return MAKE_SHARED(DiskCopy42Image, f); } static uint8_t DiskFormat(size_t blocks) @@ -163,7 +165,9 @@ BlockDevicePointer DiskCopy42Image::Create(const char *name, size_t blocks, cons std::memcpy(file->address(), header.buffer(), oUserData); file->sync(); - return BlockDevicePointer(new DiskCopy42Image(file)); + //return BlockDevicePointer(new DiskCopy42Image(file)); + + return MAKE_SHARED(DiskCopy42Image, file); } void DiskCopy42Image::Validate(MappedFile *file) diff --git a/Device/DiskImage.cpp b/Device/DiskImage.cpp index 0b83da5..6025e5d 100644 --- a/Device/DiskImage.cpp +++ b/Device/DiskImage.cpp @@ -115,13 +115,15 @@ ProDOSOrderDiskImage::ProDOSOrderDiskImage(MappedFile *file) : BlockDevicePointer ProDOSOrderDiskImage::Create(const char *name, size_t blocks) { MappedFile *file = MappedFile::Create(name, blocks * 512); - return BlockDevicePointer(new ProDOSOrderDiskImage(file)); + //return BlockDevicePointer(new ProDOSOrderDiskImage(file)); + return MAKE_SHARED(ProDOSOrderDiskImage, file); } BlockDevicePointer ProDOSOrderDiskImage::Open(MappedFile *file) { Validate(file); - return BlockDevicePointer(new ProDOSOrderDiskImage(file)); + //return BlockDevicePointer(new ProDOSOrderDiskImage(file)); + return MAKE_SHARED(ProDOSOrderDiskImage, file); } void ProDOSOrderDiskImage::Validate(MappedFile *f) @@ -168,13 +170,16 @@ DOSOrderDiskImage::DOSOrderDiskImage(MappedFile *file) : BlockDevicePointer DOSOrderDiskImage::Create(const char *name, size_t blocks) { MappedFile *file = MappedFile::Create(name, blocks * 512); - return BlockDevicePointer(new DOSOrderDiskImage(file)); + //return BlockDevicePointer(new DOSOrderDiskImage(file)); + return MAKE_SHARED(DOSOrderDiskImage, file); } BlockDevicePointer DOSOrderDiskImage::Open(MappedFile *file) { Validate(file); - return BlockDevicePointer(new DOSOrderDiskImage(file)); + //return BlockDevicePointer(new DOSOrderDiskImage(file)); + return MAKE_SHARED(DOSOrderDiskImage, file); + } void DOSOrderDiskImage::Validate(MappedFile *f) diff --git a/Device/RawDevice.cpp b/Device/RawDevice.cpp index 1df2117..96f10b3 100644 --- a/Device/RawDevice.cpp +++ b/Device/RawDevice.cpp @@ -198,7 +198,8 @@ RawDevice::~RawDevice() BlockDevicePointer RawDevice::Open(const char *name, File::FileFlags flags) { - return BlockDevicePointer(new RawDevice(name, flags)); + //return BlockDevicePointer(new RawDevice(name, flags)); + return MAKE_SHARED(RawDevice, name, flags); } diff --git a/Device/UniversalDiskImage.cpp b/Device/UniversalDiskImage.cpp index 82adafb..96ad4ef 100644 --- a/Device/UniversalDiskImage.cpp +++ b/Device/UniversalDiskImage.cpp @@ -81,13 +81,17 @@ BlockDevicePointer UniversalDiskImage::Create(const char *name, size_t blocks) std::memcpy(file->address(), header.buffer(), 64); - return BlockDevicePointer(new UniversalDiskImage(file)); + //return BlockDevicePointer(new UniversalDiskImage(file)); + + return MAKE_SHARED(UniversalDiskImage, file); } BlockDevicePointer UniversalDiskImage::Open(MappedFile *file) { Validate(file); - return BlockDevicePointer(new UniversalDiskImage(file)); + + //return BlockDevicePointer(new UniversalDiskImage(file)); + return MAKE_SHARED(UniversalDiskImage, file); } diff --git a/Pascal/Entry.h b/Pascal/Entry.h index c122951..7fe8605 100644 --- a/Pascal/Entry.h +++ b/Pascal/Entry.h @@ -1,9 +1,7 @@ #ifndef __PASCAL_ENTRY_H__ #define __PASCAL_ENTRY_H__ -#include - -#include +#include namespace Device { @@ -34,13 +32,13 @@ namespace Pascal { class VolumeEntry; - typedef std::tr1::shared_ptr FileEntryPointer; - typedef std::tr1::shared_ptr VolumeEntryPointer; + typedef SHARED_PTR(FileEntry) FileEntryPointer; + typedef SHARED_PTR(VolumeEntry) VolumeEntryPointer; - typedef std::tr1::weak_ptr FileEntryWeakPointer; - typedef std::tr1::weak_ptr VolumeEntryWeakPointer; + typedef WEAK_PTR(FileEntry) FileEntryWeakPointer; + typedef WEAK_PTR(VolumeEntry) VolumeEntryWeakPointer; - class Entry : public std::tr1::enable_shared_from_this { + class Entry : public ENABLE_SHARED_FROM_THIS(Entry) { public: diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index f4a1c18..35ba7ee 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -44,12 +44,14 @@ unsigned FileEntry::ValidName(const char *cp) FileEntryPointer FileEntry::Open(void *vp) { - return FileEntryPointer(new FileEntry(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 FileEntryPointer(new FileEntry(name, fileKind)); + return MAKE_SHARED(FileEntry, name, fileKind); } FileEntry::FileEntry(void *vp) : diff --git a/Pascal/FileEntry.h b/Pascal/FileEntry.h index 7bec9ac..80e3c61 100644 --- a/Pascal/FileEntry.h +++ b/Pascal/FileEntry.h @@ -2,6 +2,7 @@ #define __PASCAL_FILEENTRY_H__ #include +#include #include #include @@ -61,7 +62,7 @@ namespace Pascal { FileEntryPointer thisPointer() { - return std::tr1::static_pointer_cast(shared_from_this()); + return STATIC_POINTER_CAST(FileEntry, shared_from_this()); } diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index a4eff36..a209c22 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -64,15 +64,19 @@ unsigned VolumeEntry::ValidName(const char *cp) VolumeEntryPointer VolumeEntry::Open(Device::BlockDevicePointer device) { - VolumeEntryPointer ptr(new VolumeEntry(device)); - + VolumeEntryPointer ptr; + + //ptr = new VolumeEntry(device)); + ptr = MAKE_SHARED(VolumeEntry, device); return ptr; } VolumeEntryPointer VolumeEntry::Create(Device::BlockDevicePointer device, const char *name) { - VolumeEntryPointer ptr(new VolumeEntry(device, name)); + VolumeEntryPointer ptr; + //ptr = new VolumeEntry(device, name); + ptr = MAKE_SHARED(VolumeEntry, device, name); // set up the weak references from the file entry to this. if (ptr) ptr->setParents(); diff --git a/Pascal/VolumeEntry.h b/Pascal/VolumeEntry.h index 4b3f8a4..ccb6b7f 100644 --- a/Pascal/VolumeEntry.h +++ b/Pascal/VolumeEntry.h @@ -71,7 +71,7 @@ namespace Pascal { VolumeEntryPointer thisPointer() { - return std::tr1::static_pointer_cast(shared_from_this()); + return STATIC_POINTER_CAST(VolumeEntry, shared_from_this()); } void init(void *); diff --git a/ProFUSE/smart_pointers.h b/ProFUSE/smart_pointers.h new file mode 100644 index 0000000..6ab4ecd --- /dev/null +++ b/ProFUSE/smart_pointers.h @@ -0,0 +1,35 @@ + +#ifndef __PROFUSE_SMART_POINTERS_H__ +#define __PROFUSE_SMART_POINTERS_H__ + +#ifdef CPP0X +//C++0x +#include + + +#define SHARED_PTR(T) std::shared_ptr +#define WEAK_PTR(T) std::weak_ptr + +#define MAKE_SHARED(T, ...) std::make_shared(__VA_ARGS__) +#define ENABLE_SHARED_FROM_THIS(T) std::enable_shared_from_this + +#define STATIC_POINTER_CAST(T, ARG) std::static_pointer_cast(ARG) +#define DYNAMIC_POINTER_CAST(T, ARG) std::dynamic_pointer_cast(ARG) + +#else + +// tr1 +#include + +#define SHARED_PTR(T) std::tr1::shared_ptr +#define WEAK_PTR(T) std::tr1::weak_ptr + +#define MAKE_SHARED(T, ...) std::tr1::shared_ptr(new T(__VA_ARGS__)) +#define ENABLE_SHARED_FROM_THIS(T) std::tr1::enable_shared_from_this + +#define STATIC_POINTER_CAST(T, ARG) std::tr1::static_pointer_cast(ARG) +#define DYNAMIC_POINTER_CAST(T, ARG) std::tr1::dynamic_pointer_cast(ARG) + +#endif + +#endif From e68854ff581d006f656333ad1d9315521f204415 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 26 Feb 2011 03:53:22 +0000 Subject: [PATCH 208/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@352 aa027e90-d47c-11dd-86d7-074df07e0730 --- bin/fuse_pascal.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/bin/fuse_pascal.cpp b/bin/fuse_pascal.cpp index e19edf8..e207ec6 100644 --- a/bin/fuse_pascal.cpp +++ b/bin/fuse_pascal.cpp @@ -195,10 +195,7 @@ int main(int argc, char **argv) try - { - - //std::tr1::shared_ptr device; - + { Device::BlockDevicePointer device; device = Device::BlockDevice::Open(fDiskImage.c_str(), File::ReadOnly, format); From efd5e7bd98ac7e34505a6953f877bdc0c34ca6ea Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 27 Feb 2011 01:32:35 +0000 Subject: [PATCH 209/236] fix parent pointer bug git-svn-id: https://profuse.googlecode.com/svn/branches/v2@353 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/ConcreteBlockCache.cpp | 1 + Makefile | 14 +- PROFuseX.xcodeproj/kelvin.pbxuser | 308 ++++++++++++++---------- PROFuseX.xcodeproj/kelvin.perspectivev3 | 43 ++-- PROFuseX.xcodeproj/project.pbxproj | 2 + Pascal/VolumeEntry.cpp | 7 +- 6 files changed, 230 insertions(+), 145 deletions(-) diff --git a/Cache/ConcreteBlockCache.cpp b/Cache/ConcreteBlockCache.cpp index 6987ad4..ef8c6b1 100644 --- a/Cache/ConcreteBlockCache.cpp +++ b/Cache/ConcreteBlockCache.cpp @@ -61,6 +61,7 @@ using ProFUSE::POSIXException; BlockCachePointer ConcreteBlockCache::Create(BlockDevicePointer device, unsigned size) { //return BlockCachePointer(new ConcreteBlockCache(device, size)); + // constructor must be accessible to std::make_shared... return MAKE_SHARED(ConcreteBlockCache, device, size); } diff --git a/Makefile b/Makefile index 750cced..1d73693 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,17 @@ CC = g++ CPPFLAGS += -Wall -W -Wno-multichar -I. -O2 -g LDFLAGS += -lpthread -fuse_pascal_LDFLAGS += -lfuse +UNAME = $(shell uname) + +ifeq ($(UNAME),Darwin) + fuse_pascal_LDFLAGS += -lfuse_ino64 +else + fuse_pascal_LDFLAGS += -lfuse +endif + + + + OBJECTS += ${wildcard *.o} OBJECTS += ${wildcard bin/*.o} @@ -78,7 +88,7 @@ fuse_pascal: bin/fuse_pascal.o bin/fuse_pascal_ops.o \ ${FILE_OBJECTS} \ ${PROFUSE_OBJECTS} \ ${PASCAL_OBJECTS} - $(CC) -lfuse $(LDFLAGS) $^ -o $@ + $(CC) $(fuse_pascal_LDFLAGS) $(LDFLAGS) $^ -o $@ clean: diff --git a/PROFuseX.xcodeproj/kelvin.pbxuser b/PROFuseX.xcodeproj/kelvin.pbxuser index 0471ce8..f8b703a 100644 --- a/PROFuseX.xcodeproj/kelvin.pbxuser +++ b/PROFuseX.xcodeproj/kelvin.pbxuser @@ -2,10 +2,9 @@ { 08FB7793FE84155DC02AAC07 /* Project object */ = { activeBuildConfigurationName = Debug; - activeExecutable = B6F3682611B431AC0045E114 /* newfs_prodos */; - activeTarget = B6F3682411B431AC0045E114 /* newfs_prodos */; + activeExecutable = B656AE0411A84F5800AB578A /* fuse_pascal */; + activeTarget = B656AE0211A84F5800AB578A /* fuse_pascal */; addToTargets = ( - B6F3682411B431AC0045E114 /* newfs_prodos */, ); breakpoints = ( B6F3642F11AA1E150045E114 /* NibbleTest.cpp:76 */, @@ -104,71 +103,77 @@ PBXFileDataSource_Warnings_ColumnID, ); }; - PBXPerProjectTemplateStateSaveDate = 319589426; - PBXWorkspaceStateSaveDate = 319589426; + PBXPerProjectTemplateStateSaveDate = 320461343; + PBXWorkspaceStateSaveDate = 320461343; }; perUserProjectItems = { - B6272A9811D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9811D5AC5E0073C73A /* PBXTextBookmark */; - B6272A9911D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9911D5AC5E0073C73A /* PBXTextBookmark */; - B6272A9A11D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9A11D5AC5E0073C73A /* PBXTextBookmark */; - B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */; - B6272A9C11D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9C11D5AC5E0073C73A /* PBXTextBookmark */; - B6272B0D11D691320073C73A /* PBXTextBookmark */ = B6272B0D11D691320073C73A /* PBXTextBookmark */; - B6272B0E11D691320073C73A /* PBXTextBookmark */ = B6272B0E11D691320073C73A /* PBXTextBookmark */; - B6272B0F11D691320073C73A /* PBXTextBookmark */ = B6272B0F11D691320073C73A /* PBXTextBookmark */; - B6272B1011D691320073C73A /* PBXTextBookmark */ = B6272B1011D691320073C73A /* PBXTextBookmark */; - B6272B1111D691320073C73A /* PBXTextBookmark */ = B6272B1111D691320073C73A /* PBXTextBookmark */; - B6272B1311D691320073C73A /* PBXTextBookmark */ = B6272B1311D691320073C73A /* PBXTextBookmark */; - B6272B1411D691320073C73A /* PBXTextBookmark */ = B6272B1411D691320073C73A /* PBXTextBookmark */; - B6272B1611D691320073C73A /* PBXTextBookmark */ = B6272B1611D691320073C73A /* PBXTextBookmark */; - B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */ = B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */; - B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */ = B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */; - B63EFDA011A4488200C90DCE /* PBXTextBookmark */ = B63EFDA011A4488200C90DCE /* PBXTextBookmark */; - B63EFDA511A4488200C90DCE /* PBXTextBookmark */ = B63EFDA511A4488200C90DCE /* PBXTextBookmark */; - B63EFDA711A4488200C90DCE /* PBXTextBookmark */ = B63EFDA711A4488200C90DCE /* PBXTextBookmark */; - B63EFDA911A4488200C90DCE /* PBXTextBookmark */ = B63EFDA911A4488200C90DCE /* PBXTextBookmark */; - B63EFDAB11A4488200C90DCE /* PBXTextBookmark */ = B63EFDAB11A4488200C90DCE /* PBXTextBookmark */; - B63EFDAD11A4488200C90DCE /* PBXTextBookmark */ = B63EFDAD11A4488200C90DCE /* PBXTextBookmark */; - B63EFDAF11A4488200C90DCE /* PBXTextBookmark */ = B63EFDAF11A4488200C90DCE /* PBXTextBookmark */; - B63EFDB111A4488200C90DCE /* PBXTextBookmark */ = B63EFDB111A4488200C90DCE /* PBXTextBookmark */; - B63EFDB311A4488200C90DCE /* PBXTextBookmark */ = B63EFDB311A4488200C90DCE /* PBXTextBookmark */; - B63EFDF211A4504200C90DCE /* PBXTextBookmark */ = B63EFDF211A4504200C90DCE /* PBXTextBookmark */; - B63EFEA011A488C200C90DCE /* PBXTextBookmark */ = B63EFEA011A488C200C90DCE /* PBXTextBookmark */; - B63EFEA111A488C200C90DCE /* PBXTextBookmark */ = B63EFEA111A488C200C90DCE /* PBXTextBookmark */; - B63EFEA811A488C200C90DCE /* PBXTextBookmark */ = B63EFEA811A488C200C90DCE /* PBXTextBookmark */; - B64E9723130C8C860072B07E /* PBXTextBookmark */ = B64E9723130C8C860072B07E /* PBXTextBookmark */; - B64E972813103CAF0072B07E /* PBXTextBookmark */ = B64E972813103CAF0072B07E /* PBXTextBookmark */; - B656AE2611A84FA400AB578A /* PBXTextBookmark */ = B656AE2611A84FA400AB578A /* PBXTextBookmark */; - B65CFB6911B495790024A2D9 /* PBXTextBookmark */ = B65CFB6911B495790024A2D9 /* PBXTextBookmark */; - B6E5F0DD11A60726000AD141 /* PBXTextBookmark */ = B6E5F0DD11A60726000AD141 /* PBXTextBookmark */; - B6E5F0F211A73144000AD141 /* PBXTextBookmark */ = B6E5F0F211A73144000AD141 /* PBXTextBookmark */; - B6E5F11211A73340000AD141 /* PBXTextBookmark */ = B6E5F11211A73340000AD141 /* PBXTextBookmark */; - B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */ = B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */; - B6E5F18211A76B74000AD141 /* PBXTextBookmark */ = B6E5F18211A76B74000AD141 /* PBXTextBookmark */; - B6F3647111AB35FE0045E114 /* PBXTextBookmark */ = B6F3647111AB35FE0045E114 /* PBXTextBookmark */; - B6F3649E11AB59190045E114 /* PBXTextBookmark */ = B6F3649E11AB59190045E114 /* PBXTextBookmark */; - B6F364B711AB84840045E114 /* PBXTextBookmark */ = B6F364B711AB84840045E114 /* PBXTextBookmark */; - B6F3652E11ADD5D20045E114 /* PBXTextBookmark */ = B6F3652E11ADD5D20045E114 /* PBXTextBookmark */; - B6F3653011ADD5D20045E114 /* PBXTextBookmark */ = B6F3653011ADD5D20045E114 /* PBXTextBookmark */; - B6F3657E11AE255B0045E114 /* PBXTextBookmark */ = B6F3657E11AE255B0045E114 /* PBXTextBookmark */; - B6F3665411B190370045E114 /* PBXTextBookmark */ = B6F3665411B190370045E114 /* PBXTextBookmark */; - B6F3665C11B194AC0045E114 /* PBXTextBookmark */ = B6F3665C11B194AC0045E114 /* PBXTextBookmark */; - B6F366C411B1A28C0045E114 /* PBXTextBookmark */ = B6F366C411B1A28C0045E114 /* PBXTextBookmark */; - B6F366C611B1A28C0045E114 /* PBXTextBookmark */ = B6F366C611B1A28C0045E114 /* PBXTextBookmark */; - B6F366C711B1A28C0045E114 /* PBXTextBookmark */ = B6F366C711B1A28C0045E114 /* PBXTextBookmark */; - B6F366C811B1A28C0045E114 /* PBXTextBookmark */ = B6F366C811B1A28C0045E114 /* PBXTextBookmark */; - B6F366C911B1A28C0045E114 /* PBXTextBookmark */ = B6F366C911B1A28C0045E114 /* PBXTextBookmark */; - B6F366CA11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CA11B1A28C0045E114 /* PBXTextBookmark */; - B6F366CB11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CB11B1A28C0045E114 /* PBXTextBookmark */; - B6F3675411B316D10045E114 /* PBXTextBookmark */ = B6F3675411B316D10045E114 /* PBXTextBookmark */; - B6F3677C11B326580045E114 /* PBXTextBookmark */ = B6F3677C11B326580045E114 /* PBXTextBookmark */; - B6F3677D11B326580045E114 /* PBXTextBookmark */ = B6F3677D11B326580045E114 /* PBXTextBookmark */; - B6F3677E11B326580045E114 /* PBXTextBookmark */ = B6F3677E11B326580045E114 /* PBXTextBookmark */; - B6F3677F11B326580045E114 /* PBXTextBookmark */ = B6F3677F11B326580045E114 /* PBXTextBookmark */; - B6F367A011B330D10045E114 /* PBXTextBookmark */ = B6F367A011B330D10045E114 /* PBXTextBookmark */; - B6F367AE11B337A70045E114 /* PBXTextBookmark */ = B6F367AE11B337A70045E114 /* PBXTextBookmark */; - B6F3684911B44D090045E114 /* PBXTextBookmark */ = B6F3684911B44D090045E114 /* PBXTextBookmark */; - B6F3684A11B44D090045E114 /* PBXTextBookmark */ = B6F3684A11B44D090045E114 /* PBXTextBookmark */; + B6272A9811D5AC5E0073C73A = B6272A9811D5AC5E0073C73A /* PBXTextBookmark */; + B6272A9911D5AC5E0073C73A = B6272A9911D5AC5E0073C73A /* PBXTextBookmark */; + B6272A9B11D5AC5E0073C73A = B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */; + B6272A9C11D5AC5E0073C73A = B6272A9C11D5AC5E0073C73A /* PBXTextBookmark */; + B6272B0D11D691320073C73A = B6272B0D11D691320073C73A /* PBXTextBookmark */; + B6272B0E11D691320073C73A = B6272B0E11D691320073C73A /* PBXTextBookmark */; + B6272B0F11D691320073C73A = B6272B0F11D691320073C73A /* PBXTextBookmark */; + B6272B1011D691320073C73A = B6272B1011D691320073C73A /* PBXTextBookmark */; + B6272B1111D691320073C73A = B6272B1111D691320073C73A /* PBXTextBookmark */; + B6272B1311D691320073C73A = B6272B1311D691320073C73A /* PBXTextBookmark */; + B6272B1411D691320073C73A = B6272B1411D691320073C73A /* PBXTextBookmark */; + B6272B1611D691320073C73A = B6272B1611D691320073C73A /* PBXTextBookmark */; + B63EFC2611A2D5A400C90DCE = B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */; + B63EFC3211A2D5A400C90DCE = B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */; + B63EFDA011A4488200C90DCE = B63EFDA011A4488200C90DCE /* PBXTextBookmark */; + B63EFDA511A4488200C90DCE = B63EFDA511A4488200C90DCE /* PBXTextBookmark */; + B63EFDA711A4488200C90DCE = B63EFDA711A4488200C90DCE /* PBXTextBookmark */; + B63EFDA911A4488200C90DCE = B63EFDA911A4488200C90DCE /* PBXTextBookmark */; + B63EFDAB11A4488200C90DCE = B63EFDAB11A4488200C90DCE /* PBXTextBookmark */; + B63EFDAD11A4488200C90DCE = B63EFDAD11A4488200C90DCE /* PBXTextBookmark */; + B63EFDAF11A4488200C90DCE = B63EFDAF11A4488200C90DCE /* PBXTextBookmark */; + B63EFDB111A4488200C90DCE = B63EFDB111A4488200C90DCE /* PBXTextBookmark */; + B63EFDB311A4488200C90DCE = B63EFDB311A4488200C90DCE /* PBXTextBookmark */; + B63EFDF211A4504200C90DCE = B63EFDF211A4504200C90DCE /* PBXTextBookmark */; + B63EFEA011A488C200C90DCE = B63EFEA011A488C200C90DCE /* PBXTextBookmark */; + B63EFEA111A488C200C90DCE = B63EFEA111A488C200C90DCE /* PBXTextBookmark */; + B63EFEA811A488C200C90DCE = B63EFEA811A488C200C90DCE /* PBXTextBookmark */; + B656AE2611A84FA400AB578A = B656AE2611A84FA400AB578A /* PBXTextBookmark */; + B65CFB6911B495790024A2D9 = B65CFB6911B495790024A2D9 /* PBXTextBookmark */; + B6A53B811319DA2D00C9070F /* PBXTextBookmark */ = B6A53B811319DA2D00C9070F /* PBXTextBookmark */; + B6A53B881319DACB00C9070F /* PBXTextBookmark */ = B6A53B881319DACB00C9070F /* PBXTextBookmark */; + B6A53B891319DACB00C9070F /* PBXBookmark */ = B6A53B891319DACB00C9070F /* PBXBookmark */; + B6A53B8A1319DACB00C9070F /* PBXTextBookmark */ = B6A53B8A1319DACB00C9070F /* PBXTextBookmark */; + B6A53B8E1319DDFC00C9070F /* PBXTextBookmark */ = B6A53B8E1319DDFC00C9070F /* PBXTextBookmark */; + B6A53B8F1319DDFC00C9070F /* PBXTextBookmark */ = B6A53B8F1319DDFC00C9070F /* PBXTextBookmark */; + B6AA3AB21318D063007D4BA1 = B6AA3AB21318D063007D4BA1 /* PBXTextBookmark */; + B6AA3AB31318D063007D4BA1 = B6AA3AB31318D063007D4BA1 /* PBXTextBookmark */; + B6AA3AB41318D063007D4BA1 = B6AA3AB41318D063007D4BA1 /* PBXTextBookmark */; + B6AA3AB51318D063007D4BA1 = B6AA3AB51318D063007D4BA1 /* PBXTextBookmark */; + B6E5F0DD11A60726000AD141 = B6E5F0DD11A60726000AD141 /* PBXTextBookmark */; + B6E5F0F211A73144000AD141 = B6E5F0F211A73144000AD141 /* PBXTextBookmark */; + B6E5F11211A73340000AD141 = B6E5F11211A73340000AD141 /* PBXTextBookmark */; + B6E5F13A11A74F2B000AD141 = B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */; + B6E5F18211A76B74000AD141 = B6E5F18211A76B74000AD141 /* PBXTextBookmark */; + B6F3647111AB35FE0045E114 = B6F3647111AB35FE0045E114 /* PBXTextBookmark */; + B6F3649E11AB59190045E114 = B6F3649E11AB59190045E114 /* PBXTextBookmark */; + B6F364B711AB84840045E114 = B6F364B711AB84840045E114 /* PBXTextBookmark */; + B6F3652E11ADD5D20045E114 = B6F3652E11ADD5D20045E114 /* PBXTextBookmark */; + B6F3653011ADD5D20045E114 = B6F3653011ADD5D20045E114 /* PBXTextBookmark */; + B6F3657E11AE255B0045E114 = B6F3657E11AE255B0045E114 /* PBXTextBookmark */; + B6F3665411B190370045E114 = B6F3665411B190370045E114 /* PBXTextBookmark */; + B6F3665C11B194AC0045E114 = B6F3665C11B194AC0045E114 /* PBXTextBookmark */; + B6F366C411B1A28C0045E114 = B6F366C411B1A28C0045E114 /* PBXTextBookmark */; + B6F366C611B1A28C0045E114 = B6F366C611B1A28C0045E114 /* PBXTextBookmark */; + B6F366C711B1A28C0045E114 = B6F366C711B1A28C0045E114 /* PBXTextBookmark */; + B6F366C811B1A28C0045E114 = B6F366C811B1A28C0045E114 /* PBXTextBookmark */; + B6F366C911B1A28C0045E114 = B6F366C911B1A28C0045E114 /* PBXTextBookmark */; + B6F366CA11B1A28C0045E114 = B6F366CA11B1A28C0045E114 /* PBXTextBookmark */; + B6F366CB11B1A28C0045E114 = B6F366CB11B1A28C0045E114 /* PBXTextBookmark */; + B6F3675411B316D10045E114 = B6F3675411B316D10045E114 /* PBXTextBookmark */; + B6F3677C11B326580045E114 = B6F3677C11B326580045E114 /* PBXTextBookmark */; + B6F3677D11B326580045E114 = B6F3677D11B326580045E114 /* PBXTextBookmark */; + B6F3677E11B326580045E114 = B6F3677E11B326580045E114 /* PBXTextBookmark */; + B6F3677F11B326580045E114 = B6F3677F11B326580045E114 /* PBXTextBookmark */; + B6F367A011B330D10045E114 = B6F367A011B330D10045E114 /* PBXTextBookmark */; + B6F367AE11B337A70045E114 = B6F367AE11B337A70045E114 /* PBXTextBookmark */; + B6F3684A11B44D090045E114 = B6F3684A11B44D090045E114 /* PBXTextBookmark */; }; sourceControlManager = B63EFA6711A093C200C90DCE /* Source Control */; userBuildSettings = { @@ -183,9 +188,9 @@ }; B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 4095}}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 4069}}"; sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 724}"; + sepNavVisRange = "{0, 672}"; }; }; B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */ = { @@ -214,7 +219,7 @@ fRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; name = "VolumeEntry.cpp: 618"; rLen = 6; - rLoc = 13761; + rLoc = 13762; rType = 0; vrLen = 1289; vrLoc = 13115; @@ -229,16 +234,6 @@ vrLen = 562; vrLoc = 0; }; - B6272A9A11D5AC5E0073C73A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */; - name = "fuse_pascal.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 724; - vrLoc = 0; - }; B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */; @@ -390,7 +385,7 @@ uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 1339}}"; sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 868}"; + sepNavVisRange = "{0, 819}"; }; }; B63EFA7611A0948500C90DCE /* Endian.h */ = { @@ -507,9 +502,9 @@ }; B63EFAB711A098C400C90DCE /* BlockCache.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 741}}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 767}}"; sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{129, 890}"; + sepNavVisRange = "{118, 910}"; }; }; B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */ = { @@ -640,16 +635,16 @@ }; B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1009, 8775}}"; - sepNavSelRange = "{5793, 0}"; - sepNavVisRange = "{4945, 1395}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 9555}}"; + sepNavSelRange = "{10781, 0}"; + sepNavVisRange = "{10345, 801}"; }; }; B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 13208}}"; - sepNavSelRange = "{13761, 6}"; - sepNavVisRange = "{13115, 1289}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 12961}}"; + sepNavSelRange = "{13762, 6}"; + sepNavVisRange = "{13219, 1185}"; }; }; B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */ = { @@ -700,9 +695,9 @@ YES, ); argumentStrings = ( - /Users/kelvin/Projects/PROFuseX/pascaltest.DSK, - rm, - LINEFEED.CODE, + /Users/kelvin/Projects/PROFuseX/bleh.po, + cat, + XATTR.CPP, ); autoAttachOnCrash = 1; breakpointsEnabled = 1; @@ -958,26 +953,6 @@ vrLen = 834; vrLoc = 0; }; - B64E9723130C8C860072B07E /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAB711A098C400C90DCE /* BlockCache.h */; - name = "BlockCache.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 890; - vrLoc = 129; - }; - B64E972813103CAF0072B07E /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAB711A098C400C90DCE /* BlockCache.h */; - name = "BlockCache.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 890; - vrLoc = 129; - }; B656AE0211A84F5800AB578A /* fuse_pascal */ = { activeExec = 0; executables = ( @@ -1084,6 +1059,107 @@ vrLen = 800; vrLoc = 2262; }; + B6A53B811319DA2D00C9070F /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; + name = "FileEntry.cpp: 544"; + rLen = 0; + rLoc = 10781; + rType = 0; + vrLen = 801; + vrLoc = 10345; + }; + B6A53B851319DA3D00C9070F /* smart_pointers.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 475}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 903}"; + }; + }; + B6A53B881319DACB00C9070F /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; + name = "FileEntry.cpp: 544"; + rLen = 0; + rLoc = 10781; + rType = 0; + vrLen = 801; + vrLoc = 10345; + }; + B6A53B891319DACB00C9070F /* PBXBookmark */ = { + isa = PBXBookmark; + fRef = B6A53B851319DA3D00C9070F /* smart_pointers.h */; + }; + B6A53B8A1319DACB00C9070F /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6A53B851319DA3D00C9070F /* smart_pointers.h */; + name = "smart_pointers.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 903; + vrLoc = 0; + }; + B6A53B8E1319DDFC00C9070F /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6A53B851319DA3D00C9070F /* smart_pointers.h */; + name = "smart_pointers.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 903; + vrLoc = 0; + }; + B6A53B8F1319DDFC00C9070F /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 618"; + rLen = 6; + rLoc = 13762; + rType = 0; + vrLen = 1185; + vrLoc = 13219; + }; + B6AA3AB21318D063007D4BA1 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAB711A098C400C90DCE /* BlockCache.h */; + name = "BlockCache.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 910; + vrLoc = 118; + }; + B6AA3AB31318D063007D4BA1 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; + name = "Endian.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 819; + vrLoc = 0; + }; + B6AA3AB41318D063007D4BA1 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */; + name = "fuse_pascal.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 672; + vrLoc = 0; + }; + B6AA3AB51318D063007D4BA1 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; + name = "FileEntry.cpp: 544"; + rLen = 0; + rLoc = 10781; + rType = 0; + vrLen = 822; + vrLoc = 10324; + }; B6E5F0DD11A60726000AD141 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; @@ -1520,16 +1596,6 @@ sourceDirectories = ( ); }; - B6F3684911B44D090045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; - name = "Endian.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 868; - vrLoc = 0; - }; B6F3684A11B44D090045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B6F3676411B323680045E114 /* TextWriter.cpp */; diff --git a/PROFuseX.xcodeproj/kelvin.perspectivev3 b/PROFuseX.xcodeproj/kelvin.perspectivev3 index c78c1ec..368f26e 100644 --- a/PROFuseX.xcodeproj/kelvin.perspectivev3 +++ b/PROFuseX.xcodeproj/kelvin.perspectivev3 @@ -231,6 +231,8 @@ Layout + BecomeActive + ContentConfiguration PBXBottomSmartGroupGIDs @@ -269,6 +271,8 @@ 08FB7794FE84155DC02AAC07 B6272A8D11D5AC3C0073C73A B6272AA411D5AE0C0073C73A + B63EFBE711A244EE00C90DCE + B63EFACF11A09DB500C90DCE B63EFAB511A098C400C90DCE B63EFA9411A094E000C90DCE B656ADED11A84D3200AB578A @@ -278,13 +282,13 @@ PBXSmartGroupTreeModuleOutlineStateSelectionKey - 39 - 24 + 61 + 60 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey - {{0, 164}, {318, 941}} + {{0, 470}, {318, 941}} PBXTopSmartGroupGIDs @@ -317,7 +321,7 @@ PBXProjectModuleGUID B63EFA6111A093C200C90DCE PBXProjectModuleLabel - BlockCache.h + VolumeEntry.cpp PBXSplitModuleInNavigatorKey Split0 @@ -325,11 +329,11 @@ PBXProjectModuleGUID B63EFA6211A093C200C90DCE PBXProjectModuleLabel - BlockCache.h + VolumeEntry.cpp _historyCapacity 0 bookmark - B64E972813103CAF0072B07E + B6A53B8F1319DDFC00C9070F history B63EFC2611A2D5A400C90DCE @@ -368,19 +372,15 @@ B6F366C911B1A28C0045E114 B6F366CA11B1A28C0045E114 B6F366CB11B1A28C0045E114 - B6F3675411B316D10045E114 B6F3677C11B326580045E114 B6F3677D11B326580045E114 B6F3677E11B326580045E114 B6F3677F11B326580045E114 B6F367A011B330D10045E114 B6F367AE11B337A70045E114 - B6F3684911B44D090045E114 B6F3684A11B44D090045E114 B65CFB6911B495790024A2D9 - B6272A9811D5AC5E0073C73A B6272A9911D5AC5E0073C73A - B6272A9A11D5AC5E0073C73A B6272A9B11D5AC5E0073C73A B6272A9C11D5AC5E0073C73A B6272B0D11D691320073C73A @@ -391,7 +391,12 @@ B6272B1311D691320073C73A B6272B1411D691320073C73A B6272B1611D691320073C73A - B64E9723130C8C860072B07E + B6AA3AB21318D063007D4BA1 + B6AA3AB31318D063007D4BA1 + B6AA3AB41318D063007D4BA1 + B6A53B881319DACB00C9070F + B6A53B8E1319DDFC00C9070F + B6272A9811D5AC5E0073C73A SplitCount @@ -405,18 +410,18 @@ GeometryConfiguration Frame - {{0, 0}, {899, 526}} + {{0, 0}, {899, 507}} RubberWindowFrame 182 101 1239 1000 0 0 1920 1178 Module PBXNavigatorGroup Proportion - 526pt + 507pt Proportion - 428pt + 447pt Tabs @@ -430,7 +435,7 @@ GeometryConfiguration Frame - {{10, 27}, {899, 401}} + {{10, 27}, {899, 420}} RubberWindowFrame 182 101 1239 1000 0 0 1920 1178 @@ -486,7 +491,7 @@ GeometryConfiguration Frame - {{10, 27}, {899, 401}} + {{10, 27}, {899, 410}} Module PBXBuildResultsModule @@ -514,11 +519,11 @@ TableOfContents - B64E9725130C8C860072B07E + B6A53B821319DA2D00C9070F 1CA23ED40692098700951B8B - B64E9726130C8C860072B07E + B6A53B831319DA2D00C9070F B63EFA6111A093C200C90DCE - B64E9727130C8C860072B07E + B6A53B841319DA2D00C9070F 1CA23EDF0692099D00951B8B 1CA23EE00692099D00951B8B 1CA23EE10692099D00951B8B diff --git a/PROFuseX.xcodeproj/project.pbxproj b/PROFuseX.xcodeproj/project.pbxproj index 944545d..b1d7df5 100644 --- a/PROFuseX.xcodeproj/project.pbxproj +++ b/PROFuseX.xcodeproj/project.pbxproj @@ -170,6 +170,7 @@ B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NibbleTest.cpp; sourceTree = ""; }; B656AF0311AA105500AB578A /* NibbleTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NibbleTest; sourceTree = BUILT_PRODUCTS_DIR; }; B659C142131368BA0058DC9C /* Device.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Device.h; sourceTree = ""; }; + B6A53B851319DA3D00C9070F /* smart_pointers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = smart_pointers.h; sourceTree = ""; }; B6F3648011AB36260045E114 /* xattr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xattr; sourceTree = BUILT_PRODUCTS_DIR; }; B6F3651A11ADD0280045E114 /* VolumeEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VolumeEntry.h; sourceTree = ""; }; B6F3651B11ADD0280045E114 /* FileEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileEntry.h; sourceTree = ""; }; @@ -343,6 +344,7 @@ B63EFACF11A09DB500C90DCE /* ProFUSE */ = { isa = PBXGroup; children = ( + B6A53B851319DA3D00C9070F /* smart_pointers.h */, B63EFAD011A09DB500C90DCE /* auto.h */, B63EFAD111A09DB500C90DCE /* Exception.cpp */, B63EFAD211A09DB500C90DCE /* Exception.h */, diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index a209c22..60ee49e 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -68,6 +68,10 @@ VolumeEntryPointer VolumeEntry::Open(Device::BlockDevicePointer device) //ptr = new VolumeEntry(device)); ptr = MAKE_SHARED(VolumeEntry, device); + + // set up the weak references from the file entry to this. + if (ptr) ptr->setParents(); + return ptr; } @@ -78,9 +82,6 @@ VolumeEntryPointer VolumeEntry::Create(Device::BlockDevicePointer device, const //ptr = new VolumeEntry(device, name); ptr = MAKE_SHARED(VolumeEntry, device, name); - // set up the weak references from the file entry to this. - if (ptr) ptr->setParents(); - return ptr; } From 5930e28f54cfff012e07dff45528796d3cf4597b Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 27 Feb 2011 02:23:03 +0000 Subject: [PATCH 210/236] statvfs support git-svn-id: https://profuse.googlecode.com/svn/branches/v2@354 aa027e90-d47c-11dd-86d7-074df07e0730 --- bin/fuse_pascal_ops.cpp | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/bin/fuse_pascal_ops.cpp b/bin/fuse_pascal_ops.cpp index fe966b0..31c8509 100644 --- a/bin/fuse_pascal_ops.cpp +++ b/bin/fuse_pascal_ops.cpp @@ -13,8 +13,11 @@ #include #include -#include #include +#include +#include + + #include @@ -75,6 +78,11 @@ static FileEntryPointer findChild(VolumeEntry *volume, unsigned inode) return FileEntryPointer(); } + +#pragma mark - +#pragma mark fs + + static void pascal_init(void *userdata, struct fuse_conn_info *conn) { DEBUGNAME() @@ -101,6 +109,34 @@ static void pascal_destroy(void *userdata) } +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 @@ -485,7 +521,6 @@ static void pascal_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, } - void init_ops(fuse_lowlevel_ops *ops) { DEBUGNAME() @@ -494,6 +529,7 @@ void init_ops(fuse_lowlevel_ops *ops) ops->init = pascal_init; ops->destroy = pascal_destroy; + ops->statfs = pascal_statfs; // returns pascal.filekind, text encoding. ops->listxattr = pascal_listxattr; From 3a671f985c368b8097264ccaeb8d1c958170fbb1 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 28 Feb 2011 04:44:56 +0000 Subject: [PATCH 211/236] fix dc42 errors git-svn-id: https://profuse.googlecode.com/svn/branches/v2@367 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/DiskCopy42Image.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Device/DiskCopy42Image.cpp b/Device/DiskCopy42Image.cpp index d6c6d59..7c0956c 100644 --- a/Device/DiskCopy42Image.cpp +++ b/Device/DiskCopy42Image.cpp @@ -32,8 +32,8 @@ DiskCopy42Image::DiskCopy42Image(MappedFile *f) : DiskImage(f), _changed(false) { - setAdaptor(new POAdaptor(oUserData + (uint8_t *)f->address())); - setBlocks(Read32(f->address(), oDataSize) / 512); + setAdaptor(new POAdaptor(oUserData + (uint8_t *)address())); + setBlocks(Read32(address(), oDataSize) / 512); } @@ -187,7 +187,7 @@ void DiskCopy42Image::Validate(MappedFile *file) // name must be < 64 if (Read8(data, 0) > 63) break; - if (Read32(data, oPrivate) != 0x100) + if (Read16(data, oPrivate) != 0x100) break; // bytes, not blocks. From 5f893f78fc8c9cef4228ad0b9ed7438a97c5a29b Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 9 Mar 2011 04:59:18 +0000 Subject: [PATCH 212/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@380 aa027e90-d47c-11dd-86d7-074df07e0730 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1d73693..d9e0f16 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CC = g++ CPPFLAGS += -Wall -W -Wno-multichar -I. -O2 -g LDFLAGS += -lpthread -UNAME = $(shell uname) +UNAME = $(shell uname -s) ifeq ($(UNAME),Darwin) fuse_pascal_LDFLAGS += -lfuse_ino64 From 32bb5d79b98993e7d2332ad2b59131677bd51a69 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 9 Mar 2011 05:02:04 +0000 Subject: [PATCH 213/236] added SDK support, better validation/sniffing git-svn-id: https://profuse.googlecode.com/svn/branches/v2@381 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/BlockDevice.cpp | 56 ++++++-- Device/BlockDevice.h | 6 +- Device/DavexDiskImage.cpp | 68 +++++----- Device/DavexDiskImage.h | 6 +- Device/DiskCopy42Image.cpp | 63 +++++---- Device/DiskCopy42Image.h | 6 +- Device/DiskImage.cpp | 47 +++++-- Device/DiskImage.h | 11 +- Device/SDKImage.cpp | 249 ++++++++++++++++++++++++++++++++++ Device/SDKImage.h | 30 ++++ Device/UniversalDiskImage.cpp | 55 ++++---- Device/UniversalDiskImage.h | 5 +- 12 files changed, 491 insertions(+), 111 deletions(-) create mode 100644 Device/SDKImage.cpp create mode 100644 Device/SDKImage.h diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index c114a00..9418d89 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -19,6 +19,7 @@ #include #include #include +#include using namespace Device; @@ -26,6 +27,30 @@ using ProFUSE::Exception; using ProFUSE::POSIXException; +unsigned BlockDevice::ImageType(MappedFile *f, unsigned defv) +{ +#undef __METHOD__ +#define __METHOD__ "BlockDevice::ImageType" + + + if (UniversalDiskImage::Validate(f, std::nothrow)) + return '2IMG'; + + if (DiskCopy42Image::Validate(f, std::nothrow)) + return 'DC42'; + + if (SDKImage::Validate(f, std::nothrow)) + return 'SDK_'; + + if (ProDOSOrderDiskImage::Validate(f, std::nothrow)) + return 'PO__'; + + if (DOSOrderDiskImage::Validate(f, std::nothrow)) + return 'DO__'; + + return defv; + +} unsigned BlockDevice::ImageType(const char *type, unsigned defv) { @@ -51,7 +76,9 @@ unsigned BlockDevice::ImageType(const char *type, unsigned defv) return '2IMG'; if (::strcasecmp(type, "2img") == 0) return '2IMG'; - + + if (::strcasecmp(type, "dc") == 0) + return 'DC42'; if (::strcasecmp(type, "dc42") == 0) return 'DC42'; @@ -74,6 +101,8 @@ unsigned BlockDevice::ImageType(const char *type, unsigned defv) // not supported yet. if (::strcasecmp(type, "sdk") == 0) return 'SDK_'; + if (::strcasecmp(type, "shk") == 0) + return 'SDK_'; return defv; } @@ -91,23 +120,20 @@ BlockDevicePointer BlockDevice::Open(const char *name, File::FileFlags flags, un { throw POSIXException(__METHOD__ ": stat error", errno); } + + // /dev/xxx ignore the type. + if (S_ISBLK(st.st_mode)) + return RawDevice::Open(name, flags); + + MappedFile file(name, flags); + if (!imageType) { - // /dev/xxxx - if (S_ISBLK(st.st_mode)) - return RawDevice::Open(name, flags); - - - imageType = ImageType(name, 'PO__'); + imageType = ImageType(&file, 'PO__'); } - - // TODO -- if no image type, guess based on file size? - - MappedFile file(name, flags); - - + switch (imageType) { case '2IMG': @@ -125,6 +151,10 @@ BlockDevicePointer BlockDevice::Open(const char *name, File::FileFlags flags, un case 'DVX_': return DavexDiskImage::Open(&file); + case 'SDK_': + return SDKImage::Open(name); + + } // throw an error? diff --git a/Device/BlockDevice.h b/Device/BlockDevice.h index c047912..4b31e71 100644 --- a/Device/BlockDevice.h +++ b/Device/BlockDevice.h @@ -12,6 +12,8 @@ #include +class MappedFile; + namespace Device { class BlockDevice : public ENABLE_SHARED_FROM_THIS(BlockDevice) { @@ -20,7 +22,9 @@ public: // static methods. static unsigned ImageType(const char *type, unsigned defv = 0); - + static unsigned ImageType(MappedFile *, unsigned defv = 0); + + static BlockDevicePointer Open(const char *name, File::FileFlags flags, unsigned imageType = 0); static BlockDevicePointer Create(const char *fname, const char *vname, unsigned blocks, unsigned imageType = 0); diff --git a/Device/DavexDiskImage.cpp b/Device/DavexDiskImage.cpp index 51270bc..f9e44ab 100644 --- a/Device/DavexDiskImage.cpp +++ b/Device/DavexDiskImage.cpp @@ -47,42 +47,48 @@ DavexDiskImage::~DavexDiskImage() // scan and update usedBlocks? } -void DavexDiskImage::Validate(MappedFile *f) +bool DavexDiskImage::Validate(MappedFile *f, const std::nothrow_t &) +{ +#undef __METHOD__ +#define __METHOD__ "DavexDiskImage::Validate" + + size_t size = f->length(); + const void * data = f->address(); + unsigned blocks = (size / 512) - 1; + + + if (size < 512) return false; + if (size % 512) return false; + + // identity. + if (std::memcmp(data, IdentityCheck, 16)) + return false; + + // file format. + if (Read8(data, 0x10) != 0) + return false; + + // total blocks + if (Read32(data, 33) != blocks) + return false; + + // file number -- must be 1 + if (Read8(data, 64) != 1) + return false; + + return true; +} + +bool DavexDiskImage::Validate(MappedFile *f) { #undef __METHOD__ #define __METHOD__ "DavexDiskImage::Validate" - size_t size = f->length(); - const void * data = f->address(); - bool ok = false; - unsigned blocks = (size / 512) - 1; - - do { - if (size < 512) break; - if (size % 512) break; - - // identity. - if (std::memcmp(data, IdentityCheck, 16)) - break; - - // file format. - if (Read8(data, 0x10) != 0) - break; - - // total blocks - if (Read32(data, 33) != blocks) - break; - - // file number -- must be 1 - if (Read8(data, 64) != 1) - break; - - ok = true; - } while (false); - - - if (!ok) + + if (!Validate(f, std::nothrow)) throw Exception(__METHOD__ ": Invalid file format."); + + return true; } BlockDevicePointer DavexDiskImage::Open(MappedFile *file) diff --git a/Device/DavexDiskImage.h b/Device/DavexDiskImage.h index b7a3d36..0c25f04 100644 --- a/Device/DavexDiskImage.h +++ b/Device/DavexDiskImage.h @@ -2,6 +2,7 @@ #define __DAVEXDISKIMAGE_H__ #include +#include #include #include @@ -22,12 +23,15 @@ public: virtual BlockCachePointer createBlockCache(); + static bool Validate(MappedFile *, const std::nothrow_t &); + static bool Validate(MappedFile *); + private: DavexDiskImage(); DavexDiskImage(MappedFile *); - static void Validate(MappedFile *); + bool _changed; std::string _volumeName; diff --git a/Device/DiskCopy42Image.cpp b/Device/DiskCopy42Image.cpp index 7c0956c..9498720 100644 --- a/Device/DiskCopy42Image.cpp +++ b/Device/DiskCopy42Image.cpp @@ -170,41 +170,38 @@ BlockDevicePointer DiskCopy42Image::Create(const char *name, size_t blocks, cons return MAKE_SHARED(DiskCopy42Image, file); } -void DiskCopy42Image::Validate(MappedFile *file) +bool DiskCopy42Image::Validate(MappedFile *file, const std::nothrow_t &) { #undef __METHOD__ #define __METHOD__ "DiskCopy42Image::Validate" - + + size_t bytes = 0; size_t size = file->length(); const void *data = file->address(); - bool ok = false; uint32_t checksum = 0; - do { - if (size < oUserData) break; - - // name must be < 64 - if (Read8(data, 0) > 63) break; - - if (Read16(data, oPrivate) != 0x100) - break; - - // bytes, not blocks. - bytes = Read32(data, oDataSize); - - if (bytes % 512) break; - - if (size < oUserData + bytes) break; - - // todo -- checksum. - checksum = Read32(data, oDataChecksum); - - ok = true; - } while (false); + if (size < oUserData) + return false; - if (!ok) - throw Exception(__METHOD__ ": Invalid file format."); + // name must be < 64 + if (Read8(data, 0) > 63) + return false; + + if (Read16(data, oPrivate) != 0x100) + return false; + + // bytes, not blocks. + bytes = Read32(data, oDataSize); + + if (bytes % 512) + return false; + + if (size < oUserData + bytes) + return false; + + // todo -- checksum. + checksum = Read32(data, oDataChecksum); uint32_t cs = Checksum(oUserData + (uint8_t *)data, bytes); @@ -212,7 +209,21 @@ void DiskCopy42Image::Validate(MappedFile *file) { fprintf(stderr, __METHOD__ ": Warning: checksum invalid.\n"); } + + return true; +} + +bool DiskCopy42Image::Validate(MappedFile *file) +{ +#undef __METHOD__ +#define __METHOD__ "DiskCopy42Image::Validate" + + + if (!Validate(file, std::nothrow)) + throw Exception(__METHOD__ ": Invalid file format."); + + return true; } void DiskCopy42Image::write(unsigned block, const void *bp) diff --git a/Device/DiskCopy42Image.h b/Device/DiskCopy42Image.h index df5c95f..a165b1a 100644 --- a/Device/DiskCopy42Image.h +++ b/Device/DiskCopy42Image.h @@ -19,6 +19,11 @@ public: static uint32_t Checksum(void *data, size_t size); + static bool Validate(MappedFile *, const std::nothrow_t &); + static bool Validate(MappedFile *); + + + virtual void write(unsigned block, const void *bp); @@ -29,7 +34,6 @@ private: DiskCopy42Image(); DiskCopy42Image(MappedFile *); - static void Validate(MappedFile *); bool _changed; }; diff --git a/Device/DiskImage.cpp b/Device/DiskImage.cpp index 6025e5d..a1c15b9 100644 --- a/Device/DiskImage.cpp +++ b/Device/DiskImage.cpp @@ -126,18 +126,33 @@ BlockDevicePointer ProDOSOrderDiskImage::Open(MappedFile *file) return MAKE_SHARED(ProDOSOrderDiskImage, file); } -void ProDOSOrderDiskImage::Validate(MappedFile *f) + +bool ProDOSOrderDiskImage::Validate(MappedFile *f, const std::nothrow_t &) +{ +#undef __METHOD__ +#define __METHOD__ "ProDOSOrderDiskImage::Validate" + + + size_t size = f->length(); + + if (size % 512) + return false; + + return true; + +} + +bool ProDOSOrderDiskImage::Validate(MappedFile *f) { #undef __METHOD__ #define __METHOD__ "ProDOSOrderDiskImage::Validate" if (!f || !f->isValid()) throw Exception(__METHOD__ ": File not set."); - - size_t size = f->length(); - - if (size % 512) + + if (!Validate(f, std::nothrow)) throw Exception(__METHOD__ ": Invalid file format."); + return true; } BlockCachePointer ProDOSOrderDiskImage::createBlockCache() @@ -157,6 +172,8 @@ DOSOrderDiskImage::DOSOrderDiskImage(const char *name, bool readOnly) : } */ + + DOSOrderDiskImage::DOSOrderDiskImage(MappedFile *file) : DiskImage(file) { @@ -182,16 +199,30 @@ BlockDevicePointer DOSOrderDiskImage::Open(MappedFile *file) } -void DOSOrderDiskImage::Validate(MappedFile *f) +bool DOSOrderDiskImage::Validate(MappedFile *f, const std::nothrow_t &) +{ +#undef __METHOD__ +#define __METHOD__ "DOSOrderDiskImage::Validate" + + size_t size = f->length(); + + if (size % 512) + return false; + + return true; + +} + +bool DOSOrderDiskImage::Validate(MappedFile *f) { #undef __METHOD__ #define __METHOD__ "DOSOrderDiskImage::Validate" if (!f || !f->isValid()) throw Exception(__METHOD__ ": File not set."); - size_t size = f->length(); - if (size % 512) + if (!Validate(f, std::nothrow)) throw Exception(__METHOD__ ": Invalid file format."); + return true; } diff --git a/Device/DiskImage.h b/Device/DiskImage.h index 35034f5..25a5c39 100644 --- a/Device/DiskImage.h +++ b/Device/DiskImage.h @@ -62,13 +62,14 @@ public: virtual BlockCachePointer createBlockCache(); - + + static bool Validate(MappedFile *, const std::nothrow_t &); + static bool Validate(MappedFile *); + private: ProDOSOrderDiskImage(); - ProDOSOrderDiskImage(MappedFile *); - static void Validate(MappedFile *); }; class DOSOrderDiskImage : public DiskImage { @@ -78,11 +79,13 @@ public: static BlockDevicePointer Create(const char *name, size_t blocks); static BlockDevicePointer Open(MappedFile *); + static bool Validate(MappedFile *, const std::nothrow_t &); + static bool Validate(MappedFile *); + private: DOSOrderDiskImage(); DOSOrderDiskImage(MappedFile *); - static void Validate(MappedFile *); }; diff --git a/Device/SDKImage.cpp b/Device/SDKImage.cpp new file mode 100644 index 0000000..4667589 --- /dev/null +++ b/Device/SDKImage.cpp @@ -0,0 +1,249 @@ +// +// SDKImage.cpp +// profuse +// +// Created by Kelvin Sherlock on 3/6/2011. +// Copyright 2011 __MyCompanyName__. All rights reserved. +// + +#include "SDKImage.h" + +#include +#include +#include +#include + +#include + + +#include +#include + +#include + + +using ProFUSE::Exception; +using ProFUSE::POSIXException; + + +class NuFXException : public Exception +{ +public: + + NuFXException(const char *cp, NuError error); + NuFXException(const std::string& string, NuError error); + + virtual const char *errorString(); + +}; + + +inline NuFXException::NuFXException(const char *cp, NuError error) : +Exception(cp, error) +{ +} + +inline NuFXException::NuFXException(const std::string& string, NuError error) : +Exception(string, error) +{ +} + +const char *NuFXException::errorString() +{ + return ::NuStrError((NuError)error()); +} + + +using namespace Device; + +struct record_thread +{ + NuRecordIdx record_index; + NuThreadIdx thread_index; +}; + + +static record_thread FindDiskImageThread(NuArchive *archive) +{ +#undef __METHOD__ +#define __METHOD__ "SDKImage::FindThread" + + record_thread rt; + NuError e; + NuAttr recordCount; + + e = NuGetAttr(archive, kNuAttrNumRecords, &recordCount); + if (e) + { + throw NuFXException(__METHOD__ ": NuGetAttr", e); + } + + for (unsigned position = 0; position < recordCount; ++position) + { + NuRecordIdx rIndex; + const NuRecord *record; + + e = NuGetRecordIdxByPosition(archive, position, &rIndex); + if (e) + { + throw NuFXException(__METHOD__ ": NuGetRecordIdxByPosition", e); + } + + e = NuGetRecord(archive, rIndex, &record); + if (e) + { + throw NuFXException(__METHOD__ ": NuGetRecord", e); + } + + for (unsigned i = 0; i < NuRecordGetNumThreads(record); ++i) + { + const NuThread *thread = NuGetThread(record, i); + + if (NuGetThreadID(thread) == kNuThreadIDDiskImage) + { + rt.thread_index = thread->threadIdx; + rt.record_index = record->recordIdx; + return rt; + } + } + } + + throw Exception(__METHOD__ ": not a disk image"); +} + + + +/* + * helper function to extract SDK image to /tmp and return a + * ProDOSDiskImage of the /tmp file. + * + */ +BlockDevicePointer SDKImage::Open(const char *name) +{ +#undef __METHOD__ +#define __METHOD__ "SDKImage::Open" + + + char tmp[] = "/tmp/pfuse.XXXXXXXX"; + + int fd = -1; + FILE *fp = NULL; + NuArchive *archive = NULL; + //const NuThread *thread = NULL; + //const NuRecord *record = NULL; + NuDataSink *sink = NULL; + //NuRecordIdx rIndex; + //NuThreadIdx tIndex; + + NuError e; + + + record_thread rt = {0, 0}; + + try { + + + e = NuOpenRO(name, &archive); + if (e) + { + throw NuFXException(__METHOD__ ": NuOpenRO", e); + } + + rt = FindDiskImageThread(archive); + + fd = mkstemp(tmp); + if (fd < 0) + { + throw POSIXException(__METHOD__ ": mkstemp", errno); + } + + fp = fdopen(fd, "w"); + if (!fp) + { + ::close(fd); + throw POSIXException(__METHOD__ ": fdopen", errno); + } + + e = NuCreateDataSinkForFP(true, kNuConvertOff, fp, &sink); + if (e) + { + throw NuFXException(__METHOD__ ": NuCreateDataSinkForFP", e); + } + + + e = NuExtractThread(archive, rt.thread_index, sink); + if (e) + { + throw NuFXException(__METHOD__ ": NuExtractThread", e); + } + + fprintf(stderr, "Extracted disk image to %s\n", tmp); + + fclose(fp); + NuClose(archive); + NuFreeDataSink(sink); + fp = NULL; + archive = NULL; + sink = NULL; + } + catch(...) + { + if (fp) fclose(fp); + if (archive) NuClose(archive); + if (sink) NuFreeDataSink(sink); + + throw; + } + + // todo -- maybe SDKImage should extend ProDOSOrderDiskImage, have destructor + // that unklinks the temp file. + + MappedFile file(tmp, File::ReadOnly); + + return ProDOSOrderDiskImage::Open(&file); + +} + + + +bool SDKImage::Validate(MappedFile * f, const std::nothrow_t &) +{ + + // NuFile, alternating ASCII. + static const char IdentityCheck[6] = { 0x4E, 0xF5, 0x46, 0xE9, 0x6C, 0xE5 }; + static const char BXYIdentityCheck[3] = { 0x0A, 0x47, 0x4C }; + + uint8_t *address = (uint8_t *)f->address(); + size_t length = f->length(); + + // check for a BXY header + if (length >= 128 + && std::memcmp(address, BXYIdentityCheck, sizeof(BXYIdentityCheck)) == 0) + { + length -= 128; + address += 128; + } + + + if (length > sizeof(IdentityCheck) + && std::memcmp(address, IdentityCheck, sizeof(IdentityCheck)) == 0) + return true; + + + return false; + +} + +bool SDKImage::Validate(MappedFile * f) +{ +#undef __METHOD__ +#define __METHOD__ "SDKImage::Validate" + + if (!Validate(f, std::nothrow)) + throw Exception(__METHOD__ ": Invalid file format."); + + return true; +} + + + diff --git a/Device/SDKImage.h b/Device/SDKImage.h new file mode 100644 index 0000000..fb51fd2 --- /dev/null +++ b/Device/SDKImage.h @@ -0,0 +1,30 @@ +// +// SDKImage.h +// profuse +// +// Created by Kelvin Sherlock on 3/6/2011. +// Copyright 2011 __MyCompanyName__. All rights reserved. +// + +#include +#include + +namespace Device { + + class SDKImage : public DiskImage + { + public: + + static BlockDevicePointer Open(const char *name); + + + static bool Validate(MappedFile *, const std::nothrow_t &); + static bool Validate(MappedFile *); + + private: + SDKImage(); + SDKImage(const SDKImage &); + ~SDKImage(); + SDKImage & operator=(const SDKImage &); + }; +} \ No newline at end of file diff --git a/Device/UniversalDiskImage.cpp b/Device/UniversalDiskImage.cpp index 96ad4ef..18cec76 100644 --- a/Device/UniversalDiskImage.cpp +++ b/Device/UniversalDiskImage.cpp @@ -100,42 +100,47 @@ BlockDevicePointer UniversalDiskImage::Open(MappedFile *file) * TODO -- honor read-only flag. * */ -void UniversalDiskImage::Validate(MappedFile *file) + +bool UniversalDiskImage::Validate(MappedFile *file, const std::nothrow_t &) { #undef __METHOD__ #define __METHOD__ "UniversalDiskImage::Validate" - + const void *data = file->address(); size_t size = file->length(); - bool ok = false; + unsigned blocks = 0; unsigned offset = 0; - do { - - if (size < 64) break; - - if (std::memcmp(data, "2IMG", 4)) break; - - // only prodos supported, for now... - // TODO -- Dos Order, Nibble support. - if (Read32(data, 0x0c) != 1) break; - - blocks = Read32(data, 0x14); - offset = Read32(data, 0x18); - - // file size == blocks * 512 - if (Read32(data, 0x1c) != blocks * 512) break; - - if (offset + blocks * 512 > size) break; - - ok = true; - } while (false); + + if (size < 64) return false; - if (!ok) + if (std::memcmp(data, "2IMG", 4)) return false; + + // only prodos supported, for now... + // TODO -- Dos Order, Nibble support. + if (Read32(data, 0x0c) != 1) return false; + + blocks = Read32(data, 0x14); + offset = Read32(data, 0x18); + + // file size == blocks * 512 + if (Read32(data, 0x1c) != blocks * 512) return false; + + if (offset + blocks * 512 > size) return false; + + return true; +} + +bool UniversalDiskImage::Validate(MappedFile *file) +{ +#undef __METHOD__ +#define __METHOD__ "UniversalDiskImage::Validate" + + if (!Validate(file, std::nothrow)) throw Exception(__METHOD__ ": Invalid file format."); - + return true; } diff --git a/Device/UniversalDiskImage.h b/Device/UniversalDiskImage.h index 23b5b9d..fc54026 100644 --- a/Device/UniversalDiskImage.h +++ b/Device/UniversalDiskImage.h @@ -21,13 +21,16 @@ public: virtual BlockCachePointer createBlockCache(); + + static bool Validate(MappedFile *, const std::nothrow_t &); + static bool Validate(MappedFile *); + private: UniversalDiskImage(); UniversalDiskImage(MappedFile *); - static void Validate(MappedFile *); uint32_t _format; uint32_t _flags; From f70b5897de5992487b27dd644bacb77cc34839fd Mon Sep 17 00:00:00 2001 From: ksherlock Date: Wed, 9 Mar 2011 05:58:10 +0000 Subject: [PATCH 214/236] conditional NUFX Support git-svn-id: https://profuse.googlecode.com/svn/branches/v2@382 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/BlockDevice.cpp | 18 +++++++++++++----- Device/SDKImage.cpp | 1 + Makefile | 25 +++++++++++++++---------- bin/fuse_pascal.cpp | 3 +++ 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index 9418d89..6ac1d9e 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -19,7 +19,10 @@ #include #include #include + +#ifdef HAVE_NUFX #include +#endif using namespace Device; @@ -38,9 +41,11 @@ 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__'; @@ -97,13 +102,14 @@ unsigned BlockDevice::ImageType(const char *type, unsigned defv) if (::strcasecmp(type, "davex") == 0) return 'DVX_'; - - // not supported yet. + +#ifdef HAVE_NUFX if (::strcasecmp(type, "sdk") == 0) return 'SDK_'; if (::strcasecmp(type, "shk") == 0) return 'SDK_'; - +#endif + return defv; } @@ -150,9 +156,11 @@ 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 } diff --git a/Device/SDKImage.cpp b/Device/SDKImage.cpp index 4667589..3c27530 100644 --- a/Device/SDKImage.cpp +++ b/Device/SDKImage.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include diff --git a/Makefile b/Makefile index d9e0f16..45cf1cf 100644 --- a/Makefile +++ b/Makefile @@ -1,16 +1,20 @@ CC = g++ CPPFLAGS += -Wall -W -Wno-multichar -I. -O2 -g -LDFLAGS += -lpthread +LIBS += -lpthread UNAME = $(shell uname -s) ifeq ($(UNAME),Darwin) - fuse_pascal_LDFLAGS += -lfuse_ino64 + fuse_pascal_LIBS += -lfuse_ino64 else - fuse_pascal_LDFLAGS += -lfuse + fuse_pascal_LIBS += -lfuse endif - - +ifdef HAVE_NUFX + DEVICE_OBJECTS += Device/SDKImage.o + LDFLAGS += -L/usr/local/lib/ + LIBS += -lnufx -lz + CPPFLAGS += -DHAVE_NUFX=1 +endif OBJECTS += ${wildcard *.o} @@ -43,6 +47,7 @@ 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 @@ -60,7 +65,7 @@ PROFUSE_OBJECTS += ProFUSE/Lock.o xattr: bin/xattr.o - $(CC) $(LDFLAGS) $^ -o $@ + $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ newfs_pascal: bin/newfs_pascal.o \ ${CACHE_OBJECTS} \ @@ -69,7 +74,7 @@ newfs_pascal: bin/newfs_pascal.o \ ${FILE_OBJECTS} \ ${PROFUSE_OBJECTS} \ ${PASCAL_OBJECTS} - $(CC) $(LDFLAGS) $^ -o $@ + $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ apfm: bin/apfm.o \ ${CACHE_OBJECTS} \ @@ -78,7 +83,7 @@ apfm: bin/apfm.o \ ${FILE_OBJECTS} \ ${PROFUSE_OBJECTS} \ ${PASCAL_OBJECTS} - $(CC) $(LDFLAGS) $^ -o $@ + $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ fuse_pascal: bin/fuse_pascal.o bin/fuse_pascal_ops.o \ @@ -87,8 +92,8 @@ fuse_pascal: bin/fuse_pascal.o bin/fuse_pascal_ops.o \ ${ENDIAN_OBJECTS} \ ${FILE_OBJECTS} \ ${PROFUSE_OBJECTS} \ - ${PASCAL_OBJECTS} - $(CC) $(fuse_pascal_LDFLAGS) $(LDFLAGS) $^ -o $@ + ${PASCAL_OBJECTS} + $(CC) $(LDFLAGS) $^ $(LIBS) $(fuse_pascal_LIBS) -o $@ clean: diff --git a/bin/fuse_pascal.cpp b/bin/fuse_pascal.cpp index e207ec6..ccfa4c4 100644 --- a/bin/fuse_pascal.cpp +++ b/bin/fuse_pascal.cpp @@ -44,6 +44,9 @@ void usage() " 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" From c3f02b28da3f07e814728001c7af1717c3a92f88 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 10 Mar 2011 18:47:04 +0000 Subject: [PATCH 215/236] sdk support for apfm git-svn-id: https://profuse.googlecode.com/svn/branches/v2@383 aa027e90-d47c-11dd-86d7-074df07e0730 --- bin/apfm.cpp | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/bin/apfm.cpp b/bin/apfm.cpp index c81885f..50fb5d2 100644 --- a/bin/apfm.cpp +++ b/bin/apfm.cpp @@ -44,25 +44,31 @@ enum commands { void usage() { std::fputs( - "Pascal File Manager v 0.0\n\n" - "Usage: apfm [-h] [-f format] diskimage action ...\n" - "Options:\n" - " -h Show usage information.\n" - " -f format Specify disk format. Valid values are:\n" - " po: ProDOS order disk image\n" - " do: DOS Order disk image\n" - "\n" - "Actions:\n" - " cat\n" - " krunch\n" - " ls\n" - " cp\n" - " mv\n" - " rm\n" - " get\n" - " put\n", - stdout - ); + "Pascal File Manager v 0.0\n\n" + "Usage: apfm [-h] [-f format] diskimage action ...\n" + "Options:\n" + " -h Show usage information.\n" + " -f format Specify disk 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" + "\n" + "Actions:\n" + " cat\n" + " krunch\n" + " ls\n" + " cp\n" + " mv\n" + " rm\n" + " get\n" + " put\n", + stdout + ); } From e6f655a2c971ccdd8cface3a7003e538531331f4 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 13 Mar 2011 05:22:02 +0000 Subject: [PATCH 216/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@384 aa027e90-d47c-11dd-86d7-074df07e0730 --- bin/fuse_pascal.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bin/fuse_pascal.cpp b/bin/fuse_pascal.cpp index ccfa4c4..2f6d72a 100644 --- a/bin/fuse_pascal.cpp +++ b/bin/fuse_pascal.cpp @@ -9,8 +9,12 @@ #include + +#ifdef __APPLE__ #define __FreeBSD__ 10 #define __DARWIN_64_BIT_INO_T 1 +#endif + #define _FILE_OFFSET_BITS 64 #define FUSE_USE_VERSION 27 From 84e0c8e08cbbad561a8fa2a891cfbefe1671bb17 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 13 Mar 2011 05:44:08 +0000 Subject: [PATCH 217/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@385 aa027e90-d47c-11dd-86d7-074df07e0730 --- PROFuseX.xcodeproj/kelvin.pbxuser | 273 ++++++++++-------------- PROFuseX.xcodeproj/kelvin.perspectivev3 | 55 +++-- PROFuseX.xcodeproj/project.pbxproj | 202 +++++++++++++++++- 3 files changed, 336 insertions(+), 194 deletions(-) diff --git a/PROFuseX.xcodeproj/kelvin.pbxuser b/PROFuseX.xcodeproj/kelvin.pbxuser index f8b703a..da439c9 100644 --- a/PROFuseX.xcodeproj/kelvin.pbxuser +++ b/PROFuseX.xcodeproj/kelvin.pbxuser @@ -1,9 +1,9 @@ // !$*UTF8*$! { 08FB7793FE84155DC02AAC07 /* Project object */ = { - activeBuildConfigurationName = Debug; - activeExecutable = B656AE0411A84F5800AB578A /* fuse_pascal */; - activeTarget = B656AE0211A84F5800AB578A /* fuse_pascal */; + activeBuildConfigurationName = "Debug Universal"; + activeExecutable = B6F3648111AB36260045E114 /* xattr */; + activeTarget = B6F3647F11AB36260045E114 /* xattr */; addToTargets = ( ); breakpoints = ( @@ -103,77 +103,72 @@ PBXFileDataSource_Warnings_ColumnID, ); }; - PBXPerProjectTemplateStateSaveDate = 320461343; - PBXWorkspaceStateSaveDate = 320461343; + PBXPerProjectTemplateStateSaveDate = 320626757; + PBXWorkspaceStateSaveDate = 320626757; }; perUserProjectItems = { - B6272A9811D5AC5E0073C73A = B6272A9811D5AC5E0073C73A /* PBXTextBookmark */; - B6272A9911D5AC5E0073C73A = B6272A9911D5AC5E0073C73A /* PBXTextBookmark */; - B6272A9B11D5AC5E0073C73A = B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */; - B6272A9C11D5AC5E0073C73A = B6272A9C11D5AC5E0073C73A /* PBXTextBookmark */; - B6272B0D11D691320073C73A = B6272B0D11D691320073C73A /* PBXTextBookmark */; - B6272B0E11D691320073C73A = B6272B0E11D691320073C73A /* PBXTextBookmark */; - B6272B0F11D691320073C73A = B6272B0F11D691320073C73A /* PBXTextBookmark */; - B6272B1011D691320073C73A = B6272B1011D691320073C73A /* PBXTextBookmark */; - B6272B1111D691320073C73A = B6272B1111D691320073C73A /* PBXTextBookmark */; - B6272B1311D691320073C73A = B6272B1311D691320073C73A /* PBXTextBookmark */; - B6272B1411D691320073C73A = B6272B1411D691320073C73A /* PBXTextBookmark */; - B6272B1611D691320073C73A = B6272B1611D691320073C73A /* PBXTextBookmark */; - B63EFC2611A2D5A400C90DCE = B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */; - B63EFC3211A2D5A400C90DCE = B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */; - B63EFDA011A4488200C90DCE = B63EFDA011A4488200C90DCE /* PBXTextBookmark */; - B63EFDA511A4488200C90DCE = B63EFDA511A4488200C90DCE /* PBXTextBookmark */; - B63EFDA711A4488200C90DCE = B63EFDA711A4488200C90DCE /* PBXTextBookmark */; - B63EFDA911A4488200C90DCE = B63EFDA911A4488200C90DCE /* PBXTextBookmark */; - B63EFDAB11A4488200C90DCE = B63EFDAB11A4488200C90DCE /* PBXTextBookmark */; - B63EFDAD11A4488200C90DCE = B63EFDAD11A4488200C90DCE /* PBXTextBookmark */; - B63EFDAF11A4488200C90DCE = B63EFDAF11A4488200C90DCE /* PBXTextBookmark */; - B63EFDB111A4488200C90DCE = B63EFDB111A4488200C90DCE /* PBXTextBookmark */; - B63EFDB311A4488200C90DCE = B63EFDB311A4488200C90DCE /* PBXTextBookmark */; - B63EFDF211A4504200C90DCE = B63EFDF211A4504200C90DCE /* PBXTextBookmark */; - B63EFEA011A488C200C90DCE = B63EFEA011A488C200C90DCE /* PBXTextBookmark */; - B63EFEA111A488C200C90DCE = B63EFEA111A488C200C90DCE /* PBXTextBookmark */; - B63EFEA811A488C200C90DCE = B63EFEA811A488C200C90DCE /* PBXTextBookmark */; - B656AE2611A84FA400AB578A = B656AE2611A84FA400AB578A /* PBXTextBookmark */; - B65CFB6911B495790024A2D9 = B65CFB6911B495790024A2D9 /* PBXTextBookmark */; - B6A53B811319DA2D00C9070F /* PBXTextBookmark */ = B6A53B811319DA2D00C9070F /* PBXTextBookmark */; - B6A53B881319DACB00C9070F /* PBXTextBookmark */ = B6A53B881319DACB00C9070F /* PBXTextBookmark */; - B6A53B891319DACB00C9070F /* PBXBookmark */ = B6A53B891319DACB00C9070F /* PBXBookmark */; - B6A53B8A1319DACB00C9070F /* PBXTextBookmark */ = B6A53B8A1319DACB00C9070F /* PBXTextBookmark */; + B6272A9911D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9911D5AC5E0073C73A /* PBXTextBookmark */; + B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */; + B6272A9C11D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9C11D5AC5E0073C73A /* PBXTextBookmark */; + B6272B0D11D691320073C73A /* PBXTextBookmark */ = B6272B0D11D691320073C73A /* PBXTextBookmark */; + B6272B0E11D691320073C73A /* PBXTextBookmark */ = B6272B0E11D691320073C73A /* PBXTextBookmark */; + B6272B0F11D691320073C73A /* PBXTextBookmark */ = B6272B0F11D691320073C73A /* PBXTextBookmark */; + B6272B1011D691320073C73A /* PBXTextBookmark */ = B6272B1011D691320073C73A /* PBXTextBookmark */; + B6272B1111D691320073C73A /* PBXTextBookmark */ = B6272B1111D691320073C73A /* PBXTextBookmark */; + B6272B1311D691320073C73A /* PBXTextBookmark */ = B6272B1311D691320073C73A /* PBXTextBookmark */; + B6272B1411D691320073C73A /* PBXTextBookmark */ = B6272B1411D691320073C73A /* PBXTextBookmark */; + B6272B1611D691320073C73A /* PBXTextBookmark */ = B6272B1611D691320073C73A /* PBXTextBookmark */; + B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */ = B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */; + B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */ = B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */; + B63EFDA011A4488200C90DCE /* PBXTextBookmark */ = B63EFDA011A4488200C90DCE /* PBXTextBookmark */; + B63EFDA511A4488200C90DCE /* PBXTextBookmark */ = B63EFDA511A4488200C90DCE /* PBXTextBookmark */; + B63EFDA711A4488200C90DCE /* PBXTextBookmark */ = B63EFDA711A4488200C90DCE /* PBXTextBookmark */; + B63EFDA911A4488200C90DCE /* PBXTextBookmark */ = B63EFDA911A4488200C90DCE /* PBXTextBookmark */; + B63EFDAB11A4488200C90DCE /* PBXTextBookmark */ = B63EFDAB11A4488200C90DCE /* PBXTextBookmark */; + B63EFDAD11A4488200C90DCE /* PBXTextBookmark */ = B63EFDAD11A4488200C90DCE /* PBXTextBookmark */; + B63EFDAF11A4488200C90DCE /* PBXTextBookmark */ = B63EFDAF11A4488200C90DCE /* PBXTextBookmark */; + B63EFDB111A4488200C90DCE /* PBXTextBookmark */ = B63EFDB111A4488200C90DCE /* PBXTextBookmark */; + B63EFDB311A4488200C90DCE /* PBXTextBookmark */ = B63EFDB311A4488200C90DCE /* PBXTextBookmark */; + B63EFDF211A4504200C90DCE /* PBXTextBookmark */ = B63EFDF211A4504200C90DCE /* PBXTextBookmark */; + B63EFEA011A488C200C90DCE /* PBXTextBookmark */ = B63EFEA011A488C200C90DCE /* PBXTextBookmark */; + B63EFEA111A488C200C90DCE /* PBXTextBookmark */ = B63EFEA111A488C200C90DCE /* PBXTextBookmark */; + B63EFEA811A488C200C90DCE /* PBXTextBookmark */ = B63EFEA811A488C200C90DCE /* PBXTextBookmark */; + B656AE2611A84FA400AB578A /* PBXTextBookmark */ = B656AE2611A84FA400AB578A /* PBXTextBookmark */; + B65CFB6911B495790024A2D9 /* PBXTextBookmark */ = B65CFB6911B495790024A2D9 /* PBXTextBookmark */; B6A53B8E1319DDFC00C9070F /* PBXTextBookmark */ = B6A53B8E1319DDFC00C9070F /* PBXTextBookmark */; - B6A53B8F1319DDFC00C9070F /* PBXTextBookmark */ = B6A53B8F1319DDFC00C9070F /* PBXTextBookmark */; - B6AA3AB21318D063007D4BA1 = B6AA3AB21318D063007D4BA1 /* PBXTextBookmark */; - B6AA3AB31318D063007D4BA1 = B6AA3AB31318D063007D4BA1 /* PBXTextBookmark */; - B6AA3AB41318D063007D4BA1 = B6AA3AB41318D063007D4BA1 /* PBXTextBookmark */; - B6AA3AB51318D063007D4BA1 = B6AA3AB51318D063007D4BA1 /* PBXTextBookmark */; - B6E5F0DD11A60726000AD141 = B6E5F0DD11A60726000AD141 /* PBXTextBookmark */; - B6E5F0F211A73144000AD141 = B6E5F0F211A73144000AD141 /* PBXTextBookmark */; - B6E5F11211A73340000AD141 = B6E5F11211A73340000AD141 /* PBXTextBookmark */; - B6E5F13A11A74F2B000AD141 = B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */; - B6E5F18211A76B74000AD141 = B6E5F18211A76B74000AD141 /* PBXTextBookmark */; - B6F3647111AB35FE0045E114 = B6F3647111AB35FE0045E114 /* PBXTextBookmark */; - B6F3649E11AB59190045E114 = B6F3649E11AB59190045E114 /* PBXTextBookmark */; - B6F364B711AB84840045E114 = B6F364B711AB84840045E114 /* PBXTextBookmark */; - B6F3652E11ADD5D20045E114 = B6F3652E11ADD5D20045E114 /* PBXTextBookmark */; - B6F3653011ADD5D20045E114 = B6F3653011ADD5D20045E114 /* PBXTextBookmark */; - B6F3657E11AE255B0045E114 = B6F3657E11AE255B0045E114 /* PBXTextBookmark */; - B6F3665411B190370045E114 = B6F3665411B190370045E114 /* PBXTextBookmark */; - B6F3665C11B194AC0045E114 = B6F3665C11B194AC0045E114 /* PBXTextBookmark */; - B6F366C411B1A28C0045E114 = B6F366C411B1A28C0045E114 /* PBXTextBookmark */; - B6F366C611B1A28C0045E114 = B6F366C611B1A28C0045E114 /* PBXTextBookmark */; - B6F366C711B1A28C0045E114 = B6F366C711B1A28C0045E114 /* PBXTextBookmark */; - B6F366C811B1A28C0045E114 = B6F366C811B1A28C0045E114 /* PBXTextBookmark */; - B6F366C911B1A28C0045E114 = B6F366C911B1A28C0045E114 /* PBXTextBookmark */; - B6F366CA11B1A28C0045E114 = B6F366CA11B1A28C0045E114 /* PBXTextBookmark */; - B6F366CB11B1A28C0045E114 = B6F366CB11B1A28C0045E114 /* PBXTextBookmark */; - B6F3675411B316D10045E114 = B6F3675411B316D10045E114 /* PBXTextBookmark */; - B6F3677C11B326580045E114 = B6F3677C11B326580045E114 /* PBXTextBookmark */; - B6F3677D11B326580045E114 = B6F3677D11B326580045E114 /* PBXTextBookmark */; - B6F3677E11B326580045E114 = B6F3677E11B326580045E114 /* PBXTextBookmark */; - B6F3677F11B326580045E114 = B6F3677F11B326580045E114 /* PBXTextBookmark */; - B6F367A011B330D10045E114 = B6F367A011B330D10045E114 /* PBXTextBookmark */; - B6F367AE11B337A70045E114 = B6F367AE11B337A70045E114 /* PBXTextBookmark */; - B6F3684A11B44D090045E114 = B6F3684A11B44D090045E114 /* PBXTextBookmark */; + B6A53BC7131B400800C9070F /* PBXTextBookmark */ = B6A53BC7131B400800C9070F /* PBXTextBookmark */; + B6A53BC8131B400800C9070F /* PBXTextBookmark */ = B6A53BC8131B400800C9070F /* PBXTextBookmark */; + B6A53C34131B4CF800C9070F /* PBXTextBookmark */ = B6A53C34131B4CF800C9070F /* PBXTextBookmark */; + B6AA3AB21318D063007D4BA1 /* PBXTextBookmark */ = B6AA3AB21318D063007D4BA1 /* PBXTextBookmark */; + B6AA3AB31318D063007D4BA1 /* PBXTextBookmark */ = B6AA3AB31318D063007D4BA1 /* PBXTextBookmark */; + B6AA3AB41318D063007D4BA1 /* PBXTextBookmark */ = B6AA3AB41318D063007D4BA1 /* PBXTextBookmark */; + B6E5F0DD11A60726000AD141 /* PBXTextBookmark */ = B6E5F0DD11A60726000AD141 /* PBXTextBookmark */; + B6E5F0F211A73144000AD141 /* PBXTextBookmark */ = B6E5F0F211A73144000AD141 /* PBXTextBookmark */; + B6E5F11211A73340000AD141 /* PBXTextBookmark */ = B6E5F11211A73340000AD141 /* PBXTextBookmark */; + B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */ = B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */; + B6E5F18211A76B74000AD141 /* PBXTextBookmark */ = B6E5F18211A76B74000AD141 /* PBXTextBookmark */; + B6F3647111AB35FE0045E114 /* PBXTextBookmark */ = B6F3647111AB35FE0045E114 /* PBXTextBookmark */; + B6F3649E11AB59190045E114 /* PBXTextBookmark */ = B6F3649E11AB59190045E114 /* PBXTextBookmark */; + B6F364B711AB84840045E114 /* PBXTextBookmark */ = B6F364B711AB84840045E114 /* PBXTextBookmark */; + B6F3652E11ADD5D20045E114 /* PBXTextBookmark */ = B6F3652E11ADD5D20045E114 /* PBXTextBookmark */; + B6F3653011ADD5D20045E114 /* PBXTextBookmark */ = B6F3653011ADD5D20045E114 /* PBXTextBookmark */; + B6F3657E11AE255B0045E114 /* PBXTextBookmark */ = B6F3657E11AE255B0045E114 /* PBXTextBookmark */; + B6F3665411B190370045E114 /* PBXTextBookmark */ = B6F3665411B190370045E114 /* PBXTextBookmark */; + B6F3665C11B194AC0045E114 /* PBXTextBookmark */ = B6F3665C11B194AC0045E114 /* PBXTextBookmark */; + B6F366C411B1A28C0045E114 /* PBXTextBookmark */ = B6F366C411B1A28C0045E114 /* PBXTextBookmark */; + B6F366C611B1A28C0045E114 /* PBXTextBookmark */ = B6F366C611B1A28C0045E114 /* PBXTextBookmark */; + B6F366C711B1A28C0045E114 /* PBXTextBookmark */ = B6F366C711B1A28C0045E114 /* PBXTextBookmark */; + B6F366C811B1A28C0045E114 /* PBXTextBookmark */ = B6F366C811B1A28C0045E114 /* PBXTextBookmark */; + B6F366C911B1A28C0045E114 /* PBXTextBookmark */ = B6F366C911B1A28C0045E114 /* PBXTextBookmark */; + B6F366CA11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CA11B1A28C0045E114 /* PBXTextBookmark */; + B6F366CB11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CB11B1A28C0045E114 /* PBXTextBookmark */; + B6F3677C11B326580045E114 /* PBXTextBookmark */ = B6F3677C11B326580045E114 /* PBXTextBookmark */; + B6F3677D11B326580045E114 /* PBXTextBookmark */ = B6F3677D11B326580045E114 /* PBXTextBookmark */; + B6F3677E11B326580045E114 /* PBXTextBookmark */ = B6F3677E11B326580045E114 /* PBXTextBookmark */; + B6F367A011B330D10045E114 /* PBXTextBookmark */ = B6F367A011B330D10045E114 /* PBXTextBookmark */; + B6F367AE11B337A70045E114 /* PBXTextBookmark */ = B6F367AE11B337A70045E114 /* PBXTextBookmark */; + B6F3684A11B44D090045E114 /* PBXTextBookmark */ = B6F3684A11B44D090045E114 /* PBXTextBookmark */; + B6F8D4AD131CB30300461B54 /* PBXTextBookmark */ = B6F8D4AD131CB30300461B54 /* PBXTextBookmark */; }; sourceControlManager = B63EFA6711A093C200C90DCE /* Source Control */; userBuildSettings = { @@ -195,9 +190,9 @@ }; B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 6396}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 643}"; + sepNavIntBoundsRect = "{{0, 0}, {1245, 7124}}"; + sepNavSelRange = "{1531, 0}"; + sepNavVisRange = "{367, 1775}"; }; }; B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */ = { @@ -214,16 +209,6 @@ sepNavVisRange = "{0, 936}"; }; }; - B6272A9811D5AC5E0073C73A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 618"; - rLen = 6; - rLoc = 13762; - rType = 0; - vrLen = 1289; - vrLoc = 13115; - }; B6272A9911D5AC5E0073C73A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B6272A8E11D5AC3C0073C73A /* apfm.cpp */; @@ -635,16 +620,16 @@ }; B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 9555}}"; - sepNavSelRange = "{10781, 0}"; - sepNavVisRange = "{10345, 801}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 9581}}"; + sepNavSelRange = "{628, 36}"; + sepNavVisRange = "{335, 746}"; }; }; B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 12961}}"; - sepNavSelRange = "{13762, 6}"; - sepNavVisRange = "{13219, 1185}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 13026}}"; + sepNavSelRange = "{13717, 0}"; + sepNavVisRange = "{13228, 1176}"; }; }; B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */ = { @@ -1059,16 +1044,6 @@ vrLen = 800; vrLoc = 2262; }; - B6A53B811319DA2D00C9070F /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; - name = "FileEntry.cpp: 544"; - rLen = 0; - rLoc = 10781; - rType = 0; - vrLen = 801; - vrLoc = 10345; - }; B6A53B851319DA3D00C9070F /* smart_pointers.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 475}}"; @@ -1076,30 +1051,6 @@ sepNavVisRange = "{0, 903}"; }; }; - B6A53B881319DACB00C9070F /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; - name = "FileEntry.cpp: 544"; - rLen = 0; - rLoc = 10781; - rType = 0; - vrLen = 801; - vrLoc = 10345; - }; - B6A53B891319DACB00C9070F /* PBXBookmark */ = { - isa = PBXBookmark; - fRef = B6A53B851319DA3D00C9070F /* smart_pointers.h */; - }; - B6A53B8A1319DACB00C9070F /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6A53B851319DA3D00C9070F /* smart_pointers.h */; - name = "smart_pointers.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 903; - vrLoc = 0; - }; B6A53B8E1319DDFC00C9070F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B6A53B851319DA3D00C9070F /* smart_pointers.h */; @@ -1110,12 +1061,32 @@ vrLen = 903; vrLoc = 0; }; - B6A53B8F1319DDFC00C9070F /* PBXTextBookmark */ = { + B6A53BC7131B400800C9070F /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F3651B11ADD0280045E114 /* FileEntry.h */; + name = "FileEntry.h: 20"; + rLen = 23; + rLoc = 292; + rType = 0; + vrLen = 797; + vrLoc = 62; + }; + B6A53BC8131B400800C9070F /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; + name = "FileEntry.cpp: 40"; + rLen = 36; + rLoc = 628; + rType = 0; + vrLen = 746; + vrLoc = 335; + }; + B6A53C34131B4CF800C9070F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 618"; - rLen = 6; - rLoc = 13762; + name = "VolumeEntry.cpp: 616"; + rLen = 0; + rLoc = 13717; rType = 0; vrLen = 1185; vrLoc = 13219; @@ -1150,16 +1121,6 @@ vrLen = 672; vrLoc = 0; }; - B6AA3AB51318D063007D4BA1 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; - name = "FileEntry.cpp: 544"; - rLen = 0; - rLoc = 10781; - rType = 0; - vrLen = 822; - vrLoc = 10324; - }; B6E5F0DD11A60726000AD141 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; @@ -1299,9 +1260,9 @@ }; B6F3651B11ADD0280045E114 /* FileEntry.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1009, 1326}}"; - sepNavSelRange = "{1407, 0}"; - sepNavVisRange = "{0, 1668}"; + sepNavIntBoundsRect = "{{0, 0}, {838, 1430}}"; + sepNavSelRange = "{292, 23}"; + sepNavVisRange = "{62, 797}"; }; }; B6F3651C11ADD0280045E114 /* Entry.h */ = { @@ -1479,16 +1440,6 @@ vrLen = 613; vrLoc = 128; }; - B6F3675411B316D10045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; - name = "FileEntry.cpp: 113"; - rLen = 0; - rLoc = 2383; - rType = 0; - vrLen = 767; - vrLoc = 1707; - }; B6F3676311B323680045E114 /* TextWriter.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1009, 958}}"; @@ -1533,16 +1484,6 @@ vrLen = 532; vrLoc = 0; }; - B6F3677F11B326580045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6F3651B11ADD0280045E114 /* FileEntry.h */; - name = "FileEntry.h: 41"; - rLen = 0; - rLoc = 1069; - rType = 0; - vrLen = 933; - vrLoc = 1184; - }; B6F367A011B330D10045E114 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = B63EFACA11A09DAA00C90DCE /* File.h */; @@ -1606,4 +1547,14 @@ vrLen = 803; vrLoc = 0; }; + B6F8D4AD131CB30300461B54 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 616"; + rLen = 0; + rLoc = 13717; + rType = 0; + vrLen = 1176; + vrLoc = 13228; + }; } diff --git a/PROFuseX.xcodeproj/kelvin.perspectivev3 b/PROFuseX.xcodeproj/kelvin.perspectivev3 index 368f26e..c7b1723 100644 --- a/PROFuseX.xcodeproj/kelvin.perspectivev3 +++ b/PROFuseX.xcodeproj/kelvin.perspectivev3 @@ -231,8 +231,6 @@ Layout - BecomeActive - ContentConfiguration PBXBottomSmartGroupGIDs @@ -282,13 +280,12 @@ PBXSmartGroupTreeModuleOutlineStateSelectionKey - 61 - 60 - 0 + 63 + 62 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey - {{0, 470}, {318, 941}} + {{0, 0}, {318, 941}} PBXTopSmartGroupGIDs @@ -305,7 +302,7 @@ 318 RubberWindowFrame - 182 101 1239 1000 0 0 1920 1178 + 413 92 1239 1000 0 0 1920 1178 Module PBXSmartGroupTreeModule @@ -333,7 +330,7 @@ _historyCapacity 0 bookmark - B6A53B8F1319DDFC00C9070F + B6F8D4AD131CB30300461B54 history B63EFC2611A2D5A400C90DCE @@ -375,7 +372,6 @@ B6F3677C11B326580045E114 B6F3677D11B326580045E114 B6F3677E11B326580045E114 - B6F3677F11B326580045E114 B6F367A011B330D10045E114 B6F367AE11B337A70045E114 B6F3684A11B44D090045E114 @@ -394,9 +390,10 @@ B6AA3AB21318D063007D4BA1 B6AA3AB31318D063007D4BA1 B6AA3AB41318D063007D4BA1 - B6A53B881319DACB00C9070F B6A53B8E1319DDFC00C9070F - B6272A9811D5AC5E0073C73A + B6A53BC7131B400800C9070F + B6A53BC8131B400800C9070F + B6A53C34131B4CF800C9070F SplitCount @@ -410,21 +407,23 @@ GeometryConfiguration Frame - {{0, 0}, {899, 507}} + {{0, 0}, {899, 497}} RubberWindowFrame - 182 101 1239 1000 0 0 1920 1178 + 413 92 1239 1000 0 0 1920 1178 Module PBXNavigatorGroup Proportion - 507pt + 497pt Proportion - 447pt + 457pt Tabs + BecomeActive + ContentConfiguration PBXProjectModuleGUID @@ -435,9 +434,9 @@ GeometryConfiguration Frame - {{10, 27}, {899, 420}} + {{10, 27}, {899, 430}} RubberWindowFrame - 182 101 1239 1000 0 0 1920 1178 + 413 92 1239 1000 0 0 1920 1178 Module XCDetailModule @@ -491,7 +490,7 @@ GeometryConfiguration Frame - {{10, 27}, {899, 410}} + {{10, 27}, {899, 420}} Module PBXBuildResultsModule @@ -519,11 +518,11 @@ TableOfContents - B6A53B821319DA2D00C9070F + B6F8D48A131C605200461B54 1CA23ED40692098700951B8B - B6A53B831319DA2D00C9070F + B6F8D48B131C605200461B54 B63EFA6111A093C200C90DCE - B6A53B841319DA2D00C9070F + B6F8D48C131C605200461B54 1CA23EDF0692099D00951B8B 1CA23EE00692099D00951B8B 1CA23EE10692099D00951B8B @@ -672,14 +671,14 @@ TableOfContents - B6F3647611AB35FE0045E114 + B6A53BCB131B400800C9070F 1CCC7628064C1048000F2A68 1CCC7629064C1048000F2A68 - B6F3647711AB35FE0045E114 - B6F3647811AB35FE0045E114 - B6F3647911AB35FE0045E114 - B6F3647A11AB35FE0045E114 - B63EFA6111A093C200C90DCE + B6A53BCC131B400800C9070F + B6A53BCD131B400800C9070F + B6A53BCE131B400800C9070F + B6A53BCF131B400800C9070F + B6A53BD0131B400800C9070F ToolbarConfigUserDefaultsMinorVersion 2 @@ -716,7 +715,7 @@ /Users/kelvin/Projects/PROFuseX/PROFuseX.xcodeproj WindowString - 182 101 1239 1000 0 0 1920 1178 + 413 92 1239 1000 0 0 1920 1178 WindowToolsV3 diff --git a/PROFuseX.xcodeproj/project.pbxproj b/PROFuseX.xcodeproj/project.pbxproj index b1d7df5..cc25a44 100644 --- a/PROFuseX.xcodeproj/project.pbxproj +++ b/PROFuseX.xcodeproj/project.pbxproj @@ -92,6 +92,14 @@ B656AF1911AA106C00AB578A /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; B656AF1A11AA106C00AB578A /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; B656AF1B11AA106C00AB578A /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; + B6A590EF132995D4007B0EE2 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EC132995D4007B0EE2 /* Carbon.framework */; }; + B6A590F0132995D4007B0EE2 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EC132995D4007B0EE2 /* Carbon.framework */; }; + B6A590F3132995D5007B0EE2 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EE132995D4007B0EE2 /* libz.dylib */; }; + B6A590F4132995D5007B0EE2 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EE132995D4007B0EE2 /* libz.dylib */; }; + B6A590F813299626007B0EE2 /* libNuFX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590F713299626007B0EE2 /* libNuFX.a */; }; + B6A590F913299626007B0EE2 /* libNuFX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590F713299626007B0EE2 /* libNuFX.a */; }; + B6A591281329C417007B0EE2 /* SDKImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6A591261329C417007B0EE2 /* SDKImage.cpp */; }; + B6A591291329C417007B0EE2 /* SDKImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6A591261329C417007B0EE2 /* SDKImage.cpp */; }; B6F3676511B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; B6F3676611B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; B6F3676711B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; @@ -163,7 +171,7 @@ B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileEntry.cpp; sourceTree = ""; }; B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = VolumeEntry.cpp; sourceTree = ""; }; B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOBuffer.cpp.h; sourceTree = ""; }; - B63EFCCE11A36C7300C90DCE /* apfpm */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = apfpm; sourceTree = BUILT_PRODUCTS_DIR; }; + B63EFCCE11A36C7300C90DCE /* apfm */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = apfm; sourceTree = BUILT_PRODUCTS_DIR; }; B63EFE8111A4886C00C90DCE /* newfs_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = newfs_pascal; sourceTree = BUILT_PRODUCTS_DIR; }; B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libfuse_ino64.dylib; path = /usr/local/lib/libfuse_ino64.dylib; sourceTree = ""; }; B656AE0311A84F5800AB578A /* fuse_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fuse_pascal; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -171,6 +179,11 @@ B656AF0311AA105500AB578A /* NibbleTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NibbleTest; sourceTree = BUILT_PRODUCTS_DIR; }; B659C142131368BA0058DC9C /* Device.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Device.h; sourceTree = ""; }; B6A53B851319DA3D00C9070F /* smart_pointers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = smart_pointers.h; sourceTree = ""; }; + B6A590EC132995D4007B0EE2 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = ../../../../System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; + B6A590EE132995D4007B0EE2 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = ../../../../usr/lib/libz.dylib; sourceTree = ""; }; + B6A590F713299626007B0EE2 /* libNuFX.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libNuFX.a; sourceTree = ""; }; + B6A591261329C417007B0EE2 /* SDKImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SDKImage.cpp; sourceTree = ""; }; + B6A591271329C417007B0EE2 /* SDKImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDKImage.h; sourceTree = ""; }; B6F3648011AB36260045E114 /* xattr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xattr; sourceTree = BUILT_PRODUCTS_DIR; }; B6F3651A11ADD0280045E114 /* VolumeEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VolumeEntry.h; sourceTree = ""; }; B6F3651B11ADD0280045E114 /* FileEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileEntry.h; sourceTree = ""; }; @@ -186,6 +199,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B6A590EF132995D4007B0EE2 /* Carbon.framework in Frameworks */, + B6A590F3132995D5007B0EE2 /* libz.dylib in Frameworks */, + B6A590F813299626007B0EE2 /* libNuFX.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -201,6 +217,9 @@ buildActionMask = 2147483647; files = ( B656AE0811A84F6C00AB578A /* libfuse_ino64.dylib in Frameworks */, + B6A590F0132995D4007B0EE2 /* Carbon.framework in Frameworks */, + B6A590F4132995D5007B0EE2 /* libz.dylib in Frameworks */, + B6A590F913299626007B0EE2 /* libNuFX.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -249,7 +268,7 @@ 1AB674ADFE9D54B511CA2CBB /* Products */ = { isa = PBXGroup; children = ( - B63EFCCE11A36C7300C90DCE /* apfpm */, + B63EFCCE11A36C7300C90DCE /* apfm */, B63EFE8111A4886C00C90DCE /* newfs_pascal */, B656AE0311A84F5800AB578A /* fuse_pascal */, B656AF0311AA105500AB578A /* NibbleTest */, @@ -313,6 +332,8 @@ B63EFAA511A094E000C90DCE /* UniversalDiskImage.h */, B63EFB0611A0AC4800C90DCE /* Adaptor.h */, B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */, + B6A591261329C417007B0EE2 /* SDKImage.cpp */, + B6A591271329C417007B0EE2 /* SDKImage.h */, ); path = Device; sourceTree = ""; @@ -375,6 +396,9 @@ B656ADED11A84D3200AB578A /* Libraries */ = { isa = PBXGroup; children = ( + B6A590F713299626007B0EE2 /* libNuFX.a */, + B6A590EC132995D4007B0EE2 /* Carbon.framework */, + B6A590EE132995D4007B0EE2 /* libz.dylib */, B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */, ); name = Libraries; @@ -396,7 +420,7 @@ ); name = apfm; productName = apfpm; - productReference = B63EFCCE11A36C7300C90DCE /* apfpm */; + productReference = B63EFCCE11A36C7300C90DCE /* apfm */; productType = "com.apple.product-type.tool"; }; B63EFE8011A4886C00C90DCE /* newfs_pascal */ = { @@ -531,6 +555,7 @@ B63EFCE511A36C8B00C90DCE /* VolumeEntry.cpp in Sources */, B6F3676711B323680045E114 /* TextWriter.cpp in Sources */, B6272A9311D5AC440073C73A /* apfm.cpp in Sources */, + B6A591281329C417007B0EE2 /* SDKImage.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -588,6 +613,7 @@ B6F3676511B323680045E114 /* TextWriter.cpp in Sources */, B6272A9411D5AC4C0073C73A /* fuse_pascal.cpp in Sources */, B6272A9511D5AC530073C73A /* fuse_pascal_ops.cpp in Sources */, + B6A591291329C417007B0EE2 /* SDKImage.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -667,7 +693,7 @@ /usr/local/include/, ., ); - ONLY_ACTIVE_ARCH = YES; + ONLY_ACTIVE_ARCH = NO; PREBINDING = NO; SDKROOT = macosx; }; @@ -681,6 +707,7 @@ GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = NO; PREBINDING = NO; SDKROOT = macosx; }; @@ -696,6 +723,12 @@ GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../profuse_interim\"", + "\"$(SRCROOT)\"", + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; PREBINDING = NO; PRODUCT_NAME = apfpm; }; @@ -710,6 +743,12 @@ GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../profuse_interim\"", + "\"$(SRCROOT)\"", + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; PREBINDING = NO; PRODUCT_NAME = apfpm; ZERO_LINK = NO; @@ -761,7 +800,7 @@ /usr/local/include/, ., ); - ONLY_ACTIVE_ARCH = YES; + ONLY_ACTIVE_ARCH = NO; PREBINDING = NO; SDKROOT = macosx; }; @@ -777,6 +816,12 @@ GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../profuse_interim\"", + "\"$(SRCROOT)\"", + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; PREBINDING = NO; PRODUCT_NAME = apfpm; }; @@ -808,6 +853,12 @@ GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../profuse_interim\"", + "\"$(SRCROOT)\"", + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; PREBINDING = NO; PRODUCT_NAME = fuse_pascal; }; @@ -820,6 +871,12 @@ GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../profuse_interim\"", + "\"$(SRCROOT)\"", + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; PREBINDING = NO; PRODUCT_NAME = fuse_pascal; }; @@ -834,6 +891,12 @@ GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../profuse_interim\"", + "\"$(SRCROOT)\"", + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; PREBINDING = NO; PRODUCT_NAME = fuse_pascal; ZERO_LINK = NO; @@ -882,6 +945,128 @@ }; name = Release; }; + B6A53C1E131B47DC00C9070F /* Debug Universal */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + /usr/local/include/, + ., + ); + ONLY_ACTIVE_ARCH = NO; + PREBINDING = NO; + SDKROOT = macosx; + }; + name = "Debug Universal"; + }; + B6A53C1F131B47DC00C9070F /* 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; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../profuse_interim\"", + "\"$(SRCROOT)\"", + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = apfm; + }; + name = "Debug Universal"; + }; + B6A53C20131B47DC00C9070F /* 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_VERSION = com.apple.compilers.llvm.clang.1_0; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = newfs_pascal; + }; + name = "Debug Universal"; + }; + B6A53C21131B47DC00C9070F /* 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; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../profuse_interim\"", + "\"$(SRCROOT)\"", + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = fuse_pascal; + }; + name = "Debug Universal"; + }; + B6A53C22131B47DC00C9070F /* 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; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = NibbleTest; + }; + name = "Debug Universal"; + }; + B6A53C23131B47DC00C9070F /* 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; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = xattr; + }; + name = "Debug Universal"; + }; + B6A53C24131B47DC00C9070F /* 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; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = newfs_prodos; + }; + name = "Debug Universal"; + }; B6F3648211AB36260045E114 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -973,6 +1158,7 @@ isa = XCConfigurationList; buildConfigurations = ( 1DEB923608733DC60010E9CD /* Debug */, + B6A53C1E131B47DC00C9070F /* Debug Universal */, B656AD7A11A84B5D00AB578A /* Debug fuse */, 1DEB923708733DC60010E9CD /* Release */, ); @@ -983,6 +1169,7 @@ isa = XCConfigurationList; buildConfigurations = ( B63EFCD011A36C7300C90DCE /* Debug */, + B6A53C1F131B47DC00C9070F /* Debug Universal */, B656AD7C11A84B5D00AB578A /* Debug fuse */, B63EFCD111A36C7300C90DCE /* Release */, ); @@ -993,6 +1180,7 @@ isa = XCConfigurationList; buildConfigurations = ( B63EFE8311A4886C00C90DCE /* Debug */, + B6A53C20131B47DC00C9070F /* Debug Universal */, B656AD7D11A84B5D00AB578A /* Debug fuse */, B63EFE8411A4886C00C90DCE /* Release */, ); @@ -1003,6 +1191,7 @@ isa = XCConfigurationList; buildConfigurations = ( B656AE0511A84F5900AB578A /* Debug */, + B6A53C21131B47DC00C9070F /* Debug Universal */, B656AE0611A84F5900AB578A /* Debug fuse */, B656AE0711A84F5900AB578A /* Release */, ); @@ -1013,6 +1202,7 @@ isa = XCConfigurationList; buildConfigurations = ( B656AF0511AA105600AB578A /* Debug */, + B6A53C22131B47DC00C9070F /* Debug Universal */, B656AF0611AA105600AB578A /* Debug fuse */, B656AF0711AA105600AB578A /* Release */, ); @@ -1023,6 +1213,7 @@ isa = XCConfigurationList; buildConfigurations = ( B6F3648211AB36260045E114 /* Debug */, + B6A53C23131B47DC00C9070F /* Debug Universal */, B6F3648311AB36260045E114 /* Debug fuse */, B6F3648411AB36260045E114 /* Release */, ); @@ -1033,6 +1224,7 @@ isa = XCConfigurationList; buildConfigurations = ( B6F3682711B431AC0045E114 /* Debug */, + B6A53C24131B47DC00C9070F /* Debug Universal */, B6F3682811B431AC0045E114 /* Debug fuse */, B6F3682911B431AC0045E114 /* Release */, ); From 304164ecfa2a3627e99b753301eeded748ae0fe1 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 13 Mar 2011 16:02:30 +0000 Subject: [PATCH 218/236] integrate profuse (classic) git-svn-id: https://profuse.googlecode.com/svn/branches/v2@386 aa027e90-d47c-11dd-86d7-074df07e0730 --- Makefile | 58 ++++- ProDOS/Bitmap.cpp | 101 +++++--- ProDOS/Bitmap.h | 17 +- ProDOS/Disk.cpp | 486 ++++++++++++++++++++++++++++++++++ ProDOS/Disk.h | 83 ++++++ ProDOS/File.cpp | 230 +++++++++++++++++ ProDOS/File.h | 133 ++++++++++ ProDOS/Makefile | 7 - ProDOS/common.h | 18 ++ bin/profuse.cpp | 374 +++++++++++++++++++++++++++ bin/profuse.h | 62 +++++ bin/profuse_dirent.cpp | 130 ++++++++++ bin/profuse_file.cpp | 136 ++++++++++ bin/profuse_stat.cpp | 252 ++++++++++++++++++ bin/profuse_xattr.cpp | 573 +++++++++++++++++++++++++++++++++++++++++ 15 files changed, 2598 insertions(+), 62 deletions(-) create mode 100644 ProDOS/Disk.cpp create mode 100644 ProDOS/Disk.h create mode 100644 ProDOS/File.cpp create mode 100644 ProDOS/File.h delete mode 100644 ProDOS/Makefile create mode 100644 ProDOS/common.h create mode 100644 bin/profuse.cpp create mode 100644 bin/profuse.h create mode 100644 bin/profuse_dirent.cpp create mode 100644 bin/profuse_file.cpp create mode 100644 bin/profuse_stat.cpp create mode 100644 bin/profuse_xattr.cpp diff --git a/Makefile b/Makefile index 45cf1cf..02ebdab 100644 --- a/Makefile +++ b/Makefile @@ -4,9 +4,9 @@ LIBS += -lpthread UNAME = $(shell uname -s) ifeq ($(UNAME),Darwin) - fuse_pascal_LIBS += -lfuse_ino64 + FUSE_LIBS += -lfuse_ino64 else - fuse_pascal_LIBS += -lfuse + FUSE_LIBS += -lfuse endif ifdef HAVE_NUFX @@ -25,8 +25,9 @@ OBJECTS += ${wildcard Endian/*.o} OBJECTS += ${wildcard File/*.o} OBJECTS += ${wildcard Pascal/*.o} OBJECTS += ${wildcard ProFUSE/*.o} +OBJECTS += ${wildcard ProDOS/*.o} -TARGETS = apfm newfs_pascal profuse_pascal xattr +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 @@ -34,6 +35,13 @@ 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 @@ -62,12 +70,25 @@ PASCAL_OBJECTS += Pascal/VolumeEntry.o PROFUSE_OBJECTS += ProFUSE/Exception.o PROFUSE_OBJECTS += ProFUSE/Lock.o +PRODOS_OBJECTS += ProDOS/DateTime.o +PRODOS_OBJECTS += ProDOS/Disk.o +PRODOS_OBJECTS += ProDOS/File.o + +all: $(TARGETS) -xattr: bin/xattr.o +#apfm: o/apfm +#fuse_pascal: o/fuse_pascal +#newfs_pascal: o/newfs_pascal +#profuse: o/profuse +#xattr: o/xattr + + + +o/xattr: bin/xattr.o $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ -newfs_pascal: bin/newfs_pascal.o \ +o/newfs_pascal: bin/newfs_pascal.o \ ${CACHE_OBJECTS} \ ${DEVICE_OBJECTS} \ ${ENDIAN_OBJECTS} \ @@ -76,7 +97,7 @@ newfs_pascal: bin/newfs_pascal.o \ ${PASCAL_OBJECTS} $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ -apfm: bin/apfm.o \ +o/apfm: bin/apfm.o \ ${CACHE_OBJECTS} \ ${DEVICE_OBJECTS} \ ${ENDIAN_OBJECTS} \ @@ -86,14 +107,25 @@ apfm: bin/apfm.o \ $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ -fuse_pascal: bin/fuse_pascal.o bin/fuse_pascal_ops.o \ +o/fuse_pascal: bin/fuse_pascal.o bin/fuse_pascal_ops.o \ ${CACHE_OBJECTS} \ ${DEVICE_OBJECTS} \ ${ENDIAN_OBJECTS} \ ${FILE_OBJECTS} \ ${PROFUSE_OBJECTS} \ ${PASCAL_OBJECTS} - $(CC) $(LDFLAGS) $^ $(LIBS) $(fuse_pascal_LIBS) -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} \ + ${PROFUSE_OBJECTS} \ + ${PRODOS_OBJECTS} + $(CC) $(LDFLAGS) $^ $(LIBS) $(FUSE_LIBS) -o $@ clean: @@ -201,3 +233,13 @@ Pascal/VolumeEntry.o: Pascal/VolumeEntry.cpp Pascal/Pascal.h Pascal/Date.h \ Pascal/TextWriter.o: Pascal/TextWriter.cpp Pascal/TextWriter.h \ Pascal/FileEntry.h Pascal/Entry.h Pascal/Date.h ProFUSE/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 + + diff --git a/ProDOS/Bitmap.cpp b/ProDOS/Bitmap.cpp index 57ed601..c6868aa 100644 --- a/ProDOS/Bitmap.cpp +++ b/ProDOS/Bitmap.cpp @@ -1,9 +1,8 @@ #include #include -#include -#include "auto.h" - +#include +#include using namespace ProDOS; @@ -34,26 +33,25 @@ Bitmap::Bitmap(unsigned blocks) _freeIndex = 0; unsigned bitmapSize = _bitmapBlocks * 512; - unsigned blockSize = blocks / 8; - auto_array 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); + _bitmap.reserve(bitmapSize); - // edge case - unsigned tmp = blocks & 0x07; + // mark blocks as free.. + _bitmap.resize(blocks / 8, 0xff); - bitmap[blocks / 8] = ~(0xff >> tmp); + // edge case... - _bitmap = bitmap.release(); + if (blocks & 0x0f) + { + _bitmap.push_back( ~(0xff >> (blocks & 0x0f)) ); + } + // mark any trailing blocks as in use. + _bitmap.resize(bitmapSize, 0x00); } -Bitmap::Bitmap(BlockDevice *device, unsigned keyPointer, unsigned blocks) +Bitmap::Bitmap(Device::BlockCache *cache, unsigned keyPointer, unsigned blocks) { _blocks = blocks; _freeBlocks = 0; @@ -64,47 +62,68 @@ Bitmap::Bitmap(BlockDevice *device, unsigned keyPointer, unsigned blocks) unsigned bitmapSize = _bitmapBlocks * 512; unsigned blockSize = blocks / 8; - auto_array bitmap(new uint8_t[bitmapSize]); + _bitmap.reserve(bitmapSize); + + // load the full block(s). for (unsigned i = 0; i < blockSize; ++i) { - device->read(keyPointer + i, bitmap + 512 * i); + uint8_t *buffer = (uint8_t *)cache->acquire(keyPointer); + + _bitmap.insert(_bitmap.end(), buffer, buffer + 512); + + cache->release(keyPointer); + + keyPointer++; } - // make sure all trailing bits are marked in use. - - // edge case - unsigned tmp = blocks & 0x07; + // and any remaining partial block. - 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) + if (blocks & 4095) { - _freeBlocks += popCount(bitmap[i]); - } - - if (_freeBlocks) - { - 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) { - if (bitmap[i]) - { - _freeIndex = i; - break; - } + uint8_t tmp = buffer[bytes]; + tmp &= ~(0xff >> (blocks & 0x0f)); + + _bitmap.push_back(tmp); } - } + + // remainder set to in use. + _bitmap.resize(bitmapSize, 0x00); + cache->release(keyPointer); + + keyPointer++; + + } - _bitmap = bitmap.release(); + + // now set _freeBlocks and _freeIndex; + std::vector::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() { - if (_bitmap) delete []_bitmap; } diff --git a/ProDOS/Bitmap.h b/ProDOS/Bitmap.h index 77388a6..54fe12e 100644 --- a/ProDOS/Bitmap.h +++ b/ProDOS/Bitmap.h @@ -2,20 +2,25 @@ #define __BITMAP_H__ #include +#include +namespace Device +{ + class BlockDevice; + class BlockCache; +} + namespace ProDOS { -class BlockDevice; - class Bitmap { public: Bitmap(unsigned blocks); - Bitmap(BlockDevice *device, unsigned keyPointer, unsigned blocks); - //todo -- constructor by loading from, block device... + Bitmap(Device::BlockCache *cache, unsigned keyPointer, unsigned blocks); + ~Bitmap(); int allocBlock(); @@ -28,7 +33,7 @@ public: unsigned blocks() const { return _blocks; } unsigned bitmapBlocks() const { return _bitmapBlocks; } unsigned bitmapSize() const { return _bitmapBlocks * 512; } - const void *bitmap() const { return _bitmap; } + const void *bitmap() const { return &_bitmap[0]; } private: @@ -38,7 +43,7 @@ private: unsigned _blocks; unsigned _bitmapBlocks; - uint8_t *_bitmap; + std::vector _bitmap; }; diff --git a/ProDOS/Disk.cpp b/ProDOS/Disk.cpp new file mode 100644 index 0000000..0270073 --- /dev/null +++ b/ProDOS/Disk.cpp @@ -0,0 +1,486 @@ +/* + * Disk.cpp + * ProFUSE + * + * Created by Kelvin Sherlock on 12/18/08. + * + */ + +#include "Disk.h" + + +#include "common.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +struct ucmp +{ + bool operator()(unsigned a, unsigned b) const + { + return a < b; + } +}; + +using std::set; +using std::vector; + +using namespace LittleEndian; + +typedef set uset; + +Disk::Disk() +{ + _blocks = 0; + +} + +Disk::~Disk() +{ +} + +Disk::Disk(Device::BlockDevicePointer device) : + _device(device) +{ + _blocks = _device->blocks(); +} + +DiskPointer Disk::OpenFile(Device::BlockDevicePointer device) +{ + DiskPointer disk(new Disk(device)); + + return disk; +} + +// load the mini entry into the regular entry. +int Disk::Normalize(FileEntry &f, unsigned fork, ExtendedEntry *ee) +{ + uint8_t buffer[BLOCK_SIZE]; + int ok; + + if (fork > 1) return -P8_INVALID_FORK; + + if (f.storage_type != EXTENDED_FILE) + { + return fork == 0 ? 0 : -P8_INVALID_FORK; + } + + ok = Read(f.key_pointer, buffer); + if (ok < 0) return ok; + + ExtendedEntry e; + e.Load(buffer); + + if (fork == 0) + { + f.storage_type = e.dataFork.storage_type; + f.key_pointer = e.dataFork.key_block; + f.eof = e.dataFork.eof; + f.blocks_used = e.dataFork.blocks_used; + } + else + { + f.storage_type = e.resourceFork.storage_type; + f.key_pointer = e.resourceFork.key_block; + f.eof = e.resourceFork.eof; + f.blocks_used = e.resourceFork.blocks_used; + } + + if (ee) *ee = e; + + return 0; + +} + + +int Disk::Read(unsigned block, void *buffer) +{ + + if (block > _blocks) return -P8_INVALID_BLOCK; + + _device->read(block, buffer); + + return 1; +} + + +void *Disk::ReadFile(const FileEntry &f, unsigned fork, uint32_t *size, int *error) +{ + +#define SET_ERROR(x) if (error) *error = (x) +#define SET_SIZE(x) if (size) *size = (x) + + + SET_ERROR(0); + SET_SIZE(0); + + if (fork != P8_DATA_FORK && fork != P8_RESOURCE_FORK) + { + SET_ERROR(-P8_INVALID_FORK); + return NULL; + } + + uint8_t buffer[BLOCK_SIZE]; + int ok; + uint32_t eof; + uint32_t alloc; + unsigned blocks; + unsigned storage_type; + unsigned key_block; + + switch(f.storage_type) + { + case SEEDLING_FILE: + case SAPLING_FILE: + case TREE_FILE: + if (fork != P8_DATA_FORK) + { + SET_ERROR(1); + return NULL; + } + storage_type = f.storage_type; + eof = f.eof; + key_block = f.key_pointer; + break; + + case EXTENDED_FILE: + { + ok = Read(f.key_pointer, buffer); + if (ok < 0) + { + SET_ERROR(ok); + return NULL; + } + + ExtendedEntry entry; + entry.Load(buffer); + + if (fork == P8_DATA_FORK) + { + storage_type = entry.dataFork.storage_type; + eof = entry.dataFork.eof; + key_block = entry.dataFork.key_block; + } + else + { + storage_type = entry.resourceFork.storage_type; + eof = entry.resourceFork.eof; + key_block = entry.resourceFork.key_block; + } + } + break; + default: + SET_ERROR(-P8_INVALID_STORAGE_TYPE); + return NULL; + } + + if (eof == 0) + { + SET_ERROR(1); + return NULL; + } + + blocks = (eof + BLOCK_SIZE - 1) >> 9; + alloc = (eof + BLOCK_SIZE - 1) & (~BLOCK_SIZE); + uint8_t* data = new uint8_t[alloc]; + + + switch (storage_type) + { + case SEEDLING_FILE: + ok = Read(key_block, data); + break; + case SAPLING_FILE: + ok = ReadIndex(f.key_pointer, buffer, 1, 0, blocks); + break; + case TREE_FILE: + ok = ReadIndex(f.key_pointer, buffer, 2, 0, blocks); + break; + + default: + ok = false; + } + + if (ok < 0) + { + SET_ERROR(ok); + delete[] data; + return NULL; + } + + + bzero(data + eof, alloc - eof); + SET_SIZE(eof); + + return data; +} + + +int Disk::ReadFile(const FileEntry &f, void *buffer) +{ + int blocks = (f.eof + BLOCK_SIZE - 1) >> 9; + int ok; + + switch(f.storage_type) + { + case TREE_FILE: + ok = ReadIndex(f.key_pointer, buffer, 2, 0, blocks); + break; + case SAPLING_FILE: + ok = ReadIndex(f.key_pointer, buffer, 1, 0, blocks); + break; + case SEEDLING_FILE: + ok = Read(f.key_pointer, buffer); + break; + + default: + return -P8_INVALID_STORAGE_TYPE; + } + + if (ok >= 0) + { + bzero((uint8_t *)buffer + f.eof, (blocks << 9) - f.eof); + } + + return ok; +} + + +int Disk::ReadIndex(unsigned block, void *buffer, unsigned level, off_t offset, unsigned blocks) +{ + if (level == 0) + { + // data level + if (block == 0) // sparse file + { + bzero(buffer, BLOCK_SIZE); + return 1; + } + return Read(block, buffer); + } + + + unsigned blockCount; + unsigned readSize; + unsigned first; + //unsigned last; + + + switch(level) + { + case 1: + first = (offset >> 9) & 0xff; + blockCount = 1; + readSize = BLOCK_SIZE; + offset = 0; + break; + case 2: + first = (offset >> 17) & 0xff; + blockCount = 256; + readSize = BLOCK_SIZE << 8; + offset &= 0x1ffff; + break; + default: + return -P8_INTERNAL_ERROR; + } + + + + + int ok; + uint8_t key[BLOCK_SIZE]; + + if (block) // not sparse. + { + ok = Read(block, key); + if (ok < 0 ) return ok; + } + else + { + // sparse -- zero it out so code below works w/o special cases. + bzero(key, BLOCK_SIZE); + } + + for (unsigned i = first; blocks; i++) + { + // block pointers are split up since 8-bit indexing is limited to 256. + unsigned newBlock = (key[i]) | (key[256 + i] << 8); + + unsigned b = std::min(blocks, blockCount); + + ok = ReadIndex(newBlock, buffer, level - 1, offset, b); + if (ok < 0) return ok; + offset = 0; + buffer = ((char *)buffer) + readSize; + blocks -= b; + } + return blocks; +} + + + +int Disk::ReadVolume(VolumeEntry *volume, std::vector *files) +{ + if (files) files->resize(0); + + uint8_t buffer[BLOCK_SIZE]; + int ok; + unsigned prev; + unsigned next; + + uset blocks; + + unsigned block = 2; + blocks.insert(block); + ok = Read(block, buffer); + + if (ok < 0) return ok; + + prev = Read16(&buffer[0x00]); + next = Read16(&buffer[0x02]); + + VolumeEntry v; + v.Load(buffer + 0x04); + + if (v.storage_type != VOLUME_HEADER) return -P8_INVALID_STORAGE_TYPE; + + if (volume) *volume = v; + + if (!files) return 1; + + if (v.file_count) + { + files->reserve(v.file_count); + //files->resize(v.file_count); + + //unsigned count = 0; + unsigned index = 1; // skip the header. + for(;;) + { + // + if ( (buffer[0x04 + v.entry_length * index] >> 4) != DELETED_FILE) + { + unsigned offset = v.entry_length * index + 0x4; + FileEntry f; + f.Load(buffer + offset); + f.address = (block << 9) + offset; + + files->push_back(f); + //if (++count == v.file_count) break; + } + index++; + if (index >= v.entries_per_block) + { + if (!next) break; // all done! + + + if (blocks.insert(next).second == false) + { + return -P8_CYCLICAL_BLOCK; + } + + ok = Read(next, buffer); + if (ok < 0) return ok; + block = next; + + prev = Read16(&buffer[0x00]); + next = Read16(&buffer[0x02]); + + index = 0; + } + } + } + + return 1; +} + + +int Disk::ReadDirectory(unsigned block, SubdirEntry *dir, std::vector *files) +{ + if (files) files->resize(0); + + uint8_t buffer[BLOCK_SIZE]; + int ok; + unsigned prev; + unsigned next; + + // keep a list of blocks to prevent cyclical problems. + uset blocks; + + blocks.insert(block); + + ok = Read(block, buffer); + + if (ok < 0) return ok; + + prev = Read16(&buffer[0x00]); + next = Read16(&buffer[0x02]); + + SubdirEntry v; + v.Load(buffer + 0x04); + + if (v.storage_type != SUBDIR_HEADER) return -P8_INVALID_STORAGE_TYPE; + + + if (dir) *dir = v; + + if (!files) return 1; + + if (v.file_count) + { + files->reserve(v.file_count); + //files->resize(v.file_count); + + //unsigned count = 0; + unsigned index = 1; // skip the header. + for(;;) + { + // + if ( (buffer[0x04 + v.entry_length * index] >> 4) != DELETED_FILE) + { + unsigned offset = v.entry_length * index + 0x4; + FileEntry f; + f.Load(buffer + offset); + f.address = (block << 9) + offset; + + files->push_back(f); + + //if (++count == v.file_count) break; + } + index++; + if (index >= v.entries_per_block) + { + if (!next) break; // all done! + + + if (blocks.insert(next).second == false) + { + return -P8_CYCLICAL_BLOCK; + } + + ok = Read(next, buffer); + if (ok < 0) return ok; + block = next; + + + prev = Read16(&buffer[0x00]); + next = Read16(&buffer[0x02]); + + index = 0; + } + } + } + + return 1; +} diff --git a/ProDOS/Disk.h b/ProDOS/Disk.h new file mode 100644 index 0000000..683defc --- /dev/null +++ b/ProDOS/Disk.h @@ -0,0 +1,83 @@ +/* + * Disk.h + * ProFUSE + * + * Created by Kelvin Sherlock on 12/18/08. + * + */ +#ifndef __DISK_H__ +#define __DISK_H__ + +#include +#include + +#include + +#include +#include + +#include + + +enum { + P8_OK = 0, + P8_INTERNAL_ERROR, + P8_INVALID_FORK, + P8_INVALID_BLOCK, + P8_INVALID_STORAGE_TYPE, + P8_CYCLICAL_BLOCK + +}; + +enum { + P8_DATA_FORK = 0, + P8_RESOURCE_FORK = 1 +}; + + +/* flags */ +enum { + P8_DOS_ORDER = 1, + P8_2MG = 2, + P8_DC42 = 4 + +}; + +class Disk; +typedef std::tr1::shared_ptr DiskPointer; + +class Disk { + +public: + ~Disk(); + + //static Disk *Open2MG(const char *file); + static DiskPointer OpenFile(Device::BlockDevicePointer device); + + + int Normalize(FileEntry &f, unsigned fork, ExtendedEntry *ee = NULL); + + int Read(unsigned block, void *buffer); + int ReadIndex(unsigned block, void *buffer, unsigned level, off_t offset, unsigned blocks); + + int ReadFile(const FileEntry &f, void *buffer); + + void *ReadFile(const FileEntry &f, unsigned fork, uint32_t *size, int * error); + + + int ReadVolume(VolumeEntry *volume, std::vector *files); + int ReadDirectory(unsigned block, SubdirEntry *dir, std::vector *files); + +private: + Disk(); + Disk(Device::BlockDevicePointer device); + + unsigned _blocks; + + Device::BlockDevicePointer _device; +}; + + + +#endif + diff --git a/ProDOS/File.cpp b/ProDOS/File.cpp new file mode 100644 index 0000000..985d8a4 --- /dev/null +++ b/ProDOS/File.cpp @@ -0,0 +1,230 @@ +/* + * File.cpp + * ProFUSE + * + * Created by Kelvin Sherlock on 12/18/08. + * + */ + +#include +#include +#include + +#include "common.h" +#include +#include +#include +#include + +using namespace LittleEndian; + + +bool FileEntry::Load(const void *data) +{ + const uint8_t *cp = (const uint8_t *)data; + + address = 0; + + storage_type = cp[0x00] >> 4; + name_length = cp[0x00] & 0x0f; + + memcpy(file_name, &cp[0x01], name_length); + file_name[name_length] = 0; + + file_type = cp[0x10]; + + key_pointer = Read16(&cp[0x11]); + + blocks_used = Read16(&cp[0x13]); + + eof = Read24(&cp[0x15]); + + creation = ProDOS::DateTime(Read16(&cp[0x18]), Read16(&cp[0x1a])); + + //version = cp[0x1c]; + //min_version = cp[0x1d]; + + unsigned xcase = Read16(&cp[0x1c]); + if (xcase & 0x8000) + { + // gsos technote #8 + unsigned mask = 0x4000; + for (unsigned i = 0; i < name_length; i++) + { + if (xcase & mask) file_name[i] = tolower(file_name[i]); + mask = mask >> 1; + } + } + + + + access = cp[0x1e]; + + + aux_type = Read16(&cp[0x1f]); + + last_mod = ProDOS::DateTime(Read16(&cp[0x21]), Read16(&cp[0x23])); + + header_pointer = Read16(&cp[0x25]); + + return true; +} + + + + +bool ExtendedEntry::Load(const void *data) +{ + const uint8_t *cp = (const uint8_t *)data; + + //prodos technote #25. + // offset 0 - mini entry for data fork + + dataFork.storage_type = cp[0x00] & 0x0f; + dataFork.key_block = Read16(&cp[0x01]); + dataFork.blocks_used = Read16(&cp[0x03]); + dataFork.eof = Read24(&cp[0x05]); + + // offset 256 - mini entry for resource fork. + + resourceFork.storage_type = cp[256 + 0x00] & 0x0f; + resourceFork.key_block = Read16(&cp[256 + 0x01]); + resourceFork.blocks_used = Read16(&cp[256 + 0x03]); + resourceFork.eof = Read24(&cp[256 + 0x05]); + + // xFInfo may be missing. + bzero(FInfo, sizeof(FInfo)); + bzero(xFInfo, sizeof(xFInfo)); + + // size must be 18. + unsigned size; + unsigned entry; + + for (unsigned i = 0; i < 2; i++) + { + unsigned ptr = i == 0 ? 8 : 26; + size = cp[ptr]; + if (size != 18) continue; + entry = cp[ptr + 1]; + switch(entry) + { + case 1: + memcpy(FInfo, &cp[ptr + 2], 16); + break; + case 2: + memcpy(xFInfo, &cp[ptr + 2], 16); + break; + } + } + // + return true; +} + + + +bool VolumeEntry::Load(const void *data) +{ + const uint8_t *cp = (const uint8_t *)data; + + //prev_block = load16(&cp[0x00]); + //next_block = load16(&cp[0x02]); + + storage_type = cp[0x00] >> 4; + name_length = cp[0x00] & 0x0f; + + memcpy(volume_name, &cp[0x01], name_length); + volume_name[name_length] = 0; + + // 0x14--0x1b reserved + + creation = ProDOS::DateTime(Read16(&cp[0x18]), Read16(&cp[0x1a])); + last_mod = ProDOS::DateTime(Read16(&cp[0x12]), Read16(&cp[0x14])); + + if (last_mod == 0) last_mod = creation; + + //version = cp[0x1c]; + //min_version = cp[0x1d]; + + unsigned xcase = Read16(&cp[0x16]); + if (xcase & 0x8000) + { + // gsos technote #8 + unsigned mask = 0x4000; + for (unsigned i = 0; i < name_length; i++) + { + if (xcase & mask) volume_name[i] = tolower(volume_name[i]); + mask = mask >> 1; + } + } + + + access = cp[0x1e]; + + entry_length = cp[0x1f]; + + entries_per_block = cp[0x20]; + + file_count = Read16(&cp[0x21]); + + bit_map_pointer = Read16(&cp[0x23]); + + total_blocks = Read16(&cp[0x25]); + + return true; +} + + + + +bool SubdirEntry::Load(const void *data) +{ + const uint8_t *cp = (const uint8_t *)data; + + + //prev_block = load16(&cp[0x00]); + //next_block = load16(&cp[0x02]); + + storage_type = cp[0x00] >> 4; + name_length = cp[0x00] & 0x0f; + + memcpy(subdir_name, &cp[0x01], name_length); + subdir_name[name_length] = 0; + + // 0x14 should be $14. + + // 0x145-0x1b reserved + + creation = ProDOS::DateTime(Read16(&cp[0x18]), Read16(&cp[0x1a])); + + //version = cp[0x1c]; + //min_version = cp[0x1d]; + /* + unsigned xcase = load16(&cp[0x1c]); + if (xcase & 0x8000) + { + // gsos technote #8 + unsigned mask = 0x4000; + for (unsigned i = 0; i < name_length; i++) + { + if (xcase & mask) subdir_name[i] = tolower(subdir_name[i]); + mask = mask >> 1; + } + } + */ + + access = cp[0x1e]; + + entry_length = cp[0x1f]; + + entries_per_block = cp[0x20]; + + file_count = Read16(&cp[0x21]); + + parent_pointer = Read16(&cp[0x23]); + + parent_entry = cp[0x25]; + + parent_entry_length = cp[0x26]; + + return true; +} diff --git a/ProDOS/File.h b/ProDOS/File.h new file mode 100644 index 0000000..4d76c86 --- /dev/null +++ b/ProDOS/File.h @@ -0,0 +1,133 @@ +/* + * File.h + * ProFUSE + * + * Created by Kelvin Sherlock on 12/18/08. + * + */ + +#ifndef __PRODOS_FILE_H__ +#define __PRODOS_FILE_H__ + +#include +#include + +enum { + DELETED_FILE = 0, + SEEDLING_FILE = 1, + SAPLING_FILE = 2, + TREE_FILE = 3, + PASCAL_FILE = 4, + EXTENDED_FILE = 5, + DIRECTORY_FILE = 0x0d, + SUBDIR_HEADER = 0x0e, + VOLUME_HEADER = 0x0f +}; + + +enum { + FILE_ENTRY_SIZE = 0x27, +}; + + +enum { + ACCESS_DESTROY = 0x80, + ACCESS_RENAME = 0x40, + ACCESS_MODIFIED = 0x20, + ACCESS_WRITE = 0x02, + ACCRESS_READ = 0x01 +}; + + +class FileEntry { +public: + + bool Load(const void *data); + + unsigned storage_type; + unsigned name_length; + char file_name[15 + 1]; + unsigned file_type; + unsigned key_pointer; + unsigned blocks_used; + uint32_t eof; + time_t creation; + //unsigned version; + //unsigned min_version; + unsigned access; + unsigned aux_type; + time_t last_mod; + unsigned header_pointer; + + uint32_t address; +}; + + + +struct MiniEntry { + + unsigned storage_type; + unsigned key_block; + unsigned blocks_used; + uint32_t eof; + +}; + +class ExtendedEntry { +public: + + bool Load(const void *data); + + MiniEntry dataFork; + MiniEntry resourceFork; + + uint8_t FInfo[16]; + uint8_t xFInfo[16]; +}; + + +class VolumeEntry { +public: + + bool Load(const void *data); + + unsigned storage_type; + unsigned name_length; + char volume_name[15+1]; + time_t creation; + time_t last_mod; + //unsigned version; + //unsigned min_version; + unsigned access; + unsigned entry_length; + unsigned entries_per_block; + unsigned file_count; + unsigned bit_map_pointer; + unsigned total_blocks; + + friend class DirIter; + +}; + +class SubdirEntry { +public: + + bool Load(const void *data); + + unsigned storage_type; + unsigned name_length; + char subdir_name[15+1]; + time_t creation; + //unsigned version; + //unsigned min_version; + unsigned access; + unsigned entry_length; + unsigned entries_per_block; + unsigned file_count; + unsigned parent_pointer; + unsigned parent_entry; + unsigned parent_entry_length; +}; + + +#endif diff --git a/ProDOS/Makefile b/ProDOS/Makefile deleted file mode 100644 index 84af29e..0000000 --- a/ProDOS/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -CC = g++ -CPPFLAGS += -g -Wall -I../ - - -all : DateTime.o - -DateTime.o : DateTime.cpp DateTime.h diff --git a/ProDOS/common.h b/ProDOS/common.h new file mode 100644 index 0000000..615bfbc --- /dev/null +++ b/ProDOS/common.h @@ -0,0 +1,18 @@ +/* + * common.h + * ProFUSE + * + * Created by Kelvin Sherlock on 12/20/08. + * + */ + +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include + +#define BLOCK_SIZE 512 + + +#endif + diff --git a/bin/profuse.cpp b/bin/profuse.cpp new file mode 100644 index 0000000..62dff80 --- /dev/null +++ b/bin/profuse.cpp @@ -0,0 +1,374 @@ +/* + * main.cpp + * ProFUSE + * + * Created by Kelvin Sherlock on 12/24/08. + * + */ +/* + +#define __FreeBSD__ 10 +#define _FILE_OFFSET_BITS 64 +#define __DARWIN_64_BIT_INO_T 1 +#define _REENTRANT +#define _POSIX_C_SOURCE 200112L +*/ + +#include +#include +#include +#include + +#include +#include + +#include + +#include + + +#include "profuse.h" + + + +using std::vector; +using std::string; +using std::tr1::shared_ptr; + + +/* + * globals variables. + * + */ + +std::string fDiskImage; + + +DiskPointer disk; +VolumeEntry volume; + +bool validProdosName(const char *name) +{ + // OS X looks for hidden files that don't exist (and aren't legal prodos names) + // most are not legal prodos names, so this filters them out easily. + + // [A-Za-z][0-9A-Za-z.]{0,14} + + if (!isalpha(*name)) return false; + + unsigned i; + for(i = 1; name[i]; i++) + { + char c = name[i]; + if (c == '.' || isalnum(c)) continue; + + return false; + + } + + return i < 16; +} + + + + + + + +static struct fuse_lowlevel_ops prodos_oper; + +enum { + PRODOS_OPT_HELP, + PRODOS_OPT_VERSION, + PRODOS_OPT_WRITE, + PRODOS_OPT_FORMAT, + PRODOS_OPT_VERBOSE +}; + +struct options { + char *format; + int readOnly; + int readWrite; + int verbose; + int debug; + +} options; + +#define PRODOS_OPT_KEY(T, P, V) {T, offsetof(struct options, P), V} + + +static struct fuse_opt prodos_opts[] = { + FUSE_OPT_KEY("-h", PRODOS_OPT_HELP), + FUSE_OPT_KEY("--help", PRODOS_OPT_HELP), + + FUSE_OPT_KEY("-V", PRODOS_OPT_VERSION), + FUSE_OPT_KEY("--version", PRODOS_OPT_VERSION), + + PRODOS_OPT_KEY("-v", verbose, 1), + + PRODOS_OPT_KEY("-w", readWrite, 1), + PRODOS_OPT_KEY("rw", readWrite, 1), + + PRODOS_OPT_KEY("-d", debug, 1), + + PRODOS_OPT_KEY("--format=%s", format, 0), + PRODOS_OPT_KEY("format=%s", format, 0), + {0, 0, 0} +}; + +static void usage() +{ + fprintf(stderr, "profuse [options] disk_image [mountpoint]\n" + + "Options:\n" + " -d debug\n" + " -r readonly\n" + " -w mount writable [not yet]\n" + " -v verbose\n" + " --format=format specify the disk image format. Valid values are:\n" + " dc42 DiskCopy 4.2 Image\n" + " davex Davex Disk Image\n" + " sdk ShrinkIt Disk Image\n" + " 2img Universal Disk Image\n" + " do DOS Order Disk Image\n" + " po ProDOS Order Disk Image (default)\n" + " -o opt1,opt2... other mount parameters.\n" + + ); +} + +static int prodos_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs) +{ + switch(key) + { + case PRODOS_OPT_HELP: + usage(); + exit(0); + break; + + case PRODOS_OPT_VERSION: + // TODO + exit(1); + break; + + case 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(string name, string &path) +{ + path = ""; + + if (name.find('/') != string::npos) return false; + if (name.find('\\') != string::npos) return false; + if (name.find(':') != string::npos) return false; + + 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[]) +{ + + struct fuse_args args = FUSE_ARGS_INIT(argc, argv); + struct fuse_chan *ch; + char *mountpoint = NULL; + int err = -1; + struct options options; + + unsigned format = 0; + + int foreground = false; + int multithread = false; + + +#if __APPLE__ + string mountpath; +#endif + + + + + std::memset(&prodos_oper, 0, sizeof(prodos_oper)); + + std::memset(&options, 0, sizeof(options)); + + + prodos_oper.listxattr = prodos_listxattr; + prodos_oper.getxattr = prodos_getxattr; + + prodos_oper.opendir = prodos_opendir; + prodos_oper.releasedir = prodos_releasedir; + prodos_oper.readdir = prodos_readdir; + + prodos_oper.lookup = prodos_lookup; + prodos_oper.getattr = prodos_getattr; + + prodos_oper.open = prodos_open; + prodos_oper.release = prodos_release; + prodos_oper.read = prodos_read; + + prodos_oper.statfs = prodos_statfs; + + + // scan the argument list, looking for the name of the disk image. + if (fuse_opt_parse(&args, &options , prodos_opts, prodos_opt_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) + { + std::fprintf(stderr, "Error: Unknown or unsupported device type.\n"); + exit(1); + } + + disk = Disk::OpenFile(device); + + if (!disk) + { + fprintf(stderr, "Unable to mount disk %s\n", fDiskImage.c_str()); + exit(1); + } + } + + catch (ProFUSE::Exception &e) + { + std::fprintf(stderr, "%s\n", e.what()); + std::fprintf(stderr, "%s\n", e.errorString()); + return -1; + } + + + + disk->ReadVolume(&volume, NULL); + +#ifdef __APPLE__ + { + // Macfuse supports custom volume names (displayed in Finder) + string str="-ovolname="; + str += volume.volume_name; + fuse_opt_add_arg(&args, str.c_str()); + } +#endif + + + // use 512byte blocks. + #if __APPLE__ + fuse_opt_add_arg(&args, "-oiosize=512"); + #endif + + do { + + if (fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) == -1) break; + +#ifdef __APPLE__ + + if (mountpoint == NULL || *mountpoint == 0) + { + if (make_mount_dir(volume.volume_name, mountpath)) + mountpoint = (char *)mountpath.c_str(); + } + +#endif + + foreground = options.debug; + + + if (mountpoint == NULL || *mountpoint == 0) + { + fprintf(stderr, "no mount point\n"); + break; + } + + + + if ( (ch = fuse_mount(mountpoint, &args)) != NULL) + { + struct fuse_session *se; + + se = fuse_lowlevel_new(&args, &prodos_oper, sizeof(prodos_oper), NULL); + if (se != NULL) 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); + } + + } while (false); + + fuse_opt_free_args(&args); + + disk.reset(); + + +#ifdef __APPLE__ + if (mountpath.size()) rmdir(mountpath.c_str()); +#endif + + return err ? 1 : 0; +} diff --git a/bin/profuse.h b/bin/profuse.h new file mode 100644 index 0000000..999c213 --- /dev/null +++ b/bin/profuse.h @@ -0,0 +1,62 @@ +/* + * profuse.h + * profuse + * + * Created by Kelvin Sherlock on 1/23/2009. + * + */ + +#ifndef __PROFUSE_H__ +#define __PROFUSE_H__ + +#include +#include +#include + + +#ifdef __APPLE__ +#define __FreeBSD__ 10 +#define __DARWIN_64_BIT_INO_T 1 +#endif + +#define _FILE_OFFSET_BITS 64 +#define FUSE_USE_VERSION 27 + +#include +#include + + +#undef ERROR +#define ERROR(cond,errno) if ( (cond) ){ fuse_reply_err(req, errno); return; } + + +extern DiskPointer disk; + +bool validProdosName(const char *name); + +// xattr +void prodos_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, size_t size, uint32_t off); +void prodos_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, size_t size); +void prodos_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size); + +//dirent +void prodos_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi); +void prodos_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi); +void prodos_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi); + +// stat +void prodos_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi); +void prodos_lookup(fuse_req_t req, fuse_ino_t parent, const char *name); + +void prodos_statfs(fuse_req_t req, fuse_ino_t ino); + + +// file io. +void prodos_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi); +void prodos_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi); +void prodos_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi); + + + +#endif + diff --git a/bin/profuse_dirent.cpp b/bin/profuse_dirent.cpp new file mode 100644 index 0000000..a124739 --- /dev/null +++ b/bin/profuse_dirent.cpp @@ -0,0 +1,130 @@ +/* + * profuse_dirent.cpp + * profuse + * + * Created by Kelvin Sherlock on 1/23/2009. + * + */ + +#include "profuse.h" + +#include +#include + +#include +#include +#include + +using std::string; +using std::vector; + +#pragma mark Directory Functions + +/* + * when the directory is opened, we load the volume/directory and store the FileEntry vector into + * fi->fh. + * + */ +void prodos_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) +{ + fprintf(stderr, "opendir: %u\n", (unsigned)ino); + // verify it's a directory/volume here? + + + uint8_t buffer[BLOCK_SIZE]; + vector files; + bool ok; + + + ok = disk->Read(ino == 1 ? 2 : ino >> 9, buffer); + ERROR(ok < 0, EIO) + + + if (ino == 1) + { + VolumeEntry v; + v.Load(buffer + 0x04); + + ok = disk->ReadVolume(&v, &files); + + ERROR(ok < 0, EIO) + } + else + { + + FileEntry e; + e.Load(buffer + (ino & 0x1ff)); + + ERROR(e.storage_type != DIRECTORY_FILE, ENOTDIR) + + ok = disk->ReadDirectory(e.key_pointer, NULL, &files); + + ERROR(ok < 0, EIO); + } + + // copy the vector contents to a vector *. + vector *fp = new vector(); + files.swap(*fp); + + fi->fh = (uint64_t)fp; + fuse_reply_open(req, fi); +} + +void prodos_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) +{ + fprintf(stderr,"releasedir: %u\n", (unsigned)ino); + vector *files = (vector *)fi->fh; + + if (files) delete files; + + fuse_reply_err(req, 0); +} + +void prodos_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) +{ + vector *files = (vector *)fi->fh; + struct stat st; + + fprintf(stderr, "readdir %u %u %u\n", (unsigned)ino, (unsigned)size, (unsigned)off); + + // TODO -- add "." and ".." entries... + + + // if the offset >= number of entries, get out. + if (!files || files->size() <= off) + { + fprintf(stderr, "fuse_reply_buf(req, NULL, 0)\n"); + fuse_reply_buf(req, NULL, 0); + return; + } + + + // now some dirent info... + + bzero(&st, sizeof(st)); + // only mode and ino are used. + + char *buffer = new char[size]; + + unsigned count = files->size(); + unsigned current_size = 0; + for (unsigned i = off; i < count; ++i) + { + FileEntry &f = (*files)[i]; + + st.st_mode = f.storage_type == DIRECTORY_FILE ? S_IFDIR | 0555 : S_IFREG | 0444; + st.st_ino = f.address; + + unsigned entry_size = fuse_add_direntry(req, NULL, 0, f.file_name, NULL, 0); + if (entry_size + current_size >= size) break; + + + fuse_add_direntry(req, (char *)buffer + current_size, size, f.file_name, &st, i + 1); + current_size += entry_size; + + } + + fuse_reply_buf(req, buffer, current_size); + delete []buffer; +} + diff --git a/bin/profuse_file.cpp b/bin/profuse_file.cpp new file mode 100644 index 0000000..69d5125 --- /dev/null +++ b/bin/profuse_file.cpp @@ -0,0 +1,136 @@ +/* + * profuse_file.cpp + * profuse + * + * Created by Kelvin Sherlock on 1/23/2009. + * + */ + +#include "profuse.h" +#include +#include + + +#pragma mark Read Functions + +void prodos_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) +{ + fprintf(stderr, "open: %u\n", (unsigned)ino); + + + uint8_t buffer[BLOCK_SIZE]; + int ok; + + FileEntry *e = NULL; + + ERROR(ino == 1, EISDIR) + + ok = disk->Read(ino >> 9, buffer); + ERROR(ok < 0, EIO) + + e = new FileEntry(); + e->Load(buffer + (ino & 0x1ff)); + + if (e->storage_type == EXTENDED_FILE) + { + ok = disk->Normalize(*e, 0); + + if (ok < 0) + { + delete e; + ERROR(true, EIO) + } + } + + // EXTENDED_FILE already handled (it would be an error here.) + switch(e->storage_type) + { + case SEEDLING_FILE: + case SAPLING_FILE: + case TREE_FILE: + break; + //case PASCAL_FILE: //? + case DIRECTORY_FILE: + delete e; + ERROR(true, EISDIR) + break; + default: + ERROR(true, EIO) + } + + if ( (fi->flags & O_ACCMODE) != O_RDONLY) + { + delete e; + ERROR(true, EACCES); + } + fi->fh = (uint64_t)e; + + fuse_reply_open(req, fi); +} + +void prodos_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) +{ + fprintf(stderr, "release: %u\n", (unsigned)ino); + + FileEntry *e = (FileEntry *)fi->fh; + + if (e) delete e; + + fuse_reply_err(req, 0); + +} + +void prodos_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) +{ + fprintf(stderr, "read: %u %u %u\n", (unsigned)ino, (unsigned)size, (unsigned)off); + + FileEntry *e = (FileEntry *)fi->fh; + + ERROR(e == NULL, EIO) + + if (off >= e->eof) + { + fuse_reply_buf(req, NULL, 0); + return; + } + + + unsigned level = 0; + switch(e->storage_type) + { + case TREE_FILE: + level = 2; + break; + case SAPLING_FILE: + level = 1; + break; + case SEEDLING_FILE: + level = 0; + break; + } + + // currently, reading is done on a block basis. + // experimentally, fuse reads the entire file + // this may not hold for larger files. + + + // TODO -- error if size + off > eof. + + unsigned blocks = (size + (off & 0x1ff) + BLOCK_SIZE - 1) >> 9; + int ok; + uint8_t *buffer = new uint8_t[blocks << 9]; + + fprintf(stderr, "ReadIndex(%x, buffer, %x, %x, %x)\n", e->key_pointer, level, (int)off, (int)blocks); + + ok = disk->ReadIndex(e->key_pointer, buffer, level, off, blocks); + if (ok < 0) + { + fuse_reply_err(req, EIO); + } + else + { + fuse_reply_buf(req, (const char *)buffer + (off & 0x1ff), size); + } + + delete []buffer; +} diff --git a/bin/profuse_stat.cpp b/bin/profuse_stat.cpp new file mode 100644 index 0000000..68e8546 --- /dev/null +++ b/bin/profuse_stat.cpp @@ -0,0 +1,252 @@ +/* + * prodos_stat.cpp + * profuse + * + * Created by Kelvin Sherlock on 1/23/2009. + * + */ + + +#pragma mark Stat Functions + +#include "profuse.h" +#include +#include +#include + +#include + +#include +#include + +using std::vector; + +int prodos_stat(FileEntry& e, struct stat *st) +{ + uint8_t buffer[BLOCK_SIZE]; + int ok; + + + if (e.storage_type == EXTENDED_FILE) + { + ok = disk->Normalize(e, 0); + if (ok < 0) return ok; + } + + st->st_blksize = BLOCK_SIZE; + + st->st_ctime = e.creation; +#ifdef HAVE_STAT_BIRTHTIME + st->st_birthtime = e.creation; +#endif + + st->st_mtime = e.last_mod; + st->st_atime = e.last_mod; + + + st->st_nlink = 1; + st->st_mode = 0444 | S_IFREG; + st->st_size = e.eof; + + + if (e.storage_type == DIRECTORY_FILE) + { + ok = disk->Read(e.key_pointer, buffer); + if (ok < 0) return -1; + + SubdirEntry se; + se.Load(buffer + 0x04); + + if (se.storage_type != SUBDIR_HEADER) return -1; + + st->st_mode = S_IFDIR | 0555; + st->st_size = BLOCK_SIZE; + st->st_nlink = se.file_count + 1; + + return 0; + } + + + switch(e.storage_type) + { + case SEEDLING_FILE: + case SAPLING_FILE: + case TREE_FILE: + //case PASCAL_FILE: + break; + + default: + return -1; + } + + return 0; +} + +int prodos_stat(const VolumeEntry &v, struct stat *st) +{ + + if (v.storage_type != VOLUME_HEADER) return -1; + + st->st_mode = S_IFDIR | 0555; + st->st_ctime = v.creation; + +#ifdef HAVE_STAT_BIRTHTIME + st->st_birthtime = v.creation; +#endif + st->st_mtime = v.last_mod; + st->st_atime = v.last_mod; + + st->st_nlink = v.file_count + 1; + st->st_size = BLOCK_SIZE; + st->st_blksize = BLOCK_SIZE; + + + return 1; +} + + +void prodos_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) +{ + uint8_t buffer[BLOCK_SIZE]; + struct stat st; + int ok; + + fprintf(stderr, "get_attr %u\n", (unsigned)ino); + + bzero(&st, sizeof(st)); + + /* + * ino 1 is the volume header. Others are pointers. + * + */ + + + ok = disk->Read(ino == 1 ? 2 : ino >> 9, buffer); + ERROR(ok < 0, EIO) + + // ino 1 is the volume header. + if (ino == 1) + { + VolumeEntry v; + v.Load(buffer + 0x04); + ok = prodos_stat(v, &st); + ERROR(ok < 0, EIO); + + st.st_ino = ino; + + fuse_reply_attr(req, &st, 0.0); + return; + } + else + { + + + FileEntry e; + e.Load(buffer + (ino & 0x1ff)); + ok = prodos_stat(e, &st); + + ERROR(ok < 0, EIO); + + st.st_ino = ino; + + fuse_reply_attr(req, &st, 0.0); // + } +} + + +// TODO -- add Disk::Lookup support so we don't have to parse the entire dir header. +// TODO -- add caching. +void prodos_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) +{ + uint8_t buffer[BLOCK_SIZE]; + struct fuse_entry_param entry; + int ok; + vector files; + + + fprintf(stderr, "lookup: %u %s\n", (unsigned)parent, name); + + ERROR(!validProdosName(name), ENOENT) + + ok = disk->Read(parent == 1 ? 2 : parent >> 9, buffer); + ERROR(ok < 0, EIO) + + bzero(&entry, sizeof(entry)); + + entry.attr_timeout = 0.0; + entry.entry_timeout = 0.0; + + // get the file list + // TODO -- Disk::look-up-one-file + if (parent == 1) + { + VolumeEntry v; + ok = disk->ReadVolume(&v, &files); + ERROR(ok < 0, EIO) + } + else + { + FileEntry e; + e.Load(buffer + (parent & 0x1ff)); + ERROR(e.storage_type != DIRECTORY_FILE, ENOENT); + + ok = disk->ReadDirectory(e.key_pointer, NULL, &files); + ERROR(ok < 0, EIO) + } + // ok, now go through the file list and look for a (case insensitive) match. + + + ok = -1; + unsigned name_length = strlen(name); + + for(vector::iterator iter = files.begin(); iter != files.end(); ++iter) + { + FileEntry& f = *iter; + if ( (f.name_length == name_length) && (strcasecmp(name, f.file_name) == 0)) + { + ok = prodos_stat(f, &entry.attr); + fprintf(stderr, "stat %s %x (%x %x) %d\n", f.file_name, f.address, f.address >> 9, f.address & 0x1ff, ok); + entry.ino = f.address; + entry.attr.st_ino = f.address; + break; + } + } + + ERROR(ok < 0, ENOENT); + + fprintf(stderr, "file found!\n"); + + fuse_reply_entry(req, &entry); +} + + + + +void prodos_statfs(fuse_req_t req, fuse_ino_t ino) +{ + struct statvfs vst; + + VolumeEntry volume; + + + disk->ReadVolume(&volume, NULL); + + // returns statvfs for the mount path or any file in the fs + // therefore, ignore ino. + std::memset(&vst, 0, sizeof(vst)); + + vst.f_bsize = 512; // fs block size + vst.f_frsize = 512; // fundamental fs block size + vst.f_blocks = volume.total_blocks; + vst.f_bfree = 0; // free blocks + vst.f_bavail = 0; // free blocks (non-root) + vst.f_files = 0; // ? + vst.f_ffree = -1; // free inodes. + vst.f_favail = -1; // free inodes (non-root) + vst.f_fsid = 0; // file system id? + vst.f_flag = ST_RDONLY | ST_NOSUID; + vst.f_namemax = 15; + + fuse_reply_statfs(req, &vst); +} + diff --git a/bin/profuse_xattr.cpp b/bin/profuse_xattr.cpp new file mode 100644 index 0000000..6159e86 --- /dev/null +++ b/bin/profuse_xattr.cpp @@ -0,0 +1,573 @@ +/* + * profuse_xattr.cpp + * profuse + * + * Created by Kelvin Sherlock on 1/23/2009. + * + */ + + +#include "profuse.h" + +#include +#include + +#include +#include +#include + +using std::string; + + +#ifdef __APPLE__ +#define NO_ATTRIBUTE ENOATTR +#else +#define NO_ATTRIBUTE EOPNOTSUPP +#endif + +static bool isTextFile(unsigned ftype, unsigned auxtype) +{ + if (ftype == 0x04) return true; // ascii text + if (ftype == 0xb0) return true; // source code. + if (ftype == 0x50 && auxtype == 0x5445) return true; // teach text + + return false; +} + + +static const char *mimeType(unsigned ftype, unsigned auxtype) +{ + switch(ftype) + { + case 0x04: + if (auxtype == 0) return "text/plain"; + break; + case 0xb0: + return "text/plain"; + break; + case 0x50: + if (auxtype == 0x5445) return "text/plain"; + break; + case 0xc0: + if (auxtype == 0x8006) return "image/gif"; + break; + case 0xe0: + if (auxtype == 0x8000) return "application/x-BinaryII"; + if (auxtype == 0x8002) return "application/x-Shrinkit"; + break; + } + return NULL; +} + + +static void setCreator(uint8_t *finfo, unsigned ftype, unsigned auxtype) +{ + + /* + + tech note PT515 + ProDOS -> Macintosh conversion + + ProDOS Macintosh + Filetype Auxtype Creator Filetype + $00 $0000 'pdos' 'BINA' + $B0 (SRC) (any) 'pdos' 'TEXT' + $04 (TXT) $0000 'pdos' 'TEXT' + $FF (SYS) (any) 'pdos' 'PSYS' + $B3 (S16) (any) 'pdos' 'PS16' + $uv $wxyz 'pdos' 'p' $uv $wx $yz + + Programmer's Reference for System 6.0: + + ProDOS Macintosh + File Type Auxiliary Type Creator Type File Type + $00 $0000 “pdos” “BINA” + $04 (TXT) $0000 “pdos” “TEXT” + $FF (SYS) (any) “pdos” “PSYS” + $B3 (S16) $DByz “pdos” “p” $B3 $DB $yz + $B3 (S16) (any) “pdos” “PS16” + $D7 $0000 “pdos” “MIDI” + $D8 $0000 “pdos” “AIFF” + $D8 $0001 “pdos” “AIFC” + $E0 $0005 “dCpy” “dImg” + $FF (SYS) (any) “pdos” “PSYS” + $uv $wxyz “pdos” “p” $uv $wx $yz + + + + */ + + finfo[0] = 'p'; + finfo[1] = ftype; + finfo[2] = auxtype >> 8; + finfo[3] = auxtype; + + memcpy(finfo + 4, "pdos", 4); + + switch (ftype) + { + case 0x00: + if (auxtype == 0) memcpy(finfo, "BINA", 4); + break; + + case 0x04: + if (auxtype == 0) memcpy(finfo, "TEXT", 4); + break; + + case 0x50: + if (auxtype == 0x5445) memcpy(finfo, "TEXT", 4); + break; + + case 0xb0: + memcpy(finfo, "TEXT", 4); + break; + + case 0xb3: + if ((auxtype >> 8) != 0xdb) memcpy(finfo, "PS16", 4); + break; + + case 0xd7: + if (auxtype == 0) memcpy(finfo, "MIDI", 4); + break; + + case 0xd8: + if (auxtype == 0) memcpy(finfo, "AIFF", 4); + if (auxtype == 1) memcpy(finfo, "AIFC", 4); + break; + + case 0xe0: + if (auxtype == 5) memcpy(finfo, "dImgdCpy", 8); + break; + + case 0xff: + memcpy(finfo, "PSYS", 4); + break; + } +} + + +#pragma mark XAttribute Functions + + +static void xattr_filetype(FileEntry& e, fuse_req_t req, size_t size, off_t off) +{ + uint8_t attr = e.file_type; + unsigned attr_size = 1; + + if (size == 0) + { + fuse_reply_xattr(req, attr_size); + return; + } + + ERROR (size < attr_size, ERANGE) + + // consider position here? + fuse_reply_buf(req, (char *)&attr, attr_size); +} + + +static void xattr_auxtype(FileEntry& e, fuse_req_t req, size_t size, off_t off) +{ + uint8_t attr[2]; + unsigned attr_size = 2; + + attr[0] = e.aux_type & 0xff; + attr[1] = (e.aux_type >> 8) & 0xff; + + if (size == 0) + { + fuse_reply_xattr(req, attr_size); + return; + } + + ERROR (size < attr_size, ERANGE) + + // consider position here? + fuse_reply_buf(req, (char *)&attr, attr_size); +} + +// user.charset +static void xattr_charset(FileEntry& e, fuse_req_t req, size_t size, off_t off) +{ + const char attr[] = "macintosh"; + unsigned attr_size = sizeof(attr) - 1; + + ERROR(!isTextFile(e.file_type, e.aux_type), NO_ATTRIBUTE) + + if (size == 0) + { + fuse_reply_xattr(req, attr_size); + return; + } + + ERROR (size < attr_size, ERANGE) + + fuse_reply_buf(req, (char *)&attr, attr_size); +} + +//apple.TextEncoding +static void xattr_textencoding(FileEntry& e, fuse_req_t req, size_t size, off_t off) +{ + const char attr[] = "MACINTOSH;0"; + unsigned attr_size = sizeof(attr) - 1; + + ERROR(!isTextFile(e.file_type, e.aux_type), NO_ATTRIBUTE) + + if (size == 0) + { + fuse_reply_xattr(req, attr_size); + return; + } + + ERROR (size < attr_size, ERANGE) + + fuse_reply_buf(req, (char *)&attr, attr_size); +} + +static void xattr_rfork(FileEntry& e, fuse_req_t req, size_t size, off_t off) +{ + int ok; + unsigned level; + + ERROR (e.storage_type != EXTENDED_FILE, NO_ATTRIBUTE) + + ok = disk->Normalize(e, 1); + ERROR(ok < 0, EIO) + + + switch(e.storage_type) + { + case SEEDLING_FILE: + level = 0; + break; + case SAPLING_FILE: + level = 1; + break; + case TREE_FILE: + level = 2; + break; + default: + ERROR(true, EIO) + } + + if (size == 0) + { + fuse_reply_xattr(req, e.eof); + return; + } + + size = std::min((uint32_t)(size + off), e.eof); + + unsigned blocks = (size + (off & 0x1ff) + BLOCK_SIZE - 1) >> 9; + uint8_t *buffer = new uint8_t[blocks << 9]; + + fprintf(stderr, "ReadIndex(%x, buffer, %x, %x, %x)\n", e.key_pointer, level, (int)off, (int)blocks); + + ok = disk->ReadIndex(e.key_pointer, buffer, level, off, blocks); + + if (ok < 0) + { + fuse_reply_err(req, EIO); + } + else + { + fuse_reply_buf(req, (char *)buffer + (off & 0x1ff), size); + } + delete []buffer; + return; +} + + + +// Finder info. +static void xattr_finfo(FileEntry& e, fuse_req_t req, size_t size, off_t off) +{ + int ok; + ExtendedEntry ee; + + uint8_t attr[32]; + unsigned attr_size = 32; + + //ERROR (e.storage_type != EXTENDED_FILE, ENOENT) + + switch (e.storage_type) + { + case SEEDLING_FILE: + case SAPLING_FILE: + case TREE_FILE: + + if (size == 0) + { + fuse_reply_xattr(req, attr_size); + return; + } + + bzero(attr, attr_size); + setCreator(attr, e.file_type, e.aux_type); + fuse_reply_buf(req, (char *)attr, attr_size); + return; + + case EXTENDED_FILE: + // handled below. + break; + + default: + ERROR(true, NO_ATTRIBUTE); + } + + + ok = disk->Normalize(e, 1, &ee); + ERROR(ok < 0, EIO) + + // sanity check + switch(e.storage_type) + { + case SEEDLING_FILE: + case SAPLING_FILE: + case TREE_FILE: + break; + default: + ERROR(true, EIO) + } + + if (size == 0) + { + fuse_reply_xattr(req, attr_size); + return; + } + + ERROR (size < attr_size, ERANGE) + + memcpy(attr, ee.FInfo, 16); + memcpy(attr + 16, ee.xFInfo, 16); + + // if no creator, create one. + if (memcmp(attr, "\0\0\0\0\0\0\0\0", 8) == 0) + setCreator(attr, e.file_type, e.aux_type); + + fuse_reply_buf(req, (char *)attr, attr_size); +} + + +static void xattr_mimetype(FileEntry& e, fuse_req_t req, size_t size, off_t off) +{ + unsigned attr_size; + const char *mime = mimeType(e.file_type, e.aux_type); + ERROR(!mime, NO_ATTRIBUTE); + + attr_size = strlen(mime); + + if (size == 0) + { + fuse_reply_xattr(req, attr_size); + return; + } + + ERROR (size < attr_size, ERANGE) + + fuse_reply_buf(req, mime, attr_size); +} + + + +void prodos_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) +{ + // list of supported attributes. + // +#define NO_ATTR() \ +{ \ +if (size) fuse_reply_buf(req, NULL, 0); \ +else fuse_reply_xattr(req, 0); \ +return; \ +} + + fprintf(stderr, "listxattr %u\n", (unsigned)ino); + + uint8_t buffer[BLOCK_SIZE]; + int ok; + unsigned attr_size; + string attr; + + + + if(ino == 1) + NO_ATTR() + + ok = disk->Read(ino >> 9, buffer); + + ERROR(ok < 0, EIO) + + + FileEntry e; + e.Load(buffer + (ino & 0x1ff)); + + + attr += "prodos.FileType"; + attr.append(1, 0); + + attr += "prodos.AuxType"; + attr.append(1, 0); + + switch(e.storage_type) + { + case EXTENDED_FILE: + { + // TODO -- pretend there's no resource fork if resource fork eof == 0 ? + // + //ok = disk->Normalize(e, 1); + //ERROR(ok < 0, EIO) + + attr += "prodos.ResourceFork"; + attr.append(1, 0); + + attr += "com.apple.FinderInfo"; + attr.append(1, 0); + break; + } + + case SEEDLING_FILE: + case SAPLING_FILE: + case TREE_FILE: + // generate HFS creator codes. + attr += "com.apple.FinderInfo"; + attr.append(1, 0); + break; + + case DIRECTORY_FILE: + NO_ATTR() + break; + + default: + + NO_ATTR() + break; + } + + if (isTextFile(e.file_type, e.aux_type)) + { + attr += "com.apple.TextEncoding"; + attr.append(1, 0); + + attr += "user.charset"; + attr.append(1, 0); + } + + if (mimeType(e.file_type, e.aux_type)) + { + attr += "user.mime_type"; + attr.append(1, 0); + } + + attr_size = attr.length(); + + fprintf(stderr, "%d %s\n", attr_size, attr.c_str()); + + if (size == 0) + { + fuse_reply_xattr(req, attr_size); + return; + } + + if (size < attr_size) + { + fuse_reply_err(req, ERANGE); + return; + } + + fuse_reply_buf(req, attr.data(), attr_size); + return; +} + +/* + * offset is only valid in OS X for the resource fork. + * + */ +void prodos_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, size_t size, uint32_t off) +{ + + + fprintf(stderr, "getxattr: %u %s %u %u \n", (unsigned)ino, name, (unsigned)size, (unsigned)off); + + uint8_t buffer[BLOCK_SIZE]; + + + ERROR(ino == 1, NO_ATTRIBUTE) // finder can't handle EISDIR. + + + int ok = disk->Read(ino >> 9, buffer); + + ERROR(ok < 0, EIO) + + + FileEntry e; + e.Load(buffer + (ino & 0x1ff)); + + switch(e.storage_type) + { + case SEEDLING_FILE: + case SAPLING_FILE: + case TREE_FILE: + case EXTENDED_FILE: + break; + case DIRECTORY_FILE: + ERROR(true, NO_ATTRIBUTE) // Finder can't handle EISDIR. + default: + ERROR(true, NO_ATTRIBUTE); + } + + if (strcmp("prodos.FileType", name) == 0) + { + xattr_filetype(e, req, size, off); + return; + } + + if (strcmp("prodos.AuxType", name) == 0) + { + xattr_auxtype(e, req, size, off); + return; + } + + if (strcmp("com.apple.TextEncoding", name) == 0) + { + xattr_textencoding(e, req, size, off); + return; + } + + if ( (e.storage_type == EXTENDED_FILE) && (strcmp("prodos.ResourceFork", name) == 0)) + { + xattr_rfork(e, req, size, off); + return; + } + + if ( strcmp("com.apple.FinderInfo", name) == 0) + { + xattr_finfo(e, req, size, off); + return; + } + + // linux standard + if (strcmp("user.mime_type", name) == 0) + { + xattr_mimetype(e, req, size, off); + return; + } + + // linux standard + if (strcmp("user.charset", name) == 0) + { + xattr_charset(e, req, size, off); + return; + } + + fuse_reply_err(req, NO_ATTRIBUTE); + +} +/* + * Linux, et alia do not have an offset parameter. + */ +void prodos_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, size_t size) +{ + prodos_getxattr(req, ino, name, size, 0); +} + From ad6fd87c3e61d16920cea7c8c78cb0f00095bc36 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 14 Mar 2011 15:51:53 +0000 Subject: [PATCH 219/236] clean up c++ headers git-svn-id: https://profuse.googlecode.com/svn/branches/v2@387 aa027e90-d47c-11dd-86d7-074df07e0730 --- ProDOS/Disk.cpp | 4 ++-- ProDOS/File.cpp | 7 ++++--- bin/profuse_dirent.cpp | 4 +++- bin/profuse_file.cpp | 4 ++-- bin/profuse_stat.cpp | 7 ++++--- bin/profuse_xattr.cpp | 6 ++++-- 6 files changed, 19 insertions(+), 13 deletions(-) diff --git a/ProDOS/Disk.cpp b/ProDOS/Disk.cpp index 0270073..7f6d7c3 100644 --- a/ProDOS/Disk.cpp +++ b/ProDOS/Disk.cpp @@ -16,8 +16,8 @@ #include #include -#include -#include +#include +#include #include #include diff --git a/ProDOS/File.cpp b/ProDOS/File.cpp index 985d8a4..ddea416 100644 --- a/ProDOS/File.cpp +++ b/ProDOS/File.cpp @@ -11,10 +11,11 @@ #include #include "common.h" -#include +#include +#include +#include + #include -#include -#include using namespace LittleEndian; diff --git a/bin/profuse_dirent.cpp b/bin/profuse_dirent.cpp index a124739..cf3aeec 100644 --- a/bin/profuse_dirent.cpp +++ b/bin/profuse_dirent.cpp @@ -8,9 +8,11 @@ #include "profuse.h" -#include #include +#include +#include + #include #include #include diff --git a/bin/profuse_file.cpp b/bin/profuse_file.cpp index 69d5125..7a4f88f 100644 --- a/bin/profuse_file.cpp +++ b/bin/profuse_file.cpp @@ -7,8 +7,8 @@ */ #include "profuse.h" -#include -#include +#include +#include #pragma mark Read Functions diff --git a/bin/profuse_stat.cpp b/bin/profuse_stat.cpp index 68e8546..6b2eef0 100644 --- a/bin/profuse_stat.cpp +++ b/bin/profuse_stat.cpp @@ -10,9 +10,10 @@ #pragma mark Stat Functions #include "profuse.h" -#include -#include -#include + +#include +#include +#include #include diff --git a/bin/profuse_xattr.cpp b/bin/profuse_xattr.cpp index 6159e86..5b65a08 100644 --- a/bin/profuse_xattr.cpp +++ b/bin/profuse_xattr.cpp @@ -12,8 +12,10 @@ #include #include -#include -#include +#include +#include +#include + #include using std::string; From 02e3c4c532a46a8d21c9b9792c1be546cdf1aab6 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 14 Mar 2011 22:17:49 +0000 Subject: [PATCH 220/236] move around exceptions, ProFUSE -> Common git-svn-id: https://profuse.googlecode.com/svn/branches/v2@388 aa027e90-d47c-11dd-86d7-074df07e0730 --- Common/Exception.cpp | 44 +++++++++++++ Common/Exception.h | 36 +++++++++++ {ProFUSE => Common}/Lock.cpp | 3 +- {ProFUSE => Common}/Lock.h | 3 - {ProFUSE => Common}/Makefile | 0 {ProFUSE => Common}/auto.h | 2 - {ProFUSE => Common}/smart_pointers.h | 4 +- NuFX/Exception.cpp | 10 +++ NuFX/Exception.h | 35 ++++++++++ POSIX/Exception.cpp | 13 ++++ POSIX/Exception.h | 34 ++++++++++ {ProFUSE => ProDOS}/Exception.cpp | 25 ++----- {ProFUSE => ProDOS}/Exception.h | 93 +++++---------------------- libNuFX.a | Bin 0 -> 1624216 bytes 14 files changed, 195 insertions(+), 107 deletions(-) create mode 100644 Common/Exception.cpp create mode 100644 Common/Exception.h rename {ProFUSE => Common}/Lock.cpp (85%) rename {ProFUSE => Common}/Lock.h (94%) rename {ProFUSE => Common}/Makefile (100%) rename {ProFUSE => Common}/auto.h (98%) rename {ProFUSE => Common}/smart_pointers.h (91%) create mode 100644 NuFX/Exception.cpp create mode 100644 NuFX/Exception.h create mode 100644 POSIX/Exception.cpp create mode 100644 POSIX/Exception.h rename {ProFUSE => ProDOS}/Exception.cpp (92%) rename {ProFUSE => ProDOS}/Exception.h (51%) create mode 100644 libNuFX.a diff --git a/Common/Exception.cpp b/Common/Exception.cpp new file mode 100644 index 0000000..5295312 --- /dev/null +++ b/Common/Exception.cpp @@ -0,0 +1,44 @@ + +#include "Exception.h" +#include +#include + + +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() +{ + return _string.c_str(); +} + +const char *Exception::errorString() +{ + return ""; +} diff --git a/Common/Exception.h b/Common/Exception.h new file mode 100644 index 0000000..3377cac --- /dev/null +++ b/Common/Exception.h @@ -0,0 +1,36 @@ +#ifndef __COMMON_EXCEPTION_H__ +#define __COMMON_EXCEPTION_H__ + +#include +#include + + +class Exception : public std::exception +{ +public: + Exception(const char *cp); + Exception(const std::string &str); + + + virtual ~Exception() throw (); + + virtual const char *what(); + virtual const char *errorString(); + + int error() const { return _error; } + +protected: + Exception(const char *cp, int error); + Exception(const std::string& string, int error); + +private: + int _error; + std::string _string; + +}; + + + + + +#endif \ No newline at end of file diff --git a/ProFUSE/Lock.cpp b/Common/Lock.cpp similarity index 85% rename from ProFUSE/Lock.cpp rename to Common/Lock.cpp index 7f6130c..7ef6acf 100644 --- a/ProFUSE/Lock.cpp +++ b/Common/Lock.cpp @@ -1,6 +1,5 @@ -#include +#include "Lock.h" -using namespace ProFUSE; Lock::Lock() { diff --git a/ProFUSE/Lock.h b/Common/Lock.h similarity index 94% rename from ProFUSE/Lock.h rename to Common/Lock.h index 8e32a80..246cf08 100644 --- a/ProFUSE/Lock.h +++ b/Common/Lock.h @@ -3,7 +3,6 @@ #include -namespace ProFUSE { class Lock { public: @@ -28,6 +27,4 @@ private: }; -} - #endif diff --git a/ProFUSE/Makefile b/Common/Makefile similarity index 100% rename from ProFUSE/Makefile rename to Common/Makefile diff --git a/ProFUSE/auto.h b/Common/auto.h similarity index 98% rename from ProFUSE/auto.h rename to Common/auto.h index e7c6876..8610d84 100644 --- a/ProFUSE/auto.h +++ b/Common/auto.h @@ -3,7 +3,6 @@ #include -namespace ProFUSE { template class auto_array @@ -98,7 +97,6 @@ private: }; #endif -} #endif diff --git a/ProFUSE/smart_pointers.h b/Common/smart_pointers.h similarity index 91% rename from ProFUSE/smart_pointers.h rename to Common/smart_pointers.h index 6ab4ecd..eee7fab 100644 --- a/ProFUSE/smart_pointers.h +++ b/Common/smart_pointers.h @@ -1,6 +1,6 @@ -#ifndef __PROFUSE_SMART_POINTERS_H__ -#define __PROFUSE_SMART_POINTERS_H__ +#ifndef __COMMON_SMART_POINTERS_H__ +#define __COMMON_SMART_POINTERS_H__ #ifdef CPP0X //C++0x diff --git a/NuFX/Exception.cpp b/NuFX/Exception.cpp new file mode 100644 index 0000000..60d9878 --- /dev/null +++ b/NuFX/Exception.cpp @@ -0,0 +1,10 @@ +#include "Exception.h" + +namespace NuFX { + +const char *NuFX::Exception::errorString() +{ + return ::NuStrError((NuError)error()); +} + +} \ No newline at end of file diff --git a/NuFX/Exception.h b/NuFX/Exception.h new file mode 100644 index 0000000..04ca32b --- /dev/null +++ b/NuFX/Exception.h @@ -0,0 +1,35 @@ +#ifndef __NUFX_EXCEPTION_H__ +#define __NUFX_EXCEPTION_H__ + +#include +#include + +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 \ No newline at end of file diff --git a/POSIX/Exception.cpp b/POSIX/Exception.cpp new file mode 100644 index 0000000..5670956 --- /dev/null +++ b/POSIX/Exception.cpp @@ -0,0 +1,13 @@ + +#include "Exception.h" +#include +#include + +namespace POSIX { + +const char *Exception::errorString() +{ + return strerror(error()); +} + +} \ No newline at end of file diff --git a/POSIX/Exception.h b/POSIX/Exception.h new file mode 100644 index 0000000..016e8e4 --- /dev/null +++ b/POSIX/Exception.h @@ -0,0 +1,34 @@ +#ifndef __POSIX_EXCEPTION_H__ +#define __POSIX_EXCEPTION_H__ + +#include + +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 \ No newline at end of file diff --git a/ProFUSE/Exception.cpp b/ProDOS/Exception.cpp similarity index 92% rename from ProFUSE/Exception.cpp rename to ProDOS/Exception.cpp index 512a4d2..fe71da5 100644 --- a/ProFUSE/Exception.cpp +++ b/ProDOS/Exception.cpp @@ -1,33 +1,14 @@ -#include +#include "Exception.h" #include #include -using namespace ProFUSE; +namespace ProDOS { -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()) { @@ -147,3 +128,5 @@ const char *ProDOSException::errorString() } return ""; } + +} diff --git a/ProFUSE/Exception.h b/ProDOS/Exception.h similarity index 51% rename from ProFUSE/Exception.h rename to ProDOS/Exception.h index caa9964..b89bf39 100644 --- a/ProFUSE/Exception.h +++ b/ProDOS/Exception.h @@ -1,10 +1,9 @@ -#ifndef __EXCEPTION_H__ -#define __EXCEPTION_H__ +#ifndef __PRODOS_EXCEPTION_H__ +#define __PRODOS_EXCEPTION_H__ -#include -#include +#include -namespace ProFUSE { +namespace ProDOS { // ProDOS Errors @@ -67,87 +66,27 @@ enum resAddErr = 0x71 }; -class Exception : public std::exception -{ + +class Exception : public ::Exception { public: - Exception(const char *cp); - Exception(const std::string &str); - - - virtual ~Exception() throw (); - - virtual const char *what(); - virtual const char *errorString(); - - int error() const { return _error; } - -protected: Exception(const char *cp, int error); Exception(const std::string& string, int error); - -private: - int _error; - std::string _string; - -}; - -class POSIXException : public Exception { -public: - POSIXException(const char *cp, int error); - POSIXException(const std::string& string, int error); - - virtual const char *errorString(); -}; - -class ProDOSException : public Exception { -public: - ProDOSException(const char *cp, int error); - ProDOSException(const std::string& string, int error); virtual const char *errorString(); + +private: + typedef ::Exception super; }; -inline Exception::Exception(const char *cp): - _error(0), - _string(cp) + + +inline Exception::Exception(const char *cp, int error) : + super(cp, 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) +inline Exception::Exception(const std::string& string, int error) : + super(string, error) { } @@ -155,4 +94,4 @@ inline ProDOSException::ProDOSException(const std::string& string, int error) : } -#endif \ No newline at end of file +#endif diff --git a/libNuFX.a b/libNuFX.a new file mode 100644 index 0000000000000000000000000000000000000000..c715ef52df10e67a2654f3f5f5967277b553c6de GIT binary patch literal 1624216 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

S9Mo$#j~zkBPX?SnU_uMCzqoLxG2T4L_2cYVF( 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

E%Q|3s?i<*1v1`a%J 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

o{?k3?nTD}z2sldb?z>v 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

IxIjyI5JdBA~;U+sm8?_f7i|9=MJ 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%0AT4r2pbjP)8Ei)z3b;Lr)V$a}P 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:v_j>wNpUDwZXWDjH3tJFfkCf|`h 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 IWP))2ANZqZ^#A|> literal 0 HcmV?d00001 From b4db3e59ab936257820a7ee0a4e394a357c022d1 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 14 Mar 2011 23:08:19 +0000 Subject: [PATCH 221/236] rename ProFUSE:: -> Common:: git-svn-id: https://profuse.googlecode.com/svn/branches/v2@389 aa027e90-d47c-11dd-86d7-074df07e0730 --- Cache/BlockCache.cpp | 6 +-- Cache/ConcreteBlockCache.cpp | 6 +-- Cache/MappedBlockCache.cpp | 10 ++-- Device/Adaptor.cpp | 20 ++++---- Device/BlockDevice.cpp | 7 ++- Device/BlockDevice.h | 4 +- Device/DavexDiskImage.cpp | 4 +- Device/Device.h | 2 +- Device/DiskCopy42Image.cpp | 5 +- Device/DiskImage.cpp | 18 ++++--- Device/DiskImage.h | 2 - Device/RawDevice.cpp | 57 +++++++++++------------ Device/SDKImage.cpp | 35 +------------- Device/UniversalDiskImage.cpp | 8 +--- File/File.cpp | 16 +++---- File/MappedFile.cpp | 22 ++++----- Makefile | 88 ++++++++++++++++++++++------------- Pascal/Entry.cpp | 2 +- Pascal/Entry.h | 2 +- Pascal/FileEntry.cpp | 11 +++-- Pascal/TextWriter.cpp | 4 +- Pascal/VolumeEntry.cpp | 34 +++++++------- bin/apfm.cpp | 2 +- bin/fuse_pascal.cpp | 10 ++-- bin/fuse_pascal_ops.cpp | 12 +++-- bin/newfs_pascal.cpp | 10 ++-- bin/profuse.cpp | 2 +- 27 files changed, 178 insertions(+), 221 deletions(-) diff --git a/Cache/BlockCache.cpp b/Cache/BlockCache.cpp index 3c24d2a..7811e20 100644 --- a/Cache/BlockCache.cpp +++ b/Cache/BlockCache.cpp @@ -11,16 +11,14 @@ #include #include -#include -#include +#include +#include using namespace Device; -using ProFUSE::Exception; -using ProFUSE::POSIXException; BlockCache::BlockCache(BlockDevicePointer device) : diff --git a/Cache/ConcreteBlockCache.cpp b/Cache/ConcreteBlockCache.cpp index ef8c6b1..62a788f 100644 --- a/Cache/ConcreteBlockCache.cpp +++ b/Cache/ConcreteBlockCache.cpp @@ -10,8 +10,8 @@ #include #include -#include -#include +#include +#include /* @@ -51,8 +51,6 @@ using namespace Device; -using ProFUSE::Exception; -using ProFUSE::POSIXException; //typedef std::vector::iterator EntryIter; diff --git a/Cache/MappedBlockCache.cpp b/Cache/MappedBlockCache.cpp index bf0892b..973fb05 100644 --- a/Cache/MappedBlockCache.cpp +++ b/Cache/MappedBlockCache.cpp @@ -10,14 +10,12 @@ #include #include -#include - +#include +#include using namespace Device; -using ProFUSE::Exception; -using ProFUSE::POSIXException; BlockCachePointer MappedBlockCache::Create(BlockDevicePointer device, void *data) { @@ -124,12 +122,12 @@ void MappedBlockCache::sync(unsigned block) end = (void *)((ptrdiff_t)end / pagesize * pagesize); if (::msync(start, pagesize, MS_SYNC) != 0) - throw POSIXException(__METHOD__ ": msync", errno); + throw POSIX::Exception(__METHOD__ ": msync", errno); if (start != end) { if (::msync(end, pagesize, MS_SYNC) != 0) - throw POSIXException(__METHOD__ ": msync", errno); + throw POSIX::Exception(__METHOD__ ": msync", errno); } } diff --git a/Device/Adaptor.cpp b/Device/Adaptor.cpp index 7410611..7b99083 100644 --- a/Device/Adaptor.cpp +++ b/Device/Adaptor.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include using namespace Device; @@ -142,7 +142,7 @@ uint8_t NibbleAdaptor::encode62(uint8_t val) }; if (val > 0x3f) - throw ProFUSE::Exception(__METHOD__ ": Invalid 6-2 value."); + throw ::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 ProFUSE::Exception(__METHOD__ ": Invalid 6-2 encoding."); + throw ::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 ProFUSE::Exception(__METHOD__ ": Invalid address checksum."); + throw ::Exception(__METHOD__ ": Invalid address checksum."); if (track > 35 || sector > 16) - throw ProFUSE::Exception(__METHOD__ ": Invalid track/sector."); + throw ::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 ProFUSE::Exception(__METHOD__ ": Sector missing."); + //throw ::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 ProFUSE::Exception(__METHOD__ ": Invalid track/sector."); + throw ::Exception(__METHOD__ ": Invalid track/sector."); CircleBuffer buffer(_address, _length); @@ -374,7 +374,7 @@ void NibbleAdaptor::readTrackSector(TrackSector ts, void *bp) if (offset == -1) { - throw ProFUSE::Exception(__METHOD__ ": Missing track/sector."); + throw ::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 ProFUSE::Exception(__METHOD__ ": Invalid field checksum."); + //throw ::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 ProFUSE::Exception(__METHOD__ ": Invalid track/sector."); + throw ::Exception(__METHOD__ ": Invalid track/sector."); uint8_t auxBuffer[86]; uint8_t checksum = 0; diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index 6ac1d9e..15becd0 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -12,7 +12,8 @@ #include #include -#include +#include +#include #include #include @@ -26,8 +27,6 @@ using namespace Device; -using ProFUSE::Exception; -using ProFUSE::POSIXException; unsigned BlockDevice::ImageType(MappedFile *f, unsigned defv) @@ -124,7 +123,7 @@ BlockDevicePointer BlockDevice::Open(const char *name, File::FileFlags flags, un if (::stat(name, &st) != 0) { - throw POSIXException(__METHOD__ ": stat error", errno); + throw POSIX::Exception(__METHOD__ ": stat error", errno); } // /dev/xxx ignore the type. diff --git a/Device/BlockDevice.h b/Device/BlockDevice.h index 4b31e71..2f23f8a 100644 --- a/Device/BlockDevice.h +++ b/Device/BlockDevice.h @@ -7,8 +7,8 @@ #include #include -#include -#include +#include +#include #include diff --git a/Device/DavexDiskImage.cpp b/Device/DavexDiskImage.cpp index f9e44ab..ea2b813 100644 --- a/Device/DavexDiskImage.cpp +++ b/Device/DavexDiskImage.cpp @@ -19,8 +19,6 @@ using namespace Device; using namespace LittleEndian; -using ProFUSE::Exception; -using ProFUSE::POSIXException; /* http://www.umich.edu/~archive/apple2/technotes/ftn/FTN.E0.8004 @@ -86,7 +84,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; } diff --git a/Device/Device.h b/Device/Device.h index 458320c..efb49db 100644 --- a/Device/Device.h +++ b/Device/Device.h @@ -9,7 +9,7 @@ #ifndef __DEVICE_DEVICE_H__ #define __DEVICE_DEVICE_H__ -#include +#include namespace Device { diff --git a/Device/DiskCopy42Image.cpp b/Device/DiskCopy42Image.cpp index 9498720..1665a54 100644 --- a/Device/DiskCopy42Image.cpp +++ b/Device/DiskCopy42Image.cpp @@ -16,9 +16,6 @@ using namespace Device; using namespace BigEndian; -using ProFUSE::Exception; -using ProFUSE::POSIXException; - enum { @@ -221,7 +218,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; } diff --git a/Device/DiskImage.cpp b/Device/DiskImage.cpp index a1c15b9..4eae7b7 100644 --- a/Device/DiskImage.cpp +++ b/Device/DiskImage.cpp @@ -14,13 +14,11 @@ #include -#include +#include using namespace Device; -using ProFUSE::Exception; -using ProFUSE::POSIXException; /* @@ -74,7 +72,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); } @@ -85,7 +83,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); } @@ -97,7 +95,7 @@ void DiskImage::sync() if (_file.isValid()) return _file.sync(); - throw Exception(__METHOD__ ": File not set."); + throw ::Exception(__METHOD__ ": File not set."); } @@ -147,10 +145,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; } @@ -218,11 +216,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; } diff --git a/Device/DiskImage.h b/Device/DiskImage.h index 25a5c39..8a1b786 100644 --- a/Device/DiskImage.h +++ b/Device/DiskImage.h @@ -4,8 +4,6 @@ #include #include -#include - #include #include diff --git a/Device/RawDevice.cpp b/Device/RawDevice.cpp index 96f10b3..0cf846d 100644 --- a/Device/RawDevice.cpp +++ b/Device/RawDevice.cpp @@ -31,12 +31,11 @@ #include -#include +#include +#include using namespace Device; -using ProFUSE::Exception; -using ProFUSE::POSIXException; #ifdef __SUN__ void RawDevice::devSize(int fd) @@ -47,7 +46,7 @@ void RawDevice::devSize(int fd) struct dk_minfo minfo; if (::ioctl(fd, DKIOCGMEDIAINFO, &minfo) < 0) - throw POSIXException(__METHOD__ ": Unable to determine device size.", errno); + throw POSIX::Exception(__METHOD__ ": Unable to determine device size.", errno); _size = minfo.dki_lbsize * minfo.dki_capacity; _blockSize = 512; // not really, but whatever. @@ -66,11 +65,11 @@ void RawDevice::devSize(int fd) uint64_t blockCount; // 64 bit if (::ioctl(fd, DKIOCGETBLOCKSIZE, &blockSize) < 0) - throw POSIXException(__METHOD__ ": Unable to determine block size.", errno); + throw POSIX::Exception(__METHOD__ ": Unable to determine block size.", errno); if (::ioctl(fd, DKIOCGETBLOCKCOUNT, &blockCount) < 0) - throw POSIXException(__METHOD__ ": Unable to determine block count.", errno); + throw POSIX::Exception(__METHOD__ ": Unable to determine block count.", errno); _blockSize = blockSize; _size = _blockSize * blockCount; @@ -90,7 +89,7 @@ void RawDevice::devSize(int fd) int blocks; if (::ioctl(fd, BLKGETSIZE, &blocks) < 0) - throw POSIXException(__METHOD__ ": Unable to determine device size.", errno); + throw POSIX::Exception(__METHOD__ ": Unable to determine device size.", errno); _size = 512 * blocks; _blockSize = 512; // @@ -113,10 +112,10 @@ void RawDevice::devSize(int fd) off_t mediaSize; if (::ioctl(fd, DIOCGSECTORSIZE, &blockSize) - throw POSIXException(__METHOD__ ": Unable to determine block size.", errno); + throw POSIX::Exception(__METHOD__ ": Unable to determine block size.", errno); if (::ioctl(fd, DIOCGMEDIASIZE, &mediaSize) - throw POSIXException(__METHOD__ ": Unable to determine media size.", errno); + throw POSIX::Exception(__METHOD__ ": Unable to determine media size.", errno); _blockSize = blockSize; _size = mediaSize; @@ -138,7 +137,7 @@ void RawDevice::devSize(int fd) if (::ioctl(fd, DIOCGETP, &entry) < 0) - throw POSIXException(__METHOD__ ": Unable to determine device size.", errno); + throw POSIX::Exception(__METHOD__ ": Unable to determine device size.", errno); _size = entry.size _blockSize = 512; // not really but whatever. @@ -157,7 +156,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; @@ -178,7 +177,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; @@ -208,8 +207,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) ? @@ -220,8 +219,8 @@ void RawDevice::read(unsigned block, void *bp) // TODO -- EINTR? if (ok != 512) throw ok < 0 - ? POSIXException(__METHOD__ ": Error reading block.", errno) - : Exception(__METHOD__ ": Error reading block."); + ? POSIX::Exception(__METHOD__ ": Error reading block.", errno) + : ::Exception(__METHOD__ ": Error reading block."); } @@ -231,8 +230,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) ? @@ -243,8 +242,8 @@ void RawDevice::read(TrackSector ts, void *bp) // TODO -- EINTR? if (ok != 256) throw ok < 0 - ? POSIXException(__METHOD__ ": Error reading block.", errno) - : Exception(__METHOD__ ": Error reading block."); + ? POSIX::Exception(__METHOD__ ": Error reading block.", errno) + : ::Exception(__METHOD__ ": Error reading block."); } @@ -253,10 +252,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; @@ -264,8 +263,8 @@ void RawDevice::write(unsigned block, const void *bp) if (ok != 512) throw ok < 0 - ? POSIXException(__METHOD__ ": Error writing block.", errno) - : Exception(__METHOD__ ": Error writing block."); + ? POSIX::Exception(__METHOD__ ": Error writing block.", errno) + : ::Exception(__METHOD__ ": Error writing block."); } @@ -275,10 +274,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; @@ -286,8 +285,8 @@ void RawDevice::write(TrackSector ts, const void *bp) if (ok != 256) throw ok < 0 - ? POSIXException(__METHOD__ ": Error writing block.", errno) - : Exception(__METHOD__ ": Error writing block."); + ? POSIX::Exception(__METHOD__ ": Error writing block.", errno) + : ::Exception(__METHOD__ ": Error writing block."); } @@ -316,6 +315,6 @@ void RawDevice::sync() if (_readOnly) return; if (::fsync(_file.fd()) < 0) - throw POSIXException(__METHOD__ ": fsync error.", errno); + throw POSIX::Exception(__METHOD__ ": fsync error.", errno); } diff --git a/Device/SDKImage.cpp b/Device/SDKImage.cpp index 3c27530..ab6c662 100644 --- a/Device/SDKImage.cpp +++ b/Device/SDKImage.cpp @@ -20,39 +20,8 @@ #include #include -#include - - -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()); -} +#include +#include using namespace Device; diff --git a/Device/UniversalDiskImage.cpp b/Device/UniversalDiskImage.cpp index 18cec76..08f7c4d 100644 --- a/Device/UniversalDiskImage.cpp +++ b/Device/UniversalDiskImage.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include @@ -11,10 +11,6 @@ using namespace Device; using namespace LittleEndian; -using ProFUSE::Exception; -using ProFUSE::POSIXException; - - UniversalDiskImage::UniversalDiskImage(MappedFile *file) : @@ -138,7 +134,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; } diff --git a/File/File.cpp b/File/File.cpp index 4cc41db..0b9f41e 100644 --- a/File/File.cpp +++ b/File/File.cpp @@ -2,12 +2,8 @@ #include #include -#include - - - -using ProFUSE::Exception; -using ProFUSE::POSIXException; +#include +#include File::File() @@ -49,7 +45,7 @@ File::File(const char *name, int flags) _fd = ::open(name, flags); if (_fd < 0) - throw POSIXException( __METHOD__ ": open", errno); + throw POSIX::Exception( __METHOD__ ": open", errno); } File::File(const char *name, int flags, mode_t mode) @@ -59,7 +55,7 @@ File::File(const char *name, int flags, mode_t mode) _fd = ::open(name, flags, mode); if (_fd < 0) - throw POSIXException( __METHOD__ ": open", errno); + throw POSIX::Exception( __METHOD__ ": open", errno); } @@ -70,7 +66,7 @@ File::File(const char *name, FileFlags flags) _fd = ::open(name, flags == ReadOnly ? O_RDONLY : O_RDWR); if (_fd < 0) - throw POSIXException( __METHOD__ ": open", errno); + throw POSIX::Exception( __METHOD__ ": open", errno); } @@ -99,7 +95,7 @@ void File::close() // destructor shouldn't throw. /* if (::close(fd) != 0) - throw POSIXException(__METHOD__ ": close", errno); + throw POSIX::Exception(__METHOD__ ": close", errno); */ } } diff --git a/File/MappedFile.cpp b/File/MappedFile.cpp index 2b8eb91..5387376 100644 --- a/File/MappedFile.cpp +++ b/File/MappedFile.cpp @@ -4,10 +4,8 @@ #include #include -#include - - -using ProFUSE::POSIXException; +#include +#include MappedFile::MappedFile() { @@ -81,16 +79,16 @@ void MappedFile::init(const File &f, bool readOnly, size_t size) // close enough if (f.fd() < 0) - throw POSIXException( __METHOD__, EBADF); + throw POSIX::Exception( __METHOD__, EBADF); if (!size) { if (::fstat(f.fd(), &st) != 0) - throw POSIXException(__METHOD__ ": fstat", errno); + throw POSIX::Exception(__METHOD__ ": fstat", errno); if (!S_ISREG(st.st_mode)) - throw POSIXException(__METHOD__, ENODEV); + throw POSIX::Exception(__METHOD__, ENODEV); size = st.st_size; } @@ -99,7 +97,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 POSIXException(__METHOD__ ": mmap", errno); + throw POSIX::Exception(__METHOD__ ": mmap", errno); _readOnly = readOnly; } @@ -127,7 +125,7 @@ void MappedFile::close() // destructor shouldn't throw. /* if (::munmap(address, length) != 0) - throw POSIXException(__METHOD__ ": munmap", errno); + throw POSIX::Exception(__METHOD__ ": munmap", errno); */ } } @@ -140,7 +138,7 @@ void MappedFile::sync() if (_address != MAP_FAILED) { if (::msync(_address, _length, MS_SYNC) != 0) - throw POSIXException(__METHOD__ ": msync", errno); + throw POSIX::Exception(__METHOD__ ": msync", errno); } } @@ -173,14 +171,14 @@ MappedFile *MappedFile::Create(const char *name, size_t size) if (!fd.isValid()) { - throw POSIXException(__METHOD__ ": Unable to create file.", errno); + throw POSIX::Exception(__METHOD__ ": Unable to create file.", errno); } // TODO -- is ftruncate portable? if (::ftruncate(fd.fd(), size) < 0) { // TODO -- unlink? - throw POSIXException(__METHOD__ ": Unable to truncate file.", errno); + throw POSIX::Exception(__METHOD__ ": Unable to truncate file.", errno); } return new MappedFile(fd, File::ReadWrite, size); diff --git a/Makefile b/Makefile index 02ebdab..1fb3bbb 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ endif ifdef HAVE_NUFX DEVICE_OBJECTS += Device/SDKImage.o + EXCEPTION_OBJECTS += NuFX/Exception.o LDFLAGS += -L/usr/local/lib/ LIBS += -lnufx -lz CPPFLAGS += -DHAVE_NUFX=1 @@ -24,8 +25,11 @@ OBJECTS += ${wildcard Device/*.o} OBJECTS += ${wildcard Endian/*.o} OBJECTS += ${wildcard File/*.o} OBJECTS += ${wildcard Pascal/*.o} -OBJECTS += ${wildcard ProFUSE/*.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 @@ -67,13 +71,19 @@ PASCAL_OBJECTS += Pascal/TextWriter.o PASCAL_OBJECTS += Pascal/Entry.o PASCAL_OBJECTS += Pascal/VolumeEntry.o -PROFUSE_OBJECTS += ProFUSE/Exception.o -PROFUSE_OBJECTS += ProFUSE/Lock.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) @@ -93,7 +103,8 @@ o/newfs_pascal: bin/newfs_pascal.o \ ${DEVICE_OBJECTS} \ ${ENDIAN_OBJECTS} \ ${FILE_OBJECTS} \ - ${PROFUSE_OBJECTS} \ + ${COMMON_OBJECTS} \ + ${EXCEPTION_OBJECTS} \ ${PASCAL_OBJECTS} $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ @@ -102,7 +113,8 @@ o/apfm: bin/apfm.o \ ${DEVICE_OBJECTS} \ ${ENDIAN_OBJECTS} \ ${FILE_OBJECTS} \ - ${PROFUSE_OBJECTS} \ + ${COMMON_OBJECTS} \ + ${EXCEPTION_OBJECTS} \ ${PASCAL_OBJECTS} $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ @@ -112,7 +124,8 @@ o/fuse_pascal: bin/fuse_pascal.o bin/fuse_pascal_ops.o \ ${DEVICE_OBJECTS} \ ${ENDIAN_OBJECTS} \ ${FILE_OBJECTS} \ - ${PROFUSE_OBJECTS} \ + ${COMMON_OBJECTS} \ + ${EXCEPTION_OBJECTS} \ ${PASCAL_OBJECTS} $(CC) $(LDFLAGS) $^ $(LIBS) $(FUSE_LIBS) -o $@ @@ -123,7 +136,8 @@ o/profuse: bin/profuse.o bin/profuse_dirent.o bin/profuse_file.o \ ${DEVICE_OBJECTS} \ ${ENDIAN_OBJECTS} \ ${FILE_OBJECTS} \ - ${PROFUSE_OBJECTS} \ + ${COMMON_OBJECTS} \ + ${EXCEPTION_OBJECTS} \ ${PRODOS_OBJECTS} $(CC) $(LDFLAGS) $^ $(LIBS) $(FUSE_LIBS) -o $@ @@ -133,59 +147,59 @@ clean: xattr.o: bin/xattr.cpp -newfs_pascal.o: bin/newfs_pascal.cpp Device/BlockDevice.h ProFUSE/Exception.h \ +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 \ - ProFUSE/Exception.h Device/BlockDevice.h Device/TrackSector.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 \ - ProFUSE/auto.h ProFUSE/Exception.h + Common/auto.h Common/Exception.h apfm.o: bin/apfm.cpp Pascal/Pascal.h Pascal/Date.h Device/BlockDevice.h \ - ProFUSE/Exception.h Device/TrackSector.h Cache/BlockCache.h + Common/Exception.h Device/TrackSector.h Cache/BlockCache.h -File/File.o: File/File.cpp File/File.h ProFUSE/Exception.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 \ - ProFUSE/Exception.h + Common/Exception.h Device/Adaptor.o: Device/Adaptor.cpp Device/Adaptor.h Device/TrackSector.h \ - ProFUSE/Exception.h + Common/Exception.h Device/BlockDevice.o: Device/BlockDevice.cpp Device/BlockDevice.h \ - ProFUSE/Exception.h Device/TrackSector.h Cache/BlockCache.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 ProFUSE/Exception.h Device/TrackSector.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 ProFUSE/Exception.h Device/TrackSector.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 \ - ProFUSE/Exception.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 \ - ProFUSE/Exception.h Device/TrackSector.h Cache/BlockCache.h File/File.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 ProFUSE/Exception.h \ + 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 \ @@ -194,45 +208,45 @@ Device/UniversalDiskImage.o: Device/UniversalDiskImage.cpp \ Endian/Endian.o: Endian/Endian.cpp Endian/Endian.h Cache/BlockCache.o: Cache/BlockCache.cpp Cache/BlockCache.h \ - Device/BlockDevice.h ProFUSE/Exception.h Device/TrackSector.h \ - ProFUSE/auto.h + Device/BlockDevice.h Common/Exception.h Device/TrackSector.h \ + Common/auto.h Cache/ConcreteBlockCache.o: Cache/ConcreteBlockCache.cpp \ Device/BlockDevice.h \ - ProFUSE/Exception.h Device/TrackSector.h Cache/BlockCache.h \ - Cache/ConcreteBlockCache.h ProFUSE/auto.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 ProFUSE/Exception.h \ + Cache/BlockCache.h Device/BlockDevice.h Common/Exception.h \ Device/TrackSector.h -ProFUSE/Exception.o: ProFUSE/Exception.cpp ProFUSE/Exception.h +Common/Exception.o: Common/Exception.cpp Common/Exception.h -ProFUSE/Lock.o: ProFUSE/Lock.cpp ProFUSE/Lock.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 \ - ProFUSE/Exception.h Endian/Endian.h Endian/IOBuffer.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 ProFUSE/auto.h \ - ProFUSE/Exception.h Endian/Endian.h Endian/IOBuffer.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 ProFUSE/auto.h \ - ProFUSE/Exception.h Endian/Endian.h Endian/IOBuffer.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 ProFUSE/Exception.h + Pascal/FileEntry.h Pascal/Entry.h Pascal/Date.h Common/Exception.h @@ -243,3 +257,11 @@ 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 + + + diff --git a/Pascal/Entry.cpp b/Pascal/Entry.cpp index 6cb406e..176b5bb 100644 --- a/Pascal/Entry.cpp +++ b/Pascal/Entry.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include #include diff --git a/Pascal/Entry.h b/Pascal/Entry.h index 7fe8605..f367bf7 100644 --- a/Pascal/Entry.h +++ b/Pascal/Entry.h @@ -1,7 +1,7 @@ #ifndef __PASCAL_ENTRY_H__ #define __PASCAL_ENTRY_H__ -#include +#include namespace Device { diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index 35ba7ee..7d54bbc 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -8,8 +8,9 @@ #include #include -#include -#include +#include +#include +#include #include #include @@ -77,7 +78,7 @@ FileEntry::FileEntry(const char *name, unsigned fileKind) unsigned length = ValidName(name); if (!length) - throw ProFUSE::Exception(__METHOD__ ": Invalid file name."); + throw ::Exception(__METHOD__ ": Invalid file name."); _fileKind = fileKind; _status = 0; @@ -126,7 +127,7 @@ void FileEntry::setName(const char *name) unsigned length = ValidName(name); if (!length) - throw ProFUSE::ProDOSException(__METHOD__ ": Invalid file name.", ProFUSE::badPathSyntax); + throw ProDOS::Exception(__METHOD__ ": Invalid file name.", ProDOS::badPathSyntax); _fileNameLength = length; for (unsigned i = 0; i < length; ++i) @@ -523,7 +524,7 @@ int FileEntry::textRead(uint8_t *buffer, unsigned size, unsigned offset) unsigned l; unsigned count = 0; - ProFUSE::auto_array tmp; + ::auto_array tmp; unsigned tmpSize = 0; if (!_pageSize) textInit(); diff --git a/Pascal/TextWriter.cpp b/Pascal/TextWriter.cpp index 309f4f4..b1d2563 100644 --- a/Pascal/TextWriter.cpp +++ b/Pascal/TextWriter.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include @@ -89,7 +89,7 @@ void TextWriter::writeLine(const char *line, unsigned length) if (length > 1024) { - throw ProFUSE::Exception(__METHOD__ ": String is too long."); + throw ::Exception(__METHOD__ ": String is too long."); } if (_offset + length > 1024) { diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index 60ee49e..07e3453 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -5,8 +5,9 @@ #include -#include -#include +#include +#include +#include #include #include @@ -21,9 +22,6 @@ using namespace Pascal; using namespace Device; -using ProFUSE::Exception; -using ProFUSE::ProDOSException; -using ProFUSE::POSIXException; enum { kMaxFiles = 77 @@ -111,13 +109,13 @@ VolumeEntry::VolumeEntry(Device::BlockDevicePointer device, const char *name) : deviceBlocks = std::min(0xffffu, deviceBlocks); if (deviceBlocks < 6) - throw Exception(__METHOD__ ": device too small."); + throw ::Exception(__METHOD__ ": device too small."); length = ValidName(name); if (!length) - throw ProDOSException(__METHOD__ ": Invalid volume name.", ProFUSE::badPathSyntax); + throw ProDOS::Exception(__METHOD__ ": Invalid volume name.", ProDOS::badPathSyntax); _firstBlock = 0; _lastBlock = 6; @@ -164,7 +162,7 @@ VolumeEntry::VolumeEntry(Device::BlockDevicePointer device) { unsigned blockCount; //unsigned deviceBlocks = device->blocks(); - ProFUSE::auto_array buffer(new uint8_t[512]); + ::auto_array buffer(new uint8_t[512]); // read the header block, then load up all the header @@ -234,7 +232,7 @@ VolumeEntry::VolumeEntry(Device::BlockDevicePointer device) error = true; if (error) - throw ProDOSException(__METHOD__ ": Invalid file entry.", ProFUSE::dirError); + throw ProDOS::Exception(__METHOD__ ": Invalid file entry.", ProDOS::dirError); block = e->_lastBlock; @@ -274,7 +272,7 @@ void VolumeEntry::init(void *vp) // verify filenamelength <= 7 if (_fileNameLength > 7) - throw ProDOSException(__METHOD__ ": invalid name length", ProFUSE::badPathSyntax); + throw ProDOS::Exception(__METHOD__ ": invalid name length", ProDOS::badPathSyntax); // verify fileKind == 0 // verify _fileCount reasonable @@ -367,7 +365,7 @@ int VolumeEntry::unlink(const char *name) } // need to update the header blocks. - ProFUSE::auto_array buffer(readDirectoryHeader()); + ::auto_array buffer(readDirectoryHeader()); // update the filecount. @@ -596,7 +594,7 @@ FileEntryPointer VolumeEntry::create(const char *name, unsigned blocks) entry = FileEntry::Create(name, kUntypedFile); - ProFUSE::auto_array buffer(readDirectoryHeader()); + ::auto_array buffer(readDirectoryHeader()); for (iter = _files.begin(); iter != _files.end(); ++iter) { @@ -740,13 +738,13 @@ int VolumeEntry::krunch() if (first != prevBlock) gap = true; if (first < prevBlock) - return ProFUSE::damagedBitMap; + return ProDOS::damagedBitMap; if (last < first) - return ProFUSE::damagedBitMap; + return ProDOS::damagedBitMap; if (first < volumeBlocks()) - return ProFUSE::damagedBitMap; + return ProDOS::damagedBitMap; prevBlock = last; @@ -758,7 +756,7 @@ int VolumeEntry::krunch() // need to update the header blocks. - ProFUSE::auto_array buffer(readDirectoryHeader()); + ::auto_array buffer(readDirectoryHeader()); IOBuffer b(buffer.get(), 512 * blocks()); @@ -956,7 +954,7 @@ void VolumeEntry::writeDirectoryHeader(void *buffer) uint8_t *VolumeEntry::readBlocks(unsigned startingBlock, unsigned count) { - ProFUSE::auto_array buffer(new uint8_t[512 * count]); + ::auto_array buffer(new uint8_t[512 * count]); for (unsigned i = 0; i < count; ++i) _cache->read(startingBlock + i, buffer.get() + 512 * i); @@ -1001,7 +999,7 @@ void VolumeEntry::writeEntry(FileEntry *e) else { // crosses page boundaries. - ProFUSE::auto_array buffer(readBlocks(startBlock, 2)); + ::auto_array buffer(readBlocks(startBlock, 2)); IOBuffer b(buffer.get() + offset, 0x1a); diff --git a/bin/apfm.cpp b/bin/apfm.cpp index 50fb5d2..23b2f37 100644 --- a/bin/apfm.cpp +++ b/bin/apfm.cpp @@ -1067,7 +1067,7 @@ int main(int argc, char **argv) usage(); return 3; } - catch (ProFUSE::Exception& e) + catch (Exception& e) { std::fprintf(stderr, "%s\n", e.what()); std::fprintf(stderr, "%s\n", e.errorString()); diff --git a/bin/fuse_pascal.cpp b/bin/fuse_pascal.cpp index 2f6d72a..d384486 100644 --- a/bin/fuse_pascal.cpp +++ b/bin/fuse_pascal.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include @@ -216,17 +216,13 @@ int main(int argc, char **argv) volume = Pascal::VolumeEntry::Open(device); } - catch (ProFUSE::POSIXException &e) + catch (::Exception &e) { std::fprintf(stderr, "%s\n", e.what()); std::fprintf(stderr, "%s\n", std::strerror(e.error())); return -1; } - catch (ProFUSE::Exception &e) - { - std::fprintf(stderr, "%s\n", e.what()); - return -1; - } + diff --git a/bin/fuse_pascal_ops.cpp b/bin/fuse_pascal_ops.cpp index 31c8509..d44ac32 100644 --- a/bin/fuse_pascal_ops.cpp +++ b/bin/fuse_pascal_ops.cpp @@ -26,8 +26,9 @@ #include -#include -#include +#include +#include +#include #define NO_ATTR() \ { \ @@ -264,7 +265,7 @@ static void pascal_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t of DEBUGNAME() VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); - ProFUSE::auto_array buffer(new uint8_t[size]); + ::auto_array buffer(new uint8_t[size]); unsigned count = volume->fileCount(); @@ -502,13 +503,14 @@ static void pascal_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, try { - ProFUSE::auto_array buffer(new uint8_t[size]); + ::auto_array buffer(new uint8_t[size]); unsigned rsize = file->read(buffer.get(), size, off); fuse_reply_buf(req, (char *)(buffer.get()), rsize); return; } - catch (ProFUSE::POSIXException &e) + + catch (POSIX::Exception &e) { printf("posix error...\n"); ERROR(true, e.error()); diff --git a/bin/newfs_pascal.cpp b/bin/newfs_pascal.cpp index 7b1bbb0..fb08a2b 100644 --- a/bin/newfs_pascal.cpp +++ b/bin/newfs_pascal.cpp @@ -14,7 +14,7 @@ #include -#include +#include #include @@ -302,17 +302,13 @@ int main(int argc, char **argv) } - catch (ProFUSE::POSIXException& e) + catch (::Exception& e) { std::fprintf(stderr, "%s\n", e.what()); std::fprintf(stderr, "%s\n", ::strerror(e.error())); return -2; } - catch (ProFUSE::Exception& e) - { - std::fprintf(stderr, "%s\n", e.what()); - return -2; - } + return 0; } diff --git a/bin/profuse.cpp b/bin/profuse.cpp index 62dff80..1c8675a 100644 --- a/bin/profuse.cpp +++ b/bin/profuse.cpp @@ -280,7 +280,7 @@ int main(int argc, char *argv[]) } } - catch (ProFUSE::Exception &e) + catch (::Exception &e) { std::fprintf(stderr, "%s\n", e.what()); std::fprintf(stderr, "%s\n", e.errorString()); From 8778d0dcf263cdd0f40d05c83bed197d8dad5c33 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 14 Mar 2011 23:15:37 +0000 Subject: [PATCH 222/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@390 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/SDKImage.cpp | 21 +++++++++++---------- Makefile | 2 +- bin/profuse.cpp | 2 ++ 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Device/SDKImage.cpp b/Device/SDKImage.cpp index ab6c662..17b726f 100644 --- a/Device/SDKImage.cpp +++ b/Device/SDKImage.cpp @@ -22,6 +22,7 @@ #include #include +#include using namespace Device; @@ -45,7 +46,7 @@ static record_thread FindDiskImageThread(NuArchive *archive) e = NuGetAttr(archive, kNuAttrNumRecords, &recordCount); if (e) { - throw NuFXException(__METHOD__ ": NuGetAttr", e); + throw NuFX::Exception(__METHOD__ ": NuGetAttr", e); } for (unsigned position = 0; position < recordCount; ++position) @@ -56,13 +57,13 @@ static record_thread FindDiskImageThread(NuArchive *archive) e = NuGetRecordIdxByPosition(archive, position, &rIndex); if (e) { - throw NuFXException(__METHOD__ ": NuGetRecordIdxByPosition", e); + throw NuFX::Exception(__METHOD__ ": NuGetRecordIdxByPosition", e); } e = NuGetRecord(archive, rIndex, &record); if (e) { - throw NuFXException(__METHOD__ ": NuGetRecord", e); + throw NuFX::Exception(__METHOD__ ": NuGetRecord", e); } for (unsigned i = 0; i < NuRecordGetNumThreads(record); ++i) @@ -78,7 +79,7 @@ static record_thread FindDiskImageThread(NuArchive *archive) } } - throw Exception(__METHOD__ ": not a disk image"); + throw ::Exception(__METHOD__ ": not a disk image"); } @@ -116,7 +117,7 @@ BlockDevicePointer SDKImage::Open(const char *name) e = NuOpenRO(name, &archive); if (e) { - throw NuFXException(__METHOD__ ": NuOpenRO", e); + throw NuFX::Exception(__METHOD__ ": NuOpenRO", e); } rt = FindDiskImageThread(archive); @@ -124,27 +125,27 @@ BlockDevicePointer SDKImage::Open(const char *name) fd = mkstemp(tmp); if (fd < 0) { - throw POSIXException(__METHOD__ ": mkstemp", errno); + throw POSIX::Exception(__METHOD__ ": mkstemp", errno); } fp = fdopen(fd, "w"); if (!fp) { ::close(fd); - throw POSIXException(__METHOD__ ": fdopen", errno); + throw POSIX::Exception(__METHOD__ ": fdopen", errno); } e = NuCreateDataSinkForFP(true, kNuConvertOff, fp, &sink); if (e) { - throw NuFXException(__METHOD__ ": NuCreateDataSinkForFP", e); + throw NuFX::Exception(__METHOD__ ": NuCreateDataSinkForFP", e); } e = NuExtractThread(archive, rt.thread_index, sink); if (e) { - throw NuFXException(__METHOD__ ": NuExtractThread", e); + throw NuFX::Exception(__METHOD__ ": NuExtractThread", e); } fprintf(stderr, "Extracted disk image to %s\n", tmp); @@ -210,7 +211,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; } diff --git a/Makefile b/Makefile index 1fb3bbb..cc7ebc7 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ ifdef HAVE_NUFX DEVICE_OBJECTS += Device/SDKImage.o EXCEPTION_OBJECTS += NuFX/Exception.o LDFLAGS += -L/usr/local/lib/ - LIBS += -lnufx -lz + LIBS += -lnufx -lz -framework carbon CPPFLAGS += -DHAVE_NUFX=1 endif diff --git a/bin/profuse.cpp b/bin/profuse.cpp index 1c8675a..cf60cd1 100644 --- a/bin/profuse.cpp +++ b/bin/profuse.cpp @@ -128,7 +128,9 @@ 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" From b39aeba7ced78ac1dd1e99333b69e275e9f5f99a Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 14 Mar 2011 23:16:23 +0000 Subject: [PATCH 223/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@391 aa027e90-d47c-11dd-86d7-074df07e0730 --- Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cc7ebc7..3bb6ef1 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,12 @@ ifdef HAVE_NUFX DEVICE_OBJECTS += Device/SDKImage.o EXCEPTION_OBJECTS += NuFX/Exception.o LDFLAGS += -L/usr/local/lib/ - LIBS += -lnufx -lz -framework carbon + LIBS += -lnufx -lz + + ifeq ($(UNAME),Darwin) + LIBS += -framework carbon + endif + CPPFLAGS += -DHAVE_NUFX=1 endif From 1fe6327ab119d89f6160d065257000be2b91b117 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 18 Mar 2011 03:07:16 +0000 Subject: [PATCH 224/236] updated xcode project git-svn-id: https://profuse.googlecode.com/svn/branches/v2@392 aa027e90-d47c-11dd-86d7-074df07e0730 --- PROFuseX.xcodeproj/project.pbxproj | 372 ++++++++++++++++++++++++----- 1 file changed, 308 insertions(+), 64 deletions(-) diff --git a/PROFuseX.xcodeproj/project.pbxproj b/PROFuseX.xcodeproj/project.pbxproj index cc25a44..b2d79e2 100644 --- a/PROFuseX.xcodeproj/project.pbxproj +++ b/PROFuseX.xcodeproj/project.pbxproj @@ -26,8 +26,6 @@ B63EFCDB11A36C8B00C90DCE /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; B63EFCDC11A36C8B00C90DCE /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; B63EFCDD11A36C8B00C90DCE /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; - B63EFCDE11A36C8B00C90DCE /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD111A09DB500C90DCE /* Exception.cpp */; }; - B63EFCDF11A36C8B00C90DCE /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD311A09DB500C90DCE /* Lock.cpp */; }; B63EFCE011A36C8B00C90DCE /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; B63EFCE111A36C8B00C90DCE /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; }; B63EFCE211A36C8B00C90DCE /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; @@ -45,13 +43,61 @@ B63EFE8E11A4888500C90DCE /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; B63EFE8F11A4888500C90DCE /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; B63EFE9011A4888500C90DCE /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; - B63EFE9111A4888500C90DCE /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD111A09DB500C90DCE /* Exception.cpp */; }; - B63EFE9211A4888500C90DCE /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD311A09DB500C90DCE /* Lock.cpp */; }; B63EFE9311A4888500C90DCE /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; B63EFE9411A4888500C90DCE /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; }; B63EFE9511A4888500C90DCE /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; B63EFE9611A4888500C90DCE /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; B63EFE9711A4888500C90DCE /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; + B650901B1332FE5000FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090181332FE5000FBA318 /* Exception.cpp */; }; + B650901D1332FE5000FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090181332FE5000FBA318 /* Exception.cpp */; }; + B650901E1332FE5000FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090181332FE5000FBA318 /* Exception.cpp */; }; + B65090271332FE6A00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090241332FE6A00FBA318 /* Exception.cpp */; }; + B65090281332FE6A00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090241332FE6A00FBA318 /* Exception.cpp */; }; + B65090291332FE6A00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090241332FE6A00FBA318 /* Exception.cpp */; }; + B650902A1332FE6A00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090241332FE6A00FBA318 /* Exception.cpp */; }; + B65090311332FE8B00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650902F1332FE8B00FBA318 /* Exception.cpp */; }; + B65090321332FE8B00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650902F1332FE8B00FBA318 /* Exception.cpp */; }; + B65090331332FE8B00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650902F1332FE8B00FBA318 /* Exception.cpp */; }; + B65090341332FE8B00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650902F1332FE8B00FBA318 /* Exception.cpp */; }; + B650903F1332FEBE00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090371332FEBE00FBA318 /* Exception.cpp */; }; + B65090401332FEBE00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090371332FEBE00FBA318 /* Exception.cpp */; }; + B65090411332FEBE00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090371332FEBE00FBA318 /* Exception.cpp */; }; + B65090421332FEBE00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090371332FEBE00FBA318 /* Exception.cpp */; }; + B65090471332FEBE00FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; + B65090481332FEBE00FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; + B65090491332FEBE00FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; + B650904A1332FEBE00FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; + B65090511333006900FBA318 /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; + B65090521333006900FBA318 /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; + B65090531333006900FBA318 /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; + B65090541333006900FBA318 /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; + B65090551333006900FBA318 /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; + B65090561333006900FBA318 /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; + B65090571333006900FBA318 /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; + B65090581333006900FBA318 /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; + B65090591333006900FBA318 /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; + B650905A1333006900FBA318 /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; + B650905B1333006900FBA318 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; + B650905C1333006900FBA318 /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; + B650905D1333006900FBA318 /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; + B65090651333006900FBA318 /* SDKImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6A591261329C417007B0EE2 /* SDKImage.cpp */; }; + B65090661333006900FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090181332FE5000FBA318 /* Exception.cpp */; }; + B65090671333006900FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090241332FE6A00FBA318 /* Exception.cpp */; }; + B65090681333006900FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650902F1332FE8B00FBA318 /* Exception.cpp */; }; + B65090691333006900FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090371332FEBE00FBA318 /* Exception.cpp */; }; + B650906A1333006900FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; + B650906C1333006900FBA318 /* libfuse_ino64.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */; }; + B650906D1333006900FBA318 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EC132995D4007B0EE2 /* Carbon.framework */; }; + B650906E1333006900FBA318 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EE132995D4007B0EE2 /* libz.dylib */; }; + B650906F1333006900FBA318 /* libNuFX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590F713299626007B0EE2 /* libNuFX.a */; }; + B65090771333009400FBA318 /* DateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272AA711D5AE0C0073C73A /* DateTime.cpp */; }; + B650907D133300BA00FBA318 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509078133300BA00FBA318 /* File.cpp */; }; + B650907E133300BA00FBA318 /* Disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509079133300BA00FBA318 /* Disk.cpp */; }; + B6509080133300DD00FBA318 /* profuse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650907F133300DD00FBA318 /* profuse.cpp */; }; + B6509086133300FB00FBA318 /* profuse_xattr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509081133300FB00FBA318 /* profuse_xattr.cpp */; }; + B6509087133300FB00FBA318 /* profuse_stat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509082133300FB00FBA318 /* profuse_stat.cpp */; }; + B6509088133300FB00FBA318 /* profuse_file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509083133300FB00FBA318 /* profuse_file.cpp */; }; + B6509089133300FB00FBA318 /* profuse_dirent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509084133300FB00FBA318 /* profuse_dirent.cpp */; }; B656AE0811A84F6C00AB578A /* libfuse_ino64.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */; }; B656AE0911A84F7700AB578A /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; B656AE0A11A84F7700AB578A /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; @@ -65,8 +111,6 @@ B656AE1211A84F7700AB578A /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; B656AE1311A84F7700AB578A /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; B656AE1411A84F7700AB578A /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; - B656AE1511A84F7700AB578A /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD111A09DB500C90DCE /* Exception.cpp */; }; - B656AE1611A84F7700AB578A /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD311A09DB500C90DCE /* Lock.cpp */; }; B656AE1711A84F7700AB578A /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; B656AE1811A84F7700AB578A /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; }; B656AE1911A84F7700AB578A /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; @@ -85,8 +129,6 @@ B656AF1211AA106C00AB578A /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; B656AF1311AA106C00AB578A /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; B656AF1411AA106C00AB578A /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; - B656AF1511AA106C00AB578A /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD111A09DB500C90DCE /* Exception.cpp */; }; - B656AF1611AA106C00AB578A /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD311A09DB500C90DCE /* Lock.cpp */; }; B656AF1711AA106C00AB578A /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; B656AF1811AA106C00AB578A /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; }; B656AF1911AA106C00AB578A /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; @@ -116,8 +158,6 @@ B6F3683311B431CC0045E114 /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; B6F3683411B431CC0045E114 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; B6F3683511B431CC0045E114 /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; - B6F3683611B431CC0045E114 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD111A09DB500C90DCE /* Exception.cpp */; }; - B6F3683711B431CC0045E114 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAD311A09DB500C90DCE /* Lock.cpp */; }; B6F3683811B431CC0045E114 /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; /* End PBXBuildFile section */ @@ -158,11 +198,6 @@ B63EFACA11A09DAA00C90DCE /* File.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = File.h; sourceTree = ""; }; B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MappedFile.cpp; sourceTree = ""; }; B63EFACC11A09DAA00C90DCE /* MappedFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MappedFile.h; sourceTree = ""; }; - B63EFAD011A09DB500C90DCE /* auto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = auto.h; sourceTree = ""; }; - B63EFAD111A09DB500C90DCE /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = ""; }; - B63EFAD211A09DB500C90DCE /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; - B63EFAD311A09DB500C90DCE /* Lock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Lock.cpp; sourceTree = ""; }; - B63EFAD411A09DB500C90DCE /* Lock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Lock.h; sourceTree = ""; }; B63EFB0611A0AC4800C90DCE /* Adaptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Adaptor.h; sourceTree = ""; }; B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Adaptor.cpp; sourceTree = ""; }; B63EFBE811A244EE00C90DCE /* Date.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Date.cpp; sourceTree = ""; }; @@ -173,12 +208,36 @@ B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOBuffer.cpp.h; sourceTree = ""; }; B63EFCCE11A36C7300C90DCE /* apfm */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = apfm; sourceTree = BUILT_PRODUCTS_DIR; }; B63EFE8111A4886C00C90DCE /* newfs_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = newfs_pascal; sourceTree = BUILT_PRODUCTS_DIR; }; + B65090181332FE5000FBA318 /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = ""; }; + B65090191332FE5000FBA318 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; + B65090241332FE6A00FBA318 /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = ""; }; + B65090251332FE6A00FBA318 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; + B650902F1332FE8B00FBA318 /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = ""; }; + B65090301332FE8B00FBA318 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; + B65090361332FEBE00FBA318 /* auto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = auto.h; sourceTree = ""; }; + B65090371332FEBE00FBA318 /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = ""; }; + B65090381332FEBE00FBA318 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; + B650903A1332FEBE00FBA318 /* Lock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Lock.cpp; sourceTree = ""; }; + B650903B1332FEBE00FBA318 /* Lock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Lock.h; sourceTree = ""; }; + B650903D1332FEBE00FBA318 /* smart_pointers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = smart_pointers.h; sourceTree = ""; }; + B650903E1332FEBE00FBA318 /* unordered_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unordered_map.h; sourceTree = ""; }; + B65090751333006900FBA318 /* fuse_pascal copy */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = "fuse_pascal copy"; path = "/Users/kelvin/Projects/PROFuseX/build/Release/fuse_pascal copy"; sourceTree = ""; }; + B6509078133300BA00FBA318 /* File.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = File.cpp; sourceTree = ""; }; + B6509079133300BA00FBA318 /* Disk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Disk.cpp; sourceTree = ""; }; + B650907A133300BA00FBA318 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; }; + B650907B133300BA00FBA318 /* Disk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Disk.h; sourceTree = ""; }; + B650907C133300BA00FBA318 /* File.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = File.h; sourceTree = ""; }; + B650907F133300DD00FBA318 /* profuse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse.cpp; sourceTree = ""; }; + B6509081133300FB00FBA318 /* profuse_xattr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_xattr.cpp; sourceTree = ""; }; + B6509082133300FB00FBA318 /* profuse_stat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_stat.cpp; sourceTree = ""; }; + B6509083133300FB00FBA318 /* profuse_file.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_file.cpp; sourceTree = ""; }; + B6509084133300FB00FBA318 /* profuse_dirent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_dirent.cpp; sourceTree = ""; }; + B6509085133300FB00FBA318 /* profuse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = profuse.h; sourceTree = ""; }; B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libfuse_ino64.dylib; path = /usr/local/lib/libfuse_ino64.dylib; sourceTree = ""; }; B656AE0311A84F5800AB578A /* fuse_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fuse_pascal; sourceTree = BUILT_PRODUCTS_DIR; }; B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NibbleTest.cpp; sourceTree = ""; }; B656AF0311AA105500AB578A /* NibbleTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NibbleTest; sourceTree = BUILT_PRODUCTS_DIR; }; B659C142131368BA0058DC9C /* Device.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Device.h; sourceTree = ""; }; - B6A53B851319DA3D00C9070F /* smart_pointers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = smart_pointers.h; sourceTree = ""; }; B6A590EC132995D4007B0EE2 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = ../../../../System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; B6A590EE132995D4007B0EE2 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = ../../../../usr/lib/libz.dylib; sourceTree = ""; }; B6A590F713299626007B0EE2 /* libNuFX.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libNuFX.a; sourceTree = ""; }; @@ -212,6 +271,17 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + B650906B1333006900FBA318 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B650906C1333006900FBA318 /* libfuse_ino64.dylib in Frameworks */, + B650906D1333006900FBA318 /* Carbon.framework in Frameworks */, + B650906E1333006900FBA318 /* libz.dylib in Frameworks */, + B650906F1333006900FBA318 /* libNuFX.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; B656AE0111A84F5800AB578A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -254,11 +324,13 @@ B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */, B6272AA411D5AE0C0073C73A /* ProDOS */, B63EFBE711A244EE00C90DCE /* Pascal */, - B63EFACF11A09DB500C90DCE /* ProFUSE */, B63EFAC811A09DAA00C90DCE /* File */, B63EFAB511A098C400C90DCE /* Cache */, B63EFA9411A094E000C90DCE /* Device */, B63EFA7411A0948500C90DCE /* Endian */, + B65090351332FEBE00FBA318 /* Common */, + B65090171332FE5000FBA318 /* NuFX */, + B65090231332FE6A00FBA318 /* POSIX */, 1AB674ADFE9D54B511CA2CBB /* Products */, B656ADED11A84D3200AB578A /* Libraries */, ); @@ -281,6 +353,12 @@ B6272A8D11D5AC3C0073C73A /* bin */ = { isa = PBXGroup; children = ( + B6509081133300FB00FBA318 /* profuse_xattr.cpp */, + B6509082133300FB00FBA318 /* profuse_stat.cpp */, + B6509083133300FB00FBA318 /* profuse_file.cpp */, + B6509084133300FB00FBA318 /* profuse_dirent.cpp */, + B6509085133300FB00FBA318 /* profuse.h */, + B650907F133300DD00FBA318 /* profuse.cpp */, B6272A8E11D5AC3C0073C73A /* apfm.cpp */, B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */, B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */, @@ -294,6 +372,13 @@ B6272AA411D5AE0C0073C73A /* ProDOS */ = { isa = PBXGroup; children = ( + B6509078133300BA00FBA318 /* File.cpp */, + B6509079133300BA00FBA318 /* Disk.cpp */, + B650907A133300BA00FBA318 /* common.h */, + B650907B133300BA00FBA318 /* Disk.h */, + B650907C133300BA00FBA318 /* File.h */, + B650902F1332FE8B00FBA318 /* Exception.cpp */, + B65090301332FE8B00FBA318 /* Exception.h */, B6272AA511D5AE0C0073C73A /* Bitmap.cpp */, B6272AA611D5AE0C0073C73A /* Bitmap.h */, B6272AA711D5AE0C0073C73A /* DateTime.cpp */, @@ -362,19 +447,6 @@ path = File; sourceTree = ""; }; - B63EFACF11A09DB500C90DCE /* ProFUSE */ = { - isa = PBXGroup; - children = ( - B6A53B851319DA3D00C9070F /* smart_pointers.h */, - B63EFAD011A09DB500C90DCE /* auto.h */, - B63EFAD111A09DB500C90DCE /* Exception.cpp */, - B63EFAD211A09DB500C90DCE /* Exception.h */, - B63EFAD311A09DB500C90DCE /* Lock.cpp */, - B63EFAD411A09DB500C90DCE /* Lock.h */, - ); - path = ProFUSE; - sourceTree = ""; - }; B63EFBE711A244EE00C90DCE /* Pascal */ = { isa = PBXGroup; children = ( @@ -393,6 +465,38 @@ path = Pascal; sourceTree = ""; }; + B65090171332FE5000FBA318 /* NuFX */ = { + isa = PBXGroup; + children = ( + B65090181332FE5000FBA318 /* Exception.cpp */, + B65090191332FE5000FBA318 /* Exception.h */, + ); + path = NuFX; + sourceTree = ""; + }; + B65090231332FE6A00FBA318 /* POSIX */ = { + isa = PBXGroup; + children = ( + B65090241332FE6A00FBA318 /* Exception.cpp */, + B65090251332FE6A00FBA318 /* Exception.h */, + ); + path = POSIX; + sourceTree = ""; + }; + B65090351332FEBE00FBA318 /* Common */ = { + isa = PBXGroup; + children = ( + B65090361332FEBE00FBA318 /* auto.h */, + B65090371332FEBE00FBA318 /* Exception.cpp */, + B65090381332FEBE00FBA318 /* Exception.h */, + B650903A1332FEBE00FBA318 /* Lock.cpp */, + B650903B1332FEBE00FBA318 /* Lock.h */, + B650903D1332FEBE00FBA318 /* smart_pointers.h */, + B650903E1332FEBE00FBA318 /* unordered_map.h */, + ); + path = Common; + sourceTree = ""; + }; B656ADED11A84D3200AB578A /* Libraries */ = { isa = PBXGroup; children = ( @@ -439,6 +543,22 @@ productReference = B63EFE8111A4886C00C90DCE /* newfs_pascal */; productType = "com.apple.product-type.tool"; }; + B650904F1333006900FBA318 /* profuse */ = { + isa = PBXNativeTarget; + buildConfigurationList = B65090701333006900FBA318 /* Build configuration list for PBXNativeTarget "profuse" */; + buildPhases = ( + B65090501333006900FBA318 /* Sources */, + B650906B1333006900FBA318 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = profuse; + productName = fuse_pascal; + productReference = B65090751333006900FBA318 /* fuse_pascal copy */; + productType = "com.apple.product-type.tool"; + }; B656AE0211A84F5800AB578A /* fuse_pascal */ = { isa = PBXNativeTarget; buildConfigurationList = B656AE3411A84FA400AB578A /* Build configuration list for PBXNativeTarget "fuse_pascal" */; @@ -525,6 +645,7 @@ B656AF0211AA105500AB578A /* NibbleTest */, B6F3647F11AB36260045E114 /* xattr */, B6F3682411B431AC0045E114 /* newfs_prodos */, + B650904F1333006900FBA318 /* profuse */, ); }; /* End PBXProject section */ @@ -546,8 +667,6 @@ B63EFCDB11A36C8B00C90DCE /* MappedBlockCache.cpp in Sources */, B63EFCDC11A36C8B00C90DCE /* File.cpp in Sources */, B63EFCDD11A36C8B00C90DCE /* MappedFile.cpp in Sources */, - B63EFCDE11A36C8B00C90DCE /* Exception.cpp in Sources */, - B63EFCDF11A36C8B00C90DCE /* Lock.cpp in Sources */, B63EFCE011A36C8B00C90DCE /* Adaptor.cpp in Sources */, B63EFCE111A36C8B00C90DCE /* Date.cpp in Sources */, B63EFCE211A36C8B00C90DCE /* Entry.cpp in Sources */, @@ -556,6 +675,11 @@ B6F3676711B323680045E114 /* TextWriter.cpp in Sources */, B6272A9311D5AC440073C73A /* apfm.cpp in Sources */, B6A591281329C417007B0EE2 /* SDKImage.cpp in Sources */, + B650901B1332FE5000FBA318 /* Exception.cpp in Sources */, + B65090271332FE6A00FBA318 /* Exception.cpp in Sources */, + B65090311332FE8B00FBA318 /* Exception.cpp in Sources */, + B650903F1332FEBE00FBA318 /* Exception.cpp in Sources */, + B65090471332FEBE00FBA318 /* Lock.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -575,8 +699,6 @@ B63EFE8E11A4888500C90DCE /* MappedBlockCache.cpp in Sources */, B63EFE8F11A4888500C90DCE /* File.cpp in Sources */, B63EFE9011A4888500C90DCE /* MappedFile.cpp in Sources */, - B63EFE9111A4888500C90DCE /* Exception.cpp in Sources */, - B63EFE9211A4888500C90DCE /* Lock.cpp in Sources */, B63EFE9311A4888500C90DCE /* Adaptor.cpp in Sources */, B63EFE9411A4888500C90DCE /* Date.cpp in Sources */, B63EFE9511A4888500C90DCE /* Entry.cpp in Sources */, @@ -584,6 +706,44 @@ B63EFE9711A4888500C90DCE /* VolumeEntry.cpp in Sources */, B6F3676811B323680045E114 /* TextWriter.cpp in Sources */, B6272A9611D5AC560073C73A /* newfs_pascal.cpp in Sources */, + B65090281332FE6A00FBA318 /* Exception.cpp in Sources */, + B65090321332FE8B00FBA318 /* Exception.cpp in Sources */, + B65090401332FEBE00FBA318 /* Exception.cpp in Sources */, + B65090481332FEBE00FBA318 /* Lock.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B65090501333006900FBA318 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B65090511333006900FBA318 /* Endian.cpp in Sources */, + B65090521333006900FBA318 /* BlockDevice.cpp in Sources */, + B65090531333006900FBA318 /* DavexDiskImage.cpp in Sources */, + B65090541333006900FBA318 /* DiskCopy42Image.cpp in Sources */, + B65090551333006900FBA318 /* DiskImage.cpp in Sources */, + B65090561333006900FBA318 /* RawDevice.cpp in Sources */, + B65090571333006900FBA318 /* UniversalDiskImage.cpp in Sources */, + B65090581333006900FBA318 /* BlockCache.cpp in Sources */, + B65090591333006900FBA318 /* ConcreteBlockCache.cpp in Sources */, + B650905A1333006900FBA318 /* MappedBlockCache.cpp in Sources */, + B650905B1333006900FBA318 /* File.cpp in Sources */, + B650905C1333006900FBA318 /* MappedFile.cpp in Sources */, + B650905D1333006900FBA318 /* Adaptor.cpp in Sources */, + B65090651333006900FBA318 /* SDKImage.cpp in Sources */, + B65090661333006900FBA318 /* Exception.cpp in Sources */, + B65090671333006900FBA318 /* Exception.cpp in Sources */, + B65090681333006900FBA318 /* Exception.cpp in Sources */, + B65090691333006900FBA318 /* Exception.cpp in Sources */, + B650906A1333006900FBA318 /* Lock.cpp in Sources */, + B65090771333009400FBA318 /* DateTime.cpp in Sources */, + B650907D133300BA00FBA318 /* File.cpp in Sources */, + B650907E133300BA00FBA318 /* Disk.cpp in Sources */, + B6509080133300DD00FBA318 /* profuse.cpp in Sources */, + B6509086133300FB00FBA318 /* profuse_xattr.cpp in Sources */, + B6509087133300FB00FBA318 /* profuse_stat.cpp in Sources */, + B6509088133300FB00FBA318 /* profuse_file.cpp in Sources */, + B6509089133300FB00FBA318 /* profuse_dirent.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -603,8 +763,6 @@ B656AE1211A84F7700AB578A /* MappedBlockCache.cpp in Sources */, B656AE1311A84F7700AB578A /* File.cpp in Sources */, B656AE1411A84F7700AB578A /* MappedFile.cpp in Sources */, - B656AE1511A84F7700AB578A /* Exception.cpp in Sources */, - B656AE1611A84F7700AB578A /* Lock.cpp in Sources */, B656AE1711A84F7700AB578A /* Adaptor.cpp in Sources */, B656AE1811A84F7700AB578A /* Date.cpp in Sources */, B656AE1911A84F7700AB578A /* Entry.cpp in Sources */, @@ -614,6 +772,11 @@ B6272A9411D5AC4C0073C73A /* fuse_pascal.cpp in Sources */, B6272A9511D5AC530073C73A /* fuse_pascal_ops.cpp in Sources */, B6A591291329C417007B0EE2 /* SDKImage.cpp in Sources */, + B650901D1332FE5000FBA318 /* Exception.cpp in Sources */, + B65090291332FE6A00FBA318 /* Exception.cpp in Sources */, + B65090331332FE8B00FBA318 /* Exception.cpp in Sources */, + B65090411332FEBE00FBA318 /* Exception.cpp in Sources */, + B65090491332FEBE00FBA318 /* Lock.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -633,8 +796,6 @@ B656AF1211AA106C00AB578A /* MappedBlockCache.cpp in Sources */, B656AF1311AA106C00AB578A /* File.cpp in Sources */, B656AF1411AA106C00AB578A /* MappedFile.cpp in Sources */, - B656AF1511AA106C00AB578A /* Exception.cpp in Sources */, - B656AF1611AA106C00AB578A /* Lock.cpp in Sources */, B656AF1711AA106C00AB578A /* Adaptor.cpp in Sources */, B656AF1811AA106C00AB578A /* Date.cpp in Sources */, B656AF1911AA106C00AB578A /* Entry.cpp in Sources */, @@ -669,11 +830,14 @@ B6F3683311B431CC0045E114 /* MappedBlockCache.cpp in Sources */, B6F3683411B431CC0045E114 /* File.cpp in Sources */, B6F3683511B431CC0045E114 /* MappedFile.cpp in Sources */, - B6F3683611B431CC0045E114 /* Exception.cpp in Sources */, - B6F3683711B431CC0045E114 /* Lock.cpp in Sources */, B6F3683811B431CC0045E114 /* Adaptor.cpp in Sources */, B6272AAA11D5AE0C0073C73A /* Bitmap.cpp in Sources */, B6272AAB11D5AE0C0073C73A /* DateTime.cpp in Sources */, + B650901E1332FE5000FBA318 /* Exception.cpp in Sources */, + B650902A1332FE6A00FBA318 /* Exception.cpp in Sources */, + B65090341332FE8B00FBA318 /* Exception.cpp in Sources */, + B65090421332FEBE00FBA318 /* Exception.cpp in Sources */, + B650904A1332FEBE00FBA318 /* Lock.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -724,9 +888,8 @@ GCC_OPTIMIZATION_LEVEL = 0; INSTALL_PATH = /usr/local/bin; LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/../profuse_interim\"", - "\"$(SRCROOT)\"", + ., + /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; PREBINDING = NO; @@ -744,9 +907,8 @@ GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/../profuse_interim\"", - "\"$(SRCROOT)\"", + ., + /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; PREBINDING = NO; @@ -787,6 +949,83 @@ }; name = Release; }; + B65090711333006900FBA318 /* 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; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + ., + /usr/local/lib/, + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = profuse; + }; + name = Debug; + }; + B65090721333006900FBA318 /* 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; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + ., + /usr/local/lib/, + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = profuse; + }; + name = "Debug Universal"; + }; + B65090731333006900FBA318 /* Debug fuse */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + ., + /usr/local/lib/, + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = profuse; + }; + name = "Debug fuse"; + }; + B65090741333006900FBA318 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + ., + /usr/local/lib/, + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = profuse; + ZERO_LINK = NO; + }; + name = Release; + }; B656AD7A11A84B5D00AB578A /* Debug fuse */ = { isa = XCBuildConfiguration; buildSettings = { @@ -817,9 +1056,8 @@ GCC_OPTIMIZATION_LEVEL = 0; INSTALL_PATH = /usr/local/bin; LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/../profuse_interim\"", - "\"$(SRCROOT)\"", + ., + /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; PREBINDING = NO; @@ -854,9 +1092,8 @@ GCC_OPTIMIZATION_LEVEL = 0; INSTALL_PATH = /usr/local/bin; LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/../profuse_interim\"", - "\"$(SRCROOT)\"", + ., + /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; PREBINDING = NO; @@ -872,9 +1109,8 @@ GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/../profuse_interim\"", - "\"$(SRCROOT)\"", + ., + /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; PREBINDING = NO; @@ -892,9 +1128,8 @@ GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/../profuse_interim\"", - "\"$(SRCROOT)\"", + ., + /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; PREBINDING = NO; @@ -975,9 +1210,8 @@ GCC_OPTIMIZATION_LEVEL = 0; INSTALL_PATH = /usr/local/bin; LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/../profuse_interim\"", - "\"$(SRCROOT)\"", + ., + /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; PREBINDING = NO; @@ -1012,9 +1246,8 @@ GCC_OPTIMIZATION_LEVEL = 0; INSTALL_PATH = /usr/local/bin; LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/../profuse_interim\"", - "\"$(SRCROOT)\"", + ., + /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; PREBINDING = NO; @@ -1187,6 +1420,17 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + B65090701333006900FBA318 /* Build configuration list for PBXNativeTarget "profuse" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B65090711333006900FBA318 /* Debug */, + B65090721333006900FBA318 /* Debug Universal */, + B65090731333006900FBA318 /* Debug fuse */, + B65090741333006900FBA318 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; B656AE3411A84FA400AB578A /* Build configuration list for PBXNativeTarget "fuse_pascal" */ = { isa = XCConfigurationList; buildConfigurations = ( From 82ecf63db63962e3c486379fdb7c372b0a5f086d Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 18 Mar 2011 03:07:21 +0000 Subject: [PATCH 225/236] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@393 aa027e90-d47c-11dd-86d7-074df07e0730 --- Common/Makefile | 9 --------- Common/unordered_map.h | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 9 deletions(-) delete mode 100644 Common/Makefile create mode 100644 Common/unordered_map.h diff --git a/Common/Makefile b/Common/Makefile deleted file mode 100644 index 657e89d..0000000 --- a/Common/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -CC = g++ -CPPFLAGS += -g -Wall -I../ - - -all : Exception.o Lock.o - -Exception.o : Exception.cpp Exception.h - -Lock.o : Lock.cpp Lock.h \ No newline at end of file diff --git a/Common/unordered_map.h b/Common/unordered_map.h new file mode 100644 index 0000000..19ff5f5 --- /dev/null +++ b/Common/unordered_map.h @@ -0,0 +1,14 @@ +#ifndef __COMMON_UNORDERED_MAP_H__ +#define __COMMON_UNORDERED_MAP_H__ + +#ifdef CPP0X +//c++0x +#include +#define UNORDERED_MAP(...) std::unordered_map(__VA_ARGS__) +#else +// tr1 +#include +#define UNORDERED_MAP(...) std::tr1::unordered_map(__VA_ARGS__) +#endif + +#endif From 3af649af7c238c35dc24f5e03b370be12711a9e2 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 18 Mar 2011 03:36:34 +0000 Subject: [PATCH 226/236] fix up xcode project git-svn-id: https://profuse.googlecode.com/svn/branches/v2@394 aa027e90-d47c-11dd-86d7-074df07e0730 --- PROFuseX.xcodeproj/project.pbxproj | 171 +++++++++++++++-------------- 1 file changed, 86 insertions(+), 85 deletions(-) diff --git a/PROFuseX.xcodeproj/project.pbxproj b/PROFuseX.xcodeproj/project.pbxproj index b2d79e2..7d1f572 100644 --- a/PROFuseX.xcodeproj/project.pbxproj +++ b/PROFuseX.xcodeproj/project.pbxproj @@ -67,37 +67,37 @@ B65090481332FEBE00FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; B65090491332FEBE00FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; B650904A1332FEBE00FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; - B65090511333006900FBA318 /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; - B65090521333006900FBA318 /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; - B65090531333006900FBA318 /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; - B65090541333006900FBA318 /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; - B65090551333006900FBA318 /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; - B65090561333006900FBA318 /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; - B65090571333006900FBA318 /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; - B65090581333006900FBA318 /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; - B65090591333006900FBA318 /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; - B650905A1333006900FBA318 /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; - B650905B1333006900FBA318 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; - B650905C1333006900FBA318 /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; - B650905D1333006900FBA318 /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; - B65090651333006900FBA318 /* SDKImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6A591261329C417007B0EE2 /* SDKImage.cpp */; }; - B65090661333006900FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090181332FE5000FBA318 /* Exception.cpp */; }; - B65090671333006900FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090241332FE6A00FBA318 /* Exception.cpp */; }; - B65090681333006900FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650902F1332FE8B00FBA318 /* Exception.cpp */; }; - B65090691333006900FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090371332FEBE00FBA318 /* Exception.cpp */; }; - B650906A1333006900FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; - B650906C1333006900FBA318 /* libfuse_ino64.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */; }; - B650906D1333006900FBA318 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EC132995D4007B0EE2 /* Carbon.framework */; }; - B650906E1333006900FBA318 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EE132995D4007B0EE2 /* libz.dylib */; }; - B650906F1333006900FBA318 /* libNuFX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590F713299626007B0EE2 /* libNuFX.a */; }; - B65090771333009400FBA318 /* DateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272AA711D5AE0C0073C73A /* DateTime.cpp */; }; - B650907D133300BA00FBA318 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509078133300BA00FBA318 /* File.cpp */; }; - B650907E133300BA00FBA318 /* Disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509079133300BA00FBA318 /* Disk.cpp */; }; - B6509080133300DD00FBA318 /* profuse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650907F133300DD00FBA318 /* profuse.cpp */; }; - B6509086133300FB00FBA318 /* profuse_xattr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509081133300FB00FBA318 /* profuse_xattr.cpp */; }; - B6509087133300FB00FBA318 /* profuse_stat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509082133300FB00FBA318 /* profuse_stat.cpp */; }; - B6509088133300FB00FBA318 /* profuse_file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509083133300FB00FBA318 /* profuse_file.cpp */; }; - B6509089133300FB00FBA318 /* profuse_dirent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509084133300FB00FBA318 /* profuse_dirent.cpp */; }; + B650908C133304C800FBA318 /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; + B650908D133304C800FBA318 /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; + B650908E133304C800FBA318 /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; + B650908F133304C800FBA318 /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; + B6509090133304C800FBA318 /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; + B6509091133304C800FBA318 /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; + B6509092133304C800FBA318 /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; + B6509093133304C800FBA318 /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; + B6509094133304C800FBA318 /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; + B6509095133304C800FBA318 /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; + B6509096133304C800FBA318 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; + B6509097133304C800FBA318 /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; + B6509098133304C800FBA318 /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; + B6509099133304C800FBA318 /* SDKImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6A591261329C417007B0EE2 /* SDKImage.cpp */; }; + B650909A133304C800FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090181332FE5000FBA318 /* Exception.cpp */; }; + B650909B133304C800FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090241332FE6A00FBA318 /* Exception.cpp */; }; + B650909C133304C800FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650902F1332FE8B00FBA318 /* Exception.cpp */; }; + B650909D133304C800FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090371332FEBE00FBA318 /* Exception.cpp */; }; + B650909E133304C800FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; + B650909F133304C800FBA318 /* DateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272AA711D5AE0C0073C73A /* DateTime.cpp */; }; + B65090A0133304C800FBA318 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509078133300BA00FBA318 /* File.cpp */; }; + B65090A1133304C800FBA318 /* Disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509079133300BA00FBA318 /* Disk.cpp */; }; + B65090A2133304C800FBA318 /* profuse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650907F133300DD00FBA318 /* profuse.cpp */; }; + B65090A3133304C800FBA318 /* profuse_xattr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509081133300FB00FBA318 /* profuse_xattr.cpp */; }; + B65090A4133304C800FBA318 /* profuse_stat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509082133300FB00FBA318 /* profuse_stat.cpp */; }; + B65090A5133304C800FBA318 /* profuse_file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509083133300FB00FBA318 /* profuse_file.cpp */; }; + B65090A6133304C800FBA318 /* profuse_dirent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509084133300FB00FBA318 /* profuse_dirent.cpp */; }; + B65090A8133304C800FBA318 /* libfuse_ino64.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */; }; + B65090A9133304C800FBA318 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EC132995D4007B0EE2 /* Carbon.framework */; }; + B65090AA133304C800FBA318 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EE132995D4007B0EE2 /* libz.dylib */; }; + B65090AB133304C800FBA318 /* libNuFX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590F713299626007B0EE2 /* libNuFX.a */; }; B656AE0811A84F6C00AB578A /* libfuse_ino64.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */; }; B656AE0911A84F7700AB578A /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; B656AE0A11A84F7700AB578A /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; @@ -221,7 +221,6 @@ B650903B1332FEBE00FBA318 /* Lock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Lock.h; sourceTree = ""; }; B650903D1332FEBE00FBA318 /* smart_pointers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = smart_pointers.h; sourceTree = ""; }; B650903E1332FEBE00FBA318 /* unordered_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unordered_map.h; sourceTree = ""; }; - B65090751333006900FBA318 /* fuse_pascal copy */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = "fuse_pascal copy"; path = "/Users/kelvin/Projects/PROFuseX/build/Release/fuse_pascal copy"; sourceTree = ""; }; B6509078133300BA00FBA318 /* File.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = File.cpp; sourceTree = ""; }; B6509079133300BA00FBA318 /* Disk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Disk.cpp; sourceTree = ""; }; B650907A133300BA00FBA318 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; }; @@ -233,6 +232,7 @@ B6509083133300FB00FBA318 /* profuse_file.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_file.cpp; sourceTree = ""; }; B6509084133300FB00FBA318 /* profuse_dirent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_dirent.cpp; sourceTree = ""; }; B6509085133300FB00FBA318 /* profuse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = profuse.h; sourceTree = ""; }; + B65090B1133304C800FBA318 /* profuse */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = profuse; sourceTree = BUILT_PRODUCTS_DIR; }; B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libfuse_ino64.dylib; path = /usr/local/lib/libfuse_ino64.dylib; sourceTree = ""; }; B656AE0311A84F5800AB578A /* fuse_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fuse_pascal; sourceTree = BUILT_PRODUCTS_DIR; }; B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NibbleTest.cpp; sourceTree = ""; }; @@ -271,14 +271,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - B650906B1333006900FBA318 /* Frameworks */ = { + B65090A7133304C800FBA318 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - B650906C1333006900FBA318 /* libfuse_ino64.dylib in Frameworks */, - B650906D1333006900FBA318 /* Carbon.framework in Frameworks */, - B650906E1333006900FBA318 /* libz.dylib in Frameworks */, - B650906F1333006900FBA318 /* libNuFX.a in Frameworks */, + B65090A8133304C800FBA318 /* libfuse_ino64.dylib in Frameworks */, + B65090A9133304C800FBA318 /* Carbon.framework in Frameworks */, + B65090AA133304C800FBA318 /* libz.dylib in Frameworks */, + B65090AB133304C800FBA318 /* libNuFX.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -346,6 +346,7 @@ B656AF0311AA105500AB578A /* NibbleTest */, B6F3648011AB36260045E114 /* xattr */, B6F3682511B431AC0045E114 /* newfs_prodos */, + B65090B1133304C800FBA318 /* profuse */, ); name = Products; sourceTree = ""; @@ -523,7 +524,7 @@ dependencies = ( ); name = apfm; - productName = apfpm; + productName = apfm; productReference = B63EFCCE11A36C7300C90DCE /* apfm */; productType = "com.apple.product-type.tool"; }; @@ -543,20 +544,20 @@ productReference = B63EFE8111A4886C00C90DCE /* newfs_pascal */; productType = "com.apple.product-type.tool"; }; - B650904F1333006900FBA318 /* profuse */ = { + B650908A133304C800FBA318 /* profuse */ = { isa = PBXNativeTarget; - buildConfigurationList = B65090701333006900FBA318 /* Build configuration list for PBXNativeTarget "profuse" */; + buildConfigurationList = B65090AC133304C800FBA318 /* Build configuration list for PBXNativeTarget "profuse" */; buildPhases = ( - B65090501333006900FBA318 /* Sources */, - B650906B1333006900FBA318 /* Frameworks */, + B650908B133304C800FBA318 /* Sources */, + B65090A7133304C800FBA318 /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = profuse; - productName = fuse_pascal; - productReference = B65090751333006900FBA318 /* fuse_pascal copy */; + productName = profuse; + productReference = B65090B1133304C800FBA318 /* profuse */; productType = "com.apple.product-type.tool"; }; B656AE0211A84F5800AB578A /* fuse_pascal */ = { @@ -645,7 +646,7 @@ B656AF0211AA105500AB578A /* NibbleTest */, B6F3647F11AB36260045E114 /* xattr */, B6F3682411B431AC0045E114 /* newfs_prodos */, - B650904F1333006900FBA318 /* profuse */, + B650908A133304C800FBA318 /* profuse */, ); }; /* End PBXProject section */ @@ -713,37 +714,37 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - B65090501333006900FBA318 /* Sources */ = { + B650908B133304C800FBA318 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - B65090511333006900FBA318 /* Endian.cpp in Sources */, - B65090521333006900FBA318 /* BlockDevice.cpp in Sources */, - B65090531333006900FBA318 /* DavexDiskImage.cpp in Sources */, - B65090541333006900FBA318 /* DiskCopy42Image.cpp in Sources */, - B65090551333006900FBA318 /* DiskImage.cpp in Sources */, - B65090561333006900FBA318 /* RawDevice.cpp in Sources */, - B65090571333006900FBA318 /* UniversalDiskImage.cpp in Sources */, - B65090581333006900FBA318 /* BlockCache.cpp in Sources */, - B65090591333006900FBA318 /* ConcreteBlockCache.cpp in Sources */, - B650905A1333006900FBA318 /* MappedBlockCache.cpp in Sources */, - B650905B1333006900FBA318 /* File.cpp in Sources */, - B650905C1333006900FBA318 /* MappedFile.cpp in Sources */, - B650905D1333006900FBA318 /* Adaptor.cpp in Sources */, - B65090651333006900FBA318 /* SDKImage.cpp in Sources */, - B65090661333006900FBA318 /* Exception.cpp in Sources */, - B65090671333006900FBA318 /* Exception.cpp in Sources */, - B65090681333006900FBA318 /* Exception.cpp in Sources */, - B65090691333006900FBA318 /* Exception.cpp in Sources */, - B650906A1333006900FBA318 /* Lock.cpp in Sources */, - B65090771333009400FBA318 /* DateTime.cpp in Sources */, - B650907D133300BA00FBA318 /* File.cpp in Sources */, - B650907E133300BA00FBA318 /* Disk.cpp in Sources */, - B6509080133300DD00FBA318 /* profuse.cpp in Sources */, - B6509086133300FB00FBA318 /* profuse_xattr.cpp in Sources */, - B6509087133300FB00FBA318 /* profuse_stat.cpp in Sources */, - B6509088133300FB00FBA318 /* profuse_file.cpp in Sources */, - B6509089133300FB00FBA318 /* profuse_dirent.cpp in Sources */, + B650908C133304C800FBA318 /* Endian.cpp in Sources */, + B650908D133304C800FBA318 /* BlockDevice.cpp in Sources */, + B650908E133304C800FBA318 /* DavexDiskImage.cpp in Sources */, + B650908F133304C800FBA318 /* DiskCopy42Image.cpp in Sources */, + B6509090133304C800FBA318 /* DiskImage.cpp in Sources */, + B6509091133304C800FBA318 /* RawDevice.cpp in Sources */, + B6509092133304C800FBA318 /* UniversalDiskImage.cpp in Sources */, + B6509093133304C800FBA318 /* BlockCache.cpp in Sources */, + B6509094133304C800FBA318 /* ConcreteBlockCache.cpp in Sources */, + B6509095133304C800FBA318 /* MappedBlockCache.cpp in Sources */, + B6509096133304C800FBA318 /* File.cpp in Sources */, + B6509097133304C800FBA318 /* MappedFile.cpp in Sources */, + B6509098133304C800FBA318 /* Adaptor.cpp in Sources */, + B6509099133304C800FBA318 /* SDKImage.cpp in Sources */, + B650909A133304C800FBA318 /* Exception.cpp in Sources */, + B650909B133304C800FBA318 /* Exception.cpp in Sources */, + B650909C133304C800FBA318 /* Exception.cpp in Sources */, + B650909D133304C800FBA318 /* Exception.cpp in Sources */, + B650909E133304C800FBA318 /* Lock.cpp in Sources */, + B650909F133304C800FBA318 /* DateTime.cpp in Sources */, + B65090A0133304C800FBA318 /* File.cpp in Sources */, + B65090A1133304C800FBA318 /* Disk.cpp in Sources */, + B65090A2133304C800FBA318 /* profuse.cpp in Sources */, + B65090A3133304C800FBA318 /* profuse_xattr.cpp in Sources */, + B65090A4133304C800FBA318 /* profuse_stat.cpp in Sources */, + B65090A5133304C800FBA318 /* profuse_file.cpp in Sources */, + B65090A6133304C800FBA318 /* profuse_dirent.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -893,7 +894,7 @@ ); OTHER_CFLAGS = "-DHAVE_NUFX"; PREBINDING = NO; - PRODUCT_NAME = apfpm; + PRODUCT_NAME = apfm; }; name = Debug; }; @@ -912,7 +913,7 @@ ); OTHER_CFLAGS = "-DHAVE_NUFX"; PREBINDING = NO; - PRODUCT_NAME = apfpm; + PRODUCT_NAME = apfm; ZERO_LINK = NO; }; name = Release; @@ -949,7 +950,7 @@ }; name = Release; }; - B65090711333006900FBA318 /* Debug */ = { + B65090AD133304C800FBA318 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -969,7 +970,7 @@ }; name = Debug; }; - B65090721333006900FBA318 /* Debug Universal */ = { + B65090AE133304C800FBA318 /* Debug Universal */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -989,7 +990,7 @@ }; name = "Debug Universal"; }; - B65090731333006900FBA318 /* Debug fuse */ = { + B65090AF133304C800FBA318 /* Debug fuse */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -1006,7 +1007,7 @@ }; name = "Debug fuse"; }; - B65090741333006900FBA318 /* Release */ = { + B65090B0133304C800FBA318 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -1061,7 +1062,7 @@ ); OTHER_CFLAGS = "-DHAVE_NUFX"; PREBINDING = NO; - PRODUCT_NAME = apfpm; + PRODUCT_NAME = apfm; }; name = "Debug fuse"; }; @@ -1420,13 +1421,13 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - B65090701333006900FBA318 /* Build configuration list for PBXNativeTarget "profuse" */ = { + B65090AC133304C800FBA318 /* Build configuration list for PBXNativeTarget "profuse" */ = { isa = XCConfigurationList; buildConfigurations = ( - B65090711333006900FBA318 /* Debug */, - B65090721333006900FBA318 /* Debug Universal */, - B65090731333006900FBA318 /* Debug fuse */, - B65090741333006900FBA318 /* Release */, + B65090AD133304C800FBA318 /* Debug */, + B65090AE133304C800FBA318 /* Debug Universal */, + B65090AF133304C800FBA318 /* Debug fuse */, + B65090B0133304C800FBA318 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; From a686f7d6461d75c4670bfe798e40345afaf18831 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 19 Mar 2011 01:57:28 +0000 Subject: [PATCH 227/236] rename xcode project git-svn-id: https://profuse.googlecode.com/svn/branches/v2@395 aa027e90-d47c-11dd-86d7-074df07e0730 --- ProFUSE.xcodeproj/kelvin.pbxuser | 1560 ++++++++++++++++++++++++ ProFUSE.xcodeproj/kelvin.perspectivev3 | 1547 +++++++++++++++++++++++ ProFUSE.xcodeproj/project.pbxproj | 1482 ++++++++++++++++++++++ 3 files changed, 4589 insertions(+) create mode 100644 ProFUSE.xcodeproj/kelvin.pbxuser create mode 100644 ProFUSE.xcodeproj/kelvin.perspectivev3 create mode 100644 ProFUSE.xcodeproj/project.pbxproj diff --git a/ProFUSE.xcodeproj/kelvin.pbxuser b/ProFUSE.xcodeproj/kelvin.pbxuser new file mode 100644 index 0000000..da439c9 --- /dev/null +++ b/ProFUSE.xcodeproj/kelvin.pbxuser @@ -0,0 +1,1560 @@ +// !$*UTF8*$! +{ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + activeBuildConfigurationName = "Debug Universal"; + activeExecutable = B6F3648111AB36260045E114 /* xattr */; + activeTarget = B6F3647F11AB36260045E114 /* xattr */; + addToTargets = ( + ); + breakpoints = ( + B6F3642F11AA1E150045E114 /* NibbleTest.cpp:76 */, + B6F3657711AE24C40045E114 /* apfm.cpp:589 */, + B6F3663D11B1809A0045E114 /* Adaptor.cpp:167 */, + ); + codeSenseManager = B63EFA6811A093C200C90DCE /* Code sense */; + executables = ( + B63EFCCF11A36C7300C90DCE /* apfm */, + B63EFE8211A4886C00C90DCE /* newfs_pascal */, + B656AE0411A84F5800AB578A /* fuse_pascal */, + B656AF0411AA105500AB578A /* NibbleTest */, + B6F3648111AB36260045E114 /* xattr */, + B6F3682611B431AC0045E114 /* newfs_prodos */, + ); + perUserDictionary = { + "PBXConfiguration.PBXBreakpointsDataSource.v1:1CA1AED706398EBD00589147" = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXBreakpointsDataSource_BreakpointID; + PBXFileTableDataSourceColumnWidthsKey = ( + 20, + 20, + 198, + 20, + 99, + 99, + 29, + 20, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXBreakpointsDataSource_ActionID, + PBXBreakpointsDataSource_TypeID, + PBXBreakpointsDataSource_BreakpointID, + PBXBreakpointsDataSource_UseID, + PBXBreakpointsDataSource_LocationID, + PBXBreakpointsDataSource_ConditionID, + PBXBreakpointsDataSource_IgnoreCountID, + PBXBreakpointsDataSource_ContinueID, + ); + }; + PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; + PBXFileTableDataSourceColumnWidthsKey = ( + 22, + 300, + 548, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXExecutablesDataSource_ActiveFlagID, + PBXExecutablesDataSource_NameID, + PBXExecutablesDataSource_CommentsID, + ); + }; + PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_ObjectSize_ColumnID; + PBXFileTableDataSourceColumnWidthsKey = ( + 20, + 660, + 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.PBXTargetDataSource.PBXTargetDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; + PBXFileTableDataSourceColumnWidthsKey = ( + 20, + 620, + 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 = 320626757; + PBXWorkspaceStateSaveDate = 320626757; + }; + perUserProjectItems = { + B6272A9911D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9911D5AC5E0073C73A /* PBXTextBookmark */; + B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */; + B6272A9C11D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9C11D5AC5E0073C73A /* PBXTextBookmark */; + B6272B0D11D691320073C73A /* PBXTextBookmark */ = B6272B0D11D691320073C73A /* PBXTextBookmark */; + B6272B0E11D691320073C73A /* PBXTextBookmark */ = B6272B0E11D691320073C73A /* PBXTextBookmark */; + B6272B0F11D691320073C73A /* PBXTextBookmark */ = B6272B0F11D691320073C73A /* PBXTextBookmark */; + B6272B1011D691320073C73A /* PBXTextBookmark */ = B6272B1011D691320073C73A /* PBXTextBookmark */; + B6272B1111D691320073C73A /* PBXTextBookmark */ = B6272B1111D691320073C73A /* PBXTextBookmark */; + B6272B1311D691320073C73A /* PBXTextBookmark */ = B6272B1311D691320073C73A /* PBXTextBookmark */; + B6272B1411D691320073C73A /* PBXTextBookmark */ = B6272B1411D691320073C73A /* PBXTextBookmark */; + B6272B1611D691320073C73A /* PBXTextBookmark */ = B6272B1611D691320073C73A /* PBXTextBookmark */; + B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */ = B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */; + B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */ = B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */; + B63EFDA011A4488200C90DCE /* PBXTextBookmark */ = B63EFDA011A4488200C90DCE /* PBXTextBookmark */; + B63EFDA511A4488200C90DCE /* PBXTextBookmark */ = B63EFDA511A4488200C90DCE /* PBXTextBookmark */; + B63EFDA711A4488200C90DCE /* PBXTextBookmark */ = B63EFDA711A4488200C90DCE /* PBXTextBookmark */; + B63EFDA911A4488200C90DCE /* PBXTextBookmark */ = B63EFDA911A4488200C90DCE /* PBXTextBookmark */; + B63EFDAB11A4488200C90DCE /* PBXTextBookmark */ = B63EFDAB11A4488200C90DCE /* PBXTextBookmark */; + B63EFDAD11A4488200C90DCE /* PBXTextBookmark */ = B63EFDAD11A4488200C90DCE /* PBXTextBookmark */; + B63EFDAF11A4488200C90DCE /* PBXTextBookmark */ = B63EFDAF11A4488200C90DCE /* PBXTextBookmark */; + B63EFDB111A4488200C90DCE /* PBXTextBookmark */ = B63EFDB111A4488200C90DCE /* PBXTextBookmark */; + B63EFDB311A4488200C90DCE /* PBXTextBookmark */ = B63EFDB311A4488200C90DCE /* PBXTextBookmark */; + B63EFDF211A4504200C90DCE /* PBXTextBookmark */ = B63EFDF211A4504200C90DCE /* PBXTextBookmark */; + B63EFEA011A488C200C90DCE /* PBXTextBookmark */ = B63EFEA011A488C200C90DCE /* PBXTextBookmark */; + B63EFEA111A488C200C90DCE /* PBXTextBookmark */ = B63EFEA111A488C200C90DCE /* PBXTextBookmark */; + B63EFEA811A488C200C90DCE /* PBXTextBookmark */ = B63EFEA811A488C200C90DCE /* PBXTextBookmark */; + B656AE2611A84FA400AB578A /* PBXTextBookmark */ = B656AE2611A84FA400AB578A /* PBXTextBookmark */; + B65CFB6911B495790024A2D9 /* PBXTextBookmark */ = B65CFB6911B495790024A2D9 /* PBXTextBookmark */; + B6A53B8E1319DDFC00C9070F /* PBXTextBookmark */ = B6A53B8E1319DDFC00C9070F /* PBXTextBookmark */; + B6A53BC7131B400800C9070F /* PBXTextBookmark */ = B6A53BC7131B400800C9070F /* PBXTextBookmark */; + B6A53BC8131B400800C9070F /* PBXTextBookmark */ = B6A53BC8131B400800C9070F /* PBXTextBookmark */; + B6A53C34131B4CF800C9070F /* PBXTextBookmark */ = B6A53C34131B4CF800C9070F /* PBXTextBookmark */; + B6AA3AB21318D063007D4BA1 /* PBXTextBookmark */ = B6AA3AB21318D063007D4BA1 /* PBXTextBookmark */; + B6AA3AB31318D063007D4BA1 /* PBXTextBookmark */ = B6AA3AB31318D063007D4BA1 /* PBXTextBookmark */; + B6AA3AB41318D063007D4BA1 /* PBXTextBookmark */ = B6AA3AB41318D063007D4BA1 /* PBXTextBookmark */; + B6E5F0DD11A60726000AD141 /* PBXTextBookmark */ = B6E5F0DD11A60726000AD141 /* PBXTextBookmark */; + B6E5F0F211A73144000AD141 /* PBXTextBookmark */ = B6E5F0F211A73144000AD141 /* PBXTextBookmark */; + B6E5F11211A73340000AD141 /* PBXTextBookmark */ = B6E5F11211A73340000AD141 /* PBXTextBookmark */; + B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */ = B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */; + B6E5F18211A76B74000AD141 /* PBXTextBookmark */ = B6E5F18211A76B74000AD141 /* PBXTextBookmark */; + B6F3647111AB35FE0045E114 /* PBXTextBookmark */ = B6F3647111AB35FE0045E114 /* PBXTextBookmark */; + B6F3649E11AB59190045E114 /* PBXTextBookmark */ = B6F3649E11AB59190045E114 /* PBXTextBookmark */; + B6F364B711AB84840045E114 /* PBXTextBookmark */ = B6F364B711AB84840045E114 /* PBXTextBookmark */; + B6F3652E11ADD5D20045E114 /* PBXTextBookmark */ = B6F3652E11ADD5D20045E114 /* PBXTextBookmark */; + B6F3653011ADD5D20045E114 /* PBXTextBookmark */ = B6F3653011ADD5D20045E114 /* PBXTextBookmark */; + B6F3657E11AE255B0045E114 /* PBXTextBookmark */ = B6F3657E11AE255B0045E114 /* PBXTextBookmark */; + B6F3665411B190370045E114 /* PBXTextBookmark */ = B6F3665411B190370045E114 /* PBXTextBookmark */; + B6F3665C11B194AC0045E114 /* PBXTextBookmark */ = B6F3665C11B194AC0045E114 /* PBXTextBookmark */; + B6F366C411B1A28C0045E114 /* PBXTextBookmark */ = B6F366C411B1A28C0045E114 /* PBXTextBookmark */; + B6F366C611B1A28C0045E114 /* PBXTextBookmark */ = B6F366C611B1A28C0045E114 /* PBXTextBookmark */; + B6F366C711B1A28C0045E114 /* PBXTextBookmark */ = B6F366C711B1A28C0045E114 /* PBXTextBookmark */; + B6F366C811B1A28C0045E114 /* PBXTextBookmark */ = B6F366C811B1A28C0045E114 /* PBXTextBookmark */; + B6F366C911B1A28C0045E114 /* PBXTextBookmark */ = B6F366C911B1A28C0045E114 /* PBXTextBookmark */; + B6F366CA11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CA11B1A28C0045E114 /* PBXTextBookmark */; + B6F366CB11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CB11B1A28C0045E114 /* PBXTextBookmark */; + B6F3677C11B326580045E114 /* PBXTextBookmark */ = B6F3677C11B326580045E114 /* PBXTextBookmark */; + B6F3677D11B326580045E114 /* PBXTextBookmark */ = B6F3677D11B326580045E114 /* PBXTextBookmark */; + B6F3677E11B326580045E114 /* PBXTextBookmark */ = B6F3677E11B326580045E114 /* PBXTextBookmark */; + B6F367A011B330D10045E114 /* PBXTextBookmark */ = B6F367A011B330D10045E114 /* PBXTextBookmark */; + B6F367AE11B337A70045E114 /* PBXTextBookmark */ = B6F367AE11B337A70045E114 /* PBXTextBookmark */; + B6F3684A11B44D090045E114 /* PBXTextBookmark */ = B6F3684A11B44D090045E114 /* PBXTextBookmark */; + B6F8D4AD131CB30300461B54 /* PBXTextBookmark */ = B6F8D4AD131CB30300461B54 /* PBXTextBookmark */; + }; + sourceControlManager = B63EFA6711A093C200C90DCE /* Source Control */; + userBuildSettings = { + }; + }; + B6272A8E11D5AC3C0073C73A /* apfm.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 13975}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 562}"; + }; + }; + B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 4069}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 672}"; + }; + }; + B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1245, 7124}}"; + sepNavSelRange = "{1531, 0}"; + sepNavVisRange = "{367, 1775}"; + }; + }; + B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 4615}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 477}"; + }; + }; + B6272A9211D5AC3C0073C73A /* xattr.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 5434}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 936}"; + }; + }; + B6272A9911D5AC5E0073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272A8E11D5AC3C0073C73A /* apfm.cpp */; + name = "apfm.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 562; + vrLoc = 0; + }; + B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */; + name = "fuse_pascal_ops.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 643; + vrLoc = 0; + }; + B6272A9C11D5AC5E0073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */; + name = "newfs_pascal.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 477; + vrLoc = 0; + }; + B6272AA211D5AC840073C73A /* newfs_prodos.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 3094}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 1145}"; + }; + }; + B6272AA511D5AE0C0073C73A /* Bitmap.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1249, 2912}}"; + sepNavSelRange = "{108, 0}"; + sepNavVisRange = "{0, 1570}"; + }; + }; + B6272AA611D5AE0C0073C73A /* Bitmap.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1249, 978}}"; + sepNavSelRange = "{147, 0}"; + sepNavVisRange = "{0, 888}"; + }; + }; + B6272AA711D5AE0C0073C73A /* DateTime.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 1911}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 870}"; + }; + }; + B6272B0D11D691320073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272A9211D5AC3C0073C73A /* xattr.cpp */; + name = "xattr.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 936; + vrLoc = 0; + }; + B6272B0E11D691320073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272AA211D5AC840073C73A /* newfs_prodos.cpp */; + name = "newfs_prodos.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1145; + vrLoc = 0; + }; + B6272B0F11D691320073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272AA711D5AE0C0073C73A /* DateTime.cpp */; + name = "DateTime.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 870; + vrLoc = 0; + }; + B6272B1011D691320073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272AA511D5AE0C0073C73A /* Bitmap.cpp */; + name = "Bitmap.cpp: 29"; + rLen = 0; + rLoc = 456; + rType = 0; + vrLen = 679; + vrLoc = 0; + }; + B6272B1111D691320073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + comments = "'Device' has not been declared"; + fRef = B6272B1211D691320073C73A /* Bitmap.h */; + rLen = 1; + rLoc = 21; + rType = 1; + }; + B6272B1211D691320073C73A /* Bitmap.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = Bitmap.h; + path = ./ProDOS/Bitmap.h; + sourceTree = ""; + }; + B6272B1311D691320073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9611A094E000C90DCE /* BlockDevice.h */; + name = "BlockDevice.h: 24"; + rLen = 0; + rLoc = 431; + rType = 0; + vrLen = 853; + vrLoc = 0; + }; + B6272B1411D691320073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; + name = "BlockDevice.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 740; + vrLoc = 0; + }; + B6272B1611D691320073C73A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; + name = "BlockCache.cpp: 58"; + rLen = 0; + rLoc = 962; + rType = 0; + vrLen = 718; + vrLoc = 403; + }; + B63EFA6711A093C200C90DCE /* Source Control */ = { + isa = PBXSourceControlManager; + fallbackIsa = XCSourceControlManager; + isSCMEnabled = 0; + scmConfiguration = { + repositoryNamesForRoots = { + "" = ""; + }; + }; + }; + B63EFA6811A093C200C90DCE /* Code sense */ = { + isa = PBXCodeSenseManager; + indexTemplatePath = ""; + }; + B63EFA7511A0948500C90DCE /* Endian.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 1339}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 819}"; + }; + }; + B63EFA7611A0948500C90DCE /* Endian.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {409, 2080}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 97}"; + }; + }; + B63EFA7711A0948500C90DCE /* IOBuffer.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 562}}"; + sepNavSelRange = "{190, 0}"; + sepNavVisRange = "{0, 206}"; + }; + }; + B63EFA9511A094E000C90DCE /* BlockDevice.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 3198}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 740}"; + }; + }; + B63EFA9611A094E000C90DCE /* BlockDevice.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 780}}"; + sepNavSelRange = "{431, 0}"; + sepNavVisRange = "{0, 853}"; + }; + }; + B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 2119}}"; + sepNavSelRange = "{2355, 0}"; + sepNavVisRange = "{1920, 875}"; + }; + }; + B63EFA9811A094E000C90DCE /* DavexDiskImage.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1015, 944}}"; + sepNavSelRange = "{597, 0}"; + sepNavVisRange = "{0, 740}"; + }; + }; + B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 2938}}"; + sepNavSelRange = "{2053, 0}"; + sepNavVisRange = "{1629, 925}"; + }; + }; + B63EFA9C11A094E000C90DCE /* DiskCopy42Image.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1015, 944}}"; + sepNavSelRange = "{661, 0}"; + sepNavVisRange = "{0, 772}"; + }; + }; + B63EFA9D11A094E000C90DCE /* DiskImage.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1009, 2743}}"; + sepNavSelRange = "{550, 0}"; + sepNavVisRange = "{0, 1053}"; + }; + }; + B63EFA9E11A094E000C90DCE /* DiskImage.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 1027}}"; + sepNavSelRange = "{652, 0}"; + sepNavVisRange = "{0, 1529}"; + }; + }; + B63EFAA111A094E000C90DCE /* RawDevice.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 4186}}"; + sepNavSelRange = "{2579, 0}"; + sepNavVisRange = "{2262, 800}"; + }; + }; + B63EFAA211A094E000C90DCE /* RawDevice.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1009, 958}}"; + sepNavSelRange = "{894, 0}"; + sepNavVisRange = "{0, 1056}"; + }; + }; + B63EFAA311A094E000C90DCE /* TrackSector.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1178, 341}}"; + sepNavSelRange = "{262, 0}"; + sepNavVisRange = "{0, 316}"; + }; + }; + B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 2067}}"; + sepNavSelRange = "{956, 0}"; + sepNavVisRange = "{497, 808}"; + }; + }; + B63EFAA511A094E000C90DCE /* UniversalDiskImage.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 546}}"; + sepNavSelRange = "{507, 4}"; + sepNavVisRange = "{0, 692}"; + }; + }; + B63EFAB611A098C400C90DCE /* BlockCache.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 962}}"; + sepNavSelRange = "{962, 0}"; + sepNavVisRange = "{403, 718}"; + }; + }; + B63EFAB711A098C400C90DCE /* BlockCache.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 767}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{118, 910}"; + }; + }; + B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 5070}}"; + sepNavSelRange = "{5248, 0}"; + sepNavVisRange = "{4735, 1303}"; + }; + }; + B63EFAB911A098C400C90DCE /* ConcreteBlockCache.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 932}}"; + sepNavSelRange = "{526, 0}"; + sepNavVisRange = "{0, 1257}"; + }; + }; + B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 1846}}"; + sepNavSelRange = "{1292, 0}"; + sepNavVisRange = "{0, 1315}"; + }; + }; + B63EFABB11A098C400C90DCE /* MappedBlockCache.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 948}}"; + sepNavSelRange = "{630, 0}"; + sepNavVisRange = "{0, 659}"; + }; + }; + B63EFAC911A09DAA00C90DCE /* File.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1009, 1599}}"; + sepNavSelRange = "{1429, 0}"; + sepNavVisRange = "{248, 1374}"; + }; + }; + B63EFACA11A09DAA00C90DCE /* File.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 754}}"; + sepNavSelRange = "{244, 0}"; + sepNavVisRange = "{0, 749}"; + }; + }; + B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 2574}}"; + sepNavSelRange = "{1115, 0}"; + sepNavVisRange = "{0, 1267}"; + }; + }; + B63EFACC11A09DAA00C90DCE /* MappedFile.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 932}}"; + sepNavSelRange = "{211, 0}"; + sepNavVisRange = "{0, 927}"; + }; + }; + B63EFAD011A09DB500C90DCE /* auto.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1264, 1365}}"; + sepNavSelRange = "{287, 0}"; + sepNavVisRange = "{517, 1036}"; + }; + }; + B63EFAD111A09DB500C90DCE /* Exception.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 562}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 157}"; + }; + }; + B63EFAD211A09DB500C90DCE /* Exception.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 1911}}"; + sepNavSelRange = "{633, 13}"; + sepNavVisRange = "{0, 1568}"; + }; + }; + B63EFAD311A09DB500C90DCE /* Lock.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1207, 914}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 353}"; + }; + }; + B63EFB0611A0AC4800C90DCE /* Adaptor.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 1066}}"; + sepNavSelRange = "{1806, 0}"; + sepNavVisRange = "{442, 1126}"; + }; + }; + B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 6448}}"; + sepNavSelRange = "{8303, 0}"; + sepNavVisRange = "{2730, 1774}"; + }; + }; + B63EFB8811A1FB2500C90DCE /* DiskImage.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = DiskImage.h; + path = ./Device/DiskImage.h; + sourceTree = ""; + }; + B63EFBE811A244EE00C90DCE /* Date.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 611}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 834}"; + }; + }; + B63EFBE911A244EE00C90DCE /* Date.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 585}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 654}"; + }; + }; + B63EFBEA11A244EE00C90DCE /* Entry.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {701, 1248}}"; + sepNavSelRange = "{22, 0}"; + sepNavVisRange = "{0, 1220}"; + }; + }; + B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 9581}}"; + sepNavSelRange = "{628, 36}"; + sepNavVisRange = "{335, 746}"; + }; + }; + B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 13026}}"; + sepNavSelRange = "{13717, 0}"; + sepNavVisRange = "{13228, 1176}"; + }; + }; + B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA7611A0948500C90DCE /* Endian.h */; + name = "Endian.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 97; + vrLoc = 0; + }; + B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAB911A098C400C90DCE /* ConcreteBlockCache.h */; + name = "ConcreteBlockCache.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 297; + vrLoc = 0; + }; + B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1009, 1339}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{687, 1732}"; + }; + }; + B63EFCC811A366C800C90DCE /* MappedFile.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = MappedFile.h; + path = ./File/MappedFile.h; + sourceTree = ""; + }; + B63EFCCD11A36C7300C90DCE /* apfm */ = { + activeExec = 0; + executables = ( + B63EFCCF11A36C7300C90DCE /* apfm */, + ); + }; + B63EFCCF11A36C7300C90DCE /* apfm */ = { + isa = PBXExecutable; + activeArgIndices = ( + YES, + YES, + YES, + ); + argumentStrings = ( + /Users/kelvin/Projects/PROFuseX/bleh.po, + cat, + XATTR.CPP, + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 1; + configStateDict = { + }; + customDataFormattersEnabled = 1; + dataTipCustomDataFormattersEnabled = 1; + dataTipShowTypeColumn = 1; + dataTipSortType = 0; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + dylibVariantSuffix = ""; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + libgmallocEnabled = 0; + name = apfm; + savedGlobals = { + }; + showTypeColumn = 0; + sourceDirectories = ( + ); + variableFormatDictionary = { + "_length-size_t-Device::DOSOrderDiskImage::DOSOrderDiskImage" = 1; + "size-size_t-MappedFile::init" = 1; + }; + }; + B63EFDA011A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDA111A4488200C90DCE /* memory */; + name = "memory: 300"; + rLen = 0; + rLoc = 10169; + rType = 0; + vrLen = 348; + vrLoc = 9980; + }; + B63EFDA111A4488200C90DCE /* memory */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.h; + name = memory; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/memory"; + sourceTree = ""; + }; + B63EFDA511A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDA611A4488200C90DCE /* new */; + name = "new: 105"; + rLen = 0; + rLoc = 3667; + rType = 0; + vrLen = 1002; + vrLoc = 3039; + }; + B63EFDA611A4488200C90DCE /* new */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.h; + name = new; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/new"; + sourceTree = ""; + }; + B63EFDA711A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDA811A4488200C90DCE /* new_allocator.h */; + name = "new_allocator.h: 70"; + rLen = 0; + rLoc = 2448; + rType = 0; + vrLen = 768; + vrLoc = 2080; + }; + B63EFDA811A4488200C90DCE /* new_allocator.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = new_allocator.h; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/ext/new_allocator.h"; + sourceTree = ""; + }; + B63EFDA911A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDAA11A4488200C90DCE /* allocator.h */; + name = "allocator.h: 103"; + rLen = 0; + rLoc = 3498; + rType = 0; + vrLen = 729; + vrLoc = 3092; + }; + B63EFDAA11A4488200C90DCE /* allocator.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = allocator.h; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/allocator.h"; + sourceTree = ""; + }; + B63EFDAB11A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDAC11A4488200C90DCE /* stl_iterator.h */; + name = "stl_iterator.h: 718"; + rLen = 0; + rLoc = 22590; + rType = 0; + vrLen = 1056; + vrLoc = 22176; + }; + B63EFDAC11A4488200C90DCE /* stl_iterator.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = stl_iterator.h; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_iterator.h"; + sourceTree = ""; + }; + B63EFDAD11A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDAE11A4488200C90DCE /* stl_algobase.h */; + name = "stl_algobase.h: 398"; + rLen = 0; + rLoc = 13483; + rType = 0; + vrLen = 1046; + vrLoc = 13073; + }; + B63EFDAE11A4488200C90DCE /* stl_algobase.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = stl_algobase.h; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_algobase.h"; + sourceTree = ""; + }; + B63EFDAF11A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDB011A4488200C90DCE /* stl_uninitialized.h */; + name = "stl_uninitialized.h: 75"; + rLen = 0; + rLoc = 3073; + rType = 0; + vrLen = 804; + vrLoc = 8199; + }; + B63EFDB011A4488200C90DCE /* stl_uninitialized.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = stl_uninitialized.h; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_uninitialized.h"; + sourceTree = ""; + }; + B63EFDB111A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDB211A4488200C90DCE /* vector.tcc */; + name = "vector.tcc: 293"; + rLen = 0; + rLoc = 9731; + rType = 0; + vrLen = 818; + vrLoc = 9315; + }; + B63EFDB211A4488200C90DCE /* vector.tcc */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + name = vector.tcc; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/vector.tcc"; + sourceTree = ""; + }; + B63EFDB311A4488200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFDB411A4488200C90DCE /* stl_vector.h */; + name = "stl_vector.h: 608"; + rLen = 0; + rLoc = 20940; + rType = 0; + vrLen = 779; + vrLoc = 20537; + }; + B63EFDB411A4488200C90DCE /* stl_vector.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = stl_vector.h; + path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_vector.h"; + sourceTree = ""; + }; + B63EFDF211A4504200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAD011A09DB500C90DCE /* auto.h */; + name = "auto.h: 20"; + rLen = 0; + rLoc = 287; + rType = 0; + vrLen = 479; + vrLoc = 0; + }; + B63EFE8011A4886C00C90DCE /* newfs_pascal */ = { + activeExec = 0; + executables = ( + B63EFE8211A4886C00C90DCE /* newfs_pascal */, + ); + }; + B63EFE8211A4886C00C90DCE /* newfs_pascal */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 1; + configStateDict = { + }; + customDataFormattersEnabled = 1; + dataTipCustomDataFormattersEnabled = 1; + dataTipShowTypeColumn = 1; + dataTipSortType = 0; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + libgmallocEnabled = 0; + name = newfs_pascal; + showTypeColumn = 0; + sourceDirectories = ( + ); + }; + B63EFEA011A488C200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9C11A094E000C90DCE /* DiskCopy42Image.h */; + name = "DiskCopy42Image.h: 19"; + rLen = 0; + rLoc = 459; + rType = 0; + vrLen = 803; + vrLoc = 0; + }; + B63EFEA111A488C200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9811A094E000C90DCE /* DavexDiskImage.h */; + name = "DavexDiskImage.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 763; + vrLoc = 0; + }; + B63EFEA811A488C200C90DCE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; + name = "Date.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 834; + vrLoc = 0; + }; + B656AE0211A84F5800AB578A /* fuse_pascal */ = { + activeExec = 0; + executables = ( + B656AE0411A84F5800AB578A /* fuse_pascal */, + ); + }; + B656AE0411A84F5800AB578A /* fuse_pascal */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 0; + configStateDict = { + }; + customDataFormattersEnabled = 1; + dataTipCustomDataFormattersEnabled = 1; + dataTipShowTypeColumn = 1; + dataTipSortType = 0; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + libgmallocEnabled = 0; + name = fuse_pascal; + showTypeColumn = 0; + sourceDirectories = ( + ); + }; + B656AE2611A84FA400AB578A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAA211A094E000C90DCE /* RawDevice.h */; + name = "RawDevice.h: 15"; + rLen = 0; + rLoc = 186; + rType = 0; + vrLen = 781; + vrLoc = 126; + }; + B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1178, 1248}}"; + sepNavSelRange = "{1680, 0}"; + sepNavVisRange = "{1472, 529}"; + }; + }; + B656AF0211AA105500AB578A /* NibbleTest */ = { + activeExec = 0; + executables = ( + B656AF0411AA105500AB578A /* NibbleTest */, + ); + }; + B656AF0411AA105500AB578A /* NibbleTest */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 1; + configStateDict = { + }; + customDataFormattersEnabled = 1; + dataTipCustomDataFormattersEnabled = 1; + dataTipShowTypeColumn = 1; + dataTipSortType = 0; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + dylibVariantSuffix = ""; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + libgmallocEnabled = 0; + name = NibbleTest; + savedGlobals = { + }; + showTypeColumn = 0; + sourceDirectories = ( + ); + variableFormatDictionary = { + "87-unsigned int-Device::NibbleAdaptor::NibbleAdaptor" = 1; + "checksum-uint8_t-Device::NibbleAdaptor::readTrackSector" = 1; + "index-unsigned int-Device::NibbleAdaptor::readTrackSector" = 1; + "offset-int-Device::NibbleAdaptor::NibbleAdaptor" = 1; + "offset-unsigned int-Device::NibbleAdaptor::readTrackSector" = 1; + "val-uint8_t-Device::NibbleAdaptor::decode62" = 1; + "x-uint8_t-Device::NibbleAdaptor::readTrackSector" = 1; + "y-uint8_t-Device::NibbleAdaptor::readTrackSector" = 1; + }; + }; + B65CFB6911B495790024A2D9 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; + name = "RawDevice.cpp: 136"; + rLen = 0; + rLoc = 2579; + rType = 0; + vrLen = 800; + vrLoc = 2262; + }; + B6A53B851319DA3D00C9070F /* smart_pointers.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 475}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 903}"; + }; + }; + B6A53B8E1319DDFC00C9070F /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6A53B851319DA3D00C9070F /* smart_pointers.h */; + name = "smart_pointers.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 903; + vrLoc = 0; + }; + B6A53BC7131B400800C9070F /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F3651B11ADD0280045E114 /* FileEntry.h */; + name = "FileEntry.h: 20"; + rLen = 23; + rLoc = 292; + rType = 0; + vrLen = 797; + vrLoc = 62; + }; + B6A53BC8131B400800C9070F /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; + name = "FileEntry.cpp: 40"; + rLen = 36; + rLoc = 628; + rType = 0; + vrLen = 746; + vrLoc = 335; + }; + B6A53C34131B4CF800C9070F /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 616"; + rLen = 0; + rLoc = 13717; + rType = 0; + vrLen = 1185; + vrLoc = 13219; + }; + B6AA3AB21318D063007D4BA1 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAB711A098C400C90DCE /* BlockCache.h */; + name = "BlockCache.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 910; + vrLoc = 118; + }; + B6AA3AB31318D063007D4BA1 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; + name = "Endian.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 819; + vrLoc = 0; + }; + B6AA3AB41318D063007D4BA1 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */; + name = "fuse_pascal.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 672; + vrLoc = 0; + }; + B6E5F0DD11A60726000AD141 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; + name = "ConcreteBlockCache.cpp: 185"; + rLen = 0; + rLoc = 4102; + rType = 0; + vrLen = 885; + vrLoc = 3468; + }; + B6E5F0F211A73144000AD141 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFABB11A098C400C90DCE /* MappedBlockCache.h */; + name = "MappedBlockCache.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 667; + vrLoc = 0; + }; + B6E5F11211A73340000AD141 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA7711A0948500C90DCE /* IOBuffer.h */; + name = "IOBuffer.h: 12"; + rLen = 0; + rLoc = 190; + rType = 0; + vrLen = 206; + vrLoc = 0; + }; + B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */; + name = "IOBuffer.cpp.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1056; + vrLoc = 1363; + }; + B6E5F18211A76B74000AD141 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAD111A09DB500C90DCE /* Exception.cpp */; + name = "Exception.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 157; + vrLoc = 0; + }; + B6F3642F11AA1E150045E114 /* NibbleTest.cpp:76 */ = { + isa = PBXFileBreakpoint; + actions = ( + ); + breakpointStyle = 0; + continueAfterActions = 0; + countType = 0; + delayBeforeContinue = 0; + fileReference = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + functionName = "main(int argc, char **argv)"; + hitCount = 0; + ignoreCount = 0; + lineNumber = 76; + modificationTime = 299278551.142724; + originalNumberOfMultipleMatches = 1; + state = 0; + }; + B6F3647111AB35FE0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB0611A0AC4800C90DCE /* Adaptor.h */; + name = "Adaptor.h: 82"; + rLen = 0; + rLoc = 1806; + rType = 0; + vrLen = 1126; + vrLoc = 442; + }; + B6F3647F11AB36260045E114 /* xattr */ = { + activeExec = 0; + executables = ( + B6F3648111AB36260045E114 /* xattr */, + ); + }; + B6F3648111AB36260045E114 /* xattr */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 0; + configStateDict = { + }; + customDataFormattersEnabled = 1; + dataTipCustomDataFormattersEnabled = 1; + dataTipShowTypeColumn = 1; + dataTipSortType = 0; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + libgmallocEnabled = 0; + name = xattr; + showTypeColumn = 0; + sourceDirectories = ( + ); + }; + B6F3649E11AB59190045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; + name = "File.cpp: 35"; + rLen = 0; + rLoc = 384; + rType = 0; + vrLen = 571; + vrLoc = 0; + }; + B6F364B711AB84840045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAD211A09DB500C90DCE /* Exception.h */; + name = "Exception.h: 39"; + rLen = 10; + rLoc = 783; + rType = 0; + vrLen = 1003; + vrLoc = 434; + }; + B6F3651A11ADD0280045E114 /* VolumeEntry.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 1365}}"; + sepNavSelRange = "{145, 0}"; + sepNavVisRange = "{0, 974}"; + }; + }; + B6F3651B11ADD0280045E114 /* FileEntry.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 1430}}"; + sepNavSelRange = "{292, 23}"; + sepNavVisRange = "{62, 797}"; + }; + }; + B6F3651C11ADD0280045E114 /* Entry.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 1079}}"; + sepNavSelRange = "{1399, 0}"; + sepNavVisRange = "{0, 605}"; + }; + }; + B6F3652711ADD52B0045E114 /* Pascal.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 530}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 173}"; + }; + }; + B6F3652E11ADD5D20045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F3652711ADD52B0045E114 /* Pascal.h */; + name = "Pascal.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 173; + vrLoc = 0; + }; + B6F3653011ADD5D20045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; + name = "Entry.cpp: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 712; + vrLoc = 0; + }; + B6F3657711AE24C40045E114 /* apfm.cpp:589 */ = { + isa = PBXFileBreakpoint; + actions = ( + ); + breakpointStyle = 0; + continueAfterActions = 0; + countType = 0; + delayBeforeContinue = 0; + fileReference = B6272A8E11D5AC3C0073C73A /* apfm.cpp */; + functionName = "action_rm(int argc, char **argv, Pascal::VolumeEntry *volume)"; + hitCount = 0; + ignoreCount = 0; + lineNumber = 589; + modificationTime = 299278551.143155; + originalNumberOfMultipleMatches = 1; + state = 1; + }; + B6F3657E11AE255B0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBE911A244EE00C90DCE /* Date.h */; + name = "Date.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 654; + vrLoc = 0; + }; + B6F365CC11B08AE30045E114 /* VolumeEntry.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = VolumeEntry.h; + path = ./Pascal/VolumeEntry.h; + sourceTree = ""; + }; + B6F3663D11B1809A0045E114 /* Adaptor.cpp:167 */ = { + isa = PBXFileBreakpoint; + actions = ( + ); + breakpointStyle = 0; + continueAfterActions = 0; + countType = 0; + delayBeforeContinue = 0; + fileReference = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; + functionName = "NibbleAdaptor::decode62(uint8_t val)"; + hitCount = 0; + ignoreCount = 0; + lineNumber = 167; + modificationTime = 299278551.143489; + originalNumberOfMultipleMatches = 1; + state = 0; + }; + B6F3665411B190370045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; + name = "Adaptor.cpp: 167"; + rLen = 0; + rLoc = 3653; + rType = 0; + vrLen = 933; + vrLoc = 7817; + }; + B6F3665C11B194AC0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; + name = "NibbleTest.cpp: 76"; + rLen = 0; + rLoc = 1680; + rType = 0; + vrLen = 951; + vrLoc = 1203; + }; + B6F366C411B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; + name = "MappedFile.cpp: 53"; + rLen = 0; + rLoc = 970; + rType = 0; + vrLen = 737; + vrLoc = 463; + }; + B6F366C611B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFB8811A1FB2500C90DCE /* DiskImage.h */; + name = "DiskImage.h: 66"; + rLen = 0; + rLoc = 1204; + rType = 0; + vrLen = 809; + vrLoc = 709; + }; + B6F366C711B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAA511A094E000C90DCE /* UniversalDiskImage.h */; + name = "UniversalDiskImage.h: 29"; + rLen = 4; + rLoc = 507; + rType = 0; + vrLen = 692; + vrLoc = 0; + }; + B6F366C811B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; + name = "DavexDiskImage.cpp: 111"; + rLen = 0; + rLoc = 2355; + rType = 0; + vrLen = 875; + vrLoc = 1920; + }; + B6F366C911B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; + name = "DiskCopy42Image.cpp: 111"; + rLen = 0; + rLoc = 2053; + rType = 0; + vrLen = 925; + vrLoc = 1629; + }; + B6F366CA11B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; + name = "UniversalDiskImage.cpp: 47"; + rLen = 0; + rLoc = 956; + rType = 0; + vrLen = 808; + vrLoc = 497; + }; + B6F366CB11B1A28C0045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; + name = "DiskImage.cpp: 30"; + rLen = 0; + rLoc = 423; + rType = 0; + vrLen = 613; + vrLoc = 128; + }; + B6F3676311B323680045E114 /* TextWriter.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1009, 958}}"; + sepNavSelRange = "{420, 0}"; + sepNavVisRange = "{0, 587}"; + }; + }; + B6F3676411B323680045E114 /* TextWriter.cpp */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {838, 1352}}"; + sepNavSelRange = "{315, 0}"; + sepNavVisRange = "{0, 803}"; + }; + }; + B6F3677C11B326580045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F365CC11B08AE30045E114 /* VolumeEntry.h */; + name = "VolumeEntry.h: 51"; + rLen = 56; + rLoc = 1259; + rType = 0; + vrLen = 1094; + vrLoc = 758; + }; + B6F3677D11B326580045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F3651C11ADD0280045E114 /* Entry.h */; + name = "Entry.h: 72"; + rLen = 0; + rLoc = 1399; + rType = 0; + vrLen = 605; + vrLoc = 0; + }; + B6F3677E11B326580045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F3676311B323680045E114 /* TextWriter.h */; + name = "TextWriter.h: 36"; + rLen = 0; + rLoc = 587; + rType = 0; + vrLen = 532; + vrLoc = 0; + }; + B6F367A011B330D10045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFACA11A09DAA00C90DCE /* File.h */; + name = "File.h: 21"; + rLen = 0; + rLoc = 244; + rType = 0; + vrLen = 749; + vrLoc = 0; + }; + B6F367AE11B337A70045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFCC811A366C800C90DCE /* MappedFile.h */; + name = "MappedFile.h: 17"; + rLen = 0; + rLoc = 263; + rType = 0; + vrLen = 874; + vrLoc = 0; + }; + B6F3682411B431AC0045E114 /* newfs_prodos */ = { + activeExec = 0; + executables = ( + B6F3682611B431AC0045E114 /* newfs_prodos */, + ); + }; + B6F3682611B431AC0045E114 /* newfs_prodos */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 0; + configStateDict = { + }; + customDataFormattersEnabled = 1; + dataTipCustomDataFormattersEnabled = 1; + dataTipShowTypeColumn = 1; + dataTipSortType = 0; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + libgmallocEnabled = 0; + name = newfs_prodos; + showTypeColumn = 0; + sourceDirectories = ( + ); + }; + B6F3684A11B44D090045E114 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B6F3676411B323680045E114 /* TextWriter.cpp */; + name = "TextWriter.cpp: 17"; + rLen = 0; + rLoc = 315; + rType = 0; + vrLen = 803; + vrLoc = 0; + }; + B6F8D4AD131CB30300461B54 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; + name = "VolumeEntry.cpp: 616"; + rLen = 0; + rLoc = 13717; + rType = 0; + vrLen = 1176; + vrLoc = 13228; + }; +} diff --git a/ProFUSE.xcodeproj/kelvin.perspectivev3 b/ProFUSE.xcodeproj/kelvin.perspectivev3 new file mode 100644 index 0000000..c7b1723 --- /dev/null +++ b/ProFUSE.xcodeproj/kelvin.perspectivev3 @@ -0,0 +1,1547 @@ + + + + + ActivePerspectiveName + Project + AllowedModules + + + BundleLoadPath + + MaxInstances + n + Module + PBXSmartGroupTreeModule + Name + Groups and Files Outline View + + + BundleLoadPath + + MaxInstances + n + Module + PBXNavigatorGroup + Name + Editor + + + BundleLoadPath + + MaxInstances + n + Module + XCTaskListModule + Name + Task List + + + BundleLoadPath + + MaxInstances + n + Module + XCDetailModule + Name + File and Smart Group Detail Viewer + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXBuildResultsModule + Name + Detailed Build Results Viewer + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXProjectFindModule + Name + Project Batch Find Tool + + + BundleLoadPath + + MaxInstances + n + Module + XCProjectFormatConflictsModule + Name + Project Format Conflicts List + + + BundleLoadPath + + MaxInstances + n + Module + PBXBookmarksModule + Name + Bookmarks Tool + + + BundleLoadPath + + MaxInstances + n + Module + PBXClassBrowserModule + Name + Class Browser + + + BundleLoadPath + + MaxInstances + n + Module + PBXCVSModule + Name + Source Code Control Tool + + + BundleLoadPath + + MaxInstances + n + Module + PBXDebugBreakpointsModule + Name + Debug Breakpoints Tool + + + BundleLoadPath + + MaxInstances + n + Module + XCDockableInspector + Name + Inspector + + + BundleLoadPath + + MaxInstances + n + Module + PBXOpenQuicklyModule + Name + Open Quickly Tool + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXDebugSessionModule + Name + Debugger + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXDebugCLIModule + Name + Debug Console + + + BundleLoadPath + + MaxInstances + n + Module + XCSnapshotModule + Name + Snapshots Tool + + + BundlePath + /Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources + Description + AIODescriptionKey + DockingSystemVisible + + Extension + perspectivev3 + FavBarConfig + + PBXProjectModuleGUID + B63EFA6611A093C200C90DCE + XCBarModuleItemNames + + XCBarModuleItems + + + FirstTimeWindowDisplayed + + Identifier + com.apple.perspectives.project.defaultV3 + MajorVersion + 34 + MinorVersion + 0 + Name + All-In-One + Notifications + + OpenEditors + + PerspectiveWidths + + 1239 + 1239 + + Perspectives + + + ChosenToolbarItems + + XCToolbarPerspectiveControl + NSToolbarSeparatorItem + active-combo-popup + action + NSToolbarFlexibleSpaceItem + debugger-enable-breakpoints + build-and-go + com.apple.ide.PBXToolbarStopButton + get-info + NSToolbarFlexibleSpaceItem + com.apple.pbx.toolbar.searchfield + + ControllerClassBaseName + + IconName + WindowOfProject + Identifier + perspective.project + IsVertical + + Layout + + + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C37FBAC04509CD000000102 + 1C37FAAC04509CD000000102 + 1C37FABC05509CD000000102 + 1C37FABC05539CD112110102 + E2644B35053B69B200211256 + 1C37FABC04509CD000100104 + 1CC0EA4004350EF90044410B + 1CC0EA4004350EF90041110B + 1C77FABC04509CD000000102 + + PBXProjectModuleGUID + 1CA23ED40692098700951B8B + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + yes + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 318 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 08FB7794FE84155DC02AAC07 + B6272A8D11D5AC3C0073C73A + B6272AA411D5AE0C0073C73A + B63EFBE711A244EE00C90DCE + B63EFACF11A09DB500C90DCE + B63EFAB511A098C400C90DCE + B63EFA9411A094E000C90DCE + B656ADED11A84D3200AB578A + 1C37FBAC04509CD000000102 + 1C37FAAC04509CD000000102 + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 63 + 62 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {318, 941}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + + + GeometryConfiguration + + Frame + {{0, 0}, {335, 959}} + GroupTreeTableConfiguration + + MainColumn + 318 + + RubberWindowFrame + 413 92 1239 1000 0 0 1920 1178 + + Module + PBXSmartGroupTreeModule + Proportion + 335pt + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + B63EFA6111A093C200C90DCE + PBXProjectModuleLabel + VolumeEntry.cpp + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + B63EFA6211A093C200C90DCE + PBXProjectModuleLabel + VolumeEntry.cpp + _historyCapacity + 0 + bookmark + B6F8D4AD131CB30300461B54 + history + + B63EFC2611A2D5A400C90DCE + B63EFC3211A2D5A400C90DCE + B63EFDA011A4488200C90DCE + B63EFDA511A4488200C90DCE + B63EFDA711A4488200C90DCE + B63EFDA911A4488200C90DCE + B63EFDAB11A4488200C90DCE + B63EFDAD11A4488200C90DCE + B63EFDAF11A4488200C90DCE + B63EFDB111A4488200C90DCE + B63EFDB311A4488200C90DCE + B63EFDF211A4504200C90DCE + B63EFEA011A488C200C90DCE + B63EFEA111A488C200C90DCE + B63EFEA811A488C200C90DCE + B6E5F0DD11A60726000AD141 + B6E5F0F211A73144000AD141 + B6E5F11211A73340000AD141 + B6E5F13A11A74F2B000AD141 + B6E5F18211A76B74000AD141 + B656AE2611A84FA400AB578A + B6F3647111AB35FE0045E114 + B6F3649E11AB59190045E114 + B6F364B711AB84840045E114 + B6F3652E11ADD5D20045E114 + B6F3653011ADD5D20045E114 + B6F3657E11AE255B0045E114 + B6F3665411B190370045E114 + B6F3665C11B194AC0045E114 + B6F366C411B1A28C0045E114 + B6F366C611B1A28C0045E114 + B6F366C711B1A28C0045E114 + B6F366C811B1A28C0045E114 + B6F366C911B1A28C0045E114 + B6F366CA11B1A28C0045E114 + B6F366CB11B1A28C0045E114 + B6F3677C11B326580045E114 + B6F3677D11B326580045E114 + B6F3677E11B326580045E114 + B6F367A011B330D10045E114 + B6F367AE11B337A70045E114 + B6F3684A11B44D090045E114 + B65CFB6911B495790024A2D9 + B6272A9911D5AC5E0073C73A + B6272A9B11D5AC5E0073C73A + B6272A9C11D5AC5E0073C73A + B6272B0D11D691320073C73A + B6272B0E11D691320073C73A + B6272B0F11D691320073C73A + B6272B1011D691320073C73A + B6272B1111D691320073C73A + B6272B1311D691320073C73A + B6272B1411D691320073C73A + B6272B1611D691320073C73A + B6AA3AB21318D063007D4BA1 + B6AA3AB31318D063007D4BA1 + B6AA3AB41318D063007D4BA1 + B6A53B8E1319DDFC00C9070F + B6A53BC7131B400800C9070F + B6A53BC8131B400800C9070F + B6A53C34131B4CF800C9070F + + + SplitCount + 1 + + StatusBarVisibility + + XCSharingToken + com.apple.Xcode.CommonNavigatorGroupSharingToken + + GeometryConfiguration + + Frame + {{0, 0}, {899, 497}} + RubberWindowFrame + 413 92 1239 1000 0 0 1920 1178 + + Module + PBXNavigatorGroup + Proportion + 497pt + + + Proportion + 457pt + Tabs + + + BecomeActive + + ContentConfiguration + + PBXProjectModuleGUID + 1CA23EDF0692099D00951B8B + PBXProjectModuleLabel + Detail + + GeometryConfiguration + + Frame + {{10, 27}, {899, 430}} + RubberWindowFrame + 413 92 1239 1000 0 0 1920 1178 + + Module + XCDetailModule + + + ContentConfiguration + + PBXProjectModuleGUID + 1CA23EE00692099D00951B8B + PBXProjectModuleLabel + Project Find + + GeometryConfiguration + + Frame + {{10, 27}, {899, 383}} + + Module + PBXProjectFindModule + + + ContentConfiguration + + PBXCVSModuleFilterTypeKey + 1032 + PBXProjectModuleGUID + 1CA23EE10692099D00951B8B + PBXProjectModuleLabel + SCM Results + + GeometryConfiguration + + Frame + {{10, 31}, {603, 297}} + + Module + PBXCVSModule + + + ContentConfiguration + + PBXProjectModuleGUID + XCMainBuildResultsModuleGUID + PBXProjectModuleLabel + Build Results + XCBuildResultsTrigger_Collapse + 1021 + XCBuildResultsTrigger_Open + 1011 + + GeometryConfiguration + + Frame + {{10, 27}, {899, 420}} + + Module + PBXBuildResultsModule + + + + + Proportion + 899pt + + + Name + Project + ServiceClasses + + XCModuleDock + PBXSmartGroupTreeModule + XCModuleDock + PBXNavigatorGroup + XCDockableTabModule + XCDetailModule + PBXProjectFindModule + PBXCVSModule + PBXBuildResultsModule + + TableOfContents + + B6F8D48A131C605200461B54 + 1CA23ED40692098700951B8B + B6F8D48B131C605200461B54 + B63EFA6111A093C200C90DCE + B6F8D48C131C605200461B54 + 1CA23EDF0692099D00951B8B + 1CA23EE00692099D00951B8B + 1CA23EE10692099D00951B8B + XCMainBuildResultsModuleGUID + + ToolbarConfigUserDefaultsMinorVersion + 2 + ToolbarConfiguration + xcode.toolbar.config.defaultV3 + + + ChosenToolbarItems + + XCToolbarPerspectiveControl + NSToolbarSeparatorItem + active-combo-popup + NSToolbarFlexibleSpaceItem + debugger-enable-breakpoints + build-and-go + com.apple.ide.PBXToolbarStopButton + debugger-restart-executable + debugger-pause + debugger-step-over + debugger-step-into + debugger-step-out + NSToolbarFlexibleSpaceItem + servicesModulebreakpoints + debugger-show-console-window + + ControllerClassBaseName + PBXDebugSessionModule + IconName + DebugTabIcon + Identifier + perspective.debug + IsVertical + + Layout + + + ContentConfiguration + + PBXProjectModuleGUID + 1CCC7628064C1048000F2A68 + PBXProjectModuleLabel + Debugger Console + + GeometryConfiguration + + Frame + {{0, 0}, {1239, 320}} + + Module + PBXDebugCLIModule + Proportion + 320pt + + + ContentConfiguration + + Debugger + + HorizontalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {605, 308}} + {{605, 0}, {634, 308}} + + + VerticalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {1239, 308}} + {{0, 308}, {1239, 326}} + + + + LauncherConfigVersion + 8 + PBXProjectModuleGUID + 1CCC7629064C1048000F2A68 + PBXProjectModuleLabel + Debug + + GeometryConfiguration + + DebugConsoleVisible + None + DebugConsoleWindowFrame + {{200, 200}, {500, 300}} + DebugSTDIOWindowFrame + {{200, 200}, {500, 300}} + Frame + {{0, 325}, {1239, 634}} + PBXDebugSessionStackFrameViewKey + + DebugVariablesTableConfiguration + + Name + 193 + Value + 126 + Summary + 290 + + Frame + {{605, 0}, {634, 308}} + + + Module + PBXDebugSessionModule + Proportion + 634pt + + + Name + Debug + ServiceClasses + + XCModuleDock + PBXDebugCLIModule + PBXDebugSessionModule + PBXDebugProcessAndThreadModule + PBXDebugProcessViewModule + PBXDebugThreadViewModule + PBXDebugStackFrameViewModule + PBXNavigatorGroup + + TableOfContents + + B6A53BCB131B400800C9070F + 1CCC7628064C1048000F2A68 + 1CCC7629064C1048000F2A68 + B6A53BCC131B400800C9070F + B6A53BCD131B400800C9070F + B6A53BCE131B400800C9070F + B6A53BCF131B400800C9070F + B6A53BD0131B400800C9070F + + ToolbarConfigUserDefaultsMinorVersion + 2 + ToolbarConfiguration + xcode.toolbar.config.debugV3 + + + PerspectivesBarVisible + + ShelfIsVisible + + SourceDescription + file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecification.xcperspec' + StatusbarIsVisible + + TimeStamp + 0.0 + ToolbarConfigUserDefaultsMinorVersion + 2 + ToolbarDisplayMode + 1 + ToolbarIsVisible + + ToolbarSizeMode + 1 + Type + Perspectives + UpdateMessage + + WindowJustification + 5 + WindowOrderList + + /Users/kelvin/Projects/PROFuseX/PROFuseX.xcodeproj + + WindowString + 413 92 1239 1000 0 0 1920 1178 + WindowToolsV3 + + + Identifier + windowTool.debugger + Layout + + + Dock + + + ContentConfiguration + + Debugger + + HorizontalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {317, 164}} + {{317, 0}, {377, 164}} + + + VerticalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {694, 164}} + {{0, 164}, {694, 216}} + + + + LauncherConfigVersion + 8 + PBXProjectModuleGUID + 1C162984064C10D400B95A72 + PBXProjectModuleLabel + Debug - GLUTExamples (Underwater) + + GeometryConfiguration + + DebugConsoleDrawerSize + {100, 120} + DebugConsoleVisible + None + DebugConsoleWindowFrame + {{200, 200}, {500, 300}} + DebugSTDIOWindowFrame + {{200, 200}, {500, 300}} + Frame + {{0, 0}, {694, 380}} + RubberWindowFrame + 321 238 694 422 0 0 1440 878 + + Module + PBXDebugSessionModule + Proportion + 100% + + + Proportion + 100% + + + Name + Debugger + ServiceClasses + + PBXDebugSessionModule + + StatusbarIsVisible + 1 + TableOfContents + + 1CD10A99069EF8BA00B06720 + 1C0AD2AB069F1E9B00FABCE6 + 1C162984064C10D400B95A72 + 1C0AD2AC069F1E9B00FABCE6 + + ToolbarConfiguration + xcode.toolbar.config.debugV3 + WindowString + 321 238 694 422 0 0 1440 878 + WindowToolGUID + 1CD10A99069EF8BA00B06720 + WindowToolIsVisible + 0 + + + Identifier + windowTool.build + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1CD0528F0623707200166675 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1CD052900623707200166675 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {500, 215}} + RubberWindowFrame + 192 257 500 500 0 0 1280 1002 + + Module + PBXNavigatorGroup + Proportion + 218pt + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + XCMainBuildResultsModuleGUID + PBXProjectModuleLabel + Build Results + + GeometryConfiguration + + Frame + {{0, 222}, {500, 236}} + RubberWindowFrame + 192 257 500 500 0 0 1280 1002 + + Module + PBXBuildResultsModule + Proportion + 236pt + + + Proportion + 458pt + + + Name + Build Results + ServiceClasses + + PBXBuildResultsModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C78EAA5065D492600B07095 + 1C78EAA6065D492600B07095 + 1CD0528F0623707200166675 + XCMainBuildResultsModuleGUID + + ToolbarConfiguration + xcode.toolbar.config.buildV3 + WindowString + 192 257 500 500 0 0 1280 1002 + + + Identifier + windowTool.find + Layout + + + Dock + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1CDD528C0622207200134675 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1CD0528D0623707200166675 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {781, 167}} + RubberWindowFrame + 62 385 781 470 0 0 1440 878 + + Module + PBXNavigatorGroup + Proportion + 781pt + + + Proportion + 50% + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1CD0528E0623707200166675 + PBXProjectModuleLabel + Project Find + + GeometryConfiguration + + Frame + {{8, 0}, {773, 254}} + RubberWindowFrame + 62 385 781 470 0 0 1440 878 + + Module + PBXProjectFindModule + Proportion + 50% + + + Proportion + 428pt + + + Name + Project Find + ServiceClasses + + PBXProjectFindModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C530D57069F1CE1000CFCEE + 1C530D58069F1CE1000CFCEE + 1C530D59069F1CE1000CFCEE + 1CDD528C0622207200134675 + 1C530D5A069F1CE1000CFCEE + 1CE0B1FE06471DED0097A5F4 + 1CD0528E0623707200166675 + + WindowString + 62 385 781 470 0 0 1440 878 + WindowToolGUID + 1C530D57069F1CE1000CFCEE + WindowToolIsVisible + 0 + + + Identifier + windowTool.snapshots + Layout + + + Dock + + + Module + XCSnapshotModule + Proportion + 100% + + + Proportion + 100% + + + Name + Snapshots + ServiceClasses + + XCSnapshotModule + + StatusbarIsVisible + Yes + ToolbarConfiguration + xcode.toolbar.config.snapshots + WindowString + 315 824 300 550 0 0 1440 878 + WindowToolIsVisible + Yes + + + FirstTimeWindowDisplayed + + Identifier + windowTool.debuggerConsole + IsVertical + + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1C78EAAC065D492600B07095 + PBXProjectModuleLabel + Debugger Console + + GeometryConfiguration + + Frame + {{0, 0}, {440, 359}} + RubberWindowFrame + 98 717 440 400 0 0 1920 1178 + + Module + PBXDebugCLIModule + Proportion + 359pt + + + Proportion + 359pt + + + Name + Debugger Console + ServiceClasses + + PBXDebugCLIModule + + StatusbarIsVisible + + TableOfContents + + 1C530D5B069F1CE1000CFCEE + B656AF7911AA19CD00AB578A + 1C78EAAC065D492600B07095 + + ToolbarConfiguration + xcode.toolbar.config.consoleV3 + WindowString + 98 717 440 400 0 0 1920 1178 + WindowToolGUID + 1C530D5B069F1CE1000CFCEE + WindowToolIsVisible + + + + Identifier + windowTool.scm + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1C78EAB2065D492600B07095 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1C78EAB3065D492600B07095 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {452, 0}} + RubberWindowFrame + 743 379 452 308 0 0 1280 1002 + + Module + PBXNavigatorGroup + Proportion + 0pt + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1CD052920623707200166675 + PBXProjectModuleLabel + SCM + + GeometryConfiguration + + ConsoleFrame + {{0, 259}, {452, 0}} + Frame + {{0, 7}, {452, 259}} + RubberWindowFrame + 743 379 452 308 0 0 1280 1002 + TableConfiguration + + Status + 30 + FileName + 199 + Path + 197.09500122070312 + + TableFrame + {{0, 0}, {452, 250}} + + Module + PBXCVSModule + Proportion + 262pt + + + Proportion + 266pt + + + Name + SCM + ServiceClasses + + PBXCVSModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C78EAB4065D492600B07095 + 1C78EAB5065D492600B07095 + 1C78EAB2065D492600B07095 + 1CD052920623707200166675 + + ToolbarConfiguration + xcode.toolbar.config.scmV3 + WindowString + 743 379 452 308 0 0 1280 1002 + + + FirstTimeWindowDisplayed + + Identifier + windowTool.breakpoints + IsVertical + + Layout + + + Dock + + + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C77FABC04509CD000000102 + + PBXProjectModuleGUID + 1CE0B1FE06471DED0097A5F4 + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + no + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 168 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 1C77FABC04509CD000000102 + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 0 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {168, 350}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + + + GeometryConfiguration + + Frame + {{0, 0}, {185, 368}} + GroupTreeTableConfiguration + + MainColumn + 168 + + RubberWindowFrame + 215 685 744 409 0 0 1920 1178 + + Module + PBXSmartGroupTreeModule + Proportion + 185pt + + + BecomeActive + + ContentConfiguration + + PBXProjectModuleGUID + 1CA1AED706398EBD00589147 + PBXProjectModuleLabel + Detail + + GeometryConfiguration + + Frame + {{190, 0}, {554, 368}} + RubberWindowFrame + 215 685 744 409 0 0 1920 1178 + + Module + XCDetailModule + Proportion + 554pt + + + Proportion + 368pt + + + MajorVersion + 3 + MinorVersion + 0 + Name + Breakpoints + ServiceClasses + + PBXSmartGroupTreeModule + XCDetailModule + + StatusbarIsVisible + + TableOfContents + + B656AF4511AA12DA00AB578A + B656AF4611AA12DA00AB578A + 1CE0B1FE06471DED0097A5F4 + 1CA1AED706398EBD00589147 + + ToolbarConfiguration + xcode.toolbar.config.breakpointsV3 + WindowString + 215 685 744 409 0 0 1920 1178 + WindowToolGUID + B656AF4511AA12DA00AB578A + WindowToolIsVisible + + + + Identifier + windowTool.debugAnimator + Layout + + + Dock + + + Module + PBXNavigatorGroup + Proportion + 100% + + + Proportion + 100% + + + Name + Debug Visualizer + ServiceClasses + + PBXNavigatorGroup + + StatusbarIsVisible + 1 + ToolbarConfiguration + xcode.toolbar.config.debugAnimatorV3 + WindowString + 100 100 700 500 0 0 1280 1002 + + + Identifier + windowTool.bookmarks + Layout + + + Dock + + + Module + PBXBookmarksModule + Proportion + 166pt + + + Proportion + 166pt + + + Name + Bookmarks + ServiceClasses + + PBXBookmarksModule + + StatusbarIsVisible + 0 + WindowString + 538 42 401 187 0 0 1280 1002 + + + Identifier + windowTool.projectFormatConflicts + Layout + + + Dock + + + Module + XCProjectFormatConflictsModule + Proportion + 100% + + + Proportion + 100% + + + Name + Project Format Conflicts + ServiceClasses + + XCProjectFormatConflictsModule + + StatusbarIsVisible + 0 + WindowContentMinSize + 450 300 + WindowString + 50 850 472 307 0 0 1440 877 + + + Identifier + windowTool.classBrowser + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + OptionsSetName + Hierarchy, all classes + PBXProjectModuleGUID + 1CA6456E063B45B4001379D8 + PBXProjectModuleLabel + Class Browser - NSObject + + GeometryConfiguration + + ClassesFrame + {{0, 0}, {369, 96}} + ClassesTreeTableConfiguration + + PBXClassNameColumnIdentifier + 208 + PBXClassBookColumnIdentifier + 22 + + Frame + {{0, 0}, {616, 353}} + MembersFrame + {{0, 105}, {369, 395}} + MembersTreeTableConfiguration + + PBXMemberTypeIconColumnIdentifier + 22 + PBXMemberNameColumnIdentifier + 216 + PBXMemberTypeColumnIdentifier + 94 + PBXMemberBookColumnIdentifier + 22 + + PBXModuleWindowStatusBarHidden2 + 1 + RubberWindowFrame + 597 125 616 374 0 0 1280 1002 + + Module + PBXClassBrowserModule + Proportion + 354pt + + + Proportion + 354pt + + + Name + Class Browser + ServiceClasses + + PBXClassBrowserModule + + StatusbarIsVisible + 0 + TableOfContents + + 1C78EABA065D492600B07095 + 1C78EABB065D492600B07095 + 1CA6456E063B45B4001379D8 + + ToolbarConfiguration + xcode.toolbar.config.classbrowser + WindowString + 597 125 616 374 0 0 1280 1002 + + + Identifier + windowTool.refactoring + IncludeInToolsMenu + 0 + Layout + + + Dock + + + BecomeActive + 1 + GeometryConfiguration + + Frame + {0, 0}, {500, 335} + RubberWindowFrame + {0, 0}, {500, 335} + + Module + XCRefactoringModule + Proportion + 100% + + + Proportion + 100% + + + Name + Refactoring + ServiceClasses + + XCRefactoringModule + + WindowString + 200 200 500 356 0 0 1920 1200 + + + + diff --git a/ProFUSE.xcodeproj/project.pbxproj b/ProFUSE.xcodeproj/project.pbxproj new file mode 100644 index 0000000..7d1f572 --- /dev/null +++ b/ProFUSE.xcodeproj/project.pbxproj @@ -0,0 +1,1482 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + B6272A9311D5AC440073C73A /* apfm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A8E11D5AC3C0073C73A /* apfm.cpp */; }; + B6272A9411D5AC4C0073C73A /* fuse_pascal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */; }; + B6272A9511D5AC530073C73A /* fuse_pascal_ops.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */; }; + B6272A9611D5AC560073C73A /* newfs_pascal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */; }; + B6272A9711D5AC5B0073C73A /* xattr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A9211D5AC3C0073C73A /* xattr.cpp */; }; + B6272AAA11D5AE0C0073C73A /* Bitmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272AA511D5AE0C0073C73A /* Bitmap.cpp */; }; + B6272AAB11D5AE0C0073C73A /* DateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272AA711D5AE0C0073C73A /* DateTime.cpp */; }; + B63EFCD211A36C8B00C90DCE /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; + B63EFCD311A36C8B00C90DCE /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; + B63EFCD411A36C8B00C90DCE /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; + B63EFCD511A36C8B00C90DCE /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; + B63EFCD611A36C8B00C90DCE /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; + B63EFCD711A36C8B00C90DCE /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; + B63EFCD811A36C8B00C90DCE /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; + B63EFCD911A36C8B00C90DCE /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; + B63EFCDA11A36C8B00C90DCE /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; + B63EFCDB11A36C8B00C90DCE /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; + B63EFCDC11A36C8B00C90DCE /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; + B63EFCDD11A36C8B00C90DCE /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; + B63EFCE011A36C8B00C90DCE /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; + B63EFCE111A36C8B00C90DCE /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; }; + B63EFCE211A36C8B00C90DCE /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; + B63EFCE311A36C8B00C90DCE /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; + B63EFCE511A36C8B00C90DCE /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; + B63EFE8511A4888500C90DCE /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; + B63EFE8611A4888500C90DCE /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; + B63EFE8711A4888500C90DCE /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; + B63EFE8811A4888500C90DCE /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; + B63EFE8911A4888500C90DCE /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; + B63EFE8A11A4888500C90DCE /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; + B63EFE8B11A4888500C90DCE /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; + B63EFE8C11A4888500C90DCE /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; + B63EFE8D11A4888500C90DCE /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; + B63EFE8E11A4888500C90DCE /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; + B63EFE8F11A4888500C90DCE /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; + B63EFE9011A4888500C90DCE /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; + B63EFE9311A4888500C90DCE /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; + B63EFE9411A4888500C90DCE /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; }; + B63EFE9511A4888500C90DCE /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; + B63EFE9611A4888500C90DCE /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; + B63EFE9711A4888500C90DCE /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; + B650901B1332FE5000FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090181332FE5000FBA318 /* Exception.cpp */; }; + B650901D1332FE5000FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090181332FE5000FBA318 /* Exception.cpp */; }; + B650901E1332FE5000FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090181332FE5000FBA318 /* Exception.cpp */; }; + B65090271332FE6A00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090241332FE6A00FBA318 /* Exception.cpp */; }; + B65090281332FE6A00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090241332FE6A00FBA318 /* Exception.cpp */; }; + B65090291332FE6A00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090241332FE6A00FBA318 /* Exception.cpp */; }; + B650902A1332FE6A00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090241332FE6A00FBA318 /* Exception.cpp */; }; + B65090311332FE8B00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650902F1332FE8B00FBA318 /* Exception.cpp */; }; + B65090321332FE8B00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650902F1332FE8B00FBA318 /* Exception.cpp */; }; + B65090331332FE8B00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650902F1332FE8B00FBA318 /* Exception.cpp */; }; + B65090341332FE8B00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650902F1332FE8B00FBA318 /* Exception.cpp */; }; + B650903F1332FEBE00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090371332FEBE00FBA318 /* Exception.cpp */; }; + B65090401332FEBE00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090371332FEBE00FBA318 /* Exception.cpp */; }; + B65090411332FEBE00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090371332FEBE00FBA318 /* Exception.cpp */; }; + B65090421332FEBE00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090371332FEBE00FBA318 /* Exception.cpp */; }; + B65090471332FEBE00FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; + B65090481332FEBE00FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; + B65090491332FEBE00FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; + B650904A1332FEBE00FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; + B650908C133304C800FBA318 /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; + B650908D133304C800FBA318 /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; + B650908E133304C800FBA318 /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; + B650908F133304C800FBA318 /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; + B6509090133304C800FBA318 /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; + B6509091133304C800FBA318 /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; + B6509092133304C800FBA318 /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; + B6509093133304C800FBA318 /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; + B6509094133304C800FBA318 /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; + B6509095133304C800FBA318 /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; + B6509096133304C800FBA318 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; + B6509097133304C800FBA318 /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; + B6509098133304C800FBA318 /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; + B6509099133304C800FBA318 /* SDKImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6A591261329C417007B0EE2 /* SDKImage.cpp */; }; + B650909A133304C800FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090181332FE5000FBA318 /* Exception.cpp */; }; + B650909B133304C800FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090241332FE6A00FBA318 /* Exception.cpp */; }; + B650909C133304C800FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650902F1332FE8B00FBA318 /* Exception.cpp */; }; + B650909D133304C800FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090371332FEBE00FBA318 /* Exception.cpp */; }; + B650909E133304C800FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; + B650909F133304C800FBA318 /* DateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272AA711D5AE0C0073C73A /* DateTime.cpp */; }; + B65090A0133304C800FBA318 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509078133300BA00FBA318 /* File.cpp */; }; + B65090A1133304C800FBA318 /* Disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509079133300BA00FBA318 /* Disk.cpp */; }; + B65090A2133304C800FBA318 /* profuse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650907F133300DD00FBA318 /* profuse.cpp */; }; + B65090A3133304C800FBA318 /* profuse_xattr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509081133300FB00FBA318 /* profuse_xattr.cpp */; }; + B65090A4133304C800FBA318 /* profuse_stat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509082133300FB00FBA318 /* profuse_stat.cpp */; }; + B65090A5133304C800FBA318 /* profuse_file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509083133300FB00FBA318 /* profuse_file.cpp */; }; + B65090A6133304C800FBA318 /* profuse_dirent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509084133300FB00FBA318 /* profuse_dirent.cpp */; }; + B65090A8133304C800FBA318 /* libfuse_ino64.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */; }; + B65090A9133304C800FBA318 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EC132995D4007B0EE2 /* Carbon.framework */; }; + B65090AA133304C800FBA318 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EE132995D4007B0EE2 /* libz.dylib */; }; + B65090AB133304C800FBA318 /* libNuFX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590F713299626007B0EE2 /* libNuFX.a */; }; + B656AE0811A84F6C00AB578A /* libfuse_ino64.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */; }; + B656AE0911A84F7700AB578A /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; + B656AE0A11A84F7700AB578A /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; + B656AE0B11A84F7700AB578A /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; + B656AE0C11A84F7700AB578A /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; + B656AE0D11A84F7700AB578A /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; + B656AE0E11A84F7700AB578A /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; + B656AE0F11A84F7700AB578A /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; + B656AE1011A84F7700AB578A /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; + B656AE1111A84F7700AB578A /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; + B656AE1211A84F7700AB578A /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; + B656AE1311A84F7700AB578A /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; + B656AE1411A84F7700AB578A /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; + B656AE1711A84F7700AB578A /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; + B656AE1811A84F7700AB578A /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; }; + B656AE1911A84F7700AB578A /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; + B656AE1A11A84F7700AB578A /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; + B656AE1B11A84F7700AB578A /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; + B656AF0811AA106400AB578A /* NibbleTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; }; + B656AF0911AA106C00AB578A /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; + B656AF0A11AA106C00AB578A /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; + B656AF0B11AA106C00AB578A /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; + B656AF0C11AA106C00AB578A /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; + B656AF0D11AA106C00AB578A /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; + B656AF0E11AA106C00AB578A /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; + B656AF0F11AA106C00AB578A /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; + B656AF1011AA106C00AB578A /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; + B656AF1111AA106C00AB578A /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; + B656AF1211AA106C00AB578A /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; + B656AF1311AA106C00AB578A /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; + B656AF1411AA106C00AB578A /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; + B656AF1711AA106C00AB578A /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; + B656AF1811AA106C00AB578A /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; }; + B656AF1911AA106C00AB578A /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; + B656AF1A11AA106C00AB578A /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; + B656AF1B11AA106C00AB578A /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; + B6A590EF132995D4007B0EE2 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EC132995D4007B0EE2 /* Carbon.framework */; }; + B6A590F0132995D4007B0EE2 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EC132995D4007B0EE2 /* Carbon.framework */; }; + B6A590F3132995D5007B0EE2 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EE132995D4007B0EE2 /* libz.dylib */; }; + B6A590F4132995D5007B0EE2 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EE132995D4007B0EE2 /* libz.dylib */; }; + B6A590F813299626007B0EE2 /* libNuFX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590F713299626007B0EE2 /* libNuFX.a */; }; + B6A590F913299626007B0EE2 /* libNuFX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590F713299626007B0EE2 /* libNuFX.a */; }; + B6A591281329C417007B0EE2 /* SDKImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6A591261329C417007B0EE2 /* SDKImage.cpp */; }; + B6A591291329C417007B0EE2 /* SDKImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6A591261329C417007B0EE2 /* SDKImage.cpp */; }; + B6F3676511B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; + B6F3676611B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; + B6F3676711B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; + B6F3676811B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; + B6F3682A11B431CC0045E114 /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; + B6F3682B11B431CC0045E114 /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; + B6F3682C11B431CC0045E114 /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; + B6F3682D11B431CC0045E114 /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; + B6F3682E11B431CC0045E114 /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; + B6F3682F11B431CC0045E114 /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; + B6F3683011B431CC0045E114 /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; + B6F3683111B431CC0045E114 /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; + B6F3683211B431CC0045E114 /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; + B6F3683311B431CC0045E114 /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; + B6F3683411B431CC0045E114 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; + B6F3683511B431CC0045E114 /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; + B6F3683811B431CC0045E114 /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + B6272A8E11D5AC3C0073C73A /* apfm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = apfm.cpp; sourceTree = ""; }; + B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fuse_pascal.cpp; sourceTree = ""; }; + B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fuse_pascal_ops.cpp; sourceTree = ""; }; + B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = newfs_pascal.cpp; sourceTree = ""; }; + B6272A9211D5AC3C0073C73A /* xattr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xattr.cpp; sourceTree = ""; }; + B6272AA211D5AC840073C73A /* newfs_prodos.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = newfs_prodos.cpp; sourceTree = ""; }; + B6272AA511D5AE0C0073C73A /* Bitmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Bitmap.cpp; sourceTree = ""; }; + B6272AA611D5AE0C0073C73A /* Bitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bitmap.h; sourceTree = ""; }; + B6272AA711D5AE0C0073C73A /* DateTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DateTime.cpp; sourceTree = ""; }; + B6272AA811D5AE0C0073C73A /* DateTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DateTime.h; sourceTree = ""; }; + B63EFA7511A0948500C90DCE /* Endian.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Endian.cpp; sourceTree = ""; }; + B63EFA7611A0948500C90DCE /* Endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Endian.h; sourceTree = ""; }; + B63EFA7711A0948500C90DCE /* IOBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOBuffer.h; sourceTree = ""; }; + B63EFA9511A094E000C90DCE /* BlockDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BlockDevice.cpp; sourceTree = ""; }; + B63EFA9611A094E000C90DCE /* BlockDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockDevice.h; sourceTree = ""; }; + B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DavexDiskImage.cpp; sourceTree = ""; }; + B63EFA9811A094E000C90DCE /* DavexDiskImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DavexDiskImage.h; sourceTree = ""; }; + B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DiskCopy42Image.cpp; sourceTree = ""; }; + B63EFA9C11A094E000C90DCE /* DiskCopy42Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiskCopy42Image.h; sourceTree = ""; }; + B63EFA9D11A094E000C90DCE /* DiskImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DiskImage.cpp; sourceTree = ""; }; + B63EFA9E11A094E000C90DCE /* DiskImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiskImage.h; sourceTree = ""; }; + B63EFAA111A094E000C90DCE /* RawDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RawDevice.cpp; sourceTree = ""; }; + B63EFAA211A094E000C90DCE /* RawDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RawDevice.h; sourceTree = ""; }; + B63EFAA311A094E000C90DCE /* TrackSector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackSector.h; sourceTree = ""; }; + B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UniversalDiskImage.cpp; sourceTree = ""; }; + B63EFAA511A094E000C90DCE /* UniversalDiskImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UniversalDiskImage.h; sourceTree = ""; }; + B63EFAB611A098C400C90DCE /* BlockCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BlockCache.cpp; sourceTree = ""; }; + B63EFAB711A098C400C90DCE /* BlockCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockCache.h; sourceTree = ""; }; + B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConcreteBlockCache.cpp; sourceTree = ""; }; + B63EFAB911A098C400C90DCE /* ConcreteBlockCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConcreteBlockCache.h; sourceTree = ""; }; + B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MappedBlockCache.cpp; sourceTree = ""; }; + B63EFABB11A098C400C90DCE /* MappedBlockCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MappedBlockCache.h; sourceTree = ""; }; + B63EFAC911A09DAA00C90DCE /* File.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = File.cpp; sourceTree = ""; }; + B63EFACA11A09DAA00C90DCE /* File.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = File.h; sourceTree = ""; }; + B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MappedFile.cpp; sourceTree = ""; }; + B63EFACC11A09DAA00C90DCE /* MappedFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MappedFile.h; sourceTree = ""; }; + B63EFB0611A0AC4800C90DCE /* Adaptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Adaptor.h; sourceTree = ""; }; + B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Adaptor.cpp; sourceTree = ""; }; + B63EFBE811A244EE00C90DCE /* Date.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Date.cpp; sourceTree = ""; }; + B63EFBE911A244EE00C90DCE /* Date.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Date.h; sourceTree = ""; }; + B63EFBEA11A244EE00C90DCE /* Entry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Entry.cpp; sourceTree = ""; }; + B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileEntry.cpp; sourceTree = ""; }; + B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = VolumeEntry.cpp; sourceTree = ""; }; + B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOBuffer.cpp.h; sourceTree = ""; }; + B63EFCCE11A36C7300C90DCE /* apfm */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = apfm; sourceTree = BUILT_PRODUCTS_DIR; }; + B63EFE8111A4886C00C90DCE /* newfs_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = newfs_pascal; sourceTree = BUILT_PRODUCTS_DIR; }; + B65090181332FE5000FBA318 /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = ""; }; + B65090191332FE5000FBA318 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; + B65090241332FE6A00FBA318 /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = ""; }; + B65090251332FE6A00FBA318 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; + B650902F1332FE8B00FBA318 /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = ""; }; + B65090301332FE8B00FBA318 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; + B65090361332FEBE00FBA318 /* auto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = auto.h; sourceTree = ""; }; + B65090371332FEBE00FBA318 /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = ""; }; + B65090381332FEBE00FBA318 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; + B650903A1332FEBE00FBA318 /* Lock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Lock.cpp; sourceTree = ""; }; + B650903B1332FEBE00FBA318 /* Lock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Lock.h; sourceTree = ""; }; + B650903D1332FEBE00FBA318 /* smart_pointers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = smart_pointers.h; sourceTree = ""; }; + B650903E1332FEBE00FBA318 /* unordered_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unordered_map.h; sourceTree = ""; }; + B6509078133300BA00FBA318 /* File.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = File.cpp; sourceTree = ""; }; + B6509079133300BA00FBA318 /* Disk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Disk.cpp; sourceTree = ""; }; + B650907A133300BA00FBA318 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; }; + B650907B133300BA00FBA318 /* Disk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Disk.h; sourceTree = ""; }; + B650907C133300BA00FBA318 /* File.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = File.h; sourceTree = ""; }; + B650907F133300DD00FBA318 /* profuse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse.cpp; sourceTree = ""; }; + B6509081133300FB00FBA318 /* profuse_xattr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_xattr.cpp; sourceTree = ""; }; + B6509082133300FB00FBA318 /* profuse_stat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_stat.cpp; sourceTree = ""; }; + B6509083133300FB00FBA318 /* profuse_file.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_file.cpp; sourceTree = ""; }; + B6509084133300FB00FBA318 /* profuse_dirent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_dirent.cpp; sourceTree = ""; }; + B6509085133300FB00FBA318 /* profuse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = profuse.h; sourceTree = ""; }; + B65090B1133304C800FBA318 /* profuse */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = profuse; sourceTree = BUILT_PRODUCTS_DIR; }; + B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libfuse_ino64.dylib; path = /usr/local/lib/libfuse_ino64.dylib; sourceTree = ""; }; + B656AE0311A84F5800AB578A /* fuse_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fuse_pascal; sourceTree = BUILT_PRODUCTS_DIR; }; + B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NibbleTest.cpp; sourceTree = ""; }; + B656AF0311AA105500AB578A /* NibbleTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NibbleTest; sourceTree = BUILT_PRODUCTS_DIR; }; + B659C142131368BA0058DC9C /* Device.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Device.h; sourceTree = ""; }; + B6A590EC132995D4007B0EE2 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = ../../../../System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; + B6A590EE132995D4007B0EE2 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = ../../../../usr/lib/libz.dylib; sourceTree = ""; }; + B6A590F713299626007B0EE2 /* libNuFX.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libNuFX.a; sourceTree = ""; }; + B6A591261329C417007B0EE2 /* SDKImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SDKImage.cpp; sourceTree = ""; }; + B6A591271329C417007B0EE2 /* SDKImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDKImage.h; sourceTree = ""; }; + B6F3648011AB36260045E114 /* xattr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xattr; sourceTree = BUILT_PRODUCTS_DIR; }; + B6F3651A11ADD0280045E114 /* VolumeEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VolumeEntry.h; sourceTree = ""; }; + B6F3651B11ADD0280045E114 /* FileEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileEntry.h; sourceTree = ""; }; + B6F3651C11ADD0280045E114 /* Entry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Entry.h; sourceTree = ""; }; + B6F3652711ADD52B0045E114 /* Pascal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Pascal.h; sourceTree = ""; }; + B6F3676311B323680045E114 /* TextWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextWriter.h; sourceTree = ""; }; + B6F3676411B323680045E114 /* TextWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextWriter.cpp; sourceTree = ""; }; + B6F3682511B431AC0045E114 /* newfs_prodos */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = newfs_prodos; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + B63EFCCC11A36C7300C90DCE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B6A590EF132995D4007B0EE2 /* Carbon.framework in Frameworks */, + B6A590F3132995D5007B0EE2 /* libz.dylib in Frameworks */, + B6A590F813299626007B0EE2 /* libNuFX.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B63EFE7F11A4886C00C90DCE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B65090A7133304C800FBA318 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B65090A8133304C800FBA318 /* libfuse_ino64.dylib in Frameworks */, + B65090A9133304C800FBA318 /* Carbon.framework in Frameworks */, + B65090AA133304C800FBA318 /* libz.dylib in Frameworks */, + B65090AB133304C800FBA318 /* libNuFX.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B656AE0111A84F5800AB578A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B656AE0811A84F6C00AB578A /* libfuse_ino64.dylib in Frameworks */, + B6A590F0132995D4007B0EE2 /* Carbon.framework in Frameworks */, + B6A590F4132995D5007B0EE2 /* libz.dylib in Frameworks */, + B6A590F913299626007B0EE2 /* libNuFX.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B656AF0111AA105500AB578A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B6F3647E11AB36260045E114 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B6F3682311B431AC0045E114 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* PROFuseX */ = { + isa = PBXGroup; + children = ( + B6272A8D11D5AC3C0073C73A /* bin */, + B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */, + B6272AA411D5AE0C0073C73A /* ProDOS */, + B63EFBE711A244EE00C90DCE /* Pascal */, + B63EFAC811A09DAA00C90DCE /* File */, + B63EFAB511A098C400C90DCE /* Cache */, + B63EFA9411A094E000C90DCE /* Device */, + B63EFA7411A0948500C90DCE /* Endian */, + B65090351332FEBE00FBA318 /* Common */, + B65090171332FE5000FBA318 /* NuFX */, + B65090231332FE6A00FBA318 /* POSIX */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + B656ADED11A84D3200AB578A /* Libraries */, + ); + name = PROFuseX; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + B63EFCCE11A36C7300C90DCE /* apfm */, + B63EFE8111A4886C00C90DCE /* newfs_pascal */, + B656AE0311A84F5800AB578A /* fuse_pascal */, + B656AF0311AA105500AB578A /* NibbleTest */, + B6F3648011AB36260045E114 /* xattr */, + B6F3682511B431AC0045E114 /* newfs_prodos */, + B65090B1133304C800FBA318 /* profuse */, + ); + name = Products; + sourceTree = ""; + }; + B6272A8D11D5AC3C0073C73A /* bin */ = { + isa = PBXGroup; + children = ( + B6509081133300FB00FBA318 /* profuse_xattr.cpp */, + B6509082133300FB00FBA318 /* profuse_stat.cpp */, + B6509083133300FB00FBA318 /* profuse_file.cpp */, + B6509084133300FB00FBA318 /* profuse_dirent.cpp */, + B6509085133300FB00FBA318 /* profuse.h */, + B650907F133300DD00FBA318 /* profuse.cpp */, + B6272A8E11D5AC3C0073C73A /* apfm.cpp */, + B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */, + B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */, + B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */, + B6272AA211D5AC840073C73A /* newfs_prodos.cpp */, + B6272A9211D5AC3C0073C73A /* xattr.cpp */, + ); + path = bin; + sourceTree = ""; + }; + B6272AA411D5AE0C0073C73A /* ProDOS */ = { + isa = PBXGroup; + children = ( + B6509078133300BA00FBA318 /* File.cpp */, + B6509079133300BA00FBA318 /* Disk.cpp */, + B650907A133300BA00FBA318 /* common.h */, + B650907B133300BA00FBA318 /* Disk.h */, + B650907C133300BA00FBA318 /* File.h */, + B650902F1332FE8B00FBA318 /* Exception.cpp */, + B65090301332FE8B00FBA318 /* Exception.h */, + B6272AA511D5AE0C0073C73A /* Bitmap.cpp */, + B6272AA611D5AE0C0073C73A /* Bitmap.h */, + B6272AA711D5AE0C0073C73A /* DateTime.cpp */, + B6272AA811D5AE0C0073C73A /* DateTime.h */, + ); + path = ProDOS; + sourceTree = ""; + }; + B63EFA7411A0948500C90DCE /* Endian */ = { + isa = PBXGroup; + children = ( + B63EFA7511A0948500C90DCE /* Endian.cpp */, + B63EFA7611A0948500C90DCE /* Endian.h */, + B63EFA7711A0948500C90DCE /* IOBuffer.h */, + B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */, + ); + path = Endian; + sourceTree = ""; + }; + B63EFA9411A094E000C90DCE /* Device */ = { + isa = PBXGroup; + children = ( + B659C142131368BA0058DC9C /* Device.h */, + B63EFA9511A094E000C90DCE /* BlockDevice.cpp */, + B63EFA9611A094E000C90DCE /* BlockDevice.h */, + B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */, + B63EFA9811A094E000C90DCE /* DavexDiskImage.h */, + B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */, + B63EFA9C11A094E000C90DCE /* DiskCopy42Image.h */, + B63EFA9D11A094E000C90DCE /* DiskImage.cpp */, + B63EFA9E11A094E000C90DCE /* DiskImage.h */, + B63EFAA111A094E000C90DCE /* RawDevice.cpp */, + B63EFAA211A094E000C90DCE /* RawDevice.h */, + B63EFAA311A094E000C90DCE /* TrackSector.h */, + B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */, + B63EFAA511A094E000C90DCE /* UniversalDiskImage.h */, + B63EFB0611A0AC4800C90DCE /* Adaptor.h */, + B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */, + B6A591261329C417007B0EE2 /* SDKImage.cpp */, + B6A591271329C417007B0EE2 /* SDKImage.h */, + ); + path = Device; + sourceTree = ""; + }; + B63EFAB511A098C400C90DCE /* Cache */ = { + isa = PBXGroup; + children = ( + B63EFAB611A098C400C90DCE /* BlockCache.cpp */, + B63EFAB711A098C400C90DCE /* BlockCache.h */, + B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */, + B63EFAB911A098C400C90DCE /* ConcreteBlockCache.h */, + B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */, + B63EFABB11A098C400C90DCE /* MappedBlockCache.h */, + ); + path = Cache; + sourceTree = ""; + }; + B63EFAC811A09DAA00C90DCE /* File */ = { + isa = PBXGroup; + children = ( + B63EFAC911A09DAA00C90DCE /* File.cpp */, + B63EFACA11A09DAA00C90DCE /* File.h */, + B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */, + B63EFACC11A09DAA00C90DCE /* MappedFile.h */, + ); + path = File; + sourceTree = ""; + }; + B63EFBE711A244EE00C90DCE /* Pascal */ = { + isa = PBXGroup; + children = ( + B6F3652711ADD52B0045E114 /* Pascal.h */, + B63EFBE811A244EE00C90DCE /* Date.cpp */, + B63EFBE911A244EE00C90DCE /* Date.h */, + B63EFBEA11A244EE00C90DCE /* Entry.cpp */, + B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */, + B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */, + B6F3651A11ADD0280045E114 /* VolumeEntry.h */, + B6F3651B11ADD0280045E114 /* FileEntry.h */, + B6F3651C11ADD0280045E114 /* Entry.h */, + B6F3676311B323680045E114 /* TextWriter.h */, + B6F3676411B323680045E114 /* TextWriter.cpp */, + ); + path = Pascal; + sourceTree = ""; + }; + B65090171332FE5000FBA318 /* NuFX */ = { + isa = PBXGroup; + children = ( + B65090181332FE5000FBA318 /* Exception.cpp */, + B65090191332FE5000FBA318 /* Exception.h */, + ); + path = NuFX; + sourceTree = ""; + }; + B65090231332FE6A00FBA318 /* POSIX */ = { + isa = PBXGroup; + children = ( + B65090241332FE6A00FBA318 /* Exception.cpp */, + B65090251332FE6A00FBA318 /* Exception.h */, + ); + path = POSIX; + sourceTree = ""; + }; + B65090351332FEBE00FBA318 /* Common */ = { + isa = PBXGroup; + children = ( + B65090361332FEBE00FBA318 /* auto.h */, + B65090371332FEBE00FBA318 /* Exception.cpp */, + B65090381332FEBE00FBA318 /* Exception.h */, + B650903A1332FEBE00FBA318 /* Lock.cpp */, + B650903B1332FEBE00FBA318 /* Lock.h */, + B650903D1332FEBE00FBA318 /* smart_pointers.h */, + B650903E1332FEBE00FBA318 /* unordered_map.h */, + ); + path = Common; + sourceTree = ""; + }; + B656ADED11A84D3200AB578A /* Libraries */ = { + isa = PBXGroup; + children = ( + B6A590F713299626007B0EE2 /* libNuFX.a */, + B6A590EC132995D4007B0EE2 /* Carbon.framework */, + B6A590EE132995D4007B0EE2 /* libz.dylib */, + B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */, + ); + name = Libraries; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + B63EFCCD11A36C7300C90DCE /* apfm */ = { + isa = PBXNativeTarget; + buildConfigurationList = B63EFCEC11A36CB800C90DCE /* Build configuration list for PBXNativeTarget "apfm" */; + buildPhases = ( + B63EFCCB11A36C7300C90DCE /* Sources */, + B63EFCCC11A36C7300C90DCE /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = apfm; + productName = apfm; + productReference = B63EFCCE11A36C7300C90DCE /* apfm */; + productType = "com.apple.product-type.tool"; + }; + B63EFE8011A4886C00C90DCE /* newfs_pascal */ = { + isa = PBXNativeTarget; + buildConfigurationList = B63EFEB311A488C200C90DCE /* Build configuration list for PBXNativeTarget "newfs_pascal" */; + buildPhases = ( + B63EFE7E11A4886C00C90DCE /* Sources */, + B63EFE7F11A4886C00C90DCE /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = newfs_pascal; + productName = newfs_pascal; + productReference = B63EFE8111A4886C00C90DCE /* newfs_pascal */; + productType = "com.apple.product-type.tool"; + }; + B650908A133304C800FBA318 /* profuse */ = { + isa = PBXNativeTarget; + buildConfigurationList = B65090AC133304C800FBA318 /* Build configuration list for PBXNativeTarget "profuse" */; + buildPhases = ( + B650908B133304C800FBA318 /* Sources */, + B65090A7133304C800FBA318 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = profuse; + productName = profuse; + productReference = B65090B1133304C800FBA318 /* profuse */; + productType = "com.apple.product-type.tool"; + }; + B656AE0211A84F5800AB578A /* fuse_pascal */ = { + isa = PBXNativeTarget; + buildConfigurationList = B656AE3411A84FA400AB578A /* Build configuration list for PBXNativeTarget "fuse_pascal" */; + buildPhases = ( + B656AE0011A84F5800AB578A /* Sources */, + B656AE0111A84F5800AB578A /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = fuse_pascal; + productName = fuse_pascal; + productReference = B656AE0311A84F5800AB578A /* fuse_pascal */; + productType = "com.apple.product-type.tool"; + }; + B656AF0211AA105500AB578A /* NibbleTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = B656AF2111AA10A100AB578A /* Build configuration list for PBXNativeTarget "NibbleTest" */; + buildPhases = ( + B656AF0011AA105500AB578A /* Sources */, + B656AF0111AA105500AB578A /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = NibbleTest; + productName = NibbleTest; + productReference = B656AF0311AA105500AB578A /* NibbleTest */; + productType = "com.apple.product-type.tool"; + }; + B6F3647F11AB36260045E114 /* xattr */ = { + isa = PBXNativeTarget; + buildConfigurationList = B6F3648911AB36590045E114 /* Build configuration list for PBXNativeTarget "xattr" */; + buildPhases = ( + B6F3647D11AB36260045E114 /* Sources */, + B6F3647E11AB36260045E114 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = xattr; + productName = xattr; + productReference = B6F3648011AB36260045E114 /* xattr */; + productType = "com.apple.product-type.tool"; + }; + B6F3682411B431AC0045E114 /* newfs_prodos */ = { + isa = PBXNativeTarget; + buildConfigurationList = B6F3684111B432000045E114 /* Build configuration list for PBXNativeTarget "newfs_prodos" */; + buildPhases = ( + B6F3682211B431AC0045E114 /* Sources */, + B6F3682311B431AC0045E114 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = newfs_prodos; + productName = newfs_prodos; + productReference = B6F3682511B431AC0045E114 /* newfs_prodos */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "PROFuseX" */; + compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* PROFuseX */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + B63EFCCD11A36C7300C90DCE /* apfm */, + B63EFE8011A4886C00C90DCE /* newfs_pascal */, + B656AE0211A84F5800AB578A /* fuse_pascal */, + B656AF0211AA105500AB578A /* NibbleTest */, + B6F3647F11AB36260045E114 /* xattr */, + B6F3682411B431AC0045E114 /* newfs_prodos */, + B650908A133304C800FBA318 /* profuse */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + B63EFCCB11A36C7300C90DCE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B63EFCD211A36C8B00C90DCE /* Endian.cpp in Sources */, + B63EFCD311A36C8B00C90DCE /* BlockDevice.cpp in Sources */, + B63EFCD411A36C8B00C90DCE /* DavexDiskImage.cpp in Sources */, + B63EFCD511A36C8B00C90DCE /* DiskCopy42Image.cpp in Sources */, + B63EFCD611A36C8B00C90DCE /* DiskImage.cpp in Sources */, + B63EFCD711A36C8B00C90DCE /* RawDevice.cpp in Sources */, + B63EFCD811A36C8B00C90DCE /* UniversalDiskImage.cpp in Sources */, + B63EFCD911A36C8B00C90DCE /* BlockCache.cpp in Sources */, + B63EFCDA11A36C8B00C90DCE /* ConcreteBlockCache.cpp in Sources */, + B63EFCDB11A36C8B00C90DCE /* MappedBlockCache.cpp in Sources */, + B63EFCDC11A36C8B00C90DCE /* File.cpp in Sources */, + B63EFCDD11A36C8B00C90DCE /* MappedFile.cpp in Sources */, + B63EFCE011A36C8B00C90DCE /* Adaptor.cpp in Sources */, + B63EFCE111A36C8B00C90DCE /* Date.cpp in Sources */, + B63EFCE211A36C8B00C90DCE /* Entry.cpp in Sources */, + B63EFCE311A36C8B00C90DCE /* FileEntry.cpp in Sources */, + B63EFCE511A36C8B00C90DCE /* VolumeEntry.cpp in Sources */, + B6F3676711B323680045E114 /* TextWriter.cpp in Sources */, + B6272A9311D5AC440073C73A /* apfm.cpp in Sources */, + B6A591281329C417007B0EE2 /* SDKImage.cpp in Sources */, + B650901B1332FE5000FBA318 /* Exception.cpp in Sources */, + B65090271332FE6A00FBA318 /* Exception.cpp in Sources */, + B65090311332FE8B00FBA318 /* Exception.cpp in Sources */, + B650903F1332FEBE00FBA318 /* Exception.cpp in Sources */, + B65090471332FEBE00FBA318 /* Lock.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B63EFE7E11A4886C00C90DCE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B63EFE8511A4888500C90DCE /* Endian.cpp in Sources */, + B63EFE8611A4888500C90DCE /* BlockDevice.cpp in Sources */, + B63EFE8711A4888500C90DCE /* DavexDiskImage.cpp in Sources */, + B63EFE8811A4888500C90DCE /* DiskCopy42Image.cpp in Sources */, + B63EFE8911A4888500C90DCE /* DiskImage.cpp in Sources */, + B63EFE8A11A4888500C90DCE /* RawDevice.cpp in Sources */, + B63EFE8B11A4888500C90DCE /* UniversalDiskImage.cpp in Sources */, + B63EFE8C11A4888500C90DCE /* BlockCache.cpp in Sources */, + B63EFE8D11A4888500C90DCE /* ConcreteBlockCache.cpp in Sources */, + B63EFE8E11A4888500C90DCE /* MappedBlockCache.cpp in Sources */, + B63EFE8F11A4888500C90DCE /* File.cpp in Sources */, + B63EFE9011A4888500C90DCE /* MappedFile.cpp in Sources */, + B63EFE9311A4888500C90DCE /* Adaptor.cpp in Sources */, + B63EFE9411A4888500C90DCE /* Date.cpp in Sources */, + B63EFE9511A4888500C90DCE /* Entry.cpp in Sources */, + B63EFE9611A4888500C90DCE /* FileEntry.cpp in Sources */, + B63EFE9711A4888500C90DCE /* VolumeEntry.cpp in Sources */, + B6F3676811B323680045E114 /* TextWriter.cpp in Sources */, + B6272A9611D5AC560073C73A /* newfs_pascal.cpp in Sources */, + B65090281332FE6A00FBA318 /* Exception.cpp in Sources */, + B65090321332FE8B00FBA318 /* Exception.cpp in Sources */, + B65090401332FEBE00FBA318 /* Exception.cpp in Sources */, + B65090481332FEBE00FBA318 /* Lock.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B650908B133304C800FBA318 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B650908C133304C800FBA318 /* Endian.cpp in Sources */, + B650908D133304C800FBA318 /* BlockDevice.cpp in Sources */, + B650908E133304C800FBA318 /* DavexDiskImage.cpp in Sources */, + B650908F133304C800FBA318 /* DiskCopy42Image.cpp in Sources */, + B6509090133304C800FBA318 /* DiskImage.cpp in Sources */, + B6509091133304C800FBA318 /* RawDevice.cpp in Sources */, + B6509092133304C800FBA318 /* UniversalDiskImage.cpp in Sources */, + B6509093133304C800FBA318 /* BlockCache.cpp in Sources */, + B6509094133304C800FBA318 /* ConcreteBlockCache.cpp in Sources */, + B6509095133304C800FBA318 /* MappedBlockCache.cpp in Sources */, + B6509096133304C800FBA318 /* File.cpp in Sources */, + B6509097133304C800FBA318 /* MappedFile.cpp in Sources */, + B6509098133304C800FBA318 /* Adaptor.cpp in Sources */, + B6509099133304C800FBA318 /* SDKImage.cpp in Sources */, + B650909A133304C800FBA318 /* Exception.cpp in Sources */, + B650909B133304C800FBA318 /* Exception.cpp in Sources */, + B650909C133304C800FBA318 /* Exception.cpp in Sources */, + B650909D133304C800FBA318 /* Exception.cpp in Sources */, + B650909E133304C800FBA318 /* Lock.cpp in Sources */, + B650909F133304C800FBA318 /* DateTime.cpp in Sources */, + B65090A0133304C800FBA318 /* File.cpp in Sources */, + B65090A1133304C800FBA318 /* Disk.cpp in Sources */, + B65090A2133304C800FBA318 /* profuse.cpp in Sources */, + B65090A3133304C800FBA318 /* profuse_xattr.cpp in Sources */, + B65090A4133304C800FBA318 /* profuse_stat.cpp in Sources */, + B65090A5133304C800FBA318 /* profuse_file.cpp in Sources */, + B65090A6133304C800FBA318 /* profuse_dirent.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B656AE0011A84F5800AB578A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B656AE0911A84F7700AB578A /* Endian.cpp in Sources */, + B656AE0A11A84F7700AB578A /* BlockDevice.cpp in Sources */, + B656AE0B11A84F7700AB578A /* DavexDiskImage.cpp in Sources */, + B656AE0C11A84F7700AB578A /* DiskCopy42Image.cpp in Sources */, + B656AE0D11A84F7700AB578A /* DiskImage.cpp in Sources */, + B656AE0E11A84F7700AB578A /* RawDevice.cpp in Sources */, + B656AE0F11A84F7700AB578A /* UniversalDiskImage.cpp in Sources */, + B656AE1011A84F7700AB578A /* BlockCache.cpp in Sources */, + B656AE1111A84F7700AB578A /* ConcreteBlockCache.cpp in Sources */, + B656AE1211A84F7700AB578A /* MappedBlockCache.cpp in Sources */, + B656AE1311A84F7700AB578A /* File.cpp in Sources */, + B656AE1411A84F7700AB578A /* MappedFile.cpp in Sources */, + B656AE1711A84F7700AB578A /* Adaptor.cpp in Sources */, + B656AE1811A84F7700AB578A /* Date.cpp in Sources */, + B656AE1911A84F7700AB578A /* Entry.cpp in Sources */, + B656AE1A11A84F7700AB578A /* FileEntry.cpp in Sources */, + B656AE1B11A84F7700AB578A /* VolumeEntry.cpp in Sources */, + B6F3676511B323680045E114 /* TextWriter.cpp in Sources */, + B6272A9411D5AC4C0073C73A /* fuse_pascal.cpp in Sources */, + B6272A9511D5AC530073C73A /* fuse_pascal_ops.cpp in Sources */, + B6A591291329C417007B0EE2 /* SDKImage.cpp in Sources */, + B650901D1332FE5000FBA318 /* Exception.cpp in Sources */, + B65090291332FE6A00FBA318 /* Exception.cpp in Sources */, + B65090331332FE8B00FBA318 /* Exception.cpp in Sources */, + B65090411332FEBE00FBA318 /* Exception.cpp in Sources */, + B65090491332FEBE00FBA318 /* Lock.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B656AF0011AA105500AB578A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B656AF0911AA106C00AB578A /* Endian.cpp in Sources */, + B656AF0A11AA106C00AB578A /* BlockDevice.cpp in Sources */, + B656AF0B11AA106C00AB578A /* DavexDiskImage.cpp in Sources */, + B656AF0C11AA106C00AB578A /* DiskCopy42Image.cpp in Sources */, + B656AF0D11AA106C00AB578A /* DiskImage.cpp in Sources */, + B656AF0E11AA106C00AB578A /* RawDevice.cpp in Sources */, + B656AF0F11AA106C00AB578A /* UniversalDiskImage.cpp in Sources */, + B656AF1011AA106C00AB578A /* BlockCache.cpp in Sources */, + B656AF1111AA106C00AB578A /* ConcreteBlockCache.cpp in Sources */, + B656AF1211AA106C00AB578A /* MappedBlockCache.cpp in Sources */, + B656AF1311AA106C00AB578A /* File.cpp in Sources */, + B656AF1411AA106C00AB578A /* MappedFile.cpp in Sources */, + B656AF1711AA106C00AB578A /* Adaptor.cpp in Sources */, + B656AF1811AA106C00AB578A /* Date.cpp in Sources */, + B656AF1911AA106C00AB578A /* Entry.cpp in Sources */, + B656AF1A11AA106C00AB578A /* FileEntry.cpp in Sources */, + B656AF1B11AA106C00AB578A /* VolumeEntry.cpp in Sources */, + B656AF0811AA106400AB578A /* NibbleTest.cpp in Sources */, + B6F3676611B323680045E114 /* TextWriter.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B6F3647D11AB36260045E114 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B6272A9711D5AC5B0073C73A /* xattr.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B6F3682211B431AC0045E114 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B6F3682A11B431CC0045E114 /* Endian.cpp in Sources */, + B6F3682B11B431CC0045E114 /* BlockDevice.cpp in Sources */, + B6F3682C11B431CC0045E114 /* DavexDiskImage.cpp in Sources */, + B6F3682D11B431CC0045E114 /* DiskCopy42Image.cpp in Sources */, + B6F3682E11B431CC0045E114 /* DiskImage.cpp in Sources */, + B6F3682F11B431CC0045E114 /* RawDevice.cpp in Sources */, + B6F3683011B431CC0045E114 /* UniversalDiskImage.cpp in Sources */, + B6F3683111B431CC0045E114 /* BlockCache.cpp in Sources */, + B6F3683211B431CC0045E114 /* ConcreteBlockCache.cpp in Sources */, + B6F3683311B431CC0045E114 /* MappedBlockCache.cpp in Sources */, + B6F3683411B431CC0045E114 /* File.cpp in Sources */, + B6F3683511B431CC0045E114 /* MappedFile.cpp in Sources */, + B6F3683811B431CC0045E114 /* Adaptor.cpp in Sources */, + B6272AAA11D5AE0C0073C73A /* Bitmap.cpp in Sources */, + B6272AAB11D5AE0C0073C73A /* DateTime.cpp in Sources */, + B650901E1332FE5000FBA318 /* Exception.cpp in Sources */, + B650902A1332FE6A00FBA318 /* Exception.cpp in Sources */, + B65090341332FE8B00FBA318 /* Exception.cpp in Sources */, + B65090421332FEBE00FBA318 /* Exception.cpp in Sources */, + B650904A1332FEBE00FBA318 /* Lock.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB923608733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + /usr/local/include/, + ., + ); + ONLY_ACTIVE_ARCH = NO; + PREBINDING = NO; + SDKROOT = macosx; + }; + name = Debug; + }; + 1DEB923708733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = NO; + PREBINDING = NO; + SDKROOT = macosx; + }; + name = Release; + }; + B63EFCD011A36C7300C90DCE /* 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; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + ., + /usr/local/lib/, + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = apfm; + }; + name = Debug; + }; + B63EFCD111A36C7300C90DCE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + ., + /usr/local/lib/, + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = apfm; + ZERO_LINK = NO; + }; + name = Release; + }; + B63EFE8311A4886C00C90DCE /* 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_VERSION = com.apple.compilers.llvm.clang.1_0; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = newfs_pascal; + }; + name = Debug; + }; + B63EFE8411A4886C00C90DCE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = newfs_pascal; + ZERO_LINK = NO; + }; + name = Release; + }; + B65090AD133304C800FBA318 /* 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; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + ., + /usr/local/lib/, + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = profuse; + }; + name = Debug; + }; + B65090AE133304C800FBA318 /* 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; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + ., + /usr/local/lib/, + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = profuse; + }; + name = "Debug Universal"; + }; + B65090AF133304C800FBA318 /* Debug fuse */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + ., + /usr/local/lib/, + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = profuse; + }; + name = "Debug fuse"; + }; + B65090B0133304C800FBA318 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + ., + /usr/local/lib/, + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = profuse; + ZERO_LINK = NO; + }; + name = Release; + }; + B656AD7A11A84B5D00AB578A /* Debug fuse */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + /usr/local/include/, + ., + ); + ONLY_ACTIVE_ARCH = NO; + PREBINDING = NO; + SDKROOT = macosx; + }; + name = "Debug fuse"; + }; + B656AD7C11A84B5D00AB578A /* Debug fuse */ = { + 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; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + ., + /usr/local/lib/, + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = apfm; + }; + name = "Debug fuse"; + }; + B656AD7D11A84B5D00AB578A /* Debug fuse */ = { + 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_VERSION = com.apple.compilers.llvm.clang.1_0; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = newfs_pascal; + }; + name = "Debug fuse"; + }; + B656AE0511A84F5900AB578A /* 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; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + ., + /usr/local/lib/, + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = fuse_pascal; + }; + name = Debug; + }; + B656AE0611A84F5900AB578A /* Debug fuse */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + ., + /usr/local/lib/, + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = fuse_pascal; + }; + name = "Debug fuse"; + }; + B656AE0711A84F5900AB578A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + ., + /usr/local/lib/, + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = fuse_pascal; + ZERO_LINK = NO; + }; + name = Release; + }; + B656AF0511AA105600AB578A /* 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; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = NibbleTest; + }; + name = Debug; + }; + B656AF0611AA105600AB578A /* Debug fuse */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = NibbleTest; + }; + name = "Debug fuse"; + }; + B656AF0711AA105600AB578A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = NibbleTest; + ZERO_LINK = NO; + }; + name = Release; + }; + B6A53C1E131B47DC00C9070F /* Debug Universal */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + /usr/local/include/, + ., + ); + ONLY_ACTIVE_ARCH = NO; + PREBINDING = NO; + SDKROOT = macosx; + }; + name = "Debug Universal"; + }; + B6A53C1F131B47DC00C9070F /* 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; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + ., + /usr/local/lib/, + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = apfm; + }; + name = "Debug Universal"; + }; + B6A53C20131B47DC00C9070F /* 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_VERSION = com.apple.compilers.llvm.clang.1_0; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = newfs_pascal; + }; + name = "Debug Universal"; + }; + B6A53C21131B47DC00C9070F /* 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; + INSTALL_PATH = /usr/local/bin; + LIBRARY_SEARCH_PATHS = ( + ., + /usr/local/lib/, + ); + OTHER_CFLAGS = "-DHAVE_NUFX"; + PREBINDING = NO; + PRODUCT_NAME = fuse_pascal; + }; + name = "Debug Universal"; + }; + B6A53C22131B47DC00C9070F /* 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; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = NibbleTest; + }; + name = "Debug Universal"; + }; + B6A53C23131B47DC00C9070F /* 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; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = xattr; + }; + name = "Debug Universal"; + }; + B6A53C24131B47DC00C9070F /* 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; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = newfs_prodos; + }; + name = "Debug Universal"; + }; + B6F3648211AB36260045E114 /* 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; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = xattr; + }; + name = Debug; + }; + B6F3648311AB36260045E114 /* Debug fuse */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = xattr; + }; + name = "Debug fuse"; + }; + B6F3648411AB36260045E114 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = xattr; + ZERO_LINK = NO; + }; + name = Release; + }; + B6F3682711B431AC0045E114 /* 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; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = newfs_prodos; + }; + name = Debug; + }; + B6F3682811B431AC0045E114 /* Debug fuse */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = newfs_prodos; + }; + name = "Debug fuse"; + }; + B6F3682911B431AC0045E114 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = newfs_prodos; + ZERO_LINK = NO; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "PROFuseX" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923608733DC60010E9CD /* Debug */, + B6A53C1E131B47DC00C9070F /* Debug Universal */, + B656AD7A11A84B5D00AB578A /* Debug fuse */, + 1DEB923708733DC60010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B63EFCEC11A36CB800C90DCE /* Build configuration list for PBXNativeTarget "apfm" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B63EFCD011A36C7300C90DCE /* Debug */, + B6A53C1F131B47DC00C9070F /* Debug Universal */, + B656AD7C11A84B5D00AB578A /* Debug fuse */, + B63EFCD111A36C7300C90DCE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B63EFEB311A488C200C90DCE /* Build configuration list for PBXNativeTarget "newfs_pascal" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B63EFE8311A4886C00C90DCE /* Debug */, + B6A53C20131B47DC00C9070F /* Debug Universal */, + B656AD7D11A84B5D00AB578A /* Debug fuse */, + B63EFE8411A4886C00C90DCE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B65090AC133304C800FBA318 /* Build configuration list for PBXNativeTarget "profuse" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B65090AD133304C800FBA318 /* Debug */, + B65090AE133304C800FBA318 /* Debug Universal */, + B65090AF133304C800FBA318 /* Debug fuse */, + B65090B0133304C800FBA318 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B656AE3411A84FA400AB578A /* Build configuration list for PBXNativeTarget "fuse_pascal" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B656AE0511A84F5900AB578A /* Debug */, + B6A53C21131B47DC00C9070F /* Debug Universal */, + B656AE0611A84F5900AB578A /* Debug fuse */, + B656AE0711A84F5900AB578A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B656AF2111AA10A100AB578A /* Build configuration list for PBXNativeTarget "NibbleTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B656AF0511AA105600AB578A /* Debug */, + B6A53C22131B47DC00C9070F /* Debug Universal */, + B656AF0611AA105600AB578A /* Debug fuse */, + B656AF0711AA105600AB578A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B6F3648911AB36590045E114 /* Build configuration list for PBXNativeTarget "xattr" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B6F3648211AB36260045E114 /* Debug */, + B6A53C23131B47DC00C9070F /* Debug Universal */, + B6F3648311AB36260045E114 /* Debug fuse */, + B6F3648411AB36260045E114 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B6F3684111B432000045E114 /* Build configuration list for PBXNativeTarget "newfs_prodos" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B6F3682711B431AC0045E114 /* Debug */, + B6A53C24131B47DC00C9070F /* Debug Universal */, + B6F3682811B431AC0045E114 /* Debug fuse */, + B6F3682911B431AC0045E114 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} From e3aea1657f8472d66d9d9a23eb6b2eccbc5377d4 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 19 Mar 2011 01:58:19 +0000 Subject: [PATCH 228/236] rename xcode project git-svn-id: https://profuse.googlecode.com/svn/branches/v2@396 aa027e90-d47c-11dd-86d7-074df07e0730 --- PROFuseX.xcodeproj/kelvin.pbxuser | 1560 ----------------------- PROFuseX.xcodeproj/kelvin.perspectivev3 | 1547 ---------------------- PROFuseX.xcodeproj/project.pbxproj | 1482 --------------------- 3 files changed, 4589 deletions(-) delete mode 100644 PROFuseX.xcodeproj/kelvin.pbxuser delete mode 100644 PROFuseX.xcodeproj/kelvin.perspectivev3 delete mode 100644 PROFuseX.xcodeproj/project.pbxproj diff --git a/PROFuseX.xcodeproj/kelvin.pbxuser b/PROFuseX.xcodeproj/kelvin.pbxuser deleted file mode 100644 index da439c9..0000000 --- a/PROFuseX.xcodeproj/kelvin.pbxuser +++ /dev/null @@ -1,1560 +0,0 @@ -// !$*UTF8*$! -{ - 08FB7793FE84155DC02AAC07 /* Project object */ = { - activeBuildConfigurationName = "Debug Universal"; - activeExecutable = B6F3648111AB36260045E114 /* xattr */; - activeTarget = B6F3647F11AB36260045E114 /* xattr */; - addToTargets = ( - ); - breakpoints = ( - B6F3642F11AA1E150045E114 /* NibbleTest.cpp:76 */, - B6F3657711AE24C40045E114 /* apfm.cpp:589 */, - B6F3663D11B1809A0045E114 /* Adaptor.cpp:167 */, - ); - codeSenseManager = B63EFA6811A093C200C90DCE /* Code sense */; - executables = ( - B63EFCCF11A36C7300C90DCE /* apfm */, - B63EFE8211A4886C00C90DCE /* newfs_pascal */, - B656AE0411A84F5800AB578A /* fuse_pascal */, - B656AF0411AA105500AB578A /* NibbleTest */, - B6F3648111AB36260045E114 /* xattr */, - B6F3682611B431AC0045E114 /* newfs_prodos */, - ); - perUserDictionary = { - "PBXConfiguration.PBXBreakpointsDataSource.v1:1CA1AED706398EBD00589147" = { - PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; - PBXFileTableDataSourceColumnSortingKey = PBXBreakpointsDataSource_BreakpointID; - PBXFileTableDataSourceColumnWidthsKey = ( - 20, - 20, - 198, - 20, - 99, - 99, - 29, - 20, - ); - PBXFileTableDataSourceColumnsKey = ( - PBXBreakpointsDataSource_ActionID, - PBXBreakpointsDataSource_TypeID, - PBXBreakpointsDataSource_BreakpointID, - PBXBreakpointsDataSource_UseID, - PBXBreakpointsDataSource_LocationID, - PBXBreakpointsDataSource_ConditionID, - PBXBreakpointsDataSource_IgnoreCountID, - PBXBreakpointsDataSource_ContinueID, - ); - }; - PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { - PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; - PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; - PBXFileTableDataSourceColumnWidthsKey = ( - 22, - 300, - 548, - ); - PBXFileTableDataSourceColumnsKey = ( - PBXExecutablesDataSource_ActiveFlagID, - PBXExecutablesDataSource_NameID, - PBXExecutablesDataSource_CommentsID, - ); - }; - PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { - PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; - PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_ObjectSize_ColumnID; - PBXFileTableDataSourceColumnWidthsKey = ( - 20, - 660, - 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.PBXTargetDataSource.PBXTargetDataSource = { - PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; - PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; - PBXFileTableDataSourceColumnWidthsKey = ( - 20, - 620, - 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 = 320626757; - PBXWorkspaceStateSaveDate = 320626757; - }; - perUserProjectItems = { - B6272A9911D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9911D5AC5E0073C73A /* PBXTextBookmark */; - B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */; - B6272A9C11D5AC5E0073C73A /* PBXTextBookmark */ = B6272A9C11D5AC5E0073C73A /* PBXTextBookmark */; - B6272B0D11D691320073C73A /* PBXTextBookmark */ = B6272B0D11D691320073C73A /* PBXTextBookmark */; - B6272B0E11D691320073C73A /* PBXTextBookmark */ = B6272B0E11D691320073C73A /* PBXTextBookmark */; - B6272B0F11D691320073C73A /* PBXTextBookmark */ = B6272B0F11D691320073C73A /* PBXTextBookmark */; - B6272B1011D691320073C73A /* PBXTextBookmark */ = B6272B1011D691320073C73A /* PBXTextBookmark */; - B6272B1111D691320073C73A /* PBXTextBookmark */ = B6272B1111D691320073C73A /* PBXTextBookmark */; - B6272B1311D691320073C73A /* PBXTextBookmark */ = B6272B1311D691320073C73A /* PBXTextBookmark */; - B6272B1411D691320073C73A /* PBXTextBookmark */ = B6272B1411D691320073C73A /* PBXTextBookmark */; - B6272B1611D691320073C73A /* PBXTextBookmark */ = B6272B1611D691320073C73A /* PBXTextBookmark */; - B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */ = B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */; - B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */ = B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */; - B63EFDA011A4488200C90DCE /* PBXTextBookmark */ = B63EFDA011A4488200C90DCE /* PBXTextBookmark */; - B63EFDA511A4488200C90DCE /* PBXTextBookmark */ = B63EFDA511A4488200C90DCE /* PBXTextBookmark */; - B63EFDA711A4488200C90DCE /* PBXTextBookmark */ = B63EFDA711A4488200C90DCE /* PBXTextBookmark */; - B63EFDA911A4488200C90DCE /* PBXTextBookmark */ = B63EFDA911A4488200C90DCE /* PBXTextBookmark */; - B63EFDAB11A4488200C90DCE /* PBXTextBookmark */ = B63EFDAB11A4488200C90DCE /* PBXTextBookmark */; - B63EFDAD11A4488200C90DCE /* PBXTextBookmark */ = B63EFDAD11A4488200C90DCE /* PBXTextBookmark */; - B63EFDAF11A4488200C90DCE /* PBXTextBookmark */ = B63EFDAF11A4488200C90DCE /* PBXTextBookmark */; - B63EFDB111A4488200C90DCE /* PBXTextBookmark */ = B63EFDB111A4488200C90DCE /* PBXTextBookmark */; - B63EFDB311A4488200C90DCE /* PBXTextBookmark */ = B63EFDB311A4488200C90DCE /* PBXTextBookmark */; - B63EFDF211A4504200C90DCE /* PBXTextBookmark */ = B63EFDF211A4504200C90DCE /* PBXTextBookmark */; - B63EFEA011A488C200C90DCE /* PBXTextBookmark */ = B63EFEA011A488C200C90DCE /* PBXTextBookmark */; - B63EFEA111A488C200C90DCE /* PBXTextBookmark */ = B63EFEA111A488C200C90DCE /* PBXTextBookmark */; - B63EFEA811A488C200C90DCE /* PBXTextBookmark */ = B63EFEA811A488C200C90DCE /* PBXTextBookmark */; - B656AE2611A84FA400AB578A /* PBXTextBookmark */ = B656AE2611A84FA400AB578A /* PBXTextBookmark */; - B65CFB6911B495790024A2D9 /* PBXTextBookmark */ = B65CFB6911B495790024A2D9 /* PBXTextBookmark */; - B6A53B8E1319DDFC00C9070F /* PBXTextBookmark */ = B6A53B8E1319DDFC00C9070F /* PBXTextBookmark */; - B6A53BC7131B400800C9070F /* PBXTextBookmark */ = B6A53BC7131B400800C9070F /* PBXTextBookmark */; - B6A53BC8131B400800C9070F /* PBXTextBookmark */ = B6A53BC8131B400800C9070F /* PBXTextBookmark */; - B6A53C34131B4CF800C9070F /* PBXTextBookmark */ = B6A53C34131B4CF800C9070F /* PBXTextBookmark */; - B6AA3AB21318D063007D4BA1 /* PBXTextBookmark */ = B6AA3AB21318D063007D4BA1 /* PBXTextBookmark */; - B6AA3AB31318D063007D4BA1 /* PBXTextBookmark */ = B6AA3AB31318D063007D4BA1 /* PBXTextBookmark */; - B6AA3AB41318D063007D4BA1 /* PBXTextBookmark */ = B6AA3AB41318D063007D4BA1 /* PBXTextBookmark */; - B6E5F0DD11A60726000AD141 /* PBXTextBookmark */ = B6E5F0DD11A60726000AD141 /* PBXTextBookmark */; - B6E5F0F211A73144000AD141 /* PBXTextBookmark */ = B6E5F0F211A73144000AD141 /* PBXTextBookmark */; - B6E5F11211A73340000AD141 /* PBXTextBookmark */ = B6E5F11211A73340000AD141 /* PBXTextBookmark */; - B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */ = B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */; - B6E5F18211A76B74000AD141 /* PBXTextBookmark */ = B6E5F18211A76B74000AD141 /* PBXTextBookmark */; - B6F3647111AB35FE0045E114 /* PBXTextBookmark */ = B6F3647111AB35FE0045E114 /* PBXTextBookmark */; - B6F3649E11AB59190045E114 /* PBXTextBookmark */ = B6F3649E11AB59190045E114 /* PBXTextBookmark */; - B6F364B711AB84840045E114 /* PBXTextBookmark */ = B6F364B711AB84840045E114 /* PBXTextBookmark */; - B6F3652E11ADD5D20045E114 /* PBXTextBookmark */ = B6F3652E11ADD5D20045E114 /* PBXTextBookmark */; - B6F3653011ADD5D20045E114 /* PBXTextBookmark */ = B6F3653011ADD5D20045E114 /* PBXTextBookmark */; - B6F3657E11AE255B0045E114 /* PBXTextBookmark */ = B6F3657E11AE255B0045E114 /* PBXTextBookmark */; - B6F3665411B190370045E114 /* PBXTextBookmark */ = B6F3665411B190370045E114 /* PBXTextBookmark */; - B6F3665C11B194AC0045E114 /* PBXTextBookmark */ = B6F3665C11B194AC0045E114 /* PBXTextBookmark */; - B6F366C411B1A28C0045E114 /* PBXTextBookmark */ = B6F366C411B1A28C0045E114 /* PBXTextBookmark */; - B6F366C611B1A28C0045E114 /* PBXTextBookmark */ = B6F366C611B1A28C0045E114 /* PBXTextBookmark */; - B6F366C711B1A28C0045E114 /* PBXTextBookmark */ = B6F366C711B1A28C0045E114 /* PBXTextBookmark */; - B6F366C811B1A28C0045E114 /* PBXTextBookmark */ = B6F366C811B1A28C0045E114 /* PBXTextBookmark */; - B6F366C911B1A28C0045E114 /* PBXTextBookmark */ = B6F366C911B1A28C0045E114 /* PBXTextBookmark */; - B6F366CA11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CA11B1A28C0045E114 /* PBXTextBookmark */; - B6F366CB11B1A28C0045E114 /* PBXTextBookmark */ = B6F366CB11B1A28C0045E114 /* PBXTextBookmark */; - B6F3677C11B326580045E114 /* PBXTextBookmark */ = B6F3677C11B326580045E114 /* PBXTextBookmark */; - B6F3677D11B326580045E114 /* PBXTextBookmark */ = B6F3677D11B326580045E114 /* PBXTextBookmark */; - B6F3677E11B326580045E114 /* PBXTextBookmark */ = B6F3677E11B326580045E114 /* PBXTextBookmark */; - B6F367A011B330D10045E114 /* PBXTextBookmark */ = B6F367A011B330D10045E114 /* PBXTextBookmark */; - B6F367AE11B337A70045E114 /* PBXTextBookmark */ = B6F367AE11B337A70045E114 /* PBXTextBookmark */; - B6F3684A11B44D090045E114 /* PBXTextBookmark */ = B6F3684A11B44D090045E114 /* PBXTextBookmark */; - B6F8D4AD131CB30300461B54 /* PBXTextBookmark */ = B6F8D4AD131CB30300461B54 /* PBXTextBookmark */; - }; - sourceControlManager = B63EFA6711A093C200C90DCE /* Source Control */; - userBuildSettings = { - }; - }; - B6272A8E11D5AC3C0073C73A /* apfm.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 13975}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 562}"; - }; - }; - B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 4069}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 672}"; - }; - }; - B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1245, 7124}}"; - sepNavSelRange = "{1531, 0}"; - sepNavVisRange = "{367, 1775}"; - }; - }; - B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 4615}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 477}"; - }; - }; - B6272A9211D5AC3C0073C73A /* xattr.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 5434}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 936}"; - }; - }; - B6272A9911D5AC5E0073C73A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6272A8E11D5AC3C0073C73A /* apfm.cpp */; - name = "apfm.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 562; - vrLoc = 0; - }; - B6272A9B11D5AC5E0073C73A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */; - name = "fuse_pascal_ops.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 643; - vrLoc = 0; - }; - B6272A9C11D5AC5E0073C73A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */; - name = "newfs_pascal.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 477; - vrLoc = 0; - }; - B6272AA211D5AC840073C73A /* newfs_prodos.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 3094}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 1145}"; - }; - }; - B6272AA511D5AE0C0073C73A /* Bitmap.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1249, 2912}}"; - sepNavSelRange = "{108, 0}"; - sepNavVisRange = "{0, 1570}"; - }; - }; - B6272AA611D5AE0C0073C73A /* Bitmap.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1249, 978}}"; - sepNavSelRange = "{147, 0}"; - sepNavVisRange = "{0, 888}"; - }; - }; - B6272AA711D5AE0C0073C73A /* DateTime.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 1911}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 870}"; - }; - }; - B6272B0D11D691320073C73A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6272A9211D5AC3C0073C73A /* xattr.cpp */; - name = "xattr.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 936; - vrLoc = 0; - }; - B6272B0E11D691320073C73A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6272AA211D5AC840073C73A /* newfs_prodos.cpp */; - name = "newfs_prodos.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 1145; - vrLoc = 0; - }; - B6272B0F11D691320073C73A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6272AA711D5AE0C0073C73A /* DateTime.cpp */; - name = "DateTime.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 870; - vrLoc = 0; - }; - B6272B1011D691320073C73A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6272AA511D5AE0C0073C73A /* Bitmap.cpp */; - name = "Bitmap.cpp: 29"; - rLen = 0; - rLoc = 456; - rType = 0; - vrLen = 679; - vrLoc = 0; - }; - B6272B1111D691320073C73A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - comments = "'Device' has not been declared"; - fRef = B6272B1211D691320073C73A /* Bitmap.h */; - rLen = 1; - rLoc = 21; - rType = 1; - }; - B6272B1211D691320073C73A /* Bitmap.h */ = { - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - name = Bitmap.h; - path = ./ProDOS/Bitmap.h; - sourceTree = ""; - }; - B6272B1311D691320073C73A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA9611A094E000C90DCE /* BlockDevice.h */; - name = "BlockDevice.h: 24"; - rLen = 0; - rLoc = 431; - rType = 0; - vrLen = 853; - vrLoc = 0; - }; - B6272B1411D691320073C73A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; - name = "BlockDevice.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 740; - vrLoc = 0; - }; - B6272B1611D691320073C73A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; - name = "BlockCache.cpp: 58"; - rLen = 0; - rLoc = 962; - rType = 0; - vrLen = 718; - vrLoc = 403; - }; - B63EFA6711A093C200C90DCE /* Source Control */ = { - isa = PBXSourceControlManager; - fallbackIsa = XCSourceControlManager; - isSCMEnabled = 0; - scmConfiguration = { - repositoryNamesForRoots = { - "" = ""; - }; - }; - }; - B63EFA6811A093C200C90DCE /* Code sense */ = { - isa = PBXCodeSenseManager; - indexTemplatePath = ""; - }; - B63EFA7511A0948500C90DCE /* Endian.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 1339}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 819}"; - }; - }; - B63EFA7611A0948500C90DCE /* Endian.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {409, 2080}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 97}"; - }; - }; - B63EFA7711A0948500C90DCE /* IOBuffer.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 562}}"; - sepNavSelRange = "{190, 0}"; - sepNavVisRange = "{0, 206}"; - }; - }; - B63EFA9511A094E000C90DCE /* BlockDevice.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 3198}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 740}"; - }; - }; - B63EFA9611A094E000C90DCE /* BlockDevice.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 780}}"; - sepNavSelRange = "{431, 0}"; - sepNavVisRange = "{0, 853}"; - }; - }; - B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 2119}}"; - sepNavSelRange = "{2355, 0}"; - sepNavVisRange = "{1920, 875}"; - }; - }; - B63EFA9811A094E000C90DCE /* DavexDiskImage.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1015, 944}}"; - sepNavSelRange = "{597, 0}"; - sepNavVisRange = "{0, 740}"; - }; - }; - B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 2938}}"; - sepNavSelRange = "{2053, 0}"; - sepNavVisRange = "{1629, 925}"; - }; - }; - B63EFA9C11A094E000C90DCE /* DiskCopy42Image.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1015, 944}}"; - sepNavSelRange = "{661, 0}"; - sepNavVisRange = "{0, 772}"; - }; - }; - B63EFA9D11A094E000C90DCE /* DiskImage.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1009, 2743}}"; - sepNavSelRange = "{550, 0}"; - sepNavVisRange = "{0, 1053}"; - }; - }; - B63EFA9E11A094E000C90DCE /* DiskImage.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1264, 1027}}"; - sepNavSelRange = "{652, 0}"; - sepNavVisRange = "{0, 1529}"; - }; - }; - B63EFAA111A094E000C90DCE /* RawDevice.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 4186}}"; - sepNavSelRange = "{2579, 0}"; - sepNavVisRange = "{2262, 800}"; - }; - }; - B63EFAA211A094E000C90DCE /* RawDevice.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1009, 958}}"; - sepNavSelRange = "{894, 0}"; - sepNavVisRange = "{0, 1056}"; - }; - }; - B63EFAA311A094E000C90DCE /* TrackSector.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1178, 341}}"; - sepNavSelRange = "{262, 0}"; - sepNavVisRange = "{0, 316}"; - }; - }; - B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 2067}}"; - sepNavSelRange = "{956, 0}"; - sepNavVisRange = "{497, 808}"; - }; - }; - B63EFAA511A094E000C90DCE /* UniversalDiskImage.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 546}}"; - sepNavSelRange = "{507, 4}"; - sepNavVisRange = "{0, 692}"; - }; - }; - B63EFAB611A098C400C90DCE /* BlockCache.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 962}}"; - sepNavSelRange = "{962, 0}"; - sepNavVisRange = "{403, 718}"; - }; - }; - B63EFAB711A098C400C90DCE /* BlockCache.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 767}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{118, 910}"; - }; - }; - B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 5070}}"; - sepNavSelRange = "{5248, 0}"; - sepNavVisRange = "{4735, 1303}"; - }; - }; - B63EFAB911A098C400C90DCE /* ConcreteBlockCache.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1264, 932}}"; - sepNavSelRange = "{526, 0}"; - sepNavVisRange = "{0, 1257}"; - }; - }; - B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 1846}}"; - sepNavSelRange = "{1292, 0}"; - sepNavVisRange = "{0, 1315}"; - }; - }; - B63EFABB11A098C400C90DCE /* MappedBlockCache.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 948}}"; - sepNavSelRange = "{630, 0}"; - sepNavVisRange = "{0, 659}"; - }; - }; - B63EFAC911A09DAA00C90DCE /* File.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1009, 1599}}"; - sepNavSelRange = "{1429, 0}"; - sepNavVisRange = "{248, 1374}"; - }; - }; - B63EFACA11A09DAA00C90DCE /* File.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 754}}"; - sepNavSelRange = "{244, 0}"; - sepNavVisRange = "{0, 749}"; - }; - }; - B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 2574}}"; - sepNavSelRange = "{1115, 0}"; - sepNavVisRange = "{0, 1267}"; - }; - }; - B63EFACC11A09DAA00C90DCE /* MappedFile.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1264, 932}}"; - sepNavSelRange = "{211, 0}"; - sepNavVisRange = "{0, 927}"; - }; - }; - B63EFAD011A09DB500C90DCE /* auto.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1264, 1365}}"; - sepNavSelRange = "{287, 0}"; - sepNavVisRange = "{517, 1036}"; - }; - }; - B63EFAD111A09DB500C90DCE /* Exception.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 562}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 157}"; - }; - }; - B63EFAD211A09DB500C90DCE /* Exception.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 1911}}"; - sepNavSelRange = "{633, 13}"; - sepNavVisRange = "{0, 1568}"; - }; - }; - B63EFAD311A09DB500C90DCE /* Lock.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1207, 914}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 353}"; - }; - }; - B63EFB0611A0AC4800C90DCE /* Adaptor.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 1066}}"; - sepNavSelRange = "{1806, 0}"; - sepNavVisRange = "{442, 1126}"; - }; - }; - B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 6448}}"; - sepNavSelRange = "{8303, 0}"; - sepNavVisRange = "{2730, 1774}"; - }; - }; - B63EFB8811A1FB2500C90DCE /* DiskImage.h */ = { - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - name = DiskImage.h; - path = ./Device/DiskImage.h; - sourceTree = ""; - }; - B63EFBE811A244EE00C90DCE /* Date.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 611}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 834}"; - }; - }; - B63EFBE911A244EE00C90DCE /* Date.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 585}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 654}"; - }; - }; - B63EFBEA11A244EE00C90DCE /* Entry.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {701, 1248}}"; - sepNavSelRange = "{22, 0}"; - sepNavVisRange = "{0, 1220}"; - }; - }; - B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 9581}}"; - sepNavSelRange = "{628, 36}"; - sepNavVisRange = "{335, 746}"; - }; - }; - B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 13026}}"; - sepNavSelRange = "{13717, 0}"; - sepNavVisRange = "{13228, 1176}"; - }; - }; - B63EFC2611A2D5A400C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA7611A0948500C90DCE /* Endian.h */; - name = "Endian.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 97; - vrLoc = 0; - }; - B63EFC3211A2D5A400C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAB911A098C400C90DCE /* ConcreteBlockCache.h */; - name = "ConcreteBlockCache.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 297; - vrLoc = 0; - }; - B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1009, 1339}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{687, 1732}"; - }; - }; - B63EFCC811A366C800C90DCE /* MappedFile.h */ = { - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - name = MappedFile.h; - path = ./File/MappedFile.h; - sourceTree = ""; - }; - B63EFCCD11A36C7300C90DCE /* apfm */ = { - activeExec = 0; - executables = ( - B63EFCCF11A36C7300C90DCE /* apfm */, - ); - }; - B63EFCCF11A36C7300C90DCE /* apfm */ = { - isa = PBXExecutable; - activeArgIndices = ( - YES, - YES, - YES, - ); - argumentStrings = ( - /Users/kelvin/Projects/PROFuseX/bleh.po, - cat, - XATTR.CPP, - ); - autoAttachOnCrash = 1; - breakpointsEnabled = 1; - configStateDict = { - }; - customDataFormattersEnabled = 1; - dataTipCustomDataFormattersEnabled = 1; - dataTipShowTypeColumn = 1; - dataTipSortType = 0; - debuggerPlugin = GDBDebugging; - disassemblyDisplayState = 0; - dylibVariantSuffix = ""; - enableDebugStr = 1; - environmentEntries = ( - ); - executableSystemSymbolLevel = 0; - executableUserSymbolLevel = 0; - libgmallocEnabled = 0; - name = apfm; - savedGlobals = { - }; - showTypeColumn = 0; - sourceDirectories = ( - ); - variableFormatDictionary = { - "_length-size_t-Device::DOSOrderDiskImage::DOSOrderDiskImage" = 1; - "size-size_t-MappedFile::init" = 1; - }; - }; - B63EFDA011A4488200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFDA111A4488200C90DCE /* memory */; - name = "memory: 300"; - rLen = 0; - rLoc = 10169; - rType = 0; - vrLen = 348; - vrLoc = 9980; - }; - B63EFDA111A4488200C90DCE /* memory */ = { - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.h; - name = memory; - path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/memory"; - sourceTree = ""; - }; - B63EFDA511A4488200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFDA611A4488200C90DCE /* new */; - name = "new: 105"; - rLen = 0; - rLoc = 3667; - rType = 0; - vrLen = 1002; - vrLoc = 3039; - }; - B63EFDA611A4488200C90DCE /* new */ = { - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.h; - name = new; - path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/new"; - sourceTree = ""; - }; - B63EFDA711A4488200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFDA811A4488200C90DCE /* new_allocator.h */; - name = "new_allocator.h: 70"; - rLen = 0; - rLoc = 2448; - rType = 0; - vrLen = 768; - vrLoc = 2080; - }; - B63EFDA811A4488200C90DCE /* new_allocator.h */ = { - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - name = new_allocator.h; - path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/ext/new_allocator.h"; - sourceTree = ""; - }; - B63EFDA911A4488200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFDAA11A4488200C90DCE /* allocator.h */; - name = "allocator.h: 103"; - rLen = 0; - rLoc = 3498; - rType = 0; - vrLen = 729; - vrLoc = 3092; - }; - B63EFDAA11A4488200C90DCE /* allocator.h */ = { - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - name = allocator.h; - path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/allocator.h"; - sourceTree = ""; - }; - B63EFDAB11A4488200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFDAC11A4488200C90DCE /* stl_iterator.h */; - name = "stl_iterator.h: 718"; - rLen = 0; - rLoc = 22590; - rType = 0; - vrLen = 1056; - vrLoc = 22176; - }; - B63EFDAC11A4488200C90DCE /* stl_iterator.h */ = { - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - name = stl_iterator.h; - path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_iterator.h"; - sourceTree = ""; - }; - B63EFDAD11A4488200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFDAE11A4488200C90DCE /* stl_algobase.h */; - name = "stl_algobase.h: 398"; - rLen = 0; - rLoc = 13483; - rType = 0; - vrLen = 1046; - vrLoc = 13073; - }; - B63EFDAE11A4488200C90DCE /* stl_algobase.h */ = { - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - name = stl_algobase.h; - path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_algobase.h"; - sourceTree = ""; - }; - B63EFDAF11A4488200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFDB011A4488200C90DCE /* stl_uninitialized.h */; - name = "stl_uninitialized.h: 75"; - rLen = 0; - rLoc = 3073; - rType = 0; - vrLen = 804; - vrLoc = 8199; - }; - B63EFDB011A4488200C90DCE /* stl_uninitialized.h */ = { - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - name = stl_uninitialized.h; - path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_uninitialized.h"; - sourceTree = ""; - }; - B63EFDB111A4488200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFDB211A4488200C90DCE /* vector.tcc */; - name = "vector.tcc: 293"; - rLen = 0; - rLoc = 9731; - rType = 0; - vrLen = 818; - vrLoc = 9315; - }; - B63EFDB211A4488200C90DCE /* vector.tcc */ = { - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - name = vector.tcc; - path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/vector.tcc"; - sourceTree = ""; - }; - B63EFDB311A4488200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFDB411A4488200C90DCE /* stl_vector.h */; - name = "stl_vector.h: 608"; - rLen = 0; - rLoc = 20940; - rType = 0; - vrLen = 779; - vrLoc = 20537; - }; - B63EFDB411A4488200C90DCE /* stl_vector.h */ = { - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - name = stl_vector.h; - path = "/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_vector.h"; - sourceTree = ""; - }; - B63EFDF211A4504200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAD011A09DB500C90DCE /* auto.h */; - name = "auto.h: 20"; - rLen = 0; - rLoc = 287; - rType = 0; - vrLen = 479; - vrLoc = 0; - }; - B63EFE8011A4886C00C90DCE /* newfs_pascal */ = { - activeExec = 0; - executables = ( - B63EFE8211A4886C00C90DCE /* newfs_pascal */, - ); - }; - B63EFE8211A4886C00C90DCE /* newfs_pascal */ = { - isa = PBXExecutable; - activeArgIndices = ( - ); - argumentStrings = ( - ); - autoAttachOnCrash = 1; - breakpointsEnabled = 1; - configStateDict = { - }; - customDataFormattersEnabled = 1; - dataTipCustomDataFormattersEnabled = 1; - dataTipShowTypeColumn = 1; - dataTipSortType = 0; - debuggerPlugin = GDBDebugging; - disassemblyDisplayState = 0; - enableDebugStr = 1; - environmentEntries = ( - ); - executableSystemSymbolLevel = 0; - executableUserSymbolLevel = 0; - libgmallocEnabled = 0; - name = newfs_pascal; - showTypeColumn = 0; - sourceDirectories = ( - ); - }; - B63EFEA011A488C200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA9C11A094E000C90DCE /* DiskCopy42Image.h */; - name = "DiskCopy42Image.h: 19"; - rLen = 0; - rLoc = 459; - rType = 0; - vrLen = 803; - vrLoc = 0; - }; - B63EFEA111A488C200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA9811A094E000C90DCE /* DavexDiskImage.h */; - name = "DavexDiskImage.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 763; - vrLoc = 0; - }; - B63EFEA811A488C200C90DCE /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; - name = "Date.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 834; - vrLoc = 0; - }; - B656AE0211A84F5800AB578A /* fuse_pascal */ = { - activeExec = 0; - executables = ( - B656AE0411A84F5800AB578A /* fuse_pascal */, - ); - }; - B656AE0411A84F5800AB578A /* fuse_pascal */ = { - isa = PBXExecutable; - activeArgIndices = ( - ); - argumentStrings = ( - ); - autoAttachOnCrash = 1; - breakpointsEnabled = 0; - configStateDict = { - }; - customDataFormattersEnabled = 1; - dataTipCustomDataFormattersEnabled = 1; - dataTipShowTypeColumn = 1; - dataTipSortType = 0; - debuggerPlugin = GDBDebugging; - disassemblyDisplayState = 0; - enableDebugStr = 1; - environmentEntries = ( - ); - executableSystemSymbolLevel = 0; - executableUserSymbolLevel = 0; - libgmallocEnabled = 0; - name = fuse_pascal; - showTypeColumn = 0; - sourceDirectories = ( - ); - }; - B656AE2611A84FA400AB578A /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAA211A094E000C90DCE /* RawDevice.h */; - name = "RawDevice.h: 15"; - rLen = 0; - rLoc = 186; - rType = 0; - vrLen = 781; - vrLoc = 126; - }; - B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1178, 1248}}"; - sepNavSelRange = "{1680, 0}"; - sepNavVisRange = "{1472, 529}"; - }; - }; - B656AF0211AA105500AB578A /* NibbleTest */ = { - activeExec = 0; - executables = ( - B656AF0411AA105500AB578A /* NibbleTest */, - ); - }; - B656AF0411AA105500AB578A /* NibbleTest */ = { - isa = PBXExecutable; - activeArgIndices = ( - ); - argumentStrings = ( - ); - autoAttachOnCrash = 1; - breakpointsEnabled = 1; - configStateDict = { - }; - customDataFormattersEnabled = 1; - dataTipCustomDataFormattersEnabled = 1; - dataTipShowTypeColumn = 1; - dataTipSortType = 0; - debuggerPlugin = GDBDebugging; - disassemblyDisplayState = 0; - dylibVariantSuffix = ""; - enableDebugStr = 1; - environmentEntries = ( - ); - executableSystemSymbolLevel = 0; - executableUserSymbolLevel = 0; - libgmallocEnabled = 0; - name = NibbleTest; - savedGlobals = { - }; - showTypeColumn = 0; - sourceDirectories = ( - ); - variableFormatDictionary = { - "87-unsigned int-Device::NibbleAdaptor::NibbleAdaptor" = 1; - "checksum-uint8_t-Device::NibbleAdaptor::readTrackSector" = 1; - "index-unsigned int-Device::NibbleAdaptor::readTrackSector" = 1; - "offset-int-Device::NibbleAdaptor::NibbleAdaptor" = 1; - "offset-unsigned int-Device::NibbleAdaptor::readTrackSector" = 1; - "val-uint8_t-Device::NibbleAdaptor::decode62" = 1; - "x-uint8_t-Device::NibbleAdaptor::readTrackSector" = 1; - "y-uint8_t-Device::NibbleAdaptor::readTrackSector" = 1; - }; - }; - B65CFB6911B495790024A2D9 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; - name = "RawDevice.cpp: 136"; - rLen = 0; - rLoc = 2579; - rType = 0; - vrLen = 800; - vrLoc = 2262; - }; - B6A53B851319DA3D00C9070F /* smart_pointers.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 475}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 903}"; - }; - }; - B6A53B8E1319DDFC00C9070F /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6A53B851319DA3D00C9070F /* smart_pointers.h */; - name = "smart_pointers.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 903; - vrLoc = 0; - }; - B6A53BC7131B400800C9070F /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6F3651B11ADD0280045E114 /* FileEntry.h */; - name = "FileEntry.h: 20"; - rLen = 23; - rLoc = 292; - rType = 0; - vrLen = 797; - vrLoc = 62; - }; - B6A53BC8131B400800C9070F /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; - name = "FileEntry.cpp: 40"; - rLen = 36; - rLoc = 628; - rType = 0; - vrLen = 746; - vrLoc = 335; - }; - B6A53C34131B4CF800C9070F /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 616"; - rLen = 0; - rLoc = 13717; - rType = 0; - vrLen = 1185; - vrLoc = 13219; - }; - B6AA3AB21318D063007D4BA1 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAB711A098C400C90DCE /* BlockCache.h */; - name = "BlockCache.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 910; - vrLoc = 118; - }; - B6AA3AB31318D063007D4BA1 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; - name = "Endian.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 819; - vrLoc = 0; - }; - B6AA3AB41318D063007D4BA1 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */; - name = "fuse_pascal.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 672; - vrLoc = 0; - }; - B6E5F0DD11A60726000AD141 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; - name = "ConcreteBlockCache.cpp: 185"; - rLen = 0; - rLoc = 4102; - rType = 0; - vrLen = 885; - vrLoc = 3468; - }; - B6E5F0F211A73144000AD141 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFABB11A098C400C90DCE /* MappedBlockCache.h */; - name = "MappedBlockCache.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 667; - vrLoc = 0; - }; - B6E5F11211A73340000AD141 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA7711A0948500C90DCE /* IOBuffer.h */; - name = "IOBuffer.h: 12"; - rLen = 0; - rLoc = 190; - rType = 0; - vrLen = 206; - vrLoc = 0; - }; - B6E5F13A11A74F2B000AD141 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */; - name = "IOBuffer.cpp.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 1056; - vrLoc = 1363; - }; - B6E5F18211A76B74000AD141 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAD111A09DB500C90DCE /* Exception.cpp */; - name = "Exception.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 157; - vrLoc = 0; - }; - B6F3642F11AA1E150045E114 /* NibbleTest.cpp:76 */ = { - isa = PBXFileBreakpoint; - actions = ( - ); - breakpointStyle = 0; - continueAfterActions = 0; - countType = 0; - delayBeforeContinue = 0; - fileReference = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; - functionName = "main(int argc, char **argv)"; - hitCount = 0; - ignoreCount = 0; - lineNumber = 76; - modificationTime = 299278551.142724; - originalNumberOfMultipleMatches = 1; - state = 0; - }; - B6F3647111AB35FE0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFB0611A0AC4800C90DCE /* Adaptor.h */; - name = "Adaptor.h: 82"; - rLen = 0; - rLoc = 1806; - rType = 0; - vrLen = 1126; - vrLoc = 442; - }; - B6F3647F11AB36260045E114 /* xattr */ = { - activeExec = 0; - executables = ( - B6F3648111AB36260045E114 /* xattr */, - ); - }; - B6F3648111AB36260045E114 /* xattr */ = { - isa = PBXExecutable; - activeArgIndices = ( - ); - argumentStrings = ( - ); - autoAttachOnCrash = 1; - breakpointsEnabled = 0; - configStateDict = { - }; - customDataFormattersEnabled = 1; - dataTipCustomDataFormattersEnabled = 1; - dataTipShowTypeColumn = 1; - dataTipSortType = 0; - debuggerPlugin = GDBDebugging; - disassemblyDisplayState = 0; - enableDebugStr = 1; - environmentEntries = ( - ); - executableSystemSymbolLevel = 0; - executableUserSymbolLevel = 0; - libgmallocEnabled = 0; - name = xattr; - showTypeColumn = 0; - sourceDirectories = ( - ); - }; - B6F3649E11AB59190045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; - name = "File.cpp: 35"; - rLen = 0; - rLoc = 384; - rType = 0; - vrLen = 571; - vrLoc = 0; - }; - B6F364B711AB84840045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAD211A09DB500C90DCE /* Exception.h */; - name = "Exception.h: 39"; - rLen = 10; - rLoc = 783; - rType = 0; - vrLen = 1003; - vrLoc = 434; - }; - B6F3651A11ADD0280045E114 /* VolumeEntry.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 1365}}"; - sepNavSelRange = "{145, 0}"; - sepNavVisRange = "{0, 974}"; - }; - }; - B6F3651B11ADD0280045E114 /* FileEntry.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 1430}}"; - sepNavSelRange = "{292, 23}"; - sepNavVisRange = "{62, 797}"; - }; - }; - B6F3651C11ADD0280045E114 /* Entry.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 1079}}"; - sepNavSelRange = "{1399, 0}"; - sepNavVisRange = "{0, 605}"; - }; - }; - B6F3652711ADD52B0045E114 /* Pascal.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 530}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 173}"; - }; - }; - B6F3652E11ADD5D20045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6F3652711ADD52B0045E114 /* Pascal.h */; - name = "Pascal.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 173; - vrLoc = 0; - }; - B6F3653011ADD5D20045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; - name = "Entry.cpp: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 712; - vrLoc = 0; - }; - B6F3657711AE24C40045E114 /* apfm.cpp:589 */ = { - isa = PBXFileBreakpoint; - actions = ( - ); - breakpointStyle = 0; - continueAfterActions = 0; - countType = 0; - delayBeforeContinue = 0; - fileReference = B6272A8E11D5AC3C0073C73A /* apfm.cpp */; - functionName = "action_rm(int argc, char **argv, Pascal::VolumeEntry *volume)"; - hitCount = 0; - ignoreCount = 0; - lineNumber = 589; - modificationTime = 299278551.143155; - originalNumberOfMultipleMatches = 1; - state = 1; - }; - B6F3657E11AE255B0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBE911A244EE00C90DCE /* Date.h */; - name = "Date.h: 1"; - rLen = 0; - rLoc = 0; - rType = 0; - vrLen = 654; - vrLoc = 0; - }; - B6F365CC11B08AE30045E114 /* VolumeEntry.h */ = { - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - name = VolumeEntry.h; - path = ./Pascal/VolumeEntry.h; - sourceTree = ""; - }; - B6F3663D11B1809A0045E114 /* Adaptor.cpp:167 */ = { - isa = PBXFileBreakpoint; - actions = ( - ); - breakpointStyle = 0; - continueAfterActions = 0; - countType = 0; - delayBeforeContinue = 0; - fileReference = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; - functionName = "NibbleAdaptor::decode62(uint8_t val)"; - hitCount = 0; - ignoreCount = 0; - lineNumber = 167; - modificationTime = 299278551.143489; - originalNumberOfMultipleMatches = 1; - state = 0; - }; - B6F3665411B190370045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; - name = "Adaptor.cpp: 167"; - rLen = 0; - rLoc = 3653; - rType = 0; - vrLen = 933; - vrLoc = 7817; - }; - B6F3665C11B194AC0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; - name = "NibbleTest.cpp: 76"; - rLen = 0; - rLoc = 1680; - rType = 0; - vrLen = 951; - vrLoc = 1203; - }; - B6F366C411B1A28C0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; - name = "MappedFile.cpp: 53"; - rLen = 0; - rLoc = 970; - rType = 0; - vrLen = 737; - vrLoc = 463; - }; - B6F366C611B1A28C0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFB8811A1FB2500C90DCE /* DiskImage.h */; - name = "DiskImage.h: 66"; - rLen = 0; - rLoc = 1204; - rType = 0; - vrLen = 809; - vrLoc = 709; - }; - B6F366C711B1A28C0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAA511A094E000C90DCE /* UniversalDiskImage.h */; - name = "UniversalDiskImage.h: 29"; - rLen = 4; - rLoc = 507; - rType = 0; - vrLen = 692; - vrLoc = 0; - }; - B6F366C811B1A28C0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; - name = "DavexDiskImage.cpp: 111"; - rLen = 0; - rLoc = 2355; - rType = 0; - vrLen = 875; - vrLoc = 1920; - }; - B6F366C911B1A28C0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; - name = "DiskCopy42Image.cpp: 111"; - rLen = 0; - rLoc = 2053; - rType = 0; - vrLen = 925; - vrLoc = 1629; - }; - B6F366CA11B1A28C0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; - name = "UniversalDiskImage.cpp: 47"; - rLen = 0; - rLoc = 956; - rType = 0; - vrLen = 808; - vrLoc = 497; - }; - B6F366CB11B1A28C0045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; - name = "DiskImage.cpp: 30"; - rLen = 0; - rLoc = 423; - rType = 0; - vrLen = 613; - vrLoc = 128; - }; - B6F3676311B323680045E114 /* TextWriter.h */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1009, 958}}"; - sepNavSelRange = "{420, 0}"; - sepNavVisRange = "{0, 587}"; - }; - }; - B6F3676411B323680045E114 /* TextWriter.cpp */ = { - uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {838, 1352}}"; - sepNavSelRange = "{315, 0}"; - sepNavVisRange = "{0, 803}"; - }; - }; - B6F3677C11B326580045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6F365CC11B08AE30045E114 /* VolumeEntry.h */; - name = "VolumeEntry.h: 51"; - rLen = 56; - rLoc = 1259; - rType = 0; - vrLen = 1094; - vrLoc = 758; - }; - B6F3677D11B326580045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6F3651C11ADD0280045E114 /* Entry.h */; - name = "Entry.h: 72"; - rLen = 0; - rLoc = 1399; - rType = 0; - vrLen = 605; - vrLoc = 0; - }; - B6F3677E11B326580045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6F3676311B323680045E114 /* TextWriter.h */; - name = "TextWriter.h: 36"; - rLen = 0; - rLoc = 587; - rType = 0; - vrLen = 532; - vrLoc = 0; - }; - B6F367A011B330D10045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFACA11A09DAA00C90DCE /* File.h */; - name = "File.h: 21"; - rLen = 0; - rLoc = 244; - rType = 0; - vrLen = 749; - vrLoc = 0; - }; - B6F367AE11B337A70045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFCC811A366C800C90DCE /* MappedFile.h */; - name = "MappedFile.h: 17"; - rLen = 0; - rLoc = 263; - rType = 0; - vrLen = 874; - vrLoc = 0; - }; - B6F3682411B431AC0045E114 /* newfs_prodos */ = { - activeExec = 0; - executables = ( - B6F3682611B431AC0045E114 /* newfs_prodos */, - ); - }; - B6F3682611B431AC0045E114 /* newfs_prodos */ = { - isa = PBXExecutable; - activeArgIndices = ( - ); - argumentStrings = ( - ); - autoAttachOnCrash = 1; - breakpointsEnabled = 0; - configStateDict = { - }; - customDataFormattersEnabled = 1; - dataTipCustomDataFormattersEnabled = 1; - dataTipShowTypeColumn = 1; - dataTipSortType = 0; - debuggerPlugin = GDBDebugging; - disassemblyDisplayState = 0; - enableDebugStr = 1; - environmentEntries = ( - ); - executableSystemSymbolLevel = 0; - executableUserSymbolLevel = 0; - libgmallocEnabled = 0; - name = newfs_prodos; - showTypeColumn = 0; - sourceDirectories = ( - ); - }; - B6F3684A11B44D090045E114 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B6F3676411B323680045E114 /* TextWriter.cpp */; - name = "TextWriter.cpp: 17"; - rLen = 0; - rLoc = 315; - rType = 0; - vrLen = 803; - vrLoc = 0; - }; - B6F8D4AD131CB30300461B54 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; - name = "VolumeEntry.cpp: 616"; - rLen = 0; - rLoc = 13717; - rType = 0; - vrLen = 1176; - vrLoc = 13228; - }; -} diff --git a/PROFuseX.xcodeproj/kelvin.perspectivev3 b/PROFuseX.xcodeproj/kelvin.perspectivev3 deleted file mode 100644 index c7b1723..0000000 --- a/PROFuseX.xcodeproj/kelvin.perspectivev3 +++ /dev/null @@ -1,1547 +0,0 @@ - - - - - ActivePerspectiveName - Project - AllowedModules - - - BundleLoadPath - - MaxInstances - n - Module - PBXSmartGroupTreeModule - Name - Groups and Files Outline View - - - BundleLoadPath - - MaxInstances - n - Module - PBXNavigatorGroup - Name - Editor - - - BundleLoadPath - - MaxInstances - n - Module - XCTaskListModule - Name - Task List - - - BundleLoadPath - - MaxInstances - n - Module - XCDetailModule - Name - File and Smart Group Detail Viewer - - - BundleLoadPath - - MaxInstances - 1 - Module - PBXBuildResultsModule - Name - Detailed Build Results Viewer - - - BundleLoadPath - - MaxInstances - 1 - Module - PBXProjectFindModule - Name - Project Batch Find Tool - - - BundleLoadPath - - MaxInstances - n - Module - XCProjectFormatConflictsModule - Name - Project Format Conflicts List - - - BundleLoadPath - - MaxInstances - n - Module - PBXBookmarksModule - Name - Bookmarks Tool - - - BundleLoadPath - - MaxInstances - n - Module - PBXClassBrowserModule - Name - Class Browser - - - BundleLoadPath - - MaxInstances - n - Module - PBXCVSModule - Name - Source Code Control Tool - - - BundleLoadPath - - MaxInstances - n - Module - PBXDebugBreakpointsModule - Name - Debug Breakpoints Tool - - - BundleLoadPath - - MaxInstances - n - Module - XCDockableInspector - Name - Inspector - - - BundleLoadPath - - MaxInstances - n - Module - PBXOpenQuicklyModule - Name - Open Quickly Tool - - - BundleLoadPath - - MaxInstances - 1 - Module - PBXDebugSessionModule - Name - Debugger - - - BundleLoadPath - - MaxInstances - 1 - Module - PBXDebugCLIModule - Name - Debug Console - - - BundleLoadPath - - MaxInstances - n - Module - XCSnapshotModule - Name - Snapshots Tool - - - BundlePath - /Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources - Description - AIODescriptionKey - DockingSystemVisible - - Extension - perspectivev3 - FavBarConfig - - PBXProjectModuleGUID - B63EFA6611A093C200C90DCE - XCBarModuleItemNames - - XCBarModuleItems - - - FirstTimeWindowDisplayed - - Identifier - com.apple.perspectives.project.defaultV3 - MajorVersion - 34 - MinorVersion - 0 - Name - All-In-One - Notifications - - OpenEditors - - PerspectiveWidths - - 1239 - 1239 - - Perspectives - - - ChosenToolbarItems - - XCToolbarPerspectiveControl - NSToolbarSeparatorItem - active-combo-popup - action - NSToolbarFlexibleSpaceItem - debugger-enable-breakpoints - build-and-go - com.apple.ide.PBXToolbarStopButton - get-info - NSToolbarFlexibleSpaceItem - com.apple.pbx.toolbar.searchfield - - ControllerClassBaseName - - IconName - WindowOfProject - Identifier - perspective.project - IsVertical - - Layout - - - ContentConfiguration - - PBXBottomSmartGroupGIDs - - 1C37FBAC04509CD000000102 - 1C37FAAC04509CD000000102 - 1C37FABC05509CD000000102 - 1C37FABC05539CD112110102 - E2644B35053B69B200211256 - 1C37FABC04509CD000100104 - 1CC0EA4004350EF90044410B - 1CC0EA4004350EF90041110B - 1C77FABC04509CD000000102 - - PBXProjectModuleGUID - 1CA23ED40692098700951B8B - PBXProjectModuleLabel - Files - PBXProjectStructureProvided - yes - PBXSmartGroupTreeModuleColumnData - - PBXSmartGroupTreeModuleColumnWidthsKey - - 318 - - PBXSmartGroupTreeModuleColumnsKey_v4 - - MainColumn - - - PBXSmartGroupTreeModuleOutlineStateKey_v7 - - PBXSmartGroupTreeModuleOutlineStateExpansionKey - - 08FB7794FE84155DC02AAC07 - B6272A8D11D5AC3C0073C73A - B6272AA411D5AE0C0073C73A - B63EFBE711A244EE00C90DCE - B63EFACF11A09DB500C90DCE - B63EFAB511A098C400C90DCE - B63EFA9411A094E000C90DCE - B656ADED11A84D3200AB578A - 1C37FBAC04509CD000000102 - 1C37FAAC04509CD000000102 - - PBXSmartGroupTreeModuleOutlineStateSelectionKey - - - 63 - 62 - - - PBXSmartGroupTreeModuleOutlineStateVisibleRectKey - {{0, 0}, {318, 941}} - - PBXTopSmartGroupGIDs - - XCIncludePerspectivesSwitch - - - GeometryConfiguration - - Frame - {{0, 0}, {335, 959}} - GroupTreeTableConfiguration - - MainColumn - 318 - - RubberWindowFrame - 413 92 1239 1000 0 0 1920 1178 - - Module - PBXSmartGroupTreeModule - Proportion - 335pt - - - Dock - - - ContentConfiguration - - PBXProjectModuleGUID - B63EFA6111A093C200C90DCE - PBXProjectModuleLabel - VolumeEntry.cpp - PBXSplitModuleInNavigatorKey - - Split0 - - PBXProjectModuleGUID - B63EFA6211A093C200C90DCE - PBXProjectModuleLabel - VolumeEntry.cpp - _historyCapacity - 0 - bookmark - B6F8D4AD131CB30300461B54 - history - - B63EFC2611A2D5A400C90DCE - B63EFC3211A2D5A400C90DCE - B63EFDA011A4488200C90DCE - B63EFDA511A4488200C90DCE - B63EFDA711A4488200C90DCE - B63EFDA911A4488200C90DCE - B63EFDAB11A4488200C90DCE - B63EFDAD11A4488200C90DCE - B63EFDAF11A4488200C90DCE - B63EFDB111A4488200C90DCE - B63EFDB311A4488200C90DCE - B63EFDF211A4504200C90DCE - B63EFEA011A488C200C90DCE - B63EFEA111A488C200C90DCE - B63EFEA811A488C200C90DCE - B6E5F0DD11A60726000AD141 - B6E5F0F211A73144000AD141 - B6E5F11211A73340000AD141 - B6E5F13A11A74F2B000AD141 - B6E5F18211A76B74000AD141 - B656AE2611A84FA400AB578A - B6F3647111AB35FE0045E114 - B6F3649E11AB59190045E114 - B6F364B711AB84840045E114 - B6F3652E11ADD5D20045E114 - B6F3653011ADD5D20045E114 - B6F3657E11AE255B0045E114 - B6F3665411B190370045E114 - B6F3665C11B194AC0045E114 - B6F366C411B1A28C0045E114 - B6F366C611B1A28C0045E114 - B6F366C711B1A28C0045E114 - B6F366C811B1A28C0045E114 - B6F366C911B1A28C0045E114 - B6F366CA11B1A28C0045E114 - B6F366CB11B1A28C0045E114 - B6F3677C11B326580045E114 - B6F3677D11B326580045E114 - B6F3677E11B326580045E114 - B6F367A011B330D10045E114 - B6F367AE11B337A70045E114 - B6F3684A11B44D090045E114 - B65CFB6911B495790024A2D9 - B6272A9911D5AC5E0073C73A - B6272A9B11D5AC5E0073C73A - B6272A9C11D5AC5E0073C73A - B6272B0D11D691320073C73A - B6272B0E11D691320073C73A - B6272B0F11D691320073C73A - B6272B1011D691320073C73A - B6272B1111D691320073C73A - B6272B1311D691320073C73A - B6272B1411D691320073C73A - B6272B1611D691320073C73A - B6AA3AB21318D063007D4BA1 - B6AA3AB31318D063007D4BA1 - B6AA3AB41318D063007D4BA1 - B6A53B8E1319DDFC00C9070F - B6A53BC7131B400800C9070F - B6A53BC8131B400800C9070F - B6A53C34131B4CF800C9070F - - - SplitCount - 1 - - StatusBarVisibility - - XCSharingToken - com.apple.Xcode.CommonNavigatorGroupSharingToken - - GeometryConfiguration - - Frame - {{0, 0}, {899, 497}} - RubberWindowFrame - 413 92 1239 1000 0 0 1920 1178 - - Module - PBXNavigatorGroup - Proportion - 497pt - - - Proportion - 457pt - Tabs - - - BecomeActive - - ContentConfiguration - - PBXProjectModuleGUID - 1CA23EDF0692099D00951B8B - PBXProjectModuleLabel - Detail - - GeometryConfiguration - - Frame - {{10, 27}, {899, 430}} - RubberWindowFrame - 413 92 1239 1000 0 0 1920 1178 - - Module - XCDetailModule - - - ContentConfiguration - - PBXProjectModuleGUID - 1CA23EE00692099D00951B8B - PBXProjectModuleLabel - Project Find - - GeometryConfiguration - - Frame - {{10, 27}, {899, 383}} - - Module - PBXProjectFindModule - - - ContentConfiguration - - PBXCVSModuleFilterTypeKey - 1032 - PBXProjectModuleGUID - 1CA23EE10692099D00951B8B - PBXProjectModuleLabel - SCM Results - - GeometryConfiguration - - Frame - {{10, 31}, {603, 297}} - - Module - PBXCVSModule - - - ContentConfiguration - - PBXProjectModuleGUID - XCMainBuildResultsModuleGUID - PBXProjectModuleLabel - Build Results - XCBuildResultsTrigger_Collapse - 1021 - XCBuildResultsTrigger_Open - 1011 - - GeometryConfiguration - - Frame - {{10, 27}, {899, 420}} - - Module - PBXBuildResultsModule - - - - - Proportion - 899pt - - - Name - Project - ServiceClasses - - XCModuleDock - PBXSmartGroupTreeModule - XCModuleDock - PBXNavigatorGroup - XCDockableTabModule - XCDetailModule - PBXProjectFindModule - PBXCVSModule - PBXBuildResultsModule - - TableOfContents - - B6F8D48A131C605200461B54 - 1CA23ED40692098700951B8B - B6F8D48B131C605200461B54 - B63EFA6111A093C200C90DCE - B6F8D48C131C605200461B54 - 1CA23EDF0692099D00951B8B - 1CA23EE00692099D00951B8B - 1CA23EE10692099D00951B8B - XCMainBuildResultsModuleGUID - - ToolbarConfigUserDefaultsMinorVersion - 2 - ToolbarConfiguration - xcode.toolbar.config.defaultV3 - - - ChosenToolbarItems - - XCToolbarPerspectiveControl - NSToolbarSeparatorItem - active-combo-popup - NSToolbarFlexibleSpaceItem - debugger-enable-breakpoints - build-and-go - com.apple.ide.PBXToolbarStopButton - debugger-restart-executable - debugger-pause - debugger-step-over - debugger-step-into - debugger-step-out - NSToolbarFlexibleSpaceItem - servicesModulebreakpoints - debugger-show-console-window - - ControllerClassBaseName - PBXDebugSessionModule - IconName - DebugTabIcon - Identifier - perspective.debug - IsVertical - - Layout - - - ContentConfiguration - - PBXProjectModuleGUID - 1CCC7628064C1048000F2A68 - PBXProjectModuleLabel - Debugger Console - - GeometryConfiguration - - Frame - {{0, 0}, {1239, 320}} - - Module - PBXDebugCLIModule - Proportion - 320pt - - - ContentConfiguration - - Debugger - - HorizontalSplitView - - _collapsingFrameDimension - 0.0 - _indexOfCollapsedView - 0 - _percentageOfCollapsedView - 0.0 - isCollapsed - yes - sizes - - {{0, 0}, {605, 308}} - {{605, 0}, {634, 308}} - - - VerticalSplitView - - _collapsingFrameDimension - 0.0 - _indexOfCollapsedView - 0 - _percentageOfCollapsedView - 0.0 - isCollapsed - yes - sizes - - {{0, 0}, {1239, 308}} - {{0, 308}, {1239, 326}} - - - - LauncherConfigVersion - 8 - PBXProjectModuleGUID - 1CCC7629064C1048000F2A68 - PBXProjectModuleLabel - Debug - - GeometryConfiguration - - DebugConsoleVisible - None - DebugConsoleWindowFrame - {{200, 200}, {500, 300}} - DebugSTDIOWindowFrame - {{200, 200}, {500, 300}} - Frame - {{0, 325}, {1239, 634}} - PBXDebugSessionStackFrameViewKey - - DebugVariablesTableConfiguration - - Name - 193 - Value - 126 - Summary - 290 - - Frame - {{605, 0}, {634, 308}} - - - Module - PBXDebugSessionModule - Proportion - 634pt - - - Name - Debug - ServiceClasses - - XCModuleDock - PBXDebugCLIModule - PBXDebugSessionModule - PBXDebugProcessAndThreadModule - PBXDebugProcessViewModule - PBXDebugThreadViewModule - PBXDebugStackFrameViewModule - PBXNavigatorGroup - - TableOfContents - - B6A53BCB131B400800C9070F - 1CCC7628064C1048000F2A68 - 1CCC7629064C1048000F2A68 - B6A53BCC131B400800C9070F - B6A53BCD131B400800C9070F - B6A53BCE131B400800C9070F - B6A53BCF131B400800C9070F - B6A53BD0131B400800C9070F - - ToolbarConfigUserDefaultsMinorVersion - 2 - ToolbarConfiguration - xcode.toolbar.config.debugV3 - - - PerspectivesBarVisible - - ShelfIsVisible - - SourceDescription - file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecification.xcperspec' - StatusbarIsVisible - - TimeStamp - 0.0 - ToolbarConfigUserDefaultsMinorVersion - 2 - ToolbarDisplayMode - 1 - ToolbarIsVisible - - ToolbarSizeMode - 1 - Type - Perspectives - UpdateMessage - - WindowJustification - 5 - WindowOrderList - - /Users/kelvin/Projects/PROFuseX/PROFuseX.xcodeproj - - WindowString - 413 92 1239 1000 0 0 1920 1178 - WindowToolsV3 - - - Identifier - windowTool.debugger - Layout - - - Dock - - - ContentConfiguration - - Debugger - - HorizontalSplitView - - _collapsingFrameDimension - 0.0 - _indexOfCollapsedView - 0 - _percentageOfCollapsedView - 0.0 - isCollapsed - yes - sizes - - {{0, 0}, {317, 164}} - {{317, 0}, {377, 164}} - - - VerticalSplitView - - _collapsingFrameDimension - 0.0 - _indexOfCollapsedView - 0 - _percentageOfCollapsedView - 0.0 - isCollapsed - yes - sizes - - {{0, 0}, {694, 164}} - {{0, 164}, {694, 216}} - - - - LauncherConfigVersion - 8 - PBXProjectModuleGUID - 1C162984064C10D400B95A72 - PBXProjectModuleLabel - Debug - GLUTExamples (Underwater) - - GeometryConfiguration - - DebugConsoleDrawerSize - {100, 120} - DebugConsoleVisible - None - DebugConsoleWindowFrame - {{200, 200}, {500, 300}} - DebugSTDIOWindowFrame - {{200, 200}, {500, 300}} - Frame - {{0, 0}, {694, 380}} - RubberWindowFrame - 321 238 694 422 0 0 1440 878 - - Module - PBXDebugSessionModule - Proportion - 100% - - - Proportion - 100% - - - Name - Debugger - ServiceClasses - - PBXDebugSessionModule - - StatusbarIsVisible - 1 - TableOfContents - - 1CD10A99069EF8BA00B06720 - 1C0AD2AB069F1E9B00FABCE6 - 1C162984064C10D400B95A72 - 1C0AD2AC069F1E9B00FABCE6 - - ToolbarConfiguration - xcode.toolbar.config.debugV3 - WindowString - 321 238 694 422 0 0 1440 878 - WindowToolGUID - 1CD10A99069EF8BA00B06720 - WindowToolIsVisible - 0 - - - Identifier - windowTool.build - Layout - - - Dock - - - ContentConfiguration - - PBXProjectModuleGUID - 1CD0528F0623707200166675 - PBXProjectModuleLabel - <No Editor> - PBXSplitModuleInNavigatorKey - - Split0 - - PBXProjectModuleGUID - 1CD052900623707200166675 - - SplitCount - 1 - - StatusBarVisibility - 1 - - GeometryConfiguration - - Frame - {{0, 0}, {500, 215}} - RubberWindowFrame - 192 257 500 500 0 0 1280 1002 - - Module - PBXNavigatorGroup - Proportion - 218pt - - - BecomeActive - 1 - ContentConfiguration - - PBXProjectModuleGUID - XCMainBuildResultsModuleGUID - PBXProjectModuleLabel - Build Results - - GeometryConfiguration - - Frame - {{0, 222}, {500, 236}} - RubberWindowFrame - 192 257 500 500 0 0 1280 1002 - - Module - PBXBuildResultsModule - Proportion - 236pt - - - Proportion - 458pt - - - Name - Build Results - ServiceClasses - - PBXBuildResultsModule - - StatusbarIsVisible - 1 - TableOfContents - - 1C78EAA5065D492600B07095 - 1C78EAA6065D492600B07095 - 1CD0528F0623707200166675 - XCMainBuildResultsModuleGUID - - ToolbarConfiguration - xcode.toolbar.config.buildV3 - WindowString - 192 257 500 500 0 0 1280 1002 - - - Identifier - windowTool.find - Layout - - - Dock - - - Dock - - - ContentConfiguration - - PBXProjectModuleGUID - 1CDD528C0622207200134675 - PBXProjectModuleLabel - <No Editor> - PBXSplitModuleInNavigatorKey - - Split0 - - PBXProjectModuleGUID - 1CD0528D0623707200166675 - - SplitCount - 1 - - StatusBarVisibility - 1 - - GeometryConfiguration - - Frame - {{0, 0}, {781, 167}} - RubberWindowFrame - 62 385 781 470 0 0 1440 878 - - Module - PBXNavigatorGroup - Proportion - 781pt - - - Proportion - 50% - - - BecomeActive - 1 - ContentConfiguration - - PBXProjectModuleGUID - 1CD0528E0623707200166675 - PBXProjectModuleLabel - Project Find - - GeometryConfiguration - - Frame - {{8, 0}, {773, 254}} - RubberWindowFrame - 62 385 781 470 0 0 1440 878 - - Module - PBXProjectFindModule - Proportion - 50% - - - Proportion - 428pt - - - Name - Project Find - ServiceClasses - - PBXProjectFindModule - - StatusbarIsVisible - 1 - TableOfContents - - 1C530D57069F1CE1000CFCEE - 1C530D58069F1CE1000CFCEE - 1C530D59069F1CE1000CFCEE - 1CDD528C0622207200134675 - 1C530D5A069F1CE1000CFCEE - 1CE0B1FE06471DED0097A5F4 - 1CD0528E0623707200166675 - - WindowString - 62 385 781 470 0 0 1440 878 - WindowToolGUID - 1C530D57069F1CE1000CFCEE - WindowToolIsVisible - 0 - - - Identifier - windowTool.snapshots - Layout - - - Dock - - - Module - XCSnapshotModule - Proportion - 100% - - - Proportion - 100% - - - Name - Snapshots - ServiceClasses - - XCSnapshotModule - - StatusbarIsVisible - Yes - ToolbarConfiguration - xcode.toolbar.config.snapshots - WindowString - 315 824 300 550 0 0 1440 878 - WindowToolIsVisible - Yes - - - FirstTimeWindowDisplayed - - Identifier - windowTool.debuggerConsole - IsVertical - - Layout - - - Dock - - - ContentConfiguration - - PBXProjectModuleGUID - 1C78EAAC065D492600B07095 - PBXProjectModuleLabel - Debugger Console - - GeometryConfiguration - - Frame - {{0, 0}, {440, 359}} - RubberWindowFrame - 98 717 440 400 0 0 1920 1178 - - Module - PBXDebugCLIModule - Proportion - 359pt - - - Proportion - 359pt - - - Name - Debugger Console - ServiceClasses - - PBXDebugCLIModule - - StatusbarIsVisible - - TableOfContents - - 1C530D5B069F1CE1000CFCEE - B656AF7911AA19CD00AB578A - 1C78EAAC065D492600B07095 - - ToolbarConfiguration - xcode.toolbar.config.consoleV3 - WindowString - 98 717 440 400 0 0 1920 1178 - WindowToolGUID - 1C530D5B069F1CE1000CFCEE - WindowToolIsVisible - - - - Identifier - windowTool.scm - Layout - - - Dock - - - ContentConfiguration - - PBXProjectModuleGUID - 1C78EAB2065D492600B07095 - PBXProjectModuleLabel - <No Editor> - PBXSplitModuleInNavigatorKey - - Split0 - - PBXProjectModuleGUID - 1C78EAB3065D492600B07095 - - SplitCount - 1 - - StatusBarVisibility - 1 - - GeometryConfiguration - - Frame - {{0, 0}, {452, 0}} - RubberWindowFrame - 743 379 452 308 0 0 1280 1002 - - Module - PBXNavigatorGroup - Proportion - 0pt - - - BecomeActive - 1 - ContentConfiguration - - PBXProjectModuleGUID - 1CD052920623707200166675 - PBXProjectModuleLabel - SCM - - GeometryConfiguration - - ConsoleFrame - {{0, 259}, {452, 0}} - Frame - {{0, 7}, {452, 259}} - RubberWindowFrame - 743 379 452 308 0 0 1280 1002 - TableConfiguration - - Status - 30 - FileName - 199 - Path - 197.09500122070312 - - TableFrame - {{0, 0}, {452, 250}} - - Module - PBXCVSModule - Proportion - 262pt - - - Proportion - 266pt - - - Name - SCM - ServiceClasses - - PBXCVSModule - - StatusbarIsVisible - 1 - TableOfContents - - 1C78EAB4065D492600B07095 - 1C78EAB5065D492600B07095 - 1C78EAB2065D492600B07095 - 1CD052920623707200166675 - - ToolbarConfiguration - xcode.toolbar.config.scmV3 - WindowString - 743 379 452 308 0 0 1280 1002 - - - FirstTimeWindowDisplayed - - Identifier - windowTool.breakpoints - IsVertical - - Layout - - - Dock - - - ContentConfiguration - - PBXBottomSmartGroupGIDs - - 1C77FABC04509CD000000102 - - PBXProjectModuleGUID - 1CE0B1FE06471DED0097A5F4 - PBXProjectModuleLabel - Files - PBXProjectStructureProvided - no - PBXSmartGroupTreeModuleColumnData - - PBXSmartGroupTreeModuleColumnWidthsKey - - 168 - - PBXSmartGroupTreeModuleColumnsKey_v4 - - MainColumn - - - PBXSmartGroupTreeModuleOutlineStateKey_v7 - - PBXSmartGroupTreeModuleOutlineStateExpansionKey - - 1C77FABC04509CD000000102 - - PBXSmartGroupTreeModuleOutlineStateSelectionKey - - - 0 - - - PBXSmartGroupTreeModuleOutlineStateVisibleRectKey - {{0, 0}, {168, 350}} - - PBXTopSmartGroupGIDs - - XCIncludePerspectivesSwitch - - - GeometryConfiguration - - Frame - {{0, 0}, {185, 368}} - GroupTreeTableConfiguration - - MainColumn - 168 - - RubberWindowFrame - 215 685 744 409 0 0 1920 1178 - - Module - PBXSmartGroupTreeModule - Proportion - 185pt - - - BecomeActive - - ContentConfiguration - - PBXProjectModuleGUID - 1CA1AED706398EBD00589147 - PBXProjectModuleLabel - Detail - - GeometryConfiguration - - Frame - {{190, 0}, {554, 368}} - RubberWindowFrame - 215 685 744 409 0 0 1920 1178 - - Module - XCDetailModule - Proportion - 554pt - - - Proportion - 368pt - - - MajorVersion - 3 - MinorVersion - 0 - Name - Breakpoints - ServiceClasses - - PBXSmartGroupTreeModule - XCDetailModule - - StatusbarIsVisible - - TableOfContents - - B656AF4511AA12DA00AB578A - B656AF4611AA12DA00AB578A - 1CE0B1FE06471DED0097A5F4 - 1CA1AED706398EBD00589147 - - ToolbarConfiguration - xcode.toolbar.config.breakpointsV3 - WindowString - 215 685 744 409 0 0 1920 1178 - WindowToolGUID - B656AF4511AA12DA00AB578A - WindowToolIsVisible - - - - Identifier - windowTool.debugAnimator - Layout - - - Dock - - - Module - PBXNavigatorGroup - Proportion - 100% - - - Proportion - 100% - - - Name - Debug Visualizer - ServiceClasses - - PBXNavigatorGroup - - StatusbarIsVisible - 1 - ToolbarConfiguration - xcode.toolbar.config.debugAnimatorV3 - WindowString - 100 100 700 500 0 0 1280 1002 - - - Identifier - windowTool.bookmarks - Layout - - - Dock - - - Module - PBXBookmarksModule - Proportion - 166pt - - - Proportion - 166pt - - - Name - Bookmarks - ServiceClasses - - PBXBookmarksModule - - StatusbarIsVisible - 0 - WindowString - 538 42 401 187 0 0 1280 1002 - - - Identifier - windowTool.projectFormatConflicts - Layout - - - Dock - - - Module - XCProjectFormatConflictsModule - Proportion - 100% - - - Proportion - 100% - - - Name - Project Format Conflicts - ServiceClasses - - XCProjectFormatConflictsModule - - StatusbarIsVisible - 0 - WindowContentMinSize - 450 300 - WindowString - 50 850 472 307 0 0 1440 877 - - - Identifier - windowTool.classBrowser - Layout - - - Dock - - - BecomeActive - 1 - ContentConfiguration - - OptionsSetName - Hierarchy, all classes - PBXProjectModuleGUID - 1CA6456E063B45B4001379D8 - PBXProjectModuleLabel - Class Browser - NSObject - - GeometryConfiguration - - ClassesFrame - {{0, 0}, {369, 96}} - ClassesTreeTableConfiguration - - PBXClassNameColumnIdentifier - 208 - PBXClassBookColumnIdentifier - 22 - - Frame - {{0, 0}, {616, 353}} - MembersFrame - {{0, 105}, {369, 395}} - MembersTreeTableConfiguration - - PBXMemberTypeIconColumnIdentifier - 22 - PBXMemberNameColumnIdentifier - 216 - PBXMemberTypeColumnIdentifier - 94 - PBXMemberBookColumnIdentifier - 22 - - PBXModuleWindowStatusBarHidden2 - 1 - RubberWindowFrame - 597 125 616 374 0 0 1280 1002 - - Module - PBXClassBrowserModule - Proportion - 354pt - - - Proportion - 354pt - - - Name - Class Browser - ServiceClasses - - PBXClassBrowserModule - - StatusbarIsVisible - 0 - TableOfContents - - 1C78EABA065D492600B07095 - 1C78EABB065D492600B07095 - 1CA6456E063B45B4001379D8 - - ToolbarConfiguration - xcode.toolbar.config.classbrowser - WindowString - 597 125 616 374 0 0 1280 1002 - - - Identifier - windowTool.refactoring - IncludeInToolsMenu - 0 - Layout - - - Dock - - - BecomeActive - 1 - GeometryConfiguration - - Frame - {0, 0}, {500, 335} - RubberWindowFrame - {0, 0}, {500, 335} - - Module - XCRefactoringModule - Proportion - 100% - - - Proportion - 100% - - - Name - Refactoring - ServiceClasses - - XCRefactoringModule - - WindowString - 200 200 500 356 0 0 1920 1200 - - - - diff --git a/PROFuseX.xcodeproj/project.pbxproj b/PROFuseX.xcodeproj/project.pbxproj deleted file mode 100644 index 7d1f572..0000000 --- a/PROFuseX.xcodeproj/project.pbxproj +++ /dev/null @@ -1,1482 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 45; - objects = { - -/* Begin PBXBuildFile section */ - B6272A9311D5AC440073C73A /* apfm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A8E11D5AC3C0073C73A /* apfm.cpp */; }; - B6272A9411D5AC4C0073C73A /* fuse_pascal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */; }; - B6272A9511D5AC530073C73A /* fuse_pascal_ops.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */; }; - B6272A9611D5AC560073C73A /* newfs_pascal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */; }; - B6272A9711D5AC5B0073C73A /* xattr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A9211D5AC3C0073C73A /* xattr.cpp */; }; - B6272AAA11D5AE0C0073C73A /* Bitmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272AA511D5AE0C0073C73A /* Bitmap.cpp */; }; - B6272AAB11D5AE0C0073C73A /* DateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272AA711D5AE0C0073C73A /* DateTime.cpp */; }; - B63EFCD211A36C8B00C90DCE /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; - B63EFCD311A36C8B00C90DCE /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; - B63EFCD411A36C8B00C90DCE /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; - B63EFCD511A36C8B00C90DCE /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; - B63EFCD611A36C8B00C90DCE /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; - B63EFCD711A36C8B00C90DCE /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; - B63EFCD811A36C8B00C90DCE /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; - B63EFCD911A36C8B00C90DCE /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; - B63EFCDA11A36C8B00C90DCE /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; - B63EFCDB11A36C8B00C90DCE /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; - B63EFCDC11A36C8B00C90DCE /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; - B63EFCDD11A36C8B00C90DCE /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; - B63EFCE011A36C8B00C90DCE /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; - B63EFCE111A36C8B00C90DCE /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; }; - B63EFCE211A36C8B00C90DCE /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; - B63EFCE311A36C8B00C90DCE /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; - B63EFCE511A36C8B00C90DCE /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; - B63EFE8511A4888500C90DCE /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; - B63EFE8611A4888500C90DCE /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; - B63EFE8711A4888500C90DCE /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; - B63EFE8811A4888500C90DCE /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; - B63EFE8911A4888500C90DCE /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; - B63EFE8A11A4888500C90DCE /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; - B63EFE8B11A4888500C90DCE /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; - B63EFE8C11A4888500C90DCE /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; - B63EFE8D11A4888500C90DCE /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; - B63EFE8E11A4888500C90DCE /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; - B63EFE8F11A4888500C90DCE /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; - B63EFE9011A4888500C90DCE /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; - B63EFE9311A4888500C90DCE /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; - B63EFE9411A4888500C90DCE /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; }; - B63EFE9511A4888500C90DCE /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; - B63EFE9611A4888500C90DCE /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; - B63EFE9711A4888500C90DCE /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; - B650901B1332FE5000FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090181332FE5000FBA318 /* Exception.cpp */; }; - B650901D1332FE5000FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090181332FE5000FBA318 /* Exception.cpp */; }; - B650901E1332FE5000FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090181332FE5000FBA318 /* Exception.cpp */; }; - B65090271332FE6A00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090241332FE6A00FBA318 /* Exception.cpp */; }; - B65090281332FE6A00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090241332FE6A00FBA318 /* Exception.cpp */; }; - B65090291332FE6A00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090241332FE6A00FBA318 /* Exception.cpp */; }; - B650902A1332FE6A00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090241332FE6A00FBA318 /* Exception.cpp */; }; - B65090311332FE8B00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650902F1332FE8B00FBA318 /* Exception.cpp */; }; - B65090321332FE8B00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650902F1332FE8B00FBA318 /* Exception.cpp */; }; - B65090331332FE8B00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650902F1332FE8B00FBA318 /* Exception.cpp */; }; - B65090341332FE8B00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650902F1332FE8B00FBA318 /* Exception.cpp */; }; - B650903F1332FEBE00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090371332FEBE00FBA318 /* Exception.cpp */; }; - B65090401332FEBE00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090371332FEBE00FBA318 /* Exception.cpp */; }; - B65090411332FEBE00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090371332FEBE00FBA318 /* Exception.cpp */; }; - B65090421332FEBE00FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090371332FEBE00FBA318 /* Exception.cpp */; }; - B65090471332FEBE00FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; - B65090481332FEBE00FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; - B65090491332FEBE00FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; - B650904A1332FEBE00FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; - B650908C133304C800FBA318 /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; - B650908D133304C800FBA318 /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; - B650908E133304C800FBA318 /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; - B650908F133304C800FBA318 /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; - B6509090133304C800FBA318 /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; - B6509091133304C800FBA318 /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; - B6509092133304C800FBA318 /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; - B6509093133304C800FBA318 /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; - B6509094133304C800FBA318 /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; - B6509095133304C800FBA318 /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; - B6509096133304C800FBA318 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; - B6509097133304C800FBA318 /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; - B6509098133304C800FBA318 /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; - B6509099133304C800FBA318 /* SDKImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6A591261329C417007B0EE2 /* SDKImage.cpp */; }; - B650909A133304C800FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090181332FE5000FBA318 /* Exception.cpp */; }; - B650909B133304C800FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090241332FE6A00FBA318 /* Exception.cpp */; }; - B650909C133304C800FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650902F1332FE8B00FBA318 /* Exception.cpp */; }; - B650909D133304C800FBA318 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65090371332FEBE00FBA318 /* Exception.cpp */; }; - B650909E133304C800FBA318 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650903A1332FEBE00FBA318 /* Lock.cpp */; }; - B650909F133304C800FBA318 /* DateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272AA711D5AE0C0073C73A /* DateTime.cpp */; }; - B65090A0133304C800FBA318 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509078133300BA00FBA318 /* File.cpp */; }; - B65090A1133304C800FBA318 /* Disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509079133300BA00FBA318 /* Disk.cpp */; }; - B65090A2133304C800FBA318 /* profuse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B650907F133300DD00FBA318 /* profuse.cpp */; }; - B65090A3133304C800FBA318 /* profuse_xattr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509081133300FB00FBA318 /* profuse_xattr.cpp */; }; - B65090A4133304C800FBA318 /* profuse_stat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509082133300FB00FBA318 /* profuse_stat.cpp */; }; - B65090A5133304C800FBA318 /* profuse_file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509083133300FB00FBA318 /* profuse_file.cpp */; }; - B65090A6133304C800FBA318 /* profuse_dirent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509084133300FB00FBA318 /* profuse_dirent.cpp */; }; - B65090A8133304C800FBA318 /* libfuse_ino64.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */; }; - B65090A9133304C800FBA318 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EC132995D4007B0EE2 /* Carbon.framework */; }; - B65090AA133304C800FBA318 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EE132995D4007B0EE2 /* libz.dylib */; }; - B65090AB133304C800FBA318 /* libNuFX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590F713299626007B0EE2 /* libNuFX.a */; }; - B656AE0811A84F6C00AB578A /* libfuse_ino64.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */; }; - B656AE0911A84F7700AB578A /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; - B656AE0A11A84F7700AB578A /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; - B656AE0B11A84F7700AB578A /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; - B656AE0C11A84F7700AB578A /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; - B656AE0D11A84F7700AB578A /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; - B656AE0E11A84F7700AB578A /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; - B656AE0F11A84F7700AB578A /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; - B656AE1011A84F7700AB578A /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; - B656AE1111A84F7700AB578A /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; - B656AE1211A84F7700AB578A /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; - B656AE1311A84F7700AB578A /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; - B656AE1411A84F7700AB578A /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; - B656AE1711A84F7700AB578A /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; - B656AE1811A84F7700AB578A /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; }; - B656AE1911A84F7700AB578A /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; - B656AE1A11A84F7700AB578A /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; - B656AE1B11A84F7700AB578A /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; - B656AF0811AA106400AB578A /* NibbleTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */; }; - B656AF0911AA106C00AB578A /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; - B656AF0A11AA106C00AB578A /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; - B656AF0B11AA106C00AB578A /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; - B656AF0C11AA106C00AB578A /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; - B656AF0D11AA106C00AB578A /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; - B656AF0E11AA106C00AB578A /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; - B656AF0F11AA106C00AB578A /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; - B656AF1011AA106C00AB578A /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; - B656AF1111AA106C00AB578A /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; - B656AF1211AA106C00AB578A /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; - B656AF1311AA106C00AB578A /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; - B656AF1411AA106C00AB578A /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; - B656AF1711AA106C00AB578A /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; - B656AF1811AA106C00AB578A /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBE811A244EE00C90DCE /* Date.cpp */; }; - B656AF1911AA106C00AB578A /* Entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEA11A244EE00C90DCE /* Entry.cpp */; }; - B656AF1A11AA106C00AB578A /* FileEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */; }; - B656AF1B11AA106C00AB578A /* VolumeEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */; }; - B6A590EF132995D4007B0EE2 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EC132995D4007B0EE2 /* Carbon.framework */; }; - B6A590F0132995D4007B0EE2 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EC132995D4007B0EE2 /* Carbon.framework */; }; - B6A590F3132995D5007B0EE2 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EE132995D4007B0EE2 /* libz.dylib */; }; - B6A590F4132995D5007B0EE2 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EE132995D4007B0EE2 /* libz.dylib */; }; - B6A590F813299626007B0EE2 /* libNuFX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590F713299626007B0EE2 /* libNuFX.a */; }; - B6A590F913299626007B0EE2 /* libNuFX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590F713299626007B0EE2 /* libNuFX.a */; }; - B6A591281329C417007B0EE2 /* SDKImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6A591261329C417007B0EE2 /* SDKImage.cpp */; }; - B6A591291329C417007B0EE2 /* SDKImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6A591261329C417007B0EE2 /* SDKImage.cpp */; }; - B6F3676511B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; - B6F3676611B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; - B6F3676711B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; - B6F3676811B323680045E114 /* TextWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6F3676411B323680045E114 /* TextWriter.cpp */; }; - B6F3682A11B431CC0045E114 /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; - B6F3682B11B431CC0045E114 /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; - B6F3682C11B431CC0045E114 /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; - B6F3682D11B431CC0045E114 /* DiskCopy42Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */; }; - B6F3682E11B431CC0045E114 /* DiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9D11A094E000C90DCE /* DiskImage.cpp */; }; - B6F3682F11B431CC0045E114 /* RawDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA111A094E000C90DCE /* RawDevice.cpp */; }; - B6F3683011B431CC0045E114 /* UniversalDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */; }; - B6F3683111B431CC0045E114 /* BlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB611A098C400C90DCE /* BlockCache.cpp */; }; - B6F3683211B431CC0045E114 /* ConcreteBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */; }; - B6F3683311B431CC0045E114 /* MappedBlockCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */; }; - B6F3683411B431CC0045E114 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFAC911A09DAA00C90DCE /* File.cpp */; }; - B6F3683511B431CC0045E114 /* MappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */; }; - B6F3683811B431CC0045E114 /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - B6272A8E11D5AC3C0073C73A /* apfm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = apfm.cpp; sourceTree = ""; }; - B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fuse_pascal.cpp; sourceTree = ""; }; - B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fuse_pascal_ops.cpp; sourceTree = ""; }; - B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = newfs_pascal.cpp; sourceTree = ""; }; - B6272A9211D5AC3C0073C73A /* xattr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xattr.cpp; sourceTree = ""; }; - B6272AA211D5AC840073C73A /* newfs_prodos.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = newfs_prodos.cpp; sourceTree = ""; }; - B6272AA511D5AE0C0073C73A /* Bitmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Bitmap.cpp; sourceTree = ""; }; - B6272AA611D5AE0C0073C73A /* Bitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bitmap.h; sourceTree = ""; }; - B6272AA711D5AE0C0073C73A /* DateTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DateTime.cpp; sourceTree = ""; }; - B6272AA811D5AE0C0073C73A /* DateTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DateTime.h; sourceTree = ""; }; - B63EFA7511A0948500C90DCE /* Endian.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Endian.cpp; sourceTree = ""; }; - B63EFA7611A0948500C90DCE /* Endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Endian.h; sourceTree = ""; }; - B63EFA7711A0948500C90DCE /* IOBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOBuffer.h; sourceTree = ""; }; - B63EFA9511A094E000C90DCE /* BlockDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BlockDevice.cpp; sourceTree = ""; }; - B63EFA9611A094E000C90DCE /* BlockDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockDevice.h; sourceTree = ""; }; - B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DavexDiskImage.cpp; sourceTree = ""; }; - B63EFA9811A094E000C90DCE /* DavexDiskImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DavexDiskImage.h; sourceTree = ""; }; - B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DiskCopy42Image.cpp; sourceTree = ""; }; - B63EFA9C11A094E000C90DCE /* DiskCopy42Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiskCopy42Image.h; sourceTree = ""; }; - B63EFA9D11A094E000C90DCE /* DiskImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DiskImage.cpp; sourceTree = ""; }; - B63EFA9E11A094E000C90DCE /* DiskImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiskImage.h; sourceTree = ""; }; - B63EFAA111A094E000C90DCE /* RawDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RawDevice.cpp; sourceTree = ""; }; - B63EFAA211A094E000C90DCE /* RawDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RawDevice.h; sourceTree = ""; }; - B63EFAA311A094E000C90DCE /* TrackSector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackSector.h; sourceTree = ""; }; - B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UniversalDiskImage.cpp; sourceTree = ""; }; - B63EFAA511A094E000C90DCE /* UniversalDiskImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UniversalDiskImage.h; sourceTree = ""; }; - B63EFAB611A098C400C90DCE /* BlockCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BlockCache.cpp; sourceTree = ""; }; - B63EFAB711A098C400C90DCE /* BlockCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockCache.h; sourceTree = ""; }; - B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConcreteBlockCache.cpp; sourceTree = ""; }; - B63EFAB911A098C400C90DCE /* ConcreteBlockCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConcreteBlockCache.h; sourceTree = ""; }; - B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MappedBlockCache.cpp; sourceTree = ""; }; - B63EFABB11A098C400C90DCE /* MappedBlockCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MappedBlockCache.h; sourceTree = ""; }; - B63EFAC911A09DAA00C90DCE /* File.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = File.cpp; sourceTree = ""; }; - B63EFACA11A09DAA00C90DCE /* File.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = File.h; sourceTree = ""; }; - B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MappedFile.cpp; sourceTree = ""; }; - B63EFACC11A09DAA00C90DCE /* MappedFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MappedFile.h; sourceTree = ""; }; - B63EFB0611A0AC4800C90DCE /* Adaptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Adaptor.h; sourceTree = ""; }; - B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Adaptor.cpp; sourceTree = ""; }; - B63EFBE811A244EE00C90DCE /* Date.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Date.cpp; sourceTree = ""; }; - B63EFBE911A244EE00C90DCE /* Date.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Date.h; sourceTree = ""; }; - B63EFBEA11A244EE00C90DCE /* Entry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Entry.cpp; sourceTree = ""; }; - B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileEntry.cpp; sourceTree = ""; }; - B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = VolumeEntry.cpp; sourceTree = ""; }; - B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOBuffer.cpp.h; sourceTree = ""; }; - B63EFCCE11A36C7300C90DCE /* apfm */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = apfm; sourceTree = BUILT_PRODUCTS_DIR; }; - B63EFE8111A4886C00C90DCE /* newfs_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = newfs_pascal; sourceTree = BUILT_PRODUCTS_DIR; }; - B65090181332FE5000FBA318 /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = ""; }; - B65090191332FE5000FBA318 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; - B65090241332FE6A00FBA318 /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = ""; }; - B65090251332FE6A00FBA318 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; - B650902F1332FE8B00FBA318 /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = ""; }; - B65090301332FE8B00FBA318 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; - B65090361332FEBE00FBA318 /* auto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = auto.h; sourceTree = ""; }; - B65090371332FEBE00FBA318 /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = ""; }; - B65090381332FEBE00FBA318 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; - B650903A1332FEBE00FBA318 /* Lock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Lock.cpp; sourceTree = ""; }; - B650903B1332FEBE00FBA318 /* Lock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Lock.h; sourceTree = ""; }; - B650903D1332FEBE00FBA318 /* smart_pointers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = smart_pointers.h; sourceTree = ""; }; - B650903E1332FEBE00FBA318 /* unordered_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unordered_map.h; sourceTree = ""; }; - B6509078133300BA00FBA318 /* File.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = File.cpp; sourceTree = ""; }; - B6509079133300BA00FBA318 /* Disk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Disk.cpp; sourceTree = ""; }; - B650907A133300BA00FBA318 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; }; - B650907B133300BA00FBA318 /* Disk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Disk.h; sourceTree = ""; }; - B650907C133300BA00FBA318 /* File.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = File.h; sourceTree = ""; }; - B650907F133300DD00FBA318 /* profuse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse.cpp; sourceTree = ""; }; - B6509081133300FB00FBA318 /* profuse_xattr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_xattr.cpp; sourceTree = ""; }; - B6509082133300FB00FBA318 /* profuse_stat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_stat.cpp; sourceTree = ""; }; - B6509083133300FB00FBA318 /* profuse_file.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_file.cpp; sourceTree = ""; }; - B6509084133300FB00FBA318 /* profuse_dirent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_dirent.cpp; sourceTree = ""; }; - B6509085133300FB00FBA318 /* profuse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = profuse.h; sourceTree = ""; }; - B65090B1133304C800FBA318 /* profuse */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = profuse; sourceTree = BUILT_PRODUCTS_DIR; }; - B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libfuse_ino64.dylib; path = /usr/local/lib/libfuse_ino64.dylib; sourceTree = ""; }; - B656AE0311A84F5800AB578A /* fuse_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fuse_pascal; sourceTree = BUILT_PRODUCTS_DIR; }; - B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NibbleTest.cpp; sourceTree = ""; }; - B656AF0311AA105500AB578A /* NibbleTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NibbleTest; sourceTree = BUILT_PRODUCTS_DIR; }; - B659C142131368BA0058DC9C /* Device.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Device.h; sourceTree = ""; }; - B6A590EC132995D4007B0EE2 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = ../../../../System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; - B6A590EE132995D4007B0EE2 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = ../../../../usr/lib/libz.dylib; sourceTree = ""; }; - B6A590F713299626007B0EE2 /* libNuFX.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libNuFX.a; sourceTree = ""; }; - B6A591261329C417007B0EE2 /* SDKImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SDKImage.cpp; sourceTree = ""; }; - B6A591271329C417007B0EE2 /* SDKImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDKImage.h; sourceTree = ""; }; - B6F3648011AB36260045E114 /* xattr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xattr; sourceTree = BUILT_PRODUCTS_DIR; }; - B6F3651A11ADD0280045E114 /* VolumeEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VolumeEntry.h; sourceTree = ""; }; - B6F3651B11ADD0280045E114 /* FileEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileEntry.h; sourceTree = ""; }; - B6F3651C11ADD0280045E114 /* Entry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Entry.h; sourceTree = ""; }; - B6F3652711ADD52B0045E114 /* Pascal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Pascal.h; sourceTree = ""; }; - B6F3676311B323680045E114 /* TextWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextWriter.h; sourceTree = ""; }; - B6F3676411B323680045E114 /* TextWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextWriter.cpp; sourceTree = ""; }; - B6F3682511B431AC0045E114 /* newfs_prodos */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = newfs_prodos; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - B63EFCCC11A36C7300C90DCE /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - B6A590EF132995D4007B0EE2 /* Carbon.framework in Frameworks */, - B6A590F3132995D5007B0EE2 /* libz.dylib in Frameworks */, - B6A590F813299626007B0EE2 /* libNuFX.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B63EFE7F11A4886C00C90DCE /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B65090A7133304C800FBA318 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - B65090A8133304C800FBA318 /* libfuse_ino64.dylib in Frameworks */, - B65090A9133304C800FBA318 /* Carbon.framework in Frameworks */, - B65090AA133304C800FBA318 /* libz.dylib in Frameworks */, - B65090AB133304C800FBA318 /* libNuFX.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B656AE0111A84F5800AB578A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - B656AE0811A84F6C00AB578A /* libfuse_ino64.dylib in Frameworks */, - B6A590F0132995D4007B0EE2 /* Carbon.framework in Frameworks */, - B6A590F4132995D5007B0EE2 /* libz.dylib in Frameworks */, - B6A590F913299626007B0EE2 /* libNuFX.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B656AF0111AA105500AB578A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B6F3647E11AB36260045E114 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B6F3682311B431AC0045E114 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 08FB7794FE84155DC02AAC07 /* PROFuseX */ = { - isa = PBXGroup; - children = ( - B6272A8D11D5AC3C0073C73A /* bin */, - B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */, - B6272AA411D5AE0C0073C73A /* ProDOS */, - B63EFBE711A244EE00C90DCE /* Pascal */, - B63EFAC811A09DAA00C90DCE /* File */, - B63EFAB511A098C400C90DCE /* Cache */, - B63EFA9411A094E000C90DCE /* Device */, - B63EFA7411A0948500C90DCE /* Endian */, - B65090351332FEBE00FBA318 /* Common */, - B65090171332FE5000FBA318 /* NuFX */, - B65090231332FE6A00FBA318 /* POSIX */, - 1AB674ADFE9D54B511CA2CBB /* Products */, - B656ADED11A84D3200AB578A /* Libraries */, - ); - name = PROFuseX; - sourceTree = ""; - }; - 1AB674ADFE9D54B511CA2CBB /* Products */ = { - isa = PBXGroup; - children = ( - B63EFCCE11A36C7300C90DCE /* apfm */, - B63EFE8111A4886C00C90DCE /* newfs_pascal */, - B656AE0311A84F5800AB578A /* fuse_pascal */, - B656AF0311AA105500AB578A /* NibbleTest */, - B6F3648011AB36260045E114 /* xattr */, - B6F3682511B431AC0045E114 /* newfs_prodos */, - B65090B1133304C800FBA318 /* profuse */, - ); - name = Products; - sourceTree = ""; - }; - B6272A8D11D5AC3C0073C73A /* bin */ = { - isa = PBXGroup; - children = ( - B6509081133300FB00FBA318 /* profuse_xattr.cpp */, - B6509082133300FB00FBA318 /* profuse_stat.cpp */, - B6509083133300FB00FBA318 /* profuse_file.cpp */, - B6509084133300FB00FBA318 /* profuse_dirent.cpp */, - B6509085133300FB00FBA318 /* profuse.h */, - B650907F133300DD00FBA318 /* profuse.cpp */, - B6272A8E11D5AC3C0073C73A /* apfm.cpp */, - B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */, - B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */, - B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */, - B6272AA211D5AC840073C73A /* newfs_prodos.cpp */, - B6272A9211D5AC3C0073C73A /* xattr.cpp */, - ); - path = bin; - sourceTree = ""; - }; - B6272AA411D5AE0C0073C73A /* ProDOS */ = { - isa = PBXGroup; - children = ( - B6509078133300BA00FBA318 /* File.cpp */, - B6509079133300BA00FBA318 /* Disk.cpp */, - B650907A133300BA00FBA318 /* common.h */, - B650907B133300BA00FBA318 /* Disk.h */, - B650907C133300BA00FBA318 /* File.h */, - B650902F1332FE8B00FBA318 /* Exception.cpp */, - B65090301332FE8B00FBA318 /* Exception.h */, - B6272AA511D5AE0C0073C73A /* Bitmap.cpp */, - B6272AA611D5AE0C0073C73A /* Bitmap.h */, - B6272AA711D5AE0C0073C73A /* DateTime.cpp */, - B6272AA811D5AE0C0073C73A /* DateTime.h */, - ); - path = ProDOS; - sourceTree = ""; - }; - B63EFA7411A0948500C90DCE /* Endian */ = { - isa = PBXGroup; - children = ( - B63EFA7511A0948500C90DCE /* Endian.cpp */, - B63EFA7611A0948500C90DCE /* Endian.h */, - B63EFA7711A0948500C90DCE /* IOBuffer.h */, - B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */, - ); - path = Endian; - sourceTree = ""; - }; - B63EFA9411A094E000C90DCE /* Device */ = { - isa = PBXGroup; - children = ( - B659C142131368BA0058DC9C /* Device.h */, - B63EFA9511A094E000C90DCE /* BlockDevice.cpp */, - B63EFA9611A094E000C90DCE /* BlockDevice.h */, - B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */, - B63EFA9811A094E000C90DCE /* DavexDiskImage.h */, - B63EFA9B11A094E000C90DCE /* DiskCopy42Image.cpp */, - B63EFA9C11A094E000C90DCE /* DiskCopy42Image.h */, - B63EFA9D11A094E000C90DCE /* DiskImage.cpp */, - B63EFA9E11A094E000C90DCE /* DiskImage.h */, - B63EFAA111A094E000C90DCE /* RawDevice.cpp */, - B63EFAA211A094E000C90DCE /* RawDevice.h */, - B63EFAA311A094E000C90DCE /* TrackSector.h */, - B63EFAA411A094E000C90DCE /* UniversalDiskImage.cpp */, - B63EFAA511A094E000C90DCE /* UniversalDiskImage.h */, - B63EFB0611A0AC4800C90DCE /* Adaptor.h */, - B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */, - B6A591261329C417007B0EE2 /* SDKImage.cpp */, - B6A591271329C417007B0EE2 /* SDKImage.h */, - ); - path = Device; - sourceTree = ""; - }; - B63EFAB511A098C400C90DCE /* Cache */ = { - isa = PBXGroup; - children = ( - B63EFAB611A098C400C90DCE /* BlockCache.cpp */, - B63EFAB711A098C400C90DCE /* BlockCache.h */, - B63EFAB811A098C400C90DCE /* ConcreteBlockCache.cpp */, - B63EFAB911A098C400C90DCE /* ConcreteBlockCache.h */, - B63EFABA11A098C400C90DCE /* MappedBlockCache.cpp */, - B63EFABB11A098C400C90DCE /* MappedBlockCache.h */, - ); - path = Cache; - sourceTree = ""; - }; - B63EFAC811A09DAA00C90DCE /* File */ = { - isa = PBXGroup; - children = ( - B63EFAC911A09DAA00C90DCE /* File.cpp */, - B63EFACA11A09DAA00C90DCE /* File.h */, - B63EFACB11A09DAA00C90DCE /* MappedFile.cpp */, - B63EFACC11A09DAA00C90DCE /* MappedFile.h */, - ); - path = File; - sourceTree = ""; - }; - B63EFBE711A244EE00C90DCE /* Pascal */ = { - isa = PBXGroup; - children = ( - B6F3652711ADD52B0045E114 /* Pascal.h */, - B63EFBE811A244EE00C90DCE /* Date.cpp */, - B63EFBE911A244EE00C90DCE /* Date.h */, - B63EFBEA11A244EE00C90DCE /* Entry.cpp */, - B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */, - B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */, - B6F3651A11ADD0280045E114 /* VolumeEntry.h */, - B6F3651B11ADD0280045E114 /* FileEntry.h */, - B6F3651C11ADD0280045E114 /* Entry.h */, - B6F3676311B323680045E114 /* TextWriter.h */, - B6F3676411B323680045E114 /* TextWriter.cpp */, - ); - path = Pascal; - sourceTree = ""; - }; - B65090171332FE5000FBA318 /* NuFX */ = { - isa = PBXGroup; - children = ( - B65090181332FE5000FBA318 /* Exception.cpp */, - B65090191332FE5000FBA318 /* Exception.h */, - ); - path = NuFX; - sourceTree = ""; - }; - B65090231332FE6A00FBA318 /* POSIX */ = { - isa = PBXGroup; - children = ( - B65090241332FE6A00FBA318 /* Exception.cpp */, - B65090251332FE6A00FBA318 /* Exception.h */, - ); - path = POSIX; - sourceTree = ""; - }; - B65090351332FEBE00FBA318 /* Common */ = { - isa = PBXGroup; - children = ( - B65090361332FEBE00FBA318 /* auto.h */, - B65090371332FEBE00FBA318 /* Exception.cpp */, - B65090381332FEBE00FBA318 /* Exception.h */, - B650903A1332FEBE00FBA318 /* Lock.cpp */, - B650903B1332FEBE00FBA318 /* Lock.h */, - B650903D1332FEBE00FBA318 /* smart_pointers.h */, - B650903E1332FEBE00FBA318 /* unordered_map.h */, - ); - path = Common; - sourceTree = ""; - }; - B656ADED11A84D3200AB578A /* Libraries */ = { - isa = PBXGroup; - children = ( - B6A590F713299626007B0EE2 /* libNuFX.a */, - B6A590EC132995D4007B0EE2 /* Carbon.framework */, - B6A590EE132995D4007B0EE2 /* libz.dylib */, - B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */, - ); - name = Libraries; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - B63EFCCD11A36C7300C90DCE /* apfm */ = { - isa = PBXNativeTarget; - buildConfigurationList = B63EFCEC11A36CB800C90DCE /* Build configuration list for PBXNativeTarget "apfm" */; - buildPhases = ( - B63EFCCB11A36C7300C90DCE /* Sources */, - B63EFCCC11A36C7300C90DCE /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = apfm; - productName = apfm; - productReference = B63EFCCE11A36C7300C90DCE /* apfm */; - productType = "com.apple.product-type.tool"; - }; - B63EFE8011A4886C00C90DCE /* newfs_pascal */ = { - isa = PBXNativeTarget; - buildConfigurationList = B63EFEB311A488C200C90DCE /* Build configuration list for PBXNativeTarget "newfs_pascal" */; - buildPhases = ( - B63EFE7E11A4886C00C90DCE /* Sources */, - B63EFE7F11A4886C00C90DCE /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = newfs_pascal; - productName = newfs_pascal; - productReference = B63EFE8111A4886C00C90DCE /* newfs_pascal */; - productType = "com.apple.product-type.tool"; - }; - B650908A133304C800FBA318 /* profuse */ = { - isa = PBXNativeTarget; - buildConfigurationList = B65090AC133304C800FBA318 /* Build configuration list for PBXNativeTarget "profuse" */; - buildPhases = ( - B650908B133304C800FBA318 /* Sources */, - B65090A7133304C800FBA318 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = profuse; - productName = profuse; - productReference = B65090B1133304C800FBA318 /* profuse */; - productType = "com.apple.product-type.tool"; - }; - B656AE0211A84F5800AB578A /* fuse_pascal */ = { - isa = PBXNativeTarget; - buildConfigurationList = B656AE3411A84FA400AB578A /* Build configuration list for PBXNativeTarget "fuse_pascal" */; - buildPhases = ( - B656AE0011A84F5800AB578A /* Sources */, - B656AE0111A84F5800AB578A /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = fuse_pascal; - productName = fuse_pascal; - productReference = B656AE0311A84F5800AB578A /* fuse_pascal */; - productType = "com.apple.product-type.tool"; - }; - B656AF0211AA105500AB578A /* NibbleTest */ = { - isa = PBXNativeTarget; - buildConfigurationList = B656AF2111AA10A100AB578A /* Build configuration list for PBXNativeTarget "NibbleTest" */; - buildPhases = ( - B656AF0011AA105500AB578A /* Sources */, - B656AF0111AA105500AB578A /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = NibbleTest; - productName = NibbleTest; - productReference = B656AF0311AA105500AB578A /* NibbleTest */; - productType = "com.apple.product-type.tool"; - }; - B6F3647F11AB36260045E114 /* xattr */ = { - isa = PBXNativeTarget; - buildConfigurationList = B6F3648911AB36590045E114 /* Build configuration list for PBXNativeTarget "xattr" */; - buildPhases = ( - B6F3647D11AB36260045E114 /* Sources */, - B6F3647E11AB36260045E114 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = xattr; - productName = xattr; - productReference = B6F3648011AB36260045E114 /* xattr */; - productType = "com.apple.product-type.tool"; - }; - B6F3682411B431AC0045E114 /* newfs_prodos */ = { - isa = PBXNativeTarget; - buildConfigurationList = B6F3684111B432000045E114 /* Build configuration list for PBXNativeTarget "newfs_prodos" */; - buildPhases = ( - B6F3682211B431AC0045E114 /* Sources */, - B6F3682311B431AC0045E114 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = newfs_prodos; - productName = newfs_prodos; - productReference = B6F3682511B431AC0045E114 /* newfs_prodos */; - productType = "com.apple.product-type.tool"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 08FB7793FE84155DC02AAC07 /* Project object */ = { - isa = PBXProject; - buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "PROFuseX" */; - compatibilityVersion = "Xcode 3.1"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - en, - ); - mainGroup = 08FB7794FE84155DC02AAC07 /* PROFuseX */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - B63EFCCD11A36C7300C90DCE /* apfm */, - B63EFE8011A4886C00C90DCE /* newfs_pascal */, - B656AE0211A84F5800AB578A /* fuse_pascal */, - B656AF0211AA105500AB578A /* NibbleTest */, - B6F3647F11AB36260045E114 /* xattr */, - B6F3682411B431AC0045E114 /* newfs_prodos */, - B650908A133304C800FBA318 /* profuse */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - B63EFCCB11A36C7300C90DCE /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - B63EFCD211A36C8B00C90DCE /* Endian.cpp in Sources */, - B63EFCD311A36C8B00C90DCE /* BlockDevice.cpp in Sources */, - B63EFCD411A36C8B00C90DCE /* DavexDiskImage.cpp in Sources */, - B63EFCD511A36C8B00C90DCE /* DiskCopy42Image.cpp in Sources */, - B63EFCD611A36C8B00C90DCE /* DiskImage.cpp in Sources */, - B63EFCD711A36C8B00C90DCE /* RawDevice.cpp in Sources */, - B63EFCD811A36C8B00C90DCE /* UniversalDiskImage.cpp in Sources */, - B63EFCD911A36C8B00C90DCE /* BlockCache.cpp in Sources */, - B63EFCDA11A36C8B00C90DCE /* ConcreteBlockCache.cpp in Sources */, - B63EFCDB11A36C8B00C90DCE /* MappedBlockCache.cpp in Sources */, - B63EFCDC11A36C8B00C90DCE /* File.cpp in Sources */, - B63EFCDD11A36C8B00C90DCE /* MappedFile.cpp in Sources */, - B63EFCE011A36C8B00C90DCE /* Adaptor.cpp in Sources */, - B63EFCE111A36C8B00C90DCE /* Date.cpp in Sources */, - B63EFCE211A36C8B00C90DCE /* Entry.cpp in Sources */, - B63EFCE311A36C8B00C90DCE /* FileEntry.cpp in Sources */, - B63EFCE511A36C8B00C90DCE /* VolumeEntry.cpp in Sources */, - B6F3676711B323680045E114 /* TextWriter.cpp in Sources */, - B6272A9311D5AC440073C73A /* apfm.cpp in Sources */, - B6A591281329C417007B0EE2 /* SDKImage.cpp in Sources */, - B650901B1332FE5000FBA318 /* Exception.cpp in Sources */, - B65090271332FE6A00FBA318 /* Exception.cpp in Sources */, - B65090311332FE8B00FBA318 /* Exception.cpp in Sources */, - B650903F1332FEBE00FBA318 /* Exception.cpp in Sources */, - B65090471332FEBE00FBA318 /* Lock.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B63EFE7E11A4886C00C90DCE /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - B63EFE8511A4888500C90DCE /* Endian.cpp in Sources */, - B63EFE8611A4888500C90DCE /* BlockDevice.cpp in Sources */, - B63EFE8711A4888500C90DCE /* DavexDiskImage.cpp in Sources */, - B63EFE8811A4888500C90DCE /* DiskCopy42Image.cpp in Sources */, - B63EFE8911A4888500C90DCE /* DiskImage.cpp in Sources */, - B63EFE8A11A4888500C90DCE /* RawDevice.cpp in Sources */, - B63EFE8B11A4888500C90DCE /* UniversalDiskImage.cpp in Sources */, - B63EFE8C11A4888500C90DCE /* BlockCache.cpp in Sources */, - B63EFE8D11A4888500C90DCE /* ConcreteBlockCache.cpp in Sources */, - B63EFE8E11A4888500C90DCE /* MappedBlockCache.cpp in Sources */, - B63EFE8F11A4888500C90DCE /* File.cpp in Sources */, - B63EFE9011A4888500C90DCE /* MappedFile.cpp in Sources */, - B63EFE9311A4888500C90DCE /* Adaptor.cpp in Sources */, - B63EFE9411A4888500C90DCE /* Date.cpp in Sources */, - B63EFE9511A4888500C90DCE /* Entry.cpp in Sources */, - B63EFE9611A4888500C90DCE /* FileEntry.cpp in Sources */, - B63EFE9711A4888500C90DCE /* VolumeEntry.cpp in Sources */, - B6F3676811B323680045E114 /* TextWriter.cpp in Sources */, - B6272A9611D5AC560073C73A /* newfs_pascal.cpp in Sources */, - B65090281332FE6A00FBA318 /* Exception.cpp in Sources */, - B65090321332FE8B00FBA318 /* Exception.cpp in Sources */, - B65090401332FEBE00FBA318 /* Exception.cpp in Sources */, - B65090481332FEBE00FBA318 /* Lock.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B650908B133304C800FBA318 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - B650908C133304C800FBA318 /* Endian.cpp in Sources */, - B650908D133304C800FBA318 /* BlockDevice.cpp in Sources */, - B650908E133304C800FBA318 /* DavexDiskImage.cpp in Sources */, - B650908F133304C800FBA318 /* DiskCopy42Image.cpp in Sources */, - B6509090133304C800FBA318 /* DiskImage.cpp in Sources */, - B6509091133304C800FBA318 /* RawDevice.cpp in Sources */, - B6509092133304C800FBA318 /* UniversalDiskImage.cpp in Sources */, - B6509093133304C800FBA318 /* BlockCache.cpp in Sources */, - B6509094133304C800FBA318 /* ConcreteBlockCache.cpp in Sources */, - B6509095133304C800FBA318 /* MappedBlockCache.cpp in Sources */, - B6509096133304C800FBA318 /* File.cpp in Sources */, - B6509097133304C800FBA318 /* MappedFile.cpp in Sources */, - B6509098133304C800FBA318 /* Adaptor.cpp in Sources */, - B6509099133304C800FBA318 /* SDKImage.cpp in Sources */, - B650909A133304C800FBA318 /* Exception.cpp in Sources */, - B650909B133304C800FBA318 /* Exception.cpp in Sources */, - B650909C133304C800FBA318 /* Exception.cpp in Sources */, - B650909D133304C800FBA318 /* Exception.cpp in Sources */, - B650909E133304C800FBA318 /* Lock.cpp in Sources */, - B650909F133304C800FBA318 /* DateTime.cpp in Sources */, - B65090A0133304C800FBA318 /* File.cpp in Sources */, - B65090A1133304C800FBA318 /* Disk.cpp in Sources */, - B65090A2133304C800FBA318 /* profuse.cpp in Sources */, - B65090A3133304C800FBA318 /* profuse_xattr.cpp in Sources */, - B65090A4133304C800FBA318 /* profuse_stat.cpp in Sources */, - B65090A5133304C800FBA318 /* profuse_file.cpp in Sources */, - B65090A6133304C800FBA318 /* profuse_dirent.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B656AE0011A84F5800AB578A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - B656AE0911A84F7700AB578A /* Endian.cpp in Sources */, - B656AE0A11A84F7700AB578A /* BlockDevice.cpp in Sources */, - B656AE0B11A84F7700AB578A /* DavexDiskImage.cpp in Sources */, - B656AE0C11A84F7700AB578A /* DiskCopy42Image.cpp in Sources */, - B656AE0D11A84F7700AB578A /* DiskImage.cpp in Sources */, - B656AE0E11A84F7700AB578A /* RawDevice.cpp in Sources */, - B656AE0F11A84F7700AB578A /* UniversalDiskImage.cpp in Sources */, - B656AE1011A84F7700AB578A /* BlockCache.cpp in Sources */, - B656AE1111A84F7700AB578A /* ConcreteBlockCache.cpp in Sources */, - B656AE1211A84F7700AB578A /* MappedBlockCache.cpp in Sources */, - B656AE1311A84F7700AB578A /* File.cpp in Sources */, - B656AE1411A84F7700AB578A /* MappedFile.cpp in Sources */, - B656AE1711A84F7700AB578A /* Adaptor.cpp in Sources */, - B656AE1811A84F7700AB578A /* Date.cpp in Sources */, - B656AE1911A84F7700AB578A /* Entry.cpp in Sources */, - B656AE1A11A84F7700AB578A /* FileEntry.cpp in Sources */, - B656AE1B11A84F7700AB578A /* VolumeEntry.cpp in Sources */, - B6F3676511B323680045E114 /* TextWriter.cpp in Sources */, - B6272A9411D5AC4C0073C73A /* fuse_pascal.cpp in Sources */, - B6272A9511D5AC530073C73A /* fuse_pascal_ops.cpp in Sources */, - B6A591291329C417007B0EE2 /* SDKImage.cpp in Sources */, - B650901D1332FE5000FBA318 /* Exception.cpp in Sources */, - B65090291332FE6A00FBA318 /* Exception.cpp in Sources */, - B65090331332FE8B00FBA318 /* Exception.cpp in Sources */, - B65090411332FEBE00FBA318 /* Exception.cpp in Sources */, - B65090491332FEBE00FBA318 /* Lock.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B656AF0011AA105500AB578A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - B656AF0911AA106C00AB578A /* Endian.cpp in Sources */, - B656AF0A11AA106C00AB578A /* BlockDevice.cpp in Sources */, - B656AF0B11AA106C00AB578A /* DavexDiskImage.cpp in Sources */, - B656AF0C11AA106C00AB578A /* DiskCopy42Image.cpp in Sources */, - B656AF0D11AA106C00AB578A /* DiskImage.cpp in Sources */, - B656AF0E11AA106C00AB578A /* RawDevice.cpp in Sources */, - B656AF0F11AA106C00AB578A /* UniversalDiskImage.cpp in Sources */, - B656AF1011AA106C00AB578A /* BlockCache.cpp in Sources */, - B656AF1111AA106C00AB578A /* ConcreteBlockCache.cpp in Sources */, - B656AF1211AA106C00AB578A /* MappedBlockCache.cpp in Sources */, - B656AF1311AA106C00AB578A /* File.cpp in Sources */, - B656AF1411AA106C00AB578A /* MappedFile.cpp in Sources */, - B656AF1711AA106C00AB578A /* Adaptor.cpp in Sources */, - B656AF1811AA106C00AB578A /* Date.cpp in Sources */, - B656AF1911AA106C00AB578A /* Entry.cpp in Sources */, - B656AF1A11AA106C00AB578A /* FileEntry.cpp in Sources */, - B656AF1B11AA106C00AB578A /* VolumeEntry.cpp in Sources */, - B656AF0811AA106400AB578A /* NibbleTest.cpp in Sources */, - B6F3676611B323680045E114 /* TextWriter.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B6F3647D11AB36260045E114 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - B6272A9711D5AC5B0073C73A /* xattr.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B6F3682211B431AC0045E114 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - B6F3682A11B431CC0045E114 /* Endian.cpp in Sources */, - B6F3682B11B431CC0045E114 /* BlockDevice.cpp in Sources */, - B6F3682C11B431CC0045E114 /* DavexDiskImage.cpp in Sources */, - B6F3682D11B431CC0045E114 /* DiskCopy42Image.cpp in Sources */, - B6F3682E11B431CC0045E114 /* DiskImage.cpp in Sources */, - B6F3682F11B431CC0045E114 /* RawDevice.cpp in Sources */, - B6F3683011B431CC0045E114 /* UniversalDiskImage.cpp in Sources */, - B6F3683111B431CC0045E114 /* BlockCache.cpp in Sources */, - B6F3683211B431CC0045E114 /* ConcreteBlockCache.cpp in Sources */, - B6F3683311B431CC0045E114 /* MappedBlockCache.cpp in Sources */, - B6F3683411B431CC0045E114 /* File.cpp in Sources */, - B6F3683511B431CC0045E114 /* MappedFile.cpp in Sources */, - B6F3683811B431CC0045E114 /* Adaptor.cpp in Sources */, - B6272AAA11D5AE0C0073C73A /* Bitmap.cpp in Sources */, - B6272AAB11D5AE0C0073C73A /* DateTime.cpp in Sources */, - B650901E1332FE5000FBA318 /* Exception.cpp in Sources */, - B650902A1332FE6A00FBA318 /* Exception.cpp in Sources */, - B65090341332FE8B00FBA318 /* Exception.cpp in Sources */, - B65090421332FEBE00FBA318 /* Exception.cpp in Sources */, - B650904A1332FEBE00FBA318 /* Lock.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 1DEB923608733DC60010E9CD /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - /usr/local/include/, - ., - ); - ONLY_ACTIVE_ARCH = NO; - PREBINDING = NO; - SDKROOT = macosx; - }; - name = Debug; - }; - 1DEB923708733DC60010E9CD /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - ONLY_ACTIVE_ARCH = NO; - PREBINDING = NO; - SDKROOT = macosx; - }; - name = Release; - }; - B63EFCD011A36C7300C90DCE /* 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; - INSTALL_PATH = /usr/local/bin; - LIBRARY_SEARCH_PATHS = ( - ., - /usr/local/lib/, - ); - OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; - PRODUCT_NAME = apfm; - }; - name = Debug; - }; - B63EFCD111A36C7300C90DCE /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_MODEL_TUNING = G5; - INSTALL_PATH = /usr/local/bin; - LIBRARY_SEARCH_PATHS = ( - ., - /usr/local/lib/, - ); - OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; - PRODUCT_NAME = apfm; - ZERO_LINK = NO; - }; - name = Release; - }; - B63EFE8311A4886C00C90DCE /* 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_VERSION = com.apple.compilers.llvm.clang.1_0; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = newfs_pascal; - }; - name = Debug; - }; - B63EFE8411A4886C00C90DCE /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_MODEL_TUNING = G5; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = newfs_pascal; - ZERO_LINK = NO; - }; - name = Release; - }; - B65090AD133304C800FBA318 /* 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; - INSTALL_PATH = /usr/local/bin; - LIBRARY_SEARCH_PATHS = ( - ., - /usr/local/lib/, - ); - OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; - PRODUCT_NAME = profuse; - }; - name = Debug; - }; - B65090AE133304C800FBA318 /* 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; - INSTALL_PATH = /usr/local/bin; - LIBRARY_SEARCH_PATHS = ( - ., - /usr/local/lib/, - ); - OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; - PRODUCT_NAME = profuse; - }; - name = "Debug Universal"; - }; - B65090AF133304C800FBA318 /* Debug fuse */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_MODEL_TUNING = G5; - INSTALL_PATH = /usr/local/bin; - LIBRARY_SEARCH_PATHS = ( - ., - /usr/local/lib/, - ); - OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; - PRODUCT_NAME = profuse; - }; - name = "Debug fuse"; - }; - B65090B0133304C800FBA318 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_MODEL_TUNING = G5; - INSTALL_PATH = /usr/local/bin; - LIBRARY_SEARCH_PATHS = ( - ., - /usr/local/lib/, - ); - OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; - PRODUCT_NAME = profuse; - ZERO_LINK = NO; - }; - name = Release; - }; - B656AD7A11A84B5D00AB578A /* Debug fuse */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - /usr/local/include/, - ., - ); - ONLY_ACTIVE_ARCH = NO; - PREBINDING = NO; - SDKROOT = macosx; - }; - name = "Debug fuse"; - }; - B656AD7C11A84B5D00AB578A /* Debug fuse */ = { - 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; - INSTALL_PATH = /usr/local/bin; - LIBRARY_SEARCH_PATHS = ( - ., - /usr/local/lib/, - ); - OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; - PRODUCT_NAME = apfm; - }; - name = "Debug fuse"; - }; - B656AD7D11A84B5D00AB578A /* Debug fuse */ = { - 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_VERSION = com.apple.compilers.llvm.clang.1_0; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = newfs_pascal; - }; - name = "Debug fuse"; - }; - B656AE0511A84F5900AB578A /* 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; - INSTALL_PATH = /usr/local/bin; - LIBRARY_SEARCH_PATHS = ( - ., - /usr/local/lib/, - ); - OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; - PRODUCT_NAME = fuse_pascal; - }; - name = Debug; - }; - B656AE0611A84F5900AB578A /* Debug fuse */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_MODEL_TUNING = G5; - INSTALL_PATH = /usr/local/bin; - LIBRARY_SEARCH_PATHS = ( - ., - /usr/local/lib/, - ); - OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; - PRODUCT_NAME = fuse_pascal; - }; - name = "Debug fuse"; - }; - B656AE0711A84F5900AB578A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_MODEL_TUNING = G5; - INSTALL_PATH = /usr/local/bin; - LIBRARY_SEARCH_PATHS = ( - ., - /usr/local/lib/, - ); - OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; - PRODUCT_NAME = fuse_pascal; - ZERO_LINK = NO; - }; - name = Release; - }; - B656AF0511AA105600AB578A /* 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; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = NibbleTest; - }; - name = Debug; - }; - B656AF0611AA105600AB578A /* Debug fuse */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_MODEL_TUNING = G5; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = NibbleTest; - }; - name = "Debug fuse"; - }; - B656AF0711AA105600AB578A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_MODEL_TUNING = G5; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = NibbleTest; - ZERO_LINK = NO; - }; - name = Release; - }; - B6A53C1E131B47DC00C9070F /* Debug Universal */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - /usr/local/include/, - ., - ); - ONLY_ACTIVE_ARCH = NO; - PREBINDING = NO; - SDKROOT = macosx; - }; - name = "Debug Universal"; - }; - B6A53C1F131B47DC00C9070F /* 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; - INSTALL_PATH = /usr/local/bin; - LIBRARY_SEARCH_PATHS = ( - ., - /usr/local/lib/, - ); - OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; - PRODUCT_NAME = apfm; - }; - name = "Debug Universal"; - }; - B6A53C20131B47DC00C9070F /* 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_VERSION = com.apple.compilers.llvm.clang.1_0; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = newfs_pascal; - }; - name = "Debug Universal"; - }; - B6A53C21131B47DC00C9070F /* 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; - INSTALL_PATH = /usr/local/bin; - LIBRARY_SEARCH_PATHS = ( - ., - /usr/local/lib/, - ); - OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; - PRODUCT_NAME = fuse_pascal; - }; - name = "Debug Universal"; - }; - B6A53C22131B47DC00C9070F /* 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; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = NibbleTest; - }; - name = "Debug Universal"; - }; - B6A53C23131B47DC00C9070F /* 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; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = xattr; - }; - name = "Debug Universal"; - }; - B6A53C24131B47DC00C9070F /* 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; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = newfs_prodos; - }; - name = "Debug Universal"; - }; - B6F3648211AB36260045E114 /* 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; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = xattr; - }; - name = Debug; - }; - B6F3648311AB36260045E114 /* Debug fuse */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_MODEL_TUNING = G5; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = xattr; - }; - name = "Debug fuse"; - }; - B6F3648411AB36260045E114 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_MODEL_TUNING = G5; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = xattr; - ZERO_LINK = NO; - }; - name = Release; - }; - B6F3682711B431AC0045E114 /* 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; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = newfs_prodos; - }; - name = Debug; - }; - B6F3682811B431AC0045E114 /* Debug fuse */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_MODEL_TUNING = G5; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = newfs_prodos; - }; - name = "Debug fuse"; - }; - B6F3682911B431AC0045E114 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_MODEL_TUNING = G5; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = newfs_prodos; - ZERO_LINK = NO; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "PROFuseX" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1DEB923608733DC60010E9CD /* Debug */, - B6A53C1E131B47DC00C9070F /* Debug Universal */, - B656AD7A11A84B5D00AB578A /* Debug fuse */, - 1DEB923708733DC60010E9CD /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - B63EFCEC11A36CB800C90DCE /* Build configuration list for PBXNativeTarget "apfm" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B63EFCD011A36C7300C90DCE /* Debug */, - B6A53C1F131B47DC00C9070F /* Debug Universal */, - B656AD7C11A84B5D00AB578A /* Debug fuse */, - B63EFCD111A36C7300C90DCE /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - B63EFEB311A488C200C90DCE /* Build configuration list for PBXNativeTarget "newfs_pascal" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B63EFE8311A4886C00C90DCE /* Debug */, - B6A53C20131B47DC00C9070F /* Debug Universal */, - B656AD7D11A84B5D00AB578A /* Debug fuse */, - B63EFE8411A4886C00C90DCE /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - B65090AC133304C800FBA318 /* Build configuration list for PBXNativeTarget "profuse" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B65090AD133304C800FBA318 /* Debug */, - B65090AE133304C800FBA318 /* Debug Universal */, - B65090AF133304C800FBA318 /* Debug fuse */, - B65090B0133304C800FBA318 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - B656AE3411A84FA400AB578A /* Build configuration list for PBXNativeTarget "fuse_pascal" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B656AE0511A84F5900AB578A /* Debug */, - B6A53C21131B47DC00C9070F /* Debug Universal */, - B656AE0611A84F5900AB578A /* Debug fuse */, - B656AE0711A84F5900AB578A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - B656AF2111AA10A100AB578A /* Build configuration list for PBXNativeTarget "NibbleTest" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B656AF0511AA105600AB578A /* Debug */, - B6A53C22131B47DC00C9070F /* Debug Universal */, - B656AF0611AA105600AB578A /* Debug fuse */, - B656AF0711AA105600AB578A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - B6F3648911AB36590045E114 /* Build configuration list for PBXNativeTarget "xattr" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B6F3648211AB36260045E114 /* Debug */, - B6A53C23131B47DC00C9070F /* Debug Universal */, - B6F3648311AB36260045E114 /* Debug fuse */, - B6F3648411AB36260045E114 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - B6F3684111B432000045E114 /* Build configuration list for PBXNativeTarget "newfs_prodos" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B6F3682711B431AC0045E114 /* Debug */, - B6A53C24131B47DC00C9070F /* Debug Universal */, - B6F3682811B431AC0045E114 /* Debug fuse */, - B6F3682911B431AC0045E114 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; -} From 5d219195bb8b0ed3db7af053142a0f35541870f3 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 2 Apr 2011 18:14:27 +0000 Subject: [PATCH 229/236] Support for 2MG w/o 0 filesize field (leadlight) git-svn-id: https://profuse.googlecode.com/svn/branches/v2@397 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/UniversalDiskImage.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Device/UniversalDiskImage.cpp b/Device/UniversalDiskImage.cpp index 08f7c4d..23cdacd 100644 --- a/Device/UniversalDiskImage.cpp +++ b/Device/UniversalDiskImage.cpp @@ -107,6 +107,7 @@ bool UniversalDiskImage::Validate(MappedFile *file, const std::nothrow_t &) unsigned blocks = 0; unsigned offset = 0; + unsigned fileSize = 0; if (size < 64) return false; @@ -121,8 +122,11 @@ bool UniversalDiskImage::Validate(MappedFile *file, const std::nothrow_t &) offset = Read32(data, 0x18); // file size == blocks * 512 - if (Read32(data, 0x1c) != blocks * 512) return false; - + // 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 (offset + blocks * 512 > size) return false; return true; From 1dd7becb2fd6639963ce208e99f5209d26810b1f Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 19 Apr 2011 17:27:08 +0000 Subject: [PATCH 230/236] updated makefile git-svn-id: https://profuse.googlecode.com/svn/branches/v2@398 aa027e90-d47c-11dd-86d7-074df07e0730 --- Makefile | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 3bb6ef1..a5b7496 100644 --- a/Makefile +++ b/Makefile @@ -92,11 +92,20 @@ EXCEPTION_OBJECTS += POSIX/Exception.o all: $(TARGETS) -#apfm: o/apfm -#fuse_pascal: o/fuse_pascal -#newfs_pascal: o/newfs_pascal -#profuse: o/profuse -#xattr: o/xattr +apfm: o/apfm + @true + +fuse_pascal: o/fuse_pascal + @true + +newfs_pascal: o/newfs_pascal + @true + +profuse: o/profuse + @true + +xattr: o/xattr + @true From 75080971764f1b2e1f18d8aac44aeea96a219e91 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 26 Aug 2011 22:48:51 +0000 Subject: [PATCH 231/236] Update makefile for OS X 10.7 w/ OSXFUSE instead of MacFUSE git-svn-id: https://profuse.googlecode.com/svn/branches/v2@399 aa027e90-d47c-11dd-86d7-074df07e0730 --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a5b7496..14dbe1e 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,8 @@ LIBS += -lpthread UNAME = $(shell uname -s) ifeq ($(UNAME),Darwin) - FUSE_LIBS += -lfuse_ino64 + FUSE_LIBS += -losxfuse + CPPFLAGS += -I/usr/local/include/osxfuse/fuse else FUSE_LIBS += -lfuse endif From ef1874977b4c0dd97f9e0edda300e8e73d415750 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 27 Aug 2011 00:33:18 +0000 Subject: [PATCH 232/236] update project for osxfuse git-svn-id: https://profuse.googlecode.com/svn/branches/v2@400 aa027e90-d47c-11dd-86d7-074df07e0730 --- ProFUSE.xcodeproj/project.pbxproj | 357 +++++++++++++++--------------- 1 file changed, 178 insertions(+), 179 deletions(-) diff --git a/ProFUSE.xcodeproj/project.pbxproj b/ProFUSE.xcodeproj/project.pbxproj index 7d1f572..485dad9 100644 --- a/ProFUSE.xcodeproj/project.pbxproj +++ b/ProFUSE.xcodeproj/project.pbxproj @@ -3,15 +3,17 @@ archiveVersion = 1; classes = { }; - objectVersion = 45; + objectVersion = 46; objects = { /* Begin PBXBuildFile section */ + B60BD4A414086E0600329025 /* libosxfuse.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B60BD4A314086E0600329025 /* libosxfuse.dylib */; }; + B60BD4A514086E0600329025 /* libosxfuse.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B60BD4A314086E0600329025 /* libosxfuse.dylib */; }; + B60BD4B71408705400329025 /* xattr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A9211D5AC3C0073C73A /* xattr.cpp */; }; B6272A9311D5AC440073C73A /* apfm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A8E11D5AC3C0073C73A /* apfm.cpp */; }; B6272A9411D5AC4C0073C73A /* fuse_pascal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */; }; B6272A9511D5AC530073C73A /* fuse_pascal_ops.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */; }; B6272A9611D5AC560073C73A /* newfs_pascal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A9111D5AC3C0073C73A /* newfs_pascal.cpp */; }; - B6272A9711D5AC5B0073C73A /* xattr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272A9211D5AC3C0073C73A /* xattr.cpp */; }; B6272AAA11D5AE0C0073C73A /* Bitmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272AA511D5AE0C0073C73A /* Bitmap.cpp */; }; B6272AAB11D5AE0C0073C73A /* DateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6272AA711D5AE0C0073C73A /* DateTime.cpp */; }; B63EFCD211A36C8B00C90DCE /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; @@ -94,11 +96,9 @@ B65090A4133304C800FBA318 /* profuse_stat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509082133300FB00FBA318 /* profuse_stat.cpp */; }; B65090A5133304C800FBA318 /* profuse_file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509083133300FB00FBA318 /* profuse_file.cpp */; }; B65090A6133304C800FBA318 /* profuse_dirent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6509084133300FB00FBA318 /* profuse_dirent.cpp */; }; - B65090A8133304C800FBA318 /* libfuse_ino64.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */; }; B65090A9133304C800FBA318 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EC132995D4007B0EE2 /* Carbon.framework */; }; B65090AA133304C800FBA318 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590EE132995D4007B0EE2 /* libz.dylib */; }; B65090AB133304C800FBA318 /* libNuFX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B6A590F713299626007B0EE2 /* libNuFX.a */; }; - B656AE0811A84F6C00AB578A /* libfuse_ino64.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */; }; B656AE0911A84F7700AB578A /* Endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA7511A0948500C90DCE /* Endian.cpp */; }; B656AE0A11A84F7700AB578A /* BlockDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9511A094E000C90DCE /* BlockDevice.cpp */; }; B656AE0B11A84F7700AB578A /* DavexDiskImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFA9711A094E000C90DCE /* DavexDiskImage.cpp */; }; @@ -161,7 +161,21 @@ B6F3683811B431CC0045E114 /* Adaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63EFB0711A0AC4800C90DCE /* Adaptor.cpp */; }; /* End PBXBuildFile section */ +/* Begin PBXCopyFilesBuildPhase section */ + B60BD4A81408702900329025 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ + B60BD4A314086E0600329025 /* libosxfuse.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libosxfuse.dylib; path = ../../../../usr/local/lib/libosxfuse.dylib; sourceTree = ""; }; + B60BD4AA1408702900329025 /* xattr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xattr; sourceTree = BUILT_PRODUCTS_DIR; }; B6272A8E11D5AC3C0073C73A /* apfm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = apfm.cpp; sourceTree = ""; }; B6272A8F11D5AC3C0073C73A /* fuse_pascal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fuse_pascal.cpp; sourceTree = ""; }; B6272A9011D5AC3C0073C73A /* fuse_pascal_ops.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fuse_pascal_ops.cpp; sourceTree = ""; }; @@ -206,8 +220,8 @@ B63EFBEC11A244EE00C90DCE /* FileEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileEntry.cpp; sourceTree = ""; }; B63EFBF111A244EE00C90DCE /* VolumeEntry.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = VolumeEntry.cpp; sourceTree = ""; }; B63EFC4311A31B7200C90DCE /* IOBuffer.cpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOBuffer.cpp.h; sourceTree = ""; }; - B63EFCCE11A36C7300C90DCE /* apfm */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = apfm; sourceTree = BUILT_PRODUCTS_DIR; }; - B63EFE8111A4886C00C90DCE /* newfs_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = newfs_pascal; sourceTree = BUILT_PRODUCTS_DIR; }; + B63EFCCE11A36C7300C90DCE /* apfm */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = apfm; path = /Users/kelvin/Projects/ProFUSE/build/Release/apfm; sourceTree = ""; }; + B63EFE8111A4886C00C90DCE /* newfs_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = newfs_pascal; path = /Users/kelvin/Projects/ProFUSE/build/Release/newfs_pascal; sourceTree = ""; }; B65090181332FE5000FBA318 /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = ""; }; B65090191332FE5000FBA318 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; B65090241332FE6A00FBA318 /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = ""; }; @@ -232,28 +246,33 @@ B6509083133300FB00FBA318 /* profuse_file.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_file.cpp; sourceTree = ""; }; B6509084133300FB00FBA318 /* profuse_dirent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profuse_dirent.cpp; sourceTree = ""; }; B6509085133300FB00FBA318 /* profuse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = profuse.h; sourceTree = ""; }; - B65090B1133304C800FBA318 /* profuse */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = profuse; sourceTree = BUILT_PRODUCTS_DIR; }; - B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libfuse_ino64.dylib; path = /usr/local/lib/libfuse_ino64.dylib; sourceTree = ""; }; - B656AE0311A84F5800AB578A /* fuse_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fuse_pascal; sourceTree = BUILT_PRODUCTS_DIR; }; + B65090B1133304C800FBA318 /* profuse */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = profuse; path = /Users/kelvin/Projects/ProFUSE/build/Release/profuse; sourceTree = ""; }; + B656AE0311A84F5800AB578A /* fuse_pascal */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = fuse_pascal; path = /Users/kelvin/Projects/ProFUSE/build/Release/fuse_pascal; sourceTree = ""; }; B656AEFE11AA0F8C00AB578A /* NibbleTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NibbleTest.cpp; sourceTree = ""; }; - B656AF0311AA105500AB578A /* NibbleTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NibbleTest; sourceTree = BUILT_PRODUCTS_DIR; }; + B656AF0311AA105500AB578A /* NibbleTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = NibbleTest; path = /Users/kelvin/Projects/ProFUSE/build/Release/NibbleTest; sourceTree = ""; }; B659C142131368BA0058DC9C /* Device.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Device.h; sourceTree = ""; }; B6A590EC132995D4007B0EE2 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = ../../../../System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; B6A590EE132995D4007B0EE2 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = ../../../../usr/lib/libz.dylib; sourceTree = ""; }; B6A590F713299626007B0EE2 /* libNuFX.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libNuFX.a; sourceTree = ""; }; B6A591261329C417007B0EE2 /* SDKImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SDKImage.cpp; sourceTree = ""; }; B6A591271329C417007B0EE2 /* SDKImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDKImage.h; sourceTree = ""; }; - B6F3648011AB36260045E114 /* xattr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xattr; sourceTree = BUILT_PRODUCTS_DIR; }; B6F3651A11ADD0280045E114 /* VolumeEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VolumeEntry.h; sourceTree = ""; }; B6F3651B11ADD0280045E114 /* FileEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileEntry.h; sourceTree = ""; }; B6F3651C11ADD0280045E114 /* Entry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Entry.h; sourceTree = ""; }; B6F3652711ADD52B0045E114 /* Pascal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Pascal.h; sourceTree = ""; }; B6F3676311B323680045E114 /* TextWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextWriter.h; sourceTree = ""; }; B6F3676411B323680045E114 /* TextWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextWriter.cpp; sourceTree = ""; }; - B6F3682511B431AC0045E114 /* newfs_prodos */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = newfs_prodos; sourceTree = BUILT_PRODUCTS_DIR; }; + B6F3682511B431AC0045E114 /* newfs_prodos */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = newfs_prodos; path = /Users/kelvin/Projects/ProFUSE/build/Release/newfs_prodos; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + B60BD4A71408702900329025 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; B63EFCCC11A36C7300C90DCE /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -275,10 +294,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - B65090A8133304C800FBA318 /* libfuse_ino64.dylib in Frameworks */, B65090A9133304C800FBA318 /* Carbon.framework in Frameworks */, B65090AA133304C800FBA318 /* libz.dylib in Frameworks */, B65090AB133304C800FBA318 /* libNuFX.a in Frameworks */, + B60BD4A514086E0600329025 /* libosxfuse.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -286,10 +305,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - B656AE0811A84F6C00AB578A /* libfuse_ino64.dylib in Frameworks */, B6A590F0132995D4007B0EE2 /* Carbon.framework in Frameworks */, B6A590F4132995D5007B0EE2 /* libz.dylib in Frameworks */, B6A590F913299626007B0EE2 /* libNuFX.a in Frameworks */, + B60BD4A414086E0600329025 /* libosxfuse.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -300,13 +319,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - B6F3647E11AB36260045E114 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; B6F3682311B431AC0045E114 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -331,22 +343,16 @@ B65090351332FEBE00FBA318 /* Common */, B65090171332FE5000FBA318 /* NuFX */, B65090231332FE6A00FBA318 /* POSIX */, - 1AB674ADFE9D54B511CA2CBB /* Products */, B656ADED11A84D3200AB578A /* Libraries */, + B60BD4AB1408702900329025 /* Products */, ); name = PROFuseX; sourceTree = ""; }; - 1AB674ADFE9D54B511CA2CBB /* Products */ = { + B60BD4AB1408702900329025 /* Products */ = { isa = PBXGroup; children = ( - B63EFCCE11A36C7300C90DCE /* apfm */, - B63EFE8111A4886C00C90DCE /* newfs_pascal */, - B656AE0311A84F5800AB578A /* fuse_pascal */, - B656AF0311AA105500AB578A /* NibbleTest */, - B6F3648011AB36260045E114 /* xattr */, - B6F3682511B431AC0045E114 /* newfs_prodos */, - B65090B1133304C800FBA318 /* profuse */, + B60BD4AA1408702900329025 /* xattr */, ); name = Products; sourceTree = ""; @@ -501,10 +507,10 @@ B656ADED11A84D3200AB578A /* Libraries */ = { isa = PBXGroup; children = ( + B60BD4A314086E0600329025 /* libosxfuse.dylib */, B6A590F713299626007B0EE2 /* libNuFX.a */, B6A590EC132995D4007B0EE2 /* Carbon.framework */, B6A590EE132995D4007B0EE2 /* libz.dylib */, - B656ADEB11A84D2800AB578A /* libfuse_ino64.dylib */, ); name = Libraries; sourceTree = ""; @@ -512,6 +518,23 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + B60BD4A91408702900329025 /* xattr */ = { + isa = PBXNativeTarget; + buildConfigurationList = B60BD4B21408702900329025 /* Build configuration list for PBXNativeTarget "xattr" */; + buildPhases = ( + B60BD4A61408702900329025 /* Sources */, + B60BD4A71408702900329025 /* Frameworks */, + B60BD4A81408702900329025 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = xattr; + productName = xattr; + productReference = B60BD4AA1408702900329025 /* xattr */; + productType = "com.apple.product-type.tool"; + }; B63EFCCD11A36C7300C90DCE /* apfm */ = { isa = PBXNativeTarget; buildConfigurationList = B63EFCEC11A36CB800C90DCE /* Build configuration list for PBXNativeTarget "apfm" */; @@ -592,22 +615,6 @@ productReference = B656AF0311AA105500AB578A /* NibbleTest */; productType = "com.apple.product-type.tool"; }; - B6F3647F11AB36260045E114 /* xattr */ = { - isa = PBXNativeTarget; - buildConfigurationList = B6F3648911AB36590045E114 /* Build configuration list for PBXNativeTarget "xattr" */; - buildPhases = ( - B6F3647D11AB36260045E114 /* Sources */, - B6F3647E11AB36260045E114 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = xattr; - productName = xattr; - productReference = B6F3648011AB36260045E114 /* xattr */; - productType = "com.apple.product-type.tool"; - }; B6F3682411B431AC0045E114 /* newfs_prodos */ = { isa = PBXNativeTarget; buildConfigurationList = B6F3684111B432000045E114 /* Build configuration list for PBXNativeTarget "newfs_prodos" */; @@ -629,14 +636,18 @@ /* Begin PBXProject section */ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; - buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "PROFuseX" */; - compatibilityVersion = "Xcode 3.1"; + attributes = { + LastUpgradeCheck = 0410; + }; + buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "ProFUSE" */; + compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( en, ); mainGroup = 08FB7794FE84155DC02AAC07 /* PROFuseX */; + productRefGroup = B60BD4AB1408702900329025 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( @@ -644,14 +655,22 @@ B63EFE8011A4886C00C90DCE /* newfs_pascal */, B656AE0211A84F5800AB578A /* fuse_pascal */, B656AF0211AA105500AB578A /* NibbleTest */, - B6F3647F11AB36260045E114 /* xattr */, B6F3682411B431AC0045E114 /* newfs_prodos */, B650908A133304C800FBA318 /* profuse */, + B60BD4A91408702900329025 /* xattr */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ + B60BD4A61408702900329025 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B60BD4B71408705400329025 /* xattr.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; B63EFCCB11A36C7300C90DCE /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -807,14 +826,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - B6F3647D11AB36260045E114 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - B6272A9711D5AC5B0073C73A /* xattr.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; B6F3682211B431AC0045E114 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -859,7 +870,6 @@ ., ); ONLY_ACTIVE_ARCH = NO; - PREBINDING = NO; SDKROOT = macosx; }; name = Debug; @@ -872,19 +882,99 @@ GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + /usr/local/include/, + ., + ); ONLY_ACTIVE_ARCH = NO; - PREBINDING = NO; SDKROOT = macosx; }; name = Release; }; + B60BD4B31408702900329025 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + B60BD4B41408702900329025 /* Debug Universal */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = "Debug Universal"; + }; + B60BD4B51408702900329025 /* Debug fuse */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = "Debug fuse"; + }; + B60BD4B61408702900329025 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; B63EFCD011A36C7300C90DCE /* 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; INSTALL_PATH = /usr/local/bin; @@ -893,7 +983,6 @@ /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; PRODUCT_NAME = apfm; }; name = Debug; @@ -904,7 +993,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; LIBRARY_SEARCH_PATHS = ( @@ -912,7 +1000,6 @@ /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; PRODUCT_NAME = apfm; ZERO_LINK = NO; }; @@ -924,12 +1011,10 @@ 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_VERSION = com.apple.compilers.llvm.clang.1_0; INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; PRODUCT_NAME = newfs_pascal; }; name = Debug; @@ -940,11 +1025,9 @@ ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_MODEL_TUNING = G5; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; PRODUCT_NAME = newfs_pascal; ZERO_LINK = NO; }; @@ -956,16 +1039,18 @@ 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; + HEADER_SEARCH_PATHS = ( + /usr/local/include/, + ., + ); INSTALL_PATH = /usr/local/bin; LIBRARY_SEARCH_PATHS = ( ., /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; PRODUCT_NAME = profuse; }; name = Debug; @@ -976,16 +1061,18 @@ 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; + HEADER_SEARCH_PATHS = ( + /usr/local/include/, + ., + ); INSTALL_PATH = /usr/local/bin; LIBRARY_SEARCH_PATHS = ( ., /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; PRODUCT_NAME = profuse; }; name = "Debug Universal"; @@ -994,15 +1081,17 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_MODEL_TUNING = G5; + HEADER_SEARCH_PATHS = ( + /usr/local/include/, + ., + ); INSTALL_PATH = /usr/local/bin; LIBRARY_SEARCH_PATHS = ( ., /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; PRODUCT_NAME = profuse; }; name = "Debug fuse"; @@ -1013,15 +1102,17 @@ ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_MODEL_TUNING = G5; + HEADER_SEARCH_PATHS = ( + /usr/local/include/, + ., + ); INSTALL_PATH = /usr/local/bin; LIBRARY_SEARCH_PATHS = ( ., /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; PRODUCT_NAME = profuse; ZERO_LINK = NO; }; @@ -1041,7 +1132,6 @@ ., ); ONLY_ACTIVE_ARCH = NO; - PREBINDING = NO; SDKROOT = macosx; }; name = "Debug fuse"; @@ -1052,7 +1142,6 @@ 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; INSTALL_PATH = /usr/local/bin; @@ -1061,7 +1150,6 @@ /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; PRODUCT_NAME = apfm; }; name = "Debug fuse"; @@ -1072,12 +1160,10 @@ 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_VERSION = com.apple.compilers.llvm.clang.1_0; INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; PRODUCT_NAME = newfs_pascal; }; name = "Debug fuse"; @@ -1088,7 +1174,6 @@ 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; INSTALL_PATH = /usr/local/bin; @@ -1097,7 +1182,6 @@ /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; PRODUCT_NAME = fuse_pascal; }; name = Debug; @@ -1106,7 +1190,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; LIBRARY_SEARCH_PATHS = ( @@ -1114,7 +1197,6 @@ /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; PRODUCT_NAME = fuse_pascal; }; name = "Debug fuse"; @@ -1125,7 +1207,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; LIBRARY_SEARCH_PATHS = ( @@ -1133,7 +1214,6 @@ /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; PRODUCT_NAME = fuse_pascal; ZERO_LINK = NO; }; @@ -1145,11 +1225,9 @@ 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; INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; PRODUCT_NAME = NibbleTest; }; name = Debug; @@ -1158,10 +1236,8 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; PRODUCT_NAME = NibbleTest; }; name = "Debug fuse"; @@ -1172,10 +1248,8 @@ ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; PRODUCT_NAME = NibbleTest; ZERO_LINK = NO; }; @@ -1195,7 +1269,6 @@ ., ); ONLY_ACTIVE_ARCH = NO; - PREBINDING = NO; SDKROOT = macosx; }; name = "Debug Universal"; @@ -1206,7 +1279,6 @@ 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; INSTALL_PATH = /usr/local/bin; @@ -1215,7 +1287,6 @@ /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; PRODUCT_NAME = apfm; }; name = "Debug Universal"; @@ -1226,12 +1297,10 @@ 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_VERSION = com.apple.compilers.llvm.clang.1_0; INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; PRODUCT_NAME = newfs_pascal; }; name = "Debug Universal"; @@ -1242,7 +1311,6 @@ 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; INSTALL_PATH = /usr/local/bin; @@ -1251,7 +1319,6 @@ /usr/local/lib/, ); OTHER_CFLAGS = "-DHAVE_NUFX"; - PREBINDING = NO; PRODUCT_NAME = fuse_pascal; }; name = "Debug Universal"; @@ -1262,98 +1329,35 @@ 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; INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; PRODUCT_NAME = NibbleTest; }; name = "Debug Universal"; }; - B6A53C23131B47DC00C9070F /* 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; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = xattr; - }; - name = "Debug Universal"; - }; B6A53C24131B47DC00C9070F /* 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; INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; PRODUCT_NAME = newfs_prodos; }; name = "Debug Universal"; }; - B6F3648211AB36260045E114 /* 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; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = xattr; - }; - name = Debug; - }; - B6F3648311AB36260045E114 /* Debug fuse */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_MODEL_TUNING = G5; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = xattr; - }; - name = "Debug fuse"; - }; - B6F3648411AB36260045E114 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_MODEL_TUNING = G5; - INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; - PRODUCT_NAME = xattr; - ZERO_LINK = NO; - }; - name = Release; - }; B6F3682711B431AC0045E114 /* 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; INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; PRODUCT_NAME = newfs_prodos; }; name = Debug; @@ -1362,10 +1366,8 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; PRODUCT_NAME = newfs_prodos; }; name = "Debug fuse"; @@ -1376,10 +1378,8 @@ ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; - PREBINDING = NO; PRODUCT_NAME = newfs_prodos; ZERO_LINK = NO; }; @@ -1388,7 +1388,7 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "PROFuseX" */ = { + 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "ProFUSE" */ = { isa = XCConfigurationList; buildConfigurations = ( 1DEB923608733DC60010E9CD /* Debug */, @@ -1399,6 +1399,16 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + B60BD4B21408702900329025 /* Build configuration list for PBXNativeTarget "xattr" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B60BD4B31408702900329025 /* Debug */, + B60BD4B41408702900329025 /* Debug Universal */, + B60BD4B51408702900329025 /* Debug fuse */, + B60BD4B61408702900329025 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; B63EFCEC11A36CB800C90DCE /* Build configuration list for PBXNativeTarget "apfm" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -1454,17 +1464,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - B6F3648911AB36590045E114 /* Build configuration list for PBXNativeTarget "xattr" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B6F3648211AB36260045E114 /* Debug */, - B6A53C23131B47DC00C9070F /* Debug Universal */, - B6F3648311AB36260045E114 /* Debug fuse */, - B6F3648411AB36260045E114 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; B6F3684111B432000045E114 /* Build configuration list for PBXNativeTarget "newfs_prodos" */ = { isa = XCConfigurationList; buildConfigurations = ( From 9ad93a51a7579f7109f117e3dd378a47830e1f8f Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 29 Jan 2012 04:42:35 +0000 Subject: [PATCH 233/236] fix clang analyzer issues git-svn-id: https://profuse.googlecode.com/svn/branches/v2@401 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/SDKImage.cpp | 2 +- bin/newfs_pascal.cpp | 2 +- bin/xattr.cpp | 29 +++++++++++++++++++++-------- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/Device/SDKImage.cpp b/Device/SDKImage.cpp index 17b726f..562c534 100644 --- a/Device/SDKImage.cpp +++ b/Device/SDKImage.cpp @@ -70,7 +70,7 @@ static record_thread FindDiskImageThread(NuArchive *archive) { const NuThread *thread = NuGetThread(record, i); - if (NuGetThreadID(thread) == kNuThreadIDDiskImage) + if (thread && NuGetThreadID(thread) == kNuThreadIDDiskImage) { rt.thread_index = thread->threadIdx; rt.record_index = record->recordIdx; diff --git a/bin/newfs_pascal.cpp b/bin/newfs_pascal.cpp index fb08a2b..3879d15 100644 --- a/bin/newfs_pascal.cpp +++ b/bin/newfs_pascal.cpp @@ -212,7 +212,7 @@ int main(int argc, char **argv) { struct stat st; - bool rawDevice; + bool rawDevice = false; BlockDevicePointer device; VolumeEntryPointer volume; diff --git a/bin/xattr.cpp b/bin/xattr.cpp index 89a0b3a..4dec48f 100644 --- a/bin/xattr.cpp +++ b/bin/xattr.cpp @@ -17,6 +17,19 @@ typedef std::vector::iterator vsiter; +// prototypes to shut up clang. + +void hexdump(const uint8_t *data, ssize_t size); +ssize_t get_attr_list(const char * fname, std::vector &out); +void dumpxattr(const char *file, const char *attr); +int op_list(int argc, char **argv); +int op_dump(int argc, char **argv); +int op_read(int argc, char **argv); +ssize_t read_all(int fd, std::vector &out); +int op_write(int argc, char **argv); +void usage(const char *name); + + #ifdef __APPLE__ // apple has additional parameter for position and options. @@ -165,7 +178,7 @@ char *buffer; * list a file's attributes (and size) * */ -int list(int argc, char **argv) +int op_list(int argc, char **argv) { const char *fname = *argv; @@ -217,7 +230,7 @@ int list(int argc, char **argv) * hexdump a file's attributes. * */ -int dump(int argc, char **argv) +int op_dump(int argc, char **argv) { const char *fname = *argv; @@ -250,7 +263,7 @@ int dump(int argc, char **argv) // must specify the xattr name. -int read(int argc, char **argv) +int op_read(int argc, char **argv) { if (argc != 2) @@ -339,7 +352,7 @@ ssize_t read_all(int fd, std::vector &out) // xattr write filename attrname // stdin -> filename:attrname -int write(int argc, char **argv) +int op_write(int argc, char **argv) { std::vector buffer; @@ -401,11 +414,11 @@ int main(int argc, char **argv) { if (argc < 3) usage(*argv); - if (std::strcmp(argv[1], "list") == 0) return list(argc - 2, argv + 2); - if (std::strcmp(argv[1], "dump") == 0) return dump(argc - 2, argv + 2); + if (std::strcmp(argv[1], "list") == 0) return op_list(argc - 2, argv + 2); + if (std::strcmp(argv[1], "dump") == 0) return op_dump(argc - 2, argv + 2); - if (std::strcmp(argv[1], "read") == 0) return read(argc - 2, argv + 2); - if (std::strcmp(argv[1], "write") == 0) return write(argc - 2, argv + 2); + if (std::strcmp(argv[1], "read") == 0) return op_read(argc - 2, argv + 2); + if (std::strcmp(argv[1], "write") == 0) return op_write(argc - 2, argv + 2); usage(*argv); From 818ab5f6021b7babd8e7089d88d76491088e31be Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sun, 29 Jan 2012 05:33:16 +0000 Subject: [PATCH 234/236] fix bug when adding new file (apfm put) git-svn-id: https://profuse.googlecode.com/svn/branches/v2@402 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/VolumeEntry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index 07e3453..708b080 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -600,7 +600,7 @@ FileEntryPointer VolumeEntry::create(const char *name, unsigned blocks) { FileEntryPointer e = *iter; - unsigned freeSpace = e->_firstBlock - _lastBlock; + unsigned freeSpace = e->_firstBlock - lastBlock; // this could do something stupid like selecting a slot with only 1 free block but too bad. if (freeSpace < blocks) From 25ad5cf7f596167f80b89eec7c4cb100060bf6c8 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 31 Aug 2012 00:17:35 +0000 Subject: [PATCH 235/236] exception::what() const throw() git-svn-id: https://profuse.googlecode.com/svn/branches/v2@403 aa027e90-d47c-11dd-86d7-074df07e0730 --- Common/Exception.cpp | 2 +- Common/Exception.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Common/Exception.cpp b/Common/Exception.cpp index 5295312..ea79889 100644 --- a/Common/Exception.cpp +++ b/Common/Exception.cpp @@ -33,7 +33,7 @@ Exception::~Exception() throw() { } -const char *Exception::what() +const char *Exception::what() const throw() { return _string.c_str(); } diff --git a/Common/Exception.h b/Common/Exception.h index 3377cac..d55eed3 100644 --- a/Common/Exception.h +++ b/Common/Exception.h @@ -14,7 +14,7 @@ public: virtual ~Exception() throw (); - virtual const char *what(); + virtual const char *what() const throw(); virtual const char *errorString(); int error() const { return _error; } From d4a7107bde22dd7610f0c04f4af7224c984a5277 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 31 Aug 2012 00:20:20 +0000 Subject: [PATCH 236/236] some NuFX code not yet checked in git-svn-id: https://profuse.googlecode.com/svn/branches/v2@404 aa027e90-d47c-11dd-86d7-074df07e0730 --- NuFX/DirectoryEntry.cpp | 63 +++++++++++++++++++++++++++++++++++++ NuFX/DirectoryEntry.h | 38 +++++++++++++++++++++++ NuFX/Entry.cpp | 66 +++++++++++++++++++++++++++++++++++++++ NuFX/Entry.h | 69 +++++++++++++++++++++++++++++++++++++++++ NuFX/FileEntry.h | 23 ++++++++++++++ NuFX/VolumeEntry.cpp | 14 +++++++++ NuFX/VolumeEntry.h | 35 +++++++++++++++++++++ 7 files changed, 308 insertions(+) create mode 100644 NuFX/DirectoryEntry.cpp create mode 100644 NuFX/DirectoryEntry.h create mode 100644 NuFX/Entry.cpp create mode 100644 NuFX/Entry.h create mode 100644 NuFX/FileEntry.h create mode 100644 NuFX/VolumeEntry.cpp create mode 100644 NuFX/VolumeEntry.h diff --git a/NuFX/DirectoryEntry.cpp b/NuFX/DirectoryEntry.cpp new file mode 100644 index 0000000..cc99cef --- /dev/null +++ b/NuFX/DirectoryEntry.cpp @@ -0,0 +1,63 @@ +#include "DirectoryEntry.h" + +#include + +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]; +} diff --git a/NuFX/DirectoryEntry.h b/NuFX/DirectoryEntry.h new file mode 100644 index 0000000..abcffb5 --- /dev/null +++ b/NuFX/DirectoryEntry.h @@ -0,0 +1,38 @@ +#ifndef __NUFX_DIRECTORYENTRY_H__ +#define __NUFX_DIRECTORYENTRY_H__ + +#include "Entry.h" + +#include +#include + +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 _children; + + typedef std::vector::iterator EntryIterator; + + }; +} + + +#endif \ No newline at end of file diff --git a/NuFX/Entry.cpp b/NuFX/Entry.cpp new file mode 100644 index 0000000..3f8408e --- /dev/null +++ b/NuFX/Entry.cpp @@ -0,0 +1,66 @@ +#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; +} diff --git a/NuFX/Entry.h b/NuFX/Entry.h new file mode 100644 index 0000000..20c8320 --- /dev/null +++ b/NuFX/Entry.h @@ -0,0 +1,69 @@ +#ifndef __NUFX_ENTRY_H__ +#define __NUFX_ENTRY_H__ + + +#include + +#include +#include + + +#include +#include +#include +#include + +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 \ No newline at end of file diff --git a/NuFX/FileEntry.h b/NuFX/FileEntry.h new file mode 100644 index 0000000..0963319 --- /dev/null +++ b/NuFX/FileEntry.h @@ -0,0 +1,23 @@ +#ifndef __NUFX_FILEENTRY_H__ +#define __NUFX_FILEENTRY_H__ + +#include "Entry.h" +#include + +namespace NuFX { + + + class FileEntry : public Entry + { + public: + + private: + + NuRecordIdx _recordID; + unsigned _flags; // threads + size_t _size; // data size + }; +} + + +#endif \ No newline at end of file diff --git a/NuFX/VolumeEntry.cpp b/NuFX/VolumeEntry.cpp new file mode 100644 index 0000000..116e2bb --- /dev/null +++ b/NuFX/VolumeEntry.cpp @@ -0,0 +1,14 @@ +#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; +} \ No newline at end of file diff --git a/NuFX/VolumeEntry.h b/NuFX/VolumeEntry.h new file mode 100644 index 0000000..540dbaa --- /dev/null +++ b/NuFX/VolumeEntry.h @@ -0,0 +1,35 @@ +#ifndef __NUFX_VOLUMEENTRY_H__ +#define __NUFX_VOLUMEENTRY_H__ + +#include "DirectoryEntry.h" + +#include + +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 _inodeIndex; + }; +} + + +#endif \ No newline at end of file