mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
wc: better handle files in pseudo-filesystems
This commit is contained in:
parent
ca024abe31
commit
054ca4a6b5
2 changed files with 29 additions and 5 deletions
|
@ -2,6 +2,8 @@
|
||||||
//
|
//
|
||||||
// For the full copyright and license information, please view the LICENSE
|
// For the full copyright and license information, please view the LICENSE
|
||||||
// file that was distributed with this source code.
|
// file that was distributed with this source code.
|
||||||
|
|
||||||
|
// cSpell:ignore sysconf
|
||||||
use crate::word_count::WordCount;
|
use crate::word_count::WordCount;
|
||||||
|
|
||||||
use super::WordCountable;
|
use super::WordCountable;
|
||||||
|
@ -11,7 +13,7 @@ use std::fs::OpenOptions;
|
||||||
use std::io::{self, ErrorKind, Read};
|
use std::io::{self, ErrorKind, Read};
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use libc::S_IFREG;
|
use libc::{sysconf, S_IFREG, _SC_PAGESIZE};
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use nix::sys::stat;
|
use nix::sys::stat;
|
||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
|
@ -87,11 +89,25 @@ pub(crate) fn count_bytes_fast<T: WordCountable>(handle: &mut T) -> (usize, Opti
|
||||||
// If stat.st_size = 0 then
|
// If stat.st_size = 0 then
|
||||||
// - either the size is 0
|
// - either the size is 0
|
||||||
// - or the size is unknown.
|
// - or the size is unknown.
|
||||||
// The second case happens for files in pseudo-filesystems. For
|
// The second case happens for files in pseudo-filesystems.
|
||||||
// example with /proc/version and /sys/kernel/profiling. So,
|
// For example with /proc/version.
|
||||||
// if it is 0 we don't report that and instead do a full read.
|
// So, if it is 0 we don't report that and instead do a full read.
|
||||||
|
//
|
||||||
|
// Another thing to consider for files in pseudo-filesystems like /proc, /sys
|
||||||
|
// and similar is that they could report `st_size` greater than actual content.
|
||||||
|
// For example /sys/kernel/profiling could report `st_size` equal to
|
||||||
|
// system page size (typically 4096 on 64bit system), while it's file content
|
||||||
|
// would count up only to a couple of bytes.
|
||||||
|
// This condition usually occurs for files in pseudo-filesystems like /proc, /sys
|
||||||
|
// that report `st_size` in the multiples of system page size.
|
||||||
|
// In such cases - fall back on full read
|
||||||
if (stat.st_mode as libc::mode_t & S_IFREG) != 0 && stat.st_size > 0 {
|
if (stat.st_mode as libc::mode_t & S_IFREG) != 0 && stat.st_size > 0 {
|
||||||
return (stat.st_size as usize, None);
|
let sys_page_size = unsafe { sysconf(_SC_PAGESIZE) as usize };
|
||||||
|
if stat.st_size as usize % sys_page_size > 0 {
|
||||||
|
// regular file or file from /proc, /sys and similar pseudo-filesystems
|
||||||
|
// with size that is NOT a multiple of system page size
|
||||||
|
return (stat.st_size as usize, None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
{
|
{
|
||||||
|
|
|
@ -419,6 +419,14 @@ fn test_files_from_pseudo_filesystem() {
|
||||||
use pretty_assertions::assert_ne;
|
use pretty_assertions::assert_ne;
|
||||||
let result = new_ucmd!().arg("-c").arg("/proc/cpuinfo").succeeds();
|
let result = new_ucmd!().arg("-c").arg("/proc/cpuinfo").succeeds();
|
||||||
assert_ne!(result.stdout_str(), "0 /proc/cpuinfo\n");
|
assert_ne!(result.stdout_str(), "0 /proc/cpuinfo\n");
|
||||||
|
|
||||||
|
let (at, mut ucmd) = at_and_ucmd!();
|
||||||
|
let result = ucmd.arg("-c").arg("/sys/kernel/profiling").succeeds();
|
||||||
|
let actual = at.read("/sys/kernel/profiling").len();
|
||||||
|
assert_eq!(
|
||||||
|
result.stdout_str(),
|
||||||
|
format!("{} /sys/kernel/profiling\n", actual)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue