From bcf6cd3890606e69781507f176ad57466910d72e Mon Sep 17 00:00:00 2001 From: ksherlock Date: Tue, 18 May 2010 02:58:26 +0000 Subject: [PATCH] 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; };