Added INFO_IMAGE_FILES and INFO_NETWORK_INTERFACES (#243)

* Added GET_IMAGE_FILES

* Added default folder to GET_IMAGE_FILES

* Renaming

* Updated setting image folder

* Fixed default image folder handling

* Added NETWORK_INTERFACES_INFO

* Filter "lo"

* Use PF_INET in favor of PF_INET6

* Added network interfaces to server info

* Filter rascsi_bridge

* Use list of available network interfaces as default parameters
This commit is contained in:
Uwe Seimet 2021-09-19 09:05:01 +02:00 committed by GitHub
parent 5161a83999
commit f782156e51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 283 additions and 110 deletions

View File

@ -3,6 +3,8 @@
rasctl \- Sends management commands to the rascsi process
.SH SYNOPSIS
.B rasctl
\fB\-e\fR |
\fB\-k\fR |
\fB\-l\fR |
\fB\-s\fR |
[\fB\-d\fR \fIIMAGE_FOLDER\fR]
@ -32,7 +34,7 @@ Note: The command and type arguments are case insensitive. Only the first letter
.BR \-a\fI " "\fIFILENAME:FILESIZE
Create an image file in the default image folder with the specified name and size in bytes.
.TP
.BR \-g\fI " "\fIIMAGE_FOLDER
.BR \-d\fI " "\fIIMAGE_FOLDER
Set the default image folder.
.TP
.BR \-g\fI " "\fILOG_LEVEL
@ -41,6 +43,12 @@ Set the rascsi log level (trace, debug, info, warn, err, critical, off).
.BR \-h\fI " " \fIHOST
The rascsi host to connect to, default is 'localhost'.
.TP
.BR \-e\fI
List all images files in the default image folder.
.TP
.BR \-k\fI
Lists all available network interfaces provided that they are up.
.TP
.BR \-l\fI
List all of the devices that are currently being emulated by RaSCSI, as well as their current status.
.TP

View File

@ -6,9 +6,9 @@ NAME
rasctl - Sends management commands to the rascsi process
SYNOPSIS
rasctl -l | -s | [-d IMAGE_FOLDER] [-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 -e | -k | -l | -s | [-d IMAGE_FOLDER] [-g LOG_LEVEL] [-h HOST]
[-p PORT] [-r RESERVED_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
@ -26,7 +26,7 @@ OPTIONS
Create an image file in the default image folder with the speci
fied name and size in bytes.
-g IMAGE_FOLDER
-d IMAGE_FOLDER
Set the default image folder.
-g LOG_LEVEL
@ -36,7 +36,12 @@ OPTIONS
-h HOST
The rascsi host to connect to, default is 'localhost'.
-l List all of the devices that are currently being emulated by
-e List all images files in the default image folder.
-k Lists all available network interfaces provided that they are
up.
-l List all of the devices that are currently being emulated by
RaSCSI, as well as their current status.
-m CURRENT_NAME:NEW_NAME
@ -48,7 +53,7 @@ OPTIONS
-r RESERVED_IDS
Comma-separated list of IDs to reserve.
-s Display server-side settings like available images or supported
-s Display server-side settings like available images or supported
device types.
-v Display the rascsi version.
@ -66,7 +71,7 @@ OPTIONS
d(etach): Detach disk
i(nsert): Insert media (removable media devices only)
e(ject): Eject media (removable media devices only)
p(rotect): Write protect the medium (not for CD-ROMs, which
p(rotect): Write protect the medium (not for CD-ROMs, which
are always read-only)
u(nprotect): Remove write protection from the medium (not for
CD-ROMs, which are always read-only)
@ -76,18 +81,18 @@ OPTIONS
-b BLOCK_SIZE
The optional block size. For SCSI drives 512, 1024, 2048 or 4096
bytes, default size is 512 bytes. For SASI drives 256 or 1024
bytes, default size is 512 bytes. For SASI drives 256 or 1024
bytes, default is 256 bytes.
-f FILE|PARAM
Device-specific: Either a path to a disk image file, or a param
eter for a non-disk device. See the rascsi(1) man page for per
eter for a non-disk device. See the rascsi(1) man page for per
mitted file types.
-t TYPE
Specifies the device type. This type overrides the type derived
Specifies the device type. This type overrides the type derived
from the file extension of the specified image. See the
rascsi(1) man page for the available device types. For some
rascsi(1) man page for the available device types. For some
types there are shortcuts (only the first letter is required):
hd: SCSI hard disk drive
rm: SCSI removable media drive
@ -97,16 +102,16 @@ OPTIONS
daynaport: DaynaPORT network adapter
-n VENDOR:PRODUCT:REVISION
The vendor, product and revision for the device, to be returned
The vendor, product and revision for the device, to be returned
with the INQUIRY data. A complete set of name components must be
provided. VENDOR may have up to 8, PRODUCT up to 16, REVISION up
to 4 characters. Padding with blanks to the maxium length is au
tomatically applied. Once set the name of a device cannot be
tomatically applied. Once set the name of a device cannot be
changed.
-u UNIT
Unit number (0 or 1). This will default to 0. This option is
only used when there are multiple SCSI devices on a shared SCSI
Unit number (0 or 1). This will default to 0. This option is
only used when there are multiple SCSI devices on a shared SCSI
controller. (This is not common)
EXAMPLES

View File

@ -16,6 +16,7 @@
#include "scsi_daynaport.h"
#include "exceptions.h"
#include "device_factory.h"
#include <ifaddrs.h>
#include <set>
#include <map>
@ -48,13 +49,21 @@ DeviceFactory::DeviceFactory()
geometries[SCBR] = {};
geometries[SCDP] = {};
string network_interfaces;
for (const auto& network_interface : GetNetworkInterfaces()) {
if (!network_interfaces.empty()) {
network_interfaces += ",";
}
network_interfaces += network_interface;
}
default_params[SAHD] = {};
default_params[SCHD] = {};
default_params[SCRM] = {};
default_params[SCMO] = {};
default_params[SCCD] = {};
default_params[SCBR]["interfaces"] = "eth0,wlan0";
default_params[SCDP]["interfaces"] = "eth0,wlan0";
default_params[SCBR]["interfaces"] = network_interfaces;
default_params[SCDP]["interfaces"] = network_interfaces;
}
DeviceFactory& DeviceFactory::instance()
@ -194,3 +203,41 @@ const set<uint64_t> DeviceFactory::GetCapacities(PbDeviceType type)
return keys;
}
const list<string> DeviceFactory::GetNetworkInterfaces() const
{
list<string> network_interfaces;
struct ifaddrs *addrs;
getifaddrs(&addrs);
struct ifaddrs *tmp = addrs;
while (tmp) {
if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_PACKET &&
strcmp(tmp->ifa_name, "lo") && strcmp(tmp->ifa_name, "rascsi_bridge")) {
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, tmp->ifa_name);
if (!ioctl(fd, SIOCGIFFLAGS, &ifr)) {
close(fd);
// Only list interfaces that are up
if (ifr.ifr_flags & IFF_UP) {
network_interfaces.push_back(tmp->ifa_name);
}
}
else {
close(fd);
}
}
tmp = tmp->ifa_next;
}
freeifaddrs(addrs);
return network_interfaces;
}

