Added a special disk device class, that is responsible for representing

files as disk devices. This will not only be great for testing the
file and partitioning system modules' writing capabilities, it will also
just be a nice feature to have.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3598 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2003-06-22 22:54:16 +00:00
parent cd902621dd
commit 17750c7774
2 changed files with 194 additions and 0 deletions

View File

@ -0,0 +1,42 @@
// KFileDiskDevice.h
#ifndef _K_FILE_DISK_DEVICE_H
#define _K_FILE_DISK_DEVICE_H
#include <OS.h>
#include "KDiskDevice.h"
namespace BPrivate {
namespace DiskDevice {
class KFileDiskDevice : public KDiskDevice {
public:
KFileDiskDevice(partition_id id = -1);
virtual ~KFileDiskDevice();
status_t SetTo(const char *filePath, const char *devicePath = NULL);
void Unset();
virtual status_t InitCheck() const;
// TODO: probably superfluous
const char *FilePath() const;
virtual KPartition *CreateShadowPartition();
// virtual void Dump(bool deep = true, int32 level = 0);
protected:
virtual status_t GetMediaStatus(status_t *mediaStatus);
virtual status_t GetGeometry(device_geometry *geometry);
private:
char *fFilePath;
};
} // namespace DiskDevice
} // namespace BPrivate
using BPrivate::DiskDevice::KFileDiskDevice;
#endif // _K_FILE_DISK_DEVICE_H

View File

@ -0,0 +1,152 @@
// KFileDiskDevice.cpp
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <Drivers.h>
#include <KDiskDeviceUtils.h>
#include <KFileDiskDevice.h>
static const char *kFileDevicesDir = "/dev/disk/virtual/files";
// constructor
KFileDiskDevice::KFileDiskDevice(partition_id id)
: KDiskDevice(id),
fFilePath(NULL)
{
}
// destructor
KFileDiskDevice::~KFileDiskDevice()
{
Unset();
}
// SetTo
status_t
KFileDiskDevice::SetTo(const char *filePath, const char *devicePath)
{
// check params
if (!filePath || strlen(filePath) > B_PATH_NAME_LENGTH
|| (devicePath && strlen(devicePath) > B_PATH_NAME_LENGTH)) {
return B_BAD_VALUE;
}
// normalize the file path
// TODO: For the time being, we get an absolute file name only.
char tmpFilePath[B_PATH_NAME_LENGTH];
if (filePath[0] != '/') {
int32 len = (int32)B_PATH_NAME_LENGTH - (int32)strlen(filePath) - 2;
if (len < 0)
return B_ERROR;
// prepend the current directory path
if (!getcwd(tmpFilePath, len))
return B_ERROR;
strcat(tmpFilePath, "/");
strcat(tmpFilePath, filePath);
filePath = tmpFilePath;
}
// check the file
struct stat st;
if (stat(filePath, &st) != 0)
return errno;
if (!S_ISREG(st.st_mode))
return B_BAD_VALUE;
// create the device, if requested
char tmpDevicePath[B_PATH_NAME_LENGTH];
if (!devicePath) {
// no device path: we shall create a new device entry
// create the device entry
// TODO: Now we simply create a link. Replace that with the
// respective kernel magic!
// make the file devices dir
if (mkdir(kFileDevicesDir, 0777) != 0) {
if (errno != B_FILE_EXISTS)
return errno;
}
// make the directory
sprintf(tmpDevicePath, "%s/%ld", kFileDevicesDir, ID());
if (mkdir(tmpDevicePath, 0777) != 0)
return errno;
// get the device path name
sprintf(tmpDevicePath, "%s/%ld/raw", kFileDevicesDir, ID());
devicePath = tmpDevicePath;
if (symlink(filePath, devicePath) != 0)
return errno;
}
status_t error = set_string(fFilePath, filePath);
if (error != B_OK)
return error;
return KDiskDevice::SetTo(devicePath);
}
// Unset
void
KFileDiskDevice::Unset()
{
free(fFilePath);
fFilePath = NULL;
}
// InitCheck
status_t
KFileDiskDevice::InitCheck() const
{
return KDiskDevice::InitCheck();
}
// FilePath
const char *
KFileDiskDevice::FilePath() const
{
return fFilePath;
}
// CreateShadowPartition
KPartition *
KFileDiskDevice::CreateShadowPartition()
{
// not implemented
return NULL;
}
// GetMediaStatus
status_t
KFileDiskDevice::GetMediaStatus(status_t *mediaStatus)
{
*mediaStatus = B_OK;
return B_OK;
}
// GetGeometry
status_t
KFileDiskDevice::GetGeometry(device_geometry *geometry)
{
// get the file size
struct stat st;
if (stat(fFilePath, &st) != 0)
return errno;
// default to 512 bytes block size
off_t size = st.st_size;
uint32 blockSize = 512;
// Optimally we have only 1 block per sector and only one head.
// Since we have only a uint32 for the cylinder count, this won't work
// for files > 2TB. So, we set the head count to the minimally possible
// value.
off_t blocks = size / blockSize;
uint32 heads = (blocks + ULONG_MAX - 1) / ULONG_MAX;
if (heads == 0)
heads = 1;
geometry->bytes_per_sector = blockSize;
geometry->sectors_per_track = 1;
geometry->cylinder_count = blocks / heads;
geometry->head_count = heads;
geometry->device_type = B_DISK; // TODO: Add a new constant.
geometry->removable = false;
geometry->read_only = false;
geometry->write_once = false;
return B_OK;
}