* 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:
Ingo Weinhold 2004-10-28 22:22:04 +00:00
parent 1e2e4b3c71
commit c06238cbd6
2 changed files with 150 additions and 87 deletions

View File

@ -26,6 +26,10 @@ public:
// 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:
static status_t _GetDirectoryPath(partition_id id, KPath *path);

View File

@ -21,6 +21,22 @@
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
KFileDiskDevice::KFileDiskDevice(partition_id id)
: KDiskDevice(id),
@ -44,19 +60,12 @@ KFileDiskDevice::SetTo(const char *filePath, const char *devicePath)
return B_BAD_VALUE;
}
// 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;
if (filePath[0] != '/') {
if (tmpFilePath.InitCheck() != B_OK)
return tmpFilePath.InitCheck();
// 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();
}
status_t error = tmpFilePath.SetTo(filePath, true);
if (error != B_OK)
return error;
// check the file
struct stat st;
if (stat(filePath, &st) != 0)
@ -66,30 +75,32 @@ KFileDiskDevice::SetTo(const char *filePath, const char *devicePath)
// create the device, if requested
KPath tmpDevicePath;
if (!devicePath) {
// no device path: we shall create a new device entry
if (tmpDevicePath.InitCheck() != B_OK)
return tmpDevicePath.InitCheck();
// no device path: we shall create a new device entry
// make the file devices dir
if (mkdir(kFileDevicesDir, 0777) != 0) {
if (errno != B_FILE_EXISTS)
return errno;
}
// TODO: Cleanup. The directory creation is done automatically by the devfs.
// // make the file devices dir
// if (mkdir(kFileDevicesDir, 0777) != 0) {
// if (errno != B_FILE_EXISTS)
// return errno;
// }
// make the directory
status_t error = _GetDirectoryPath(ID(), &tmpDevicePath);
if (error != B_OK)
return error;
if (mkdir(tmpDevicePath.Path(), 0777) != 0)
return errno;
// if (mkdir(tmpDevicePath.Path(), 0777) != 0)
// return errno;
// get the device path name
if (tmpDevicePath.Append("raw") != B_OK)
return B_BUFFER_OVERFLOW;
error = tmpDevicePath.Append("raw");
if (error != B_OK)
return error;
devicePath = tmpDevicePath.Path();
// register the file as virtual drive
// register the file as virtual disk device
error = _RegisterDevice(filePath, devicePath);
if (error != B_OK)
return error;
}
status_t error = set_string(fFilePath, filePath);
error = set_string(fFilePath, filePath);
if (error != B_OK)
return error;
return KDiskDevice::SetTo(devicePath);
@ -102,9 +113,10 @@ KFileDiskDevice::Unset()
// remove the device and the directory it resides in
if (Path() && ID() >= 0) {
_UnregisterDevice(Path());
KPath dirPath;
if (_GetDirectoryPath(ID(), &dirPath) == B_OK)
rmdir(dirPath.Path());
// TODO: Cleanup. The devfs will automatically remove the directory.
// KPath dirPath;
// if (_GetDirectoryPath(ID(), &dirPath) == B_OK)
// rmdir(dirPath.Path());
}
// free file path
free(fFilePath);
@ -125,82 +137,129 @@ KFileDiskDevice::FilePath() const
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
status_t
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
// as a device and then simply symlink the assigned device to the
// desired device location. Replace that with the
// respective kernel magic for the OBOS kernel!
// -> Well, we could simply symlink the file there. Doesn't work for R5,
// but we should be able to deal with it properly.
// open the virtualdrive control device
int fd = open(VIRTUAL_DRIVE_CONTROL_DEVICE, O_RDONLY);
if (fd < 0) {
DBG(OUT("Failed to open virtualdrive control device: %s\n",
strerror(errno)));
return errno;
}
// set up the info
virtual_drive_info info;
strcpy(info.file_name, file);
info.use_geometry = false;
status_t error = B_OK;
if (ioctl(fd, VIRTUAL_DRIVE_REGISTER_FILE, &info) != 0) {
error = errno;
DBG(OUT("Failed to install file device: %s\n", strerror(error)));
}
// close the control device
close(fd);
// create a symlink
if (error == B_OK) {
if (symlink(info.device_name, device) != 0) {
DBG(OUT("Failed to create file device symlink: %s\n",
strerror(error)));
error = errno;
// unregister the file device
// open the device
int deviceFD = open(info.device_name, O_RDONLY);
if (deviceFD >= 0) {
ioctl(deviceFD, VIRTUAL_DRIVE_UNREGISTER_FILE);
close(deviceFD);
}
}
}
return error;
//
// // open the virtualdrive control device
// int fd = open(VIRTUAL_DRIVE_CONTROL_DEVICE, O_RDONLY);
// if (fd < 0) {
// DBG(OUT("Failed to open virtualdrive control device: %s\n",
// strerror(errno)));
// return errno;
// }
// // set up the info
// virtual_drive_info info;
// strcpy(info.file_name, file);
// info.use_geometry = false;
// status_t error = B_OK;
// if (ioctl(fd, VIRTUAL_DRIVE_REGISTER_FILE, &info) != 0) {
// error = errno;
// DBG(OUT("Failed to install file device: %s\n", strerror(error)));
// }
// // close the control device
// close(fd);
// // create a symlink
// if (error == B_OK) {
// if (symlink(info.device_name, device) != 0) {
// DBG(OUT("Failed to create file device symlink: %s\n",
// strerror(error)));
// error = errno;
// // unregister the file device
// // open the device
// int deviceFD = open(info.device_name, O_RDONLY);
// if (deviceFD >= 0) {
// ioctl(deviceFD, VIRTUAL_DRIVE_UNREGISTER_FILE);
// close(deviceFD);
// }
// }
// }
// return error;
}
// _UnregisterDevice
status_t
KFileDiskDevice::_UnregisterDevice(const char *_device)
{
return B_ERROR;
#if 0
// read the symlink to get the path of the virtualdrive device
char device[B_PATH_NAME_LENGTH];
ssize_t bytesRead = readlink(_device, device, sizeof(device) - 1);
if (bytesRead < 0)
return errno;
device[bytesRead] = '\0';
// open the device
int fd = open(device, O_RDONLY);
if (fd < 0)
return errno;
// issue the ioctl
status_t error = B_OK;
if (ioctl(fd, VIRTUAL_DRIVE_UNREGISTER_FILE) != 0)
error = errno;
// close the control device
close(fd);
// remove the symlink
if (error == B_OK) {
if (remove(_device) < 0)
error = errno;
}
return error;
#endif
return devfs_unpublish_file_device(_device);
// // read the symlink to get the path of the virtualdrive device
// char device[B_PATH_NAME_LENGTH];
// ssize_t bytesRead = readlink(_device, device, sizeof(device) - 1);
// if (bytesRead < 0)
// return errno;
// device[bytesRead] = '\0';
// // open the device
// int fd = open(device, O_RDONLY);
// if (fd < 0)
// return errno;
// // issue the ioctl
// status_t error = B_OK;
// if (ioctl(fd, VIRTUAL_DRIVE_UNREGISTER_FILE) != 0)
// error = errno;
// // close the control device
// close(fd);
// // remove the symlink
// if (error == B_OK) {
// if (remove(_device) < 0)
// error = errno;
// }
// return error;
}
// _GetDirectoryPath