From 11da5b2816e11b081d8ff38db4330addd2014f7e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 27 Mar 2019 14:12:20 +0100 Subject: [PATCH] Add some Rust code --- .gitignore | 2 ++ Makefile | 1 + nix-rust/Cargo.lock | 59 +++++++++++++++++++++++++++++++++++++++++++ nix-rust/Cargo.toml | 12 +++++++++ nix-rust/local.mk | 7 ++++++ nix-rust/src/lib.rs | 48 +++++++++++++++++++++++++++++++++++ release-common.nix | 1 + shell.nix | 2 +- src/nix/local.mk | 4 +-- src/nix/test.cc | 61 +++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 194 insertions(+), 3 deletions(-) create mode 100644 nix-rust/Cargo.lock create mode 100644 nix-rust/Cargo.toml create mode 100644 nix-rust/local.mk create mode 100644 nix-rust/src/lib.rs create mode 100644 src/nix/test.cc diff --git a/.gitignore b/.gitignore index fd62dfb38..f58e1f90f 100644 --- a/.gitignore +++ b/.gitignore @@ -119,3 +119,5 @@ GPATH GRTAGS GSYMS GTAGS + +nix-rust/target diff --git a/Makefile b/Makefile index 866c0961e..469070533 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ makefiles = \ mk/precompiled-headers.mk \ local.mk \ + nix-rust/local.mk \ src/libutil/local.mk \ src/libstore/local.mk \ src/libmain/local.mk \ diff --git a/nix-rust/Cargo.lock b/nix-rust/Cargo.lock new file mode 100644 index 000000000..cfaedc3ed --- /dev/null +++ b/nix-rust/Cargo.lock @@ -0,0 +1,59 @@ +[[package]] +name = "cfg-if" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "filetime" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.50" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "nix-rust" +version = "0.1.0" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "tar 0.4.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "tar" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "xattr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" +"checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" +"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" +"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum tar 0.4.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2167ff53da2a661702b3299f71a91b61b1dffef36b4b2884b1f9c67254c0133" +"checksum xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" diff --git a/nix-rust/Cargo.toml b/nix-rust/Cargo.toml new file mode 100644 index 000000000..2d2bf6752 --- /dev/null +++ b/nix-rust/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "nix-rust" +version = "0.1.0" +authors = ["Eelco Dolstra "] + +[lib] +name = "nixrust" +crate-type = ["staticlib"] + +[dependencies] +tar = "0.4" +libc = "0.2" diff --git a/nix-rust/local.mk b/nix-rust/local.mk new file mode 100644 index 000000000..c69e3b9ea --- /dev/null +++ b/nix-rust/local.mk @@ -0,0 +1,7 @@ +libnixrust_PATH := $(d)/target/release/libnixrust.a +libnixrust_INSTALL_PATH := $(libnixrust_PATH) +libnixrust_LDFLAGS_USE := -L$(d)/target/release -lnixrust -ldl +libnixrust_LDFLAGS_USE_INSTALLED := $(libnixrust_LDFLAGS_USE) + +$(d)/target/release/libnixrust.a: $(wildcard $(d)/src/*.rs) $(d)/Cargo.toml + $(trace-gen) cd nix-rust && RUSTC_BOOTSTRAP=1 cargo build --release && touch target/release/libnixrust.a diff --git a/nix-rust/src/lib.rs b/nix-rust/src/lib.rs new file mode 100644 index 000000000..abcb89055 --- /dev/null +++ b/nix-rust/src/lib.rs @@ -0,0 +1,48 @@ +extern crate libc; +extern crate tar; + +use std::fs; +use std::io; +use std::os::unix::fs::OpenOptionsExt; +use std::path::Path; +use tar::Archive; + +#[no_mangle] +pub extern "C" fn unpack_tarfile(data: &[u8], dest_dir: &str) -> bool { + // FIXME: handle errors. + + let dest_dir = Path::new(dest_dir); + + let mut tar = Archive::new(data); + + for file in tar.entries().unwrap() { + let mut file = file.unwrap(); + + let dest_file = dest_dir.join(file.header().path().unwrap()); + + fs::create_dir_all(dest_file.parent().unwrap()).unwrap(); + + match file.header().entry_type() { + tar::EntryType::Directory => { + fs::create_dir(dest_file).unwrap(); + } + tar::EntryType::Regular => { + let mode = if file.header().mode().unwrap() & libc::S_IXUSR == 0 { + 0o666 + } else { + 0o777 + }; + let mut f = fs::OpenOptions::new() + .create(true) + .write(true) + .mode(mode) + .open(dest_file) + .unwrap(); + io::copy(&mut file, &mut f).unwrap(); + } + t => panic!("Unsupported tar entry type '{:?}'.", t), + } + } + + true +} diff --git a/release-common.nix b/release-common.nix index 63f39f005..dd5f939d9 100644 --- a/release-common.nix +++ b/release-common.nix @@ -51,6 +51,7 @@ rec { openssl pkgconfig sqlite boehmgc boost nlohmann_json + rustc cargo # Tests git diff --git a/shell.nix b/shell.nix index 9c504f024..21ed47121 100644 --- a/shell.nix +++ b/shell.nix @@ -7,7 +7,7 @@ with import ./release-common.nix { inherit pkgs; }; (if useClang then clangStdenv else stdenv).mkDerivation { name = "nix"; - buildInputs = buildDeps ++ tarballDeps ++ perlDeps; + buildInputs = buildDeps ++ tarballDeps ++ perlDeps ++ [ pkgs.rustfmt ]; inherit configureFlags; diff --git a/src/nix/local.mk b/src/nix/local.mk index c09efd1fc..a145cf9b1 100644 --- a/src/nix/local.mk +++ b/src/nix/local.mk @@ -15,9 +15,9 @@ nix_SOURCES := \ $(wildcard src/nix-prefetch-url/*.cc) \ $(wildcard src/nix-store/*.cc) \ -nix_LIBS = libexpr libmain libstore libutil +nix_LIBS = libexpr libmain libstore libutil libnixrust -nix_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) -lboost_context -lboost_thread -lboost_system +nix_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) -lboost_context -lboost_thread -lboost_system -Lnix-rust/target/release $(foreach name, \ nix-build nix-channel nix-collect-garbage nix-copy-closure nix-daemon nix-env nix-hash nix-instantiate nix-prefetch-url nix-shell nix-store, \ diff --git a/src/nix/test.cc b/src/nix/test.cc new file mode 100644 index 000000000..70e0a903d --- /dev/null +++ b/src/nix/test.cc @@ -0,0 +1,61 @@ +#include "command.hh" +#include "store-api.hh" +#include "common-args.hh" + +using namespace nix; + +namespace rust { + +// Depending on the internal representation of Rust slices is slightly +// evil... +template struct Slice +{ + const T * ptr; + size_t size; + + Slice(const T * ptr, size_t size) : ptr(ptr), size(size) + { + assert(ptr); + } +}; + +struct StringSlice : Slice +{ + StringSlice(const std::string & s): Slice(s.data(), s.size()) { } +}; + +} + +extern "C" { + bool unpack_tarfile(rust::Slice data, rust::StringSlice dest_dir); +} + +struct CmdTest : StoreCommand +{ + CmdTest() + { + } + + std::string name() override + { + return "test"; + } + + std::string description() override + { + return "bla bla"; + } + + void run(ref store) override + { + auto data = readFile("./nix-2.2.tar"); + + std::string destDir = "./dest"; + + deletePath(destDir); + + unpack_tarfile({(uint8_t*) data.data(), data.size()}, destDir); + } +}; + +static RegisterCommand r(make_ref());