View File

@ -33,12 +33,13 @@ public:
static DeviceFactory& instance();
Device *CreateDevice(PbDeviceType type, const string& filename, const string& ext);
const set<uint32_t>& GetSectorSizes(PbDeviceType type) { return sector_sizes[type]; }
const set<uint32_t>& GetSectorSizes(const string&);
const set<uint64_t> GetCapacities(PbDeviceType);
const map<string, string>& GetDefaultParams(PbDeviceType type) { return default_params[type]; }
Device *CreateDevice(PbDeviceType type, const string& filename, const string& ext);
const list<string> GetNetworkInterfaces() const;
private:

View File

@ -528,15 +528,40 @@ void GetAllDeviceTypeProperties(PbServerInfo& server_info)
void GetAvailableImages(PbServerInfo& server_info)
{
PbImageFilesInfo *image_files_info = new PbImageFilesInfo();
server_info.set_allocated_image_files_info(image_files_info);
image_files_info->set_default_image_folder(default_image_folder);
if (!access(default_image_folder.c_str(), F_OK)) {
for (const auto& entry : filesystem::directory_iterator(default_image_folder, filesystem::directory_options::skip_permission_denied)) {
if (entry.is_regular_file() && entry.file_size() && !(entry.file_size() & 0x1ff)) {
GetImageFile(server_info.add_image_files(), entry.path().filename());
GetImageFile(image_files_info->add_image_files(), entry.path().filename());
}
}
}
}
void GetAvailableImages(PbImageFilesInfo& image_files_info)
{
image_files_info.set_default_image_folder(default_image_folder);
if (!access(default_image_folder.c_str(), F_OK)) {
for (const auto& entry : filesystem::directory_iterator(default_image_folder, filesystem::directory_options::skip_permission_denied)) {
if (entry.is_regular_file() && entry.file_size() && !(entry.file_size() & 0x1ff)) {
GetImageFile(image_files_info.add_image_files(), entry.path().filename());
}
}
}
}
void GetNetworkInterfacesInfo(PbNetworkInterfacesInfo& network_interfaces_info)
{
for (const auto& network_interface : device_factory.GetNetworkInterfaces()) {
network_interfaces_info.add_name(network_interface);
}
}
void GetDevice(const Device *device, PbDevice *pb_device)
{
pb_device->set_id(device->GetId());
@ -634,9 +659,11 @@ void GetServerInfo(PbResult& result)
server_info->set_patch_version(rascsi_patch_version);
GetLogLevels(*server_info);
server_info->set_current_log_level(current_log_level);
server_info->set_default_image_folder(default_image_folder);
GetAllDeviceTypeProperties(*server_info);
GetAvailableImages(*server_info);
PbNetworkInterfacesInfo * network_interfaces_info = new PbNetworkInterfacesInfo();
server_info->set_allocated_network_interfaces_info(network_interfaces_info);
GetNetworkInterfacesInfo(*network_interfaces_info);
GetDevices(*server_info);
for (int id : reserved_ids) {
server_info->add_reserved_ids(id);
@ -1703,7 +1730,7 @@ static void *MonThread(void *param)
switch(command.operation()) {
case LOG_LEVEL: {
LOGTRACE(string("Received " + PbOperation_Name(LOG_LEVEL) + " command").c_str());
LOGTRACE(string("Received " + PbOperation_Name(command.operation()) + " command").c_str());
string log_level = GetParam(command, "level");
bool status = SetLogLevel(log_level);
@ -1717,7 +1744,7 @@ static void *MonThread(void *param)
}
case DEFAULT_FOLDER: {
LOGTRACE(string("Received " + PbOperation_Name(DEFAULT_FOLDER) + " command").c_str());
LOGTRACE(string("Received " + PbOperation_Name(command.operation()) + " command").c_str());
string folder = GetParam(command, "folder");
if (folder.empty()) {
@ -1734,7 +1761,7 @@ static void *MonThread(void *param)
}
case DEVICE_INFO: {
LOGTRACE(string("Received " + PbOperation_Name(DEVICE_INFO) + " command").c_str());
LOGTRACE(string("Received " + PbOperation_Name(command.operation()) + " command").c_str());
PbResult result;
result.set_status(true);
@ -1750,7 +1777,7 @@ static void *MonThread(void *param)
}
case SERVER_INFO: {
LOGTRACE(string("Received " + PbOperation_Name(SERVER_INFO) + " command").c_str());
LOGTRACE(string("Received " + PbOperation_Name(command.operation()) + " command").c_str());
PbResult result;
result.set_status(true);
@ -1759,6 +1786,30 @@ static void *MonThread(void *param)
break;
}
case IMAGE_FILES_INFO: {
LOGTRACE(string("Received " + PbOperation_Name(command.operation()) + " command").c_str());
PbImageFilesInfo *image_files_info = new PbImageFilesInfo();
GetAvailableImages(*image_files_info);
PbResult result;
result.set_status(true);
result.set_allocated_image_files_info(image_files_info);
SerializeMessage(fd, result);
break;
}
case NETWORK_INTERFACES_INFO: {
LOGTRACE(string("Received " + PbOperation_Name(command.operation()) + " command").c_str());
PbNetworkInterfacesInfo *network_interfaces_info = new PbNetworkInterfacesInfo();
GetNetworkInterfacesInfo(*network_interfaces_info);
PbResult result;
result.set_status(true);
result.set_allocated_network_interfaces_info(network_interfaces_info);
SerializeMessage(fd, result);
break;
}
default: {
// Wait until we become idle
while (active) {

View File

@ -66,59 +66,65 @@ enum PbOperation {
// Gets the server information
SERVER_INFO = 10;
// Gets information for a list of attached devices. Returns data for all attached devices if empty.
// Gets information on attached devices. Returns data for all attached devices if empty.
DEVICE_INFO = 11;
// Gets information on available image files. A lightweight alternative to getting the complete server info.
IMAGE_FILES_INFO = 12;
// Gets the names of the available network interfaces. Only lists interfaces that are up.
NETWORK_INTERFACES_INFO = 13;
// Set the default folder for image files.
// Parameters:
// "folder": The default folder name.
DEFAULT_FOLDER = 12;
DEFAULT_FOLDER = 14;
// Set server log level.
// Parameters:
// "level": The new log level
LOG_LEVEL = 13;
LOG_LEVEL = 15;
// 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 = 14;
RESERVE = 16;
// 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 = 15;
CREATE_IMAGE = 17;
// Delete an image file.
// Parameters:
// "file": The filename, relative to the default image folder. It must not contain a slash.
DELETE_IMAGE = 16;
DELETE_IMAGE = 18;
// 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 = 17;
RENAME_IMAGE = 19;
// 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 = 18;
COPY_IMAGE = 20;
// Write-protect an image file.
// Parameters:
// "file": The filename, relative to the default image folder. It must not contain a slash.
PROTECT_IMAGE = 19;
PROTECT_IMAGE = 21;
// Make an image file writable.
// Parameters:
// "file": The filename, relative to the default image folder. It must not contain a slash.
UNPROTECT_IMAGE = 20;
UNPROTECT_IMAGE = 22;
}
// The properties supported by a device
@ -172,6 +178,17 @@ message PbImageFile {
int64 size = 3;
}
// The default image folder and the image files it contains
message PbImageFilesInfo {
string default_image_folder = 1;
repeated PbImageFile image_files = 2;
}
// The network interfaces information
message PbNetworkInterfacesInfo {
repeated string name = 1;
}
// The device definition, sent from the client to the server
message PbDeviceDefinition {
int32 id = 1;
@ -234,6 +251,10 @@ message PbResult {
PbServerInfo server_info = 3;
// The result of a DEVICE_INFO command
PbDevices device_info = 4;
// The result of an IMAGE_FILES_INFO command
PbImageFilesInfo image_files_info = 5;
// The result of a NETWORK_INTERFACES_INFO command
PbNetworkInterfacesInfo network_interfaces_info = 6;
}
}
@ -247,11 +268,10 @@ message PbServerInfo {
// List of available log levels, ordered by increasing by severity
repeated string log_levels = 4;
string current_log_level = 5;
string default_image_folder = 6;
// Supported device types and their properties
repeated PbDeviceTypeProperties types_properties = 7;
// Unordered list of files in the default image folder
repeated PbImageFile image_files = 8;
repeated PbDeviceTypeProperties types_properties = 6;
PbImageFilesInfo image_files_info = 7;
PbNetworkInterfacesInfo network_interfaces_info = 8;
// The attached devices
repeated PbDevice devices = 9;
// The unsorted list of reserved IDs

View File

@ -154,23 +154,50 @@ void DisplayDeviceInfo(const PbDevice& pb_device)
cout << endl;
}
void DisplayImageFiles(const list<PbImageFile> image_files, const string& default_image_folder)
{
cout << "Default image file folder: " << default_image_folder << endl;
if (image_files.empty()) {
cout << " No image files available" << endl;
}
else {
list<PbImageFile> files = { image_files.begin(), image_files.end() };
files.sort([](const auto& a, const auto& b) { return a.name() < b.name(); });
cout << "Available image files:" << endl;
for (const auto& file : files) {
cout << " " << file.name() << " (" << file.size() << " bytes)";
if (file.read_only()) {
cout << ", read-only";
}
cout << endl;
}
}
}
void DisplayNetworkInterfaces(list<string> interfaces)
{
interfaces.sort([](const auto& a, const auto& b) { return a < b; });
cout << "Available (up) network interfaces:" << endl;
bool isFirst = true;
for (const auto& interface : interfaces) {
if (!isFirst) {
cout << ", ";
}
isFirst = false;
cout << interface;
}
cout << endl;
}
//---------------------------------------------------------------------------
//
// Command implementations
//
//---------------------------------------------------------------------------
const PbServerInfo GetServerInfo(const string& hostname, int port)
{
PbCommand command;
command.set_operation(SERVER_INFO);
PbResult result;
SendCommand(hostname.c_str(), port, command, result);
return result.server_info();
}
void CommandList(const string& hostname, int port)
{
PbCommand command;
@ -183,31 +210,32 @@ void CommandList(const string& hostname, int port)
cout << ListDevices(devices) << endl;
}
void CommandLogLevel(const string& hostname, int port, const string& log_level)
const PbServerInfo GetServerInfo(const PbCommand& command, const string& hostname, int port)
{
PbResult result;
SendCommand(hostname.c_str(), port, command, result);
return result.server_info();
}
void CommandLogLevel(PbCommand& command, const string& hostname, int port, const string& log_level)
{
PbCommand command;
command.set_operation(LOG_LEVEL);
AddParam(command, "level", log_level);
PbResult result;
SendCommand(hostname.c_str(), port, command, result);
}
void CommandReserve(const string&hostname, int port, const string& reserved_ids)
void CommandReserve(PbCommand& command, const string&hostname, int port, const string& reserved_ids)
{
PbCommand command;
command.set_operation(RESERVE);
AddParam(command, "ids", reserved_ids);
PbResult result;
SendCommand(hostname.c_str(), port, command, result);
}
void CommandCreateImage(const string&hostname, int port, const string& image_params)
void CommandCreateImage(PbCommand& command, const string&hostname, int port, const string& image_params)
{
PbCommand command;
command.set_operation(CREATE_IMAGE);
size_t separatorPos = image_params.find(COMPONENT_SEPARATOR);
if (separatorPos != string::npos) {
AddParam(command, "file", image_params.substr(0, separatorPos));
@ -224,21 +252,16 @@ void CommandCreateImage(const string&hostname, int port, const string& image_par
SendCommand(hostname.c_str(), port, command, result);
}
void CommandDeleteImage(const string&hostname, int port, const string& filename)
void CommandDeleteImage(PbCommand& command, const string&hostname, int port, const string& filename)
{
PbCommand command;
command.set_operation(DELETE_IMAGE);
AddParam(command, "file", filename);
PbResult result;
SendCommand(hostname.c_str(), port, command, result);
}
void CommandRenameImage(const string&hostname, int port, const string& image_params)
void CommandRenameImage(PbCommand& command, const string&hostname, int port, const string& image_params)
{
PbCommand command;
command.set_operation(RENAME_IMAGE);
size_t separatorPos = image_params.find(COMPONENT_SEPARATOR);
if (separatorPos != string::npos) {
AddParam(command, "from", image_params.substr(0, separatorPos));
@ -253,11 +276,8 @@ void CommandRenameImage(const string&hostname, int port, const string& image_par
SendCommand(hostname.c_str(), port, command, result);
}
void CommandCopyImage(const string&hostname, int port, const string& image_params)
void CommandCopyImage(PbCommand& command, const string&hostname, int port, const string& image_params)
{
PbCommand command;
command.set_operation(COPY_IMAGE);
size_t separatorPos = image_params.find(COMPONENT_SEPARATOR);
if (separatorPos != string::npos) {
AddParam(command, "from", image_params.substr(0, separatorPos));
@ -272,17 +292,15 @@ void CommandCopyImage(const string&hostname, int port, const string& image_param
SendCommand(hostname.c_str(), port, command, result);
}
void CommandDefaultImageFolder(const string& hostname, int port, const string& folder)
void CommandDefaultImageFolder(PbCommand& command, const string& hostname, int port, const string& folder)
{
PbCommand command;
command.set_operation(DEFAULT_FOLDER);
AddParam(command, "folder", folder);
PbResult result;
SendCommand(hostname.c_str(), port, command, result);
}
void CommandDeviceInfo(const string& hostname, int port, const PbCommand& command)
void CommandDeviceInfo(const PbCommand& command, const string& hostname, int port)
{
PbResult result;
SendCommand(hostname.c_str(), port, command, result);
@ -292,11 +310,8 @@ void CommandDeviceInfo(const string& hostname, int port, const PbCommand& comman
}
}
void CommandServerInfo(const string& hostname, int port)
void CommandServerInfo(PbCommand& command, const string& hostname, int port)
{
PbCommand command;
command.set_operation(SERVER_INFO);
PbResult result;
SendCommand(hostname.c_str(), port, command, result);
@ -316,30 +331,20 @@ void CommandServerInfo(const string& hostname, int port)
}
else {
cout << "rascsi log levels, sorted by severity:" << endl;
for (int i = 0; i < server_info.log_levels_size(); i++) {
cout << " " << server_info.log_levels(i) << endl;
for (const auto& log_level : server_info.log_levels()) {
cout << " " << log_level << endl;
}
cout << "Current rascsi log level: " << server_info.current_log_level() << endl;
}
cout << "Default image file folder: " << server_info.default_image_folder() << endl;
if (!server_info.image_files_size()) {
cout << " No image files available" << endl;
}
else {
list<PbImageFile> files = { server_info.image_files().begin(), server_info.image_files().end() };
files.sort([](const auto& a, const auto& b) { return a.name() < b.name(); });
const list<PbImageFile> image_files =
{ server_info.image_files_info().image_files().begin(), server_info.image_files_info().image_files().end() };
DisplayImageFiles(image_files, server_info.image_files_info().default_image_folder());
cout << "Available image files:" << endl;
for (const auto& file : files) {
cout << " " << file.name() << " (" << file.size() << " bytes)";
if (file.read_only()) {
cout << ", read-only";
}
cout << endl;
}
}
const list<string> network_interfaces =
{ server_info.network_interfaces_info().name().begin(), server_info.network_interfaces_info().name().end() };
DisplayNetworkInterfaces(network_interfaces);
cout << "Supported device types and their properties:" << endl;
for (auto it = server_info.types_properties().begin(); it != server_info.types_properties().end(); ++it) {
@ -459,6 +464,26 @@ void CommandServerInfo(const string& hostname, int port)
}
}
void CommandImageFilesInfo(const PbCommand& command, const string& hostname, int port)
{
PbResult result;
SendCommand(hostname.c_str(), port, command, result);
const list<PbImageFile> image_files =
{ result.image_files_info().image_files().begin(),result.image_files_info().image_files().end() };
DisplayImageFiles(image_files, result.image_files_info().default_image_folder());
}
void CommandNetworkInterfacesInfo(const PbCommand& command, const string&hostname, int port)
{
PbResult result;
SendCommand(hostname.c_str(), port, command, result);
list<string> network_interfaces =
{ result.network_interfaces_info().name().begin(), result.network_interfaces_info().name().end() };
DisplayNetworkInterfaces(network_interfaces);
}
PbOperation ParseOperation(const char *optarg)
{
switch (tolower(optarg[0])) {
@ -539,7 +564,7 @@ int main(int argc, char* argv[])
cerr << "Usage: " << argv[0] << " -i ID [-u UNIT] [-c CMD] [-t TYPE] [-b BLOCK_SIZE] [-n NAME] [-f FILE|PARAM] ";
cerr << "[-d IMAGE_FOLDER] [-g LOG_LEVEL] [-h HOST] [-p PORT] [-r RESERVED_IDS] ";
cerr << "[-a FILENAME:FILESIZE] [-w FILENAME] [-m CURRENT_NAME:NEW_NAME] [-x CURRENT_NAME:NEW_NAME] ";
cerr << "[-l] [-v]" << endl;
cerr << "[-e] [-k] [-l] [-v]" << 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;
@ -575,7 +600,7 @@ int main(int argc, char* argv[])
opterr = 1;
int opt;
while ((opt = getopt(argc, argv, "a:b:c:d:f:g:h:i:m:n:p:r:t:u:x:w:lsv")) != -1) {
while ((opt = getopt(argc, argv, "a:b:c:d:f:g:h:i:m:n:p:r:t:u:x:w:eklsv")) != -1) {
switch (opt) {
case 'i':
device->set_id(optarg[0] - '0');
@ -612,10 +637,18 @@ int main(int argc, char* argv[])
default_folder = optarg;
break;
case'e':
command.set_operation(IMAGE_FILES_INFO);
break;
case 'f':
param = optarg;
break;
case 'k':
command.set_operation(NETWORK_INTERFACES_INFO);
break;
case 't':
device->set_type(ParseType(optarg));
if (device->type() == UNDEFINED) {
@ -710,39 +743,47 @@ int main(int argc, char* argv[])
switch(command.operation()) {
case LOG_LEVEL:
CommandLogLevel(hostname, port, log_level);
CommandLogLevel(command, hostname, port, log_level);
exit(EXIT_SUCCESS);
case DEFAULT_FOLDER:
CommandDefaultImageFolder(hostname, port, default_folder);
CommandDefaultImageFolder(command, hostname, port, default_folder);
exit(EXIT_SUCCESS);
case RESERVE:
CommandReserve(hostname, port, reserved_ids);
CommandReserve(command, hostname, port, reserved_ids);
exit(EXIT_SUCCESS);
case CREATE_IMAGE:
CommandCreateImage(hostname, port, image_params);
CommandCreateImage(command, hostname, port, image_params);
exit(EXIT_SUCCESS);
case DELETE_IMAGE:
CommandDeleteImage(hostname, port, image_params);
CommandDeleteImage(command, hostname, port, image_params);
exit(EXIT_SUCCESS);
case RENAME_IMAGE:
CommandRenameImage(hostname, port, image_params);
CommandRenameImage(command, hostname, port, image_params);
exit(EXIT_SUCCESS);
case COPY_IMAGE:
CommandCopyImage(hostname, port, image_params);
CommandCopyImage(command, hostname, port, image_params);
exit(EXIT_SUCCESS);
case DEVICE_INFO:
CommandDeviceInfo(hostname, port, command);
CommandDeviceInfo(command, hostname, port);
exit(EXIT_SUCCESS);
case SERVER_INFO:
CommandServerInfo(hostname, port);
CommandServerInfo(command, hostname, port);
exit(EXIT_SUCCESS);
case IMAGE_FILES_INFO:
CommandImageFilesInfo(command, hostname, port);
exit(EXIT_SUCCESS);
case NETWORK_INTERFACES_INFO:
CommandNetworkInterfacesInfo(command, hostname, port);
exit(EXIT_SUCCESS);
default: