1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
#[macro_use] extern crate log; #[macro_use] extern crate error_chain; use std::ffi::CString; use std::path::Path; pub mod errors { error_chain! { foreign_links { Io(::std::io::Error) #[cfg(unix)]; } } } pub(crate) trait LibcString { fn as_libc(&self) -> (*const i8, CString); } impl LibcString for Path { fn as_libc(&self) -> (*const i8, CString) { let res = unsafe { use std::os::unix::ffi::OsStrExt; CString::from_vec_unchecked(self.as_os_str().as_bytes().to_vec()) }; (res.as_ptr() as *const i8, res) } } pub mod fd; pub mod dir; pub mod chroot; #[cfg(test)] extern crate libc; #[cfg(test)] extern crate tempdir; #[cfg(test)] extern crate env_logger; #[cfg(test)] mod test { use std; use libc; use std::ffi::OsString; use std::os::unix::ffi::OsStringExt; use tempdir::TempDir; pub enum FsItem<'a> { Dir(&'a [u8], &'a [FsItem<'a>]), File(&'a [u8], &'a str), DirLink(&'a [u8], &'a [u8], &'a [u8]), FileLink(&'a [u8], &'a [u8], &'a str), DeadLink(&'a [u8], &'a [u8]), Empty, } pub fn create_fsitem(dir_fd: &::fd::Fd, item: &FsItem) { use std::io::Write; match item { &FsItem::Dir(name, content) => { let path = OsString::from_vec(name.to_vec()); if name != b"." { dir_fd .mkdirat(&path, 0o777) .expect(&format!("failed to create dir {:?}", name)); } let sub_fd = dir_fd.openat(&path, 0 | libc::O_RDONLY | libc::O_DIRECTORY | libc::O_CLOEXEC) .expect(&format!("failed to open dir {:?}", path)); for i in content { create_fsitem(&sub_fd, i); } } &FsItem::File(name, content) => { let path = OsString::from_vec(name.to_vec()); let fs_fd = dir_fd.createat(&path, 0 | libc::O_WRONLY | libc::O_CLOEXEC | libc::O_EXCL, 0o0666) .expect(&format!("failed to create file {:?}", path)); fs_fd .into_rawfd() .expect(&format!("failed to unref fd")) .into_file() .expect(&format!("failed to transform file {:?}", path)) .write_all(content.as_bytes()) .expect(&format!("failed to fill file {:?}", path)); } &FsItem::DirLink(name, dst, _) | &FsItem::FileLink(name, dst, _) | &FsItem::DeadLink(name, dst) => { let path = OsString::from_vec(name.to_vec()); let target = OsString::from_vec(dst.to_vec()); dir_fd.symlinkat(&target, &path) .expect(&format!("failed to create {:?} -> {:?} link", path, target)); } &FsItem::Empty => { }, } } pub fn create_fs(tmpdir: &std::path::Path, item: &FsItem) { let fd = ::fd::Fd::open(&tmpdir, 0 | libc::O_RDONLY | libc::O_DIRECTORY | libc::O_CLOEXEC) .expect(&format!("failed to open tmpdir {:?}", tmpdir)); create_fsitem(&fd, item); } pub fn create_tmpdir() -> TempDir { let res = TempDir::new("unix-fd-test") .expect("failed to create tmpdir"); res } }