mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
Merge pull request #7775 from jfinkels/cp-make-fifo-uucore
cp: factor make_fifo() function out to uucore::fs
This commit is contained in:
parent
74e353dec0
commit
3965bc5b9e
2 changed files with 61 additions and 14 deletions
|
@ -7,14 +7,10 @@
|
|||
use quick_error::quick_error;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
#[cfg(not(windows))]
|
||||
use std::ffi::CString;
|
||||
use std::ffi::OsString;
|
||||
use std::fs::{self, Metadata, OpenOptions, Permissions};
|
||||
use std::io;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::{FileTypeExt, PermissionsExt};
|
||||
use std::path::{Path, PathBuf, StripPrefixError};
|
||||
#[cfg(all(unix, not(target_os = "android")))]
|
||||
|
@ -23,13 +19,13 @@ use uucore::fsxattr::copy_xattrs;
|
|||
use clap::{Arg, ArgAction, ArgMatches, Command, builder::ValueParser};
|
||||
use filetime::FileTime;
|
||||
use indicatif::{ProgressBar, ProgressStyle};
|
||||
#[cfg(unix)]
|
||||
use libc::mkfifo;
|
||||
use quick_error::ResultExt;
|
||||
|
||||
use platform::copy_on_write;
|
||||
use uucore::display::Quotable;
|
||||
use uucore::error::{UClapError, UError, UResult, UUsageError, set_exit_code};
|
||||
#[cfg(unix)]
|
||||
use uucore::fs::make_fifo;
|
||||
use uucore::fs::{
|
||||
FileInformation, MissingHandling, ResolveMode, are_hardlinks_to_same_file, canonicalize,
|
||||
get_filename, is_symlink_loop, normalize_path, path_ends_with_terminator,
|
||||
|
@ -2534,12 +2530,7 @@ fn copy_fifo(dest: &Path, overwrite: OverwriteMode, debug: bool) -> CopyResult<(
|
|||
fs::remove_file(dest)?;
|
||||
}
|
||||
|
||||
let name = CString::new(dest.as_os_str().as_bytes()).unwrap();
|
||||
let err = unsafe { mkfifo(name.as_ptr(), 0o666) };
|
||||
if err == -1 {
|
||||
return Err(format!("cannot create fifo {}: File exists", dest.quote()).into());
|
||||
}
|
||||
Ok(())
|
||||
make_fifo(dest).map_err(|_| format!("cannot create fifo {}: File exists", dest.quote()).into())
|
||||
}
|
||||
|
||||
fn copy_link(
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
//! Set of functions to manage files and symlinks
|
||||
//! Set of functions to manage regular files, special files, and links.
|
||||
|
||||
// spell-checker:ignore backport
|
||||
|
||||
|
@ -11,11 +11,13 @@
|
|||
use libc::{
|
||||
S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFREG, S_IFSOCK, S_IRGRP, S_IROTH,
|
||||
S_IRUSR, S_ISGID, S_ISUID, S_ISVTX, S_IWGRP, S_IWOTH, S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR,
|
||||
mode_t,
|
||||
mkfifo, mode_t,
|
||||
};
|
||||
use std::collections::HashSet;
|
||||
use std::collections::VecDeque;
|
||||
use std::env;
|
||||
#[cfg(unix)]
|
||||
use std::ffi::CString;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fs;
|
||||
use std::fs::read_dir;
|
||||
|
@ -798,6 +800,37 @@ pub fn get_filename(file: &Path) -> Option<&str> {
|
|||
file.file_name().and_then(|filename| filename.to_str())
|
||||
}
|
||||
|
||||
/// Make a FIFO, also known as a named pipe.
|
||||
///
|
||||
/// This is a safe wrapper for the unsafe [`libc::mkfifo`] function,
|
||||
/// which makes a [named
|
||||
/// pipe](https://en.wikipedia.org/wiki/Named_pipe) on Unix systems.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If the named pipe cannot be created.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use uucore::fs::make_fifo;
|
||||
///
|
||||
/// make_fifo("my-pipe").expect("failed to create the named pipe");
|
||||
///
|
||||
/// std::thread::spawn(|| { std::fs::write("my-pipe", b"hello").unwrap(); });
|
||||
/// assert_eq!(std::fs::read("my-pipe").unwrap(), b"hello");
|
||||
/// ```
|
||||
#[cfg(unix)]
|
||||
pub fn make_fifo(path: &Path) -> std::io::Result<()> {
|
||||
let name = CString::new(path.to_str().unwrap()).unwrap();
|
||||
let err = unsafe { mkfifo(name.as_ptr(), 0o666) };
|
||||
if err == -1 {
|
||||
Err(std::io::Error::from_raw_os_error(err))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
// Note this useful idiom: importing names from outer (for mod tests) scope.
|
||||
|
@ -807,6 +840,8 @@ mod tests {
|
|||
#[cfg(unix)]
|
||||
use std::os::unix;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::FileTypeExt;
|
||||
#[cfg(unix)]
|
||||
use tempfile::{NamedTempFile, tempdir};
|
||||
|
||||
struct NormalizePathTestCase<'a> {
|
||||
|
@ -1039,4 +1074,25 @@ mod tests {
|
|||
let file_path = PathBuf::from("~/foo.txt");
|
||||
assert!(matches!(get_filename(&file_path), Some("foo.txt")));
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn test_make_fifo() {
|
||||
// Create the FIFO in a temporary directory.
|
||||
let tempdir = tempdir().unwrap();
|
||||
let path = tempdir.path().join("f");
|
||||
assert!(make_fifo(&path).is_ok());
|
||||
|
||||
// Check that it is indeed a FIFO.
|
||||
assert!(std::fs::metadata(&path).unwrap().file_type().is_fifo());
|
||||
|
||||
// Check that we can write to it and read from it.
|
||||
//
|
||||
// Write and read need to happen in different threads,
|
||||
// otherwise `write` would block indefinitely while waiting
|
||||
// for the `read`.
|
||||
let path2 = path.clone();
|
||||
std::thread::spawn(move || assert!(std::fs::write(&path2, b"foo").is_ok()));
|
||||
assert_eq!(std::fs::read(&path).unwrap(), b"foo");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue