Fix two issues with the string formatting width for counts displayed
by `wc`.
First, the output was previously not using the default minimum width
(seven characters) when reading from `stdin`. This commit corrects
this behavior to match GNU `wc`. For example,
$ cat alice_in_wonderland.txt | wc
5 57 302
Second, if at least 10^7 bytes were read from `stdin` *after* reading
from a smaller regular file, then every output row would have width
8. This disagrees with GNU `wc`, in which only the `stdin` row and the
total row would have width 8. This commit corrects this behavior to
match GNU `wc`. For example,
$ printf "%.0s0" {1..10000000} | wc emptyfile.txt -
0 0 0 emptyfile.txt
0 1 10000000
0 1 10000000 total
Fixes#2186.
Change the error messages that get printed to `stderr` for compatibility
with GNU `wc` when an input is a directory and when an input does not
exist.
Fixes#2211.
This closes#2181.
`who --lookup` is failing with a runtime panic (double free).
Since `crate::dns-lookup` already includes a safe wrapper for `getaddrinfo`
I used this crate instead of further debugging the existing code in
utmpx::canon_host().
* It was neccessary to remove the version constraint for libc in uucore.
Refactor code from the `backwards_thru_file()` function into a new
`ReverseChunks` iterator, and use that iterator to simplify the
implementation of the `backwards_thru_file()` function. The
`ReverseChunks` iterator yields `Vec<u8>` objects, each of which
references bytes of a given file.
- add `==` as undocumented alias of `=`
- handle negated comparison of `=` as literal
- negation generally applies to only the first expression of a Boolean chain,
except when combining evaluation of two literal strings
Refactor common code out of two branches of the `unbounded_tail()`
function into a new `unbounded_tail_collect()` helper function, that
collects from an iterator into a `VecDeque` and keeps either the last
`n` elements or all but the first `n` elements.
This commit also adds a new struct, `RingBuffer`, in a new module,
`ringbuffer.rs`, to be responsible for keeping the last `n` elements
of an iterator.
When merging files we need to prioritize files that occur earlier in the
command line arguments with -m.
This also makes the extsort merge step (and thus extsort itself) stable again.
Refactor the counting code from the inner loop of the `wc` program
into the `WordCount::from_line()` associated function. This commit
also splits that function up into other helper functions that
encapsulate decoding characters and finding word boundaries from raw
bytes.
This commit also implements the `Sum` trait for the `WordCount`
struct, so that we can simply call `sum()` on an iterator that yields
`WordCount` instances.
This is a refactor to reduce duplicate code, it affects chmod/ls/stat.
* merge `stat/src/fsext::pretty_access` into `uucore/src/lib/feature/fs::display_permissions_unix`
* move tests for `fs::display_permissions` from `test_stat::test_access` to `uucore/src/lib/features/fs::test_display_permissions`
* adjust `uu_chmod`, `uu_ls` and `uu_stat` to use `uucore::fs::display_permissions`
FileMerger is much more efficient than the previous algorithm,
which looped over all elements every time to determine the next element.
FileMerger uses a BinaryHeap, which should bring the complexity for
the merge step down from O(n²) to O(n log n).
* ls: Implement total size feature
- Implement total size reporting that was missing
- Fix minor formatting / readability nits
* tests: Add tests for ls total sizes feature
* ls: Fix MSRV build errors due to unsupported attributes for if blocks
* ls: Add windows support for total sizes feature
- Add windows support (defaults to file size as block sizes related
infromation is not avialable on windows)
- Renamed some functions
Add the `WordCountable::lines()` method that returns an iterator over
lines of a file-like object. This mirrors the
`std::io::BufRead::lines()` method, with some minor differences due to
the particular use case of `wc`.
This commit also creates a new module, `countable.rs`, to contain the
`WordCountable` trait and the new `Lines` struct returned by `lines()`.
Use clap for argument parsing instead of getopts
Also, make the following changes
* Use `executable!()` macro to output the name of utility
* Add another usage to help message
- Replace the parser with a recursive descent implementation that handles
parentheses and produces a stack of operations in postfix order.
Parsing now operates directly on OsStrings passed by the uucore framework.
- Replace the dispatch mechanism with a stack machine operating on the
symbol stack produced by the parser.
- Add tests for parenthesized expressions.
- Begin testing character encoding handling.
Moved argument parsing to clap and added tests to cover using "-" as
stdin, passing in too many file arguments, and updated the "wrap" error
message in the tests.
It is much faster to just write the lines to disk, separated by \n
(or \0 if zero-terminated is enabled), instead of serializing to json.
external_sort now knows of the Line struct instead of interacting with
it using the ExternallySortable trait. Similarly, it now uses the
crash_if_err! macro to handle errors, instead of bubbling them up.
Some functions were changed from taking &[Line] as the input to taking
an Iterator<Item = Line>. This removes the need to collect to a Vec
when not necessary.
This removes the need to allocate a new string for each line when used
with -f, -d or -i. Instead, a custom string comparison algorithm takes
care of these cases.
The resulting performance improvement is about 20% per flag (i.e. there
is a 60% improvement when combining all three flags)
As a side-effect, the size of the Line struct was reduced from 96 to 80
bytes, reducing the overhead for each line.
Add crossterm as dependency
Complete the paging portion
Fixed tests
cp: extract linux COW logic into function
cp: add --reflink support for macOS
Fixes#1773
Fix error in Cargo.lock
Quit automatically if not much output is left
Remove unnecessary redox and windows specific code
Handle line wrapping
Put everything according to uutils coding standards
Add support for multiple files
Fix failing test
Use the args argument to get cli arguments
Fix bug where text is repeated multiple times during printing
Add a little prompt
Add a top file prompt for multiple files
Change println in loops to stdout.write and setup terminal only once
Fix bug where all lines were printed in a single row
Remove useless file and fix failing test
Fix another test
* ls: added creation time
* ls: Added most time features
Missing support for posix-,Format+, translating via locales. Also required more tests
* ls: rustfmt
* ls: Additional changes and fixes
Fixed the argument order, fixed a wrong iso format.
* ls: additional tests for styles
* ls: perfected arg parsing on time styles
* fix birthime test
* ls: Use 'stdout_str' in new tests
* ls: Disabled birthtime test for windows
* ls: removed indoc as a dependency
* ls: birthime test, sync first created file
* ls: birthime test, add comment explaining sync
* Removed ruby testfile birth_test.rb
This accidentally got commited in a merge
Note, I needed to change the error messages in one of the tests because
getopt and clap have different error messages when not providing a
default value
* Change unchecked unwrapping to unwrap_or_default for argument parsing (resolving #1845)
* Added unit-testing for the collect_str function on invalid utf8 OsStrs
* Added a warning-message for identification purpose to the collect_str method.
* - Add removal of wrongly encoded empty strings to basename
- Add testing of broken encoding to basename
- Changed UCommand to use collect_str in args method to allow for integration testing of that method
- Change UCommand to use unwarp_or_default in arg method to match the behaviour of collect_str
* Trying out a new pattern for convert_str for getting a feeling of how the API feels with more control
* Adding convenience API for compact calls
* Add new API to everywhere, fix test for basename
* Added unit-testing for the conversion options
* Added unit-testing for the conversion options for windows
* fixed compilation and some merge hiccups
* Remove windows tests in order to make merge request build
* Fix formatting to match rustfmt for the merged file
* Improve documentation of the collect_str method and the unit-tests
* Fix compilation problems with test
Co-authored-by: Christopher Regali <chris.vdop@gmail.com>
Co-authored-by: Sylvestre Ledru <sylvestre@debian.org>
* ls: ignore leading period when sorting by name
ls now behaves like GNU ls with respect to sorting files by ignoring
leading periods when sorting by main.
Added tests to ensure "touch a .a b .b ; ls" returns ".a a .b b"
* Replaced clone/collect calls.
* Use buffered stdout to reduce write sys calls.
This simple change yielded the biggest performace gain.
* Use `for_byte_record_with_terminator` from the `bstr` crate.
This is to minimize the per line copying needed by
`BufReader::read_until`. The `cut_fields` and `cut_fields_delimiter`
functions used `read_until` to iterate over lines. That required copying
each input line to the line buffer. With
`for_byte_record_with_terminator` copying is minimized as it calls our
closure with a reference to BufReader's buffer most of the time. It
needs to copy (internally) only to process any incomplete lines at the
end of the buffer.
* Re-write `Searcher` to use `memchr`.
Switch from the naive implementation to one that uses `memchr`.
* Rewrite `cut_bytes` almost entirely.
This was already well optimized. The performance gain in this case is
not from avoiding copying. In fact, it needed zero copying whereas new
implementation introduces some copying similar to `cut_fields` described
above. But the occassional copying cost is more than offset by the use
of the very fast `memchr` inside `for_byte_record_with_terminator`.
This change also simplifies the code significantly. Removed the `buffer`
module.
This adds a --debug flag, which, when activated, will draw lines below
the characters that are actually used for comparisons.
This is not a complete implementation of --debug. It should, quoting the man page
for GNU sort: "annotate the part of the line used to sort, and warn
about questionable usage to stderr". Warning about "questionable usage"
is not part of this patch.
This change required some adjustments to be able to get the range that
is actually used for comparisons. Most notably, general numeric comparisons
were rewritten, fixing some bugs along the lines.
Testing is mostly done by adding fixtures for the expected debug output of
existing tests.
* ls: Remove allocations by eliminating collect/clones
* ls: Introduce PathData structure
- PathData will hold Path related metadata / strings that are required
frequently in subsequent functions
- All data is precomputed and cached and subsequent functions just
use cached data
* ls: Cache more data related to paths
- Cache filename and sort by filename instead of full path
- Cache uid->usr and gid->grp mappings
https://github.com/uutils/coreutils/pull/2099/files
* ls: Add BENCHMARKING.md
* ls: Document PathData structure
* tests/ls: Add testcase for error paths with width option
* ls: Fix unused import warning
cached will be only used for unix currently as current use of
caching gid/uid mappings is only relevant on unix
* ls: Suggest checking syscall count in BENCHMARKING.md
* ls: Remove mentions of sort in BENCHMARKING.md
* ls: Remove dependency on cached
Implement caching using HashMap and lazy_static
* ls: Fix MSRV error related to map_or
Rust 1.40 did not support map_or for result types
Trailing separators were included at the end of the last token, but they
should not be.
This changes tokenize_with_separator as suggested by @cbjadwani.
GNU sort disallows these combinations, presumably because they are
likely not what the user really wants.
Ignoring characters would cause things to be put together that aren't
together in the input. For example, -dn would cause "0.12" or "0,12" to
be parsed as "12" which is highly unexpected and confusing.
This reduces memory usage by only storing two lines of the input file at
a time. The current implementation first builds a list of all duplicate
lines ('group') and then decides which lines of the group should be
printed.
- Passing `never` to `--reflink` does not raise an error anymore.
- Remove `Options::reflink` flag as it was redundant with
`reflink_mode`.
- Add basic tests for this option. Does not check that a copy-on-write
rather than a regular copy was made.
* sort: use unstable sort when possible
This results in a very minor performance (speed) improvement.
It does however result in a memory usage reduction, because unstable
sort does not allocate auxiliary memory. There's also an improvement in
overall CPU usage.
* add benchmarking instructions
* add user time
* fix typo
* sort: implement numeric string comparison
This implements -n and -h using a string comparison algorithm instead
of parsing each number to a f64 and comparing those.
This should result in a moderate performance increase and eliminate loss
of precision.
* cache parsed f64 numbers
For general numeric comparisons we have to parse numbers as f64,
as this behavior is explicitly documented by GNU coreutils.
We can however cache the parsed value to speed up comparisons.
* fix leading zeroes for negative numbers
* use more appropriate name for exponent
* improvements to the parse function
* move checks into main loop and fix thousands separator condition
* remove unneeded checks
* rustfmt
* du error output should match GNU
* Created a new error macro which allows the customization of the
"error:" string part
* Match the du output based on the type of error encountered. Can extend
to handling other errors I guess.
* Rustfmt updates
* Added non-windows test for du no permission output
* Various fixes and performance improvements
* fix a typo
Co-authored-by: Michael Debertol <michael.debertol@gmail.com>
* Fix month parse for months with leading whitespace
* Implement test for months whitespace fix
* Confirm human numeric works as expected with whitespace with a test
* Correct arg help value name for --parallel
* Fix SemVer non version lines/empty line sorting with a test
Co-authored-by: Sylvestre Ledru <sledru@mozilla.com>
Co-authored-by: Michael Debertol <michael.debertol@gmail.com>
* cat: Unrevert splice patch
* cat: Add fifo test
* cat: Add tests for error cases
* cat: Add tests for character devices
* wc: Make sure we handle short splice writes
* cat: Fix tests for 1.40.0 compiler
* cat: Run rustfmt on test_cat.rs
* Run 'cargo +1.40.0 update'
* sort: implement basic -k and -t support
This allows to specify keys after the -k flag and a custom field
separator using -t.
Support for options for specific keys is still missing, and the -b flag
is not passed down correctly.
* sort: implement support for key options
* remove unstable feature use
* don't pipe in input when we expect a failure
* only tokenize when needed, remove a clone()
* improve comments
* fix clippy lints
* re-add test
* buffer writes to stdout
* fix ignore_non_printing
and make the test fail in case it is broken :)
* move attribute to the right position
* add more tests
* add my name to the copyright section
* disallow dead code
* move a comment
* re-add a loc
* use smallvec for a perf improvement in the common case
* add BENCHMARKING.md
* add ignore_case to benchmarks
* Various fixes and performance improvements
* fix a typo
Co-authored-by: Michael Debertol <michael.debertol@gmail.com>
Co-authored-by: Sylvestre Ledru <sledru@mozilla.com>
Co-authored-by: Michael Debertol <michael.debertol@gmail.com>
* Replace outdated time 0.1 dependancy with latest version of chrono
I also noticed that times are being miscalculated on linux, so I fixed that.
* Add time test for issue #2042
* Cleanup use declarations
* Tie time test to `touch` feature
- if we compile with the right OS feature flag then we should have it,
even on Windows
Forgot to handle the case where no arguments were passed to the COMMAND.
Because ARGS can be empty, we need two separate cases for handling
options.values_of(options::ARGS)
Fixed some minor ownership issues in converting from the options to the
arguments to the timeout COMMAND.
Additionally, fixed a rustfmt issue in other files (fold/stdbuf.rs)
Changed from optparse to clap.
None of the logic within timeout has been changed, which could use some
refactoring, but that's beyond the scope of this commit.
refactor `is_wsl` to `is_wsl_1` and `is_wsl_2`
On my tests with wsl2 ubuntu2004 all tests pass without special cases
I moved wsl detection into uucore so that it can be shared instead of duplicated
I moved `parse_mode` into uucode as it seemed to fit there better and anyway requires libc feature
Treat tab chars as advancing to the next tab stop rather than having a fixed
8-column width.
Also treat tab as a whitespace split target only when splitting on word
boundaries.
The '-d' flag should create all ancestors (or components) of a
directory regardless of the presence of the "-D" flag.
From the man page:
-d, --directory
treat all arguments as directory names; create all components of the specified directories
With GNU:
$ install -v -d dir1/di2
install: creating directory 'dir1'
install: creating directory 'dir1/di2'
With this version:
$ ./target/release/install -v -d dir3/di4
install: dir3/di4: No such file or directory (os error 2)
install: dir3/di4: chmod failed with error No such file or directory (os error 2)
install: created directory 'dir3/di4'
Also, one of the unit tests misinterprets what a "component" is,
and hence was fixed.
Also don't run chmod when we just failed to create the directory.
Behaviour before this patch:
$ ./target/release/install -v -d dir1/dir2
install: dir1/dir2: Permission denied (os error 13)
install: dir1/dir2: chmod failed with error No such file or directory (os error 2)
install: created directory 'dir1/dir2'
* Issue #1622 port `du` to windows
* Attempt to support Rust 1.32
Old version was getting "attributes are not yet allowed on `if`
expressions" on Rust 1.32
* Less #[cfg]
* Less duplicate code.
I need the return and the semicolon after if otherwise the second #[cfg]
leads to unexpected token complilation error
* More accurate size on disk calculations for windows
* Expect the same output on windows as with WSL
* Better matches output from du on WSL
* In the absence of feedback I'm disabling these tests on Windows.
They require `ln`. Windows does not ship with this utility.
* Use the coreutils version of `ln` to test `du`
`fn ccmd` is courtesy of @Artoria2e5
* Look up inodes (file ids) on Windows
* One more #[cfg(windows)] to prevent unreachable statement warning on linux
* cat: Improve performance, especially on Linux
* cat: Don't use io::copy for splice fallback
On my MacBook Pro 2020, it is around 25% faster to not use io::copy.
* cat: Only fall back to generic copy if first splice fails
* cat: Don't double buffer stdout
* cat: Don't use experimental or-pattern syntax
* cat: Remove nix symbol use from non-Linux
* wc: Don't read() if we only need to count number of bytes
* Resolve a few code review comments
* Use write macros instead of print
* Fix wc tests in case only one thing is printed
* wc: Fix style
* wc: Use return value of first splice rather than second
* wc: Make main loop more readable
* wc: Don't unwrap on failed write to stdout
* wc: Increment error count when stats fail to print
* Re-add Cargo.lock
* Implemented --indicator-style flag on ls.
* Rust fmt
* Grouped indicator_style args.
* Added tests for sockets and pipes.
Needed to modify util.rs to add support for pipes (aka FIFOs).
* Updated util.rs to remove FIFO operations on Windows
* Fixed slight error in specifying (not(windows))
* Fixed style violations and added indicator_style test for non-unix systems
+ aligned 'tee' output with GNU tee when one of the files is '/dev/full'
+ don't stop tee when one of the outputs fails; just continue and return
error status from tee in the end
Co-authored-by: Ivan Rymarchyk <irymarchyk@arlo.com>
* mkfifo: general refactor, move to clap, add unimplemented flags
* chore: update Cargo.lock
* chore: delete unused variables, simplify multiple lines with crash
* test: add tests
* chore: revert the use of crash
* test: use even more invalid mod mode
* install: implement `-C` / `--compare`
GNU coreutils [1] checks the following: whether
- either file is nonexistent,
- there's a sticky bit or set[ug]id bit in play,
- either file isn't a regular file,
- the sizes of both files mismatch,
- the destination file's owner differs from intended, or
- the contents of both files mismatch.
[1] https://git.savannah.gnu.org/cgit/coreutils.git/tree/src/install.c?h=v8.32#n174
* Add test: non-regular files
* Forgot a #[test]
* Give up on non-regular file test
* `cargo fmt` install.rs
Previously this used `print` instead of `println`, and as a result the
prompt would never appear and the command would hang. The Rust docs
note this about print:
> Note that stdout is frequently line-buffered by default so it may be
> necessary to use io::stdout().flush() to ensure the output is emitted
> immediately.
Changing to `println` fixes the issue.
Fixes#1889.
Co-authored-by: Kevin Burke <kevin@burke.dev>
* feat: move unexpand to clap
* chore: allow muliple files
* test: add test fixture, test reading from a file
* test: fix typo on file name, add test for multiple inputs
* chore: use 'success()' instead of asserting
* chore: delete unused variables
* chore: use help instead of long_help, break long line
* fix: use settings to allow leading hyphen and trailing var arg
fixes: https://github.com/uutils/coreutils/issues/1873
* test: add test cases
* test: add more test cases with different order in hyphen values
* chore: add comment to explain why we need TrailingVarArg
- changed some error return codes to match GNU implementation
- changed warning/error messages to match GNU nohup
- replaced getopts dependency with clap
- added a test
This PR adds the options to customize what information is shown in long format regarding author, group & owner. Specifically it adds:
- `--author`: shows the author, which is always the same as the owner. GNU has this feature because GNU/Hurd supports a difference between author and owner, but I don't think Rust supports GNU/Hurd, so I just used the owner.
- `-G` & `--no-group`: hide the group information.
- `-o`: hide the group and use long format (equivalent to `-lG`).
- `-g`: hide the owner and use long format.
The `-o` and `-g` options have some interesting behaviour that I had to account for. Some examples:
- `-og` hides both group and owner.
- `-ol` still hides the group. Same behaviour with variations such as `-o --format=long`, `-gl`, `-g --format=long` and `-ogl`.
- They even retain some information when overridden by another format: `-oCl` (or `-o --format=vertical --format=long`) still hides the group.
My previous solution for handling the behaviour where `-l1` shows the long format did not fit with these additions, so I had to rewrite that as well.
The tests only cover the how many names (author, group and owner) are present in the output, so it can't distinguish between, for example, author & group and group & owner.
It was a draft PR, not ready for merging, and its premature inclusion
caused repeated issues, see 368f47381b & friends.
Close#1841.
This reverts commits 3743a3e1e7,
ce218e01b6, and
b7b0c76b8e.
* date: implement set date for unix and windows
Parsing the date string is not fully implemented yet, as in it relies
on the internals of chrono - things like "Mon, 14 Aug 2006 02:34:56 -0600"
do not work, nor does "2006-08-14 02:34:56" (no TZ / local time). This
is no different to using the "--date" option however, and will get fixed
when `parse_date` is a bit smarter.
Only supports unix and Windows platforms for now.
* factor::tests::recombines_factors: Minor refactor (skip useless bool)
* factor::tests: Check factorizations of powers of factored numbers
* factor::Factors: Add debug assertions to (Factor ^ Exponent)
* factor::tests: Drop obsoleted tests
`factor_correctly_recombines_prior_test_failures` was replaced with
`factor_2044854919485649` as this was the only test not subsumed.
* factor::tests::2044854919485649: Check the expected factorisation
Current implementation of the skip fields logic does not handle
multibyte code points correctly. It assumes each code point (`char`) is
one byte. If the skipped part of the input line has any multibyte code
points then this can cause fields not being skipped correctly (field
start index is calculated to be before it actually starts).
expand has one odd behavior that allows two format for tabstop
From expand --help
```
-t, --tabs=N have tabs N characters apart, not 8
-t, --tabs=LIST use comma separated list of tab positions
```
This patch use one `value_name("N, LIST")` for tabstop and
deal with above behavior in `parse_tabstop`.
Close#1795
* touch: use arggroup for sources
* tests/touch: add tests for multiple sources
* touch: turn macros into functions
* test/touch: fmt
* touch: constant for the sources ArgGroup
New tests in busybox are based on the fact that the function
appears in the usage of the busybox binary.
Because the tests are searching for an exact string they don't see
the function defined by coreutils.
By using the exact same string as busybox we can now also run the new
busybox tests
- added `-` as the default input, since `paste` reads stdin if no file
is provided
- `paste` also supports providing `-` multiple times
- added a test for it
* muted test not for windows and added windows temp file convention
* Update mktemp.rs
Revert windows mktmp template difference
Co-authored-by: Chad Brewbaker <chad@flyingdogsolutions.com>
When converting to SI or IEC, produce values that align with the conventions
used by GNU numfmt.
- values > 10 are represented without a decimal place, so 10000 becomes 10K
instead of 10.0K
- when truncating, take the ceiling of the value, so 100001 becomes 101K
- values < 10 are truncated to the highest tenth, so 1001 becomes 1.1K
closes#1726
Adjust header option handling to prohibit passing a value of 0 to align
with GNU numfmt. Also report header option parse errors as GNU does.
closes#1708
Align with GNU numfmt by trimming leading whitespace from supplied values.
If the user did not specify a padding, calculate an implied padding from
the leading whitespace and the value.
Also track closer to GNU numfmt’s error message format.
Previously if no --color argument was input, we would always print
colors in the output. This breaks `configure` scripts which run `ls`
and then compare the output against what they expect to see, since the
left side has ANSI escape sequences and the right side doesn't.
Instead, only print escape sequences if a TTY is present, or if
`--color=always` is specified.
Fixes#1638.