This commit is contained in:
Uwe Seimet 2023-11-15 23:19:36 +01:00
parent 11e4eb29c2
commit b2847e7e62
4 changed files with 59 additions and 23 deletions

View File

@ -12,7 +12,7 @@
#include "generated/piscsi_interface.pb.h"
#include <google/protobuf/util/json_util.h>
#include <spdlog/spdlog.h>
#include <vector>
#include <array>
#include <fstream>
#include <iostream>
#include <filesystem>
@ -23,14 +23,14 @@ using namespace spdlog;
using namespace scsi_defs;
using namespace piscsi_interface;
bool ScsiExecutor::Execute(const string& filename, bool binary, string& result)
bool ScsiExecutor::Execute(const string& input_filename, const string& output_filename, bool binary, string& result)
{
int input_length = 0;
if (!binary) {
ifstream in(filename);
ifstream in(input_filename);
if (in.fail()) {
result = "Can't open JSON input file '" + filename + "': " + strerror(errno);
result = "Can't open JSON input file '" + input_filename + "': " + strerror(errno);
return false;
}
@ -41,19 +41,19 @@ bool ScsiExecutor::Execute(const string& filename, bool binary, string& result)
memcpy(buffer.data(), json.data(), input_length);
}
else {
ifstream in(filename, ios::binary);
ifstream in(input_filename, ios::binary);
if (in.fail()) {
result = "Can't open binary input file '" + filename + "': " + strerror(errno);
result = "Can't open binary input file '" + input_filename + "': " + strerror(errno);
return false;
}
input_length = file_size(filename);
input_length = file_size(input_filename);
vector<char> b(input_length);
in.read(b.data(), input_length);
memcpy(buffer.data(), b.data(), input_length);
}
vector<uint8_t> cdb(10);
array<uint8_t, 10> cdb = { };
cdb[1] = binary ? 0x0a : 0x05;
cdb[5] = static_cast<uint8_t>(input_length >> 8);
cdb[6] = static_cast<uint8_t>(input_length);
@ -70,11 +70,36 @@ bool ScsiExecutor::Execute(const string& filename, bool binary, string& result)
result = "Can't parse received binary protobuf data";
return false;
}
google::protobuf::util::MessageToJsonString(r, &result);
if (output_filename.empty()) {
google::protobuf::util::MessageToJsonString(r, &result);
}
else {
if (binary) {
ofstream out(output_filename, ios::binary);
if (out.fail()) {
result = "Can't open binary output file '" + output_filename + "'";
return false;
}
}
else {
ofstream out(output_filename);
if (out.fail()) {
result = "Can't open JSON output file '" + output_filename + "'";
return false;
}
}
}
}
else {
const string json((const char*) buffer.data(), length);
result = json;
if (output_filename.empty()) {
result = json;
}
else {
}
}
return true;
@ -82,7 +107,7 @@ bool ScsiExecutor::Execute(const string& filename, bool binary, string& result)
bool ScsiExecutor::ShutDown()
{
vector<uint8_t> cdb(6);
array<uint8_t, 6> cdb = { };
cdb[4] = 0x02;
phase_executor->Execute(scsi_command::eCmdStartStop, cdb, buffer, 0, 0);

View File

@ -29,7 +29,7 @@ public:
}
~ScsiExecutor() = default;
bool Execute(const string&, bool, string&);
bool Execute(const string&, const string&, bool, string&);
bool ShutDown();
void SetTarget(int id, int lun)

View File

@ -45,12 +45,15 @@ bool ScsiExec::Banner(span<char*> args) const
cout << piscsi_util::Banner("(SCSI Action Execution Tool)");
if (args.size() < 2 || string(args[1]) == "-h" || string(args[1]) == "--help") {
cout << "Usage: " << args[0] << " -t ID[:LUN] [-i BID] -f FILE [-L LOG_LEVEL] [-b] [-X]\n"
cout << "Usage: " << args[0] << " -t ID[:LUN] [-i BID] [-f INPUT_FILE] [-o OUTPUT_FILE]"
<< " -L LOG_LEVEL] [-b] [-X]\n"
<< " ID is the target device ID (0-" << (ControllerManager::GetScsiIdMax() - 1) << ").\n"
<< " LUN is the optional target device LUN (0-" << (ControllerManager::GetScsiLunMax() - 1) << ")."
<< " Default is 0.\n"
<< " BID is the PiSCSI board ID (0-7). Default is 7.\n"
<< " FILENAME is the protobuf input data path.\n"
<< " INPUT_FILE is the protobuf data input file.\n"
<< " OUTPUT_FILE is the protobuf data output file. If not specified the output is always JSON"
<< " and goes to stdout.\n"
<< " LOG_LEVEL is the log level {trace|debug|info|warn|err|off}, default is 'info'.\n"
<< " -b Signal that the input file is in binary protobuf format instead of JSON format.\n"
<< " -X Shut down piscsi.\n"
@ -88,7 +91,7 @@ void ScsiExec::ParseArguments(span<char*> args)
optind = 1;
opterr = 0;
int opt;
while ((opt = getopt(static_cast<int>(args.size()), args.data(), "i:f:t:bL:X")) != -1) {
while ((opt = getopt(static_cast<int>(args.size()), args.data(), "i:f:t:bo:L:X")) != -1) {
switch (opt) {
case 'i':
if (!GetAsUnsignedInt(optarg, initiator_id) || initiator_id > 7) {
@ -96,14 +99,21 @@ void ScsiExec::ParseArguments(span<char*> args)
}
break;
case 'f':
filename = optarg;
break;
case 'b':
binary = true;
break;
case 'f':
input_filename = optarg;
break;
case 'o':
output_filename = optarg;
if (output_filename.empty()) {
throw parser_exception("Missing output filename");
}
break;
case 't':
if (const string error = ProcessId(optarg, target_id, target_lun); !error.empty()) {
throw parser_exception(error);
@ -127,8 +137,8 @@ void ScsiExec::ParseArguments(span<char*> args)
return;
}
if (filename.empty()) {
throw parser_exception("Missing filename");
if (input_filename.empty()) {
throw parser_exception("Missing input filename");
}
if (target_id == -1) {
@ -182,7 +192,7 @@ int ScsiExec::run(span<char*> args, bool in_process)
}
else {
string result;
status = scsi_executor->Execute(filename, binary, result);
status = scsi_executor->Execute(input_filename, output_filename, binary, result);
if (status) {
cout << result << '\n' << flush;
}

View File

@ -46,7 +46,8 @@ private:
int target_id = -1;
int target_lun = 0;
string filename;
string input_filename;
string output_filename;
bool binary = false;