* 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:
parent
1e2e4b3c71
commit
c06238cbd6
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user