From ebb502b1f5c931fc3651da733dd7424971fe9ace Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 21 Nov 2009 03:37:02 +0000 Subject: [PATCH] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@70 aa027e90-d47c-11dd-86d7-074df07e0730 --- RawDevice.cpp | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++ RawDevice.h | 40 ++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 RawDevice.cpp create mode 100644 RawDevice.h diff --git a/RawDevice.cpp b/RawDevice.cpp new file mode 100644 index 0000000..4c83ed3 --- /dev/null +++ b/RawDevice.cpp @@ -0,0 +1,174 @@ + +#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); +} \ No newline at end of file diff --git a/RawDevice.h b/RawDevice.h new file mode 100644 index 0000000..b2f5bc7 --- /dev/null +++ b/RawDevice.h @@ -0,0 +1,40 @@ +#ifndef __RAWDEVICE_H__ +#define __RAWDEVICE_H__ + +#include + +#include "BlockDevice.h" + +namespace ProFUSE { + +// /dev/xxx + + +class RawDevice : BlockDevice { +public: + + RawDevice(const char *name, bool readOnly); + + virtual ~RawDevice(); + + virtual void read(unsigned block, void *bp); + virtual void write(unsigned block, const void *bp); + + virtual bool readOnly(); + virtual void sync(); + +private: + + void devSize(int fd); + + int _fd; + bool _readOnly; + + uint64_t _size; + unsigned _blocks; + + unsigned _blockSize; +} + + +#endif