Merge branch 'main' into fs_extra

This commit is contained in:
Sylvestre Ledru
2023-02-18 17:23:07 +01:00
committed by GitHub
35 changed files with 426 additions and 300 deletions
+5
View File
@@ -20,6 +20,11 @@ on: [push, pull_request]
permissions:
contents: read # to fetch code (actions/checkout)
# End the current execution if there is a new changeset in the PR.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
jobs:
cargo-deny:
name: Style/cargo-deny
+20 -4
View File
@@ -14,6 +14,11 @@ on: [push, pull_request]
permissions:
contents: read
# End the current execution if there is a new changeset in the PR.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
jobs:
gnu:
permissions:
@@ -196,6 +201,9 @@ jobs:
REF_LOG_FILE='${{ steps.vars.outputs.path_reference }}/test-logs/test-suite.log'
REF_SUMMARY_FILE='${{ steps.vars.outputs.path_reference }}/test-summary/gnu-result.json'
REPO_DEFAULT_BRANCH='${{ steps.vars.outputs.repo_default_branch }}'
# https://github.com/uutils/coreutils/issues/4294
# https://github.com/uutils/coreutils/issues/4295
IGNORE_INTERMITTENT='tests/tail-2/inotify-dir-recreate tests/misc/timeout tests/rm/rm1'
mkdir -p ${{ steps.vars.outputs.path_reference }}
@@ -227,10 +235,18 @@ jobs:
do
if ! grep -Fxq ${LINE}<<<"${REF_FAILING}"
then
MSG="GNU test failed: ${LINE}. ${LINE} is passing on '${{ steps.vars.outputs.repo_default_branch }}'. Maybe you have to rebase?"
echo "::error ::$MSG"
echo $MSG >> ${COMMENT_LOG}
have_new_failures="true"
if ! grep ${LINE} ${IGNORE_INTERMITTENT}
then
MSG="GNU test failed: ${LINE}. ${LINE} is passing on '${{ steps.vars.outputs.repo_default_branch }}'. Maybe you have to rebase?"
echo "::error ::$MSG"
echo $MSG >> ${COMMENT_LOG}
have_new_failures="true"
else
MSG="Skip an intermittent issue ${LINE}"
echo "::warning ::$MSG"
echo $MSG >> ${COMMENT_LOG}
echo ""
fi
fi
done
for LINE in ${REF_ERROR}
Generated
+7 -2
View File
@@ -878,6 +878,12 @@ dependencies = [
"libc",
]
[[package]]
name = "fundu"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925250bc259498d4008ee072bf16586083ab2c491aa4b06b3c4d0a6556cebd74"
[[package]]
name = "futures"
version = "0.3.25"
@@ -2807,7 +2813,6 @@ version = "0.0.17"
dependencies = [
"clap",
"libc",
"num_cpus",
"uucore",
]
@@ -3094,9 +3099,9 @@ version = "0.0.17"
dependencies = [
"atty",
"clap",
"fundu",
"libc",
"memchr",
"nix",
"notify",
"same-file",
"uucore",
+2 -1
View File
@@ -1,7 +1,7 @@
# coreutils (uutils)
# * see the repository LICENSE, README, and CONTRIBUTING files for more information
# spell-checker:ignore (libs) libselinux gethostid procfs bigdecimal kqueue
# spell-checker:ignore (libs) libselinux gethostid procfs bigdecimal kqueue fundu
[package]
name = "coreutils"
@@ -282,6 +282,7 @@ filetime = "0.2"
fnv = "1.0.7"
fs_extra = "1.1.0"
fts-sys = "0.2"
fundu = "0.3.0"
gcd = "2.2"
glob = "0.3.0"
half = "2.1"
+24 -2
View File
@@ -43,13 +43,23 @@ pacman -S uutils-coreutils
### Debian
[![Debian Unstable package](https://repology.org/badge/version-for-repo/debian_unstable/uutils-coreutils.svg)](https://packages.debian.org/sid/source/rust-coreutils)
[![Debian package](https://repology.org/badge/version-for-repo/debian_unstable/uutils-coreutils.svg)](https://packages.debian.org/sid/source/rust-coreutils)
```bash
apt install rust-coreutils
# To use it:
export PATH=/usr/lib/cargo/bin/coreutils:$PATH
```
> **Note**: Requires the `unstable` repository.
> **Note**: Only available from Bookworm (Debian 12)
### Gentoo
[![Gentoo package](https://repology.org/badge/version-for-repo/gentoo/uutils-coreutils.svg)](https://packages.gentoo.org/packages/sys-apps/uutils)
```bash
emerge -pv sys-apps/uutils
```
### Manjaro
![Manjaro Stable package](https://repology.org/badge/version-for-repo/manjaro_stable/uutils-coreutils.svg)
@@ -69,6 +79,18 @@ pamac install uutils-coreutils
nix-env -iA nixos.uutils-coreutils
```
### Ubuntu
[![Ubuntu package](https://repology.org/badge/version-for-repo/ubuntu_23_04/uutils-coreutils.svg)](https://packages.ubuntu.com/source/lunar/rust-coreutils)
```bash
apt install rust-coreutils
# To use it:
export PATH=/usr/lib/cargo/bin/coreutils:$PATH
```
> **Note**: Only available from Kinetic (Ubuntu 22.10)
## MacOS
### Homebrew
+11
View File
@@ -0,0 +1,11 @@
# cat
## Usage
```
cat [OPTION]... [FILE]...
```
## About
Concatenate FILE(s), or standard input, to standard output
With no FILE, or when FILE is -, read standard input.
+3 -4
View File
@@ -33,11 +33,10 @@ use std::net::Shutdown;
use std::os::unix::fs::FileTypeExt;
#[cfg(unix)]
use std::os::unix::net::UnixStream;
use uucore::format_usage;
use uucore::{format_usage, help_section, help_usage};
static USAGE: &str = "{} [OPTION]... [FILE]...";
static ABOUT: &str = "Concatenate FILE(s), or standard input, to standard output
With no FILE, or when FILE is -, read standard input.";
const USAGE: &str = help_usage!("cat.md");
const ABOUT: &str = help_section!("about", "cat.md");
#[derive(Error, Debug)]
enum CatError {
+18 -20
View File
@@ -12,15 +12,21 @@ use std::fs;
use std::os::unix::fs::{MetadataExt, PermissionsExt};
use std::path::Path;
use uucore::display::Quotable;
use uucore::error::{ExitCode, UResult, USimpleError, UUsageError};
use uucore::error::{set_exit_code, ExitCode, UResult, USimpleError, UUsageError};
use uucore::fs::display_permissions_unix;
use uucore::libc::mode_t;
#[cfg(not(windows))]
use uucore::mode;
use uucore::{format_usage, show_error};
use uucore::{format_usage, show, show_error};
static ABOUT: &str = "Change the mode of each FILE to MODE.
With --reference, change the mode of each FILE to that of RFILE.";
const ABOUT: &str = "Change the mode of each FILE to MODE.\n\
With --reference, change the mode of each FILE to that of RFILE.";
const USAGE: &str = "\
{} [OPTION]... MODE[,MODE]... FILE...
{} [OPTION]... OCTAL-MODE FILE...
{} [OPTION]... --reference=RFILE FILE...";
const LONG_USAGE: &str =
"Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'.";
mod options {
pub const CHANGES: &str = "changes";
@@ -34,15 +40,6 @@ mod options {
pub const FILE: &str = "FILE";
}
const USAGE: &str = "\
{} [OPTION]... MODE[,MODE]... FILE...
{} [OPTION]... OCTAL-MODE FILE...
{} [OPTION]... --reference=RFILE FILE...";
fn get_long_usage() -> &'static str {
"Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'."
}
#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let mut args = args.collect_lossy();
@@ -51,9 +48,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
// a possible MODE prefix '-' needs to be removed (e.g. "chmod -x FILE").
let mode_had_minus_prefix = mode::strip_minus_from_mode(&mut args);
let after_help = get_long_usage();
let matches = uu_app().after_help(after_help).try_get_matches_from(args)?;
let matches = uu_app().after_help(LONG_USAGE).try_get_matches_from(args)?;
let changes = matches.get_flag(options::CHANGES);
let quiet = matches.get_flag(options::QUIET);
@@ -200,21 +195,24 @@ impl Chmoder {
filename.quote()
);
if !self.quiet {
return Err(USimpleError::new(
show!(USimpleError::new(
1,
format!("cannot operate on dangling symlink {}", filename.quote()),
));
}
} else if !self.quiet {
return Err(USimpleError::new(
show!(USimpleError::new(
1,
format!(
"cannot access {}: No such file or directory",
filename.quote()
),
)
));
}
return Err(ExitCode::new(1));
// GNU exits with exit code 1 even if -q or --quiet are passed
// So we set the exit code, because it hasn't been set yet if `self.quiet` is true.
set_exit_code(1);
continue;
}
if self.recursive && self.preserve_root && filename == "/" {
return Err(USimpleError::new(
+19 -19
View File
@@ -32,21 +32,12 @@ mod options {
pub const TOTAL: &str = "total";
}
fn mkdelim(col: usize, opts: &ArgMatches) -> String {
let mut s = String::new();
let delim = match opts.get_one::<String>(options::DELIMITER).unwrap().as_str() {
"" => "\0",
delim => delim,
};
if col > 1 && !opts.get_flag(options::COLUMN_1) {
s.push_str(delim.as_ref());
fn column_width(col: &str, opts: &ArgMatches) -> usize {
if opts.get_flag(col) {
0
} else {
1
}
if col > 2 && !opts.get_flag(options::COLUMN_2) {
s.push_str(delim.as_ref());
}
s
}
fn ensure_nl(line: &mut String) {
@@ -70,7 +61,16 @@ impl LineReader {
}
fn comm(a: &mut LineReader, b: &mut LineReader, opts: &ArgMatches) {
let delim: Vec<String> = (0..4).map(|col| mkdelim(col, opts)).collect();
let delim = match opts.get_one::<String>(options::DELIMITER).unwrap().as_str() {
"" => "\0",
delim => delim,
};
let width_col_1 = column_width(options::COLUMN_1, opts);
let width_col_2 = column_width(options::COLUMN_2, opts);
let delim_col_2 = delim.repeat(width_col_1);
let delim_col_3 = delim.repeat(width_col_1 + width_col_2);
let ra = &mut String::new();
let mut na = a.read_line(ra);
@@ -98,7 +98,7 @@ fn comm(a: &mut LineReader, b: &mut LineReader, opts: &ArgMatches) {
Ordering::Less => {
if !opts.get_flag(options::COLUMN_1) {
ensure_nl(ra);
print!("{}{}", delim[1], ra);
print!("{ra}");
}
ra.clear();
na = a.read_line(ra);
@@ -107,7 +107,7 @@ fn comm(a: &mut LineReader, b: &mut LineReader, opts: &ArgMatches) {
Ordering::Greater => {
if !opts.get_flag(options::COLUMN_2) {
ensure_nl(rb);
print!("{}{}", delim[2], rb);
print!("{delim_col_2}{rb}");
}
rb.clear();
nb = b.read_line(rb);
@@ -116,7 +116,7 @@ fn comm(a: &mut LineReader, b: &mut LineReader, opts: &ArgMatches) {
Ordering::Equal => {
if !opts.get_flag(options::COLUMN_3) {
ensure_nl(ra);
print!("{}{}", delim[3], ra);
print!("{delim_col_3}{ra}");
}
ra.clear();
rb.clear();
@@ -128,7 +128,7 @@ fn comm(a: &mut LineReader, b: &mut LineReader, opts: &ArgMatches) {
}
if opts.get_flag(options::TOTAL) {
println!("{total_col_1}\t{total_col_2}\t{total_col_3}\ttotal");
println!("{total_col_1}{delim}{total_col_2}{delim}{total_col_3}{delim}total");
}
}
+12
View File
@@ -0,0 +1,12 @@
# cp
## Usage
```
cp [OPTION]... [-T] SOURCE DEST
cp [OPTION]... SOURCE... DIRECTORY
cp [OPTION]... -t DIRECTORY SOURCE...
```
## About
Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.
+3 -6
View File
@@ -40,7 +40,7 @@ use uucore::error::{set_exit_code, UClapError, UError, UResult, UUsageError};
use uucore::fs::{
canonicalize, paths_refer_to_same_file, FileInformation, MissingHandling, ResolveMode,
};
use uucore::{crash, format_usage, prompt_yes, show_error, show_warning};
use uucore::{crash, format_usage, help_section, help_usage, prompt_yes, show_error, show_warning};
use crate::copydir::copy_directory;
@@ -228,13 +228,10 @@ pub struct Options {
progress_bar: bool,
}
static ABOUT: &str = "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.";
const ABOUT: &str = help_section!("about", "cp.md");
static EXIT_ERR: i32 = 1;
const USAGE: &str = "\
{} [OPTION]... [-T] SOURCE DEST
{} [OPTION]... SOURCE... DIRECTORY
{} [OPTION]... -t DIRECTORY SOURCE...";
const USAGE: &str = help_usage!("cp.md");
// Argument constants
mod options {
+5 -9
View File
@@ -11,26 +11,22 @@ use uucore::display::print_verbatim;
use uucore::error::{UResult, UUsageError};
use uucore::format_usage;
static ABOUT: &str = "Strip last component from file name";
const ABOUT: &str = "Strip last component from file name";
const USAGE: &str = "{} [OPTION] NAME...";
const LONG_USAGE: &str = "\
Output each NAME with its last non-slash component and trailing slashes \n\
removed; if NAME contains no /'s, output '.' (meaning the current directory).";
mod options {
pub const ZERO: &str = "zero";
pub const DIR: &str = "dir";
}
fn get_long_usage() -> &'static str {
"Output each NAME with its last non-slash component and trailing slashes \n\
removed; if NAME contains no /'s, output '.' (meaning the current directory)."
}
#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let args = args.collect_lossy();
let matches = uu_app()
.after_help(get_long_usage())
.try_get_matches_from(args)?;
let matches = uu_app().after_help(LONG_USAGE).try_get_matches_from(args)?;
let separator = if matches.get_flag(options::ZERO) {
"\0"
+4 -8
View File
@@ -22,8 +22,10 @@ use uucore::{format_usage, show, show_if_err};
static DEFAULT_PERM: u32 = 0o755;
static ABOUT: &str = "Create the given DIRECTORY(ies) if they do not exist";
const ABOUT: &str = "Create the given DIRECTORY(ies) if they do not exist";
const USAGE: &str = "{} [OPTION]... [USER]";
const LONG_USAGE: &str =
"Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'.";
mod options {
pub const MODE: &str = "mode";
@@ -32,10 +34,6 @@ mod options {
pub const DIRS: &str = "dirs";
}
fn get_long_usage() -> &'static str {
"Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'."
}
#[cfg(windows)]
fn get_mode(_matches: &ArgMatches, _mode_had_minus_prefix: bool) -> Result<u32, String> {
Ok(DEFAULT_PERM)
@@ -92,9 +90,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
// Linux-specific options, not implemented
// opts.optflag("Z", "context", "set SELinux security context" +
// " of each created directory to CTX"),
let matches = uu_app()
.after_help(get_long_usage())
.try_get_matches_from(args)?;
let matches = uu_app().after_help(LONG_USAGE).try_get_matches_from(args)?;
let dirs = matches
.get_many::<OsString>(options::DIRS)
-1
View File
@@ -16,7 +16,6 @@ path = "src/nproc.rs"
[dependencies]
libc = { workspace=true }
num_cpus = { workspace=true }
clap = { workspace=true }
uucore = { workspace=true, features=["fs"] }
+16 -7
View File
@@ -8,7 +8,7 @@
// spell-checker:ignore (ToDO) NPROCESSORS nprocs numstr threadstr sysconf
use clap::{crate_version, Arg, ArgAction, Command};
use std::env;
use std::{env, thread};
use uucore::display::Quotable;
use uucore::error::{UResult, USimpleError};
use uucore::format_usage;
@@ -73,16 +73,16 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
// If OMP_NUM_THREADS=0, rejects the value
let thread: Vec<&str> = threadstr.split_terminator(',').collect();
match &thread[..] {
[] => num_cpus::get(),
[] => available_parallelism(),
[s, ..] => match s.parse() {
Ok(0) | Err(_) => num_cpus::get(),
Ok(0) | Err(_) => available_parallelism(),
Ok(n) => n,
},
}
}
// the variable 'OMP_NUM_THREADS' doesn't exist
// fallback to the regular CPU detection
Err(_) => num_cpus::get(),
Err(_) => available_parallelism(),
}
};
@@ -127,7 +127,7 @@ fn num_cpus_all() -> usize {
if nprocs == 1 {
// In some situation, /proc and /sys are not mounted, and sysconf returns 1.
// However, we want to guarantee that `nproc --all` >= `nproc`.
num_cpus::get()
available_parallelism()
} else if nprocs > 0 {
nprocs as usize
} else {
@@ -135,7 +135,7 @@ fn num_cpus_all() -> usize {
}
}
// Other platforms (e.g., windows), num_cpus::get() directly.
// Other platforms (e.g., windows), available_parallelism() directly.
#[cfg(not(any(
target_os = "linux",
target_vendor = "apple",
@@ -143,5 +143,14 @@ fn num_cpus_all() -> usize {
target_os = "netbsd"
)))]
fn num_cpus_all() -> usize {
num_cpus::get()
available_parallelism()
}
// In some cases, thread::available_parallelism() may return an Err
// In this case, we will return 1 (like GNU)
fn available_parallelism() -> usize {
match thread::available_parallelism() {
Ok(n) => n.get(),
Err(_) => 1,
}
}
+16 -21
View File
@@ -37,8 +37,22 @@ struct Options {
verbose: bool,
}
static ABOUT: &str = "Remove (unlink) the FILE(s)";
const ABOUT: &str = "Remove (unlink) the FILE(s)";
const USAGE: &str = "{} [OPTION]... FILE...";
const LONG_USAGE: &str = "\
By default, rm does not remove directories. Use the --recursive (-r or -R)
option to remove each listed directory, too, along with all of its contents
To remove a file whose name starts with a '-', for example '-foo',
use one of these commands:
rm -- -foo
rm ./-foo
Note that if you use rm to remove a file, it might be possible to recover
some of its contents, given sufficient expertise and/or time. For greater
assurance that the contents are truly unrecoverable, consider using shred.";
static OPT_DIR: &str = "dir";
static OPT_INTERACTIVE: &str = "interactive";
static OPT_FORCE: &str = "force";
@@ -53,28 +67,9 @@ static PRESUME_INPUT_TTY: &str = "-presume-input-tty";
static ARG_FILES: &str = "files";
fn get_long_usage() -> String {
String::from(
"By default, rm does not remove directories. Use the --recursive (-r or -R)
option to remove each listed directory, too, along with all of its contents
To remove a file whose name starts with a '-', for example '-foo',
use one of these commands:
rm -- -foo
rm ./-foo
Note that if you use rm to remove a file, it might be possible to recover
some of its contents, given sufficient expertise and/or time. For greater
assurance that the contents are truly unrecoverable, consider using shred.",
)
}
#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let matches = uu_app()
.after_help(get_long_usage())
.try_get_matches_from(args)?;
let matches = uu_app().after_help(LONG_USAGE).try_get_matches_from(args)?;
let files: Vec<String> = matches
.get_many::<String>(ARG_FILES)
+5 -62
View File
@@ -13,7 +13,7 @@ use uucore::fsext::{
pretty_filetype, pretty_fstype, pretty_time, read_fs_list, statfs, BirthTime, FsMeta,
};
use uucore::libc::mode_t;
use uucore::{entries, format_usage, show_error, show_warning};
use uucore::{entries, format_usage, help_section, help_usage, show_error, show_warning};
use clap::{crate_version, Arg, ArgAction, ArgMatches, Command};
use std::borrow::Cow;
@@ -24,8 +24,9 @@ use std::os::unix::fs::{FileTypeExt, MetadataExt};
use std::os::unix::prelude::OsStrExt;
use std::path::Path;
const ABOUT: &str = "Display file or file system status.";
const USAGE: &str = "{} [OPTION]... FILE...";
const ABOUT: &str = help_section!("about", "stat.md");
const USAGE: &str = help_usage!("stat.md");
const LONG_USAGE: &str = help_section!("long usage", "stat.md");
mod options {
pub const DEREFERENCE: &str = "dereference";
@@ -751,67 +752,9 @@ impl Stater {
}
}
fn get_long_usage() -> &'static str {
"
The valid format sequences for files (without --file-system):
%a access rights in octal (note '#' and '0' printf flags)
%A access rights in human readable form
%b number of blocks allocated (see %B)
%B the size in bytes of each block reported by %b
%C SELinux security context string
%d device number in decimal
%D device number in hex
%f raw mode in hex
%F file type
%g group ID of owner
%G group name of owner
%h number of hard links
%i inode number
%m mount point
%n file name
%N quoted file name with dereference if symbolic link
%o optimal I/O transfer size hint
%s total size, in bytes
%t major device type in hex, for character/block device special files
%T minor device type in hex, for character/block device special files
%u user ID of owner
%U user name of owner
%w time of file birth, human-readable; - if unknown
%W time of file birth, seconds since Epoch; 0 if unknown
%x time of last access, human-readable
%X time of last access, seconds since Epoch
%y time of last data modification, human-readable
%Y time of last data modification, seconds since Epoch
%z time of last status change, human-readable
%Z time of last status change, seconds since Epoch
Valid format sequences for file systems:
%a free blocks available to non-superuser
%b total data blocks in file system
%c total file nodes in file system
%d free file nodes in file system
%f free blocks in file system
%i file system ID in hex
%l maximum length of filenames
%n file name
%s block size (for faster transfers)
%S fundamental block size (for block counts)
%t file system type in hex
%T file system type in human readable form
NOTE: your shell may have its own version of stat, which usually supersedes
the version described here. Please refer to your shell's documentation
for details about the options it supports.
"
}
#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let matches = uu_app()
.after_help(get_long_usage())
.try_get_matches_from(args)?;
let matches = uu_app().after_help(LONG_USAGE).try_get_matches_from(args)?;
let stater = Stater::new(&matches)?;
let exit_status = stater.exec();
+64
View File
@@ -0,0 +1,64 @@
# stat
## About
Display file or file system status.
## Usage
```
stat [OPTION]... FILE...
```
## Long Usage
The valid format sequences for files (without `--file-system`):
%a access rights in octal (note '#' and '0' printf flags)
%A access rights in human readable form
%b number of blocks allocated (see %B)
%B the size in bytes of each block reported by %b
%C SELinux security context string
%d device number in decimal
%D device number in hex
%f raw mode in hex
%F file type
%g group ID of owner
%G group name of owner
%h number of hard links
%i inode number
%m mount point
%n file name
%N quoted file name with dereference if symbolic link
%o optimal I/O transfer size hint
%s total size, in bytes
%t major device type in hex, for character/block device special files
%T minor device type in hex, for character/block device special files
%u user ID of owner
%U user name of owner
%w time of file birth, human-readable; - if unknown
%W time of file birth, seconds since Epoch; 0 if unknown
%x time of last access, human-readable
%X time of last access, seconds since Epoch
%y time of last data modification, human-readable
%Y time of last data modification, seconds since Epoch
%z time of last status change, human-readable
%Z time of last status change, seconds since Epoch
Valid format sequences for file systems:
%a free blocks available to non-superuser
%b total data blocks in file system
%c total file nodes in file system
%d free file nodes in file system
%f free blocks in file system
%i file system ID in hex
%l maximum length of filenames
%n file name
%s block size (for faster transfers)
%S fundamental block size (for block counts)
%t file system type in hex
%T file system type in human readable form
NOTE: your shell may have its own version of stat, which usually supersedes
the version described here. Please refer to your shell's documentation
for details about the options it supports.
+3 -4
View File
@@ -1,3 +1,4 @@
# spell-checker:ignore (libs) kqueue fundu
[package]
name = "uu_tail"
version = "0.0.17"
@@ -19,17 +20,15 @@ clap = { workspace=true }
libc = { workspace=true }
memchr = { workspace=true }
notify = { workspace=true }
uucore = { workspace=true, features=["ringbuffer", "lines"] }
uucore = { workspace=true }
same-file = { workspace=true }
atty = { workspace=true }
fundu = { workspace=true }
[target.'cfg(windows)'.dependencies]
windows-sys = { workspace=true, features = ["Win32_System_Threading", "Win32_Foundation"] }
winapi-util = { workspace=true }
[target.'cfg(unix)'.dependencies]
nix = { workspace=true, features = ["fs"] }
[[bin]]
name = "tail"
path = "src/main.rs"
+16 -11
View File
@@ -3,13 +3,14 @@
// * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.
// spell-checker:ignore (ToDO) kqueue Signum
// spell-checker:ignore (ToDO) kqueue Signum fundu
use crate::paths::Input;
use crate::{parse, platform, Quotable};
use atty::Stream;
use clap::crate_version;
use clap::{parser::ValueSource, Arg, ArgAction, ArgMatches, Command};
use fundu::DurationParser;
use same_file::Handle;
use std::collections::VecDeque;
use std::ffi::OsString;
@@ -148,16 +149,20 @@ impl Settings {
settings.retry =
matches.get_flag(options::RETRY) || matches.get_flag(options::FOLLOW_RETRY);
if let Some(s) = matches.get_one::<String>(options::SLEEP_INT) {
settings.sleep_sec = match s.parse::<f32>() {
Ok(s) => Duration::from_secs_f32(s),
Err(_) => {
return Err(UUsageError::new(
1,
format!("invalid number of seconds: {}", s.quote()),
))
}
}
if let Some(source) = matches.get_one::<String>(options::SLEEP_INT) {
// Advantage of `fundu` over `Duration::(try_)from_secs_f64(source.parse().unwrap())`:
// * doesn't panic on errors like `Duration::from_secs_f64` would.
// * no precision loss, rounding errors or other floating point problems.
// * evaluates to `Duration::MAX` if the parsed number would have exceeded
// `DURATION::MAX` or `infinity` was given
// * not applied here but it supports customizable time units and provides better error
// messages
settings.sleep_sec =
DurationParser::without_time_units()
.parse(source)
.map_err(|_| {
UUsageError::new(1, format!("invalid number of seconds: '{source}'"))
})?;
}
settings.use_polling = matches.get_flag(options::USE_POLLING);

Some files were not shown because too many files have changed in this diff Show More