git-svn-id: https://profuse.googlecode.com/svn/branches/v2@140 aa027e90-d47c-11dd-86d7-074df07e0730

This commit is contained in:
ksherlock 2009-12-11 02:04:27 +00:00
parent 922494caa6
commit e3b89b2201
5 changed files with 91 additions and 35 deletions

View File

@ -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); }
};

View File

@ -167,7 +167,7 @@ public:
enum {
OffsetLastMod = 0x12,
OffsetFileNameCaseFlag = 0x16
OffsetFileNameCaseFlag = 0x16,
OffsetBitmapPointer = 0x23,
OffsetTotalBlocks = 0x25

View File

@ -5,6 +5,7 @@ newfs_prodos: \
newfs_prodos.o \
Exception.o \
BlockDevice.o \
BlockCache.o \
UniversalDiskImage.o \
DiskCopy42Image.o \
DavexDiskImage.o \

View File

@ -2,6 +2,7 @@
#include "../auto.h"
#include "../Endian.h"
#include "../BlockDevice.h"
#include "../BlockCache.h"
#include <algorithm>
#include <cstring>
@ -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<FileEntry> 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<uint8_t> 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

View File

@ -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<FileEntry *> _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<unsigned> *_pageLength;
std::vector<unsigned> *_pageSize;
unsigned _fileSize;
};