#include #include #include #include #include #ifdef __APPLE__ #include #endif #ifdef __LINUX__ #include #endif #ifdef __SUN__ #include #endif #include "RawDevice.h" #include "auto.h" #include "Exception.h" using Namespace ProFUSE; #ifdef __SUN__ void RawDevice::devSize(int fd) { #undef __METHOD__ #define __METHOD__ "RawDevice::devSize" struct dk_minfo minfo; if (::ioctl(fd, DKIOCGMEDIAINFO, &minfo) < 0) throw Exception(__METHOD__ ": Unable to determine device size.", errno); _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) throw Exception(__METHOD__ ": Unable to determine block size.", errno); if (::ioctl(fd, DKIOCGETBLOCKCOUNT, &blockCount) < 0) throw Exception(__METHOD__ ": Unable to determine block count.", errno); _blockSize = blockSize; _size = _blockSize * _blockCount; _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) throw Exception(__METHOD__ ": Unable to determine device size.", errno); _size = 512 * blocks; _blockSize = 512; // _blocks = blocks; } #endif RawDevice::RawDevice(const char *name, bool readOnly) : { // open read-only, verify if device is readable, and then try to upgrade to read/write? auto_fd fd(::open(name, readOnly ? O_RDONLY : O_RDWR)); if (fd < 0) throw Exception(__METHOD__ ": Unable to open device.", errno); _fd = -1; _readOnly = readOnly; _size = 0; _blocks = 0; _blockSize = 0; devSize(fd); _fd = fd.release(); } RawDevice::~RawDevice() { if (_fd >= 0) ::close(_fd); } 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) ? size_t ok = ::pread(_fd, bp, 512, block * 512); // TODO -- EINTR? if (ok != 512) throw Exception(__METHOD__ : ": Error reading block.", ok < 0 : errno, 0); } 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."); size_t ok = ::pwrite(_fd, bp, 512, block * 512); if (ok != 512) throw Exception(__METHOD__ : ": Error writing block.", ok < 0 : errno, 0); } bool RawDevice::readOnly() { return _readOnly; } void RawDevice::sync() { #undef __METHOD__ #define __METHOD__ "RawDevice::sync" if (_readOnly) return; if (::fsync(_fd) < 0) throw Exception(__METHOD__ ": msync error.", errno); }