mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
cp: fix recursive socket file copy
This commit is contained in:
+28
-1
@@ -11,6 +11,8 @@ use std::fmt::Display;
|
||||
use std::fs::{self, Metadata, OpenOptions, Permissions};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::{FileTypeExt, PermissionsExt};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::net::UnixListener;
|
||||
use std::path::{Path, PathBuf, StripPrefixError};
|
||||
use std::{fmt, io};
|
||||
#[cfg(all(unix, not(target_os = "android")))]
|
||||
@@ -2071,6 +2073,7 @@ fn handle_copy_mode(
|
||||
symlinked_files: &mut HashSet<FileInformation>,
|
||||
source_in_command_line: bool,
|
||||
source_is_fifo: bool,
|
||||
source_is_socket: bool,
|
||||
#[cfg(unix)] source_is_stream: bool,
|
||||
) -> CopyResult<PerformedAction> {
|
||||
let source_is_symlink = source_metadata.is_symlink();
|
||||
@@ -2110,6 +2113,7 @@ fn handle_copy_mode(
|
||||
context,
|
||||
source_is_symlink,
|
||||
source_is_fifo,
|
||||
source_is_socket,
|
||||
symlinked_files,
|
||||
#[cfg(unix)]
|
||||
source_is_stream,
|
||||
@@ -2132,6 +2136,7 @@ fn handle_copy_mode(
|
||||
context,
|
||||
source_is_symlink,
|
||||
source_is_fifo,
|
||||
source_is_socket,
|
||||
symlinked_files,
|
||||
#[cfg(unix)]
|
||||
source_is_stream,
|
||||
@@ -2167,6 +2172,7 @@ fn handle_copy_mode(
|
||||
context,
|
||||
source_is_symlink,
|
||||
source_is_fifo,
|
||||
source_is_socket,
|
||||
symlinked_files,
|
||||
#[cfg(unix)]
|
||||
source_is_stream,
|
||||
@@ -2181,6 +2187,7 @@ fn handle_copy_mode(
|
||||
context,
|
||||
source_is_symlink,
|
||||
source_is_fifo,
|
||||
source_is_socket,
|
||||
symlinked_files,
|
||||
#[cfg(unix)]
|
||||
source_is_stream,
|
||||
@@ -2407,8 +2414,12 @@ fn copy_file(
|
||||
|
||||
#[cfg(unix)]
|
||||
let source_is_fifo = source_metadata.file_type().is_fifo();
|
||||
#[cfg(unix)]
|
||||
let source_is_socket = source_metadata.file_type().is_socket();
|
||||
#[cfg(not(unix))]
|
||||
let source_is_fifo = false;
|
||||
#[cfg(not(unix))]
|
||||
let source_is_socket = false;
|
||||
|
||||
let source_is_stream = is_stream(&source_metadata);
|
||||
|
||||
@@ -2421,6 +2432,7 @@ fn copy_file(
|
||||
symlinked_files,
|
||||
source_in_command_line,
|
||||
source_is_fifo,
|
||||
source_is_socket,
|
||||
#[cfg(unix)]
|
||||
source_is_stream,
|
||||
)?;
|
||||
@@ -2547,6 +2559,7 @@ fn copy_helper(
|
||||
context: &str,
|
||||
source_is_symlink: bool,
|
||||
source_is_fifo: bool,
|
||||
source_is_socket: bool,
|
||||
symlinked_files: &mut HashSet<FileInformation>,
|
||||
#[cfg(unix)] source_is_stream: bool,
|
||||
) -> CopyResult<()> {
|
||||
@@ -2559,7 +2572,10 @@ fn copy_helper(
|
||||
return Err(CpError::NotADirectory(dest.to_path_buf()));
|
||||
}
|
||||
|
||||
if source_is_fifo && options.recursive && !options.copy_contents {
|
||||
if source_is_socket && options.recursive && !options.copy_contents {
|
||||
#[cfg(unix)]
|
||||
copy_socket(dest, options.overwrite, options.debug)?;
|
||||
} else if source_is_fifo && options.recursive && !options.copy_contents {
|
||||
#[cfg(unix)]
|
||||
copy_fifo(dest, options.overwrite, options.debug)?;
|
||||
} else if source_is_symlink {
|
||||
@@ -2596,6 +2612,17 @@ fn copy_fifo(dest: &Path, overwrite: OverwriteMode, debug: bool) -> CopyResult<(
|
||||
.map_err(|_| translate!("cp-error-cannot-create-fifo", "path" => dest.quote()).into())
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn copy_socket(dest: &Path, overwrite: OverwriteMode, debug: bool) -> CopyResult<()> {
|
||||
if dest.exists() {
|
||||
overwrite.verify(dest, debug)?;
|
||||
fs::remove_file(dest)?;
|
||||
}
|
||||
|
||||
UnixListener::bind(dest)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn copy_link(
|
||||
source: &Path,
|
||||
dest: &Path,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// file that was distributed with this source code.
|
||||
|
||||
// spell-checker:ignore (flags) reflink (fs) tmpfs (linux) rlimit Rlim NOFILE clob btrfs neve ROOTDIR USERDIR outfile uufs xattrs
|
||||
// spell-checker:ignore bdfl hlsl IRWXO IRWXG nconfined matchpathcon libselinux-devel prwx doesnotexist reftests subdirs
|
||||
// spell-checker:ignore bdfl hlsl IRWXO IRWXG nconfined matchpathcon libselinux-devel prwx doesnotexist reftests subdirs mksocket srwx
|
||||
use uucore::display::Quotable;
|
||||
#[cfg(feature = "feat_selinux")]
|
||||
use uucore::selinux::get_getfattr_output;
|
||||
@@ -18,10 +18,10 @@ use std::io::Write;
|
||||
#[cfg(not(windows))]
|
||||
use std::os::unix::fs;
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::{FileTypeExt, MetadataExt};
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::fs::symlink_file;
|
||||
#[cfg(not(windows))]
|
||||
@@ -3105,6 +3105,27 @@ fn test_cp_fifo() {
|
||||
assert_eq!(permission, "prwx-wx--x".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_cp_socket() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
at.mksocket("socket");
|
||||
// Also test that permissions are preserved
|
||||
at.set_mode("socket", 0o731);
|
||||
ucmd.arg("--preserve=mode")
|
||||
.arg("-r")
|
||||
.arg("socket")
|
||||
.arg("socket2")
|
||||
.succeeds()
|
||||
.no_stderr()
|
||||
.no_stdout();
|
||||
|
||||
let metadata = std::fs::metadata(at.subdir.join("socket2")).unwrap();
|
||||
let permission = uucore::fs::display_permissions(&metadata, true);
|
||||
assert!(metadata.file_type().is_socket());
|
||||
assert_eq!(permission, "srwx-wx--x".to_string());
|
||||
}
|
||||
|
||||
#[cfg(all(unix, not(target_vendor = "apple")))]
|
||||
fn find_other_group(current: u32) -> Option<u32> {
|
||||
// Get the first group that doesn't match current
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
//spell-checker: ignore (linux) rlimit prlimit coreutil ggroups uchild uncaptured scmd SHLVL canonicalized openpty
|
||||
//spell-checker: ignore (linux) winsize xpixel ypixel setrlimit FSIZE SIGBUS SIGSEGV sigbus tmpfs
|
||||
//spell-checker: ignore (linux) winsize xpixel ypixel setrlimit FSIZE SIGBUS SIGSEGV sigbus tmpfs mksocket
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![allow(
|
||||
@@ -34,6 +34,8 @@ use std::os::fd::OwnedFd;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::{PermissionsExt, symlink as symlink_dir, symlink as symlink_file};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::net::UnixListener;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::process::CommandExt;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::process::ExitStatusExt;
|
||||
@@ -1132,6 +1134,13 @@ impl AtPath {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn mksocket(&self, socket: &str) {
|
||||
let full_path = self.plus_as_string(socket);
|
||||
log_info("mksocket", &full_path);
|
||||
UnixListener::bind(full_path).expect("Socket file creation failed.");
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub fn is_fifo(&self, fifo: &str) -> bool {
|
||||
unsafe {
|
||||
|
||||
Reference in New Issue
Block a user