From 8110b4ebb29174ecd4b22510da0285abf604b8a7 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 10 Sep 2019 21:55:32 +0200 Subject: [PATCH] Rust cleanup --- nix-rust/Cargo.toml | 1 + nix-rust/src/error.rs | 5 +++ nix-rust/src/foreign.rs | 14 +++++++++ nix-rust/src/lib.rs | 68 ++++------------------------------------- nix-rust/src/tarfile.rs | 47 ++++++++++++++++++++++++++++ src/libstore/rust.hh | 2 +- 6 files changed, 74 insertions(+), 63 deletions(-) create mode 100644 nix-rust/src/error.rs create mode 100644 nix-rust/src/foreign.rs create mode 100644 nix-rust/src/tarfile.rs diff --git a/nix-rust/Cargo.toml b/nix-rust/Cargo.toml index 2d2bf6752..8b56dc89c 100644 --- a/nix-rust/Cargo.toml +++ b/nix-rust/Cargo.toml @@ -2,6 +2,7 @@ name = "nix-rust" version = "0.1.0" authors = ["Eelco Dolstra "] +edition = "2018" [lib] name = "nixrust" diff --git a/nix-rust/src/error.rs b/nix-rust/src/error.rs new file mode 100644 index 000000000..28d0abdef --- /dev/null +++ b/nix-rust/src/error.rs @@ -0,0 +1,5 @@ +#[derive(Debug)] +pub enum Error { + Misc(String), + Foreign(libc::c_void), // == std::exception_ptr +} diff --git a/nix-rust/src/foreign.rs b/nix-rust/src/foreign.rs new file mode 100644 index 000000000..7bce7753c --- /dev/null +++ b/nix-rust/src/foreign.rs @@ -0,0 +1,14 @@ +/// A wrapper around Nix's Source class that provides the Read trait. +#[repr(C)] +pub struct Source { + fun: extern "C" fn(this: *mut libc::c_void, data: &mut [u8]) -> usize, + this: *mut libc::c_void, +} + +impl std::io::Read for Source { + fn read(&mut self, buf: &mut [u8]) -> std::result::Result { + let n = (self.fun)(self.this, buf); + assert!(n <= buf.len()); + Ok(n) + } +} diff --git a/nix-rust/src/lib.rs b/nix-rust/src/lib.rs index ac6dee543..192ca29e4 100644 --- a/nix-rust/src/lib.rs +++ b/nix-rust/src/lib.rs @@ -1,66 +1,10 @@ -extern crate libc; -extern crate tar; +mod error; +mod foreign; +mod tarfile; -use std::fs; -use std::io; -use std::os::unix::fs::OpenOptionsExt; -use std::path::Path; -use tar::Archive; - -/// A wrapper around Nix's Source class that provides the Read trait. -#[repr(C)] -pub struct Source { - fun: extern "C" fn(this: *mut libc::c_void, data: &mut [u8]) -> usize, - this: *mut libc::c_void, -} - -impl std::io::Read for Source { - fn read(&mut self, buf: &mut [u8]) -> std::result::Result { - let n = (self.fun)(self.this, buf); - assert!(n <= buf.len()); - Ok(n) - } -} +pub use error::Error; #[no_mangle] -pub extern "C" fn unpack_tarfile(source: Source, dest_dir: &str) -> bool { - // FIXME: handle errors. - - let dest_dir = Path::new(dest_dir); - - let mut tar = Archive::new(source); - - for file in tar.entries().unwrap() { - let mut file = file.unwrap(); - - let dest_file = dest_dir.join(file.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(); - } - tar::EntryType::Symlink => { - std::os::unix::fs::symlink(file.header().link_name().unwrap().unwrap(), dest_file).unwrap(); - } - t => panic!("Unsupported tar entry type '{:?}'.", t), - } - } - - true +pub extern "C" fn unpack_tarfile(source: foreign::Source, dest_dir: &str) { + tarfile::unpack_tarfile(source, dest_dir).unwrap(); } diff --git a/nix-rust/src/tarfile.rs b/nix-rust/src/tarfile.rs new file mode 100644 index 000000000..696118e4d --- /dev/null +++ b/nix-rust/src/tarfile.rs @@ -0,0 +1,47 @@ +use crate::{foreign::Source, Error}; +use std::fs; +use std::io; +use std::os::unix::fs::OpenOptionsExt; +use std::path::Path; +use tar::Archive; + +pub fn unpack_tarfile(source: Source, dest_dir: &str) -> Result<(), Error> { + let dest_dir = Path::new(dest_dir); + + let mut tar = Archive::new(source); + + for file in tar.entries().unwrap() { + let mut file = file.unwrap(); + + let dest_file = dest_dir.join(file.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(); + } + tar::EntryType::Symlink => { + std::os::unix::fs::symlink(file.header().link_name().unwrap().unwrap(), dest_file) + .unwrap(); + } + t => return Err(Error::Misc(format!("unsupported tar entry type '{:?}'", t))), + } + } + + Ok(()) +} diff --git a/src/libstore/rust.hh b/src/libstore/rust.hh index 7e6c2f54d..4366e4723 100644 --- a/src/libstore/rust.hh +++ b/src/libstore/rust.hh @@ -40,5 +40,5 @@ struct Source } extern "C" { - bool unpack_tarfile(rust::Source source, rust::StringSlice dest_dir); + void unpack_tarfile(rust::Source source, rust::StringSlice dest_dir); }