From e3b89b22016022ab7642d85ae91d303a252f18a6 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Fri, 11 Dec 2009 02:04:27 +0000 Subject: [PATCH] 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; };