diff --git a/headers/private/kernel/disk_device_manager/KFileDiskDevice.h b/headers/private/kernel/disk_device_manager/KFileDiskDevice.h index 248f39aec8..4490dbaa93 100644 --- a/headers/private/kernel/disk_device_manager/KFileDiskDevice.h +++ b/headers/private/kernel/disk_device_manager/KFileDiskDevice.h @@ -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); diff --git a/src/kernel/core/disk_device_manager/KFileDiskDevice.cpp b/src/kernel/core/disk_device_manager/KFileDiskDevice.cpp index f061bbe38f..18ead1c659 100644 --- a/src/kernel/core/disk_device_manager/KFileDiskDevice.cpp +++ b/src/kernel/core/disk_device_manager/KFileDiskDevice.cpp @@ -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