Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2be51a3
add accessors for the underlying stat data
cehteh Apr 17, 2021
bba0687
FIX: make use of SimpleType::Unknown in simple_type()
cehteh Apr 18, 2021
c502cc2
FIX: use u32 for the 'dev' values
cehteh Apr 18, 2021
c8f364d
Changes to make macos happy
cehteh Apr 18, 2021
39fc803
FIX: replace ino_t with u64 to comply with statx
cehteh Apr 19, 2021
815357e
Add/Refactor Dir::list() -> DirIter ctor
cehteh Apr 19, 2021
8647f93
FIX: fixes previous commit, adds special O_PATH funcs
cehteh Apr 20, 2021
d567fb1
rename *_path to *_lite, improve docs, provide impl for non linux
cehteh Apr 21, 2021
e5e9c5b
New: clone_dirfd() may fix #34, ADD: FdType machinery, libc_ok()
cehteh Apr 21, 2021
9d48913
cosmetics: use libc_ok() where applicable
cehteh Apr 21, 2021
fcf92fa
add clone_upgrade()/clone_downgrade(), fix list_self()
cehteh Apr 21, 2021
abef3ec
Store inode in Entry, add accessor
cehteh Apr 19, 2021
ffe5d3f
use types from 'struct stat' instead 'struct statx'
cehteh Apr 21, 2021
726958c
Merge branch 'entry_metadata_feature' into cehteh
cehteh Apr 22, 2021
954a9cc
Merge branch 'list_feature' into cehteh
cehteh Apr 22, 2021
6b4d359
start abstracting OS capabilities into features
cehteh Apr 22, 2021
076ba5c
WIP: Add new 'conf_test' for build time configuration, o_path check
cehteh Apr 27, 2021
69acef0
add conf_tests for o_directory|search|tmpfile
cehteh Apr 27, 2021
34905a5
add the remaining tests (for now), remove a misleading note
cehteh Apr 27, 2021
c8fed25
FIX: The unnamed_tmp_file_link test needs o_tmpfile and link_file_at
cehteh Apr 27, 2021
7cf2583
WIP/FIX: test osx fcntl() returning O_DIRECTORY
cehteh Apr 27, 2021
c43ab67
notice about O_SEARCH when cloning
cehteh Apr 28, 2021
4b90fcb
add 'is_dir()' check, remove the 'test_open_file()' test
cehteh Apr 28, 2021
ec29aca
Add flags builder for 'Dir' objects
cehteh Apr 29, 2021
43b5cdf
Rename the builder ctor from new() to flags()
cehteh Apr 30, 2021
f57123b
Add DirMethodFlags builder
cehteh Apr 30, 2021
313cd86
bump conf_test version to 0.2
cehteh Apr 30, 2021
296d5e5
forgotten to enable the 'flag_reuse' tests
cehteh Apr 30, 2021
d22b9d4
Remove the '*_lite()' versions of open() and sub_dir()
cehteh May 1, 2021
cf11259
export O_PATH, O_SEARCH, O_DIRECTORY flags
cehteh May 1, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,28 @@ version = "0.1.21"
authors = ["[email protected]"]
edition = "2018"

[features]
default = []
linux = ["o_path", "o_directory", "o_tmpfile", "statx", "proc_self_fd", "link_file_at", "rename_exchange", "renameat_flags"]
#NOTE(cehteh): eventually provide some baseline configs for other OS'es (for cross compilation)
o_path = []
o_directory = []
o_tmpfile = []
o_search = []
fcntl_o_directory = []
proc_self_fd = []
link_file_at = []
renameat_flags = []
rename_exchange = []
statx = []

[dependencies]
libc = "0.2.34"

[build-dependencies]
libc = "0.2.34"
conf_test = "0.2"

[dev-dependencies]
argparse = "0.2.1"
tempfile = "3.0.3"
5 changes: 5 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use conf_test::ConfTest;

fn main() {
ConfTest::run();
}
16 changes: 16 additions & 0 deletions conf_tests/fcntl_o_directory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
extern crate libc;

