mirror of
https://github.com/ksherlock/profuse.git
synced 2024-06-06 21:29:30 +00:00
git-svn-id: https://profuse.googlecode.com/svn/branches/v2@214 aa027e90-d47c-11dd-86d7-074df07e0730
This commit is contained in:
parent
33f209690e
commit
bcf6cd3890
77
Device/Adaptor.cpp
Normal file
77
Device/Adaptor.cpp
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <Device/Adaptor.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
45
Device/Adaptor.h
Normal file
45
Device/Adaptor.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#ifndef __DEVICE_ADAPTOR_H__
|
||||||
|
#define __DEVICE_ADAPTOR_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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
|
|
@ -8,7 +8,8 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <Device/DavexDiskImage.h>
|
#include <Device/DavexDiskImage.h>
|
||||||
#include <Device/MappedFile.h>
|
#include <File/MappedFile.h>
|
||||||
|
#include <Device/Adaptor.h>
|
||||||
|
|
||||||
#include <Endian/Endian.h>
|
#include <Endian/Endian.h>
|
||||||
#include <Endian/IOBuffer.h>
|
#include <Endian/IOBuffer.h>
|
||||||
|
@ -26,16 +27,21 @@ using ProFUSE::POSIXException;
|
||||||
|
|
||||||
static const char *IdentityCheck = "\x60VSTORE [Davex]\x00";
|
static const char *IdentityCheck = "\x60VSTORE [Davex]\x00";
|
||||||
|
|
||||||
|
/*
|
||||||
DavexDiskImage::DavexDiskImage(const char *name, bool readOnly) :
|
DavexDiskImage::DavexDiskImage(const char *name, bool readOnly) :
|
||||||
DiskImage(name, readOnly)
|
DiskImage(name, readOnly)
|
||||||
{
|
{
|
||||||
Validate(file());
|
Validate(file());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// private, validation already performed.
|
// private, validation already performed.
|
||||||
DavexDiskImage::DavexDiskImage(MappedFile *f) :
|
DavexDiskImage::DavexDiskImage(MappedFile *file) :
|
||||||
DiskImage(f)
|
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__
|
#undef __METHOD__
|
||||||
#define __METHOD__ "DavexDiskImage::Validate"
|
#define __METHOD__ "DavexDiskImage::Validate"
|
||||||
|
|
||||||
size_t size = f->fileSize();
|
size_t size = f->length();
|
||||||
const void * data = f->fileData();
|
const void * data = f->address();
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
unsigned blocks = (size / 512) - 1;
|
unsigned blocks = (size / 512) - 1;
|
||||||
|
|
||||||
|
@ -80,10 +86,6 @@ void DavexDiskImage::Validate(MappedFile *f)
|
||||||
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
throw Exception(__METHOD__ ": Invalid file format.");
|
throw Exception(__METHOD__ ": Invalid file format.");
|
||||||
|
|
||||||
f->reset();
|
|
||||||
f->setBlocks(blocks);
|
|
||||||
f->setOffset(512);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DavexDiskImage *DavexDiskImage::Open(MappedFile *file)
|
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);
|
MappedFile *file = new MappedFile(name, blocks * 512 + 512);
|
||||||
|
|
||||||
data = (uint8_t *)file->fileData();
|
data = (uint8_t *)file->address();
|
||||||
|
|
||||||
header.writeBytes(IdentityCheck, 16);
|
header.writeBytes(IdentityCheck, 16);
|
||||||
// file Format
|
// file Format
|
||||||
|
@ -152,10 +154,8 @@ DavexDiskImage *DavexDiskImage::Create(const char *name, size_t blocks, const ch
|
||||||
header.setOffset(512, true);
|
header.setOffset(512, true);
|
||||||
|
|
||||||
|
|
||||||
std::memcpy(file->fileData(), header.buffer(), 512);
|
std::memcpy(file->address(), header.buffer(), 512);
|
||||||
file->sync();
|
file->sync();
|
||||||
|
|
||||||
file->setOffset(512);
|
|
||||||
file->setBlocks(blocks);
|
|
||||||
return new DavexDiskImage(file);
|
return new DavexDiskImage(file);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <Device/BlockDevice.h>
|
#include <Device/BlockDevice.h>
|
||||||
|
#include <Device/DiskImage.h>
|
||||||
|
|
||||||
|
|
||||||
namespace Device {
|
namespace Device {
|
||||||
|
|
||||||
|
@ -12,7 +14,6 @@ namespace Device {
|
||||||
class DavexDiskImage : public DiskImage {
|
class DavexDiskImage : public DiskImage {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DavexDiskImage(const char *, bool readOnly);
|
|
||||||
virtual ~DavexDiskImage();
|
virtual ~DavexDiskImage();
|
||||||
|
|
||||||
static DavexDiskImage *Create(const char *name, size_t blocks);
|
static DavexDiskImage *Create(const char *name, size_t blocks);
|
||||||
|
@ -22,6 +23,8 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
DavexDiskImage(const char *, bool readOnly);
|
||||||
|
|
||||||
DavexDiskImage(MappedFile *);
|
DavexDiskImage(MappedFile *);
|
||||||
static void Validate(MappedFile *);
|
static void Validate(MappedFile *);
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <Device/DiskCopy42Image.h>
|
#include <Device/DiskCopy42Image.h>
|
||||||
#include <Device/MappedFile.h>
|
|
||||||
|
|
||||||
#include <Endian/Endian.h>
|
#include <Endian/Endian.h>
|
||||||
#include <Endian/IOBuffer.h>
|
#include <Endian/IOBuffer.h>
|
||||||
|
@ -17,32 +16,45 @@ using namespace BigEndian;
|
||||||
using ProFUSE::Exception;
|
using ProFUSE::Exception;
|
||||||
using ProFUSE::POSIXException;
|
using ProFUSE::POSIXException;
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
oDataSize = 64,
|
||||||
|
oDataChecksum = 72,
|
||||||
|
oPrivate = 82,
|
||||||
|
oUserData = 84
|
||||||
|
};
|
||||||
|
|
||||||
DiskCopy42Image::DiskCopy42Image(MappedFile *f) :
|
DiskCopy42Image::DiskCopy42Image(MappedFile *f) :
|
||||||
DiskImage(f),
|
DiskImage(f),
|
||||||
_changed(false)
|
_changed(false)
|
||||||
{
|
{
|
||||||
|
setAdaptor(new POAdaptor(oUserData + (uint8_t *)f->address()));
|
||||||
|
setBlocks(Read32(f->address(), oDataSize) / 512);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
DiskCopy42Image::DiskCopy42Image(const char *name, bool readOnly) :
|
DiskCopy42Image::DiskCopy42Image(const char *name, bool readOnly) :
|
||||||
DiskImage(name, readOnly),
|
DiskImage(name, readOnly),
|
||||||
_changed(false)
|
_changed(false)
|
||||||
{
|
{
|
||||||
Validate(file());
|
Validate(file());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
DiskCopy42Image::~DiskCopy42Image()
|
DiskCopy42Image::~DiskCopy42Image()
|
||||||
{
|
{
|
||||||
if (_changed)
|
if (_changed)
|
||||||
{
|
{
|
||||||
MappedFile *f = file();
|
MappedFile *f = file();
|
||||||
void *data = f->fileData();
|
|
||||||
|
|
||||||
if (f)
|
if (f)
|
||||||
{
|
{
|
||||||
uint32_t cs = Checksum(f->offset() + (uint8_t *)data,
|
void *data = f->address();
|
||||||
f->blocks() * 512);
|
|
||||||
|
uint32_t cs = Checksum(oUserData + (uint8_t *)data, Read32(data, oDataSize));
|
||||||
|
|
||||||
Write32(data, 72, cs);
|
Write32(data, oDataChecksum, cs);
|
||||||
f->sync();
|
f->sync();
|
||||||
}
|
}
|
||||||
// TODO -- checksum
|
// 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)
|
DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks, const char *vname)
|
||||||
{
|
{
|
||||||
MappedFile *file = new MappedFile(name, blocks * 512 + 84);
|
MappedFile *file = new MappedFile(name, blocks * 512 + oUserData);
|
||||||
file->setOffset(84);
|
|
||||||
file->setBlocks(blocks);
|
|
||||||
|
|
||||||
uint8_t tmp[84];
|
|
||||||
IOBuffer header(tmp, 84);
|
uint8_t tmp[oUserData];
|
||||||
|
IOBuffer header(tmp, oUserData);
|
||||||
|
|
||||||
// name -- 64byte pstring.
|
// 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.writeBytes(vname, std::min(l, 63u));
|
||||||
|
|
||||||
//header.resize(64);
|
//header.resize(64);
|
||||||
header.setOffset(64, true);
|
header.setOffset(oDataSize, true);
|
||||||
|
|
||||||
// data size -- number of bytes
|
// data size -- number of bytes
|
||||||
header.write32(blocks * 512);
|
header.write32(blocks * 512);
|
||||||
|
@ -152,7 +164,7 @@ DiskCopy42Image *DiskCopy42Image::Create(const char *name, size_t blocks, const
|
||||||
// private
|
// private
|
||||||
header.write16(0x100);
|
header.write16(0x100);
|
||||||
|
|
||||||
std::memcpy(file->fileData(), header.buffer(), 84);
|
std::memcpy(file->address(), header.buffer(), oUserData);
|
||||||
file->sync();
|
file->sync();
|
||||||
|
|
||||||
return new DiskCopy42Image(file);
|
return new DiskCopy42Image(file);
|
||||||
|
@ -164,29 +176,29 @@ void DiskCopy42Image::Validate(MappedFile *file)
|
||||||
#define __METHOD__ "DiskCopy42Image::Validate"
|
#define __METHOD__ "DiskCopy42Image::Validate"
|
||||||
|
|
||||||
size_t bytes = 0;
|
size_t bytes = 0;
|
||||||
size_t size = file->fileSize();
|
size_t size = file->length();
|
||||||
const void *data = file->fileData();
|
const void *data = file->address();
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
uint32_t checksum = 0;
|
uint32_t checksum = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (size < 84) break;
|
if (size < oUserData) break;
|
||||||
|
|
||||||
// name must be < 64
|
// name must be < 64
|
||||||
if (Read8(data, 0) > 63) break;
|
if (Read8(data, 0) > 63) break;
|
||||||
|
|
||||||
if (Read32(data, 82) != 0x100)
|
if (Read32(data, oPrivate) != 0x100)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// bytes, not blocks.
|
// bytes, not blocks.
|
||||||
bytes = Read32(data, 64);
|
bytes = Read32(data, oDataSize);
|
||||||
|
|
||||||
if (bytes % 512) break;
|
if (bytes % 512) break;
|
||||||
|
|
||||||
if (size < 84 + bytes) break;
|
if (size < oUserData + bytes) break;
|
||||||
|
|
||||||
// todo -- checksum.
|
// todo -- checksum.
|
||||||
checksum = Read32(data, 72);
|
checksum = Read32(data, oDataChecksum);
|
||||||
|
|
||||||
ok = true;
|
ok = true;
|
||||||
} while (false);
|
} while (false);
|
||||||
|
@ -194,15 +206,13 @@ void DiskCopy42Image::Validate(MappedFile *file)
|
||||||
if (!ok)
|
if (!ok)
|
||||||
throw Exception(__METHOD__ ": Invalid file format.");
|
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)
|
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)
|
void DiskCopy42Image::write(unsigned block, const void *bp)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define __DISKCOPY42IMAGE_H__
|
#define __DISKCOPY42IMAGE_H__
|
||||||
|
|
||||||
#include <Device/BlockDevice.h>
|
#include <Device/BlockDevice.h>
|
||||||
|
#include <Device/DiskImage.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
@ -9,7 +10,6 @@ namespace Device {
|
||||||
|
|
||||||
class DiskCopy42Image : public DiskImage {
|
class DiskCopy42Image : public DiskImage {
|
||||||
public:
|
public:
|
||||||
DiskCopy42Image(const char *name, bool readOnly);
|
|
||||||
virtual ~DiskCopy42Image();
|
virtual ~DiskCopy42Image();
|
||||||
|
|
||||||
static DiskCopy42Image *Create(const char *name, size_t blocks);
|
static DiskCopy42Image *Create(const char *name, size_t blocks);
|
||||||
|
@ -24,6 +24,8 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
DiskCopy42Image(const char *name, bool readOnly);
|
||||||
|
|
||||||
DiskCopy42Image(MappedFile *);
|
DiskCopy42Image(MappedFile *);
|
||||||
static void Validate(MappedFile *);
|
static void Validate(MappedFile *);
|
||||||
bool _changed;
|
bool _changed;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include <Device/DiskImage.h>
|
#include <Device/DiskImage.h>
|
||||||
#include <MappedFile.h>
|
#include <File/MappedFile.h>
|
||||||
|
|
||||||
#include <ProFUSE/Exception.h>
|
#include <ProFUSE/Exception.h>
|
||||||
|
|
||||||
|
@ -20,96 +20,6 @@ using ProFUSE::Exception;
|
||||||
using ProFUSE::POSIXException;
|
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) :
|
DiskImage::DiskImage(const char *name, bool readOnly)
|
||||||
_file(name, readOnly)
|
|
||||||
{
|
{
|
||||||
_offset = 0;
|
File fd(name, readOnly ? O_RDONLY : O_RDWR);
|
||||||
|
MappedFile mf(fd, readOnly);
|
||||||
|
_file.adopt(mf);
|
||||||
|
|
||||||
_blocks = 0;
|
_blocks = 0;
|
||||||
_readOnly = readOnly;
|
_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;
|
_blocks = 0;
|
||||||
_readOnly = readOnly;
|
_readOnly = file->readOnly();
|
||||||
_address = file.address();
|
_adaptor = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DiskImage::~DiskImage()
|
DiskImage::~DiskImage()
|
||||||
{
|
{
|
||||||
delete _file;
|
delete _adaptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DiskImage::readOnly()
|
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()
|
void DiskImage::sync()
|
||||||
{
|
{
|
||||||
#undef __METHOD__
|
#undef __METHOD__
|
||||||
#define __METHOD__ "DiskImage::sync"
|
#define __METHOD__ "DiskImage::sync"
|
||||||
|
|
||||||
if (_file) return _file.sync();
|
if (_file.isValid()) return _file.sync();
|
||||||
|
|
||||||
throw Exception(__METHOD__ ": File not set.");
|
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) :
|
ProDOSOrderDiskImage::ProDOSOrderDiskImage(const char *name, bool readOnly) :
|
||||||
DiskImage(name, readOnly)
|
DiskImage(name, readOnly)
|
||||||
{
|
{
|
||||||
Validate(file());
|
Validate(file());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
ProDOSOrderDiskImage::ProDOSOrderDiskImage(MappedFile *file) :
|
ProDOSOrderDiskImage::ProDOSOrderDiskImage(MappedFile *file) :
|
||||||
DiskImage(file)
|
DiskImage(file)
|
||||||
{
|
{
|
||||||
|
setBlocks(file->length() / 512);
|
||||||
|
setAdaptor(new POAdaptor(file->address()));
|
||||||
}
|
}
|
||||||
|
|
||||||
ProDOSOrderDiskImage *ProDOSOrderDiskImage::Create(const char *name, size_t blocks)
|
ProDOSOrderDiskImage *ProDOSOrderDiskImage::Create(const char *name, size_t blocks)
|
||||||
{
|
{
|
||||||
MappedFile *file = new MappedFile(name, blocks * 512);
|
MappedFile *file = MappedFile::Create(name, blocks * 512);
|
||||||
file->setBlocks(blocks);
|
|
||||||
return new ProDOSOrderDiskImage(file);
|
return new ProDOSOrderDiskImage(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,33 +181,34 @@ void ProDOSOrderDiskImage::Validate(MappedFile *f)
|
||||||
#undef __METHOD__
|
#undef __METHOD__
|
||||||
#define __METHOD__ "ProDOSOrderDiskImage::Validate"
|
#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)
|
if (size % 512)
|
||||||
throw Exception(__METHOD__ ": Invalid file format.");
|
throw Exception(__METHOD__ ": Invalid file format.");
|
||||||
|
|
||||||
f->reset();
|
|
||||||
f->setBlocks(size / 512);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
DOSOrderDiskImage::DOSOrderDiskImage(const char *name, bool readOnly) :
|
DOSOrderDiskImage::DOSOrderDiskImage(const char *name, bool readOnly) :
|
||||||
DiskImage(name, readOnly)
|
DiskImage(name, readOnly)
|
||||||
{
|
{
|
||||||
Validate(file());
|
Validate(file());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
DOSOrderDiskImage::DOSOrderDiskImage(MappedFile *file) :
|
DOSOrderDiskImage::DOSOrderDiskImage(MappedFile *file) :
|
||||||
DiskImage(file)
|
DiskImage(file)
|
||||||
{
|
{
|
||||||
|
setBlocks(file->length() / 512);
|
||||||
|
setAdaptor(new DOAdaptor(file->address()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DOSOrderDiskImage *DOSOrderDiskImage::Create(const char *name, size_t blocks)
|
DOSOrderDiskImage *DOSOrderDiskImage::Create(const char *name, size_t blocks)
|
||||||
{
|
{
|
||||||
MappedFile *file = new MappedFile(name, blocks * 512);
|
MappedFile *file = MappedFile::Create(name, blocks * 512);
|
||||||
file->setEncoding(MappedFile::DOSOrder);
|
|
||||||
file->setBlocks(blocks);
|
|
||||||
return new DOSOrderDiskImage(file);
|
return new DOSOrderDiskImage(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,14 +223,11 @@ void DOSOrderDiskImage::Validate(MappedFile *f)
|
||||||
#undef __METHOD__
|
#undef __METHOD__
|
||||||
#define __METHOD__ "DOSOrderDiskImage::Validate"
|
#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)
|
if (size % 512)
|
||||||
throw Exception(__METHOD__ ": Invalid file format.");
|
throw Exception(__METHOD__ ": Invalid file format.");
|
||||||
|
|
||||||
f->reset();
|
|
||||||
f->setEncoding(MappedFile::DOSOrder);
|
|
||||||
f->setBlocks(size / 512);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,13 @@
|
||||||
|
|
||||||
#include <Device/BlockDevice.h>
|
#include <Device/BlockDevice.h>
|
||||||
|
|
||||||
#include <MappedFile.h>
|
#include <Device/Adaptor.h>
|
||||||
|
|
||||||
|
#include <File/MappedFile.h>
|
||||||
|
|
||||||
namespace Device {
|
namespace Device {
|
||||||
|
|
||||||
|
|
||||||
class DiskImage : public BlockDevice {
|
class DiskImage : public BlockDevice {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -30,27 +32,21 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
||||||
DiskImage(MappedFile * = 0);
|
DiskImage(MappedFile *file = 0);
|
||||||
DiskImage(const char *name, bool readOnly);
|
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 setBlocks(unsigned blocks) { _blocks = blocks; }
|
||||||
void writeDO(unsigned block, const void *bp);
|
|
||||||
|
void setAdaptor(Adaptor *);
|
||||||
// readNib
|
|
||||||
// writeNib
|
void *address() const { return _file.address(); }
|
||||||
|
MappedFile *file() { return &_file; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
MappedFile _file;
|
MappedFile _file;
|
||||||
void *_address;
|
Adaptor *_adaptor;
|
||||||
uint32_t _offset;
|
|
||||||
|
|
||||||
bool _readOnly;
|
bool _readOnly;
|
||||||
unsigned _blocks;
|
unsigned _blocks;
|
||||||
|
@ -60,12 +56,14 @@ private:
|
||||||
class ProDOSOrderDiskImage : public DiskImage {
|
class ProDOSOrderDiskImage : public DiskImage {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ProDOSOrderDiskImage(const char *name, bool readOnly);
|
|
||||||
|
|
||||||
static ProDOSOrderDiskImage *Create(const char *name, size_t blocks);
|
static ProDOSOrderDiskImage *Create(const char *name, size_t blocks);
|
||||||
static ProDOSOrderDiskImage *Open(MappedFile *);
|
static ProDOSOrderDiskImage *Open(MappedFile *);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ProDOSOrderDiskImage(const char *name, bool readOnly);
|
||||||
|
|
||||||
|
|
||||||
ProDOSOrderDiskImage(MappedFile *);
|
ProDOSOrderDiskImage(MappedFile *);
|
||||||
static void Validate(MappedFile *);
|
static void Validate(MappedFile *);
|
||||||
};
|
};
|
||||||
|
@ -73,12 +71,13 @@ private:
|
||||||
class DOSOrderDiskImage : public DiskImage {
|
class DOSOrderDiskImage : public DiskImage {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DOSOrderDiskImage(const char *name, bool readOnly);
|
|
||||||
|
|
||||||
static DOSOrderDiskImage *Create(const char *name, size_t blocks);
|
static DOSOrderDiskImage *Create(const char *name, size_t blocks);
|
||||||
static DOSOrderDiskImage *Open(MappedFile *);
|
static DOSOrderDiskImage *Open(MappedFile *);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
DOSOrderDiskImage(const char *name, bool readOnly);
|
||||||
|
|
||||||
DOSOrderDiskImage(MappedFile *);
|
DOSOrderDiskImage(MappedFile *);
|
||||||
static void Validate(MappedFile *);
|
static void Validate(MappedFile *);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include <Device/UniversalDiskImage.h>
|
#include <Device/UniversalDiskImage.h>
|
||||||
#include <Device/MappedFile.h>
|
|
||||||
|
|
||||||
#include <Endian/Endian.h>
|
#include <Endian/Endian.h>
|
||||||
#include <Endian/IOBuffer.h>
|
#include <Endian/IOBuffer.h>
|
||||||
|
@ -12,6 +11,7 @@ using namespace LittleEndian;
|
||||||
using ProFUSE::Exception;
|
using ProFUSE::Exception;
|
||||||
using ProFUSE::POSIXException;
|
using ProFUSE::POSIXException;
|
||||||
|
|
||||||
|
/*
|
||||||
UniversalDiskImage::UniversalDiskImage(const char *name, bool readOnly) :
|
UniversalDiskImage::UniversalDiskImage(const char *name, bool readOnly) :
|
||||||
DiskImage(name, readOnly)
|
DiskImage(name, readOnly)
|
||||||
{
|
{
|
||||||
|
@ -21,11 +21,26 @@ UniversalDiskImage::UniversalDiskImage(const char *name, bool readOnly) :
|
||||||
// flags. bit 31 = locked.
|
// flags. bit 31 = locked.
|
||||||
_flags = Read32(data, 0x10);
|
_flags = Read32(data, 0x10);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
UniversalDiskImage::UniversalDiskImage(MappedFile *file) :
|
UniversalDiskImage::UniversalDiskImage(MappedFile *file) :
|
||||||
DiskImage(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)
|
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.
|
// comment offset, creator, reserved -- 0.
|
||||||
header.setOffset(64, true);
|
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);
|
return new UniversalDiskImage(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,8 +103,8 @@ void UniversalDiskImage::Validate(MappedFile *file)
|
||||||
#undef __METHOD__
|
#undef __METHOD__
|
||||||
#define __METHOD__ "UniversalDiskImage::Validate"
|
#define __METHOD__ "UniversalDiskImage::Validate"
|
||||||
|
|
||||||
const void *data = file->fileData();
|
const void *data = file->address();
|
||||||
size_t size = file->fileSize();
|
size_t size = file->length();
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
unsigned blocks = 0;
|
unsigned blocks = 0;
|
||||||
unsigned offset = 0;
|
unsigned offset = 0;
|
||||||
|
@ -103,6 +116,7 @@ void UniversalDiskImage::Validate(MappedFile *file)
|
||||||
if (std::memcmp(data, "2IMG", 4)) break;
|
if (std::memcmp(data, "2IMG", 4)) break;
|
||||||
|
|
||||||
// only prodos supported, for now...
|
// only prodos supported, for now...
|
||||||
|
// TODO -- Dos Order, Nibble support.
|
||||||
if (Read32(data, 0x0c) != 1) break;
|
if (Read32(data, 0x0c) != 1) break;
|
||||||
|
|
||||||
offset = Read32(data, 0x20);
|
offset = Read32(data, 0x20);
|
||||||
|
@ -119,9 +133,7 @@ void UniversalDiskImage::Validate(MappedFile *file)
|
||||||
if (!ok)
|
if (!ok)
|
||||||
throw Exception(__METHOD__ ": Invalid file format.");
|
throw Exception(__METHOD__ ": Invalid file format.");
|
||||||
|
|
||||||
file->reset();
|
|
||||||
file->setOffset(offset);
|
|
||||||
file->setBlocks(blocks);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
|
|
||||||
|
|
||||||
#include <Device/BlockDevice.h>
|
#include <Device/BlockDevice.h>
|
||||||
|
#include <Device/DiskImage.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace Device {
|
namespace Device {
|
||||||
|
|
||||||
class UniversalDiskImage : public DiskImage {
|
class UniversalDiskImage : public DiskImage {
|
||||||
public:
|
public:
|
||||||
UniversalDiskImage(const char *name, bool readOnly);
|
|
||||||
|
|
||||||
static UniversalDiskImage *Create(const char *name, size_t blocks);
|
static UniversalDiskImage *Create(const char *name, size_t blocks);
|
||||||
static UniversalDiskImage *Open(MappedFile *);
|
static UniversalDiskImage *Open(MappedFile *);
|
||||||
|
@ -17,6 +18,9 @@ public:
|
||||||
virtual bool readOnly();
|
virtual bool readOnly();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
UniversalDiskImage(const char *name, bool readOnly);
|
||||||
|
|
||||||
UniversalDiskImage(MappedFile *);
|
UniversalDiskImage(MappedFile *);
|
||||||
static void Validate(MappedFile *);
|
static void Validate(MappedFile *);
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,13 @@ class File {
|
||||||
File(const char *name, int flags);
|
File(const char *name, int flags);
|
||||||
~File();
|
~File();
|
||||||
|
|
||||||
|
bool isValid() const
|
||||||
|
{
|
||||||
|
return _fd >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
int fd() const { return _fd; }
|
int fd() const { return _fd; }
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
void adopt(File &f);
|
void adopt(File &f);
|
||||||
|
|
|
@ -13,47 +13,83 @@ MappedFile::MappedFile()
|
||||||
{
|
{
|
||||||
_length = -1;
|
_length = -1;
|
||||||
_address = MAP_FAILED;
|
_address = MAP_FAILED;
|
||||||
|
_readOnly = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MappedFile::MappedFile(MappedFile &mf)
|
MappedFile::MappedFile(MappedFile &mf)
|
||||||
{
|
{
|
||||||
_address = mf._address;
|
_address = mf._address;
|
||||||
_length = mf._length;
|
_length = mf._length;
|
||||||
|
_readOnly = mf._readOnly;
|
||||||
|
|
||||||
mf._address = MAP_FAILED;
|
mf._address = MAP_FAILED;
|
||||||
mf._length = -1;
|
mf._length = -1;
|
||||||
|
mf._readOnly = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MappedFile::MappedFile(File f, bool readOnly)
|
MappedFile::MappedFile(const File &f, bool readOnly, size_t size)
|
||||||
{
|
{
|
||||||
#undef __METHOD__
|
_length = -1;
|
||||||
#define __METHOD__ "MappedFile::MappedFile"
|
_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;
|
struct stat st;
|
||||||
|
|
||||||
// close enough
|
// close enough
|
||||||
if (f.fd() < 0)
|
if (f.fd() < 0)
|
||||||
throw POSIXException( __METHOD__, EBADF);
|
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,
|
_address = ::mmap(0, _length,
|
||||||
readOnly ? PROT_READ : PROT_READ | PROT_WRITE,
|
readOnly ? PROT_READ : PROT_READ | PROT_WRITE,
|
||||||
MAP_FILE | MAP_SHARED, f.fd(), 0);
|
MAP_FILE | MAP_SHARED, f.fd(), 0);
|
||||||
|
|
||||||
if (_address == MAP_FAILED)
|
if (_address == MAP_FAILED)
|
||||||
throw POSIXException(__METHOD__ ": mmap", errno);
|
throw POSIXException(__METHOD__ ": mmap", errno);
|
||||||
}
|
|
||||||
|
_readOnly = readOnly;
|
||||||
MappedFile::~MappedFile()
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,6 +106,7 @@ void MappedFile::close()
|
||||||
|
|
||||||
_address = MAP_FAILED;
|
_address = MAP_FAILED;
|
||||||
_length = -1;
|
_length = -1;
|
||||||
|
_readOnly = true;
|
||||||
|
|
||||||
if (::munmap(address, length) != 0)
|
if (::munmap(address, length) != 0)
|
||||||
throw POSIXException(__METHOD__ ": munmap", errno);
|
throw POSIXException(__METHOD__ ": munmap", errno);
|
||||||
|
@ -93,13 +130,39 @@ void MappedFile::adopt(MappedFile &mf)
|
||||||
close();
|
close();
|
||||||
_address = mf._address;
|
_address = mf._address;
|
||||||
_length = mf._length;
|
_length = mf._length;
|
||||||
|
_readOnly = mf._readOnly;
|
||||||
|
|
||||||
mf._address = MAP_FAILED;
|
mf._address = MAP_FAILED;
|
||||||
mf._length = -1;
|
mf._length = -1;
|
||||||
|
mf._readOnly = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MappedFile::swap(MappedFile &mf)
|
void MappedFile::swap(MappedFile &mf)
|
||||||
{
|
{
|
||||||
std::swap(_address, mf._address);
|
std::swap(_address, mf._address);
|
||||||
std::swap(_length, mf._length);
|
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);
|
||||||
}
|
}
|
|
@ -10,16 +10,26 @@ class MappedFile {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
MappedFile();
|
MappedFile();
|
||||||
MappedFile(File f, bool readOnly);
|
|
||||||
MappedFile(MappedFile&);
|
MappedFile(MappedFile&);
|
||||||
|
MappedFile(const File &f, bool readOnly, size_t size = -1);
|
||||||
|
MappedFile(const char *name, bool readOnly);
|
||||||
|
|
||||||
~MappedFile();
|
~MappedFile();
|
||||||
|
|
||||||
|
|
||||||
|
static MappedFile *Create(const char *name, size_t size);
|
||||||
|
|
||||||
|
bool isValid() const
|
||||||
|
{
|
||||||
|
return _address != MAP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
void sync();
|
void sync();
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
void *address() const { return _address; }
|
void *address() const { return _address; }
|
||||||
size_t length() const { return _length; }
|
size_t length() const { return _length; }
|
||||||
|
bool readOnly() const { return _readOnly; }
|
||||||
|
|
||||||
void swap(MappedFile &);
|
void swap(MappedFile &);
|
||||||
void adopt(MappedFile &);
|
void adopt(MappedFile &);
|
||||||
|
@ -28,8 +38,11 @@ class MappedFile {
|
||||||
|
|
||||||
MappedFile& operator=(MappedFile &);
|
MappedFile& operator=(MappedFile &);
|
||||||
|
|
||||||
|
void init(const File &f, bool readOnly, size_t size);
|
||||||
|
|
||||||
void *_address;
|
void *_address;
|
||||||
size_t _length;
|
size_t _length;
|
||||||
|
bool _readOnly;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user