Skip to content

Commit

Permalink
test new cmdline processing
Browse files Browse the repository at this point in the history
  • Loading branch information
maxirmx committed Sep 28, 2024
1 parent 009d8d6 commit c440fce
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 100 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,10 @@ else (${SETUP_MODE})
DEPENDS ${DWARFS_WR_PRJ} ${RUBY_PRJ}
)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

file(GLOB GEMSPECS LIST_DIRECTORIES false ${FS_ROOT}/*.gemspec)
file(GLOB GEMFILES LIST_DIRECTORIES false ${FS_ROOT}/Gemfile)
file(GLOB GEMS LIST_DIRECTORIES false ${FS_ROOT}/*.gem)
Expand Down
210 changes: 110 additions & 100 deletions src/tebako-main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
#include <string>
#include <cstdint>
#include <vector>
#include <stdexcept>
#include <tuple>

#ifdef _WIN32
#include <winsock2.h>
Expand All @@ -64,32 +66,110 @@ TebakoMount tebako_mount;
// tebako_extract_cmdline
// Builds command line arguments to process --tebako-extract
// ruby -e "require 'fileutils'; FileUtils.copy_entry '<tebako::fs_mount_point>',argv[2] || 'source_filesystem'"
static int tebako_extract_cmdline(int* argc, char*** argv)
int tebako_extract_cmdline(int* argc, char*** argv, const char* fs_mount_point)
{
int ret = -1;
std::string dest = std::string(((*argc) < 3 ? "source_filesystem" : (*argv)[2]));
std::string cmd = std::string("require 'fileutils'; FileUtils.copy_entry '") + fs_mount_point + "', '" + dest + "'";
printf("Extracting tebako image to '%s' \n", dest.c_str());
size_t new_argv_size = 3 + cmd.size() + 1 + strlen((*argv)[0]) + 1;
char** new_argv = new char*[3];
char* argv_memory = new char[new_argv_size];
if (new_argv != NULL && argv_memory != NULL) {
strcpy(argv_memory, (*argv)[0]);
new_argv[0] = argv_memory;
argv_memory += (strlen((*argv)[0]) + 1);
strcpy(argv_memory, "-e");
new_argv[1] = argv_memory;
argv_memory += 3;
strcpy(argv_memory, cmd.c_str());
new_argv[2] = argv_memory;
*argv = new_argv;
(*argc) = 3;
ret = 0;
}
return ret;
}

int ret = -1;
std::string dest = std::string(((*argc) < 3 ? "source_filesystem" : (*argv)[2]));
std::string cmd = std::string("require 'fileutils'; FileUtils.copy_entry '") + (tebako::fs_mount_point) + "', '" + dest + "'";
printf("Extracting tebako image to '%s' \n", dest.c_str());
size_t new_argv_size = 3 + cmd.size() + 1 + strlen((*argv)[0]) + 1;
char** new_argv = new char* [3];
char* argv_memory = new char[new_argv_size];
if (new_argv != NULL && argv_memory != NULL) {
strcpy(argv_memory, (*argv)[0]);
new_argv[0] = argv_memory;
argv_memory += (strlen((*argv)[0]) + 1);
strcpy(argv_memory, "-e");
new_argv[1] = argv_memory;
argv_memory += 3;
strcpy(argv_memory, cmd.c_str());
new_argv[2] = argv_memory;
*argv = new_argv;
(*argc) = 3;
ret = 0;
}
return ret;
std::pair<int, char**> tebako_build_arguments(const std::vector<std::string>& new_argv, const char * fs_mount_point, const char * fs_entry_point)
{
if (fs_mount_point == nullptr || fs_entry_point == nullptr || fs_mount_point[0] == 0 || fs_entry_point[0] == 0) {
throw std::invalid_argument("Internal error: fs_mount_point and fs_entry_point must be non-null and non-empty");
}

size_t new_argv_size = strlen(fs_mount_point) + strlen(fs_entry_point) + 1;
for (const auto& arg : new_argv) {
new_argv_size += (arg.length() + 1);
}


char* argv_memory = new char[new_argv_size];
if (!argv_memory) throw std::bad_alloc();

// Build the new argv array
char** new_argv_final = new char*[new_argv.size() + 1];
memcpy(argv_memory, new_argv[0].c_str(), new_argv[0].length() + 1);
new_argv_final[0] = argv_memory;
argv_memory += (new_argv[0].length() + 1);

// Add tebako fs_mount_point and fs_entry_point
memcpy(argv_memory, fs_mount_point, strlen(fs_mount_point));
new_argv_final[1] = argv_memory;
argv_memory += strlen(fs_mount_point);

memcpy(argv_memory, fs_entry_point, strlen(fs_entry_point) + 1);
argv_memory += (strlen(fs_entry_point) + 1);

// Copy remaining arguments
for (size_t i = 1; i < new_argv.size(); i++) {
memcpy(argv_memory, new_argv[i].c_str(), new_argv[i].length() + 1);
new_argv_final[i + 1] = argv_memory;
argv_memory += (new_argv[i].length()+ 1);
}

// Return the new argc and argv
return {static_cast<int>(new_argv.size() + 1), new_argv_final};
}

std::pair<std::vector<std::string>, std::vector<std::string>> tebako_parse_arguments(int argc, char** argv)
{
const std::string error_msg =
"Error: --tebako-mount must be followed by a rule (e.g., --tebako-mount <mount point>:<target>)";
std::vector<std::string> tebako_mount_args;
std::vector<std::string> other_args;

for (int i = 0; i < argc; i++) {
std::string arg = argv[i];

// Check for "--tebako-mount"
if (arg == "--tebako-mount") {
// Ensure there is a next argument
if (i + 1 < argc) {
std::string next_arg = argv[i + 1];

// Check if the next argument is valid
if (next_arg[0] != '-') { // It's not a flag
tebako_mount_args.push_back(next_arg);
i += 1; // Skip the next argument as it is the rule
continue;
}
else {
throw std::invalid_argument(error_msg);
}
}

// If "--tebako-mount" is at the end of args without a rule, raise an error
throw std::invalid_argument(error_msg);
}

// If not a tebako-mount argument, add to other_args
other_args.push_back(arg);
}

return std::make_pair(tebako_mount_args, other_args);
}


extern "C" int tebako_main(int* argc, char*** argv) {
int ret = -1, fsret = -1;
char** new_argv = NULL;
Expand All @@ -115,89 +195,19 @@ extern "C" int tebako_main(int* argc, char*** argv) {

if (fsret == 0) {
if ((*argc > 1) && strcmp((*argv)[1], "--tebako-extract")==0) {
ret = tebako_extract_cmdline(argc, argv);
ret = tebako_extract_cmdline(argc, argv, tebako::fs_mount_point);
}
else {
size_t new_argv_size = strlen(tebako::fs_mount_point) + strlen(tebako::fs_entry_point) + 1;
std::vector<char*> new_argv;

for (int i = 0; i < (*argc); i++) {
// Check for "--tebako-mount"
std::string arg = (*argv)[i];

if (arg.find("--tebako-mount") == 0) {
// Check for the form "--tebako-mount=<rule>" directly attached
size_t eq_pos = arg.find('=');
if (eq_pos != std::string::npos) {
std::string potential_rule = arg.substr(eq_pos + 1);
if (!potential_rule.empty()) {
tebako_mount.rules.push_back(potential_rule);
continue; // Skip this argument, as it's extracted
}
}

// Handle space-separated cases, e.g., "--tebako-mount = <rule>", "--tebako-mount= <rule>", or "--tebako-mount =<rule>"
if (i + 1 < (*argc)) {
std::string next_arg = (*argv)[i + 1];

// Case: "--tebako-mount =" followed by "<rule>"
if (next_arg == "=" && i + 2 < (*argc)) {
tebako_mount.rules.push_back((*argv)[i + 2]);
i += 2; // Skip these arguments
continue;
}

// Case: "--tebako-mount= <rule>" or "--tebako-mount =<rule>"
if (next_arg != "=" && next_arg[0] != '-') {
tebako_mount.rules.push_back(next_arg);
i += 1; // Skip the next argument
continue;
}
}
}

// Add the remaining arguments to new_argv
new_argv_size += (strlen((*argv)[i]) + 1);
new_argv.push_back((*argv)[i]);
}
// Add tebako specific arguments
new_argv_size += (strlen(tebako::fs_mount_point) + strlen(tebako::fs_entry_point) + 1);

char* argv_memory = new char[new_argv_size];
if (!argv_memory) return -1;

// Build the new argv array
char** new_argv_final = new char*[new_argv.size() + 2];
memcpy(argv_memory, (*argv)[0], strlen((*argv)[0]) + 1);
new_argv_final[0] = argv_memory;
argv_memory += (strlen((*argv)[0]) + 1);

// Add tebako fs_mount_point and fs_entry_point
memcpy(argv_memory, tebako::fs_mount_point, strlen(tebako::fs_mount_point));
new_argv_final[1] = argv_memory;
argv_memory += strlen(tebako::fs_mount_point);

memcpy(argv_memory, tebako::fs_entry_point, strlen(tebako::fs_entry_point) + 1);
argv_memory += (strlen(tebako::fs_entry_point) + 1);

// Copy remaining arguments
for (size_t i = 0; i < new_argv.size(); i++) {
memcpy(argv_memory, new_argv[i], strlen(new_argv[i]) + 1);
new_argv_final[i + 2] = argv_memory;
argv_memory += (strlen(new_argv[i]) + 1);
}

// Update argc and argv
*argv = new_argv_final;
*argc = new_argv.size() + 2;
ret = 0;
}
auto [mount_args, parsed_argv] = tebako_parse_arguments(*argc, *argv);
std::tie(*argc, *argv) = tebako_build_arguments(parsed_argv, tebako::fs_mount_point, tebako::fs_entry_point);
ret = 0;
}
atexit(drop_fs);
}
atexit(drop_fs);
}

catch (...) {

catch (std::exception e) {
printf("Failed to process command line: %s\n", e.what());
}

if (!tebako_is_running_miniruby()) {
Expand Down

0 comments on commit c440fce

Please sign in to comment.