2009-11-21 03:37:02 +00:00
|
|
|
|
2009-11-24 04:36:48 +00:00
|
|
|
#include <sys/ioctl.h>
|
2009-11-21 03:37:02 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/uio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2009-11-24 04:46:29 +00:00
|
|
|
#include <cerrno>
|
2009-11-21 03:37:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef __APPLE__
|
|
|
|
#include <sys/disk.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __LINUX__
|
|
|
|
#include <sys/mount.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __SUN__
|
|
|
|
#include <sys/dkio.h>
|
|
|
|
#endif
|
|
|
|
|
2009-12-16 01:33:28 +00:00
|
|
|
#include <Device/RawDevice.h>
|
2009-11-21 03:37:02 +00:00
|
|
|
|
2009-12-16 01:33:28 +00:00
|
|
|
#include <ProFUSE/Exception.h>
|
2009-11-21 03:37:02 +00:00
|
|
|
|
2009-12-16 01:33:28 +00:00
|
|
|
using namespace Device;
|
|
|
|
|
|
|
|
using ProFUSE::Exception;
|
|
|
|
using ProFUSE::POSIXException;
|
2009-11-21 03:37:02 +00:00
|
|
|
|
|
|
|
#ifdef __SUN__
|
|
|
|
void RawDevice::devSize(int fd)
|
|
|
|
{
|
|
|
|
#undef __METHOD__
|
|
|
|
#define __METHOD__ "RawDevice::devSize"
|
|
|
|
|
|
|
|
struct dk_minfo minfo;
|
|
|
|
|
|
|
|
if (::ioctl(fd, DKIOCGMEDIAINFO, &minfo) < 0)
|
2009-12-02 01:19:34 +00:00
|
|
|
throw POSIXException(__METHOD__ ": Unable to determine device size.", errno);
|
2009-11-21 03:37:02 +00:00
|
|
|
|
|
|
|
_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)
|
2009-12-02 01:19:34 +00:00
|
|
|
throw POSIXException(__METHOD__ ": Unable to determine block size.", errno);
|
2009-11-21 03:37:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (::ioctl(fd, DKIOCGETBLOCKCOUNT, &blockCount) < 0)
|
2009-12-02 01:19:34 +00:00
|
|
|
throw POSIXException(__METHOD__ ": Unable to determine block count.", errno);
|
2009-11-21 03:37:02 +00:00
|
|
|
|
|
|
|
_blockSize = blockSize;
|
2009-11-24 04:46:29 +00:00
|
|
|
_size = _blockSize * blockCount;
|
2009-11-21 03:37:02 +00:00
|
|
|
_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)
|
2009-12-02 01:19:34 +00:00
|
|
|
throw POSIXException(__METHOD__ ": Unable to determine device size.", errno);
|
2009-11-21 03:37:02 +00:00
|
|
|
|
|
|
|
_size = 512 * blocks;
|
|
|
|
_blockSize = 512; //
|
|
|
|
_blocks = blocks;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2009-11-24 04:36:48 +00:00
|
|
|
// TODO -- FreeBSD/NetBSD/OpenBSD
|
|
|
|
|
2010-05-19 23:47:48 +00:00
|
|
|
RawDevice::RawDevice(const char *name, bool readOnly) :
|
|
|
|
_file(name, readOnly)
|
2009-11-21 03:37:02 +00:00
|
|
|
{
|
2009-11-24 04:46:29 +00:00
|
|
|
#undef __METHOD__
|
|
|
|
#define __METHOD__ "RawDevice::RawDevice"
|
|
|
|
|
|
|
|
|
2010-05-19 23:47:48 +00:00
|
|
|
if (!_file.isValid())
|
|
|
|
{
|
|
|
|
throw new Exception(__METHOD__ ": Invalid file handle.");
|
|
|
|
}
|
|
|
|
|
|
|
|
_readOnly = readOnly;
|
|
|
|
_size = 0;
|
|
|
|
_blocks = 0;
|
|
|
|
_blockSize = 0;
|
|
|
|
|
|
|
|
|
|
|
|
devSize(_file.fd());
|
|
|
|
}
|
2009-11-24 04:46:29 +00:00
|
|
|
|
2010-05-19 23:47:48 +00:00
|
|
|
RawDevice::RawDevice(File& file, bool readOnly) :
|
|
|
|
_file(file)
|
|
|
|
{
|
|
|
|
#undef __METHOD__
|
|
|
|
#define __METHOD__ "RawDevice::RawDevice"
|
|
|
|
|
2009-11-21 03:37:02 +00:00
|
|
|
|
2010-05-19 23:47:48 +00:00
|
|
|
if (!_file.isValid())
|
2009-11-24 04:46:29 +00:00
|
|
|
{
|
2010-05-19 23:47:48 +00:00
|
|
|
throw new Exception(__METHOD__ ": Invalid file handle.");
|
2009-11-24 04:46:29 +00:00
|
|
|
}
|
2010-05-19 23:47:48 +00:00
|
|
|
|
2009-11-21 03:37:02 +00:00
|
|
|
_readOnly = readOnly;
|
|
|
|
_size = 0;
|
|
|
|
_blocks = 0;
|
|
|
|
_blockSize = 0;
|
|
|
|
|
|
|
|
|
2010-05-19 23:47:48 +00:00
|
|
|
devSize(_file.fd());
|
2009-11-21 03:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RawDevice::~RawDevice()
|
|
|
|
{
|
2010-05-19 23:47:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RawDevice *RawDevice::Open(const char *name, bool readOnly)
|
|
|
|
{
|
|
|
|
return new RawDevice(name, readOnly);
|
2009-11-21 03:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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) ?
|
|
|
|
|
2009-12-21 13:57:48 +00:00
|
|
|
off_t offset = block * 512;
|
2010-05-19 23:47:48 +00:00
|
|
|
size_t ok = ::pread(_file.fd(), bp, 512, offset);
|
2009-11-21 03:37:02 +00:00
|
|
|
|
|
|
|
// TODO -- EINTR?
|
|
|
|
if (ok != 512)
|
2009-12-02 01:19:34 +00:00
|
|
|
throw ok < 0
|
|
|
|
? POSIXException(__METHOD__ ": Error reading block.", errno)
|
|
|
|
: Exception(__METHOD__ ": Error reading block.");
|
2009-12-21 13:57:48 +00:00
|
|
|
}
|
2009-12-02 01:19:34 +00:00
|
|
|
|
2009-12-21 13:57:48 +00:00
|
|
|
|
|
|
|
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;
|
2010-05-19 23:47:48 +00:00
|
|
|
size_t ok = ::pread(_file.fd(), bp, 256, offset);
|
2009-11-21 03:37:02 +00:00
|
|
|
|
2009-12-21 13:57:48 +00:00
|
|
|
// TODO -- EINTR?
|
|
|
|
if (ok != 256)
|
|
|
|
throw ok < 0
|
|
|
|
? POSIXException(__METHOD__ ": Error reading block.", errno)
|
|
|
|
: Exception(__METHOD__ ": Error reading block.");
|
2009-11-21 03:37:02 +00:00
|
|
|
}
|
2009-12-21 13:57:48 +00:00
|
|
|
|
|
|
|
|
2009-11-21 03:37:02 +00:00
|
|
|
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.");
|
|
|
|
|
2009-12-21 13:57:48 +00:00
|
|
|
|
|
|
|
off_t offset = block * 512;
|
2010-05-19 23:47:48 +00:00
|
|
|
size_t ok = ::pwrite(_file.fd(), bp, 512, offset);
|
2009-11-21 03:37:02 +00:00
|
|
|
|
|
|
|
if (ok != 512)
|
2009-12-02 01:19:34 +00:00
|
|
|
throw ok < 0
|
|
|
|
? POSIXException(__METHOD__ ": Error writing block.", errno)
|
|
|
|
: Exception(__METHOD__ ": Error writing block.");
|
2009-11-21 03:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-21 13:57:48 +00:00
|
|
|
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;
|
2010-05-19 23:47:48 +00:00
|
|
|
size_t ok = ::pwrite(_file.fd(), bp, 256, offset);
|
2009-12-21 13:57:48 +00:00
|
|
|
|
|
|
|
if (ok != 256)
|
|
|
|
throw ok < 0
|
|
|
|
? POSIXException(__METHOD__ ": Error writing block.", errno)
|
|
|
|
: Exception(__METHOD__ ": Error writing block.");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-21 03:37:02 +00:00
|
|
|
bool RawDevice::readOnly()
|
|
|
|
{
|
|
|
|
return _readOnly;
|
|
|
|
}
|
|
|
|
|
2009-12-21 13:57:48 +00:00
|
|
|
bool RawDevice::mapped()
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-05-19 23:47:48 +00:00
|
|
|
|
|
|
|
unsigned RawDevice::blocks()
|
|
|
|
{
|
|
|
|
return _blocks;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-21 03:37:02 +00:00
|
|
|
void RawDevice::sync()
|
|
|
|
{
|
|
|
|
#undef __METHOD__
|
|
|
|
#define __METHOD__ "RawDevice::sync"
|
|
|
|
|
|
|
|
if (_readOnly) return;
|
|
|
|
|
2010-05-19 23:47:48 +00:00
|
|
|
if (::fsync(_file.fd()) < 0)
|
2009-12-02 01:19:34 +00:00
|
|
|
throw POSIXException(__METHOD__ ": fsync error.", errno);
|
2009-11-21 03:37:02 +00:00
|
|
|
}
|