diff --git a/.clang-tidy b/.clang-tidy index deaf726..d07254d 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1 +1 @@ -Checks: '*,clang-analyzer-*,-llvmlibc-*,-fuchsia-*,-altera-*,-abseil-*,-android-*,-modernize-use-trailing-return-type,-readability-identifier-length,-*-readability-todo,-*-magic-numbers,-readability-function-cognitive-complexity,-*-easily-swappable-parameters,-*-non-private-member-variables-in-classes,-*-no-recursion' \ No newline at end of file +Checks: '*,clang-analyzer-*,-llvmlibc-*,-fuchsia-*,-altera-*,-abseil-*,-android-*,-modernize-use-trailing-return-type,-readability-identifier-length,-*-readability-todo,-*-magic-numbers,-readability-function-cognitive-complexity,-*-easily-swappable-parameters,-*-non-private-member-variables-in-classes,-*-no-recursion,-concurrency-mt-unsafe' \ No newline at end of file diff --git a/.gitignore b/.gitignore index 07adc22..9b83346 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /.cache -/build \ No newline at end of file +/build +hash.py +docker.sh \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index c86ce6d..dc51742 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,4 +4,6 @@ project(shrap) set(CMAKE_CXX_STANDARD 20) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -add_executable(${PROJECT_NAME} src/main.cc) \ No newline at end of file +add_executable(${PROJECT_NAME} src/main.cc) + +target_link_libraries(${PROJECT_NAME} PRIVATE -static) diff --git a/src/main.cc b/src/main.cc index 3f8d840..05bbde3 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,18 +1,56 @@ #include "parser.h" +#include "util.h" #include #include -#include +#include +#include int main() { + if (geteuid() != 0) { + std::cerr << "This program needs to be ran as root.\n"; + return 1; + } + mkdir("/tmp/shrap", 0777); + std::ifstream file("zlib.shrap"); if (!file) { std::cerr << "Error opening file\n"; return 1; } - std::stringstream buffer; - buffer << file.rdbuf(); + Expr pkg = Expr::parse(file); - Expr pkg = Expr::parse(buffer.str()); - std::cout << pkg.get("name").value << std::endl; -} \ No newline at end of file + Expr src = pkg.get("src").children[0]; + std::string src_type = src.children[0].value; + std::string src_url = src.children[1].value; + std::string src_path = "/tmp/shrap/" + src.children[2].value; + + if (src_type == "tar") { + std::string archive_path = "/tmp/shrap/" + Util::basename(src_url); + + // TODO: replace wget with a library for zero runtime dependencies + Util::shell_command("wget -O " + archive_path + " " + src_url); + + // TODO: check archive hash from src.children[3].value + + Util::shell_command("tar xf " + archive_path + " -C /tmp/shrap/"); + } else { + std::cerr << "ERROR: unrecognized src type: " << src_type << "\n"; + return 1; + } + + std::string jobs = std::to_string(std::thread::hardware_concurrency()); + + for (const auto &step : pkg.get("build").children) { + std::string step_type = step.children[0].value; + + if (step_type == "configure_make") { + Util::shell_command("./configure --prefix=/usr", src_path); + Util::shell_command("make -j " + jobs, src_path); + Util::shell_command("make install", src_path); + } else { + std::cerr << "ERROR: unrecognized step type: " << step_type << "\n"; + return 1; + } + } +} diff --git a/src/parser.h b/src/parser.h index 320638b..ceb6c52 100644 --- a/src/parser.h +++ b/src/parser.h @@ -1,7 +1,6 @@ #pragma once -#include -#include +#include #include struct Expr { @@ -20,19 +19,19 @@ public: if (child.type == Type::List && child.children.size() >= 2 && child.children[0].type == Type::Atom && child.children[0].value == key) { - return child.children[1]; + Expr result = {.type = Type::List}; + result.children.assign(child.children.begin() + 1, + child.children.end()); + return result; } } throw std::runtime_error("key not found: " + key); } - static Expr parse(const std::string &input) { - std::istringstream in(input); - return parse_expr(in); - } + static Expr parse(std::istream &in) { return parse_expr(in); } private: - static std::string read_atom(std::istringstream &in) { + static std::string read_atom(std::istream &in) { std::string atom; while (true) { int next = in.peek(); @@ -48,7 +47,7 @@ private: return atom; } - static Expr parse_list(std::istringstream &in) { + static Expr parse_list(std::istream &in) { Expr result = {.type = Expr::Type::List}; in.get(); // consume bracket @@ -72,7 +71,7 @@ private: return result; } - static std::string read_string(std::istringstream &in) { + static std::string read_string(std::istream &in) { std::string result; in.get(); // consume the quote @@ -91,7 +90,7 @@ private: return result; } - static Expr parse_expr(std::istringstream &in) { + static Expr parse_expr(std::istream &in) { while (is_space(static_cast(in.peek()))) { in.get(); } @@ -138,4 +137,4 @@ inline std::ostream &operator<<(std::ostream &out, const Expr &e) { break; } return out; -} \ No newline at end of file +} diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..571270e --- /dev/null +++ b/src/util.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include +#include + +namespace Util { + +static int shell_command(const std::string &cmd, const std::string &dir = ".") { + pid_t pid = fork(); + if (pid < 0) { + perror("fork failed"); + return -1; + } + + if (pid == 0) { + if (chdir(dir.c_str()) != 0) { + perror("chdir failed"); + _exit(1); + } + + execl("/bin/sh", "sh", "-c", cmd.c_str(), nullptr); // NOLINT(*-vararg) + + perror("execl failed"); + _exit(1); + } else { + int status = 0; + if (waitpid(pid, &status, 0) < 0) { + perror("waitpid failed"); + return -1; + } + return WIFEXITED(status) ? WEXITSTATUS(status) : -1; + } +} + +static std::string basename(const std::string &path) { + size_t pos = path.find_last_of("/\\"); + if (pos == std::string::npos) { + return path; + } + return path.substr(pos + 1); +} + +}; // namespace Util \ No newline at end of file diff --git a/zlib.shrap b/zlib.shrap index d30ac5c..43aabbc 100644 --- a/zlib.shrap +++ b/zlib.shrap @@ -2,6 +2,6 @@ (name "zlib") (version "1.3.1") (homepage "https://zlib.net/") - (src (tar "https://zlib.net/zlib-1.3.1.tar.gz" "207c3b0862cb4e3686f8405f76a98c38dbad9c94bcf4be4b9efca0716aba51ec")) + (src (tar "https://zlib.net/zlib-1.3.1.tar.gz" "zlib-1.3.1" "207c3b0862cb4e3686f8405f76a98c38dbad9c94bcf4be4b9efca0716aba51ec")) (build - (configure_make))) \ No newline at end of file + (configure_make)))