fn main() {
unsafe {
let conf_tests = std::ffi::CString::new("conf_tests").unwrap();
let fd = libc::open(conf_tests.as_ptr(), libc::O_DIRECTORY | libc::O_RDONLY);

let flags = libc::fcntl(fd, libc::F_GETFL);

if flags != -1 && flags & libc::O_DIRECTORY != 0 {
std::process::exit(0);
} else {
std::process::exit(1);
}
}
}
13 changes: 13 additions & 0 deletions conf_tests/link_file_at.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
extern crate libc;

fn main() {
//NOTE(cehteh): same as the proc_self_fd test, maybe we need something smarter in future
unsafe {
let conf_tests = std::ffi::CString::new("/proc/self/fd/0").unwrap();
if libc::open(conf_tests.as_ptr(), libc::O_RDONLY) != -1 {
std::process::exit(0);
} else {
std::process::exit(1);
}
}
}
8 changes: 8 additions & 0 deletions conf_tests/o_directory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
extern crate libc;

fn main() {
unsafe {
let conf_tests = std::ffi::CString::new("conf_tests").unwrap();
libc::open(conf_tests.as_ptr(), libc::O_DIRECTORY);
}
}
8 changes: 8 additions & 0 deletions conf_tests/o_path.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
extern crate libc;

fn main () {
unsafe {
let conf_tests = std::ffi::CString::new("conf_tests").unwrap();
libc::open(conf_tests.as_ptr(), libc::O_PATH);
}
}
8 changes: 8 additions & 0 deletions conf_tests/o_search.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
extern crate libc;

fn main() {
unsafe {
let conf_tests = std::ffi::CString::new("conf_tests").unwrap();
libc::open(conf_tests.as_ptr(), libc::O_SEARCH);
}
}
10 changes: 10 additions & 0 deletions conf_tests/o_tmpfile.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
extern crate libc;

fn main () {
unsafe {
let conf_tests = std::ffi::CString::new("conf_tests").unwrap();
libc::open(conf_tests.as_ptr(),
libc::O_TMPFILE | libc::O_RDWR,
libc::S_IRUSR | libc::S_IWUSR);
}
}
12 changes: 12 additions & 0 deletions conf_tests/proc_self_fd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
extern crate libc;

fn main() {
unsafe {
let conf_tests = std::ffi::CString::new("/proc/self/fd/0").unwrap();
if libc::open(conf_tests.as_ptr(), libc::O_RDONLY) != -1 {
std::process::exit(0);
} else {
std::process::exit(1);
}
}
}
5 changes: 5 additions & 0 deletions conf_tests/rename_exchange.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
extern crate libc;

fn main() {
let does_rename_exchange_exist = libc::RENAME_EXCHANGE;
}
5 changes: 5 additions & 0 deletions conf_tests/renameat_flags.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
extern crate libc;

fn main() {
let does_renameat2_exist = libc::SYS_renameat2;
}
4 changes: 3 additions & 1 deletion examples/exchange.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ fn main() {
}
let parent = path1.parent().expect("path must have parent directory");
let dir = Dir::open(parent).expect("can open directory");
#[cfg(feature = "rename_exchange")]
dir.local_exchange(
path1.file_name().expect("path1 must have filename"),
path2.file_name().expect("path2 must have filename"),
).expect("can rename");
)
.expect("can rename");
}
155 changes: 155 additions & 0 deletions src/builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
use std::ffi::CStr;
use std::fs::File;
use std::io;

use crate::dir::{clone_dirfd_upgrade, to_cstr};
use crate::{AsPath, Dir};

/// 'Dir::new()' creates a new DirFlags object with default (O_CLOEXEC) flags. One can then
/// freely add/remove flags to the set. The final open calls will add O_DIRECTORY and O_PATH
/// as applicable/supported but not verify or remove any defined flags. This allows passing
/// flags the 'openat' implementation is not even aware about. Thus the open call may fail
/// with some error when one constructed an invalid flag set.
#[derive(Copy, Clone)]
pub struct DirFlags {
flags: libc::c_int,
}

impl DirFlags {
#[inline]
pub(crate) fn new(flags: libc::c_int) -> DirFlags {
DirFlags { flags }
}

/// Sets the given flags
#[inline]
pub fn with(self, flags: libc::c_int) -> DirFlags {
DirFlags {
flags: self.flags | flags,
}
}

/// Clears the given flags
#[inline]
pub fn without(self, flags: libc::c_int) -> DirFlags {
DirFlags {
flags: self.flags & !flags,
}
}

/// Queries current flags
#[inline]
pub fn get_flags(&self) -> libc::c_int {
self.flags
}

/// Open a directory descriptor at specified path
#[inline]
pub fn open<P: AsPath>(&self, path: P) -> io::Result<Dir> {
Dir::_open(to_cstr(path)?.as_ref(), self.flags)
}
}

/// 'Dir::with(&self)'/'Dir::with(&self)' creates a new DirMethodsFlags object with default
/// (O_CLOEXEC|O_NOFOLLOW) flags. One can then freely add/remove flags to the set.
/// Implements proxies for the Dir:: methods that open contained objects.
#[derive(Copy, Clone)]
pub struct DirMethodFlags<'a> {
object: &'a Dir,
flags: libc::c_int,
}

impl<'a> DirMethodFlags<'a> {
#[inline]
pub(crate) fn new(object: &'a Dir, flags: libc::c_int) -> Self {
Self { object, flags }
}

/// Sets the given flags
#[inline]
pub fn with(self, flags: libc::c_int) -> Self {
Self {
object: self.object,
flags: self.flags | flags,
}
}

/// Clears the given flags
#[inline]
pub fn without(self, flags: libc::c_int) -> Self {
Self {
object: self.object,
flags: self.flags & !flags,
}
}

/// Open subdirectory
#[inline]
pub fn sub_dir<P: AsPath>(&self, path: P) -> io::Result<Dir> {
self.object._sub_dir(to_cstr(path)?.as_ref(), self.flags)
}

/// Open file for reading in this directory
#[inline]
pub fn open_file<P: AsPath>(&self, path: P) -> io::Result<File> {
self.object
._open_file(to_cstr(path)?.as_ref(), self.flags | libc::O_RDONLY, 0)
}

/// Open file for writing, create if necessary, truncate on open
#[inline]
pub fn write_file<P: AsPath>(&self, path: P, mode: libc::mode_t) -> io::Result<File> {
self.object._open_file(
to_cstr(path)?.as_ref(),
self.flags | libc::O_CREAT | libc::O_WRONLY | libc::O_TRUNC,
mode,
)
}

/// Open file for append, create if necessary
#[inline]
pub fn append_file<P: AsPath>(&self, path: P, mode: libc::mode_t) -> io::Result<File> {
self.object._open_file(
to_cstr(path)?.as_ref(),
self.flags | libc::O_CREAT | libc::O_WRONLY | libc::O_APPEND,
mode,
)
}

/// Create file for writing (and truncate) in this directory
#[deprecated(since = "0.1.7", note = "please use `write_file` instead")]
#[inline]
pub fn create_file<P: AsPath>(&self, path: P, mode: libc::mode_t) -> io::Result<File> {
self.object._open_file(
to_cstr(path)?.as_ref(),
self.flags | libc::O_CREAT | libc::O_WRONLY | libc::O_TRUNC,
mode,
)
}

/// Create a tmpfile in this directory which isn't linked to any filename
#[cfg(feature = "o_tmpfile")]
#[inline]
pub fn new_unnamed_file(&self, mode: libc::mode_t) -> io::Result<File> {
self.object._open_file(
unsafe { CStr::from_bytes_with_nul_unchecked(b".\0") },
self.flags | libc::O_TMPFILE | libc::O_WRONLY,
mode,
)
}

/// Create file if not exists, fail if exists
#[inline]
pub fn new_file<P: AsPath>(&self, path: P, mode: libc::mode_t) -> io::Result<File> {
self.object._open_file(
to_cstr(path)?.as_ref(),
self.flags | libc::O_CREAT | libc::O_EXCL | libc::O_WRONLY,
mode,
)
}

/// Creates a new 'Normal' independently owned handle to the underlying directory.
pub fn clone_upgrade(&self) -> io::Result<Dir> {
Ok(Dir(clone_dirfd_upgrade(self.object.0, self.flags)?))
}
}
Loading