* Reworked publishing/unpublishing of the device. This is now basically
done by (currently not existing) devfs functions. * Overridden GetMediaStatus() and GetGeometry() to return useful data. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9627 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -26,6 +26,10 @@ public:
|
|||||||
|
|
||||||
// virtual void Dump(bool deep = true, int32 level = 0);
|
// 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:
|
private:
|
||||||
static status_t _GetDirectoryPath(partition_id id, KPath *path);
|
static status_t _GetDirectoryPath(partition_id id, KPath *path);
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,22 @@
|
|||||||
|
|
||||||
static const char *kFileDevicesDir = "/dev/disk/virtual/files";
|
static const char *kFileDevicesDir = "/dev/disk/virtual/files";
|
||||||
|
|
||||||
|
// TODO: Remove when implemented in the devfs.
|
||||||
|
static
|
||||||
|
status_t
|
||||||
|
devfs_publish_file_device(const char *path, const char *filePath)
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
status_t
|
||||||
|
devfs_unpublish_file_device(const char *path)
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
KFileDiskDevice::KFileDiskDevice(partition_id id)
|
KFileDiskDevice::KFileDiskDevice(partition_id id)
|
||||||
: KDiskDevice(id),
|
: KDiskDevice(id),
|
||||||
@@ -44,19 +60,12 @@ KFileDiskDevice::SetTo(const char *filePath, const char *devicePath)
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
// normalize the file path
|
// normalize the file path
|
||||||
// TODO: For the time being, we get an absolute file name only.
|
// (should actually not be necessary, since this method is only invoked
|
||||||
|
// by the DDM, which has already normalized the path)
|
||||||
KPath tmpFilePath;
|
KPath tmpFilePath;
|
||||||
if (filePath[0] != '/') {
|
status_t error = tmpFilePath.SetTo(filePath, true);
|
||||||
if (tmpFilePath.InitCheck() != B_OK)
|
if (error != B_OK)
|
||||||
return tmpFilePath.InitCheck();
|
return error;
|
||||||
// prepend the current directory path
|
|
||||||
if (!getcwd(tmpFilePath.LockBuffer(), tmpFilePath.BufferSize() - 1))
|
|
||||||
return B_ERROR;
|
|
||||||
tmpFilePath.UnlockBuffer();
|
|
||||||
if (tmpFilePath.Append(filePath) != B_OK)
|
|
||||||
return B_ERROR;
|
|
||||||
filePath = tmpFilePath.Path();
|
|
||||||
}
|
|
||||||
// check the file
|
// check the file
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(filePath, &st) != 0)
|
if (stat(filePath, &st) != 0)
|
||||||
@@ -66,30 +75,32 @@ KFileDiskDevice::SetTo(const char *filePath, const char *devicePath)
|
|||||||
// create the device, if requested
|
// create the device, if requested
|
||||||
KPath tmpDevicePath;
|
KPath tmpDevicePath;
|
||||||
if (!devicePath) {
|
if (!devicePath) {
|
||||||
|
// no device path: we shall create a new device entry
|
||||||
if (tmpDevicePath.InitCheck() != B_OK)
|
if (tmpDevicePath.InitCheck() != B_OK)
|
||||||
return tmpDevicePath.InitCheck();
|
return tmpDevicePath.InitCheck();
|
||||||
// no device path: we shall create a new device entry
|
// TODO: Cleanup. The directory creation is done automatically by the devfs.
|
||||||
// make the file devices dir
|
// // make the file devices dir
|
||||||
if (mkdir(kFileDevicesDir, 0777) != 0) {
|
// if (mkdir(kFileDevicesDir, 0777) != 0) {
|
||||||
if (errno != B_FILE_EXISTS)
|
// if (errno != B_FILE_EXISTS)
|
||||||
return errno;
|
// return errno;
|
||||||
}
|
// }
|
||||||
// make the directory
|
// make the directory
|
||||||
status_t error = _GetDirectoryPath(ID(), &tmpDevicePath);
|
status_t error = _GetDirectoryPath(ID(), &tmpDevicePath);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
if (mkdir(tmpDevicePath.Path(), 0777) != 0)
|
// if (mkdir(tmpDevicePath.Path(), 0777) != 0)
|
||||||
return errno;
|
// return errno;
|
||||||
// get the device path name
|
// get the device path name
|
||||||
if (tmpDevicePath.Append("raw") != B_OK)
|
error = tmpDevicePath.Append("raw");
|
||||||
return B_BUFFER_OVERFLOW;
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
devicePath = tmpDevicePath.Path();
|
devicePath = tmpDevicePath.Path();
|
||||||
// register the file as virtual drive
|
// register the file as virtual disk device
|
||||||
error = _RegisterDevice(filePath, devicePath);
|
error = _RegisterDevice(filePath, devicePath);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
status_t error = set_string(fFilePath, filePath);
|
error = set_string(fFilePath, filePath);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
return KDiskDevice::SetTo(devicePath);
|
return KDiskDevice::SetTo(devicePath);
|
||||||
@@ -102,9 +113,10 @@ KFileDiskDevice::Unset()
|
|||||||
// remove the device and the directory it resides in
|
// remove the device and the directory it resides in
|
||||||
if (Path() && ID() >= 0) {
|
if (Path() && ID() >= 0) {
|
||||||
_UnregisterDevice(Path());
|
_UnregisterDevice(Path());
|
||||||
KPath dirPath;
|
// TODO: Cleanup. The devfs will automatically remove the directory.
|
||||||
if (_GetDirectoryPath(ID(), &dirPath) == B_OK)
|
// KPath dirPath;
|
||||||
rmdir(dirPath.Path());
|
// if (_GetDirectoryPath(ID(), &dirPath) == B_OK)
|
||||||
|
// rmdir(dirPath.Path());
|
||||||
}
|
}
|
||||||
// free file path
|
// free file path
|
||||||
free(fFilePath);
|
free(fFilePath);
|
||||||
@@ -125,82 +137,129 @@ KFileDiskDevice::FilePath() const
|
|||||||
return fFilePath;
|
return fFilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetMediaStatus
|
||||||
|
status_t
|
||||||
|
KFileDiskDevice::GetMediaStatus(status_t *mediaStatus)
|
||||||
|
{
|
||||||
|
// check the file
|
||||||
|
struct stat st;
|
||||||
|
if (stat(fFilePath, &st) == 0 && S_ISREG(st.st_mode))
|
||||||
|
*mediaStatus = B_OK;
|
||||||
|
else
|
||||||
|
*mediaStatus = B_DEV_NO_MEDIA;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGeometry
|
||||||
|
status_t
|
||||||
|
KFileDiskDevice::GetGeometry(device_geometry *geometry)
|
||||||
|
{
|
||||||
|
// check the file
|
||||||
|
struct stat st;
|
||||||
|
if (stat(fFilePath, &st) != 0 || !S_ISREG(st.st_mode))
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// fill in the geometry
|
||||||
|
// default to 512 bytes block 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 = st.st_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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// _RegisterDevice
|
// _RegisterDevice
|
||||||
status_t
|
status_t
|
||||||
KFileDiskDevice::_RegisterDevice(const char *file, const char *device)
|
KFileDiskDevice::_RegisterDevice(const char *file, const char *device)
|
||||||
{
|
{
|
||||||
|
return devfs_publish_file_device(device, file);
|
||||||
|
|
||||||
// TODO: For now we use the virtualdrive driver to register a file
|
// TODO: For now we use the virtualdrive driver to register a file
|
||||||
// as a device and then simply symlink the assigned device to the
|
// as a device and then simply symlink the assigned device to the
|
||||||
// desired device location. Replace that with the
|
// desired device location. Replace that with the
|
||||||
// respective kernel magic for the OBOS kernel!
|
// respective kernel magic for the OBOS kernel!
|
||||||
// -> Well, we could simply symlink the file there. Doesn't work for R5,
|
// -> Well, we could simply symlink the file there. Doesn't work for R5,
|
||||||
// but we should be able to deal with it properly.
|
// but we should be able to deal with it properly.
|
||||||
|
//
|
||||||
// open the virtualdrive control device
|
// // open the virtualdrive control device
|
||||||
int fd = open(VIRTUAL_DRIVE_CONTROL_DEVICE, O_RDONLY);
|
// int fd = open(VIRTUAL_DRIVE_CONTROL_DEVICE, O_RDONLY);
|
||||||
if (fd < 0) {
|
// if (fd < 0) {
|
||||||
DBG(OUT("Failed to open virtualdrive control device: %s\n",
|
// DBG(OUT("Failed to open virtualdrive control device: %s\n",
|
||||||
strerror(errno)));
|
// strerror(errno)));
|
||||||
return errno;
|
// return errno;
|
||||||
}
|
// }
|
||||||
// set up the info
|
// // set up the info
|
||||||
virtual_drive_info info;
|
// virtual_drive_info info;
|
||||||
strcpy(info.file_name, file);
|
// strcpy(info.file_name, file);
|
||||||
info.use_geometry = false;
|
// info.use_geometry = false;
|
||||||
status_t error = B_OK;
|
// status_t error = B_OK;
|
||||||
if (ioctl(fd, VIRTUAL_DRIVE_REGISTER_FILE, &info) != 0) {
|
// if (ioctl(fd, VIRTUAL_DRIVE_REGISTER_FILE, &info) != 0) {
|
||||||
error = errno;
|
// error = errno;
|
||||||
DBG(OUT("Failed to install file device: %s\n", strerror(error)));
|
// DBG(OUT("Failed to install file device: %s\n", strerror(error)));
|
||||||
}
|
// }
|
||||||
// close the control device
|
// // close the control device
|
||||||
close(fd);
|
// close(fd);
|
||||||
// create a symlink
|
// // create a symlink
|
||||||
if (error == B_OK) {
|
// if (error == B_OK) {
|
||||||
if (symlink(info.device_name, device) != 0) {
|
// if (symlink(info.device_name, device) != 0) {
|
||||||
DBG(OUT("Failed to create file device symlink: %s\n",
|
// DBG(OUT("Failed to create file device symlink: %s\n",
|
||||||
strerror(error)));
|
// strerror(error)));
|
||||||
error = errno;
|
// error = errno;
|
||||||
// unregister the file device
|
// // unregister the file device
|
||||||
// open the device
|
// // open the device
|
||||||
int deviceFD = open(info.device_name, O_RDONLY);
|
// int deviceFD = open(info.device_name, O_RDONLY);
|
||||||
if (deviceFD >= 0) {
|
// if (deviceFD >= 0) {
|
||||||
ioctl(deviceFD, VIRTUAL_DRIVE_UNREGISTER_FILE);
|
// ioctl(deviceFD, VIRTUAL_DRIVE_UNREGISTER_FILE);
|
||||||
close(deviceFD);
|
// close(deviceFD);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return error;
|
// return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// _UnregisterDevice
|
// _UnregisterDevice
|
||||||
status_t
|
status_t
|
||||||
KFileDiskDevice::_UnregisterDevice(const char *_device)
|
KFileDiskDevice::_UnregisterDevice(const char *_device)
|
||||||
{
|
{
|
||||||
return B_ERROR;
|
return devfs_unpublish_file_device(_device);
|
||||||
#if 0
|
|
||||||
// read the symlink to get the path of the virtualdrive device
|
// // read the symlink to get the path of the virtualdrive device
|
||||||
char device[B_PATH_NAME_LENGTH];
|
// char device[B_PATH_NAME_LENGTH];
|
||||||
ssize_t bytesRead = readlink(_device, device, sizeof(device) - 1);
|
// ssize_t bytesRead = readlink(_device, device, sizeof(device) - 1);
|
||||||
if (bytesRead < 0)
|
// if (bytesRead < 0)
|
||||||
return errno;
|
// return errno;
|
||||||
device[bytesRead] = '\0';
|
// device[bytesRead] = '\0';
|
||||||
// open the device
|
// // open the device
|
||||||
int fd = open(device, O_RDONLY);
|
// int fd = open(device, O_RDONLY);
|
||||||
if (fd < 0)
|
// if (fd < 0)
|
||||||
return errno;
|
// return errno;
|
||||||
// issue the ioctl
|
// // issue the ioctl
|
||||||
status_t error = B_OK;
|
// status_t error = B_OK;
|
||||||
if (ioctl(fd, VIRTUAL_DRIVE_UNREGISTER_FILE) != 0)
|
// if (ioctl(fd, VIRTUAL_DRIVE_UNREGISTER_FILE) != 0)
|
||||||
error = errno;
|
// error = errno;
|
||||||
// close the control device
|
// // close the control device
|
||||||
close(fd);
|
// close(fd);
|
||||||
// remove the symlink
|
// // remove the symlink
|
||||||
if (error == B_OK) {
|
// if (error == B_OK) {
|
||||||
if (remove(_device) < 0)
|
// if (remove(_device) < 0)
|
||||||
error = errno;
|
// error = errno;
|
||||||
}
|
// }
|
||||||
return error;
|
// return error;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// _GetDirectoryPath
|
// _GetDirectoryPath
|
||||||
|
|||||||
Reference in New Issue
Block a user