mirror of
https://github.com/akuker/RASCSI.git
synced 2024-12-21 23:29:39 +00:00
Fixed issue with protected devices/media, added IMAGE_FILE_INFO command (#288)
* Fixed issue with attaching protected devices * Fixed same issue when inserting a file * Added IMAGE_FILE_INFO command * rasctl output update * Added file mode and type * Datat type update * Reverted change * Update web ui for protobuf changes Co-authored-by: Daniel Markstedt <markstedt@gmail.com>
This commit is contained in:
parent
998cc2d66f
commit
969220565b
@ -9,6 +9,7 @@ rasctl \- Sends management commands to the rascsi process
|
||||
\fB\-m\fR |
|
||||
\fB\-s\fR |
|
||||
\fB\-T\fR |
|
||||
[\fB\-E\fR \fIFILENAME\fR]
|
||||
[\fB\-F\fR \fIIMAGE_FOLDER\fR]
|
||||
[\fB\-C\fR \fIFILENAME:FILESIZE\fR]
|
||||
[\fB\-x\fR \fICURRENT_NAME:NEW_NAME\fR]
|
||||
@ -39,6 +40,9 @@ Note: The command and type arguments are case insensitive. Only the first letter
|
||||
.BR \-C\fI " "\fIFILENAME:FILESIZE
|
||||
Create an image file in the default image folder with the specified name and size in bytes.
|
||||
.TP
|
||||
.BR \-E\fI " " \fIFILENAME
|
||||
Display information on an image file.
|
||||
.TP
|
||||
.BR \-F\fI " "\fIIMAGE_FOLDER
|
||||
Set the default image folder.
|
||||
.TP
|
||||
|
@ -6,10 +6,11 @@ NAME
|
||||
rasctl - Sends management commands to the rascsi process
|
||||
|
||||
SYNOPSIS
|
||||
rasctl -L | -e | -l | -m | -s | -T | [-F IMAGE_FOLDER] [-C FILE‐
|
||||
NAME:FILESIZE] [-x CURRENT_NAME:NEW_NAME] [-R CURRENT_NAME:NEW_NAME]
|
||||
[-g LOG_LEVEL] [-h HOST] [-p PORT] [-r RESERVED_IDS] [-v] -i ID [-c
|
||||
CMD] [-f FILE|PARAM] [-n NAME] [-t TYPE] [-u UNIT]
|
||||
rasctl -L | -e | -l | -m | -s | -T | [-E FILENAME] [-F IMAGE_FOLDER]
|
||||
[-C FILENAME:FILESIZE] [-x CURRENT_NAME:NEW_NAME] [-R CUR‐
|
||||
RENT_NAME:NEW_NAME] [-g LOG_LEVEL] [-h HOST] [-p PORT] [-r RE‐
|
||||
SERVED_IDS] [-v] -i ID [-c CMD] [-f FILE|PARAM] [-n NAME] [-t TYPE] [-u
|
||||
UNIT]
|
||||
|
||||
DESCRIPTION
|
||||
rasctl Sends commands to the rascsi process to make configuration ad‐
|
||||
@ -27,6 +28,9 @@ OPTIONS
|
||||
Create an image file in the default image folder with the speci‐
|
||||
fied name and size in bytes.
|
||||
|
||||
-E FILENAME
|
||||
Display information on an image file.
|
||||
|
||||
-F IMAGE_FOLDER
|
||||
Set the default image folder.
|
||||
|
||||
|
@ -131,10 +131,10 @@ void ProtobufResponseHandler::GetDevice(const Device *device, PbDevice *pb_devic
|
||||
}
|
||||
}
|
||||
|
||||
void ProtobufResponseHandler::GetImageFile(PbImageFile *image_file, const string& filename, const string& image_folder)
|
||||
bool ProtobufResponseHandler::GetImageFile(PbImageFile *image_file, const string& filename, const string& image_folder)
|
||||
{
|
||||
image_file->set_name(filename);
|
||||
if (!filename.empty()) {
|
||||
image_file->set_name(filename);
|
||||
image_file->set_type(device_factory.GetTypeForFile(filename));
|
||||
|
||||
string f = filename[0] == '/' ? filename : image_folder + "/" + filename;
|
||||
@ -144,8 +144,11 @@ void ProtobufResponseHandler::GetImageFile(PbImageFile *image_file, const string
|
||||
struct stat st;
|
||||
if (!stat(f.c_str(), &st)) {
|
||||
image_file->set_size(st.st_size);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PbImageFilesInfo *ProtobufResponseHandler::GetAvailableImages(PbResult& result, const string& image_folder)
|
||||
|
@ -30,6 +30,7 @@ public:
|
||||
|
||||
static ProtobufResponseHandler& instance();
|
||||
|
||||
bool GetImageFile(PbImageFile *, const string&, const string&);
|
||||
PbImageFilesInfo *GetAvailableImages(PbResult&, const string&);
|
||||
void GetDevices(PbServerInfo&, const vector<Device *>&, const string&);
|
||||
void GetDevicesInfo(PbResult&, const PbCommand&, const vector<Device *>&, const string&, int);
|
||||
@ -49,6 +50,5 @@ private:
|
||||
void GetAllDeviceTypeProperties(PbDeviceTypesInfo&);
|
||||
void GetDeviceTypeProperties(PbDeviceTypesInfo&, PbDeviceType);
|
||||
void GetAvailableImages(PbResult& result, PbServerInfo&, const string&);
|
||||
void GetImageFile(PbImageFile *, const string&, const string&);
|
||||
void GetLogLevels(PbServerInfo&);
|
||||
};
|
||||
|
@ -839,11 +839,6 @@ bool Attach(int fd, const PbDeviceDefinition& pb_device, Device *map[], bool dry
|
||||
device->SetId(id);
|
||||
device->SetLun(unit);
|
||||
|
||||
// Only non read-only devices support protect/unprotect
|
||||
if (!device->IsReadOnly()) {
|
||||
device->SetProtected(pb_device.protected_());
|
||||
}
|
||||
|
||||
try {
|
||||
if (!pb_device.vendor().empty()) {
|
||||
device->SetVendor(pb_device.vendor());
|
||||
@ -859,19 +854,6 @@ bool Attach(int fd, const PbDeviceDefinition& pb_device, Device *map[], bool dry
|
||||
return ReturnStatus(fd, false, e.getmsg());
|
||||
}
|
||||
|
||||
if (pb_device.block_size()) {
|
||||
Disk *disk = dynamic_cast<Disk *>(device);
|
||||
if (disk && disk->IsSectorSizeConfigurable()) {
|
||||
if (!disk->SetConfiguredSectorSize(pb_device.block_size())) {
|
||||
error << "Invalid block size " << pb_device.block_size() << " bytes";
|
||||
return ReturnStatus(fd, false, error);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return ReturnStatus(fd, false, "Block size is not configurable for device type " + PbDeviceType_Name(type));
|
||||
}
|
||||
}
|
||||
|
||||
// File check (type is HD, for removable media drives, CD and MO the medium (=file) may be inserted later)
|
||||
if (file_support && !device->IsRemovable() && filename.empty()) {
|
||||
delete device;
|
||||
@ -912,6 +894,26 @@ bool Attach(int fd, const PbDeviceDefinition& pb_device, Device *map[], bool dry
|
||||
file_support->ReserveFile(filepath, device->GetId(), device->GetLun());
|
||||
}
|
||||
|
||||
// The operations below must not be executed before Open() because Open() overrides some settings
|
||||
|
||||
if (pb_device.block_size()) {
|
||||
Disk *disk = dynamic_cast<Disk *>(device);
|
||||
if (disk && disk->IsSectorSizeConfigurable()) {
|
||||
if (!disk->SetConfiguredSectorSize(pb_device.block_size())) {
|
||||
error << "Invalid block size " << pb_device.block_size() << " bytes";
|
||||
return ReturnStatus(fd, false, error);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return ReturnStatus(fd, false, "Block size is not configurable for device type " + PbDeviceType_Name(type));
|
||||
}
|
||||
}
|
||||
|
||||
// Only non read-only devices support protect/unprotect
|
||||
if (device->IsProtectable() && !device->IsReadOnly()) {
|
||||
device->SetProtected(pb_device.protected_());
|
||||
}
|
||||
|
||||
// Stop the dry run here, before permanently modifying something
|
||||
if (dryRun) {
|
||||
delete device;
|
||||
@ -1027,7 +1029,6 @@ bool Insert(int fd, const PbDeviceDefinition& pb_device, Device *device, bool dr
|
||||
}
|
||||
|
||||
FileSupport *file_support = dynamic_cast<FileSupport *>(device);
|
||||
|
||||
try {
|
||||
try {
|
||||
file_support->Open(filepath);
|
||||
@ -1041,9 +1042,14 @@ bool Insert(int fd, const PbDeviceDefinition& pb_device, Device *device, bool dr
|
||||
catch(const io_exception& e) {
|
||||
return ReturnStatus(fd, false, "Tried to open an invalid file '" + initial_filename + "': " + e.getmsg());
|
||||
}
|
||||
|
||||
file_support->ReserveFile(filepath, device->GetId(), device->GetLun());
|
||||
|
||||
// Only non read-only devices support protect/unprotect.
|
||||
// This operation must not be executed before Open() because Open() overrides some settings.
|
||||
if (device->IsProtectable() && !device->IsReadOnly()) {
|
||||
device->SetProtected(pb_device.protected_());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1574,7 +1580,7 @@ static void *MonThread(void *param)
|
||||
break;
|
||||
}
|
||||
|
||||
case IMAGE_FILES_INFO: {
|
||||
case DEFAULT_IMAGE_FILES_INFO: {
|
||||
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
|
||||
|
||||
PbResult result;
|
||||
@ -1583,6 +1589,29 @@ static void *MonThread(void *param)
|
||||
break;
|
||||
}
|
||||
|
||||
case IMAGE_FILE_INFO: {
|
||||
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
|
||||
|
||||
string filename = GetParam(command, "file");
|
||||
if (filename.empty()) {
|
||||
ReturnStatus(fd, false, "Can't get image file info: Missing filename");
|
||||
}
|
||||
else {
|
||||
PbResult result;
|
||||
PbImageFile* image_file = new PbImageFile();
|
||||
bool status = response_helper.GetImageFile(image_file, filename, default_image_folder);
|
||||
if (status) {
|
||||
result.set_status(true);
|
||||
result.set_allocated_image_file_info(image_file);
|
||||
SerializeMessage(fd, result);
|
||||
}
|
||||
else {
|
||||
ReturnStatus(fd, false, "Can't get image file info for '" + filename + "'");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NETWORK_INTERFACES_INFO: {
|
||||
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
|
||||
|
||||
|
@ -72,65 +72,70 @@ enum PbOperation {
|
||||
// Device properties by device type
|
||||
DEVICE_TYPES_INFO = 12;
|
||||
|
||||
// Gets information on available image files. A lightweight alternative to getting the complete server info.
|
||||
IMAGE_FILES_INFO = 13;
|
||||
// Gets information on available image files in the default image folder.
|
||||
DEFAULT_IMAGE_FILES_INFO = 13;
|
||||
|
||||
// Gets information on an image file (not necessarily in the default image folder) based on an absolute path.
|
||||
// Parameters:
|
||||
// "file": The filename. Either an absolute path or a path relative to the default image folder.
|
||||
IMAGE_FILE_INFO = 14;
|
||||
|
||||
// Gets the names of the available network interfaces. Only lists interfaces that are up.
|
||||
NETWORK_INTERFACES_INFO = 14;
|
||||
NETWORK_INTERFACES_INFO = 15;
|
||||
|
||||
// Gets the mapping of extensions to device types
|
||||
MAPPING_INFO = 15;
|
||||
MAPPING_INFO = 16;
|
||||
|
||||
// Set the default folder for image files.
|
||||
// Parameters:
|
||||
// "folder": The default folder name.
|
||||
DEFAULT_FOLDER = 16;
|
||||
DEFAULT_FOLDER = 17;
|
||||
|
||||
// Set server log level.
|
||||
// Parameters:
|
||||
// "level": The new log level
|
||||
LOG_LEVEL = 17;
|
||||
LOG_LEVEL = 18;
|
||||
|
||||
// Block IDs from being used, usually the IDs of the initiators (computers) in the SCSI chain.
|
||||
// Parameters:
|
||||
// "ids": A comma-separated list of IDs to reserve, or an empty string in order not to reserve any ID.
|
||||
RESERVE = 18;
|
||||
RESERVE = 19;
|
||||
|
||||
// Create an image file. The image file must not yet exist.
|
||||
// Parameters:
|
||||
// "file": The filename, relative to the default image folder. It must not contain a slash.
|
||||
// "size": The file size in bytes, must be a multiple of 512
|
||||
// "read_only": "true" (case-insensitive) in order to create a read-only file, otherwise "false"
|
||||
CREATE_IMAGE = 19;
|
||||
CREATE_IMAGE = 20;
|
||||
|
||||
// Delete an image file.
|
||||
// Parameters:
|
||||
// "file": The filename, relative to the default image folder. It must not contain a slash.
|
||||
DELETE_IMAGE = 20;
|
||||
DELETE_IMAGE = 21;
|
||||
|
||||
// Rename an image file.
|
||||
// Parameters:
|
||||
// "from": The old filename, relative to the default image folder. It must not contain a slash.
|
||||
// "to": The new filename, relative to the default image folder. It must not contain a slash.
|
||||
// The new filename must not yet exist.
|
||||
RENAME_IMAGE = 21;
|
||||
RENAME_IMAGE = 22;
|
||||
|
||||
// Copy an image file.
|
||||
// Parameters:
|
||||
// "from": The source filename, relative to the default image folder. It must not contain a slash.
|
||||
// "to": The destination filename, relative to the default image folder. It must not contain a slash.
|
||||
// The destination filename must not yet exist.
|
||||
COPY_IMAGE = 22;
|
||||
COPY_IMAGE = 23;
|
||||
|
||||
// Write-protect an image file.
|
||||
// Parameters:
|
||||
// "file": The filename, relative to the default image folder. It must not contain a slash.
|
||||
PROTECT_IMAGE = 23;
|
||||
PROTECT_IMAGE = 24;
|
||||
|
||||
// Make an image file writable.
|
||||
// Parameters:
|
||||
// "file": The filename, relative to the default image folder. It must not contain a slash.
|
||||
UNPROTECT_IMAGE = 24;
|
||||
UNPROTECT_IMAGE = 25;
|
||||
}
|
||||
|
||||
// The supported file extensions mapped to their respective device types
|
||||
@ -189,9 +194,9 @@ message PbImageFile {
|
||||
string name = 1;
|
||||
// The assumed device type, based on the filename extension
|
||||
PbDeviceType type = 2;
|
||||
bool read_only = 3;
|
||||
// The file size in bytes, 0 for block devices
|
||||
int64 size = 4;
|
||||
uint64 size = 3;
|
||||
bool read_only = 4;
|
||||
}
|
||||
|
||||
// The default image folder and the image files it contains
|
||||
@ -269,12 +274,14 @@ message PbResult {
|
||||
PbDevices device_info = 4;
|
||||
// The result of a DEVICE_TYPES_INFO command
|
||||
PbDeviceTypesInfo device_types_info = 5;
|
||||
// The result of an IMAGE_FILES_INFO command
|
||||
// The result of a DEFAULT_IMAGE_FILES_INFO command
|
||||
PbImageFilesInfo image_files_info = 6;
|
||||
// The result of an IMAGE_FILE_INFO command
|
||||
PbImageFile image_file_info = 7;
|
||||
// The result of a NETWORK_INTERFACES_INFO command
|
||||
PbNetworkInterfacesInfo network_interfaces_info = 7;
|
||||
PbNetworkInterfacesInfo network_interfaces_info = 8;
|
||||
// The result of an MAPPING_INFO command
|
||||
PbMappingInfo mapping_info = 8;
|
||||
PbMappingInfo mapping_info = 9;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,6 +234,19 @@ void DisplayDeviceTypesInfo(const PbDeviceTypesInfo& device_types_info)
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayImageFile(const PbImageFile& image_file_info)
|
||||
{
|
||||
cout << image_file_info.name() << " " << image_file_info.size() << " bytes";
|
||||
if (image_file_info.read_only()) {
|
||||
cout << " read-only";
|
||||
}
|
||||
if (image_file_info.type() != UNDEFINED) {
|
||||
cout << " " << PbDeviceType_Name(image_file_info.type());
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
}
|
||||
|
||||
void DisplayImageFiles(const PbImageFilesInfo& image_files_info)
|
||||
{
|
||||
const list<PbImageFile> image_files = { image_files_info.image_files().begin(), image_files_info.image_files().end() };
|
||||
@ -249,14 +262,8 @@ void DisplayImageFiles(const PbImageFilesInfo& image_files_info)
|
||||
|
||||
cout << "Available image files:" << endl;
|
||||
for (const auto& file : files) {
|
||||
cout << " " << file.name() << " " << file.size() << " bytes";
|
||||
if (file.read_only()) {
|
||||
cout << " read-only";
|
||||
}
|
||||
if (file.type() != UNDEFINED) {
|
||||
cout << " " << PbDeviceType_Name(file.type());
|
||||
}
|
||||
cout << endl;
|
||||
cout << " ";
|
||||
DisplayImageFile(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -469,7 +476,7 @@ void CommandServerInfo(PbCommand& command, const string& hostname, int port)
|
||||
}
|
||||
}
|
||||
|
||||
void CommandImageFilesInfo(const PbCommand& command, const string& hostname, int port)
|
||||
void CommandDefaultImageFilesInfo(const PbCommand& command, const string& hostname, int port)
|
||||
{
|
||||
PbResult result;
|
||||
SendCommand(hostname.c_str(), port, command, result);
|
||||
@ -477,6 +484,16 @@ void CommandImageFilesInfo(const PbCommand& command, const string& hostname, int
|
||||
DisplayImageFiles(result.image_files_info());
|
||||
}
|
||||
|
||||
void CommandImageFileInfo(PbCommand& command, const string& hostname, int port, const string& filename)
|
||||
{
|
||||
AddParam(command, "file", filename);
|
||||
|
||||
PbResult result;
|
||||
SendCommand(hostname.c_str(), port, command, result);
|
||||
|
||||
DisplayImageFile(result.image_file_info());
|
||||
}
|
||||
|
||||
void CommandNetworkInterfacesInfo(const PbCommand& command, const string&hostname, int port)
|
||||
{
|
||||
PbResult result;
|
||||
@ -573,7 +590,7 @@ int main(int argc, char* argv[])
|
||||
cerr << "Usage: " << argv[0] << " -i ID [-u UNIT] [-c CMD] [-C FILE] [-t TYPE] [-b BLOCK_SIZE] [-n NAME] [-f FILE|PARAM] ";
|
||||
cerr << "[-F IMAGE_FOLDER] [-L LOG_LEVEL] [-h HOST] [-p PORT] [-r RESERVED_IDS] ";
|
||||
cerr << "[-C FILENAME:FILESIZE] [-w FILENAME] [-R CURRENT_NAME:NEW_NAME] [-x CURRENT_NAME:NEW_NAME] ";
|
||||
cerr << "[-L] [-l] [-m] [-s] [-v] [-y]" << endl;
|
||||
cerr << "[-e] [-E FILENAME] [-l] [-L] [-m] [-s] [-v] [-y]" << endl;
|
||||
cerr << " where ID := {0-7}" << endl;
|
||||
cerr << " UNIT := {0|1}, default is 0" << endl;
|
||||
cerr << " CMD := {attach|detach|insert|eject|protect|unprotect|show}" << endl;
|
||||
@ -605,11 +622,12 @@ int main(int argc, char* argv[])
|
||||
string default_folder;
|
||||
string reserved_ids;
|
||||
string image_params;
|
||||
string filename;
|
||||
bool list = false;
|
||||
|
||||
opterr = 1;
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "elmsvNTD:L:R:a:b:c:f:h:i:n:p:r:t:u:x:C:F:L:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "elmsvNTD:L:R:a:b:c:f:h:i:n:p:r:t:u:x:C:E:F:L:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'i':
|
||||
device->set_id(optarg[0] - '0');
|
||||
@ -641,13 +659,18 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
command.set_operation(DEFAULT_FOLDER);
|
||||
default_folder = optarg;
|
||||
case 'E':
|
||||
command.set_operation(IMAGE_FILE_INFO);
|
||||
filename = optarg;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
command.set_operation(IMAGE_FILES_INFO);
|
||||
command.set_operation(DEFAULT_IMAGE_FILES_INFO);
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
command.set_operation(DEFAULT_FOLDER);
|
||||
default_folder = optarg;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
@ -799,8 +822,12 @@ int main(int argc, char* argv[])
|
||||
CommandServerInfo(command, hostname, port);
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
case IMAGE_FILES_INFO:
|
||||
CommandImageFilesInfo(command, hostname, port);
|
||||
case DEFAULT_IMAGE_FILES_INFO:
|
||||
CommandDefaultImageFilesInfo(command, hostname, port);
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
case IMAGE_FILE_INFO:
|
||||
CommandImageFileInfo(command, hostname, port, filename);
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
case NETWORK_INTERFACES_INFO:
|
||||
|
@ -13,7 +13,7 @@ import rascsi_interface_pb2 as proto
|
||||
|
||||
def list_files():
|
||||
command = proto.PbCommand()
|
||||
command.operation = proto.PbOperation.IMAGE_FILES_INFO
|
||||
command.operation = proto.PbOperation.DEFAULT_IMAGE_FILES_INFO
|
||||
|
||||
data = send_pb_command(command.SerializeToString())
|
||||
result = proto.PbResult()
|
||||
|
Loading…
Reference in New Issue
Block a user