Squashed commit of the following:

commit 94786aec54
Author: Uwe Seimet <48174652+uweseimet@users.noreply.github.com>
Date:   Tue Dec 21 08:43:21 2021 +0100

    Added support for operation meta data, code cleanup (#534)

    * Added messages

    * Comment update

    * Interface update

    * Support for localized descriptions

    * Sort operations

    * Completed meta data

    * rasctl -s returns operation meta data

    * Manpage update

    * Type update

    * Comment update

    * Description updates

    * Comment update

    * Added convenience method

    * Added convenience method

    * Code cleanup

    * Comment update

    * Display permitted values

    * For completeness sake added permitted boolean values

    * Added support for default value

    * Removed redundant message field

    * Description update

    * Description upddate

    * Squashed commit of the following:

    commit 8171c6ea27982c736c30c0db69a7fdde07ee10ce
    Author: Uwe Seimet <Uwe.Seimet@seimet.de>
    Date:   Sat Dec 18 12:43:14 2021 +0100

        The data type is implicit

    commit fb01dc9d82e8ff7456b05a0cb9d08069adacc64c
    Author: Uwe Seimet <Uwe.Seimet@seimet.de>
    Date:   Sat Dec 18 12:37:49 2021 +0100

        Renaming

    commit 057dbf1aca7be3f7e76a5ff89a582a276b6d3089
    Author: Uwe Seimet <Uwe.Seimet@seimet.de>
    Date:   Sat Dec 18 12:29:54 2021 +0100

        Comment update

    commit 5f699aad2f835f72accdb445d1e59f094aeb108f
    Author: Uwe Seimet <Uwe.Seimet@seimet.de>
    Date:   Sat Dec 18 12:24:25 2021 +0100

        Signature update

    commit cbcf8b09f9d1ba7b82f816269bcfe91d9f00eb6e
    Author: Uwe Seimet <Uwe.Seimet@seimet.de>
    Date:   Sat Dec 18 12:22:45 2021 +0100

        Signature update

    commit a8148ef802ca809e5a305d2caa69856c9033d932
    Author: Uwe Seimet <Uwe.Seimet@seimet.de>
    Date:   Sat Dec 18 12:16:46 2021 +0100

        Comment update

    commit ce685a92d4827e131d80d10ecd56e2b3baf173f8
    Author: Uwe Seimet <Uwe.Seimet@seimet.de>
    Date:   Sat Dec 18 12:15:46 2021 +0100

        Use map instead of list

    commit 454c0438f3589904f5dbe5253963dd200ea416dd
    Author: Uwe Seimet <Uwe.Seimet@seimet.de>
    Date:   Sat Dec 18 10:47:36 2021 +0100

        Updated size check

    commit b386dbba4b0262f4f6f02aecb2a1daeffd41f4a2
    Author: Uwe Seimet <Uwe.Seimet@seimet.de>
    Date:   Sat Dec 18 01:23:43 2021 +0100

        Initial improvements

    * Default value update

    * Comment update

    * Comment update

    * Map operations by ordinal

    * Added safeguard against unknown operations

    * Added cast

    * Data type update

    * Sort map by operation name

    * Renaming

    * Code cleanup

    * Comment update

    * Renaming

    * Comment update

    * Description updates

    * Fixed typo

    * Added operation

    * Logging update

    * Interface comment update

    * Fixed typo

    * Aded operation parameters

    * Updated handling of mandatory parameters

    * Updated assertion handling

    * Added missing condition

    * Removed duplicate cod3

    * Code cleanup

    * Logging update

    * Removed duplicate code

    * Code cleanup

    * Squashed commit of the following:

    commit 4ae273ccbd
    Author: akuker <34318535+akuker@users.noreply.github.com>
    Date:   Sun Dec 19 22:30:22 2021 -0600

        Loopback tester pcb (#545)

    commit 46c5c1966f
    Author: akuker <34318535+akuker@users.noreply.github.com>
    Date:   Sun Dec 19 22:29:59 2021 -0600

        RaSCSI Zero version 1.0 (#546)

    commit d09df31d67
    Author: Daniel Markstedt <markstedt@gmail.com>
    Date:   Sun Dec 19 20:25:23 2021 -0800

        Remove redundant code from OLED script (#547)

    commit d8828da690
    Author: akuker <34318535+akuker@users.noreply.github.com>
    Date:   Sun Dec 19 21:02:50 2021 -0600

        Added list of sponsors

    commit bcd7e8396d
    Author: Daniel Markstedt <markstedt@gmail.com>
    Date:   Sun Dec 19 15:51:45 2021 -0800

        Second attempt at properly creating the manpage dir (#542)

    commit c887edfc8c
    Author: Daniel Markstedt <markstedt@gmail.com>
    Date:   Sun Dec 19 15:50:03 2021 -0800

        Remove special elevated privileges for the Web Interface (#536)

        * Use the pi_shutdown method to restart the rascsi service

        * Use the pi_shutdown method to restart the rascsi service

        * Remove modifications to sudoers no longer needed

        * Introduce sleeps attempting to connect to socket; reduce overall number of retries

        * Remove systemd helped methods and the functionality that depends on it

        * Attempts to speed up splash code

        * Remove unneccessary verbosity

        * Attempt to optimize service definition

    commit 801aebfb96
    Author: Daniel Markstedt <markstedt@gmail.com>
    Date:   Sun Dec 19 15:47:22 2021 -0800

        More readable message when downloading a file (#531)

    commit 29cf58288f
    Author: Daniel Markstedt <markstedt@gmail.com>
    Date:   Sun Dec 19 15:47:03 2021 -0800

        Add a warning notice when ejecting removable media (#526)

    commit 7efa895239
    Author: Daniel Markstedt <markstedt@gmail.com>
    Date:   Sun Dec 19 15:46:22 2021 -0800

        Unzip zipfiles before storing to iso (#525)

        * Unzip zipfiles before storing to iso

        * Add helptext

        * Skip unzip for MacZip format

        * Should not be an fstring

    commit 39bc485671
    Author: Daniel Markstedt <markstedt@gmail.com>
    Date:   Sun Dec 19 15:28:22 2021 -0800

        Add pip3 to global dependencies; remove duplicates from monitor_rascs… (#523)

        * Add pip3 to global dependencies; remove duplicates from monitor_rascsi dependencies

        * Cleanup

    * Shutdown functionality is only available if started with root permissions

    * Only restrict shutdown parameters, not everything if not root

    * Updated operation count check

commit 693ade2967
Author: Daniel Markstedt <markstedt@gmail.com>
Date:   Mon Dec 20 12:04:23 2021 -0800

    Bump Macproxy version to 21.12.2 (#550)

commit 958fb95908
Author: akuker <34318535+akuker@users.noreply.github.com>
Date:   Mon Dec 20 12:50:14 2021 -0600

    Adjust bus settle delay to match SCSI standard (#544)

    * Move the GCC v10 compiler flags into makefile instead of easyinstall.sh

    * #504 - Update the bus settle time to match the SCSI standard

    Co-authored-by: RaSCSI User <user@rascsi.com>

commit 200bc7251f
Author: Daniel Markstedt <markstedt@gmail.com>
Date:   Mon Dec 20 06:20:22 2021 -0800

    More helpful error message when IP does not resolve for OLED screen (#541)

    * More helpful error message

    * Remove confusing fallback IP

    * Tweak message

commit 4ae273ccbd
Author: akuker <34318535+akuker@users.noreply.github.com>
Date:   Sun Dec 19 22:30:22 2021 -0600

    Loopback tester pcb (#545)

commit 46c5c1966f
Author: akuker <34318535+akuker@users.noreply.github.com>
Date:   Sun Dec 19 22:29:59 2021 -0600

    RaSCSI Zero version 1.0 (#546)

commit d09df31d67
Author: Daniel Markstedt <markstedt@gmail.com>
Date:   Sun Dec 19 20:25:23 2021 -0800

    Remove redundant code from OLED script (#547)

commit d8828da690
Author: akuker <34318535+akuker@users.noreply.github.com>
Date:   Sun Dec 19 21:02:50 2021 -0600

    Added list of sponsors

commit bcd7e8396d
Author: Daniel Markstedt <markstedt@gmail.com>
Date:   Sun Dec 19 15:51:45 2021 -0800

    Second attempt at properly creating the manpage dir (#542)

commit c887edfc8c
Author: Daniel Markstedt <markstedt@gmail.com>
Date:   Sun Dec 19 15:50:03 2021 -0800

    Remove special elevated privileges for the Web Interface (#536)

    * Use the pi_shutdown method to restart the rascsi service

    * Use the pi_shutdown method to restart the rascsi service

    * Remove modifications to sudoers no longer needed

    * Introduce sleeps attempting to connect to socket; reduce overall number of retries

    * Remove systemd helped methods and the functionality that depends on it

    * Attempts to speed up splash code

    * Remove unneccessary verbosity

    * Attempt to optimize service definition

commit 801aebfb96
Author: Daniel Markstedt <markstedt@gmail.com>
Date:   Sun Dec 19 15:47:22 2021 -0800

    More readable message when downloading a file (#531)

commit 29cf58288f
Author: Daniel Markstedt <markstedt@gmail.com>
Date:   Sun Dec 19 15:47:03 2021 -0800

    Add a warning notice when ejecting removable media (#526)

commit 7efa895239
Author: Daniel Markstedt <markstedt@gmail.com>
Date:   Sun Dec 19 15:46:22 2021 -0800

    Unzip zipfiles before storing to iso (#525)

    * Unzip zipfiles before storing to iso

    * Add helptext

    * Skip unzip for MacZip format

    * Should not be an fstring

commit 39bc485671
Author: Daniel Markstedt <markstedt@gmail.com>
Date:   Sun Dec 19 15:28:22 2021 -0800

    Add pip3 to global dependencies; remove duplicates from monitor_rascs… (#523)

    * Add pip3 to global dependencies; remove duplicates from monitor_rascsi dependencies

    * Cleanup
This commit is contained in:
Uwe Seimet 2021-12-21 08:53:30 +01:00
parent f59eeb842e
commit ea3bb8363a
17 changed files with 339 additions and 63 deletions

View File

@ -83,6 +83,9 @@ List all of the devices that are currently being emulated by RaSCSI, as well as
.BR \-m\fI .BR \-m\fI
List all file extensions recognized by RaSCSI and the device types they map to. List all file extensions recognized by RaSCSI and the device types they map to.
.TP .TP
.BR \-o\fI
Display operation meta data information.
.TP
.BR \-R\fI " "\fICURRENT_NAME:NEW_NAME .BR \-R\fI " "\fICURRENT_NAME:NEW_NAME
Rename an image file in the default image folder. Rename an image file in the default image folder.
.TP .TP

View File

@ -62,6 +62,8 @@ OPTIONS
-m List all file extensions recognized by RaSCSI and the device -m List all file extensions recognized by RaSCSI and the device
types they map to. types they map to.
-o Display operation meta data information.
-R CURRENT_NAME:NEW_NAME -R CURRENT_NAME:NEW_NAME
Rename an image file in the default image folder. Rename an image file in the default image folder.

View File

@ -83,15 +83,8 @@ function installPackages() {
function compileRaScsi() { function compileRaScsi() {
cd "$BASE/src/raspberrypi" || exit 1 cd "$BASE/src/raspberrypi" || exit 1
# Compiler flags needed for gcc v10 and up
if [[ `gcc --version | awk '/gcc/' | awk -F ' ' '{print $3}' | awk -F '.' '{print $1}'` -ge 10 ]]; then
echo -n "gcc 10 or later detected. Will compile with the following flags: "
COMPILER_FLAGS="-DFMT_HEADER_ONLY"
echo $COMPILER_FLAGS
fi
echo "Compiling with ${CORES:-1} simultaneous cores..." echo "Compiling with ${CORES:-1} simultaneous cores..."
( make clean && EXTRA_FLAGS="$COMPILER_FLAGS" make -j "${CORES:-1}" all CONNECT_TYPE="${CONNECT_TYPE:-FULLSPEC}" ) </dev/null ( make clean && make -j "${CORES:-1}" all CONNECT_TYPE="${CONNECT_TYPE:-FULLSPEC}" ) </dev/null
} }
# install the RaSCSI binaries and modify the service configuration # install the RaSCSI binaries and modify the service configuration
@ -680,7 +673,7 @@ function installMacproxy {
( sudo apt-get update && sudo apt-get install python3 python3-venv --assume-yes ) </dev/null ( sudo apt-get update && sudo apt-get install python3 python3-venv --assume-yes ) </dev/null
MACPROXY_VER="21.12.1" MACPROXY_VER="21.12.2"
MACPROXY_PATH="$HOME/macproxy-$MACPROXY_VER" MACPROXY_PATH="$HOME/macproxy-$MACPROXY_VER"
if [ -d "$MACPROXY_PATH" ]; then if [ -d "$MACPROXY_PATH" ]; then
echo "The $MACPROXY_PATH directory already exists. Delete it to proceed with the installation." echo "The $MACPROXY_PATH directory already exists. Delete it to proceed with the installation."

View File

@ -14,7 +14,7 @@ def get_ip_and_host():
sock.connect(('10.255.255.255', 1)) sock.connect(('10.255.255.255', 1))
ip_addr = sock.getsockname()[0] ip_addr = sock.getsockname()[0]
except Exception: except Exception:
ip_addr = '127.0.0.1' ip_addr = False
finally: finally:
sock.close() sock.close()
return ip_addr, host return ip_addr, host

View File

@ -161,7 +161,11 @@ def formatted_output():
else: else:
output.append("No image mounted!") output.append("No image mounted!")
output.append(f"IP {IP_ADDR} - {HOSTNAME}") if IP_ADDR:
output.append(f"IP {IP_ADDR} - {HOSTNAME}")
else:
output.append("RaSCSI has no IP address")
output.append("Check network connection")
return output return output

View File

@ -31,6 +31,16 @@ CXXFLAGS += -std=c++17 -Wno-psabi -iquote . -D_FILE_OFFSET_BITS=64 -MD -MP
CFLAGS += $(EXTRA_FLAGS) CFLAGS += $(EXTRA_FLAGS)
CXXFLAGS += $(EXTRA_FLAGS) CXXFLAGS += $(EXTRA_FLAGS)
# If we're using GCC version 10 or later, we need to add the FMT_HEADER_ONLY definition
GCCVERSION10 := $(shell expr `gcc -dumpversion` \>= 10)
ifeq "$(GCCVERSION10)" "1"
CFLAGS += -DFMT_HEADER_ONLY
CXXFLAGS += -DFMT_HEADER_ONLY
endif
## CONNECT_TYPE=FULLSPEC : Specify the type of RaSCSI board type ## CONNECT_TYPE=FULLSPEC : Specify the type of RaSCSI board type
## that you are using. The typical options are ## that you are using. The typical options are
## STANDARD or FULLSPEC. The default is FULLSPEC ## STANDARD or FULLSPEC. The default is FULLSPEC

View File

@ -840,7 +840,7 @@ int GPIOBUS::CommandHandShake(BYTE *buf)
BOOL ret = WaitSignal(PIN_ACK, TRUE); BOOL ret = WaitSignal(PIN_ACK, TRUE);
// Wait until the signal line stabilizes // Wait until the signal line stabilizes
SysTimer::SleepNsec(GPIO_DATA_SETTLING); SysTimer::SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS);
// Get data // Get data
*buf = GetDAT(); *buf = GetDAT();
@ -874,7 +874,7 @@ int GPIOBUS::CommandHandShake(BYTE *buf)
ret = WaitSignal(PIN_ACK, TRUE); ret = WaitSignal(PIN_ACK, TRUE);
// Wait until the signal line stabilizes // Wait until the signal line stabilizes
SysTimer::SleepNsec(GPIO_DATA_SETTLING); SysTimer::SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS);
// Get data // Get data
*buf = GetDAT(); *buf = GetDAT();
@ -930,7 +930,7 @@ int GPIOBUS::ReceiveHandShake(BYTE *buf, int count)
ret = WaitSignal(PIN_ACK, TRUE); ret = WaitSignal(PIN_ACK, TRUE);
// Wait until the signal line stabilizes // Wait until the signal line stabilizes
SysTimer::SleepNsec(GPIO_DATA_SETTLING); SysTimer::SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS);
// Get data // Get data
*buf = GetDAT(); *buf = GetDAT();
@ -973,7 +973,7 @@ int GPIOBUS::ReceiveHandShake(BYTE *buf, int count)
} }
// Wait until the signal line stabilizes // Wait until the signal line stabilizes
SysTimer::SleepNsec(GPIO_DATA_SETTLING); SysTimer::SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS);
// Get data // Get data
*buf = GetDAT(); *buf = GetDAT();

View File

@ -433,7 +433,6 @@
// Constant declarations (bus control timing) // Constant declarations (bus control timing)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#define GPIO_DATA_SETTLING 100 // Data bus stabilization time (ns)
// SCSI Bus timings taken from: // SCSI Bus timings taken from:
// https://www.staff.uni-mainz.de/tacke/scsi/SCSI2-05.html // https://www.staff.uni-mainz.de/tacke/scsi/SCSI2-05.html
#define SCSI_DELAY_ARBITRATION_DELAY_NS 2400 #define SCSI_DELAY_ARBITRATION_DELAY_NS 2400

View File

@ -484,6 +484,8 @@ bool SetLogLevel(const string& log_level)
current_log_level = log_level; current_log_level = log_level;
LOGINFO("Set log level to '%s'", current_log_level.c_str());
return true; return true;
} }
@ -1431,10 +1433,19 @@ static void *MonThread(void *param)
} }
} }
if (!PbOperation_IsValid(command.operation())) {
LOGTRACE("Received unknown command %d", command.operation());
ReturnStatus(fd, false, "Unknown command", UNKNOWN_OPERATION);
continue;
}
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
PbResult result;
switch(command.operation()) { switch(command.operation()) {
case LOG_LEVEL: { case LOG_LEVEL: {
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
string log_level = GetParam(command, "level"); string log_level = GetParam(command, "level");
bool status = SetLogLevel(log_level); bool status = SetLogLevel(log_level);
if (!status) { if (!status) {
@ -1447,8 +1458,6 @@ static void *MonThread(void *param)
} }
case DEFAULT_FOLDER: { case DEFAULT_FOLDER: {
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
string folder = GetParam(command, "folder"); string folder = GetParam(command, "folder");
if (folder.empty()) { if (folder.empty()) {
ReturnStatus(fd, false, "Can't set default image folder: Missing folder name"); ReturnStatus(fd, false, "Can't set default image folder: Missing folder name");
@ -1465,28 +1474,18 @@ static void *MonThread(void *param)
} }
case DEVICES_INFO: { case DEVICES_INFO: {
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
PbResult result;
rascsi_response.GetDevicesInfo(result, command, devices, UnitNum); rascsi_response.GetDevicesInfo(result, command, devices, UnitNum);
SerializeMessage(fd, result); SerializeMessage(fd, result);
break; break;
} }
case DEVICE_TYPES_INFO: { case DEVICE_TYPES_INFO: {
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
PbResult result;
result.set_allocated_device_types_info(rascsi_response.GetDeviceTypesInfo(result, command)); result.set_allocated_device_types_info(rascsi_response.GetDeviceTypesInfo(result, command));
SerializeMessage(fd, result); SerializeMessage(fd, result);
break; break;
} }
case SERVER_INFO: { case SERVER_INFO: {
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
PbResult result;
result.set_allocated_server_info(rascsi_response.GetServerInfo( result.set_allocated_server_info(rascsi_response.GetServerInfo(
result, devices, reserved_ids, current_log_level, GetParam(command, "folder_pattern"), result, devices, reserved_ids, current_log_level, GetParam(command, "folder_pattern"),
GetParam(command, "file_pattern"), scan_depth)); GetParam(command, "file_pattern"), scan_depth));
@ -1495,27 +1494,18 @@ static void *MonThread(void *param)
} }
case VERSION_INFO: { case VERSION_INFO: {
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
PbResult result;
result.set_allocated_version_info(rascsi_response.GetVersionInfo(result)); result.set_allocated_version_info(rascsi_response.GetVersionInfo(result));
SerializeMessage(fd, result); SerializeMessage(fd, result);
break; break;
} }
case LOG_LEVEL_INFO: { case LOG_LEVEL_INFO: {
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
PbResult result;
result.set_allocated_log_level_info(rascsi_response.GetLogLevelInfo(result, current_log_level)); result.set_allocated_log_level_info(rascsi_response.GetLogLevelInfo(result, current_log_level));
SerializeMessage(fd, result); SerializeMessage(fd, result);
break; break;
} }
case DEFAULT_IMAGE_FILES_INFO: { case DEFAULT_IMAGE_FILES_INFO: {
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
PbResult result;
result.set_allocated_image_files_info(rascsi_response.GetAvailableImages(result, result.set_allocated_image_files_info(rascsi_response.GetAvailableImages(result,
GetParam(command, "folder_pattern"), GetParam(command, "file_pattern"), scan_depth)); GetParam(command, "folder_pattern"), GetParam(command, "file_pattern"), scan_depth));
SerializeMessage(fd, result); SerializeMessage(fd, result);
@ -1523,14 +1513,11 @@ static void *MonThread(void *param)
} }
case IMAGE_FILE_INFO: { case IMAGE_FILE_INFO: {
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
string filename = GetParam(command, "file"); string filename = GetParam(command, "file");
if (filename.empty()) { if (filename.empty()) {
ReturnStatus(fd, false, "Can't get image file info: Missing filename"); ReturnStatus(fd, false, "Can't get image file info: Missing filename");
} }
else { else {
PbResult result;
PbImageFile* image_file = new PbImageFile(); PbImageFile* image_file = new PbImageFile();
bool status = rascsi_response.GetImageFile(image_file, filename); bool status = rascsi_response.GetImageFile(image_file, filename);
if (status) { if (status) {
@ -1546,35 +1533,30 @@ static void *MonThread(void *param)
} }
case NETWORK_INTERFACES_INFO: { case NETWORK_INTERFACES_INFO: {
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
PbResult result;
result.set_allocated_network_interfaces_info(rascsi_response.GetNetworkInterfacesInfo(result)); result.set_allocated_network_interfaces_info(rascsi_response.GetNetworkInterfacesInfo(result));
SerializeMessage(fd, result); SerializeMessage(fd, result);
break; break;
} }
case MAPPING_INFO: { case MAPPING_INFO: {
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
PbResult result;
result.set_allocated_mapping_info(rascsi_response.GetMappingInfo(result)); result.set_allocated_mapping_info(rascsi_response.GetMappingInfo(result));
SerializeMessage(fd, result); SerializeMessage(fd, result);
break; break;
} }
case RESERVED_IDS_INFO: { case OPERATION_INFO: {
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str()); result.set_allocated_operation_info(rascsi_response.GetOperationInfo(result));
SerializeMessage(fd, result);
break;
}
PbResult result; case RESERVED_IDS_INFO: {
result.set_allocated_reserved_ids_info(rascsi_response.GetReservedIds(result, reserved_ids)); result.set_allocated_reserved_ids_info(rascsi_response.GetReservedIds(result, reserved_ids));
SerializeMessage(fd, result); SerializeMessage(fd, result);
break; break;
} }
case SHUT_DOWN: { case SHUT_DOWN: {
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());
ShutDown(fd, GetParam(command, "mode")); ShutDown(fd, GetParam(command, "mode"));
break; break;
} }
@ -1613,6 +1595,10 @@ int main(int argc, char* argv[])
{ {
GOOGLE_PROTOBUF_VERIFY_VERSION; GOOGLE_PROTOBUF_VERIFY_VERSION;
// Get temporary operation info, in order to trigger an assertion on startup if the operation list is incomplete
PbResult pb_operation_info_result;
rascsi_response.GetOperationInfo(pb_operation_info_result);
int actid; int actid;
BUS::phase_t phase; BUS::phase_t phase;
// added setvbuf to override stdout buffering, so logs are written immediately and not when the process exits. // added setvbuf to override stdout buffering, so logs are written immediately and not when the process exits.

View File

@ -72,7 +72,7 @@ enum PbOperation {
// "file_pattern": Optional filter, only filenames containing the case-insensitive pattern are returned // "file_pattern": Optional filter, only filenames containing the case-insensitive pattern are returned
SERVER_INFO = 10; SERVER_INFO = 10;
// Get rascsi version information (PbVersionInfo) // Get rascsi server version (PbVersionInfo)
VERSION_INFO = 11; VERSION_INFO = 11;
// Get information on attached devices (PbDevicesInfo) // Get information on attached devices (PbDevicesInfo)
@ -111,7 +111,7 @@ enum PbOperation {
// "folder": The path of the default folder, relative to the user's home folder if relative. // "folder": The path of the default folder, relative to the user's home folder if relative.
DEFAULT_FOLDER = 20; DEFAULT_FOLDER = 20;
// Set a new log level. // Set the log level.
// Parameters: // Parameters:
// "level": The new log level // "level": The new log level
LOG_LEVEL = 21; LOG_LEVEL = 21;
@ -121,7 +121,7 @@ enum PbOperation {
// "ids": A comma-separated list of IDs to reserve, or an empty string in order not to reserve any ID. // "ids": A comma-separated list of IDs to reserve, or an empty string in order not to reserve any ID.
RESERVE_IDS = 22; RESERVE_IDS = 22;
// Shut down the rascsi process // Shut down the rascsi process or shut down/reboot the Raspberry Pi
// Parameters: // Parameters:
// "mode": The shutdown mode, one of "rascsi", "system", "reboot" // "mode": The shutdown mode, one of "rascsi", "system", "reboot"
SHUT_DOWN = 23; SHUT_DOWN = 23;
@ -162,19 +162,54 @@ enum PbOperation {
// Parameters: // Parameters:
// "file": The filename, relative to the default image folder. It must not contain a slash. // "file": The filename, relative to the default image folder. It must not contain a slash.
UNPROTECT_IMAGE = 29; UNPROTECT_IMAGE = 29;
// Check whether an authentication token is valid. A client can use this in operation in order to // Check whether an authentication token is valid. A client can use this operation in order to
// find out whether rascsi authentication is enable or to use rascsi authentication for securing // find out whether rascsi authentication is enable or to use rascsi authentication for securing
// client-internal operations. // client-internal operations.
CHECK_AUTHENTICATION = 30; CHECK_AUTHENTICATION = 30;
// Get operation meta data (PbOperationInfo)
OPERATION_INFO = 31;
} }
// rascsi special purpose error codes for cases where a textual error message is not sufficient // The operation parameter meta data. The parameter data type is provided by the protobuf API.
message PbOperationParameter {
string name = 1;
// Optional short localized description, key is the lower case locale (e.g. en, de).
// Falling back to "en" is recommended if a description for a particular language is missing.
map<string, string> description = 2;
// There is no specific set of permitted values if empty
repeated string permitted_values = 3;
// Optional default value
string default_value = 4;
// True if this parameter is mandatory
bool is_mandatory = 5;
}
// The list of parameters supported by an operation
message PbOperationMetaData {
// The operation name at the time the server-side protobuf code was generated.
string server_side_name = 1;
// Optional short localized description, key is the lower case locale (e.g. en, de).
// Falling back to "en" is recommended if a description for a particular language is missing.
map<string, string> description = 2;
repeated PbOperationParameter parameters = 3;
}
// Mapping of operations to their ordinals
message PbOperationInfo {
map<int32, PbOperationMetaData> operations = 1;
}
// rascsi special purpose error codes for cases where a textual error message may not be not sufficient.
// The client may react on this code, e.g. by prompting the user for an authentication token.
enum PbErrorCode { enum PbErrorCode {
// No error code available // No error code available
NO_ERROR_CODE = 0; NO_ERROR_CODE = 0;
// The client sent an operation code not supported by this server
UNKNOWN_OPERATION = 1;
// Authentication/Authorization error // Authentication/Authorization error
UNAUTHORIZED = 1; UNAUTHORIZED = 2;
} }
// The supported file extensions mapped to their respective device types // The supported file extensions mapped to their respective device types
@ -327,7 +362,7 @@ message PbResult {
// An optional error or information message, depending on the status. A string without trailing CR/LF. // An optional error or information message, depending on the status. A string without trailing CR/LF.
string msg = 2; string msg = 2;
// An optional error code. Only to be used in cases where textual information is not sufficient. // An optional error code. Only to be used in cases where textual information is not sufficient.
PbErrorCode error_code = 13; PbErrorCode error_code = 14;
// Optional additional result data // Optional additional result data
oneof result { oneof result {
// The result of a SERVER_INFO command // The result of a SERVER_INFO command
@ -350,6 +385,8 @@ message PbResult {
PbMappingInfo mapping_info = 11; PbMappingInfo mapping_info = 11;
// The result of a RESERVED_IDS_INFO command // The result of a RESERVED_IDS_INFO command
PbReservedIdsInfo reserved_ids_info = 12; PbReservedIdsInfo reserved_ids_info = 12;
// The result of an OPERATION_INFO command
PbOperationInfo operation_info = 13;
} }
} }
@ -371,4 +408,6 @@ message PbServerInfo {
PbReservedIdsInfo reserved_ids_info = 7; PbReservedIdsInfo reserved_ids_info = 7;
// The attached devices // The attached devices
PbDevicesInfo devices_info = 8; PbDevicesInfo devices_info = 8;
// The operation meta data
PbOperationInfo operation_info = 9;
} }

View File

@ -304,6 +304,7 @@ PbServerInfo *RascsiResponse::GetServerInfo(PbResult& result, const vector<Devic
server_info->set_allocated_mapping_info(GetMappingInfo(result)); server_info->set_allocated_mapping_info(GetMappingInfo(result));
GetDevices(*server_info, devices); GetDevices(*server_info, devices);
server_info->set_allocated_reserved_ids_info(GetReservedIds(result, reserved_ids)); server_info->set_allocated_reserved_ids_info(GetReservedIds(result, reserved_ids));
server_info->set_allocated_operation_info(GetOperationInfo(result));
result.set_status(true); result.set_status(true);
@ -363,3 +364,161 @@ PbMappingInfo *RascsiResponse::GetMappingInfo(PbResult& result)
return mapping_info; return mapping_info;
} }
PbOperationInfo *RascsiResponse::GetOperationInfo(PbResult& result)
{
PbOperationInfo *operation_info = new PbOperationInfo();
PbOperationMetaData *meta_data = new PbOperationMetaData();
AddOperationParameter(meta_data, "name", "Image file name in case of a mass storage device");
AddOperationParameter(meta_data, "interfaces", "Comma-separated prioritized network interface list");
CreateOperation(operation_info, meta_data, ATTACH, "Attach device, device-specific parameters are required");
meta_data = new PbOperationMetaData();
CreateOperation(operation_info, meta_data, DETACH, "Detach device, device-specific parameters are required");
meta_data = new PbOperationMetaData();
CreateOperation(operation_info, meta_data, DETACH_ALL, "Detach all devices");
meta_data = new PbOperationMetaData();
CreateOperation(operation_info, meta_data, START, "Start device, device-specific parameters are required");
meta_data = new PbOperationMetaData();
CreateOperation(operation_info, meta_data, STOP, "Stop device, device-specific parameters are required");
meta_data = new PbOperationMetaData();
AddOperationParameter(meta_data, "file", "Image file name", "", true);
CreateOperation(operation_info, meta_data, INSERT, "Insert medium, device-specific parameters are required");
meta_data = new PbOperationMetaData();
CreateOperation(operation_info, meta_data, EJECT, "Eject medium, device-specific parameters are required");
meta_data = new PbOperationMetaData();
CreateOperation(operation_info, meta_data, PROTECT, "Protect medium, device-specific parameters are required");
meta_data = new PbOperationMetaData();
CreateOperation(operation_info, meta_data, UNPROTECT, "Unprotect medium, device-specific parameters are required");
meta_data = new PbOperationMetaData();
AddOperationParameter(meta_data, "filename_pattern", "Pattern for filtering image file names");
CreateOperation(operation_info, meta_data, SERVER_INFO, "Get rascsi server information");
meta_data = new PbOperationMetaData();
CreateOperation(operation_info, meta_data, VERSION_INFO, "Get rascsi server version");
meta_data = new PbOperationMetaData();
CreateOperation(operation_info, meta_data, DEVICES_INFO, "Get information on attached devices");
meta_data = new PbOperationMetaData();
CreateOperation(operation_info, meta_data, DEVICE_TYPES_INFO, "Get device properties by device type");
meta_data = new PbOperationMetaData();
AddOperationParameter(meta_data, "filename_pattern", "Pattern for filtering image file names");
CreateOperation(operation_info, meta_data, DEFAULT_IMAGE_FILES_INFO, "Get information on available image files");
meta_data = new PbOperationMetaData();
AddOperationParameter(meta_data, "file", "Image file name", "", true);
CreateOperation(operation_info, meta_data, IMAGE_FILE_INFO, "Get information on image file");
meta_data = new PbOperationMetaData();
CreateOperation(operation_info, meta_data, LOG_LEVEL_INFO, "Get log level information");
meta_data = new PbOperationMetaData();
CreateOperation(operation_info, meta_data, NETWORK_INTERFACES_INFO, "Get the available network interfaces");
meta_data = new PbOperationMetaData();
CreateOperation(operation_info, meta_data, MAPPING_INFO, "Get mapping of extensions to device types");
meta_data = new PbOperationMetaData();
CreateOperation(operation_info, meta_data, RESERVED_IDS_INFO, "Get list of reserved device IDs");
meta_data = new PbOperationMetaData();
AddOperationParameter(meta_data, "folder", "Default image file folder name", "", true);
CreateOperation(operation_info, meta_data, DEFAULT_FOLDER, "Set default image file folder");
meta_data = new PbOperationMetaData();
AddOperationParameter(meta_data, "level", "New log level", "", true);
CreateOperation(operation_info, meta_data, LOG_LEVEL, "Set log level");
meta_data = new PbOperationMetaData();
AddOperationParameter(meta_data, "ids", "Comma-separated device ID list", "", true);
CreateOperation(operation_info, meta_data, RESERVE_IDS, "Reserve device IDs");
meta_data = new PbOperationMetaData();
PbOperationParameter *parameter = AddOperationParameter(meta_data, "mode", "Shutdown mode", "", true);
parameter->add_permitted_values("rascsi");
// System shutdown/reboot requires root permissions
if (!getuid()) {
parameter->add_permitted_values("system");
parameter->add_permitted_values("reboot");
}
CreateOperation(operation_info, meta_data, SHUT_DOWN, "Shut down or reboot");
meta_data = new PbOperationMetaData();
AddOperationParameter(meta_data, "file", "Image file name", "", true);
AddOperationParameter(meta_data, "size", "Image file size in bytes", "", true);
parameter = AddOperationParameter(meta_data, "read_only", "Read-only flag", "false");
parameter->add_permitted_values("true");
parameter->add_permitted_values("false");
CreateOperation(operation_info, meta_data, CREATE_IMAGE, "Create an image file");
meta_data = new PbOperationMetaData();
AddOperationParameter(meta_data, "file", "Image file name", "", true);
CreateOperation(operation_info, meta_data, DELETE_IMAGE, "Delete image file");
meta_data = new PbOperationMetaData();
AddOperationParameter(meta_data, "from", "Source image file name", "", true);
AddOperationParameter(meta_data, "to", "Destination image file name", "", true);
CreateOperation(operation_info, meta_data, RENAME_IMAGE, "Rename image file");
meta_data = new PbOperationMetaData();
AddOperationParameter(meta_data, "from", "Source image file name image file name", "", true);
AddOperationParameter(meta_data, "to", "Destination image file name", "", true);
parameter = AddOperationParameter(meta_data, "read_only", "Read-only flag", "false");
parameter->add_permitted_values("true");
parameter->add_permitted_values("false");
CreateOperation(operation_info, meta_data, COPY_IMAGE, "Copy image file");
meta_data = new PbOperationMetaData();
AddOperationParameter(meta_data, "file", "Image file name", "", true);
CreateOperation(operation_info, meta_data, PROTECT_IMAGE, "Write-protect image file");
meta_data = new PbOperationMetaData();
AddOperationParameter(meta_data, "file", "Image file name", "", true);
CreateOperation(operation_info, meta_data, UNPROTECT_IMAGE, "Make image file writable");
meta_data = new PbOperationMetaData();
AddOperationParameter(meta_data, "token", "Authentication token to be checked", "", true);
CreateOperation(operation_info, meta_data, CHECK_AUTHENTICATION, "Check whether an authentication token is valid");
meta_data = new PbOperationMetaData();
CreateOperation(operation_info, meta_data, OPERATION_INFO, "Get operation meta data");
// Ensure that the complete set of operations is covered
assert(operation_info->operations_size() == PbOperation_ARRAYSIZE - 1);
result.set_status(true);
return operation_info;
}
void RascsiResponse::CreateOperation(PbOperationInfo *operation_info, PbOperationMetaData *meta_data,
const PbOperation& operation, const string& description)
{
meta_data->set_server_side_name(PbOperation_Name(operation));
(*meta_data->mutable_description())["en"] = description;
int ordinal = PbOperation_descriptor()->FindValueByName(PbOperation_Name(operation))->index();
(*operation_info->mutable_operations())[ordinal] = *meta_data;
}
PbOperationParameter *RascsiResponse::AddOperationParameter(PbOperationMetaData *meta_data, const string& name,
const string& description, const string& default_value, bool is_mandatory)
{
PbOperationParameter *parameter = meta_data->add_parameters();
parameter->set_name(name);
(*parameter->mutable_description())["en"] = description;
parameter->set_default_value(default_value);
parameter->set_is_mandatory(is_mandatory);
return parameter;
}

View File

@ -40,6 +40,7 @@ public:
PbNetworkInterfacesInfo *GetNetworkInterfacesInfo(PbResult&); PbNetworkInterfacesInfo *GetNetworkInterfacesInfo(PbResult&);
PbMappingInfo *GetMappingInfo(PbResult&); PbMappingInfo *GetMappingInfo(PbResult&);
PbLogLevelInfo *GetLogLevelInfo(PbResult&, const string&); PbLogLevelInfo *GetLogLevelInfo(PbResult&, const string&);
PbOperationInfo *GetOperationInfo(PbResult&);
private: private:
@ -54,4 +55,7 @@ private:
void GetDeviceTypeProperties(PbDeviceTypesInfo&, PbDeviceType); void GetDeviceTypeProperties(PbDeviceTypesInfo&, PbDeviceType);
void GetAvailableImages(PbImageFilesInfo&, const string&, const string&, const string&, const string&, int); void GetAvailableImages(PbImageFilesInfo&, const string&, const string&, const string&, const string&, int);
void GetAvailableImages(PbResult& result, PbServerInfo&, const string&, const string&, int); void GetAvailableImages(PbResult& result, PbServerInfo&, const string&, const string&, int);
void CreateOperation(PbOperationInfo *, PbOperationMetaData *, const PbOperation&, const string&);
PbOperationParameter *AddOperationParameter(PbOperationMetaData *, const string&, const string&,
const string& = "", bool = false);
}; };

View File

@ -118,8 +118,8 @@ int main(int argc, char* argv[])
cerr << "version " << rascsi_get_version_string() << " (" << __DATE__ << ", " << __TIME__ << ")" << endl; cerr << "version " << rascsi_get_version_string() << " (" << __DATE__ << ", " << __TIME__ << ")" << endl;
cerr << "Usage: " << argv[0] << " -i ID [-u UNIT] [-c CMD] [-C FILE] [-t TYPE] [-b BLOCK_SIZE] [-n NAME] [-f FILE|PARAM] "; 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 << "[-F IMAGE_FOLDER] [-L LOG_LEVEL] [-h HOST] [-p PORT] [-r RESERVED_IDS] ";
cerr << "[-C FILENAME:FILESIZE] [-d FILENAME] [-w FILENAME] [-P TOKEN] [-R CURRENT_NAME:NEW_NAME] [-x CURRENT_NAME:NEW_NAME] "; cerr << "[-C FILENAME:FILESIZE] [-d FILENAME] [-w FILENAME] [-R CURRENT_NAME:NEW_NAME] [-x CURRENT_NAME:NEW_NAME] ";
cerr << "[-e] [-E FILENAME] [-D] [-I] [-l] [-L] [-m] [-O] [-s] [-v] [-V] [-y] [-X]" << endl; cerr << "[-e] [-E FILENAME] [-D] [-I] [-l] [-L] [-m] [o] [-O] [-s] [-v] [-V] [-y] [-X]" << endl;
cerr << " where ID := {0-7}" << endl; cerr << " where ID := {0-7}" << endl;
cerr << " UNIT := {0-31}, default is 0" << endl; cerr << " UNIT := {0-31}, default is 0" << endl;
cerr << " CMD := {attach|detach|insert|eject|protect|unprotect|show}" << endl; cerr << " CMD := {attach|detach|insert|eject|protect|unprotect|show}" << endl;
@ -259,6 +259,10 @@ int main(int argc, char* argv[])
command.set_operation(LOG_LEVEL_INFO); command.set_operation(LOG_LEVEL_INFO);
break; break;
case 'o':
command.set_operation(OPERATION_INFO);
break;
case 't': case 't':
device->set_type(ParseType(optarg)); device->set_type(ParseType(optarg));
if (device->type() == UNDEFINED) { if (device->type() == UNDEFINED) {
@ -436,6 +440,10 @@ int main(int argc, char* argv[])
rasctl_commands.CommandMappingInfo(); rasctl_commands.CommandMappingInfo();
break; break;
case OPERATION_INFO:
rasctl_commands.CommandOperationInfo();
break;
default: default:
rasctl_commands.SendCommand(); rasctl_commands.SendCommand();
break; break;

View File

@ -222,6 +222,7 @@ void RasctlCommands::CommandServerInfo()
rasctl_display.DisplayNetworkInterfaces(server_info.network_interfaces_info()); rasctl_display.DisplayNetworkInterfaces(server_info.network_interfaces_info());
rasctl_display.DisplayDeviceTypesInfo(server_info.device_types_info()); rasctl_display.DisplayDeviceTypesInfo(server_info.device_types_info());
rasctl_display.DisplayReservedIdsInfo(server_info.reserved_ids_info()); rasctl_display.DisplayReservedIdsInfo(server_info.reserved_ids_info());
rasctl_display.DisplayOperationInfo(server_info.operation_info());
if (server_info.devices_info().devices_size()) { if (server_info.devices_info().devices_size()) {
list<PbDevice> sorted_devices = { server_info.devices_info().devices().begin(), server_info.devices_info().devices().end() }; list<PbDevice> sorted_devices = { server_info.devices_info().devices().begin(), server_info.devices_info().devices().end() };
@ -278,3 +279,10 @@ void RasctlCommands::CommandMappingInfo()
rasctl_display.DisplayMappingInfo(result.mapping_info()); rasctl_display.DisplayMappingInfo(result.mapping_info());
} }
void RasctlCommands::CommandOperationInfo()
{
SendCommand();
rasctl_display.DisplayOperationInfo(result.operation_info());
}

View File

@ -42,6 +42,7 @@ public:
void CommandLogLevelInfo(); void CommandLogLevelInfo();
void CommandReservedIdsInfo(); void CommandReservedIdsInfo();
void CommandMappingInfo(); void CommandMappingInfo();
void CommandOperationInfo();
private: private:

View File

@ -273,3 +273,62 @@ void RasctlDisplay::DisplayMappingInfo(const PbMappingInfo& mapping_info)
cout << " " << mapping.first << "->" << PbDeviceType_Name(mapping.second) << endl; cout << " " << mapping.first << "->" << PbDeviceType_Name(mapping.second) << endl;
} }
} }
void RasctlDisplay::DisplayOperationInfo(const PbOperationInfo& operation_info)
{
const map<int, PbOperationMetaData> operations = { operation_info.operations().begin(), operation_info.operations().end() };
// Copies result into a map sorted by operation name
const PbOperationMetaData *unknown_operation = new PbOperationMetaData();
map<string, PbOperationMetaData> sorted_operations;
for (const auto& operation : operations) {
if (PbOperation_IsValid(static_cast<PbOperation>(operation.first))) {
sorted_operations[PbOperation_Name(static_cast<PbOperation>(operation.first))] = operation.second;
}
else {
// If the server-side operation is unknown for the client use the server-provided operation name
// No further operation information is available in this case
sorted_operations[operation.second.server_side_name()] = *unknown_operation;
}
}
cout << "Remote operations supported by rascsi and their parameters:" << endl;
for (const auto& operation : sorted_operations) {
if (!operation.second.server_side_name().empty()) {
cout << " " << operation.first;
if (!operation.second.description().empty()) {
cout << " (" << operation.second.description().at("en") << ")";
}
cout << endl;
for (const auto& parameter : operation.second.parameters()) {
cout << " " << parameter.name() << ": "
<< (parameter.is_mandatory() ? "mandatory" : "optional");
if (!parameter.description().empty()) {
cout << " (" << parameter.description().at("en") << ")";
}
cout << endl;
if (parameter.permitted_values_size()) {
cout << " Permitted values: ";
bool isFirst = true;
for (const auto& permitted_value : parameter.permitted_values()) {
if (!isFirst) {
cout << ", ";
}
isFirst = false;
cout << permitted_value;
}
cout << endl;
}
if (!parameter.default_value().empty()) {
cout << " Default value: " << parameter.default_value() << endl;
}
}
}
else {
cout << " " << operation.first << " (Unknown server-side operation)" << endl;
}
}
}

View File

@ -30,4 +30,5 @@ public:
void DisplayImageFiles(const PbImageFilesInfo&); void DisplayImageFiles(const PbImageFilesInfo&);
void DisplayNetworkInterfaces(const PbNetworkInterfacesInfo&); void DisplayNetworkInterfaces(const PbNetworkInterfacesInfo&);
void DisplayMappingInfo(const PbMappingInfo&); void DisplayMappingInfo(const PbMappingInfo&);
void DisplayOperationInfo(const PbOperationInfo&);
}; };