From 7eb0b9d7e42a20b85bd7afbfe3d33d9dd5fa5794 Mon Sep 17 00:00:00 2001
From: jaseg <git@jaseg.de>
Date: Sun, 29 Aug 2021 16:27:23 +0200
Subject: svg-flatten: Add wasmtime support

---
 svg-flatten/src/main.cpp            | 48 ++++++++++++++++++++++++++++---------
 svg-flatten/src/svg_import_util.cpp |  7 +++++-
 svg-flatten/src/util.cpp            | 12 +++++++++-
 3 files changed, 54 insertions(+), 13 deletions(-)

(limited to 'svg-flatten/src')

diff --git a/svg-flatten/src/main.cpp b/svg-flatten/src/main.cpp
index 8512547..2ebcfe9 100644
--- a/svg-flatten/src/main.cpp
+++ b/svg-flatten/src/main.cpp
@@ -3,6 +3,7 @@
 #include <cstdio>
 #include <filesystem>
 #include <iostream>
+#include <iomanip>
 #include <fstream>
 #include <algorithm>
 #include <string>
@@ -17,6 +18,34 @@ using argagg::parser;
 using namespace std;
 using namespace gerbolyze;
 
+string temp_file_path(const char *suffix) {
+    ifstream rnd;
+    rnd.open("/dev/urandom", ios::in | ios::binary);
+
+    char fn_buf[8];
+    rnd.read(fn_buf, sizeof(fn_buf));
+
+    if (rnd.rdstate()) {
+        cerr << "Error getting random data for temporary file name" << endl;
+        abort();
+    }
+
+    ostringstream out;
+    out << "tmp_";
+    for (size_t i=0; i<sizeof(fn_buf); i++) {
+        out << setfill('0') << setw(2) << setbase(16) << static_cast<int>(fn_buf[i] & 0xff);
+    }
+    out << suffix;
+
+    cerr << "out \"" << out.str() << "\"" << endl;
+#ifndef WASI
+    filesystem::path base = filesystem::temp_directory_path();
+    return (base / out.str()).native();
+#else
+    return "/tmp/" + out.str();
+#endif
+}
+
 int main(int argc, char **argv) {
     parser argparser {{
             {"help", {"-h", "--help"},
@@ -114,15 +143,7 @@ int main(int argc, char **argv) {
         << endl;
 
     argagg::parser_results args;
-    try {
-        args = argparser.parse(argc, argv);
-    } catch (const std::exception& e) {
-        argagg::fmt_ostream fmt(cerr);
-        fmt << usage.str() << argparser << '\n'
-            << "Encountered exception while parsing arguments: " << e.what()
-            << '\n';
-        return EXIT_FAILURE;
-    }
+    args = argparser.parse(argc, argv);
 
     if (args["help"]) {
         argagg::fmt_ostream fmt(cerr);
@@ -267,8 +288,8 @@ int main(int argc, char **argv) {
         transform(ending.begin(), ending.end(), ending.begin(), [](unsigned char c){ return std::tolower(c); }); /* c++ yeah */
     }
     
-    filesystem::path barf = { filesystem::temp_directory_path() /= (std::tmpnam(nullptr) + string(".svg")) };
-    filesystem::path frob = { filesystem::temp_directory_path() /= (std::tmpnam(nullptr) + string(".svg")) };
+    string barf =  temp_file_path(".svg");
+    string frob = temp_file_path(".svg");
 
     bool is_svg = args["force_svg"] || (ending == ".svg" && !args["force_png"]);
     if (!is_svg) {
@@ -352,10 +373,15 @@ int main(int argc, char **argv) {
         }
         string dpi_str = to_string(dpi);
         
+#ifndef NOFORK
         const char *command_line[] = {nullptr, "--keep-named-groups", "--dpi", dpi_str.c_str(), barf.c_str(), frob.c_str(), nullptr};
         if (run_cargo_command("usvg", command_line, "USVG")) {
             return EXIT_FAILURE;
         }
+#else
+        cerr << "Error: The caller of svg-flatten (you?) must use --no-usvg and run usvg externally since wasi does not yet support fork/exec." << endl;
+        return EXIT_FAILURE;
+#endif
     }
 
     VectorizerSelectorizer vec_sel(vectorizer, args["vectorizer_map"] ? args["vectorizer_map"].as<string>() : "");
diff --git a/svg-flatten/src/svg_import_util.cpp b/svg-flatten/src/svg_import_util.cpp
index cb60482..85db3ad 100644
--- a/svg-flatten/src/svg_import_util.cpp
+++ b/svg-flatten/src/svg_import_util.cpp
@@ -61,6 +61,11 @@ string gerbolyze::parse_data_iri(const string &data_url) {
     size_t b64_begin = data_url.find_first_not_of(" ", foo + strlen("base64,"));
     assert(b64_begin != string::npos);
 
-    return base64_decode(data_url.substr(b64_begin));
+    bool err_out;
+    string out = base64_decode(data_url.substr(b64_begin), false, &err_out);
+
+    if (err_out)
+      return "";
+    return out;
 }
 
diff --git a/svg-flatten/src/util.cpp b/svg-flatten/src/util.cpp
index e88f4e9..d9a5a09 100644
--- a/svg-flatten/src/util.cpp
+++ b/svg-flatten/src/util.cpp
@@ -1,16 +1,19 @@
 
-#include <pwd.h>
 #include <sys/types.h>
 #include <string>
 #include <iostream>
 
+#ifndef NOFORK
+#include <pwd.h>
 #include <subprocess.h>
+#endif
 #include <filesystem>
 
 #include "util.h"
 
 using namespace std;
 
+#ifndef NOFORK
 int gerbolyze::run_cargo_command(const char *cmd_name, const char *cmdline[], const char *envvar) {
     const char *homedir;
     if ((homedir = getenv("HOME")) == NULL) {
@@ -81,4 +84,11 @@ int gerbolyze::run_cargo_command(const char *cmd_name, const char *cmdline[], co
 
     return 0;
 }
+#else
+int gerbolyze::run_cargo_command(const char *cmd_name, const char *cmdline[], const char *envvar) {
+    (void) cmd_name, (void) cmdline, (void) envvar;
+    cerr << "Error: Cannot spawn " << cmd_name << " subprocess since binary was built with fork/exec disabled (-DNOFORK=1)" << endl;
+    return EXIT_FAILURE;
+}
+#endif
 
-- 
cgit