* Ever since I added O_NOCACHE to the flags BFS is using to open its

device, the read-only detection did not work anymore; I've now added
  handy methods to correctly check for this. This fixes bug #1829.
* Volume::Initialize() now also checks if the device could really be 
  opened read/write.
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24212 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-03-02 23:17:26 +00:00
parent 4715069375
commit e2fed6bae3

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2007, Axel Dörfler, axeld@pinc-software.de. * Copyright 2001-2008, Axel Dörfler, axeld@pinc-software.de.
* This file may be used under the terms of the MIT License. * This file may be used under the terms of the MIT License.
*/ */
@ -40,10 +40,16 @@ class DeviceOpener {
int Device() const { return fDevice; } int Device() const { return fDevice; }
int Mode() const { return fMode; } int Mode() const { return fMode; }
bool IsReadOnly() const { return _IsReadOnly(fMode); }
status_t GetSize(off_t *_size, uint32 *_blockSize = NULL); status_t GetSize(off_t *_size, uint32 *_blockSize = NULL);
private: private:
static bool _IsReadOnly(int mode)
{ return (mode & O_RWMASK) == O_RDONLY;}
static bool _IsReadWrite(int mode)
{ return (mode & O_RWMASK) == O_RDWR;}
int fDevice; int fDevice;
int fMode; int fMode;
void *fBlockCache; void *fBlockCache;
@ -82,7 +88,7 @@ DeviceOpener::Open(const char *device, int mode)
if (fDevice < 0) if (fDevice < 0)
fDevice = errno; fDevice = errno;
if (fDevice < 0 && mode == O_RDWR) { if (fDevice < 0 && _IsReadWrite(mode)) {
// try again to open read-only (don't rely on a specific error code) // try again to open read-only (don't rely on a specific error code)
return Open(device, O_RDONLY | O_NOCACHE); return Open(device, O_RDONLY | O_NOCACHE);
} }
@ -90,7 +96,7 @@ DeviceOpener::Open(const char *device, int mode)
if (fDevice >= 0) { if (fDevice >= 0) {
// opening succeeded // opening succeeded
fMode = mode; fMode = mode;
if (mode == O_RDWR) { if (_IsReadWrite(mode)) {
// check out if the device really allows for read/write access // check out if the device really allows for read/write access
device_geometry geometry; device_geometry geometry;
if (!ioctl(fDevice, B_GET_GEOMETRY, &geometry)) { if (!ioctl(fDevice, B_GET_GEOMETRY, &geometry)) {
@ -145,10 +151,9 @@ DeviceOpener::Keep()
} }
/** Returns the size of the device in bytes. It uses B_GET_GEOMETRY /*! Returns the size of the device in bytes. It uses B_GET_GEOMETRY
* to compute the size, or fstat() if that failed. to compute the size, or fstat() if that failed.
*/ */
status_t status_t
DeviceOpener::GetSize(off_t *_size, uint32 *_blockSize) DeviceOpener::GetSize(off_t *_size, uint32 *_blockSize)
{ {
@ -319,7 +324,7 @@ Volume::Mount(const char *deviceName, uint32 flags)
if (fDevice < B_OK) if (fDevice < B_OK)
RETURN_ERROR(fDevice); RETURN_ERROR(fDevice);
if (opener.Mode() == O_RDONLY) if (opener.IsReadOnly())
fFlags |= VOLUME_READ_ONLY; fFlags |= VOLUME_READ_ONLY;
// check if it's a regular file, and if so, disable the cache for the // check if it's a regular file, and if so, disable the cache for the
@ -513,8 +518,7 @@ Volume::UpdateLiveQueries(Inode *inode, const char *attribute, int32 type,
} }
/*! /*! Checks if there is a live query whose results depend on the presence
Checks if there is a live query whose results depend on the presence
or value of the specified attribute. or value of the specified attribute.
Don't use it if you already have all the data together to evaluate Don't use it if you already have all the data together to evaluate
the queries - it wouldn't safe you anything in this case. the queries - it wouldn't safe you anything in this case.
@ -595,6 +599,9 @@ Volume::Initialize(int fd, const char *name, uint32 blockSize,
if (opener.Device() < B_OK) if (opener.Device() < B_OK)
return B_BAD_VALUE; return B_BAD_VALUE;
if (opener.IsReadOnly())
return B_READ_ONLY_DEVICE;
fDevice = opener.Device(); fDevice = opener.Device();
uint32 deviceBlockSize; uint32 deviceBlockSize;