Implements libc file open flags (unix only)

This commit is contained in:
Tyler 2021-06-17 14:33:30 -07:00
parent 19996c10a9
commit d14b5843a3
3 changed files with 132 additions and 6 deletions

1
Cargo.lock generated
View file

@ -1760,6 +1760,7 @@ dependencies = [
"gcd", "gcd",
"getopts", "getopts",
"hex-literal", "hex-literal",
"libc",
"md-5", "md-5",
"signal-hook", "signal-hook",
"uucore", "uucore",

View file

@ -20,6 +20,7 @@ debug_print = "1.0"
# Probably best to keep this identical to the version of getopts in the uucore crate # Probably best to keep this identical to the version of getopts in the uucore crate
getopts = "<= 0.2.21" getopts = "<= 0.2.21"
gcd = "2.0" gcd = "2.0"
libc = "0.2"
signal-hook = "0.3.9" signal-hook = "0.3.9"
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" } uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }

View file

@ -35,6 +35,10 @@ use std::io::{
self, Read, Write, self, Read, Write,
Seek, Seek,
}; };
#[cfg(unix)]
use libc;
#[cfg(unix)]
use std::os::unix::fs::OpenOptionsExt;
use std::sync::{ use std::sync::{
Arc, atomic::AtomicUsize, mpsc, atomic::Ordering, Arc, atomic::AtomicUsize, mpsc, atomic::Ordering,
}; };
@ -250,6 +254,53 @@ impl Input<io::Stdin>
} }
} }
fn make_unix_iflags(oflags: &IFlags) -> Option<libc::c_int>
{
let mut flag = 0;
if oflags.direct
{
flag |= libc::O_DIRECT;
}
if oflags.directory
{
flag |= libc::O_DIRECTORY;
}
if oflags.dsync
{
flag |= libc::O_DSYNC;
}
if oflags.noatime
{
flag |= libc::O_NOATIME;
}
if oflags.noctty
{
flag |= libc::O_NOCTTY;
}
if oflags.nofollow
{
flag |= libc::O_NOFOLLOW;
}
if oflags.nonblock
{
flag |= libc::O_NONBLOCK;
}
if oflags.sync
{
flag |= libc::O_SYNC;
}
if flag != 0
{
Some(flag)
}
else
{
None
}
}
impl Input<File> impl Input<File>
{ {
fn new(matches: &getopts::Matches) -> Result<Self, Box<dyn Error>> fn new(matches: &getopts::Matches) -> Result<Self, Box<dyn Error>>
@ -264,7 +315,21 @@ impl Input<File>
if let Some(fname) = matches.opt_str("if") if let Some(fname) = matches.opt_str("if")
{ {
let mut src = File::open(fname)?; let mut src =
{
let mut opts = OpenOptions::new();
opts.read(true);
if cfg!(unix)
{
if let Some(libc_flags) = make_unix_iflags(&iflags)
{
opts.custom_flags(libc_flags);
}
}
opts.open(fname)?
};
if let Some(amt) = skip if let Some(amt) = skip
{ {
@ -461,6 +526,53 @@ impl Output<io::Stdout> {
} }
} }
fn make_unix_oflags(oflags: &OFlags) -> Option<libc::c_int>
{
let mut flag = 0;
if oflags.direct
{
flag |= libc::O_DIRECT;
}
if oflags.directory
{
flag |= libc::O_DIRECTORY;
}
if oflags.dsync
{
flag |= libc::O_DSYNC;
}
if oflags.noatime
{
flag |= libc::O_NOATIME;
}
if oflags.noctty
{
flag |= libc::O_NOCTTY;
}
if oflags.nofollow
{
flag |= libc::O_NOFOLLOW;
}
if oflags.nonblock
{
flag |= libc::O_NONBLOCK;
}
if oflags.sync
{
flag |= libc::O_SYNC;
}
if flag != 0
{
Some(flag)
}
else
{
None
}
}
impl Output<File> { impl Output<File> {
fn new(matches: &getopts::Matches) -> Result<Self, Box<dyn Error>> fn new(matches: &getopts::Matches) -> Result<Self, Box<dyn Error>>
{ {
@ -471,11 +583,23 @@ impl Output<File> {
if let Some(fname) = matches.opt_str("of") if let Some(fname) = matches.opt_str("of")
{ {
let mut dst = OpenOptions::new() let mut dst = {
.write(true) let mut opts = OpenOptions::new();
.create(!cflags.nocreat) opts.write(true)
.truncate(!cflags.notrunc) .append(oflags.append)
.open(fname)?; .create_new(cflags.excl || !cflags.nocreat)
.truncate(!cflags.notrunc);
if cfg!(unix)
{
if let Some(libc_flags) = make_unix_oflags(&oflags)
{
opts.custom_flags(libc_flags);
}
}
opts.open(fname)?
};
if let Some(amt) = seek if let Some(amt) = seek
{ {