From 67b07eaaa9297389d7c32abdf61947babad02141 Mon Sep 17 00:00:00 2001 From: Roy Ivy III Date: Mon, 23 Nov 2015 00:00:01 -0500 Subject: [PATCH] create empty repository for 'uucore' --- .busybox-config | 2 - .gitignore | 14 - .travis.yml | 15 - Cargo.toml | 164 ----- LICENSE | 18 - Makefile | 442 -------------- README.md | 183 ------ appveyor.yml | 33 - build.rs | 61 -- deps/Cargo.toml | 25 - mkmain.rs | 49 -- mkuutils.rs | 63 -- src/base64/Cargo.toml | 13 - src/base64/base64.rs | 162 ----- src/base64/deps.mk | 1 - src/basename/Cargo.toml | 12 - src/basename/basename.rs | 108 ---- src/cat/Cargo.toml | 12 - src/cat/cat.rs | 347 ----------- src/chmod/Cargo.toml | 17 - src/chmod/chmod.rs | 326 ---------- src/chmod/deps.mk | 1 - src/chroot/Cargo.toml | 12 - src/chroot/chroot.rs | 220 ------- src/cksum/Cargo.toml | 12 - src/cksum/cksum.rs | 131 ---- src/cksum/crc_table.rs | 3 - src/cksum/gen_table.rs | 41 -- src/comm/Cargo.toml | 12 - src/comm/comm.rs | 160 ----- src/common/c_types.rs | 240 -------- src/common/filesystem.rs | 147 ----- src/common/parse_time.rs | 35 -- src/common/process.rs | 140 ----- src/common/signals.rs | 158 ----- src/common/util.rs | 219 ------- src/common/utmpx.rs | 126 ---- src/common/wide.rs | 35 -- src/cp/Cargo.toml | 12 - src/cp/cp.rs | 161 ----- src/cut/Cargo.toml | 12 - src/cut/buffer.rs | 151 ----- src/cut/cut.rs | 546 ----------------- src/cut/ranges.rs | 133 ---- src/cut/searcher.rs | 54 -- src/dirname/Cargo.toml | 12 - src/dirname/dirname.rs | 70 --- src/du/Cargo.toml | 13 - src/du/deps.mk | 1 - src/du/du.rs | 398 ------------ src/echo/Cargo.toml | 12 - src/echo/echo.rs | 254 -------- src/env/Cargo.toml | 12 - src/env/env.rs | 207 ------- src/expand/Cargo.toml | 13 - src/expand/deps.mk | 1 - src/expand/expand.rs | 244 -------- src/expr/Cargo.toml | 13 - src/expr/expr.rs | 135 ----- src/expr/syntax_tree.rs | 386 ------------ src/expr/tokens.rs | 160 ----- src/factor/Cargo.toml | 13 - src/factor/deps.mk | 1 - src/factor/factor.rs | 202 ------- src/factor/gen_table.rs | 134 ---- src/factor/numeric.rs | 132 ---- src/factor/prime_table.rs | 532 ---------------- src/factor/sieve.rs | 212 ------- src/false/Cargo.toml | 12 - src/false/false.rs | 14 - src/fmt/Cargo.toml | 13 - src/fmt/deps.mk | 1 - src/fmt/fmt.rs | 221 ------- src/fmt/linebreak.rs | 452 -------------- src/fmt/parasplit.rs | 570 ------------------ src/fold/Cargo.toml | 12 - src/fold/fold.rs | 222 ------- src/groups/Cargo.toml | 12 - src/groups/groups.rs | 52 -- src/hashsum/Cargo.toml | 15 - src/hashsum/deps.mk | 1 - src/hashsum/hashsum.rs | 309 ---------- src/head/Cargo.toml | 12 - src/head/head.rs | 210 ------- src/hostid/Cargo.toml | 12 - src/hostid/hostid.rs | 90 --- src/hostname/Cargo.toml | 12 - src/hostname/hostname.rs | 176 ------ src/id/Cargo.toml | 12 - src/id/id.rs | 397 ------------ src/kill/Cargo.toml | 12 - src/kill/kill.rs | 194 ------ src/link/Cargo.toml | 12 - src/link/link.rs | 66 -- src/ln/Cargo.toml | 12 - src/ln/ln.rs | 333 ---------- src/logname/Cargo.toml | 12 - src/logname/logname.rs | 81 --- src/mkdir/Cargo.toml | 12 - src/mkdir/mkdir.rs | 160 ----- src/mkfifo/Cargo.toml | 12 - src/mkfifo/mkfifo.rs | 79 --- src/mv/Cargo.toml | 12 - src/mv/deps.mk | 1 - src/mv/mv.rs | 358 ----------- src/nice/Cargo.toml | 12 - src/nice/nice.rs | 112 ---- src/nl/Cargo.toml | 16 - src/nl/deps.mk | 1 - src/nl/helper.rs | 121 ---- src/nl/nl.rs | 330 ---------- src/nohup/Cargo.toml | 12 - src/nohup/nohup.rs | 149 ----- src/nproc/Cargo.toml | 13 - src/nproc/deps.mk | 1 - src/nproc/nproc.rs | 87 --- src/od/Cargo.toml | 12 - src/od/od.rs | 126 ---- src/paste/Cargo.toml | 12 - src/paste/paste.rs | 130 ---- src/printenv/Cargo.toml | 12 - src/printenv/printenv.rs | 78 --- src/ptx/Cargo.toml | 16 - src/ptx/deps.mk | 1 - src/ptx/ptx.rs | 564 ----------------- src/pwd/Cargo.toml | 12 - src/pwd/pwd.rs | 53 -- src/readlink/Cargo.toml | 12 - src/readlink/readlink.rs | 140 ----- src/realpath/Cargo.toml | 12 - src/realpath/realpath.rs | 142 ----- src/relpath/Cargo.toml | 12 - src/relpath/relpath.rs | 107 ---- src/rm/Cargo.toml | 12 - src/rm/rm.rs | 292 --------- src/rmdir/Cargo.toml | 12 - src/rmdir/rmdir.rs | 126 ---- src/seq/Cargo.toml | 12 - src/seq/seq.rs | 260 -------- src/shuf/Cargo.toml | 13 - src/shuf/deps.mk | 1 - src/shuf/shuf.rs | 269 --------- src/sleep/Cargo.toml | 12 - src/sleep/sleep.rs | 81 --- src/sort/Cargo.toml | 12 - src/sort/sort.rs | 210 ------- src/split/Cargo.toml | 12 - src/split/README.md | 9 - src/split/deps.mk | 1 - src/split/split.rs | 317 ---------- src/stdbuf/libstdbuf.c | 7 - src/stdbuf/libstdbuf.h | 6 - src/stdbuf/libstdbuf.rs | 57 -- src/stdbuf/stdbuf.rs | 272 --------- src/sum/Cargo.toml | 12 - src/sum/sum.rs | 140 ----- src/sync/Cargo.toml | 12 - src/sync/deps.mk | 1 - src/sync/sync.rs | 146 ----- src/tac/Cargo.toml | 12 - src/tac/tac.rs | 149 ----- src/tail/Cargo.toml | 12 - src/tail/README.md | 16 - src/tail/tail.rs | 300 --------- src/tee/Cargo.toml | 12 - src/tee/tee.rs | 174 ------ src/test/Cargo.toml | 12 - src/test/test.rs | 408 ------------- src/timeout/Cargo.toml | 13 - src/timeout/deps.mk | 1 - src/timeout/timeout.rs | 159 ----- src/touch/Cargo.toml | 14 - src/touch/deps.mk | 1 - src/touch/touch.rs | 211 ------- src/tr/Cargo.toml | 14 - src/tr/deps.mk | 1 - src/tr/expand.rs | 117 ---- src/tr/tr.rs | 164 ----- src/true/Cargo.toml | 12 - src/true/true.rs | 14 - src/truncate/Cargo.toml | 12 - src/truncate/truncate.rs | 215 ------- src/tsort/Cargo.toml | 12 - src/tsort/tsort.rs | 196 ------ src/tty/Cargo.toml | 12 - src/tty/tty.rs | 83 --- src/uname/Cargo.toml | 12 - src/uname/uname.rs | 108 ---- src/unexpand/Cargo.toml | 13 - src/unexpand/deps.mk | 1 - src/unexpand/unexpand.rs | 283 --------- src/uniq/Cargo.toml | 12 - src/uniq/uniq.rs | 242 -------- src/unlink/Cargo.toml | 12 - src/unlink/unlink.rs | 96 --- src/uptime/Cargo.toml | 13 - src/uptime/deps.mk | 1 - src/uptime/uptime.rs | 207 ------- src/users/Cargo.toml | 12 - src/users/users.rs | 122 ---- src/uutils/uutils.rs | 105 ---- src/uutils/uutils_cargo.rs | 99 --- src/wc/Cargo.toml | 12 - src/wc/wc.rs | 284 --------- src/whoami/Cargo.toml | 12 - src/whoami/deps.mk | 1 - src/whoami/platform/mod.rs | 20 - src/whoami/platform/unix.rs | 34 -- src/whoami/platform/windows.rs | 31 - src/whoami/whoami.rs | 65 -- src/yes/Cargo.toml | 12 - src/yes/yes.rs | 63 -- test/base64.rs | 62 -- test/basename.rs | 54 -- test/cat.rs | 60 -- test/cksum.rs | 39 -- test/common/util.rs | 152 ----- test/cp.rs | 35 -- test/cut.rs | 58 -- test/dirname.rs | 28 - test/echo.rs | 50 -- test/env.rs | 74 --- test/factor.rs | 534 ---------------- test/false.rs | 9 - test/fixtures/cat/256.txt | Bin 256 -> 0 bytes test/fixtures/cat/alpha.txt | 5 - test/fixtures/cksum/alice_in_wonderland.txt | 5 - test/fixtures/cksum/lorem_ipsum.txt | 13 - test/fixtures/cksum/multiple_files.expected | 2 - test/fixtures/cksum/single_file.expected | 1 - test/fixtures/cksum/stdin.expected | 1 - test/fixtures/cp/hello_world.txt | 1 - test/fixtures/cut/lists.txt | 4 - .../cut/lists_change_delimiter.expected | 4 - test/fixtures/cut/lists_char_range.expected | 4 - .../cut/lists_column_to_end_of_line.expected | 4 - .../cut/lists_multiple_fields.expected | 4 - test/fixtures/cut/lists_prefix.expected | 4 - .../cut/lists_specific_field.expected | 4 - test/fixtures/cut/lists_tail.expected | 4 - test/fixtures/fold/lorem_ipsum.txt | 1 - .../fold/lorem_ipsum_40_column_hard.expected | 20 - .../fold/lorem_ipsum_40_column_word.expected | 21 - .../fold/lorem_ipsum_80_column.expected | 10 - test/fixtures/hashsum/input.txt | 1 - test/fixtures/hashsum/md5.expected | 1 - test/fixtures/hashsum/sha1.expected | 1 - test/fixtures/hashsum/sha224.expected | 1 - test/fixtures/hashsum/sha256.expected | 1 - test/fixtures/hashsum/sha384.expected | 1 - test/fixtures/hashsum/sha512.expected | 1 - test/fixtures/head/lorem_ipsum.txt | 24 - .../fixtures/head/lorem_ipsum_1_line.expected | 1 - .../head/lorem_ipsum_5_chars.expected | 1 - .../head/lorem_ipsum_default.expected | 10 - .../head/lorem_ipsum_verbose.expected | 11 - test/fixtures/mv/hello_world.txt | 1 - test/fixtures/nl/joinblanklines.txt | 27 - test/fixtures/nl/section.txt | 18 - test/fixtures/nl/simple.txt | 15 - test/fixtures/paste/html_colors.expected | 16 - test/fixtures/paste/html_colors.txt | 32 - ...ext_disabled_ignore_and_only_file.expected | 2 - .../gnu_ext_disabled_roff_auto_ref.expected | 24 - .../gnu_ext_disabled_roff_input_ref.expected | 17 - .../ptx/gnu_ext_disabled_roff_no_ref.expected | 24 - .../gnu_ext_disabled_tex_auto_ref.expected | 24 - .../gnu_ext_disabled_tex_input_ref.expected | 17 - .../ptx/gnu_ext_disabled_tex_no_ref.expected | 24 - test/fixtures/ptx/ignore | 2 - test/fixtures/ptx/input | 7 - test/fixtures/ptx/only | 5 - test/fixtures/sort/human1.ans | 11 - test/fixtures/sort/human1.txt | 11 - test/fixtures/sort/numeric1.ans | 2 - test/fixtures/sort/numeric1.txt | 2 - test/fixtures/sort/numeric2.ans | 2 - test/fixtures/sort/numeric2.txt | 2 - test/fixtures/sort/numeric3.ans | 2 - test/fixtures/sort/numeric3.txt | 2 - test/fixtures/sort/numeric4.ans | 2 - test/fixtures/sort/numeric4.txt | 2 - test/fixtures/sort/numeric5.ans | 2 - test/fixtures/sort/numeric5.txt | 2 - test/fixtures/sort/numeric6.ans | 100 --- test/fixtures/sort/numeric6.txt | 100 --- test/fixtures/sum/alice_in_wonderland.txt | 5 - test/fixtures/sum/bsd_multiple_files.expected | 2 - test/fixtures/sum/bsd_single_file.expected | 1 - test/fixtures/sum/bsd_stdin.expected | 1 - test/fixtures/sum/lorem_ipsum.txt | 13 - .../fixtures/sum/sysv_multiple_files.expected | 2 - test/fixtures/sum/sysv_single_file.expected | 1 - test/fixtures/sum/sysv_stdin.expected | 1 - test/fixtures/tac/delimited_primes.expected | 1 - test/fixtures/tac/delimited_primes.txt | 1 - .../tac/delimited_primes_before.expected | 1 - test/fixtures/tac/prime_per_line.expected | 25 - test/fixtures/tac/prime_per_line.txt | 25 - test/fixtures/tsort/call_graph.expected | 17 - test/fixtures/tsort/call_graph.txt | 22 - test/fixtures/wc/alice_in_wonderland.txt | 5 - test/fixtures/wc/lorem_ipsum.txt | 13 - test/fixtures/wc/moby_dick.txt | 18 - test/fold.rs | 53 -- test/hashsum.rs | 47 -- test/head.rs | 72 --- test/link.rs | 49 -- test/ln.rs | 354 ----------- test/mkdir.rs | 58 -- test/mv.rs | 446 -------------- test/nl.rs | 53 -- test/paste.rs | 27 - test/ptx.rs | 58 -- test/pwd.rs | 16 - test/readlink.rs | 80 --- test/realpath.rs | 46 -- test/rm.rs | 140 ----- test/rmdir.rs | 114 ---- test/seq.rs | 32 - test/sort.rs | 65 -- test/split.rs | 160 ----- test/stdbuf.rs | 16 - test/sum.rs | 70 --- test/tac.rs | 50 -- test/test.rs | 37 -- test/touch.rs | 258 -------- test/tr.rs | 43 -- test/true.rs | 9 - test/truncate.rs | 41 -- test/tsort.rs | 21 - test/unexpand.rs | 115 ---- test/unlink.rs | 59 -- test/wc.rs | 57 -- 334 files changed, 25603 deletions(-) delete mode 100644 .busybox-config delete mode 100644 .gitignore delete mode 100644 .travis.yml delete mode 100644 Cargo.toml delete mode 100644 LICENSE delete mode 100644 Makefile delete mode 100644 README.md delete mode 100644 appveyor.yml delete mode 100644 build.rs delete mode 100644 deps/Cargo.toml delete mode 100644 mkmain.rs delete mode 100644 mkuutils.rs delete mode 100644 src/base64/Cargo.toml delete mode 100644 src/base64/base64.rs delete mode 100644 src/base64/deps.mk delete mode 100644 src/basename/Cargo.toml delete mode 100644 src/basename/basename.rs delete mode 100644 src/cat/Cargo.toml delete mode 100644 src/cat/cat.rs delete mode 100644 src/chmod/Cargo.toml delete mode 100644 src/chmod/chmod.rs delete mode 100644 src/chmod/deps.mk delete mode 100644 src/chroot/Cargo.toml delete mode 100644 src/chroot/chroot.rs delete mode 100644 src/cksum/Cargo.toml delete mode 100644 src/cksum/cksum.rs delete mode 100644 src/cksum/crc_table.rs delete mode 100644 src/cksum/gen_table.rs delete mode 100644 src/comm/Cargo.toml delete mode 100644 src/comm/comm.rs delete mode 100644 src/common/c_types.rs delete mode 100644 src/common/filesystem.rs delete mode 100644 src/common/parse_time.rs delete mode 100644 src/common/process.rs delete mode 100644 src/common/signals.rs delete mode 100644 src/common/util.rs delete mode 100644 src/common/utmpx.rs delete mode 100644 src/common/wide.rs delete mode 100644 src/cp/Cargo.toml delete mode 100644 src/cp/cp.rs delete mode 100644 src/cut/Cargo.toml delete mode 100644 src/cut/buffer.rs delete mode 100644 src/cut/cut.rs delete mode 100644 src/cut/ranges.rs delete mode 100644 src/cut/searcher.rs delete mode 100644 src/dirname/Cargo.toml delete mode 100644 src/dirname/dirname.rs delete mode 100644 src/du/Cargo.toml delete mode 100644 src/du/deps.mk delete mode 100644 src/du/du.rs delete mode 100644 src/echo/Cargo.toml delete mode 100644 src/echo/echo.rs delete mode 100644 src/env/Cargo.toml delete mode 100644 src/env/env.rs delete mode 100644 src/expand/Cargo.toml delete mode 100644 src/expand/deps.mk delete mode 100644 src/expand/expand.rs delete mode 100644 src/expr/Cargo.toml delete mode 100644 src/expr/expr.rs delete mode 100644 src/expr/syntax_tree.rs delete mode 100644 src/expr/tokens.rs delete mode 100644 src/factor/Cargo.toml delete mode 100644 src/factor/deps.mk delete mode 100644 src/factor/factor.rs delete mode 100644 src/factor/gen_table.rs delete mode 100644 src/factor/numeric.rs delete mode 100644 src/factor/prime_table.rs delete mode 100644 src/factor/sieve.rs delete mode 100644 src/false/Cargo.toml delete mode 100644 src/false/false.rs delete mode 100644 src/fmt/Cargo.toml delete mode 100644 src/fmt/deps.mk delete mode 100644 src/fmt/fmt.rs delete mode 100644 src/fmt/linebreak.rs delete mode 100644 src/fmt/parasplit.rs delete mode 100644 src/fold/Cargo.toml delete mode 100644 src/fold/fold.rs delete mode 100644 src/groups/Cargo.toml delete mode 100644 src/groups/groups.rs delete mode 100644 src/hashsum/Cargo.toml delete mode 100644 src/hashsum/deps.mk delete mode 100644 src/hashsum/hashsum.rs delete mode 100644 src/head/Cargo.toml delete mode 100644 src/head/head.rs delete mode 100644 src/hostid/Cargo.toml delete mode 100644 src/hostid/hostid.rs delete mode 100644 src/hostname/Cargo.toml delete mode 100644 src/hostname/hostname.rs delete mode 100644 src/id/Cargo.toml delete mode 100644 src/id/id.rs delete mode 100644 src/kill/Cargo.toml delete mode 100644 src/kill/kill.rs delete mode 100644 src/link/Cargo.toml delete mode 100644 src/link/link.rs delete mode 100644 src/ln/Cargo.toml delete mode 100644 src/ln/ln.rs delete mode 100644 src/logname/Cargo.toml delete mode 100644 src/logname/logname.rs delete mode 100644 src/mkdir/Cargo.toml delete mode 100644 src/mkdir/mkdir.rs delete mode 100644 src/mkfifo/Cargo.toml delete mode 100644 src/mkfifo/mkfifo.rs delete mode 100644 src/mv/Cargo.toml delete mode 100644 src/mv/deps.mk delete mode 100644 src/mv/mv.rs delete mode 100644 src/nice/Cargo.toml delete mode 100644 src/nice/nice.rs delete mode 100644 src/nl/Cargo.toml delete mode 100644 src/nl/deps.mk delete mode 100644 src/nl/helper.rs delete mode 100644 src/nl/nl.rs delete mode 100644 src/nohup/Cargo.toml delete mode 100644 src/nohup/nohup.rs delete mode 100644 src/nproc/Cargo.toml delete mode 100644 src/nproc/deps.mk delete mode 100644 src/nproc/nproc.rs delete mode 100644 src/od/Cargo.toml delete mode 100644 src/od/od.rs delete mode 100644 src/paste/Cargo.toml delete mode 100644 src/paste/paste.rs delete mode 100644 src/printenv/Cargo.toml delete mode 100644 src/printenv/printenv.rs delete mode 100644 src/ptx/Cargo.toml delete mode 100644 src/ptx/deps.mk delete mode 100644 src/ptx/ptx.rs delete mode 100644 src/pwd/Cargo.toml delete mode 100644 src/pwd/pwd.rs delete mode 100644 src/readlink/Cargo.toml delete mode 100644 src/readlink/readlink.rs delete mode 100644 src/realpath/Cargo.toml delete mode 100644 src/realpath/realpath.rs delete mode 100644 src/relpath/Cargo.toml delete mode 100644 src/relpath/relpath.rs delete mode 100644 src/rm/Cargo.toml delete mode 100644 src/rm/rm.rs delete mode 100644 src/rmdir/Cargo.toml delete mode 100644 src/rmdir/rmdir.rs delete mode 100644 src/seq/Cargo.toml delete mode 100644 src/seq/seq.rs delete mode 100644 src/shuf/Cargo.toml delete mode 100644 src/shuf/deps.mk delete mode 100644 src/shuf/shuf.rs delete mode 100644 src/sleep/Cargo.toml delete mode 100644 src/sleep/sleep.rs delete mode 100644 src/sort/Cargo.toml delete mode 100644 src/sort/sort.rs delete mode 100644 src/split/Cargo.toml delete mode 100644 src/split/README.md delete mode 100644 src/split/deps.mk delete mode 100644 src/split/split.rs delete mode 100644 src/stdbuf/libstdbuf.c delete mode 100644 src/stdbuf/libstdbuf.h delete mode 100644 src/stdbuf/libstdbuf.rs delete mode 100644 src/stdbuf/stdbuf.rs delete mode 100644 src/sum/Cargo.toml delete mode 100644 src/sum/sum.rs delete mode 100644 src/sync/Cargo.toml delete mode 100644 src/sync/deps.mk delete mode 100644 src/sync/sync.rs delete mode 100644 src/tac/Cargo.toml delete mode 100644 src/tac/tac.rs delete mode 100644 src/tail/Cargo.toml delete mode 100644 src/tail/README.md delete mode 100644 src/tail/tail.rs delete mode 100644 src/tee/Cargo.toml delete mode 100644 src/tee/tee.rs delete mode 100644 src/test/Cargo.toml delete mode 100644 src/test/test.rs delete mode 100644 src/timeout/Cargo.toml delete mode 100644 src/timeout/deps.mk delete mode 100644 src/timeout/timeout.rs delete mode 100644 src/touch/Cargo.toml delete mode 100644 src/touch/deps.mk delete mode 100644 src/touch/touch.rs delete mode 100644 src/tr/Cargo.toml delete mode 100644 src/tr/deps.mk delete mode 100644 src/tr/expand.rs delete mode 100644 src/tr/tr.rs delete mode 100644 src/true/Cargo.toml delete mode 100644 src/true/true.rs delete mode 100644 src/truncate/Cargo.toml delete mode 100644 src/truncate/truncate.rs delete mode 100644 src/tsort/Cargo.toml delete mode 100644 src/tsort/tsort.rs delete mode 100644 src/tty/Cargo.toml delete mode 100644 src/tty/tty.rs delete mode 100644 src/uname/Cargo.toml delete mode 100644 src/uname/uname.rs delete mode 100644 src/unexpand/Cargo.toml delete mode 100644 src/unexpand/deps.mk delete mode 100644 src/unexpand/unexpand.rs delete mode 100644 src/uniq/Cargo.toml delete mode 100644 src/uniq/uniq.rs delete mode 100644 src/unlink/Cargo.toml delete mode 100644 src/unlink/unlink.rs delete mode 100644 src/uptime/Cargo.toml delete mode 100644 src/uptime/deps.mk delete mode 100644 src/uptime/uptime.rs delete mode 100644 src/users/Cargo.toml delete mode 100644 src/users/users.rs delete mode 100644 src/uutils/uutils.rs delete mode 100644 src/uutils/uutils_cargo.rs delete mode 100644 src/wc/Cargo.toml delete mode 100644 src/wc/wc.rs delete mode 100644 src/whoami/Cargo.toml delete mode 100644 src/whoami/deps.mk delete mode 100644 src/whoami/platform/mod.rs delete mode 100644 src/whoami/platform/unix.rs delete mode 100644 src/whoami/platform/windows.rs delete mode 100644 src/whoami/whoami.rs delete mode 100644 src/yes/Cargo.toml delete mode 100644 src/yes/yes.rs delete mode 100644 test/base64.rs delete mode 100644 test/basename.rs delete mode 100644 test/cat.rs delete mode 100644 test/cksum.rs delete mode 100644 test/common/util.rs delete mode 100644 test/cp.rs delete mode 100644 test/cut.rs delete mode 100644 test/dirname.rs delete mode 100644 test/echo.rs delete mode 100644 test/env.rs delete mode 100644 test/factor.rs delete mode 100644 test/false.rs delete mode 100644 test/fixtures/cat/256.txt delete mode 100644 test/fixtures/cat/alpha.txt delete mode 100644 test/fixtures/cksum/alice_in_wonderland.txt delete mode 100644 test/fixtures/cksum/lorem_ipsum.txt delete mode 100644 test/fixtures/cksum/multiple_files.expected delete mode 100644 test/fixtures/cksum/single_file.expected delete mode 100644 test/fixtures/cksum/stdin.expected delete mode 100644 test/fixtures/cp/hello_world.txt delete mode 100644 test/fixtures/cut/lists.txt delete mode 100644 test/fixtures/cut/lists_change_delimiter.expected delete mode 100644 test/fixtures/cut/lists_char_range.expected delete mode 100644 test/fixtures/cut/lists_column_to_end_of_line.expected delete mode 100644 test/fixtures/cut/lists_multiple_fields.expected delete mode 100644 test/fixtures/cut/lists_prefix.expected delete mode 100644 test/fixtures/cut/lists_specific_field.expected delete mode 100644 test/fixtures/cut/lists_tail.expected delete mode 100644 test/fixtures/fold/lorem_ipsum.txt delete mode 100644 test/fixtures/fold/lorem_ipsum_40_column_hard.expected delete mode 100644 test/fixtures/fold/lorem_ipsum_40_column_word.expected delete mode 100644 test/fixtures/fold/lorem_ipsum_80_column.expected delete mode 100644 test/fixtures/hashsum/input.txt delete mode 100644 test/fixtures/hashsum/md5.expected delete mode 100644 test/fixtures/hashsum/sha1.expected delete mode 100644 test/fixtures/hashsum/sha224.expected delete mode 100644 test/fixtures/hashsum/sha256.expected delete mode 100644 test/fixtures/hashsum/sha384.expected delete mode 100644 test/fixtures/hashsum/sha512.expected delete mode 100644 test/fixtures/head/lorem_ipsum.txt delete mode 100644 test/fixtures/head/lorem_ipsum_1_line.expected delete mode 100644 test/fixtures/head/lorem_ipsum_5_chars.expected delete mode 100644 test/fixtures/head/lorem_ipsum_default.expected delete mode 100644 test/fixtures/head/lorem_ipsum_verbose.expected delete mode 100644 test/fixtures/mv/hello_world.txt delete mode 100644 test/fixtures/nl/joinblanklines.txt delete mode 100644 test/fixtures/nl/section.txt delete mode 100644 test/fixtures/nl/simple.txt delete mode 100644 test/fixtures/paste/html_colors.expected delete mode 100644 test/fixtures/paste/html_colors.txt delete mode 100644 test/fixtures/ptx/gnu_ext_disabled_ignore_and_only_file.expected delete mode 100644 test/fixtures/ptx/gnu_ext_disabled_roff_auto_ref.expected delete mode 100644 test/fixtures/ptx/gnu_ext_disabled_roff_input_ref.expected delete mode 100644 test/fixtures/ptx/gnu_ext_disabled_roff_no_ref.expected delete mode 100644 test/fixtures/ptx/gnu_ext_disabled_tex_auto_ref.expected delete mode 100644 test/fixtures/ptx/gnu_ext_disabled_tex_input_ref.expected delete mode 100644 test/fixtures/ptx/gnu_ext_disabled_tex_no_ref.expected delete mode 100644 test/fixtures/ptx/ignore delete mode 100644 test/fixtures/ptx/input delete mode 100644 test/fixtures/ptx/only delete mode 100644 test/fixtures/sort/human1.ans delete mode 100644 test/fixtures/sort/human1.txt delete mode 100644 test/fixtures/sort/numeric1.ans delete mode 100644 test/fixtures/sort/numeric1.txt delete mode 100644 test/fixtures/sort/numeric2.ans delete mode 100644 test/fixtures/sort/numeric2.txt delete mode 100644 test/fixtures/sort/numeric3.ans delete mode 100644 test/fixtures/sort/numeric3.txt delete mode 100644 test/fixtures/sort/numeric4.ans delete mode 100644 test/fixtures/sort/numeric4.txt delete mode 100644 test/fixtures/sort/numeric5.ans delete mode 100644 test/fixtures/sort/numeric5.txt delete mode 100644 test/fixtures/sort/numeric6.ans delete mode 100644 test/fixtures/sort/numeric6.txt delete mode 100644 test/fixtures/sum/alice_in_wonderland.txt delete mode 100644 test/fixtures/sum/bsd_multiple_files.expected delete mode 100644 test/fixtures/sum/bsd_single_file.expected delete mode 100644 test/fixtures/sum/bsd_stdin.expected delete mode 100644 test/fixtures/sum/lorem_ipsum.txt delete mode 100644 test/fixtures/sum/sysv_multiple_files.expected delete mode 100644 test/fixtures/sum/sysv_single_file.expected delete mode 100644 test/fixtures/sum/sysv_stdin.expected delete mode 100644 test/fixtures/tac/delimited_primes.expected delete mode 100644 test/fixtures/tac/delimited_primes.txt delete mode 100644 test/fixtures/tac/delimited_primes_before.expected delete mode 100644 test/fixtures/tac/prime_per_line.expected delete mode 100644 test/fixtures/tac/prime_per_line.txt delete mode 100644 test/fixtures/tsort/call_graph.expected delete mode 100644 test/fixtures/tsort/call_graph.txt delete mode 100644 test/fixtures/wc/alice_in_wonderland.txt delete mode 100644 test/fixtures/wc/lorem_ipsum.txt delete mode 100644 test/fixtures/wc/moby_dick.txt delete mode 100644 test/fold.rs delete mode 100644 test/hashsum.rs delete mode 100644 test/head.rs delete mode 100644 test/link.rs delete mode 100644 test/ln.rs delete mode 100644 test/mkdir.rs delete mode 100644 test/mv.rs delete mode 100644 test/nl.rs delete mode 100644 test/paste.rs delete mode 100644 test/ptx.rs delete mode 100644 test/pwd.rs delete mode 100644 test/readlink.rs delete mode 100644 test/realpath.rs delete mode 100644 test/rm.rs delete mode 100644 test/rmdir.rs delete mode 100644 test/seq.rs delete mode 100644 test/sort.rs delete mode 100644 test/split.rs delete mode 100644 test/stdbuf.rs delete mode 100644 test/sum.rs delete mode 100644 test/tac.rs delete mode 100644 test/test.rs delete mode 100644 test/touch.rs delete mode 100644 test/tr.rs delete mode 100644 test/true.rs delete mode 100644 test/truncate.rs delete mode 100644 test/tsort.rs delete mode 100644 test/unexpand.rs delete mode 100644 test/unlink.rs delete mode 100644 test/wc.rs diff --git a/.busybox-config b/.busybox-config deleted file mode 100644 index d1fb62794..000000000 --- a/.busybox-config +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_FEATURE_FANCY_HEAD=y -CONFIG_UNICODE_SUPPORT=y diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 65b62036a..000000000 --- a/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -/src/*/gen_table -/build/ -/target/ -/tmp/ -/busybox/ -/deps/regex/ -/deps/rust-crypto/ -/deps/target/ -/deps/time/ -*~ -.*.swp -.*.swo -Cargo.lock -lib*.a diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3bde18d3a..000000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: rust -rust: - - stable - - beta - - nightly -sudo: false -script: - - make - - make test - - make build-check - - make test-check -matrix: - allow_failures: - - rust: stable - - rust: beta diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index d976558a0..000000000 --- a/Cargo.toml +++ /dev/null @@ -1,164 +0,0 @@ -[package] -name = "uutils" -version = "0.0.1" -authors = [] -build = "build.rs" - -[features] -default = ["all"] -all = [ - "base64", - "basename", - "cat", - "chmod", - "chroot", - "cksum", - "comm", - "cp", - "cut", - "dirname", - "du", - "echo", - "env", - "expand", - "expr", - "factor", - "false", - "fmt", - "fold", - "groups", - "hashsum", - "head", - "hostid", - "hostname", - "id", - "kill", - "link", - "ln", - "logname", - "mkdir", - "mkfifo", - "mv", - "nice", - "nl", - "nohup", - "nproc", - "od", - "paste", - "printenv", - "ptx", - "pwd", - "readlink", - "realpath", - "relpath", - "rm", - "rmdir", - "seq", - "shuf", - "sleep", - "sort", - "split", - "sum", - "sync", - "tac", - "tail", - "tee", - "test", - "timeout", - "touch", - "tr", - "true", - "truncate", - "tsort", - "tty", - "uname", - "unexpand", - "uniq", - "unlink", - "uptime", - "users", - "wc", - "whoami", - "yes", -] - -[dependencies] -base64 = { optional=true, path="src/base64" } -basename = { optional=true, path="src/basename" } -cat = { optional=true, path="src/cat" } -chmod = { optional=true, path="src/chmod" } -chroot = { optional=true, path="src/chroot" } -cksum = { optional=true, path="src/cksum" } -comm = { optional=true, path="src/comm" } -cp = { optional=true, path="src/cp" } -cut = { optional=true, path="src/cut" } -dirname = { optional=true, path="src/dirname" } -du = { optional=true, path="src/du" } -echo = { optional=true, path="src/echo" } -env = { optional=true, path="src/env" } -expand = { optional=true, path="src/expand" } -expr = { optional=true, path="src/expr" } -factor = { optional=true, path="src/factor" } -false = { optional=true, path="src/false" } -fmt = { optional=true, path="src/fmt" } -fold = { optional=true, path="src/fold" } -groups = { optional=true, path="src/groups" } -hashsum = { optional=true, path="src/hashsum" } -head = { optional=true, path="src/head" } -hostid = { optional=true, path="src/hostid" } -hostname = { optional=true, path="src/hostname" } -id = { optional=true, path="src/id" } -kill = { optional=true, path="src/kill" } -link = { optional=true, path="src/link" } -ln = { optional=true, path="src/ln" } -logname = { optional=true, path="src/logname" } -mkdir = { optional=true, path="src/mkdir" } -mkfifo = { optional=true, path="src/mkfifo" } -mv = { optional=true, path="src/mv" } -nice = { optional=true, path="src/nice" } -nl = { optional=true, path="src/nl" } -nohup = { optional=true, path="src/nohup" } -nproc = { optional=true, path="src/nproc" } -od = { optional=true, path="src/od" } -paste = { optional=true, path="src/paste" } -printenv = { optional=true, path="src/printenv" } -ptx = { optional=true, path="src/ptx" } -pwd = { optional=true, path="src/pwd" } -readlink = { optional=true, path="src/readlink" } -realpath = { optional=true, path="src/realpath" } -relpath = { optional=true, path="src/relpath" } -rm = { optional=true, path="src/rm" } -rmdir = { optional=true, path="src/rmdir" } -seq = { optional=true, path="src/seq" } -shuf = { optional=true, path="src/shuf" } -sleep = { optional=true, path="src/sleep" } -sort = { optional=true, path="src/sort" } -split = { optional=true, path="src/split" } -sum = { optional=true, path="src/sum" } -sync = { optional=true, path="src/sync" } -tac = { optional=true, path="src/tac" } -tail = { optional=true, path="src/tail" } -tee = { optional=true, path="src/tee" } -test = { optional=true, path="src/test" } -timeout = { optional=true, path="src/timeout" } -touch = { optional=true, path="src/touch" } -tr = { optional=true, path="src/tr" } -true = { optional=true, path="src/true" } -truncate = { optional=true, path="src/truncate" } -tsort = { optional=true, path="src/tsort" } -tty = { optional=true, path="src/tty" } -uname = { optional=true, path="src/uname" } -unexpand = { optional=true, path="src/unexpand" } -uniq = { optional=true, path="src/uniq" } -unlink = { optional=true, path="src/unlink" } -uptime = { optional=true, path="src/uptime" } -users = { optional=true, path="src/users" } -wc = { optional=true, path="src/wc" } -whoami = { optional=true, path="src/whoami" } -yes = { optional=true, path="src/yes" } - - -[[bin]] -name="uutils" -path="src/uutils/uutils_cargo.rs" - diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 0177c4ab7..000000000 --- a/LICENSE +++ /dev/null @@ -1,18 +0,0 @@ -Copyright (c) Jordi Boggiano - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Makefile b/Makefile deleted file mode 100644 index c97bcd906..000000000 --- a/Makefile +++ /dev/null @@ -1,442 +0,0 @@ -# Config options -ENABLE_LTO ?= n -ENABLE_STRIP ?= n - -# Binaries -RUSTC ?= rustc -CARGO ?= cargo -CC ?= gcc -RM := rm - -# Install directories -PREFIX ?= /usr/local -BINDIR ?= /bin -LIBDIR ?= /lib - -# This won't support any directory with spaces in its name, but you can just -# make a symlink without spaces that points to the directory. -BASEDIR ?= $(shell pwd) -SRCDIR := $(BASEDIR)/src -BUILDDIR := $(BASEDIR)/build -TESTDIR := $(BASEDIR)/test -TEMPDIR := $(BASEDIR)/tmp - -# Flags -RUSTCFLAGS := -O -RMFLAGS := - -RUSTCLIBFLAGS := $(RUSTCFLAGS) -L $(BUILDDIR)/ -RUSTCTESTFLAGS := $(RUSTCFLAGS) - -# Handle config setup -ifeq ($(ENABLE_LTO),y) -RUSTCBINFLAGS := $(RUSTCLIBFLAGS) -C lto -else -RUSTCBINFLAGS := $(RUSTCLIBFLAGS) -endif - -ifneq ($(ENABLE_STRIP),y) -ENABLE_STRIP := -endif - -# Possible programs -PROGS := \ - base64 \ - basename \ - cat \ - chmod \ - cksum \ - comm \ - cp \ - cut \ - dirname \ - echo \ - env \ - expand \ - expr \ - factor \ - false \ - fmt \ - fold \ - link \ - hashsum \ - ln \ - mkdir \ - nl \ - nproc \ - od \ - paste \ - printenv \ - ptx \ - pwd \ - readlink \ - realpath \ - relpath \ - rm \ - rmdir \ - sleep \ - split \ - seq \ - shuf \ - sort \ - sum \ - sync \ - tac \ - tee \ - test \ - tr \ - true \ - truncate \ - tsort \ - unexpand \ - uniq \ - wc \ - yes \ - head \ - tail \ - whoami - -UNIX_PROGS := \ - chroot \ - du \ - groups \ - hostid \ - hostname \ - id \ - kill \ - logname \ - mkfifo \ - mv \ - nice \ - nohup \ - stdbuf \ - timeout \ - touch \ - tty \ - uname \ - unlink \ - uptime \ - users - -ifneq ($(OS),Windows_NT) - PROGS := $(PROGS) $(UNIX_PROGS) -endif - -ALIASES := \ - hashsum:md5sum \ - hashsum:sha1sum \ - hashsum:sha224sum \ - hashsum:sha256sum \ - hashsum:sha384sum \ - hashsum:sha512sum - -BUILD ?= $(PROGS) - -# Output names -EXES := \ - $(sort $(filter $(BUILD),$(filter-out $(DONT_BUILD),$(PROGS)))) - -CRATE_RLIBS := - -INSTALL ?= $(EXES) - -INSTALLEES := \ - $(filter $(INSTALL),$(filter-out $(DONT_INSTALL),$(EXES) uutils)) - -# Shared library extension -SYSTEM := $(shell uname) -DYLIB_EXT := -ifeq ($(SYSTEM),Linux) - DYLIB_EXT := so - DYLIB_FLAGS := -shared -endif -ifeq ($(SYSTEM),Darwin) - DYLIB_EXT := dylib - DYLIB_FLAGS := -dynamiclib -undefined dynamic_lookup -endif - -# Libaries to install -LIBS := -ifneq (,$(findstring stdbuf, $(INSTALLEES))) -LIBS += libstdbuf.$(DYLIB_EXT) -endif - -# Programs with usable tests -TEST_PROGS := \ - base64 \ - basename \ - cat \ - cksum \ - cp \ - cut \ - env \ - dirname \ - echo \ - factor \ - false \ - fold \ - hashsum \ - head \ - link \ - ln \ - mkdir \ - mv \ - nl \ - paste \ - ptx \ - pwd \ - readlink \ - realpath \ - rm \ - rmdir \ - seq \ - sort \ - split \ - stdbuf \ - sum \ - tac \ - test \ - touch \ - tr \ - true \ - truncate \ - tsort \ - unlink \ - unexpand \ - wc - -TEST ?= $(TEST_PROGS) - -TESTS := \ - $(filter $(TEST),$(filter-out $(DONT_TEST),$(filter $(BUILD),$(filter-out $(DONT_BUILD),$(TEST_PROGS))))) - -# figure out what dependencies we need based on which programs we're building -define DEP_INCLUDE --include $(SRCDIR)/$(1)/deps.mk -endef -# we always depend on libc because common/util does -# we also depend on getopts since all utilities support command-line arguments -DEPLIBS := libc getopts -DEPPLUGS := -# now, add in deps in src/utilname/deps.mk -# if we're testing, only consider the TESTS variable, -# otherwise consider the EXES variable -ifeq ($(MAKECMDGOALS),test) -$(foreach build,$(TESTS),$(eval $(call DEP_INCLUDE,$(build)))) -else -$(foreach build,$(sort $(TESTS) $(EXES)),$(eval $(call DEP_INCLUDE,$(build)))) -endif -# uniqify deps -DEPLIBS := $(sort $(DEPLIBS)) -DEPPLUGS := $(sort $(DEPPLUGS)) -# build --extern commandline for rustc -DEP_EXTERN := $(foreach lib,$(subst -,_,$(DEPLIBS)),--extern $(lib)=$(BUILDDIR)/lib$(lib).rlib) -DEP_EXTERN += $(foreach plug,$(subst -,_,$(DEPPLUGS)),--extern $(plug)=$(BUILDDIR)/lib$(plug).$(DYLIB_EXT)) - -# Setup for building crates -define BUILD_SETUP -X := $(shell $(RUSTC) --print file-names --crate-type rlib $(SRCDIR)/$(1)/$(1).rs) -$(1)_RLIB := $$(X) -CRATE_RLIBS += $$(X) -endef -$(foreach crate,$(EXES),$(eval $(call BUILD_SETUP,$(crate)))) - -# Utils stuff -EXES_PATHS := $(addprefix $(BUILDDIR)/,$(EXES)) -RLIB_PATHS := $(addprefix $(BUILDDIR)/,$(CRATE_RLIBS)) -command = sh -c '$(1)' -RESERVED_EXTERNS := --extern uufalse=$(BUILDDIR)/libfalse.rlib --extern uutrue=$(BUILDDIR)/libtrue.rlib --extern uutest=$(BUILDDIR)/libtest.rlib - -# Main exe build rule -define EXE_BUILD -$(BUILDDIR)/gen/$(1).rs: $(BUILDDIR)/mkmain - $(BUILDDIR)/mkmain $(1) $$@ - -$(BUILDDIR)/$(1): $(BUILDDIR)/gen/$(1).rs $(BUILDDIR)/$($(1)_RLIB) | $(BUILDDIR) deps - $(RUSTC) $(RUSTCBINFLAGS) $(RESERVED_EXTERNS) -o $$@ $$< - $(if $(ENABLE_STRIP),strip $$@,) -endef - -# GRRR rust-crypto makes a crate called "crypto". -# This should NOT be allowed by crates.io. GRRRR. -define DEP_BUILD -DEP_$(1): -ifeq ($(1),crypto) - cd $(BASEDIR)/deps && $(CARGO) build --package rust-crypto --release -else ifeq ($(1),kernel32) - cd $(BASEDIR)/deps && $(CARGO) build --package kernel32-sys --release -else ifeq ($(1),advapi32) - cd $(BASEDIR)/deps && $(CARGO) build --package advapi32-sys --release -else - cd $(BASEDIR)/deps && $(CARGO) build --package $(1) --release -endif -endef - -define CRATE_BUILD --include $(BUILDDIR)/$(1).d - -$(BUILDDIR)/$($(1)_RLIB): $(SRCDIR)/$(1)/$(1).rs | $(BUILDDIR) deps - $(RUSTC) $(RUSTCLIBFLAGS) $(DEP_EXTERN) --crate-type rlib --emit link,dep-info $$< --out-dir $(BUILDDIR) -endef - -# Aliases build rule -ALIAS_SOURCE = $(firstword $(subst :, ,$(1))) -ALIAS_TARGET = $(word 2,$(subst :, ,$(1))) -define MAKE_ALIAS - -ifneq ($(ALIAS_TARGET,$(1)),) -all: $(BUILDDIR)/$(call ALIAS_TARGET,$(1)) -$(BUILDDIR)/$(call ALIAS_TARGET,$(1)): $(BUILDDIR)/$(call ALIAS_SOURCE,$(1)) - $(call command,install $$@ $$<) -endif - -endef - -# Test exe built rules -define TEST_BUILD -test_$(1): $(BUILDDIR)/$(1) $(TEMPDIR)/$(1)/$(1)_test - $(call command,cp $(BUILDDIR)/$(1) $(TEMPDIR)/$(1) && cd $(TEMPDIR)/$(1) && $(TEMPDIR)/$(1)/$(1)_test) - -$(TEMPDIR)/$(1)/$(1)_test: $(TESTDIR)/$(1).rs | $(TEMPDIR)/$(1) - $(call command,$(RUSTC) $(RUSTCTESTFLAGS) $(DEP_EXTERN) --test -o $$@ $$<) - -$(TEMPDIR)/$(1): | $(TEMPDIR) - $(call command,cp -r $(TESTDIR)/fixtures/$(1) $$@ || mkdir $$@) -endef - -# Main rules -all: $(EXES_PATHS) $(BUILDDIR)/uutils - -# Creating necessary rules for each targets -$(foreach crate,$(EXES),$(eval $(call CRATE_BUILD,$(crate)))) -$(foreach exe,$(EXES),$(eval $(call EXE_BUILD,$(exe)))) -$(foreach alias,$(ALIASES),$(eval $(call MAKE_ALIAS,$(alias)))) -$(foreach test,$(TESTS),$(eval $(call TEST_BUILD,$(test)))) -$(foreach dep,$(sort $(DEPLIBS) $(DEPPLUGS)),$(eval $(call DEP_BUILD,$(dep)))) - --include $(BUILDDIR)/uutils.d -$(BUILDDIR)/uutils: $(SRCDIR)/uutils/uutils.rs $(BUILDDIR)/mkuutils $(RLIB_PATHS) - $(BUILDDIR)/mkuutils $(BUILDDIR)/gen/uutils.rs $(EXES) - $(RUSTC) $(RUSTCBINFLAGS) $(RESERVED_EXTERNS) --emit link,dep-info $(BUILDDIR)/gen/uutils.rs --out-dir $(BUILDDIR) - $(if $(ENABLE_STRIP),strip $@) - -# Library for stdbuf -$(BUILDDIR)/libstdbuf.$(DYLIB_EXT): $(SRCDIR)/stdbuf/libstdbuf.rs $(SRCDIR)/stdbuf/libstdbuf.c $(SRCDIR)/stdbuf/libstdbuf.h | $(BUILDDIR) - cd $(SRCDIR)/stdbuf && \ - $(RUSTC) libstdbuf.rs --extern libc=$(BUILDDIR)/liblibc.rlib && \ - $(CC) -c -Wall -Werror -fPIC libstdbuf.c && \ - $(CC) $(DYLIB_FLAGS) -o libstdbuf.$(DYLIB_EXT) liblibstdbuf.a libstdbuf.o && \ - mv *.$(DYLIB_EXT) $(BUILDDIR) && $(RM) *.o && $(RM) *.a - -$(BUILDDIR)/stdbuf: $(BUILDDIR)/libstdbuf.$(DYLIB_EXT) - -deps: $(BUILDDIR) $(SRCDIR)/cksum/crc_table.rs $(addprefix DEP_,$(DEPLIBS) $(DEPPLUGS)) - $(foreach lib,$(subst -,_,$(DEPLIBS)),$(shell cp $(BASEDIR)/deps/target/release/deps/lib$(lib)-*.rlib $(BUILDDIR)/lib$(lib).rlib)) - $(foreach plug,$(subst -,_,$(DEPPLUGS)),$(shell cp $(BASEDIR)/deps/target/release/deps/lib$(plug)-*.$(DYLIB_EXT) $(BUILDDIR)/lib$(plug).$(DYLIB_EXT))) - -$(BUILDDIR)/mkmain: mkmain.rs | $(BUILDDIR) - $(RUSTC) $(RUSTCFLAGS) $< -o $@ - -$(BUILDDIR)/mkuutils: mkuutils.rs | $(BUILDDIR) - $(RUSTC) $(RUSTCFLAGS) $< -o $@ - -$(SRCDIR)/cksum/crc_table.rs: $(SRCDIR)/cksum/gen_table.rs - cd $(SRCDIR)/cksum && $(RUSTC) $(RUSTCBINFLAGS) gen_table.rs && ./gen_table && $(RM) gen_table - -$(SRCDIR)/factor/prime_table.rs: $(SRCDIR)/factor/gen_table.rs - cd $(SRCDIR)/factor && $(RUSTC) $(RUSTCBINFLAGS) gen_table.rs && ./gen_table > $@ && $(RM) gen_table - -crates: - echo $(EXES) - -test: $(TEMPDIR) $(addprefix test_,$(TESTS)) - $(RM) -rf $(TEMPDIR) - -clean: - $(RM) -rf $(BUILDDIR) $(TEMPDIR) - -distclean: clean - cd $(BASEDIR)/deps && $(CARGO) clean && $(CARGO) update - -$(BUILDDIR): - mkdir -p $(BUILDDIR)/gen - -$(TEMPDIR): - $(RM) -rf $(TEMPDIR) - mkdir $(TEMPDIR) - -install: $(addprefix $(BUILDDIR)/,$(INSTALLEES)) - mkdir -p $(DESTDIR)$(PREFIX)$(BINDIR) - for prog in $(INSTALLEES); do \ - install $(BUILDDIR)/$$prog $(DESTDIR)$(PREFIX)$(BINDIR)/$(PROG_PREFIX)$$prog; \ - done - mkdir -p $(DESTDIR)$(PREFIX)$(LIBDIR) - for lib in $(LIBS); do \ - install $(BUILDDIR)/$$lib $(DESTDIR)$(PREFIX)$(LIBDIR)/$$lib; \ - done - -# TODO: figure out if there is way for prefixes to work with the symlinks -install-multicall: $(BUILDDIR)/uutils - mkdir -p $(DESTDIR)$(PREFIX)$(BINDIR) - install $(BUILDDIR)/uutils $(DESTDIR)$(PREFIX)$(BINDIR)/$(PROG_PREFIX)uutils - cd $(DESTDIR)$(PREFIX)$(BINDIR) - for prog in $(INSTALLEES); do \ - ln -s $(PROG_PREFIX)uutils $$prog; \ - done - mkdir -p $(DESTDIR)$(PREFIX)$(LIBDIR) - for lib in $(LIBS); do \ - install $(BUILDDIR)/$$lib $(DESTDIR)$(PREFIX)$(LIBDIR)/$$lib; \ - done - -uninstall: - rm -f $(addprefix $(DESTDIR)$(PREFIX)$(BINDIR)/$(PROG_PREFIX),$(PROGS)) - rm -f $(addprefix $(DESTDIR)$(PREFIX)$(LIBDIR)/,$(LIBS)) - -uninstall-multicall: - rm -f $(addprefix $(DESTDIR)$(PREFIX)$(BINDIR)/,$(PROGS) $(PROG_PREFIX)uutils) - rm -f $(addprefix $(DESTDIR)$(PREFIX)$(LIBDIR)/,$(LIBS)) - -# Test under the busybox testsuite -$(BUILDDIR)/busybox: $(BUILDDIR)/uutils - rm -f $(BUILDDIR)/busybox - ln -s $(BUILDDIR)/uutils $(BUILDDIR)/busybox - -# This is a busybox-specific config file their test suite wants to parse. -$(BUILDDIR)/.config: $(BASEDIR)/.busybox-config $(BUILDDIR)/uutils - cp $< $@ - -ifeq ($(BUSYBOX_SRC),) -busytest: - @echo - @echo "To run \`busytest\` set BUSYBOX_SRC to the directory of the compiled busybox source code." - @echo "Optionally set RUNTEST_ARGS to arguments to pass to the busybox \`runtest\` program." - @echo - @false -else -busytest: $(BUILDDIR)/busybox $(BUILDDIR)/.config - (cd $(BUSYBOX_SRC)/testsuite && bindir=$(BUILDDIR) ./runtest $(RUNTEST_ARGS)) -endif - -# This rule will build each program, ignore all output, and return pass -# or fail depending on whether the build has errors. -build-check: - @for prog in $(sort $(PROGS)); do \ - make BUILD="$$prog" >/dev/null 2>&1; status=$$?; \ - if [ $$status -eq 0 ]; \ - then printf "%-10s\t\033[1;32mpass\033[00;m\n" $$prog; \ - else printf "%-10s\t\033[1;31mfail\033[00;m\n" $$prog; \ - fi; \ - done - -# This rule will test each program, ignore all output, and return pass -# or fail depending on whether the test has errors. -test-check: - @for prog in $(sort $(TEST_PROGS)); do \ - make TEST="$$prog" test >/dev/null 2>&1; status=$$?; \ - if [ $$status -eq 0 ]; \ - then printf "%-10s\t\033[1;32mpass\033[00;m\n" $$prog; \ - else printf "%-10s\t\033[1;31mfail\033[00;m\n" $$prog; \ - fi; \ - done - -.PHONY: $(TEMPDIR) all deps test distclean clean busytest install uninstall diff --git a/README.md b/README.md deleted file mode 100644 index f3e9a9665..000000000 --- a/README.md +++ /dev/null @@ -1,183 +0,0 @@ -uutils coreutils -================ - -[![Build Status](https://api.travis-ci.org/uutils/coreutils.svg?branch=master)](https://travis-ci.org/uutils/coreutils) -[![Build status](https://ci.appveyor.com/api/projects/status/xhlsa439de5ogodp?svg=true)](https://ci.appveyor.com/project/jbcrail/coreutils-o0l0r) - -uutils is an attempt at writing universal (as in cross-platform) CLI -utils in [Rust](http://www.rust-lang.org). This repo is to aggregate the GNU -coreutils rewrites. - -Why? ----- - -Many GNU, Linux and other utils are pretty awesome, and obviously -[some](http://gnuwin32.sourceforge.net) [effort](http://unxutils.sourceforge.net) -has been spent in the past to port them to Windows. However, those projects -are either old, abandoned, hosted on CVS, written in platform-specific C, etc. - -Rust provides a good, platform-agnostic way of writing systems utils that are easy -to compile anywhere, and this is as good a way as any to try and learn it. - -Build Instructions ------------------- - -NOTE: This currently requires the most current nightly build. - -To simply build all available utilities: -``` -make -``` - -(on Windows use [MinGW/MSYS](http://www.mingw.org/wiki/MSYS) or `Cygwin` make and make sure you have `rustc` in `PATH`) - -To build all but a few of the available utilities: -``` -make DONT_BUILD='UTILITY_1 UTILITY_2' -``` - -To build only a few of the available utilities: -``` -make BUILD='UTILITY_1 UTILITY_2' -``` - -To build with LTO and stripping: -``` -make ENABLE_LTO=y ENABLE_STRIP=y -``` - -To check all available utilities for build errors: -``` -make build-check -``` - -To check all available tests for errors: -``` -make test-check -``` - -Installation Instructions -------------------------- - -To install all available utilities: -``` -make install -``` - -To install all but a few of the available utilities: -``` -make DONT_INSTALL='UTILITY_1 UTILITY_2' install -``` - -To install only a few of the available utilities: -``` -make INSTALL='UTILITY_1 UTILITY_2' install -``` - -To install every program with a prefix: -``` -make PROG_PREFIX=PREFIX_GOES_HERE install -``` - -To install the multicall binary: -``` -make install-multicall -``` - -Uninstallation Instructions ---------------------------- - -To uninstall all utilities: -``` -make uninstall -``` - -To uninstall every program with a set prefix: -``` -make PROG_PREFIX=PREFIX_GOES_HERE uninstall -``` - -To uninstall the multicall binary: -``` -make uninstall-multicall -``` - -Test Instructions ------------------ - -To simply test all available utilities: -``` -make test -``` - -To test all but a few of the available utilities: -``` -make DONT_TEST='UTILITY_1 UTILITY_2' test -``` - -To test only a few of the available utilities: -``` -make TEST='UTILITY_1 UTILITY_2' test -``` - -Contribute ----------- - -Contributions are very welcome, and should target Rust's master branch until -Rust 1.0 is released. You may *claim* an item on the to-do list by following -these steps: - -1. Open an issue named "Implement [the utility of your choice]", e.g. "Implement ls" -2. State that you are working on this utility. -3. Develop the utility. -4. Add the reference to your utility into uutils/uutils.rs (required for multibinary). -5. Remove utility from the to-do list on this README. -6. Submit a pull request and close the issue. - -The steps above imply that, before starting to work on a utility, you should search the issues to make sure no one else is working on it. - -To do ------ - -- chcon -- chgrp -- chmod (mostly done, just needs verbosity options) -- chown -- copy -- cp (not much done) -- csplit -- date -- dd -- df -- dircolors -- expr -- getlimits -- install -- join -- ls -- mknod -- mktemp -- mv (almost done, one more option) -- numfmt -- od (in progress, needs lots of work) -- pathchk -- pinky -- pr -- printf -- remove -- runcon -- setuidgid -- shred -- sort (a couple of options implemented) -- split (a couple of missing options) -- stat -- stty -- tail (not all features implemented) -- test (not all features implemented) -- uniq (a couple of missing options) -- who - -License -------- - -uutils is licensed under the MIT License - see the `LICENSE` file for details diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index b571c1390..000000000 --- a/appveyor.yml +++ /dev/null @@ -1,33 +0,0 @@ -platform: - - x64 - -environment: - global: - MSYS2_BASEVER: 20150512 - MSYS2_ARCH: x86_64 - MBASH: msys64\usr\bin\sh --login -c - - matrix: - - TARGET: i686-pc-windows-gnu - -install: - - appveyor DownloadFile "http://kent.dl.sourceforge.net/project/msys2/Base/%MSYS2_ARCH%/msys2-base-%MSYS2_ARCH%-%MSYS2_BASEVER%.tar.xz" -FileName "msys2.tar.xz" - - 7z x msys2.tar.xz - - 7z x msys2.tar > NUL - - call %MBASH% "" - - call %MBASH% "for i in {1..3}; do pacman --noconfirm -Suy mingw-w64-%MSYS2_ARCH%-{ragel,freetype,icu,gettext} libtool pkg-config gcc make autoconf automake perl && break || sleep 15; done" - - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" - - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - - call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" amd64 - - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin - - SET PATH=%PATH%;C:\MinGW\bin - - rustc -V - - cargo -V - -build_script: - - call %MBASH% "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; exec 0 continue, - "all" => continue, - _ => {}, - } - crates.push(krate.to_string()); - } - } - crates.sort(); - let mut cf = File::create(Path::new(&out_dir).join("uutils_crates.rs")).unwrap(); - let mut mf = File::create(Path::new(&out_dir).join("uutils_map.rs")).unwrap(); - mf.write_all(" - type UtilityMap = HashMap<&'static str, fn(Vec) -> i32>; - - fn util_map() -> UtilityMap { - let mut map: UtilityMap = HashMap::new();\n".as_bytes()).unwrap(); - for krate in crates { - match krate.as_ref() { - "false" => continue, - "true" => continue, - _ => cf.write_all(format!("extern crate {krate} as uu{krate};\n", krate=krate).as_bytes()).unwrap(), - } - - match krate.as_ref() { - "hashsum" => { - mf.write_all("map.insert(\"hashsum\", uuhashsum::uumain); - map.insert(\"md5sum\", uuhashsum::uumain); - map.insert(\"sha1sum\", uuhashsum::uumain); - map.insert(\"sha224sum\", uuhashsum::uumain); - map.insert(\"sha256sum\", uuhashsum::uumain); - map.insert(\"sha384sum\", uuhashsum::uumain); - map.insert(\"sha512sum\", uuhashsum::uumain);\n".as_bytes()).unwrap(); - }, - "false" => - mf.write_all("fn uufalse(_: Vec) -> i32 { 1 } - map.insert(\"false\", uufalse as fn(Vec) -> i32);\n".as_bytes()).unwrap(), - "true" => - mf.write_all("fn uutrue(_: Vec) -> i32 { 0 } - map.insert(\"true\", uutrue as fn(Vec) -> i32);\n".as_bytes()).unwrap(), - _ => - mf.write_all(format!("map.insert(\"{krate}\", uu{krate}::uumain as fn(Vec) -> i32);\n", krate= krate).as_bytes()).unwrap(), - } - } - mf.write_all("map - }\n".as_bytes()).unwrap(); - cf.flush().unwrap(); - mf.flush().unwrap(); -} diff --git a/deps/Cargo.toml b/deps/Cargo.toml deleted file mode 100644 index c03fa5fcb..000000000 --- a/deps/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[project] -name = "deps" -version = "0.0.0" - -[lib] -name = "null" - -[dependencies] -libc = "0.1" -getopts = "0.2" -bit-vec = "0.4" -bit-set = "0.2" -vec_map = "0.3" -num_cpus = "0.2" -rand = "0.3" -regex = "0.1" -rust-crypto = "0.2" -rustc-serialize = "0.3" -time = "0.1" -unicode-width = "0.1" -winapi = "0.2" -advapi32-sys = "0.1" -kernel32-sys = "0.1" -walker = "^1.0" -filetime = "0.1" diff --git a/mkmain.rs b/mkmain.rs deleted file mode 100644 index e825a1b41..000000000 --- a/mkmain.rs +++ /dev/null @@ -1,49 +0,0 @@ -use std::env; -use std::io::Write; -use std::fs::File; - -static TEMPLATE: &'static str = "\ -extern crate @UTIL_CRATE@ as uu@UTIL_CRATE@; - -use std::io::Write; -use uu@UTIL_CRATE@::uumain; - -fn main() { - let code = uumain(std::env::args().collect()); - - // Since stdout is line-buffered by default, we need to ensure any pending - // writes are flushed before exiting. Ideally, this should be enforced by - // each utility. - // - // See: https://github.com/rust-lang/rust/issues/23818 - // - std::io::stdout().flush().unwrap(); - - std::process::exit(code); -} -"; - -fn main() { - let args : Vec = env::args().collect(); - if args.len() != 3 { - println!("usage: mkbuild "); - std::process::exit(1); - } - - let crat = match &args[1][..] { - "false" => "uufalse", - "test" => "uutest", - "true" => "uutrue", - _ => &args[1][..], - }; - let outfile = &args[2][..]; - - let main = TEMPLATE.replace("@UTIL_CRATE@", crat); - match File::create(outfile) { - Ok(mut out) => match out.write_all(main.as_bytes()) { - Err(e) => panic!("{}", e), - _ => (), - }, - Err(e) => panic!("{}", e), - } -} diff --git a/mkuutils.rs b/mkuutils.rs deleted file mode 100644 index 772b68435..000000000 --- a/mkuutils.rs +++ /dev/null @@ -1,63 +0,0 @@ -use std::env; -use std::fs::File; -use std::io::{Read, Write}; - -fn main() { - let args : Vec = env::args().collect(); - if args.len() < 3 { - println!("usage: mkuutils "); - std::process::exit(1); - } - - let mut crates = String::new(); - let mut util_map = String::new(); - let mut hashsum = false; - for prog in args[2..].iter() { - match &prog[..] { - "hashsum" | "md5sum" | "sha1sum" | "sha224sum" | "sha256sum" | "sha384sum" | "sha512sum" => { - if !hashsum { - crates.push_str("extern crate hashsum;\n"); - util_map.push_str("map.insert(\"hashsum\", hashsum::uumain);\n"); - util_map.push_str("map.insert(\"md5sum\", hashsum::uumain);\n"); - util_map.push_str("map.insert(\"sha1sum\", hashsum::uumain);\n"); - util_map.push_str("map.insert(\"sha224sum\", hashsum::uumain);\n"); - util_map.push_str("map.insert(\"sha256sum\", hashsum::uumain);\n"); - util_map.push_str("map.insert(\"sha384sum\", hashsum::uumain);\n"); - util_map.push_str("map.insert(\"sha512sum\", hashsum::uumain);\n"); - hashsum = true; - } - }, - "true" => { - util_map.push_str("fn uutrue(_: Vec) -> i32 { 0 }\n"); - util_map.push_str("map.insert(\"true\", uutrue as fn(Vec) -> i32);\n"); - }, - "false" => { - util_map.push_str("fn uufalse(_: Vec) -> i32 { 1 }\n"); - util_map.push_str("map.insert(\"false\", uufalse as fn(Vec) -> i32);\n"); - }, - _ => { - if prog == "test" { - crates.push_str(&(format!("extern crate uu{0} as uu{0};\n", prog))[..]); - } else { - crates.push_str(&(format!("extern crate {0} as uu{0};\n", prog))[..]); - } - util_map.push_str(&(format!("map.insert(\"{prog}\", uu{prog}::uumain as fn(Vec) -> i32);\n", prog = prog))[..]); - } - } - } - let outfile = &(args[1])[..]; - - // XXX: this all just assumes that the IO works correctly - let mut out = File::create(outfile).unwrap(); - let mut input = File::open("src/uutils/uutils.rs").unwrap(); - - let mut template = String::new(); - input.read_to_string(&mut template).unwrap(); - let template = template; - - let main = template.replace("@CRATES@", &crates[..]).replace("@UTIL_MAP@", &util_map[..]); - match out.write_all(main.as_bytes()) { - Err(e) => panic!("{}", e), - _ => (), - } -} diff --git a/src/base64/Cargo.toml b/src/base64/Cargo.toml deleted file mode 100644 index 6e0c8ec1f..000000000 --- a/src/base64/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "base64" -version = "0.0.1" -authors = [] - -[lib] -name = "base64" -path = "base64.rs" - -[dependencies] -getopts = "*" -libc = "*" -rustc-serialize = "*" diff --git a/src/base64/base64.rs b/src/base64/base64.rs deleted file mode 100644 index 3ea79a7c3..000000000 --- a/src/base64/base64.rs +++ /dev/null @@ -1,162 +0,0 @@ -#![crate_name = "base64"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Jordy Dickinson - * - * For the full copyright and license information, please view the LICENSE file - * that was distributed with this source code. - */ - -extern crate rustc_serialize as serialize; -extern crate getopts; -extern crate libc; - -use getopts::Options; -use serialize::base64::{self, FromBase64, ToBase64}; -use std::ascii::AsciiExt; -use std::error::Error; -use std::fs::File; -use std::io::{BufReader, Read, stdin, stdout, Write}; -use std::path::Path; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -enum Mode { - Decode, - Encode, - Help, - Version -} - -static NAME: &'static str = "base64"; -static VERSION: &'static str = "1.0.0"; - -pub type FileOrStdReader = BufReader>; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - opts.optflag("d", "decode", "decode data"); - opts.optflag("i", "ignore-garbage", "when decoding, ignore non-alphabetic characters"); - opts.optopt("w", "wrap", "wrap encoded lines after COLS character (default 76, 0 to disable wrapping)", "COLS"); - opts.optflag("h", "help", "display this help text and exit"); - opts.optflag("V", "version", "output version information and exit"); - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(e) => { crash!(1, "{}", e) } - }; - - let mode = if matches.opt_present("help") { - Mode::Help - } else if matches.opt_present("version") { - Mode::Version - } else if matches.opt_present("decode") { - Mode::Decode - } else { - Mode::Encode - }; - let ignore_garbage = matches.opt_present("ignore-garbage"); - let line_wrap = match matches.opt_str("wrap") { - Some(s) => match s.parse() { - Ok(s) => s, - Err(e)=> { - crash!(1, "Argument to option 'wrap' improperly formatted: {}", e); - } - }, - None => 76 - }; - let stdin_buf; - let file_buf; - let mut input = if matches.free.is_empty() || &matches.free[0][..] == "-" { - stdin_buf = stdin(); - BufReader::new(Box::new(stdin_buf) as Box) - } else { - let path = Path::new(&matches.free[0][..]); - file_buf = safe_unwrap!(File::open(&path)); - BufReader::new(Box::new(file_buf) as Box) - }; - - match mode { - Mode::Decode => decode(&mut input, ignore_garbage), - Mode::Encode => encode(&mut input, line_wrap), - Mode::Help => help(opts), - Mode::Version => version() - } - - 0 -} - -fn decode(input: &mut FileOrStdReader, ignore_garbage: bool) { - let mut to_decode = String::new(); - input.read_to_string(&mut to_decode).unwrap(); - - if ignore_garbage { - let mut clean = String::new(); - clean.extend(to_decode.chars().filter(|&c| { - if !c.is_ascii() { - false - } else { - c >= 'a' && c <= 'z' || - c >= 'A' && c <= 'Z' || - c >= '0' && c <= '9' || - c == '+' || c == '/' - } - })); - to_decode = clean; - } - - match to_decode[..].from_base64() { - Ok(bytes) => { - let mut out = stdout(); - - match out.write_all(&bytes[..]) { - Ok(_) => {} - Err(f) => { crash!(1, "{}", f); } - } - match out.flush() { - Ok(_) => {} - Err(f) => { crash!(1, "{}", f); } - } - } - Err(s) => { - crash!(1, "{} ({:?})", s.description(), s); - } - } -} - -fn encode(input: &mut FileOrStdReader, line_wrap: usize) { - let b64_conf = base64::Config { - char_set: base64::Standard, - newline: base64::Newline::LF, - pad: true, - line_length: match line_wrap { - 0 => None, - _ => Some(line_wrap) - } - }; - let mut to_encode: Vec = vec!(); - input.read_to_end(&mut to_encode).unwrap(); - let encoded = to_encode.to_base64(b64_conf); - - println!("{}", &encoded[..]); -} - -fn help(opts: Options) { - let msg = format!("Usage: {} [OPTION]... [FILE]\n\n\ - Base64 encode or decode FILE, or standard input, to standard output.\n\ - With no FILE, or when FILE is -, read standard input.\n\n\ - The data are encoded as described for the base64 alphabet in RFC \ - 3548. When\ndecoding, the input may contain newlines in addition \ - to the bytes of the formal\nbase64 alphabet. Use --ignore-garbage \ - to attempt to recover from any other\nnon-alphabet bytes in the \ - encoded stream.", NAME); - - print!("{}", opts.usage(&msg)); -} - -fn version() { - println!("{} {}", NAME, VERSION); -} diff --git a/src/base64/deps.mk b/src/base64/deps.mk deleted file mode 100644 index 5f486e20e..000000000 --- a/src/base64/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += rustc-serialize diff --git a/src/basename/Cargo.toml b/src/basename/Cargo.toml deleted file mode 100644 index ade2a3236..000000000 --- a/src/basename/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "basename" -version = "0.0.1" -authors = [] - -[lib] -name = "basename" -path = "basename.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/basename/basename.rs b/src/basename/basename.rs deleted file mode 100644 index 95736067d..000000000 --- a/src/basename/basename.rs +++ /dev/null @@ -1,108 +0,0 @@ -#![crate_name = "basename"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Jimmy Lu - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use getopts::Options; -use std::io::Write; -use std::path::{is_separator, PathBuf}; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "basename"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - // - // Argument parsing - // - let mut opts = Options::new(); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "Invalid options\n{}", f) - }; - - if matches.opt_present("help") { - let msg = format!("Usage: {0} NAME [SUFFIX]\n or: {0} OPTION\n\n\ - Print NAME with any leading directory components removed.\n\ - If specified, also remove a trailing SUFFIX.", NAME); - - print!("{}", opts.usage(&msg)); - - return 0; - } - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - // too few arguments - if args.len() < 2 { - println!("{}: {}", NAME, "missing operand"); - println!("Try '{} --help' for more information.", NAME); - return 1; - } - // too many arguments - else if args.len() > 3 { - println!("{}: extra operand '{}'", NAME, args[3]); - println!("Try '{} --help' for more information.", NAME); - return 1; - } - - // - // Main Program Processing - // - - let mut name = strip_dir(&args[1]); - - if args.len() > 2 { - let suffix = args[2].clone(); - name = strip_suffix(name.as_ref(), suffix.as_ref()); - } - - println!("{}", name); - - 0 -} - -fn strip_dir(fullname: &str) -> String { - // Remove all platform-specific path separators from the end - let mut path: String = fullname.chars().rev().skip_while(|&ch| is_separator(ch)).collect(); - - // Undo reverse - path = path.chars().rev().collect(); - - // Convert to path buffer and get last path component - let pb = PathBuf::from(path); - match pb.components().last() { - Some(c) => c.as_os_str().to_str().unwrap().to_string(), - None => "".to_string() - } -} - -fn strip_suffix(name: &str, suffix: &str) -> String { - if name == suffix { - return name.to_string(); - } - - if name.ends_with(suffix) { - return name[..name.len() - suffix.len()].to_string(); - } - - name.to_string() -} diff --git a/src/cat/Cargo.toml b/src/cat/Cargo.toml deleted file mode 100644 index 36066a55f..000000000 --- a/src/cat/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "cat" -version = "0.0.1" -authors = [] - -[lib] -name = "cat" -path = "cat.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/cat/cat.rs b/src/cat/cat.rs deleted file mode 100644 index 61629734e..000000000 --- a/src/cat/cat.rs +++ /dev/null @@ -1,347 +0,0 @@ -#![crate_name = "cat"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/* last synced with: cat (GNU coreutils) 8.13 */ - -extern crate getopts; -extern crate libc; - -use getopts::Options; -use std::fs::File; -use std::intrinsics::{copy_nonoverlapping}; -use std::io::{stdout, stdin, stderr, Write, Read, Result}; -use libc::consts::os::posix88::STDIN_FILENO; -use libc::funcs::posix88::unistd::isatty; -use libc::types::os::arch::c95::c_int; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "cat"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - opts.optflag("A", "show-all", "equivalent to -vET"); - opts.optflag("b", "number-nonblank", - "number nonempty output lines, overrides -n"); - opts.optflag("e", "", "equivalent to -vE"); - opts.optflag("E", "show-ends", "display $ at end of each line"); - opts.optflag("n", "number", "number all output lines"); - opts.optflag("s", "squeeze-blank", "suppress repeated empty output lines"); - opts.optflag("t", "", "equivalent to -vT"); - opts.optflag("T", "show-tabs", "display TAB characters as ^I"); - opts.optflag("v", "show-nonprinting", - "use ^ and M- notation, except for LF (\\n) and TAB (\\t)"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => panic!("Invalid options\n{}", f) - }; - if matches.opt_present("help") { - let msg = format!("{} {}\n\n\ - Usage:\n {0} [OPTION]... [FILE]...\n\n\ - Concatenate FILE(s), or standard input, to standard output.\n\n\ - With no FILE, or when FILE is -, read standard input.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - return 0; - } - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - let number_mode = if matches.opt_present("b") { - NumberingMode::NumberNonEmpty - } else if matches.opt_present("n") { - NumberingMode::NumberAll - } else { - NumberingMode::NumberNone - }; - let show_nonprint = matches.opts_present(&["A".to_string(), "e".to_string(), - "t".to_string(), "v".to_string()]); - let show_ends = matches.opts_present(&["E".to_string(), "A".to_string(), - "e".to_string()]); - let show_tabs = matches.opts_present(&["A".to_string(), "T".to_string(), - "t".to_string()]); - let squeeze_blank = matches.opt_present("s"); - let mut files = matches.free; - if files.is_empty() { - files.push("-".to_string()); - } - - exec(files, number_mode, show_nonprint, show_ends, show_tabs, squeeze_blank); - - 0 -} - -#[derive(Eq, PartialEq)] -enum NumberingMode { - NumberNone, - NumberNonEmpty, - NumberAll, -} - -fn write_lines(files: Vec, number: NumberingMode, squeeze_blank: bool, - show_ends: bool) { - - let mut line_counter: usize = 1; - - for (mut reader, interactive) in files.iter().filter_map(|p| open(&p[..])) { - - let mut in_buf = [0; 1024 * 31]; - let mut out_buf = [0; 1024 * 64]; - let mut writer = UnsafeWriter::new(&mut out_buf[..], stdout()); - let mut at_line_start = true; - while let Ok(n) = reader.read(&mut in_buf) { - if n == 0 { break } - - let in_buf = &in_buf[..n]; - let mut buf_pos = 0..n; - loop { - writer.possibly_flush(); - let pos = match buf_pos.next() { - Some(p) => p, - None => break, - }; - if in_buf[pos] == '\n' as u8 { - if !at_line_start || !squeeze_blank { - if at_line_start && number == NumberingMode::NumberAll { - (write!(&mut writer, "{0:6}\t", line_counter)).unwrap(); - line_counter += 1; - } - if show_ends { - writer.write_all(&['$' as u8]).unwrap(); - } - writer.write_all(&['\n' as u8]).unwrap(); - if interactive { - writer.flush().unwrap(); - } - } - at_line_start = true; - continue; - } - if at_line_start && number != NumberingMode::NumberNone { - (write!(&mut writer, "{0:6}\t", line_counter)).unwrap(); - line_counter += 1; - } - match in_buf[pos..].iter().position(|c| *c == '\n' as u8) { - Some(p) => { - writer.write_all(&in_buf[pos..pos + p]).unwrap(); - if show_ends { - writer.write_all(&['$' as u8]).unwrap(); - } - writer.write_all(&['\n' as u8]).unwrap(); - if interactive { - writer.flush().unwrap(); - } - buf_pos = pos + p + 1..n; - at_line_start = true; - }, - None => { - writer.write_all(&in_buf[pos..]).unwrap(); - at_line_start = false; - break; - } - }; - } - } - } -} - -fn write_bytes(files: Vec, number: NumberingMode, squeeze_blank: bool, - show_ends: bool, show_nonprint: bool, show_tabs: bool) { - - let mut line_counter: usize = 1; - - for (mut reader, interactive) in files.iter().filter_map(|p| open(&p[..])) { - - // Flush all 1024 iterations. - let mut flush_counter = 0usize..1024; - - let mut in_buf = [0; 1024 * 32]; - let mut out_buf = [0; 1024 * 64]; - let mut writer = UnsafeWriter::new(&mut out_buf[..], stdout()); - let mut at_line_start = true; - while let Ok(n) = reader.read(&mut in_buf) { - if n == 0 { break } - - for &byte in in_buf[..n].iter() { - if flush_counter.next().is_none() { - writer.possibly_flush(); - flush_counter = 0usize..1024; - } - if byte == '\n' as u8 { - if !at_line_start || !squeeze_blank { - if at_line_start && number == NumberingMode::NumberAll { - (write!(&mut writer, "{0:6}\t", line_counter)).unwrap(); - line_counter += 1; - } - if show_ends { - writer.write_all(&['$' as u8]).unwrap(); - } - writer.write_all(&['\n' as u8]).unwrap(); - if interactive { - writer.flush().unwrap(); - } - } - at_line_start = true; - continue; - } - if at_line_start && number != NumberingMode::NumberNone { - (write!(&mut writer, "{0:6}\t", line_counter)).unwrap(); - line_counter += 1; - at_line_start = false; - } - // This code is slow because of the many branches. cat in glibc avoids - // this by having the whole loop inside show_nonprint. - if byte == '\t' as u8 { - if show_tabs { - writer.write_all("^I".as_bytes()) - } else { - writer.write_all(&[byte]) - } - } else if show_nonprint { - let byte = match byte { - 128 ... 255 => { - writer.write_all("M-".as_bytes()).unwrap(); - byte - 128 - }, - _ => byte, - }; - match byte { - 0 ... 31 => writer.write_all(&['^' as u8, byte + 64]), - 127 => writer.write_all(&['^' as u8, byte - 64]), - _ => writer.write_all(&[byte]), - } - } else { - writer.write_all(&[byte]) - }.unwrap(); - } - } - } -} - -fn write_fast(files: Vec) { - let mut writer = stdout(); - let mut in_buf = [0; 1024 * 64]; - - for (mut reader, _) in files.iter().filter_map(|p| open(&p[..])) { - while let Ok(n) = reader.read(&mut in_buf) { - if n == 0 { break } - // This interface is completely broken. - writer.write_all(&in_buf[..n]).unwrap(); - } - } -} - -fn exec(files: Vec, number: NumberingMode, show_nonprint: bool, - show_ends: bool, show_tabs: bool, squeeze_blank: bool) { - - if show_nonprint || show_tabs { - write_bytes(files, number, squeeze_blank, show_ends, show_nonprint, show_tabs); - } else if number != NumberingMode::NumberNone || squeeze_blank || show_ends { - write_lines(files, number, squeeze_blank, show_ends); - } else { - write_fast(files); - } - pipe_flush!(); -} - -fn open(path: &str) -> Option<(Box, bool)> { - if path == "-" { - let stdin = stdin(); - let interactive = unsafe { isatty(STDIN_FILENO) } != 0 as c_int; - return Some((Box::new(stdin) as Box, interactive)); - } - - match File::open(path) { - Ok(f) => Some((Box::new(f) as Box, false)), - Err(e) => { - (writeln!(&mut stderr(), "cat: {0}: {1}", path, e.to_string())).unwrap(); - None - }, - } -} - -struct UnsafeWriter<'a, W: Write> { - inner: W, - buf: &'a mut [u8], - pos: usize, - threshold: usize, -} - -impl<'a, W: Write> UnsafeWriter<'a, W> { - fn new(buf: &'a mut [u8], inner: W) -> UnsafeWriter<'a, W> { - let threshold = buf.len()/2; - UnsafeWriter { - inner: inner, - buf: buf, - pos: 0, - threshold: threshold, - } - } - - fn flush_buf(&mut self) -> Result<()> { - if self.pos != 0 { - let ret = self.inner.write(&self.buf[..self.pos]); - self.pos = 0; - match ret { - Ok(_) => Ok(()), - Err(e) => Err(e), - } - } else { - Ok(()) - } - } - - fn possibly_flush(&mut self) { - if self.pos > self.threshold { - self.inner.write_all(&self.buf[..self.pos]).unwrap(); - self.pos = 0; - } - } -} - -#[inline(never)] -fn fail() -> ! { - panic!("assertion failed"); -} - -impl<'a, W: Write> Write for UnsafeWriter<'a, W> { - fn write(&mut self, buf: &[u8]) -> Result { - let dst = &mut self.buf[self.pos..]; - let len = buf.len(); - if len > dst.len() { - fail(); - } - unsafe { - copy_nonoverlapping(buf.as_ptr(), dst.as_mut_ptr(), len) - } - self.pos += len; - Ok(len) - } - - fn flush(&mut self) -> Result<()> { - self.flush_buf().and_then(|()| self.inner.flush()) - } -} - -impl<'a, W: Write> Drop for UnsafeWriter<'a, W> { - fn drop(&mut self) { - let _ = self.flush_buf(); - } -} - -/* vim: set ai ts=4 sw=4 sts=4 et : */ diff --git a/src/chmod/Cargo.toml b/src/chmod/Cargo.toml deleted file mode 100644 index 5d1508101..000000000 --- a/src/chmod/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "chmod" -version = "0.0.1" -authors = [] - -[lib] -name = "chmod" -path = "chmod.rs" - -[dependencies] -getopts = "*" -libc = "*" -aho-corasick = "*" -memchr = "*" -regex = "*" -regex-syntax = "*" -walker = "*" diff --git a/src/chmod/chmod.rs b/src/chmod/chmod.rs deleted file mode 100644 index 958e56390..000000000 --- a/src/chmod/chmod.rs +++ /dev/null @@ -1,326 +0,0 @@ -#![crate_name = "chmod"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Arcterus - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -#![allow(unused_variables)] // only necessary while the TODOs still exist - -extern crate aho_corasick; -extern crate getopts; -extern crate libc; -extern crate memchr; -extern crate regex; -extern crate regex_syntax; -extern crate walker; - -use getopts::Options; -use regex::Regex; -use std::ffi::CString; -use std::io::{Error, Write}; -use std::mem; -use std::path::Path; -use walker::Walker; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[path = "../common/filesystem.rs"] -mod filesystem; - -use filesystem::UUPathExt; - -const NAME: &'static str = "chmod"; -const VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - opts.optflag("c", "changes", "like verbose but report only when a change is made (unimplemented)"); - opts.optflag("f", "quiet", "suppress most error messages (unimplemented)"); // TODO: support --silent - opts.optflag("v", "verbose", "output a diagnostic for every file processed (unimplemented)"); - opts.optflag("", "no-preserve-root", "do not treat '/' specially (the default)"); - opts.optflag("", "preserve-root", "fail to operate recursively on '/'"); - opts.optflagopt("", "reference", "use RFILE's mode instead of MODE values", "RFILE"); - opts.optflag("R", "recursive", "change files and directories recursively"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - // TODO: sanitize input for - at beginning (e.g. chmod -x testfile). Solution is to add a to -x, making a-x - let mut matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { crash!(1, "{}", f) } - }; - if matches.opt_present("help") { - let msg = format!("{name} {version} - -Usage: - {program} [OPTION]... MODE[,MODE]... FILE... - {program} [OPTION]... OCTAL-MODE FILE... - {program} [OPTION]... --reference=RFILE FILE... - -Change the mode of each FILE to MODE. -With --reference, change the mode of each FILE to that of RFILE. -Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'.", - name = NAME, version = VERSION, program = NAME); - - print!("{}", opts.usage(&msg)); - return 0; - } else if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - } else if matches.free.is_empty() && matches.opt_present("reference") || matches.free.len() < 2 { - show_error!("missing an argument"); - show_error!("for help, try '{} --help'", NAME); - return 1; - } else { - let changes = matches.opt_present("changes"); - let quiet = matches.opt_present("quiet"); - let verbose = matches.opt_present("verbose"); - let preserve_root = matches.opt_present("preserve-root"); - let recursive = matches.opt_present("recursive"); - let fmode = matches.opt_str("reference").and_then(|fref| { - let mut stat : libc::stat = unsafe { mem::uninitialized() }; - let statres = unsafe { libc::stat(fref.as_ptr() as *const i8, &mut stat as *mut libc::stat) }; - if statres == 0 { - Some(stat.st_mode) - } else { - crash!(1, "{}", Error::last_os_error()) - } - }); - let cmode = - if fmode.is_none() { - let mode = matches.free.remove(0); - match verify_mode(&mode[..]) { - Ok(_) => Some(mode), - Err(f) => { - show_error!("{}", f); - return 1; - } - } - } else { - None - }; - match chmod(matches.free, changes, quiet, verbose, preserve_root, - recursive, fmode, cmode.as_ref()) { - Ok(()) => {} - Err(e) => return e - } - } - - 0 -} - -#[cfg(unix)] -#[inline] -fn verify_mode(modes: &str) -> Result<(), String> { - let re: regex::Regex = Regex::new(r"^[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+$").unwrap(); - for mode in modes.split(',') { - if !re.is_match(mode) { - return Err(format!("invalid mode '{}'", mode)); - } - } - Ok(()) -} - -#[cfg(windows)] -#[inline] -// XXX: THIS IS NOT TESTED!!! -fn verify_mode(modes: &str) -> Result<(), String> { - let re: regex::Regex = Regex::new(r"^[ugoa]*(?:[-+=](?:([rwxXst]*)|[ugo]))+|[-+=]?([0-7]+)$").unwrap(); - for mode in modes.split(',') { - match re.captures(mode) { - Some(cap) => { - let symbols = cap.at(1).unwrap(); - let numbers = cap.at(2).unwrap(); - if symbols.contains("s") || symbols.contains("t") { - return Err("The 's' and 't' modes are not supported on Windows".into()); - } else if numbers.len() >= 4 && numbers[..numbers.len() - 3].find(|ch| ch != '0').is_some() { - return Err("Setuid, setgid, and sticky modes are not supported on Windows".into()); - } - } - None => return Err(format!("invalid mode '{}'", mode)) - } - } - Ok(()) -} - -fn chmod(files: Vec, changes: bool, quiet: bool, verbose: bool, preserve_root: bool, recursive: bool, fmode: Option, cmode: Option<&String>) -> Result<(), i32> { - let mut r = Ok(()); - - for filename in files.iter() { - let filename = &filename[..]; - let file = Path::new(filename); - if file.uu_exists() { - if file.uu_is_dir() { - if !preserve_root || filename != "/" { - if recursive { - let walk_dir = match Walker::new(&file) { - Ok(m) => m, - Err(f) => { - crash!(1, "{}", f.to_string()); - } - }; - // XXX: here (and elsewhere) we see that this impl will have issues - // with non-UTF-8 filenames. Using OsString won't fix this because - // on Windows OsStrings cannot be built out of non-UTF-8 chars. One - // possible fix is to use CStrings rather than Strings in the args - // to chmod() and chmod_file(). - r = chmod(walk_dir.filter_map(|x| match x { - Ok(o) => match o.path().into_os_string().to_str() { - Some(s) => Some(s.to_string()), - None => None, - }, - Err(e) => None, - }).collect(), - changes, quiet, verbose, preserve_root, recursive, fmode, cmode).and(r); - r = chmod_file(&file, filename, changes, quiet, verbose, fmode, cmode).and(r); - } - } else { - show_error!("could not change permissions of directory '{}'", - filename); - r = Err(1); - } - } else { - r = chmod_file(&file, filename, changes, quiet, verbose, fmode, cmode).and(r); - } - } else { - show_error!("no such file or directory '{}'", filename); - r = Err(1); - } - } - - r -} - -#[cfg(windows)] -fn chmod_file(file: &Path, name: &str, changes: bool, quiet: bool, verbose: bool, fmode: Option, cmode: Option<&String>) -> Result<(), i32> { - // chmod is useless on Windows - // it doesn't set any permissions at all - // instead it just sets the readonly attribute on the file - Err(0) -} -#[cfg(unix)] -fn chmod_file(file: &Path, name: &str, changes: bool, quiet: bool, verbose: bool, fmode: Option, cmode: Option<&String>) -> Result<(), i32> { - let path = CString::new(name).unwrap_or_else(|e| panic!("{}", e)); - match fmode { - Some(mode) => { - if unsafe { libc::chmod(path.as_ptr(), mode) } == 0 { - // TODO: handle changes, quiet, and verbose - } else { - show_error!("{}", Error::last_os_error()); - return Err(1); - } - } - None => { - // TODO: make the regex processing occur earlier (i.e. once in the main function) - let re: regex::Regex = Regex::new(r"^(([ugoa]*)((?:[-+=](?:[rwxXst]*|[ugo]))+))|([-+=]?[0-7]+)$").unwrap(); - let mut stat: libc::stat = unsafe { mem::uninitialized() }; - let statres = unsafe { libc::stat(path.as_ptr(), &mut stat as *mut libc::stat) }; - let mut fperm = - if statres == 0 { - stat.st_mode - } else { - show_error!("{}", Error::last_os_error()); - return Err(1); - }; - for mode in cmode.unwrap().split(',') { // cmode is guaranteed to be Some in this case - let cap = re.captures(mode).unwrap(); // mode was verified earlier, so this is safe - if match cap.at(1) { - Some("") | None => false, - _ => true, - } { - // symbolic - let mut levels = cap.at(2).unwrap(); - if levels.len() == 0 { - levels = "a"; - } - let change = cap.at(3).unwrap().to_string() + "+"; - let mut action = change.chars().next().unwrap(); - let mut rwx = 0; - let mut special = 0; - let mut special_changed = false; - for ch in change[1..].chars() { - match ch { - '+' | '-' | '=' => { - for level in levels.chars() { - let (rwx, mask) = match level { - 'u' => (rwx << 6, 0o7077), - 'g' => (rwx << 3, 0o7707), - 'o' => (rwx, 0o7770), - 'a' => ((rwx << 6) | (rwx << 3) | rwx, 0o7000), - _ => unreachable!() - }; - match action { - '+' => fperm |= rwx, - '-' => fperm &= !rwx, - '=' => fperm = (fperm & mask) | rwx, - _ => unreachable!() - } - } - if special_changed { - match action { - '+' => fperm |= special, - '-' => fperm &= !special, - '=' => fperm &= special | 0o0777, - _ => unreachable!() - } - } - action = ch; - rwx = 0; - special = 0; - special_changed = false; - } - 'r' => rwx |= 0o004, - 'w' => rwx |= 0o002, - 'x' => rwx |= 0o001, - 'X' => { - if file.uu_is_dir() || (fperm & 0o0111) != 0 { - rwx |= 0o001; - } - } - 's' => { - special |= 0o4000 | 0o2000; - special_changed = true; - } - 't' => { - special |= 0o1000; - special_changed = true; - } - 'u' => rwx = (fperm >> 6) & 0o007, - 'g' => rwx = (fperm >> 3) & 0o007, - 'o' => rwx = (fperm >> 0) & 0o007, - _ => unreachable!() - } - } - } else { - // numeric - let change = cap.at(4).unwrap(); - let ch = change.chars().next().unwrap(); - let (action, slice) = match ch { - '+' | '-' | '=' => (ch, &change[1..]), - _ => ('=', change) - }; - let mode = u32::from_str_radix(slice, 8).unwrap() as libc::mode_t; // already verified - match action { - '+' => fperm |= mode, - '-' => fperm &= !mode, - '=' => fperm = mode, - _ => unreachable!() - } - } - if unsafe { libc::chmod(path.as_ptr(), fperm) } == 0 { - // TODO: see above - } else { - show_error!("{}", Error::last_os_error()); - return Err(1); - } - } - } - } - - Ok(()) -} diff --git a/src/chmod/deps.mk b/src/chmod/deps.mk deleted file mode 100644 index 07a0616b6..000000000 --- a/src/chmod/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += aho-corasick memchr regex regex-syntax walker diff --git a/src/chroot/Cargo.toml b/src/chroot/Cargo.toml deleted file mode 100644 index 25c36d15f..000000000 --- a/src/chroot/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "chroot" -version = "0.0.1" -authors = [] - -[lib] -name = "chroot" -path = "chroot.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/chroot/chroot.rs b/src/chroot/chroot.rs deleted file mode 100644 index 6ea2699df..000000000 --- a/src/chroot/chroot.rs +++ /dev/null @@ -1,220 +0,0 @@ -#![crate_name = "chroot"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Vsevolod Velichko - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use c_types::{get_pw_from_args, get_group}; -use getopts::Options; -use libc::funcs::posix88::unistd::{setgid, setuid}; -use std::ffi::CString; -use std::io::{Error, Write}; -use std::iter::FromIterator; -use std::path::Path; -use std::process::Command; - -#[path = "../common/util.rs"] #[macro_use] mod util; -#[path = "../common/c_types.rs"] mod c_types; -#[path = "../common/filesystem.rs"] mod filesystem; - -use filesystem::UUPathExt; - -extern { - fn chroot(path: *const libc::c_char) -> libc::c_int; -} - -#[cfg(any(target_os = "macos", target_os = "freebsd"))] -extern { - fn setgroups(size: libc::c_int, list: *const libc::gid_t) -> libc::c_int; -} - -#[cfg(target_os = "linux")] -extern { - fn setgroups(size: libc::size_t, list: *const libc::gid_t) -> libc::c_int; -} - -static NAME: &'static str = "chroot"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - - opts.optopt("u", "user", "User (ID or name) to switch before running the program", "USER"); - opts.optopt("g", "group", "Group (ID or name) to switch to", "GROUP"); - opts.optopt("G", "groups", "Comma-separated list of groups to switch to", "GROUP1,GROUP2..."); - opts.optopt("", "userspec", "Colon-separated user and group to switch to. \ - Same as -u USER -g GROUP. \ - Userspec has higher preference than -u and/or -g", "USER:GROUP"); - opts.optflag("h", "help", "Show help"); - opts.optflag("V", "version", "Show program's version"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - show_error!("{}", f); - help_menu(opts); - return 1 - } - }; - - if matches.opt_present("V") { version(); return 0 } - if matches.opt_present("h") { help_menu(opts); return 0 } - - if matches.free.len() == 0 { - println!("Missing operand: NEWROOT"); - println!("Try `{} --help` for more information.", NAME); - return 1 - } - - let default_shell: &'static str = "/bin/sh"; - let default_option: &'static str = "-i"; - let user_shell = std::env::var("SHELL"); - - let newroot = Path::new(&matches.free[0][..]); - if !newroot.uu_is_dir() { - crash!(1, "cannot change root directory to `{}`: no such directory", newroot.display()); - } - - let command: Vec<&str> = match matches.free.len() { - 1 => { - let shell: &str = match user_shell { - Err(_) => default_shell, - Ok(ref s) => s.as_ref(), - }; - vec!(shell, default_option) - }, - _ => matches.free[1..].iter().map(|x| &x[..]).collect() - }; - - set_context(&newroot, &matches); - - let pstatus = Command::new(command[0]) - .args(&command[1..]) - .status() - .unwrap_or_else(|e| crash!(1, "Cannot exec: {}", e)); - - if pstatus.success() { - 0 - } else { - match pstatus.code() { - Some(i) => i, - None => -1, - } - } -} - -fn set_context(root: &Path, options: &getopts::Matches) { - let userspec_str = options.opt_str("userspec"); - let user_str = options.opt_str("user").unwrap_or_default(); - let group_str = options.opt_str("group").unwrap_or_default(); - let groups_str = options.opt_str("groups").unwrap_or_default(); - let userspec = match userspec_str { - Some(ref u) => { - let s: Vec<&str> = u.split(':').collect(); - if s.len() != 2 { - crash!(1, "invalid userspec: `{}`", u) - }; - s - } - None => Vec::new() - }; - let user = if userspec.is_empty() { &user_str[..] } else { &userspec[0][..] }; - let group = if userspec.is_empty() { &group_str[..] } else { &userspec[1][..] }; - - enter_chroot(root); - - set_groups_from_str(&groups_str[..]); - set_main_group(&group[..]); - set_user(&user[..]); -} - -fn enter_chroot(root: &Path) { - let root_str = root.display(); - std::env::set_current_dir(root).unwrap(); - let err = unsafe { - chroot(CString::new(".".as_bytes()).unwrap().as_bytes_with_nul().as_ptr() as *const libc::c_char) - }; - if err != 0 { - crash!(1, "cannot chroot to {}: {}", root_str, Error::last_os_error()) - }; -} - -fn set_main_group(group: &str) { - if !group.is_empty() { - let group_id = match get_group(group) { - None => crash!(1, "no such group: {}", group), - Some(g) => g.gr_gid - }; - let err = unsafe { setgid(group_id) }; - if err != 0 { - crash!(1, "cannot set gid to {}: {}", group_id, Error::last_os_error()) - } - } -} - -#[cfg(any(target_os = "macos", target_os = "freebsd"))] -fn set_groups(groups: Vec) -> libc::c_int { - unsafe { - setgroups(groups.len() as libc::c_int, - groups.as_ptr()) - } -} - -#[cfg(target_os = "linux")] -fn set_groups(groups: Vec) -> libc::c_int { - unsafe { - setgroups(groups.len() as libc::size_t, - groups.as_ptr()) - } -} - -fn set_groups_from_str(groups: &str) { - if !groups.is_empty() { - let groups_vec: Vec = FromIterator::from_iter( - groups.split(',').map( - |x| match get_group(x) { - None => crash!(1, "no such group: {}", x), - Some(g) => g.gr_gid - }) - ); - let err = set_groups(groups_vec); - if err != 0 { - crash!(1, "cannot set groups: {}", Error::last_os_error()) - } - } -} - -fn set_user(user: &str) { - if !user.is_empty() { - let user_id = get_pw_from_args(&vec!(user.to_string())).unwrap().pw_uid; - let err = unsafe { setuid(user_id as libc::uid_t) }; - if err != 0 { - crash!(1, "cannot set user to {}: {}", user, Error::last_os_error()) - } - } -} - -fn version() { - println!("{} {}", NAME, VERSION) -} - -fn help_menu(options: Options) { - let msg = format!("{0} {1} - -Usage: - {0} [OPTION]... NEWROOT [COMMAND [ARG]...] - -Run COMMAND with root directory set to NEWROOT. -If COMMAND is not specified, it defaults to '$(SHELL) -i'. -If $(SHELL) is not set, /bin/sh is used.", NAME, VERSION); - - print!("{}", options.usage(&msg)); -} diff --git a/src/cksum/Cargo.toml b/src/cksum/Cargo.toml deleted file mode 100644 index a76fd6dc4..000000000 --- a/src/cksum/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "cksum" -version = "0.0.1" -authors = [] - -[lib] -name = "cksum" -path = "cksum.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/cksum/cksum.rs b/src/cksum/cksum.rs deleted file mode 100644 index 02696ba62..000000000 --- a/src/cksum/cksum.rs +++ /dev/null @@ -1,131 +0,0 @@ -#![crate_name = "cksum"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Michael Gehring - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; - -use getopts::Options; -use std::fs::File; -use std::io::{self, stdin, Read, Write, BufReader}; -use std::mem; -use std::path::Path; - -use crc_table::CRC_TABLE; - -#[path="../common/util.rs"] -#[macro_use] -mod util; - -mod crc_table; - -static NAME: &'static str = "cksum"; -static VERSION: &'static str = "1.0.0"; - -#[inline] -fn crc_update(crc: u32, input: u8) -> u32 { - (crc << 8) ^ CRC_TABLE[((crc >> 24) as usize ^ input as usize) & 0xFF] -} - -#[inline] -fn crc_final(mut crc: u32, mut length: usize) -> u32 { - while length != 0 { - crc = crc_update(crc, length as u8); - length >>= 8; - } - - !crc -} - -#[inline] -fn cksum(fname: &str) -> io::Result<(u32, usize)> { - let mut crc = 0u32; - let mut size = 0usize; - - let file; - let mut rd : Box = match fname { - "-" => { - Box::new(stdin()) - } - _ => { - file = try!(File::open(&Path::new(fname))); - Box::new(BufReader::new(file)) - } - }; - - let mut bytes: [u8; 1024 * 1024] = unsafe { mem::uninitialized() }; - loop { - match rd.read(&mut bytes) { - Ok(num_bytes) => { - if num_bytes == 0 { - return Ok((crc_final(crc, size), size)); - } - for &b in bytes[..num_bytes].iter() { - crc = crc_update(crc, b); - } - size += num_bytes; - } - Err(err) => return Err(err) - } - } -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(err) => panic!("{}", err), - }; - - if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: - {0} [OPTIONS] [FILE]... - -Print CRC and size for each file.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - return 0; - } - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - let files = matches.free; - - if files.is_empty() { - match cksum("-") { - Ok((crc, size)) => println!("{} {}", crc, size), - Err(err) => { - show_error!("{}", err); - return 2; - } - } - return 0; - } - - let mut exit_code = 0; - for fname in files.iter() { - match cksum(fname.as_ref()) { - Ok((crc, size)) => println!("{} {} {}", crc, size, fname), - Err(err) => { - show_error!("'{}' {}", fname, err); - exit_code = 2; - } - } - } - - exit_code -} diff --git a/src/cksum/crc_table.rs b/src/cksum/crc_table.rs deleted file mode 100644 index 592dfe9cb..000000000 --- a/src/cksum/crc_table.rs +++ /dev/null @@ -1,3 +0,0 @@ -/* auto-generated (DO NOT EDIT) */ - -pub static CRC_TABLE: [u32; 256] = [0, 79764919, 159529838, 222504665, 319059676, 398814059, 445009330, 507990021, 638119352, 583659535, 797628118, 726387553, 890018660, 835552979, 1015980042, 944750013, 1276238704, 1221641927, 1167319070, 1095957929, 1595256236, 1540665371, 1452775106, 1381403509, 1780037320, 1859660671, 1671105958, 1733955601, 2031960084, 2111593891, 1889500026, 1952343757, 2552477408, 2632100695, 2443283854, 2506133561, 2334638140, 2414271883, 2191915858, 2254759653, 3190512472, 3135915759, 3081330742, 3009969537, 2905550212, 2850959411, 2762807018, 2691435357, 3560074640, 3505614887, 3719321342, 3648080713, 3342211916, 3287746299, 3467911202, 3396681109, 4063920168, 4143685023, 4223187782, 4286162673, 3779000052, 3858754371, 3904687514, 3967668269, 881225847, 809987520, 1023691545, 969234094, 662832811, 591600412, 771767749, 717299826, 311336399, 374308984, 453813921, 533576470, 25881363, 88864420, 134795389, 214552010, 2023205639, 2086057648, 1897238633, 1976864222, 1804852699, 1867694188, 1645340341, 1724971778, 1587496639, 1516133128, 1461550545, 1406951526, 1302016099, 1230646740, 1142491917, 1087903418, 2896545431, 2825181984, 2770861561, 2716262478, 3215044683, 3143675388, 3055782693, 3001194130, 2326604591, 2389456536, 2200899649, 2280525302, 2578013683, 2640855108, 2418763421, 2498394922, 3769900519, 3832873040, 3912640137, 3992402750, 4088425275, 4151408268, 4197601365, 4277358050, 3334271071, 3263032808, 3476998961, 3422541446, 3585640067, 3514407732, 3694837229, 3640369242, 1762451694, 1842216281, 1619975040, 1682949687, 2047383090, 2127137669, 1938468188, 2001449195, 1325665622, 1271206113, 1183200824, 1111960463, 1543535498, 1489069629, 1434599652, 1363369299, 622672798, 568075817, 748617968, 677256519, 907627842, 853037301, 1067152940, 995781531, 51762726, 131386257, 177728840, 240578815, 269590778, 349224269, 429104020, 491947555, 4046411278, 4126034873, 4172115296, 4234965207, 3794477266, 3874110821, 3953728444, 4016571915, 3609705398, 3555108353, 3735388376, 3664026991, 3290680682, 3236090077, 3449943556, 3378572211, 3174993278, 3120533705, 3032266256, 2961025959, 2923101090, 2868635157, 2813903052, 2742672763, 2604032198, 2683796849, 2461293480, 2524268063, 2284983834, 2364738477, 2175806836, 2238787779, 1569362073, 1498123566, 1409854455, 1355396672, 1317987909, 1246755826, 1192025387, 1137557660, 2072149281, 2135122070, 1912620623, 1992383480, 1753615357, 1816598090, 1627664531, 1707420964, 295390185, 358241886, 404320391, 483945776, 43990325, 106832002, 186451547, 266083308, 932423249, 861060070, 1041341759, 986742920, 613929101, 542559546, 756411363, 701822548, 3316196985, 3244833742, 3425377559, 3370778784, 3601682597, 3530312978, 3744426955, 3689838204, 3819031489, 3881883254, 3928223919, 4007849240, 4037393693, 4100235434, 4180117107, 4259748804, 2310601993, 2373574846, 2151335527, 2231098320, 2596047829, 2659030626, 2470359227, 2550115596, 2947551409, 2876312838, 2788305887, 2733848168, 3165939309, 3094707162, 3040238851, 2985771188]; \ No newline at end of file diff --git a/src/cksum/gen_table.rs b/src/cksum/gen_table.rs deleted file mode 100644 index b8b9b62e4..000000000 --- a/src/cksum/gen_table.rs +++ /dev/null @@ -1,41 +0,0 @@ -/* -* This file is part of the uutils coreutils package. -* -* (c) Arcterus -* (c) Michael Gehring -* -* For the full copyright and license information, please view the LICENSE -* file that was distributed with this source code. -*/ - -use std::fs::File; -use std::io::Write; - -static CRC_TABLE_LEN: usize = 256; - -fn main() { - let mut table = Vec::with_capacity(CRC_TABLE_LEN); - for num in (0 .. CRC_TABLE_LEN) { - table.push(crc_entry(num as u8) as u32); - } - let file = File::create("crc_table.rs").unwrap_or_else(|e| panic!("{}", e)); - write!(&file, "/* auto-generated (DO NOT EDIT) */ - -pub static CRC_TABLE: [u32; {}] = {:?};", CRC_TABLE_LEN, table).unwrap(); -} - -#[inline] -fn crc_entry(input: u8) -> u32 { - let mut crc = (input as u32) << 24; - - for _ in (0 .. 8) { - if crc & 0x80000000 != 0 { - crc <<= 1; - crc ^= 0x04c11db7; - } else { - crc <<= 1; - } - } - - crc -} diff --git a/src/comm/Cargo.toml b/src/comm/Cargo.toml deleted file mode 100644 index 214a0ea22..000000000 --- a/src/comm/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "comm" -version = "0.0.1" -authors = [] - -[lib] -name = "comm" -path = "comm.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/comm/comm.rs b/src/comm/comm.rs deleted file mode 100644 index ded6a83cb..000000000 --- a/src/comm/comm.rs +++ /dev/null @@ -1,160 +0,0 @@ -#![crate_name = "comm"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Michael Gehring - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; - -use getopts::Options; -use std::cmp::Ordering; -use std::fs::File; -use std::io::{self, BufRead, BufReader, Read, stdin, Stdin}; -use std::path::Path; - -static NAME: &'static str = "comm"; -static VERSION: &'static str = "1.0.0"; - -fn mkdelim(col: usize, opts: &getopts::Matches) -> String { - let mut s = String::new(); - let delim = match opts.opt_str("output-delimiter") { - Some(d) => d.clone(), - None => "\t".to_string(), - }; - - if col > 1 && !opts.opt_present("1") { - s.push_str(delim.as_ref()); - } - if col > 2 && !opts.opt_present("2") { - s.push_str(delim.as_ref()); - } - - s -} - -fn ensure_nl(line: &mut String) { - match line.chars().last() { - Some('\n') => (), - _ => line.push_str("\n") - } -} - -enum LineReader { - Stdin(Stdin), - FileIn(BufReader) -} - -impl LineReader { - fn read_line(&mut self, buf: &mut String) -> io::Result { - match self { - &mut LineReader::Stdin(ref mut r) => r.read_line(buf), - &mut LineReader::FileIn(ref mut r) => r.read_line(buf), - } - } -} - -fn comm(a: &mut LineReader, b: &mut LineReader, opts: &getopts::Matches) { - - let delim : Vec = (0 .. 4).map(|col| mkdelim(col, opts)).collect(); - - let mut ra = &mut String::new(); - let mut na = a.read_line(ra); - let mut rb = &mut String::new(); - let mut nb = b.read_line(rb); - - while na.is_ok() || nb.is_ok() { - let ord = match (na.is_ok(), nb.is_ok()) { - (false, true) => Ordering::Greater, - (true , false) => Ordering::Less, - (true , true) => match(&na, &nb) { - (&Ok(0), _) => Ordering::Greater, - (_, &Ok(0)) => Ordering::Less, - _ => ra.cmp(&rb), - }, - _ => unreachable!(), - }; - - match ord { - Ordering::Less => { - if !opts.opt_present("1") { - ensure_nl(ra); - print!("{}{}", delim[1], ra); - } - na = a.read_line(ra); - }, - Ordering::Greater => { - if !opts.opt_present("2") { - ensure_nl(rb); - print!("{}{}", delim[2], rb); - } - nb = b.read_line(rb); - }, - Ordering::Equal => { - if !opts.opt_present("3") { - ensure_nl(ra); - print!("{}{}", delim[3], ra); - } - na = a.read_line(ra); - nb = b.read_line(rb); - } - } - } -} - -fn open_file(name: &str) -> io::Result { - match name { - "-" => Ok(LineReader::Stdin(stdin())), - _ => { - let f = try!(File::open(&Path::new(name))); - Ok(LineReader::FileIn(BufReader::new(f))) - } - } -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - opts.optflag("1", "", "suppress column 1 (lines uniq to FILE1)"); - opts.optflag("2", "", "suppress column 2 (lines uniq to FILE2)"); - opts.optflag("3", "", "suppress column 3 (lines that appear in both files)"); - opts.optopt("", "output-delimiter", "separate columns with STR", "STR"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(err) => panic!("{}", err), - }; - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - if matches.opt_present("help") || matches.free.len() != 2 { - let msg = format!("{0} {1} - -Usage: - {0} [OPTIONS] FILE1 FILE2 - -Compare sorted files line by line.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - - if matches.free.len() != 2 { - return 1; - } - return 0; - } - - let mut f1 = open_file(matches.free[0].as_ref()).unwrap(); - let mut f2 = open_file(matches.free[1].as_ref()).unwrap(); - - comm(&mut f1, &mut f2, &matches); - - 0 -} diff --git a/src/common/c_types.rs b/src/common/c_types.rs deleted file mode 100644 index d41871257..000000000 --- a/src/common/c_types.rs +++ /dev/null @@ -1,240 +0,0 @@ -#![allow(dead_code, non_camel_case_types, raw_pointer_derive)] - -extern crate libc; - -use self::libc::{ - c_char, - c_int, - uid_t, - gid_t, -}; -#[cfg(any(target_os = "macos", target_os = "freebsd"))] -use self::libc::time_t; -#[cfg(target_os = "macos")] -use self::libc::int32_t; - -use self::libc::funcs::posix88::unistd::getgroups; - -use std::ffi::{CStr, CString}; -use std::io::{Error, Write}; -use std::iter::repeat; -use std::vec::Vec; - -use std::ptr::{null_mut, read}; - -#[cfg(any(target_os = "macos", target_os = "freebsd"))] -#[repr(C)] -#[derive(Clone, Copy)] -pub struct c_passwd { - pub pw_name: *const c_char, /* user name */ - pub pw_passwd: *const c_char, /* user name */ - pub pw_uid: uid_t, /* user uid */ - pub pw_gid: gid_t, /* user gid */ - pub pw_change: time_t, - pub pw_class: *const c_char, - pub pw_gecos: *const c_char, - pub pw_dir: *const c_char, - pub pw_shell: *const c_char, - pub pw_expire: time_t -} - -#[cfg(target_os = "linux")] -#[repr(C)] -#[derive(Clone, Copy)] -pub struct c_passwd { - pub pw_name: *const c_char, /* user name */ - pub pw_passwd: *const c_char, /* user name */ - pub pw_uid: uid_t, /* user uid */ - pub pw_gid: gid_t, /* user gid */ - pub pw_gecos: *const c_char, - pub pw_dir: *const c_char, - pub pw_shell: *const c_char, -} - -#[cfg(any(target_os = "macos", target_os = "freebsd"))] -#[repr(C)] -pub struct utsname { - pub sysname: [c_char; 256], - pub nodename: [c_char; 256], - pub release: [c_char; 256], - pub version: [c_char; 256], - pub machine: [c_char; 256] -} - -#[cfg(target_os = "linux")] -#[repr(C)] -pub struct utsname { - pub sysname: [c_char; 65], - pub nodename: [c_char; 65], - pub release: [c_char; 65], - pub version: [c_char; 65], - pub machine: [c_char; 65], - pub domainame: [c_char; 65] -} - -#[repr(C)] -pub struct c_group { - pub gr_name: *const c_char, // group name - pub gr_passwd: *const c_char, // password - pub gr_gid: gid_t, // group id - pub gr_mem: *const *const c_char, // member list -} - -#[repr(C)] -pub struct c_tm { - pub tm_sec: c_int, /* seconds */ - pub tm_min: c_int, /* minutes */ - pub tm_hour: c_int, /* hours */ - pub tm_mday: c_int, /* day of the month */ - pub tm_mon: c_int, /* month */ - pub tm_year: c_int, /* year */ - pub tm_wday: c_int, /* day of the week */ - pub tm_yday: c_int, /* day in the year */ - pub tm_isdst: c_int /* daylight saving time */ -} - -extern { - pub fn getpwuid(uid: uid_t) -> *const c_passwd; - pub fn getpwnam(login: *const c_char) -> *const c_passwd; - pub fn getgrgid(gid: gid_t) -> *const c_group; - pub fn getgrnam(name: *const c_char) -> *const c_group; - pub fn getgrouplist(name: *const c_char, - gid: gid_t, - groups: *mut gid_t, - ngroups: *mut c_int) -> c_int; -} - -#[cfg(target_os = "macos")] -extern { - pub fn getgroupcount(name: *const c_char, gid: gid_t) -> int32_t; -} - -pub fn get_pw_from_args(free: &Vec) -> Option { - if free.len() == 1 { - let username = &free[0][..]; - - // Passed user as id - if username.chars().all(|c| c.is_digit(10)) { - let id = username.parse::().unwrap(); - let pw_pointer = unsafe { getpwuid(id as uid_t) }; - - if !pw_pointer.is_null() { - Some(unsafe { read(pw_pointer) }) - } else { - crash!(1, "{}: no such user", username); - } - - // Passed the username as a string - } else { - let pw_pointer = unsafe { - let cstr = CString::new(username).unwrap(); - getpwnam(cstr.as_bytes_with_nul().as_ptr() as *const i8) - }; - if !pw_pointer.is_null() { - Some(unsafe { read(pw_pointer) }) - } else { - crash!(1, "{}: no such user", username); - } - } - } else { - None - } -} - -pub fn get_group(groupname: &str) -> Option { - let group = if groupname.chars().all(|c| c.is_digit(10)) { - unsafe { getgrgid(groupname.parse().unwrap()) } - } else { - unsafe { - let cstr = CString::new(groupname).unwrap(); - getgrnam(cstr.as_bytes_with_nul().as_ptr() as *const c_char) - } - }; - - if !group.is_null() { - Some(unsafe { read(group) }) - } - else { - None - } -} - -pub fn get_group_list(name: *const c_char, gid: gid_t) -> Vec { - let mut ngroups: c_int = 32; - let mut groups: Vec = Vec::with_capacity(ngroups as usize); - - if unsafe { get_group_list_internal(name, gid, groups.as_mut_ptr(), &mut ngroups) } == -1 { - groups.reserve(ngroups as usize); - unsafe { get_group_list_internal(name, gid, groups.as_mut_ptr(), &mut ngroups); } - } else { - groups.truncate(ngroups as usize); - } - unsafe { groups.set_len(ngroups as usize); } - - groups -} - -#[cfg(any(target_os = "linux", target_os = "freebsd"))] -#[inline(always)] -unsafe fn get_group_list_internal(name: *const c_char, gid: gid_t, groups: *mut gid_t, grcnt: *mut c_int) -> c_int { - getgrouplist(name, gid, groups, grcnt) -} - -#[cfg(target_os = "macos")] -unsafe fn get_group_list_internal(name: *const c_char, gid: gid_t, groups: *mut gid_t, grcnt: *mut c_int) -> c_int { - let ngroups = getgroupcount(name, gid); - let oldsize = *grcnt; - *grcnt = ngroups; - if oldsize >= ngroups { - getgrouplist(name, gid, groups, grcnt); - 0 - } else { - -1 - } -} - -pub fn get_groups() -> Result, i32> { - let ngroups = unsafe { getgroups(0, null_mut()) }; - if ngroups == -1 { - return Err(Error::last_os_error().raw_os_error().unwrap()) - } - - let mut groups : Vec= repeat(0).take(ngroups as usize).collect(); - let ngroups = unsafe { getgroups(ngroups, groups.as_mut_ptr()) }; - if ngroups == -1 { - Err(Error::last_os_error().raw_os_error().unwrap()) - } else { - groups.truncate(ngroups as usize); - Ok(groups) - } -} - -pub fn group(possible_pw: Option, nflag: bool) { - let groups = match possible_pw { - Some(pw) => Ok(get_group_list(pw.pw_name, pw.pw_gid)), - None => get_groups(), - }; - - match groups { - Err(errno) => - crash!(1, "failed to get group list (errno={})", errno), - Ok(groups) => { - for &g in groups.iter() { - if nflag { - let group = unsafe { getgrgid(g) }; - if !group.is_null() { - let name = unsafe { - let gname = read(group).gr_name; - let bytes= CStr::from_ptr(gname).to_bytes(); - String::from_utf8_lossy(bytes).to_string() - }; - print!("{} ", name); - } - } else { - print!("{} ", g); - } - } - println!(""); - } - } -} diff --git a/src/common/filesystem.rs b/src/common/filesystem.rs deleted file mode 100644 index e00aa34b8..000000000 --- a/src/common/filesystem.rs +++ /dev/null @@ -1,147 +0,0 @@ -/* - * This file is part of the uutils coreutils package. - * - * (c) Joseph Crail - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -// Based on the pattern using by Cargo, I created a shim over the -// standard PathExt trait, so that the unstable path methods could -// be backported to stable (<= 1.1). This will likely be dropped -// when the path trait stabilizes. - -use std::env; -use std::fs; -use std::io::{Error, ErrorKind, Result}; -use std::path::{Component, Path, PathBuf}; - -pub trait UUPathExt { - fn uu_exists(&self) -> bool; - fn uu_is_file(&self) -> bool; - fn uu_is_dir(&self) -> bool; - fn uu_metadata(&self) -> Result; -} - -impl UUPathExt for Path { - fn uu_exists(&self) -> bool { - fs::metadata(self).is_ok() - } - - fn uu_is_file(&self) -> bool { - fs::metadata(self).map(|m| m.is_file()).unwrap_or(false) - } - - fn uu_is_dir(&self) -> bool { - fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false) - } - - fn uu_metadata(&self) -> Result { - fs::metadata(self) - } -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[allow(dead_code)] -pub enum CanonicalizeMode { - None, - Normal, - Existing, - Missing, -} - -#[allow(dead_code)] -fn resolve>(original: P) -> Result { - const MAX_LINKS_FOLLOWED: u32 = 255; - let mut followed = 0; - let mut result = original.as_ref().to_path_buf(); - loop { - if followed == MAX_LINKS_FOLLOWED { - return Err(Error::new(ErrorKind::InvalidInput, "maximum links followed")); - } - - match fs::metadata(&result) { - Err(e) => return Err(e), - Ok(ref m) if !m.file_type().is_symlink() => break, - Ok(..) => { - followed += 1; - match fs::read_link(&result) { - Ok(path) => { - result.pop(); - result.push(path); - }, - Err(e) => { - return Err(e); - } - } - } - } - } - Ok(result) -} - -#[allow(dead_code)] -pub fn canonicalize>(original: P, can_mode: CanonicalizeMode) -> Result { - // Create an absolute path - let original = original.as_ref(); - let original = if original.is_absolute() { - original.to_path_buf() - } else { - env::current_dir().unwrap().join(original) - }; - - let mut result = PathBuf::new(); - let mut parts = vec!(); - - // Split path by directory separator; add prefix (Windows-only) and root - // directory to final path buffer; add remaining parts to temporary - // vector for canonicalization. - for part in original.components() { - match part { - Component::Prefix(_) | Component::RootDir => { - result.push(part.as_os_str()); - }, - Component::CurDir => {}, - Component::ParentDir => { - parts.pop(); - }, - Component::Normal(_) => { - parts.push(part.as_os_str()); - } - } - } - - // Resolve the symlinks where possible - if parts.len() > 0 { - for part in parts[..parts.len()-1].iter() { - result.push(part); - - if can_mode == CanonicalizeMode::None { - continue; - } - - match resolve(&result) { - Err(e) => match can_mode { - CanonicalizeMode::Missing => continue, - _ => return Err(e) - }, - Ok(path) => { - result.pop(); - result.push(path); - } - } - } - - result.push(parts.last().unwrap()); - - match resolve(&result) { - Err(e) => { if can_mode == CanonicalizeMode::Existing { return Err(e); } }, - Ok(path) => { - result.pop(); - result.push(path); - } - } - } - Ok(result) -} diff --git a/src/common/parse_time.rs b/src/common/parse_time.rs deleted file mode 100644 index 608601fe1..000000000 --- a/src/common/parse_time.rs +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of the uutils coreutils package. - * - * (c) Arcterus - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -pub fn from_str(string: &str) -> Result { - let len = string.len(); - if len == 0 { - return Err("empty string".to_string()) - } - let slice = &string[..len - 1]; - let (numstr, times) = match string.chars().next_back().unwrap() { - 's' | 'S' => (slice, 1), - 'm' | 'M' => (slice, 60), - 'h' | 'H' => (slice, 60 * 60), - 'd' | 'D' => (slice, 60 * 60 * 24), - val => { - if !val.is_alphabetic() { - (string, 1) - } else if string == "inf" || string == "infinity" { - ("inf", 1) - } else { - return Err(format!("invalid time interval '{}'", string)) - } - } - }; - match numstr.parse::() { - Ok(m) => Ok(m * times as f64), - Err(e) => Err(format!("invalid time interval '{}': {}", string, e)) - } -} diff --git a/src/common/process.rs b/src/common/process.rs deleted file mode 100644 index 7f098a722..000000000 --- a/src/common/process.rs +++ /dev/null @@ -1,140 +0,0 @@ -/* - * This file is part of the uutils coreutils package. - * - * (c) Maciej Dziardziel - * - * For the full copyright and license information, please view the LICENSE file - * that was distributed with this source code. - */ - -extern crate libc; -extern crate time; - -use libc::{c_int, pid_t}; -use std::fmt; -use std::io; -use std::process::Child; -use std::sync::{Arc, Condvar, Mutex}; -use std::thread; -use time::{Duration, get_time}; - -// This is basically sys::unix::process::ExitStatus -#[derive(PartialEq, Eq, Clone, Copy, Debug)] -pub enum ExitStatus { - Code(i32), - Signal(i32), -} - -impl ExitStatus { - fn from_status(status: c_int) -> ExitStatus { - if status & 0x7F != 0 { // WIFSIGNALED(status) - ExitStatus::Signal(status & 0x7F) - } else { - ExitStatus::Code(status & 0xFF00 >> 8) - } - } - - pub fn success(&self) -> bool { - match *self { - ExitStatus::Code(code) => code == 0, - _ => false, - } - } - - pub fn code(&self) -> Option { - match *self { - ExitStatus::Code(code) => Some(code), - _ => None, - } - } - - pub fn signal(&self) -> Option { - match *self { - ExitStatus::Signal(code) => Some(code), - _ => None, - } - } -} - -impl fmt::Display for ExitStatus { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ExitStatus::Code(code) => write!(f, "exit code: {}", code), - ExitStatus::Signal(code) => write!(f, "exit code: {}", code), - } - } -} - -/// Missing methods for Child objects -pub trait ChildExt { - /// Send a signal to a Child process. - fn send_signal(&mut self, signal: usize) -> io::Result<()>; - - /// Wait for a process to finish or return after the specified duration. - fn wait_or_timeout(&mut self, timeout: f64) -> io::Result>; -} - -impl ChildExt for Child { - fn send_signal(&mut self, signal: usize) -> io::Result<()> { - if unsafe { libc::funcs::posix88::signal::kill(self.id() as pid_t, - signal as i32) } != 0 { - Err(io::Error::last_os_error()) - } else { - Ok(()) - } - } - - fn wait_or_timeout(&mut self, timeout: f64) -> io::Result> { - // The result will be written to that Option, protected by a Mutex - // Then the Condvar will be signaled - let state = Arc::new(( - Mutex::new(Option::None::>), - Condvar::new(), - )); - - // Start the waiting thread - let state_th = state.clone(); - let pid_th = self.id(); - thread::spawn(move || { - let &(ref lock_th, ref cvar_th) = &*state_th; - // Child::wait() would need a &mut to self, can't use that... - // use waitpid() directly, with our own ExitStatus - let mut status: c_int = 0; - let r = unsafe { libc::waitpid(pid_th as i32, &mut status, 0) }; - // Fill the Option and notify on the Condvar - let mut exitstatus_th = lock_th.lock().unwrap(); - if r != pid_th as c_int { - *exitstatus_th = Some(Err(io::Error::last_os_error())); - } else { - let s = ExitStatus::from_status(status); - *exitstatus_th = Some(Ok(s)); - } - cvar_th.notify_one(); - }); - - // Main thread waits - let &(ref lock, ref cvar) = &*state; - let mut exitstatus = lock.lock().unwrap(); - // Condvar::wait_timeout_ms() can wake too soon, in this case wait again - let target = get_time() + - Duration::seconds(timeout as i64) + - Duration::nanoseconds((timeout * 1.0e-6) as i64); - while exitstatus.is_none() { - let now = get_time(); - if now >= target { - return Ok(None) - } - let ms = (target - get_time()).num_milliseconds() as u32; - exitstatus = cvar.wait_timeout_ms(exitstatus, ms).unwrap().0; - } - - // Turn Option> into Result> - match exitstatus.take() { - Some(r) => match r { - Ok(s) => Ok(Some(s)), - Err(e) => Err(e), - }, - None => panic!(), - } - } -} diff --git a/src/common/signals.rs b/src/common/signals.rs deleted file mode 100644 index f48fefd2f..000000000 --- a/src/common/signals.rs +++ /dev/null @@ -1,158 +0,0 @@ -/* - * This file is part of the uutils coreutils package. - * - * (c) Maciej Dziardziel - * - * For the full copyright and license information, please view the LICENSE file - * that was distributed with this source code. - */ - -#![allow(dead_code)] - -pub static DEFAULT_SIGNAL:usize= 15; - - -pub struct Signal<'a> { pub name:&'a str, pub value: usize} - -/* - -Linux Programmer's Manual - - 1 HUP 2 INT 3 QUIT 4 ILL 5 TRAP 6 ABRT 7 BUS - 8 FPE 9 KILL 10 USR1 11 SEGV 12 USR2 13 PIPE 14 ALRM -15 TERM 16 STKFLT 17 CHLD 18 CONT 19 STOP 20 TSTP 21 TTIN -22 TTOU 23 URG 24 XCPU 25 XFSZ 26 VTALRM 27 PROF 28 WINCH -29 POLL 30 PWR 31 SYS - - -*/ - -#[cfg(target_os = "linux")] -pub static ALL_SIGNALS:[Signal<'static>; 31] = [ - Signal{ name: "HUP", value:1 }, - Signal{ name: "INT", value:2 }, - Signal{ name: "QUIT", value:3 }, - Signal{ name: "ILL", value:4 }, - Signal{ name: "TRAP", value:5 }, - Signal{ name: "ABRT", value:6 }, - Signal{ name: "BUS", value:7 }, - Signal{ name: "FPE", value:8 }, - Signal{ name: "KILL", value:9 }, - Signal{ name: "USR1", value:10 }, - Signal{ name: "SEGV", value:11 }, - Signal{ name: "USR2", value:12 }, - Signal{ name: "PIPE", value:13 }, - Signal{ name: "ALRM", value:14 }, - Signal{ name: "TERM", value:15 }, - Signal{ name: "STKFLT", value:16 }, - Signal{ name: "CHLD", value:17 }, - Signal{ name: "CONT", value:18 }, - Signal{ name: "STOP", value:19 }, - Signal{ name: "TSTP", value:20 }, - Signal{ name: "TTIN", value:21 }, - Signal{ name: "TTOU", value:22 }, - Signal{ name: "URG", value:23 }, - Signal{ name: "XCPU", value:24 }, - Signal{ name: "XFSZ", value:25 }, - Signal{ name: "VTALRM", value:26 }, - Signal{ name: "PROF", value:27 }, - Signal{ name: "WINCH", value:28 }, - Signal{ name: "POLL", value:29 }, - Signal{ name: "PWR", value:30 }, - Signal{ name: "SYS", value:31 }, -]; - - -/* - - -https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/signal.3.html - - -No Name Default Action Description -1 SIGHUP terminate process terminal line hangup -2 SIGINT terminate process interrupt program -3 SIGQUIT create core image quit program -4 SIGILL create core image illegal instruction -5 SIGTRAP create core image trace trap -6 SIGABRT create core image abort program (formerly SIGIOT) -7 SIGEMT create core image emulate instruction executed -8 SIGFPE create core image floating-point exception -9 SIGKILL terminate process kill program -10 SIGBUS create core image bus error -11 SIGSEGV create core image segmentation violation -12 SIGSYS create core image non-existent system call invoked -13 SIGPIPE terminate process write on a pipe with no reader -14 SIGALRM terminate process real-time timer expired -15 SIGTERM terminate process software termination signal -16 SIGURG discard signal urgent condition present on socket -17 SIGSTOP stop process stop (cannot be caught or ignored) -18 SIGTSTP stop process stop signal generated from keyboard -19 SIGCONT discard signal continue after stop -20 SIGCHLD discard signal child status has changed -21 SIGTTIN stop process background read attempted from control terminal -22 SIGTTOU stop process background write attempted to control terminal -23 SIGIO discard signal I/O is possible on a descriptor (see fcntl(2)) -24 SIGXCPU terminate process cpu time limit exceeded (see setrlimit(2)) -25 SIGXFSZ terminate process file size limit exceeded (see setrlimit(2)) -26 SIGVTALRM terminate process virtual time alarm (see setitimer(2)) -27 SIGPROF terminate process profiling timer alarm (see setitimer(2)) -28 SIGWINCH discard signal Window size change -29 SIGINFO discard signal status request from keyboard -30 SIGUSR1 terminate process User defined signal 1 -31 SIGUSR2 terminate process User defined signal 2 - -*/ - -#[cfg(any(target_os = "macos", target_os = "freebsd"))] -pub static ALL_SIGNALS:[Signal<'static>; 31] = [ - Signal{ name: "HUP", value:1 }, - Signal{ name: "INT", value:2 }, - Signal{ name: "QUIT", value:3 }, - Signal{ name: "ILL", value:4 }, - Signal{ name: "TRAP", value:5 }, - Signal{ name: "ABRT", value:6 }, - Signal{ name: "EMT", value:7 }, - Signal{ name: "FPE", value:8 }, - Signal{ name: "KILL", value:9 }, - Signal{ name: "BUS", value:10 }, - Signal{ name: "SEGV", value:11 }, - Signal{ name: "SYS", value:12 }, - Signal{ name: "PIPE", value:13 }, - Signal{ name: "ALRM", value:14 }, - Signal{ name: "TERM", value:15 }, - Signal{ name: "URG", value:16 }, - Signal{ name: "STOP", value:17 }, - Signal{ name: "TSTP", value:18 }, - Signal{ name: "CONT", value:19 }, - Signal{ name: "CHLD", value:20 }, - Signal{ name: "TTIN", value:21 }, - Signal{ name: "TTOU", value:22 }, - Signal{ name: "IO", value:23 }, - Signal{ name: "XCPU", value:24 }, - Signal{ name: "XFSZ", value:25 }, - Signal{ name: "VTALRM", value:26 }, - Signal{ name: "PROF", value:27 }, - Signal{ name: "WINCH", value:28 }, - Signal{ name: "INFO", value:29 }, - Signal{ name: "USR1", value:30 }, - Signal{ name: "USR2", value:31 }, -]; - -pub fn signal_by_name_or_value(signal_name_or_value: &str) -> Option { - if signal_name_or_value == "0" { - return Some(0); - } - for signal in ALL_SIGNALS.iter() { - let long_name = format!("SIG{}", signal.name); - if signal.name == signal_name_or_value || (signal_name_or_value == signal.value.to_string()) || (long_name == signal_name_or_value) { - return Some(signal.value); - } - } - None -} - -#[inline(always)] -pub fn is_signal(num: usize) -> bool { - num < ALL_SIGNALS.len() -} diff --git a/src/common/util.rs b/src/common/util.rs deleted file mode 100644 index d333def3e..000000000 --- a/src/common/util.rs +++ /dev/null @@ -1,219 +0,0 @@ -/* - * This file is part of the uutils coreutils package. - * - * (c) Arcterus - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -macro_rules! show_error( - ($($args:tt)+) => ({ - pipe_write!(&mut ::std::io::stderr(), "{}: error: ", ::NAME); - pipe_writeln!(&mut ::std::io::stderr(), $($args)+); - }) -); - -#[macro_export] -macro_rules! show_warning( - ($($args:tt)+) => ({ - pipe_write!(&mut ::std::io::stderr(), "{}: warning: ", ::NAME); - pipe_writeln!(&mut ::std::io::stderr(), $($args)+); - }) -); - -#[macro_export] -macro_rules! show_info( - ($($args:tt)+) => ({ - pipe_write!(&mut ::std::io::stderr(), "{}: ", ::NAME); - pipe_writeln!(&mut ::std::io::stderr(), $($args)+); - }) -); - -#[macro_export] -macro_rules! eprint( - ($($args:tt)+) => (pipe_write!(&mut ::std::io::stderr(), $($args)+)) -); - -#[macro_export] -macro_rules! eprintln( - ($($args:tt)+) => (pipe_writeln!(&mut ::std::io::stderr(), $($args)+)) -); - -#[macro_export] -macro_rules! crash( - ($exitcode:expr, $($args:tt)+) => ({ - show_error!($($args)+); - ::std::process::exit($exitcode) - }) -); - -#[macro_export] -macro_rules! exit( - ($exitcode:expr) => ({ - ::std::process::exit($exitcode) - }) -); - -#[macro_export] -macro_rules! crash_if_err( - ($exitcode:expr, $exp:expr) => ( - match $exp { - Ok(m) => m, - Err(f) => crash!($exitcode, "{}", f), - } - ) -); - -#[macro_export] -macro_rules! pipe_crash_if_err( - ($exitcode:expr, $exp:expr) => ( - match $exp { - Ok(_) => (), - Err(f) => { - if f.kind() == ::std::io::ErrorKind::BrokenPipe { - () - } else { - crash!($exitcode, "{}", f) - } - }, - } - ) -); - -#[macro_export] -macro_rules! return_if_err( - ($exitcode:expr, $exp:expr) => ( - match $exp { - Ok(m) => m, - Err(f) => { - show_error!("{}", f); - return $exitcode; - } - } - ) -); - -// XXX: should the pipe_* macros return an Err just to show the write failed? - -#[macro_export] -macro_rules! pipe_print( - ($($args:tt)+) => ( - match write!(&mut ::std::io::stdout(), $($args)+) { - Ok(_) => true, - Err(f) => { - if f.kind() == ::std::io::ErrorKind::BrokenPipe { - false - } else { - panic!("{}", f) - } - } - } - ) -); - -#[macro_export] -macro_rules! pipe_println( - ($($args:tt)+) => ( - match writeln!(&mut ::std::io::stdout(), $($args)+) { - Ok(_) => true, - Err(f) => { - if f.kind() == ::std::io::ErrorKind::BrokenPipe { - false - } else { - panic!("{}", f) - } - } - } - ) -); - -#[macro_export] -macro_rules! pipe_write( - ($fd:expr, $($args:tt)+) => ( - match write!($fd, $($args)+) { - Ok(_) => true, - Err(f) => { - if f.kind() == ::std::io::ErrorKind::BrokenPipe { - false - } else { - panic!("{}", f) - } - } - } - ) -); - -#[macro_export] -macro_rules! pipe_writeln( - ($fd:expr, $($args:tt)+) => ( - match writeln!($fd, $($args)+) { - Ok(_) => true, - Err(f) => { - if f.kind() == ::std::io::ErrorKind::BrokenPipe { - false - } else { - panic!("{}", f) - } - } - } - ) -); - -#[macro_export] -macro_rules! pipe_flush( - () => ( - match ::std::io::stdout().flush() { - Ok(_) => true, - Err(f) => { - if f.kind() == ::std::io::ErrorKind::BrokenPipe { - false - } else { - panic!("{}", f) - } - } - } - ); - ($fd:expr) => ( - match $fd.flush() { - Ok(_) => true, - Err(f) => { - if f.kind() == ::std::io::ErrorKind::BrokenPipe { - false - } else { - panic!("{}", f) - } - } - } - ) -); - -#[macro_export] -macro_rules! safe_write( - ($fd:expr, $($args:tt)+) => ( - match write!($fd, $($args)+) { - Ok(_) => {} - Err(f) => panic!(f.to_string()) - } - ) -); - -#[macro_export] -macro_rules! safe_writeln( - ($fd:expr, $($args:tt)+) => ( - match writeln!($fd, $($args)+) { - Ok(_) => {} - Err(f) => panic!(f.to_string()) - } - ) -); - -#[macro_export] -macro_rules! safe_unwrap( - ($exp:expr) => ( - match $exp { - Ok(m) => m, - Err(f) => crash!(1, "{}", f.to_string()) - } - ) -); diff --git a/src/common/utmpx.rs b/src/common/utmpx.rs deleted file mode 100644 index a210dfff4..000000000 --- a/src/common/utmpx.rs +++ /dev/null @@ -1,126 +0,0 @@ -#![allow(non_camel_case_types)] -#![allow(dead_code)] - -extern crate libc; - -pub use self::utmpx::{DEFAULT_FILE,USER_PROCESS,BOOT_TIME,c_utmp}; -#[cfg(target_os = "linux")] -mod utmpx { - use super::libc; - - pub static DEFAULT_FILE: &'static str = "/var/run/utmp"; - - pub const UT_LINESIZE: usize = 32; - pub const UT_NAMESIZE: usize = 32; - pub const UT_IDSIZE: usize = 4; - pub const UT_HOSTSIZE: usize = 256; - - pub const EMPTY: libc::c_short = 0; - pub const RUN_LVL: libc::c_short = 1; - pub const BOOT_TIME: libc::c_short = 2; - pub const NEW_TIME: libc::c_short = 3; - pub const OLD_TIME: libc::c_short = 4; - pub const INIT_PROCESS: libc::c_short = 5; - pub const LOGIN_PROCESS: libc::c_short = 6; - pub const USER_PROCESS: libc::c_short = 7; - pub const DEAD_PROCESS: libc::c_short = 8; - pub const ACCOUNTING: libc::c_short = 9; - - #[repr(C)] - pub struct c_exit_status { - pub e_termination: libc::c_short, - pub e_exit: libc::c_short, - } - - #[repr(C)] - pub struct c_utmp { - pub ut_type: libc::c_short, - pub ut_pid: libc::pid_t, - pub ut_line: [libc::c_char; UT_LINESIZE], - pub ut_id: [libc::c_char; UT_IDSIZE], - - pub ut_user: [libc::c_char; UT_NAMESIZE], - pub ut_host: [libc::c_char; UT_HOSTSIZE], - pub ut_exit: c_exit_status, - pub ut_session: libc::c_long, - pub ut_tv: libc::timeval, - - pub ut_addr_v6: [libc::int32_t; 4], - pub __unused: [libc::c_char; 20], - } -} - -#[cfg(target_os = "macos")] -mod utmpx { - use super::libc; - - pub static DEFAULT_FILE: &'static str = "/var/run/utmpx"; - - pub const UT_LINESIZE: usize = 32; - pub const UT_NAMESIZE: usize = 256; - pub const UT_IDSIZE: usize = 4; - pub const UT_HOSTSIZE: usize = 256; - - pub const EMPTY: libc::c_short = 0; - pub const RUN_LVL: libc::c_short = 1; - pub const BOOT_TIME: libc::c_short = 2; - pub const OLD_TIME: libc::c_short = 3; - pub const NEW_TIME: libc::c_short = 4; - pub const INIT_PROCESS: libc::c_short = 5; - pub const LOGIN_PROCESS: libc::c_short = 6; - pub const USER_PROCESS: libc::c_short = 7; - pub const DEAD_PROCESS: libc::c_short = 8; - pub const ACCOUNTING: libc::c_short = 9; - - #[repr(C)] - pub struct c_exit_status { - pub e_termination: libc::c_short, - pub e_exit: libc::c_short, - } - - #[repr(C)] - pub struct c_utmp { - pub ut_user: [libc::c_char; UT_NAMESIZE], - pub ut_id: [libc::c_char; UT_IDSIZE], - pub ut_line: [libc::c_char; UT_LINESIZE], - pub ut_pid: libc::pid_t, - pub ut_type: libc::c_short, - pub ut_tv: libc::timeval, - pub ut_host: [libc::c_char; UT_HOSTSIZE], - pub __unused: [libc::c_char; 16] - } -} - -#[cfg(target_os = "freebsd")] -mod utmpx { - use super::libc; - - pub static DEFAULT_FILE : &'static str = ""; - - pub const UT_LINESIZE : usize = 16; - pub const UT_NAMESIZE : usize = 32; - pub const UT_IDSIZE : usize = 8; - pub const UT_HOSTSIZE : usize = 128; - - pub const EMPTY : libc::c_short = 0; - pub const BOOT_TIME : libc::c_short = 1; - pub const OLD_TIME : libc::c_short = 2; - pub const NEW_TIME : libc::c_short = 3; - pub const USER_PROCESS : libc::c_short = 4; - pub const INIT_PROCESS : libc::c_short = 5; - pub const LOGIN_PROCESS : libc::c_short = 6; - pub const DEAD_PROCESS : libc::c_short = 7; - pub const SHUTDOWN_TIME : libc::c_short = 8; - - #[repr(C)] - pub struct c_utmp { - pub ut_type : libc::c_short, - pub ut_tv : libc::timeval, - pub ut_id : [libc::c_char; UT_IDSIZE], - pub ut_pid : libc::pid_t, - pub ut_user : [libc::c_char; UT_NAMESIZE], - pub ut_line : [libc::c_char; UT_LINESIZE], - pub ut_host : [libc::c_char; UT_HOSTSIZE], - pub ut_spare : [libc::c_char; 64], - } -} diff --git a/src/common/wide.rs b/src/common/wide.rs deleted file mode 100644 index 189e84438..000000000 --- a/src/common/wide.rs +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of the uutils coreutils package. - * - * (c) Peter Atashian - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -use std::ffi::{OsStr, OsString}; -use std::os::windows::ffi::{OsStrExt, OsStringExt}; -pub trait ToWide { - fn to_wide(&self) -> Vec; - fn to_wide_null(&self) -> Vec; -} -impl ToWide for T where T: AsRef { - fn to_wide(&self) -> Vec { - self.as_ref().encode_wide().collect() - } - fn to_wide_null(&self) -> Vec { - self.as_ref().encode_wide().chain(Some(0)).collect() - } -} -pub trait FromWide { - fn from_wide(wide: &[u16]) -> Self; - fn from_wide_null(wide: &[u16]) -> Self; -} -impl FromWide for String { - fn from_wide(wide: &[u16]) -> String { - OsString::from_wide(wide).to_string_lossy().into_owned() - } - fn from_wide_null(wide: &[u16]) -> String { - let len = wide.iter().take_while(|&&c| c != 0).count(); - OsString::from_wide(&wide[..len]).to_string_lossy().into_owned() - } -} \ No newline at end of file diff --git a/src/cp/Cargo.toml b/src/cp/Cargo.toml deleted file mode 100644 index b443112d6..000000000 --- a/src/cp/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "cp" -version = "0.0.1" -authors = [] - -[lib] -name = "cp" -path = "cp.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/cp/cp.rs b/src/cp/cp.rs deleted file mode 100644 index 3c0fa2944..000000000 --- a/src/cp/cp.rs +++ /dev/null @@ -1,161 +0,0 @@ -#![crate_name = "cp"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Jordy Dickinson - * - * For the full copyright and license information, please view the LICENSE file - * that was distributed with this source code. - */ - -extern crate getopts; - -use getopts::Options; -use std::fs; -use std::io::{ErrorKind, Result, Write}; -use std::path::Path; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[path = "../common/filesystem.rs"] -mod filesystem; - -use filesystem::{canonicalize, CanonicalizeMode, UUPathExt}; - -#[derive(Clone, Eq, PartialEq)] -pub enum Mode { - Copy, - Help, - Version, -} - -static NAME: &'static str = "cp"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(e) => { - show_error!("{}", e); - panic!() - }, - }; - - let usage = opts.usage("Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY."); - let mode = if matches.opt_present("version") { - Mode::Version - } else if matches.opt_present("help") { - Mode::Help - } else { - Mode::Copy - }; - - match mode { - Mode::Copy => copy(matches), - Mode::Help => help(&usage), - Mode::Version => version(), - } - - 0 -} - -fn version() { - println!("{} {}", NAME, VERSION); -} - -fn help(usage: &String) { - let msg = format!("{0} {1}\n\n\ - Usage: {0} SOURCE DEST\n \ - or: {0} SOURCE... DIRECTORY\n \ - or: {0} -t DIRECTORY SOURCE\n\ - \n\ - {2}", NAME, VERSION, usage); - println!("{}", msg); -} - -fn copy(matches: getopts::Matches) { - let sources: Vec = if matches.free.is_empty() { - show_error!("Missing SOURCE argument. Try --help."); - panic!() - } else { - // All but the last argument: - matches.free[..matches.free.len() - 1].iter().map(|arg| arg.clone()).collect() - }; - let dest = if matches.free.len() < 2 { - show_error!("Missing DEST argument. Try --help."); - panic!() - } else { - // Only the last argument: - Path::new(&matches.free[matches.free.len() - 1]) - }; - - assert!(sources.len() >= 1); - - if sources.len() == 1 { - let source = Path::new(&sources[0]); - let same_file = paths_refer_to_same_file(source, dest).unwrap_or_else(|err| { - match err.kind() { - ErrorKind::NotFound => false, - _ => { - show_error!("{}", err); - panic!() - } - } - }); - - if same_file { - show_error!("\"{}\" and \"{}\" are the same file", - source.display(), - dest.display()); - panic!(); - } - - if let Err(err) = fs::copy(source, dest) { - show_error!("{}", err); - panic!(); - } - } else { - if !dest.uu_is_dir() { - show_error!("TARGET must be a directory"); - panic!(); - } - - for src in sources.iter() { - let source = Path::new(&src); - - if !source.uu_is_file() { - show_error!("\"{}\" is not a file", source.display()); - continue; - } - - let mut full_dest = dest.to_path_buf(); - - full_dest.push(source.to_str().unwrap()); - - println!("{}", full_dest.display()); - - let io_result = fs::copy(source, full_dest); - - if let Err(err) = io_result { - show_error!("{}", err); - panic!() - } - } - } -} - -pub fn paths_refer_to_same_file(p1: &Path, p2: &Path) -> Result { - // We have to take symlinks and relative paths into account. - let pathbuf1 = try!(canonicalize(p1, CanonicalizeMode::Normal)); - let pathbuf2 = try!(canonicalize(p2, CanonicalizeMode::Normal)); - - Ok(pathbuf1 == pathbuf2) -} diff --git a/src/cut/Cargo.toml b/src/cut/Cargo.toml deleted file mode 100644 index dc3d30ca9..000000000 --- a/src/cut/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "cut" -version = "0.0.1" -authors = [] - -[lib] -name = "cut" -path = "cut.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/cut/buffer.rs b/src/cut/buffer.rs deleted file mode 100644 index da700513b..000000000 --- a/src/cut/buffer.rs +++ /dev/null @@ -1,151 +0,0 @@ -/* - * This file is part of the uutils coreutils package. - * - * (c) Rolf Morel - * (c) kwantam - * substantially rewritten to use the stdlib BufReader trait - * rather than re-implementing it here. - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use std::io::{BufRead, BufReader, Read, Write}; -use std::io::Result as IoResult; - -#[allow(non_snake_case)] -pub mod Bytes { - use std::io::Write; - - pub trait Select { - fn select(&mut self, bytes: usize, out: Option<&mut W>) -> Selected; - } - - #[derive(PartialEq, Eq, Debug)] - pub enum Selected { - NewlineFound, - Complete(usize), - Partial(usize), - EndOfFile, - } -} - -#[derive(Debug)] -pub struct ByteReader where R: Read { - inner: BufReader, -} - -impl ByteReader { - pub fn new(read: R) -> ByteReader { - ByteReader { - inner: BufReader::with_capacity(4096, read), - } - } -} - -impl Read for ByteReader { - fn read(&mut self, buf: &mut [u8]) -> IoResult { - self.inner.read(buf) - } -} - -impl BufRead for ByteReader { - fn fill_buf(&mut self) -> IoResult<&[u8]> { - self.inner.fill_buf() - } - - fn consume(&mut self, amt: usize) { - self.inner.consume(amt) - } -} - -impl ByteReader { - pub fn consume_line(&mut self) -> usize { - let mut bytes_consumed = 0; - let mut consume_val; - - loop { - { // need filled_buf to go out of scope - let filled_buf = match self.fill_buf() { - Ok(b) => { - if b.len() == 0 { - return bytes_consumed - } else { - b - } - }, - Err(e) => crash!(1, "read error: {}", e), - }; - - match filled_buf.iter().position(|byte| *byte == b'\n') { - Some(idx) => { - consume_val = idx + 1; - bytes_consumed += consume_val; - break; - } - _ => () - } - - consume_val = filled_buf.len(); - } - - bytes_consumed += consume_val; - self.consume(consume_val); - } - - self.consume(consume_val); - return bytes_consumed; - } -} - -impl self::Bytes::Select for ByteReader { - fn select(&mut self, bytes: usize, out: Option<&mut W>) -> Bytes::Selected { - enum SRes { - Comp, - Part, - Newl, - }; - - use self::Bytes::Selected::*; - - let (res, consume_val) = { - let buffer = match self.fill_buf() { - Err(e) => crash!(1, "read error: {}", e), - Ok(b) => b, - }; - - let (res, consume_val) = match buffer.len() { - 0 => return EndOfFile, - buf_used if bytes < buf_used => { - // because the output delimiter should only be placed between - // segments check if the byte after bytes is a newline - let buf_slice = &buffer[0..bytes + 1]; - - match buf_slice.iter().position(|byte| *byte == b'\n') { - Some(idx) => (SRes::Newl, idx+1), - None => (SRes::Comp, bytes), - } - }, - _ => { - match buffer.iter().position(|byte| *byte == b'\n') { - Some(idx) => (SRes::Newl, idx+1), - None => (SRes::Part, buffer.len()), - } - }, - }; - - match out { - Some(out) => pipe_crash_if_err!(1, out.write_all(&buffer[0..consume_val])), - None => (), - } - (res, consume_val) - }; - - self.consume(consume_val); - match res { - SRes::Comp => Complete(consume_val), - SRes::Part => Partial(consume_val), - SRes::Newl => NewlineFound, - } - } -} diff --git a/src/cut/cut.rs b/src/cut/cut.rs deleted file mode 100644 index 1381e115b..000000000 --- a/src/cut/cut.rs +++ /dev/null @@ -1,546 +0,0 @@ -#![crate_name = "cut"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Rolf Morel - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use std::fs::File; -use std::io::{stdout, stdin, BufRead, BufReader, Read, Stdout, Write}; -use std::path::Path; - -use ranges::Range; -use searcher::Searcher; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[path = "../common/filesystem.rs"] -mod filesystem; - -use filesystem::UUPathExt; - -mod buffer; -mod ranges; -mod searcher; - -static NAME: &'static str = "cut"; -static VERSION: &'static str = "1.0.0"; - -struct Options { - out_delim: Option, -} - -struct FieldOptions { - delimiter: String, // one char long, String because of UTF8 representation - out_delimeter: Option, - only_delimited: bool, -} - -enum Mode { - Bytes(Vec, Options), - Characters(Vec, Options), - Fields(Vec, FieldOptions), -} - -fn list_to_ranges(list: &str, complement: bool) -> Result, String> { - if complement { - Range::from_list(list).map(|r| ranges::complement(&r)) - } else { - Range::from_list(list) - } -} - -fn cut_bytes(reader: R, ranges: &Vec, opts: &Options) -> i32 { - use buffer::Bytes::Select; - use buffer::Bytes::Selected::*; - - let mut buf_read = buffer::ByteReader::new(reader); - let mut out = stdout(); - - 'newline: loop { - let mut cur_pos = 1; - let mut print_delim = false; - - for &Range { low, high } in ranges.iter() { - // skip upto low - let orig_pos = cur_pos; - loop { - match buf_read.select(low - cur_pos, None::<&mut Stdout>) { - NewlineFound => { - pipe_crash_if_err!(1, out.write_all(&[b'\n'])); - continue 'newline - } - Complete(len) => { - cur_pos += len; - break - } - Partial(len) => cur_pos += len, - EndOfFile => { - if orig_pos != cur_pos { - pipe_crash_if_err!(1, out.write_all(&[b'\n'])); - } - - break 'newline - } - } - } - - match opts.out_delim { - Some(ref delim) => { - if print_delim { - pipe_crash_if_err!(1, out.write_all(delim.as_bytes())); - } - print_delim = true; - } - None => () - } - - // write out from low to high - loop { - match buf_read.select(high - cur_pos + 1, Some(&mut out)) { - NewlineFound => continue 'newline, - Partial(len) => cur_pos += len, - Complete(_) => { - cur_pos = high + 1; - break - } - EndOfFile => { - if cur_pos != low || low == high { - pipe_crash_if_err!(1, out.write_all(&[b'\n'])); - } - - break 'newline - } - } - } - } - - buf_read.consume_line(); - pipe_crash_if_err!(1, out.write_all(&[b'\n'])); - } - - 0 -} - -fn cut_characters(reader: R, ranges: &Vec, opts: &Options) -> i32 { - let mut buf_in = BufReader::new(reader); - let mut out = stdout(); - let mut buffer = String::new(); - - 'newline: loop { - buffer.clear(); - match buf_in.read_line(&mut buffer) { - Ok(n) if n == 0 => break, - Err(e) => { - if buffer.len() == 0 { - crash!(1, "read error: {}", e); - } - }, - _ => (), - }; - - let line = &buffer[..]; - let mut char_pos = 0; - let mut char_indices = line.char_indices(); - let mut print_delim = false; - let mut low_idx = 0; - - for &Range { low, high } in ranges.iter() { - low_idx = if low - char_pos > 0 { - match char_indices.nth(low - char_pos - 1) { - Some((low_idx, _)) => low_idx, - None => break, - } - } else { - low_idx - }; - - match opts.out_delim { - Some(ref delim) => { - if print_delim { - pipe_crash_if_err!(1, out.write_all(delim.as_bytes())); - } - print_delim = true; - } - None => () - } - - match char_indices.nth(high - low) { - Some((high_idx, _)) => { - let segment = &line.as_bytes()[low_idx..high_idx]; - low_idx = high_idx; - - pipe_crash_if_err!(1, out.write_all(segment)); - } - None => { - let bytes = line.as_bytes(); - let segment = &bytes[low_idx..]; - - pipe_crash_if_err!(1, out.write_all(segment)); - - if line.as_bytes()[bytes.len() - 1] == b'\n' { - continue 'newline - } - } - } - - char_pos = high + 1; - } - pipe_crash_if_err!(1, out.write_all(&[b'\n'])); - } - - 0 -} - -fn cut_fields_delimiter(reader: R, ranges: &Vec, delim: &String, only_delimited: bool, out_delim: &String) -> i32 { - let mut buf_in = BufReader::new(reader); - let mut out = stdout(); - let mut buffer = Vec::new(); - - 'newline: loop { - buffer.clear(); - match buf_in.read_until(b'\n', &mut buffer) { - Ok(n) if n == 0 => break, - Err(e) => { - if buffer.len() == 0 { - crash!(1, "read error: {}", e); - } - }, - _ => (), - } - - let line = &buffer[..]; - let mut fields_pos = 1; - let mut low_idx = 0; - let mut delim_search = Searcher::new(line, delim.as_bytes()).peekable(); - let mut print_delim = false; - - if delim_search.peek().is_none() { - if ! only_delimited { - pipe_crash_if_err!(1, out.write_all(line)); - if line[line.len() - 1] != b'\n' { - pipe_crash_if_err!(1, out.write_all(&[b'\n'])); - } - } - - continue - } - - for &Range { low, high } in ranges.iter() { - if low - fields_pos > 0 { - low_idx = match delim_search.nth(low - fields_pos - 1) { - Some((_, beyond_delim)) => beyond_delim, - None => break - }; - } - - for _ in 0..high - low + 1 { - if print_delim { - pipe_crash_if_err!(1, out.write_all(out_delim.as_bytes())); - } - - match delim_search.next() { - Some((high_idx, next_low_idx)) => { - let segment = &line[low_idx..high_idx]; - - pipe_crash_if_err!(1, out.write_all(segment)); - - print_delim = true; - - low_idx = next_low_idx; - fields_pos = high + 1; - } - None => { - let segment = &line[low_idx..]; - - pipe_crash_if_err!(1, out.write_all(segment)); - - if line[line.len() - 1] == b'\n' { - continue 'newline - } - break - } - } - } - } - - pipe_crash_if_err!(1, out.write_all(&[b'\n'])); - } - - 0 -} - -fn cut_fields(reader: R, ranges: &Vec, opts: &FieldOptions) -> i32 { - match opts.out_delimeter { - Some(ref o_delim) => { - return cut_fields_delimiter(reader, ranges, &opts.delimiter, - opts.only_delimited, o_delim); - } - None => () - } - - let mut buf_in = BufReader::new(reader); - let mut out = stdout(); - let mut buffer = Vec::new(); - - 'newline: loop { - buffer.clear(); - match buf_in.read_until(b'\n', &mut buffer) { - Ok(n) if n == 0 => break, - Err(e) => { - if buffer.len() == 0 { - crash!(1, "read error: {}", e); - } - }, - _ => (), - } - - let line = &buffer[..]; - let mut fields_pos = 1; - let mut low_idx = 0; - let mut delim_search = Searcher::new(line, opts.delimiter.as_bytes()).peekable(); - let mut print_delim = false; - - if delim_search.peek().is_none() { - if ! opts.only_delimited { - pipe_crash_if_err!(1, out.write_all(line)); - if line[line.len() - 1] != b'\n' { - pipe_crash_if_err!(1, out.write_all(&[b'\n'])); - } - } - - continue - } - - for &Range { low, high } in ranges.iter() { - if low - fields_pos > 0 { - low_idx = match delim_search.nth(low - fields_pos - 1) { - Some((_, beyond_delim)) => beyond_delim, - None => break - }; - } - - if print_delim { - if low_idx >= opts.delimiter.as_bytes().len() { - low_idx -= opts.delimiter.as_bytes().len(); - } - } - - match delim_search.nth(high - low) { - Some((high_idx, next_low_idx)) => { - let segment = &line[low_idx..high_idx]; - - pipe_crash_if_err!(1, out.write_all(segment)); - - print_delim = true; - low_idx = next_low_idx; - fields_pos = high + 1; - } - None => { - let segment = &line[low_idx..line.len()]; - - pipe_crash_if_err!(1, out.write_all(segment)); - - if line[line.len() - 1] == b'\n' { - continue 'newline - } - break - } - } - } - - pipe_crash_if_err!(1, out.write_all(&[b'\n'])); - } - - 0 -} - -fn cut_files(mut filenames: Vec, mode: Mode) -> i32 { - let mut stdin_read = false; - let mut exit_code = 0; - - if filenames.len() == 0 { filenames.push("-".to_string()); } - - for filename in filenames.iter() { - if filename == "-" { - if stdin_read { continue } - - exit_code |= match mode { - Mode::Bytes(ref ranges, ref opts) => cut_bytes(stdin(), ranges, opts), - Mode::Characters(ref ranges, ref opts) => cut_characters(stdin(), ranges, opts), - Mode::Fields(ref ranges, ref opts) => cut_fields(stdin(), ranges, opts), - }; - - stdin_read = true; - } else { - let path = Path::new(&filename[..]); - - if !path.uu_exists() { - show_error!("{}: No such file or directory", filename); - continue - } - - let file = match File::open(&path) { - Ok(f) => f, - Err(e) => { - show_error!("opening '{}': {}", &filename[..], e); - continue - } - }; - - exit_code |= match mode { - Mode::Bytes(ref ranges, ref opts) => cut_bytes(file, ranges, opts), - Mode::Characters(ref ranges, ref opts) => cut_characters(file, ranges, opts), - Mode::Fields(ref ranges, ref opts) => cut_fields(file, ranges, opts), - }; - } - } - - exit_code -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optopt("b", "bytes", "select only these bytes", "LIST"); - opts.optopt("c", "characters", "select only these characters", "LIST"); - opts.optopt("d", "delimiter", "use DELIM instead of TAB for field delimiter", "DELIM"); - opts.optopt("f", "fields", "select only these fields; also print any line that contains no delimiter character, unless the -s option is specified", "LIST"); - opts.optflag("n", "", "(ignored)"); - opts.optflag("", "complement", "complement the set of selected bytes, characters or fields"); - opts.optflag("s", "only-delimited", "do not print lines not containing delimiters"); - opts.optopt("", "output-delimiter", "use STRING as the output delimiter the default is to use the input delimiter", "STRING"); - opts.optflag("", "help", "display this help and exit"); - opts.optflag("", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - show_error!("Invalid options\n{}", f); - return 1; - } - }; - - if matches.opt_present("help") { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {0} OPTION... [FILE]...", NAME); - println!(""); - println!("{}", opts.usage("Print selected parts of lines from each FILE to standard output.")); - println!(""); - println!("Use one, and only one of -b, -c or -f. Each LIST is made up of one"); - println!("range, or many ranges separated by commas. Selected input is written"); - println!("in the same order that it is read, and is written exactly once."); - println!("Each range is one of:"); - println!(""); - println!(" N N'th byte, character or field, counted from 1"); - println!(" N- from N'th byte, character or field, to end of line"); - println!(" N-M from N'th to M'th (included) byte, character or field"); - println!(" -M from first to M'th (included) byte, character or field"); - println!(""); - println!("With no FILE, or when FILE is -, read standard input."); - return 0; - } - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - let complement = matches.opt_present("complement"); - - let mode_parse = match (matches.opt_str("bytes"), - matches.opt_str("characters"), - matches.opt_str("fields")) { - (Some(byte_ranges), None, None) => { - list_to_ranges(&byte_ranges[..], complement) - .map(|ranges| Mode::Bytes(ranges, Options { out_delim: matches.opt_str("output-delimiter") })) - } - (None, Some(char_ranges), None) => { - list_to_ranges(&char_ranges[..], complement) - .map(|ranges| Mode::Characters(ranges, Options { out_delim: matches.opt_str("output-delimiter") })) - } - (None, None, Some(field_ranges)) => { - list_to_ranges(&field_ranges[..], complement).and_then(|ranges| - { - let out_delim = match matches.opt_str("output-delimiter") { - Some(s) => { - if s.len() == 0 { - Some("\0".to_string()) - } else { - Some(s) - } - }, - None => None, - }; - - let only_delimited = matches.opt_present("only-delimited"); - - match matches.opt_str("delimiter") { - Some(delim) => { - if delim.chars().count() > 1 { - Err("the delimiter must be a single character, or the empty string for null".to_string()) - } else { - let delim = if delim.len() == 0 { - "\0".to_string() - } else { - delim - }; - - Ok(Mode::Fields(ranges, - FieldOptions { - delimiter: delim, - out_delimeter: out_delim, - only_delimited: only_delimited - })) - } - } - None => Ok(Mode::Fields(ranges, - FieldOptions { - delimiter: "\t".to_string(), - out_delimeter: out_delim, - only_delimited: only_delimited - })) - } - } - ) - } - (ref b, ref c, ref f) if b.is_some() || c.is_some() || f.is_some() => { - Err("only one type of list may be specified".to_string()) - } - _ => Err("you must specify a list of bytes, characters, or fields".to_string()) - }; - - let mode_parse = match mode_parse { - Err(_) => mode_parse, - Ok(mode) => { - match mode { - Mode::Bytes(_, _) | Mode::Characters(_, _) if matches.opt_present("delimiter") => - Err("an input delimiter may be specified only when operating on fields".to_string()), - Mode::Bytes(_, _) | Mode::Characters(_, _) if matches.opt_present("only-delimited") => - Err("suppressing non-delimited lines makes sense only when operating on fields".to_string()), - _ => Ok(mode), - } - } - }; - - match mode_parse { - Ok(mode) => cut_files(matches.free, mode), - Err(err_msg) => { - show_error!("{}\n\ - Try '{} --help' for more information", - err_msg, args[0]); - 1 - } - } -} diff --git a/src/cut/ranges.rs b/src/cut/ranges.rs deleted file mode 100644 index 3e5bfd3d5..000000000 --- a/src/cut/ranges.rs +++ /dev/null @@ -1,133 +0,0 @@ -/* - * This file is part of the uutils coreutils package. - * - * (c) Rolf Morel - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use std::str::FromStr; - -#[derive(PartialEq,Eq,PartialOrd,Ord,Debug)] -pub struct Range { - pub low: usize, - pub high: usize, -} - -impl FromStr for Range { - type Err = &'static str; - - fn from_str(s: &str) -> Result { - use std::usize::MAX; - - let mut parts = s.splitn(2, '-'); - - let field = "fields and positions are numbered from 1"; - let order = "high end of range less than low end"; - let inval = "failed to parse range"; - - match (parts.next(), parts.next()) { - (Some(nm), None) => { - if let Ok(nm) = nm.parse::() { - if nm > 0 { Ok(Range{ low: nm, high: nm}) } else { Err(field) } - } else { - Err(inval) - } - } - (Some(n), Some(m)) if m.len() == 0 => { - if let Ok(low) = n.parse::() { - if low > 0 { Ok(Range{ low: low, high: MAX}) } else { Err(field) } - } else { - Err(inval) - } - } - (Some(n), Some(m)) if n.len() == 0 => { - if let Ok(high) = m.parse::() { - if high > 0 { Ok(Range{ low: 1, high: high}) } else { Err(field) } - } else { - Err(inval) - } - } - (Some(n), Some(m)) => { - match (n.parse::(), m.parse::()) { - (Ok(low), Ok(high)) => { - if low > 0 && low <= high { - Ok(Range { low: low, high: high }) - } else if low == 0 { - Err(field) - } else { - Err(order) - } - }, - _ => Err(inval), - } - } - _ => unreachable!() - } - } -} - -impl Range { - pub fn from_list(list: &str) -> Result, String> { - use std::cmp::max; - - let mut ranges : Vec = vec!(); - - for item in list.split(',') { - match FromStr::from_str(item) { - Ok(range_item) => ranges.push(range_item), - Err(e)=> return Err(format!("range '{}' was invalid: {}", item, e)) - } - } - - ranges.sort(); - - // merge overlapping ranges - for i in 0..ranges.len() { - let j = i + 1; - - while j < ranges.len() && ranges[j].low <= ranges[i].high { - let j_high = ranges.remove(j).high; - ranges[i].high = max(ranges[i].high, j_high); - } - } - - Ok(ranges) - } -} - -pub fn complement(ranges: &Vec) -> Vec { - use std::usize; - - let mut complements = Vec::with_capacity(ranges.len() + 1); - - if ranges.len() > 0 && ranges[0].low > 1 { - complements.push(Range { low: 1, high: ranges[0].low - 1 }); - } - - let mut ranges_iter = ranges.iter().peekable(); - loop { - match (ranges_iter.next(), ranges_iter.peek()) { - (Some(left), Some(right)) => { - if left.high + 1 != right.low { - complements.push(Range { - low: left.high + 1, - high: right.low - 1 - }); - } - } - (Some(last), None) => { - if last.high < usize::MAX { - complements.push(Range { - low: last.high + 1, - high: usize::MAX - }); - } - } - _ => break - } - } - - complements -} diff --git a/src/cut/searcher.rs b/src/cut/searcher.rs deleted file mode 100644 index 707a97f3a..000000000 --- a/src/cut/searcher.rs +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of the uutils coreutils package. - * - * (c) Rolf Morel - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -#[derive(Clone)] -pub struct Searcher<'a> { - haystack: &'a [u8], - needle: &'a [u8], - position: usize -} - -impl<'a> Searcher<'a> { - pub fn new(haystack: &'a [u8], needle: &'a [u8]) -> Searcher<'a> { - Searcher { - haystack: haystack, - needle: needle, - position: 0 - } - } -} - -impl<'a> Iterator for Searcher<'a> { - type Item = (usize, usize); - - fn next(&mut self) -> Option<(usize, usize)> { - if self.needle.len() == 1 { - for offset in self.position..self.haystack.len() { - if self.haystack[offset] == self.needle[0] { - self.position = offset + 1; - return Some((offset, offset + 1)); - } - } - - self.position = self.haystack.len(); - return None; - } - - while self.position + self.needle.len() <= self.haystack.len() { - if &self.haystack[self.position..self.position + self.needle.len()] == self.needle { - let match_pos = self.position; - self.position += self.needle.len(); - return Some((match_pos, match_pos + self.needle.len())); - } else { - self.position += 1; - } - } - None - } -} diff --git a/src/dirname/Cargo.toml b/src/dirname/Cargo.toml deleted file mode 100644 index 8c4e65c75..000000000 --- a/src/dirname/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "dirname" -version = "0.0.1" -authors = [] - -[lib] -name = "dirname" -path = "dirname.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/dirname/dirname.rs b/src/dirname/dirname.rs deleted file mode 100644 index 0ad6f68e5..000000000 --- a/src/dirname/dirname.rs +++ /dev/null @@ -1,70 +0,0 @@ -#![crate_name = "dirname"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Derek Chiang - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; - -use std::path::Path; - -static NAME: &'static str = "dirname"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - opts.optflag("z", "zero", "separate output with NUL rather than newline"); - opts.optflag("", "help", "display this help and exit"); - opts.optflag("", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => panic!("Invalid options\n{}", f) - }; - - if matches.opt_present("help") { - let msg = format!("{0} {1} - strip last component from file name - -Usage: - {0} [OPTION] NAME... - -Output each NAME with its last non-slash component and trailing slashes -removed; if NAME contains no /'s, output '.' (meaning the current -directory).", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - return 0; - } - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - let separator = match matches.opt_present("zero") { - true => "\0", - false => "\n" - }; - - if !matches.free.is_empty() { - for path in matches.free.iter() { - let p = Path::new(path); - let d = p.parent().unwrap().to_str(); - if d.is_some() { - print!("{}", d.unwrap()); - } - print!("{}", separator); - } - } else { - println!("{0}: missing operand", NAME); - println!("Try '{0} --help' for more information.", NAME); - return 1; - } - - 0 -} diff --git a/src/du/Cargo.toml b/src/du/Cargo.toml deleted file mode 100644 index dd6851c34..000000000 --- a/src/du/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "du" -version = "0.0.1" -authors = [] - -[lib] -name = "du" -path = "du.rs" - -[dependencies] -getopts = "*" -libc = "*" -time = "*" diff --git a/src/du/deps.mk b/src/du/deps.mk deleted file mode 100644 index bc0c2cf05..000000000 --- a/src/du/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += time kernel32 winapi diff --git a/src/du/du.rs b/src/du/du.rs deleted file mode 100644 index b80d1f193..000000000 --- a/src/du/du.rs +++ /dev/null @@ -1,398 +0,0 @@ -#![crate_name = "du"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Derek Chiang - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -#![allow(non_snake_case)] - -extern crate getopts; -extern crate libc; -extern crate time; - -use std::fs; -use std::io::{stderr, Write}; -use std::os::unix::fs::MetadataExt; -use std::path::PathBuf; -use std::sync::Arc; -use time::Timespec; -use std::sync::mpsc::channel; -use std::thread; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "du"; -static VERSION: &'static str = "1.0.0"; - -struct Options { - all: bool, - program_name: String, - max_depth: Option, - total: bool, - separate_dirs: bool, -} - -struct Stat { - path: PathBuf, - is_dir: bool, - size: u64, - blocks: u64, - nlink: u64, - created: u64, - accessed: u64, - modified: u64, -} - -impl Stat { - fn new(path: &PathBuf) -> Stat { - let metadata = safe_unwrap!(fs::metadata(path)); - Stat { - path: path.clone(), - is_dir: metadata.is_dir(), - size: metadata.len(), - blocks: metadata.blocks() as u64, - nlink: metadata.nlink() as u64, - created: metadata.mtime() as u64, - accessed: metadata.atime() as u64, - modified: metadata.mtime() as u64 - } - } -} - -// this takes `my_stat` to avoid having to stat files multiple times. -fn du(path: &PathBuf, mut my_stat: Stat, options: Arc, depth: usize) -> Vec> { - let mut stats = vec!(); - let mut futures = vec!(); - - if my_stat.is_dir { - let read = match fs::read_dir(path) { - Ok(read) => read, - Err(e) => { - safe_writeln!(stderr(), "{}: cannot read directory ‘{}‘: {}", - options.program_name, path.display(), e); - return vec!(Arc::new(my_stat)) - } - }; - - for f in read.into_iter() { - let entry = f.unwrap(); - let this_stat = Stat::new(&entry.path()); - if this_stat.is_dir { - let oa_clone = options.clone(); - let (tx, rx) = channel(); - thread::spawn(move || { - let result = du(&entry.path(), this_stat, oa_clone, depth + 1); - tx.send(result) - }); - futures.push(rx); - } else { - my_stat.size += this_stat.size; - my_stat.blocks += this_stat.blocks; - if options.all { - stats.push(Arc::new(this_stat)) - } - } - } - } - - for rx in futures.iter_mut() { - for stat in rx.recv().unwrap().into_iter().rev() { - if !options.separate_dirs && stat.path.parent().unwrap().to_path_buf() == my_stat.path { - my_stat.size += stat.size; - my_stat.blocks += stat.blocks; - } - if options.max_depth == None || depth < options.max_depth.unwrap() { - stats.push(stat.clone()); - } - } - } - - stats.push(Arc::new(my_stat)); - - stats -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - // In task - opts.optflag("a", "all", " write counts for all files, not just directories"); - // In main - opts.optflag("", "apparent-size", "print apparent sizes, rather than disk usage; - although the apparent size is usually smaller, it may be larger due to holes - in ('sparse') files, internal fragmentation, indirect blocks, and the like"); - // In main - opts.optopt("B", "block-size", "scale sizes by SIZE before printing them. - E.g., '-BM' prints sizes in units of 1,048,576 bytes. See SIZE format below.", - "SIZE"); - // In main - opts.optflag("b", "bytes", "equivalent to '--apparent-size --block-size=1'"); - // In main - opts.optflag("c", "total", "produce a grand total"); - // In task - // opts.optflag("D", "dereference-args", "dereference only symlinks that are listed - // on the command line"), - // In main - // opts.optopt("", "files0-from", "summarize disk usage of the NUL-terminated file - // names specified in file F; - // If F is - then read names from standard input", "F"), - // // In task - // opts.optflag("H", "", "equivalent to --dereference-args (-D)"), - // In main - opts.optflag("h", "human-readable", "print sizes in human readable format (e.g., 1K 234M 2G)"); - // In main - opts.optflag("", "si", "like -h, but use powers of 1000 not 1024"); - // In main - opts.optflag("k", "", "like --block-size=1K"); - // In task - opts.optflag("l", "count-links", "count sizes many times if hard linked"); - // // In main - opts.optflag("m", "", "like --block-size=1M"); - // // In task - // opts.optflag("L", "dereference", "dereference all symbolic links"), - // // In task - // opts.optflag("P", "no-dereference", "don't follow any symbolic links (this is the default)"), - // // In main - opts.optflag("0", "null", "end each output line with 0 byte rather than newline"); - // In main - opts.optflag("S", "separate-dirs", "do not include size of subdirectories"); - // In main - opts.optflag("s", "summarize", "display only a total for each argument"); - // // In task - // opts.optflag("x", "one-file-system", "skip directories on different file systems"), - // // In task - // opts.optopt("X", "exclude-from", "exclude files that match any pattern in FILE", "FILE"), - // // In task - // opts.optopt("", "exclude", "exclude files that match PATTERN", "PATTERN"), - // In main - opts.optopt("d", "max-depth", "print the total for a directory (or file, with --all) - only if it is N or fewer levels below the command - line argument; --max-depth=0 is the same as --summarize", "N"); - // In main - opts.optflagopt("", "time", "show time of the last modification of any file in the - directory, or any of its subdirectories. If WORD is given, show time as WORD instead of modification time: - atime, access, use, ctime or status", "WORD"); - // In main - opts.optopt("", "time-style", "show times using style STYLE: - full-iso, long-iso, iso, +FORMAT FORMAT is interpreted like 'date'", "STYLE"); - opts.optflag("", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - show_error!("Invalid options\n{}", f); - return 1; - } - }; - - if matches.opt_present("help") { - println!("{program} {version} - estimate file space usage - -Usage - {program} [OPTION]... [FILE]... - {program} [OPTION]... --files0-from=F - -{usage} - -Display values are in units of the first available SIZE from ---block-size, and the DU_BLOCK_SIZE, BLOCK_SIZE and BLOCKSIZE environ‐ -ment variables. Otherwise, units default to 1024 bytes (or 512 if -POSIXLY_CORRECT is set). - -SIZE is an integer and optional unit (example: 10M is 10*1024*1024). -Units are K, M, G, T, P, E, Z, Y (powers of 1024) or KB, MB, ... (pow‐ -ers of 1000).", - program = NAME, - version = VERSION, - usage = opts.usage("Summarize disk usage of each FILE, recursively for directories.")); - return 0; - } else if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - let summarize = matches.opt_present("summarize"); - - let max_depth_str = matches.opt_str("max-depth"); - let max_depth = max_depth_str.as_ref().and_then(|s| s.parse::().ok()); - match (max_depth_str, max_depth) { - (Some(ref s), _) if summarize => { - show_error!("summarizing conflicts with --max-depth={}", *s); - return 1; - } - (Some(ref s), None) => { - show_error!("invalid maximum depth '{}'", *s); - return 1; - } - (Some(_), Some(_)) | (None, _) => { /* valid */ } - } - - let options = Options { - all: matches.opt_present("all"), - program_name: NAME.to_string(), - max_depth: max_depth, - total: matches.opt_present("total"), - separate_dirs: matches.opt_present("S"), - }; - - let strs = if matches.free.is_empty() {vec!("./".to_string())} else {matches.free.clone()}; - - let options_arc = Arc::new(options); - - let MB = match matches.opt_present("si") { - true => 1000 * 1000, - false => 1024 * 1024, - }; - let KB = match matches.opt_present("si") { - true => 1000, - false => 1024, - }; - - let block_size = match matches.opt_str("block-size") { - Some(s) => { - let mut found_number = false; - let mut found_letter = false; - let mut numbers = String::new(); - let mut letters = String::new(); - for c in s.chars() { - if found_letter && c.is_digit(10) || !found_number && !c.is_digit(10) { - show_error!("invalid --block-size argument '{}'", s); - return 1; - } else if c.is_digit(10) { - found_number = true; - numbers.push(c); - } else if c.is_alphabetic() { - found_letter = true; - letters.push(c); - } - } - let number = numbers.parse::().unwrap(); - let multiple = match &letters[..] { - "K" => 1024u64.pow(1), "M" => 1024u64.pow(2), - "G" => 1024u64.pow(3), "T" => 1024u64.pow(4), - "P" => 1024u64.pow(5), "E" => 1024u64.pow(6), - "Z" => 1024u64.pow(7), "Y" => 1024u64.pow(8), - "KB" => 1000u64.pow(1), "MB" => 1000u64.pow(2), - "GB" => 1000u64.pow(3), "TB" => 1000u64.pow(4), - "PB" => 1000u64.pow(5), "EB" => 1000u64.pow(6), - "ZB" => 1000u64.pow(7), "YB" => 1000u64.pow(8), - _ => { - show_error!("invalid --block-size argument '{}'", s); - return 1; - } - }; - number * multiple - }, - None => 1024 - }; - - let convert_size = |size: u64| -> String { - if matches.opt_present("human-readable") || matches.opt_present("si") { - if size >= MB { - format!("{:.1}M", (size as f64) / (MB as f64)) - } else if size >= KB { - format!("{:.1}K", (size as f64) / (KB as f64)) - } else { - format!("{}B", size) - } - } else if matches.opt_present("k") { - format!("{}", ((size as f64) / (KB as f64)).ceil()) - } else if matches.opt_present("m") { - format!("{}", ((size as f64) / (MB as f64)).ceil()) - } else { - format!("{}", ((size as f64) / (block_size as f64)).ceil()) - } - }; - - let time_format_str = match matches.opt_str("time-style") { - Some(s) => { - match &s[..] { - "full-iso" => "%Y-%m-%d %H:%M:%S.%f %z", - "long-iso" => "%Y-%m-%d %H:%M", - "iso" => "%Y-%m-%d", - _ => { - show_error!("invalid argument '{}' for 'time style' -Valid arguments are: -- 'full-iso' -- 'long-iso' -- 'iso' -Try '{} --help' for more information.", s, NAME); - return 1; - } - } - }, - None => "%Y-%m-%d %H:%M" - }; - - let line_separator = match matches.opt_present("0") { - true => "\0", - false => "\n", - }; - - let mut grand_total = 0; - for path_str in strs.into_iter() { - let path = PathBuf::from(path_str); - let iter = du(&path, Stat::new(&path), options_arc.clone(), 0).into_iter(); - let (_, len) = iter.size_hint(); - let len = len.unwrap(); - for (index, stat) in iter.enumerate() { - let size = match matches.opt_present("apparent-size") { - true => stat.nlink * stat.size, - // C's stat is such that each block is assume to be 512 bytes - // See: http://linux.die.net/man/2/stat - false => stat.blocks * 512, - }; - if matches.opt_present("time") { - let tm = { - let (secs, nsecs) = { - let time = match matches.opt_str("time") { - Some(s) => match &s[..] { - "accessed" => stat.accessed, - "created" => stat.created, - "modified" => stat.modified, - _ => { - show_error!("invalid argument 'modified' for '--time' - Valid arguments are: - - 'accessed', 'created', 'modified' - Try '{} --help' for more information.", NAME); - return 1; - } - }, - None => stat.modified - }; - ((time / 1000) as i64, (time % 1000 * 1000000) as i32) - }; - time::at(Timespec::new(secs, nsecs)) - }; - if !summarize || (summarize && index == len-1) { - let time_str = tm.strftime(time_format_str).unwrap(); - print!("{}\t{}\t{}{}", convert_size(size), time_str, stat.path.display(), line_separator); - } - } else { - if !summarize || (summarize && index == len-1) { - print!("{}\t{}{}", convert_size(size), stat.path.display(), line_separator); - } - } - if options_arc.total && index == (len - 1) { - // The last element will be the total size of the the path under - // path_str. We add it to the grand total. - grand_total += size; - } - } - } - - if options_arc.total { - print!("{}\ttotal", convert_size(grand_total)); - print!("{}", line_separator); - } - - 0 -} diff --git a/src/echo/Cargo.toml b/src/echo/Cargo.toml deleted file mode 100644 index 1e56ce491..000000000 --- a/src/echo/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "echo" -version = "0.0.1" -authors = [] - -[lib] -name = "echo" -path = "echo.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/echo/echo.rs b/src/echo/echo.rs deleted file mode 100644 index f7e9bae2b..000000000 --- a/src/echo/echo.rs +++ /dev/null @@ -1,254 +0,0 @@ -#![crate_name = "echo"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Derek Chiang - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use std::io::Write; -use std::str::from_utf8; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[allow(dead_code)] -static NAME: &'static str = "echo"; -static VERSION: &'static str = "1.0.0"; - -#[derive(Clone)] -struct EchoOptions { - newline: bool, - escape: bool -} - -#[inline(always)] -fn to_char(bytes: &Vec, base: u32) -> char { - usize::from_str_radix(from_utf8(bytes.as_ref()).unwrap(), base).unwrap() as u8 as char -} - -#[inline(always)] -fn isxdigit(c: u8) -> bool { - match c as char { - '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | - '8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' => true, - _ => false - } -} - -#[inline(always)] -fn isodigit(c: u8) -> bool { - match c as char { - '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' => true, - _ => false - } -} - -fn convert_str(string: &[u8], index: usize, base: u32) -> (char, usize) { - let (max_digits, is_legal_digit) : (usize, fn(u8) -> bool) = match base { - 8 => (3, isodigit), - 16 => (2, isxdigit), - _ => panic!(), - }; - - let mut bytes = vec!(); - for offset in 0usize .. max_digits { - if string.len() <= index + offset as usize { - break; - } - let c = string[index + offset as usize]; - if is_legal_digit(c) { - bytes.push(c as u8); - } else { - break; - } - } - - if bytes.len() == 0 { - (' ', 0) - } else { - (to_char(&bytes, base), bytes.len()) - } -} - -fn parse_options(args: Vec, options: &mut EchoOptions) -> Option> { - let mut echo_args = vec!(); - 'argloop: for arg in args.into_iter().skip(1) { - match arg.as_ref() { - "--help" | "-h" => { - print_help(); - return None; - } - "--version" | "-V" => { - print_version(); - return None; - } - "-n" => options.newline = true, - "-e" => options.escape = true, - "-E" => options.escape = false, - _ => { - if arg.len() > 1 && arg.chars().next().unwrap_or('_') == '-' { - let mut newopts = options.clone(); - for ch in arg.chars().skip(1) { - match ch { - 'h' => { - print_help(); - return None; - } - 'V' => { - print_version(); - return None; - } - 'n' => newopts.newline = true, - 'e' => newopts.escape = true, - 'E' => newopts.escape = false, - _ => { - echo_args.push(arg.clone()); - continue 'argloop; - } - } - } - *options = newopts; - } else { - echo_args.push(arg); - } - } - } - } - Some(echo_args) -} - -fn print_help() { - let mut opts = getopts::Options::new(); - opts.optflag("n", "", "do not output the trailing newline"); - opts.optflag("e", "", "enable interpretation of backslash escapes"); - opts.optflag("E", "", "disable interpretation of backslash escapes (default)"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let msg = format!("{0} {1} - display a line of text - -Usage: - {0} [SHORT-OPTION]... [STRING]... - {0} LONG-OPTION - -Echo the STRING(s) to standard output. -If -e is in effect, the following sequences are recognized: - -\\\\ backslash -\\a alert (BEL) -\\b backspace -\\c produce no further output -\\e escape -\\f form feed -\\n new line -\\r carriage return -\\t horizontal tab -\\v vertical tab -\\0NNN byte with octal value NNN (1 to 3 digits) -\\xHH byte with hexadecimal value HH (1 to 2 digits)", NAME, VERSION); - - print!("{}", opts.usage(&msg)); -} - -fn print_version() { - println!("{} {}", NAME, VERSION); -} - -pub fn uumain(args: Vec) -> i32 { - let mut options = EchoOptions { - newline: false, - escape: false - }; - - let free = match parse_options(args, &mut options) { - Some(vec) => vec, - None => return 0 - }; - - if !free.is_empty() { - let string = free.join(" "); - if options.escape { - let mut prev_was_slash = false; - let mut iter = string.chars().enumerate(); - loop { - match iter.next() { - Some((index, c)) => { - if !prev_was_slash { - if c != '\\' { - print!("{}", c); - } else { - prev_was_slash = true; - } - } else { - prev_was_slash = false; - match c { - '\\' => print!("\\"), - 'a' => print!("\x07"), - 'b' => print!("\x08"), - 'c' => break, - 'e' => print!("\x1B"), - 'f' => print!("\x0C"), - 'n' => print!("\n"), - 'r' => print!("\r"), - 't' => print!("\t"), - 'v' => print!("\x0B"), - 'x' => { - let (c, num_char_used) = convert_str(string.as_bytes(), index + 1, 16); - if num_char_used == 0 { - print!("\\x"); - } else { - print!("{}", c); - for _ in 0 .. num_char_used { - iter.next(); // consume used characters - } - } - }, - '0' => { - let (c, num_char_used) = convert_str(string.as_bytes(), index + 1, 8); - if num_char_used == 0 { - print!("\0"); - } else { - print!("{}", c); - for _ in 0 .. num_char_used { - iter.next(); // consume used characters - } - } - } - _ => { - let (esc_c, num_char_used) = convert_str(string.as_bytes(), index, 8); - if num_char_used == 0 { - print!("\\{}", c); - } else { - print!("{}", esc_c); - for _ in 1 .. num_char_used { - iter.next(); // consume used characters - } - } - } - } - } - } - None => break - } - } - } else { - print!("{}", string); - } - } - - if options.newline { - pipe_flush!(); - } else { - println!("") - } - - 0 -} diff --git a/src/env/Cargo.toml b/src/env/Cargo.toml deleted file mode 100644 index 69d049a76..000000000 --- a/src/env/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "env" -version = "0.0.1" -authors = [] - -[lib] -name = "env" -path = "env.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/env/env.rs b/src/env/env.rs deleted file mode 100644 index 89fc38718..000000000 --- a/src/env/env.rs +++ /dev/null @@ -1,207 +0,0 @@ -#![crate_name = "env"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/* last synced with: env (GNU coreutils) 8.13 */ - -#![allow(non_camel_case_types)] - -use std::env; -use std::io::Write; -use std::process::Command; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "env"; -static VERSION: &'static str = "1.0.0"; - -struct options { - ignore_env: bool, - null: bool, - unsets: Vec, - sets: Vec<(String, String)>, - program: Vec -} - -fn usage() { - println!("Usage: {} [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]", NAME); - println!("Set each NAME to VALUE in the environment and run COMMAND\n"); - println!("Possible options are:"); - println!(" -i --ignore-environment\t start with an empty environment"); - println!(" -0 --null \t end each output line with a 0 byte rather than newline"); - println!(" -u --unset NAME \t remove variable from the environment"); - println!(" -h --help \t display this help and exit"); - println!(" -V --version \t output version information and exit\n"); - println!("A mere - implies -i. If no COMMAND, print the resulting environment"); -} - -fn version() { - println!("{} {}", NAME, VERSION); -} - -// print name=value env pairs on screen -// if null is true, separate pairs with a \0, \n otherwise -fn print_env(null: bool) { - for (n, v) in env::vars() { - print!("{}={}{}", n, v, if null { '\0' } else { '\n' }); - } -} - -pub fn uumain(args: Vec) -> i32 { - // to handle arguments the same way than GNU env, we can't use getopts - let mut opts = Box::new(options { - ignore_env: false, - null: false, - unsets: vec!(), - sets: vec!(), - program: vec!() - }); - - let mut wait_cmd = false; - let mut iter = args.iter(); - iter.next(); // skip program - let mut item = iter.next(); - - // the for loop doesn't work here, - // because we need sometines to read 2 items forward, - // and the iter can't be borrowed twice - while item != None { - let opt = item.unwrap(); - - if wait_cmd { - // we still accept NAME=VAL here but not other options - let mut sp = opt.splitn(2, '='); - let name = sp.next(); - let value = sp.next(); - - match (name, value) { - (Some(n), Some(v)) => { - opts.sets.push((n.to_string(), v.to_string())); - } - _ => { - // read the program now - opts.program.push(opt.to_string()); - break; - } - } - } else if opt.starts_with("--") { - match opt.as_ref() { - "--help" => { usage(); return 0; } - "--version" => { version(); return 0; } - - "--ignore-environment" => opts.ignore_env = true, - "--null" => opts.null = true, - "--unset" => { - let var = iter.next(); - - match var { - None => println!("{}: this option requires an argument: {}", NAME, opt), - Some(s) => opts.unsets.push(s.to_string()) - } - } - - _ => { - println!("{}: invalid option \"{}\"", NAME, *opt); - println!("Type \"{} --help\" for detailed informations", NAME); - return 1; - } - } - } else if opt.starts_with("-") { - if opt.len() == 1 { - // implies -i and stop parsing opts - wait_cmd = true; - opts.ignore_env = true; - continue; - } - - let mut chars = opt.chars(); - chars.next(); - - for c in chars { - // short versions of options - match c { - 'h' => { usage(); return 0; } - 'V' => { version(); return 0; } - 'i' => opts.ignore_env = true, - '0' => opts.null = true, - 'u' => { - let var = iter.next(); - - match var { - None => println!("{}: this option requires an argument: {}", NAME, opt), - Some(s) => opts.unsets.push(s.to_string()) - } - } - _ => { - println!("{}: illegal option -- {}", NAME, c); - println!("Type \"{} --help\" for detailed informations", NAME); - return 1; - } - } - } - } else { - // is it a NAME=VALUE like opt ? - let mut sp = opt.splitn(2, "="); - let name = sp.next(); - let value = sp.next(); - - match (name, value) { - (Some(n), Some(v)) => { - // yes - opts.sets.push((n.to_string(), v.to_string())); - wait_cmd = true; - } - // no, its a program-like opt - _ => { - opts.program.push(opt.to_string()); - break; - } - } - } - - item = iter.next(); - } - - // read program arguments - for opt in iter { - opts.program.push(opt.to_string()); - } - - if opts.ignore_env { - for (ref name, _) in env::vars() { - env::remove_var(name); - } - } - - for name in opts.unsets.iter() { - env::remove_var(name); - } - - for &(ref name, ref val) in opts.sets.iter() { - env::set_var(name, val); - } - - if opts.program.len() >= 1 { - let prog = opts.program[0].clone(); - let args = &opts.program[1..]; - match Command::new(prog).args(args).status() { - Ok(exit) => return if exit.success() { 0 } else { exit.code().unwrap() }, - Err(_) => return 1 - } - } else { - // no program provided - print_env(opts.null); - pipe_flush!(); - } - - 0 -} diff --git a/src/expand/Cargo.toml b/src/expand/Cargo.toml deleted file mode 100644 index 75176539a..000000000 --- a/src/expand/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "expand" -version = "0.0.1" -authors = [] - -[lib] -name = "expand" -path = "expand.rs" - -[dependencies] -getopts = "*" -libc = "*" -unicode-width = "*" diff --git a/src/expand/deps.mk b/src/expand/deps.mk deleted file mode 100644 index fb8005c0c..000000000 --- a/src/expand/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += unicode-width diff --git a/src/expand/expand.rs b/src/expand/expand.rs deleted file mode 100644 index 09bf427b1..000000000 --- a/src/expand/expand.rs +++ /dev/null @@ -1,244 +0,0 @@ -#![crate_name = "expand"] -#![feature(unicode)] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Virgile Andreani - * (c) kwantam - * 20150428 updated to work with both UTF-8 and non-UTF-8 encodings - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; -extern crate rustc_unicode; -extern crate unicode_width; - -use std::fs::File; -use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Write}; -use std::iter::repeat; -use std::str::from_utf8; -use rustc_unicode::str::utf8_char_width; -use unicode_width::UnicodeWidthChar; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "expand"; -static VERSION: &'static str = "0.0.1"; - -static DEFAULT_TABSTOP: usize = 8; - -fn tabstops_parse(s: String) -> Vec { - let words = s.split(',').collect::>(); - - let nums = words.into_iter() - .map(|sn| sn.parse::() - .unwrap_or_else( - |_| crash!(1, "{}\n", "tab size contains invalid character(s)")) - ) - .collect::>(); - - if nums.iter().any(|&n| n == 0) { - crash!(1, "{}\n", "tab size cannot be 0"); - } - - match nums.iter().fold((true, 0), |(acc, last), &n| (acc && last <= n, n)) { - (false, _) => crash!(1, "{}\n", "tab sizes must be ascending"), - _ => {} - } - - nums -} - -struct Options { - files: Vec, - tabstops: Vec, - tspaces: String, - iflag: bool, - uflag: bool, -} - -impl Options { - fn new(matches: getopts::Matches) -> Options { - let tabstops = match matches.opt_str("t") { - None => vec!(DEFAULT_TABSTOP), - Some(s) => tabstops_parse(s) - }; - - let iflag = matches.opt_present("i"); - let uflag = !matches.opt_present("U"); - - // avoid allocations when dumping out long sequences of spaces - // by precomputing the longest string of spaces we will ever need - let nspaces = tabstops.iter().scan(0, |pr,&it| { - let ret = Some(it - *pr); - *pr = it; - ret - }).max().unwrap(); // length of tabstops is guaranteed >= 1 - let tspaces = repeat(' ').take(nspaces).collect(); - - let files = - if matches.free.is_empty() { - vec!("-".to_string()) - } else { - matches.free - }; - - Options { files: files, tabstops: tabstops, tspaces: tspaces, iflag: iflag, uflag: uflag } - } -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("i", "initial", "do not convert tabs after non blanks"); - opts.optopt("t", "tabs", "have tabs NUMBER characters apart, not 8", "NUMBER"); - opts.optopt("t", "tabs", "use comma separated list of explicit tab positions", "LIST"); - opts.optflag("U", "no-utf8", "interpret input file as 8-bit ASCII rather than UTF-8"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "{}", f) - }; - - if matches.opt_present("help") { - println!("Usage: {} [OPTION]... [FILE]...", NAME); - println!("{}", opts.usage( - "Convert tabs in each FILE to spaces, writing to standard output.\n\ - With no FILE, or when FILE is -, read standard input.")); - return 0; - } - - if matches.opt_present("V") { - println!("{} {}", NAME, VERSION); - return 0; - } - - expand(Options::new(matches)); - - 0 -} - -fn open(path: String) -> BufReader> { - let file_buf; - if path == "-" { - BufReader::new(Box::new(stdin()) as Box) - } else { - file_buf = match File::open(&path[..]) { - Ok(a) => a, - Err(e) => crash!(1, "{}: {}\n", &path[..], e), - }; - BufReader::new(Box::new(file_buf) as Box) - } -} - -fn next_tabstop(tabstops: &[usize], col: usize) -> usize { - if tabstops.len() == 1 { - tabstops[0] - col % tabstops[0] - } else { - match tabstops.iter().skip_while(|&&t| t <= col).next() { - Some(t) => t - col, - None => 1, - } - } -} - -#[derive(PartialEq, Eq, Debug)] -enum CharType { - Backspace, - Tab, - Other, -} - -fn expand(options: Options) { - use self::CharType::*; - - let mut output = BufWriter::new(stdout()); - let ts = options.tabstops.as_ref(); - let mut buf = Vec::new(); - - for file in options.files.into_iter() { - let mut fh = open(file); - - while match fh.read_until('\n' as u8, &mut buf) { - Ok(s) => s > 0, - Err(_) => buf.len() > 0, - } { - let mut col = 0; - let mut byte = 0; - let mut init = true; - - while byte < buf.len() { - let (ctype, cwidth, nbytes) = if options.uflag { - let nbytes = utf8_char_width(buf[byte]); - - if byte + nbytes > buf.len() { - // don't overrun buffer because of invalid UTF-8 - (Other, 1, 1) - } else if let Ok(t) = from_utf8(&buf[byte..byte+nbytes]) { - match t.chars().next() { - Some('\t') => (Tab, 0, nbytes), - Some('\x08') => (Backspace, 0, nbytes), - Some(c) => (Other, UnicodeWidthChar::width(c).unwrap_or(0), nbytes), - None => { // no valid char at start of t, so take 1 byte - (Other, 1, 1) - }, - } - } else { - (Other, 1, 1) // implicit assumption: non-UTF-8 char is 1 col wide - } - } else { - (match buf[byte] { // always take exactly 1 byte in strict ASCII mode - 0x09 => Tab, - 0x08 => Backspace, - _ => Other, - }, 1, 1) - }; - - // figure out how many columns this char takes up - match ctype { - Tab => { - // figure out how many spaces to the next tabstop - let nts = next_tabstop(ts, col); - col += nts; - - // now dump out either spaces if we're expanding, or a literal tab if we're not - if init || !options.iflag { - safe_unwrap!(output.write_all(&options.tspaces[..nts].as_bytes())); - } else { - safe_unwrap!(output.write_all(&buf[byte..byte+nbytes])); - } - }, - _ => { - col = if ctype == Other { - col + cwidth - } else if col > 0 { - col - 1 - } else { - 0 - }; - - // if we're writing anything other than a space, then we're - // done with the line's leading spaces - if buf[byte] != 0x20 { - init = false; - } - - safe_unwrap!(output.write_all(&buf[byte..byte+nbytes])); - }, - } - - byte += nbytes; // advance the pointer - } - - buf.truncate(0); // clear the buffer - } - } -} diff --git a/src/expr/Cargo.toml b/src/expr/Cargo.toml deleted file mode 100644 index 164c2070d..000000000 --- a/src/expr/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ - -[package] -name = "expr" -version = "0.0.1" -authors = [] - -[lib] -name = "expr" -path = "expr.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/expr/expr.rs b/src/expr/expr.rs deleted file mode 100644 index d6a7664d2..000000000 --- a/src/expr/expr.rs +++ /dev/null @@ -1,135 +0,0 @@ -#![crate_name = "expr"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Roman Gafiyatullin - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -#[path="../common/util.rs"] -#[macro_use] -mod util; -mod tokens; -mod syntax_tree; - -use std::io::{Write}; - -static NAME: &'static str = "expr"; -static VERSION: &'static str = "0.0.1"; - -pub fn uumain(args: Vec) -> i32 { - // For expr utility we do not want getopts. - // The following usage should work without escaping hyphens: `expr -15 = 1 + 2 \* \( 3 - -4 \)` - - if maybe_handle_help_or_version( &args ) { 0 } - else { - let token_strings = args[1..].to_vec(); - - match process_expr( &token_strings ) { - Ok( expr_result ) => print_expr_ok( &expr_result ), - Err( expr_error ) => print_expr_error( &expr_error ) - } - } -} - -fn process_expr( token_strings: &Vec ) -> Result< String, String > { - let maybe_tokens = tokens::strings_to_tokens( &token_strings ); - let maybe_ast = syntax_tree::tokens_to_ast( maybe_tokens ); - let maybe_result = evaluate_ast( maybe_ast ); - - maybe_result -} - -fn print_expr_ok( expr_result: &String ) -> i32 { - println!("{}", expr_result); - if expr_result == "0" || expr_result == "" { 1 } - else { 0 } -} - -fn print_expr_error( expr_error: &String ) -> ! { - crash!(2, "{}", expr_error) -} - -fn evaluate_ast( maybe_ast: Result, String> ) -> Result { - if maybe_ast.is_err() { Err( maybe_ast.err().unwrap() ) } - else { maybe_ast.ok().unwrap().evaluate() } -} - - - -fn maybe_handle_help_or_version( args: &Vec ) -> bool { - if args.len() == 2 { - if args[1] == "--help" { print_help(); true } - else if args[1] == "--version" { print_version(); true } - else { false } - } - else { false } -} - -fn print_help() { - //! The following is taken from GNU coreutils' "expr --help" output. - print!( -r#"Usage: expr EXPRESSION - or: expr OPTION - - --help display this help and exit - --version output version information and exit - -Print the value of EXPRESSION to standard output. A blank line below -separates increasing precedence groups. EXPRESSION may be: - - ARG1 | ARG2 ARG1 if it is neither null nor 0, otherwise ARG2 - - ARG1 & ARG2 ARG1 if neither argument is null or 0, otherwise 0 - - ARG1 < ARG2 ARG1 is less than ARG2 - ARG1 <= ARG2 ARG1 is less than or equal to ARG2 - ARG1 = ARG2 ARG1 is equal to ARG2 - ARG1 != ARG2 ARG1 is unequal to ARG2 - ARG1 >= ARG2 ARG1 is greater than or equal to ARG2 - ARG1 > ARG2 ARG1 is greater than ARG2 - - ARG1 + ARG2 arithmetic sum of ARG1 and ARG2 - ARG1 - ARG2 arithmetic difference of ARG1 and ARG2 - - ARG1 * ARG2 arithmetic product of ARG1 and ARG2 - ARG1 / ARG2 arithmetic quotient of ARG1 divided by ARG2 - ARG1 % ARG2 arithmetic remainder of ARG1 divided by ARG2 - - STRING : REGEXP [NOT IMPLEMENTED] anchored pattern match of REGEXP in STRING - - match STRING REGEXP [NOT IMPLEMENTED] same as STRING : REGEXP - substr STRING POS LENGTH substring of STRING, POS counted from 1 - index STRING CHARS index in STRING where any CHARS is found, or 0 - length STRING length of STRING - + TOKEN interpret TOKEN as a string, even if it is a - keyword like 'match' or an operator like '/' - - ( EXPRESSION ) value of EXPRESSION - -Beware that many operators need to be escaped or quoted for shells. -Comparisons are arithmetic if both ARGs are numbers, else lexicographical. -Pattern matches return the string matched between \( and \) or null; if -\( and \) are not used, they return the number of characters matched or 0. - -Exit status is 0 if EXPRESSION is neither null nor 0, 1 if EXPRESSION is null -or 0, 2 if EXPRESSION is syntactically invalid, and 3 if an error occurred. - -Environment variables: - * EXPR_DEBUG_TOKENS=1 dump expression's tokens - * EXPR_DEBUG_RPN=1 dump expression represented in reverse polish notation - * EXPR_DEBUG_SYA_STEP=1 dump each parser step - * EXPR_DEBUG_AST=1 dump expression represented abstract syntax tree -"# - ); -} - -fn print_version() { - println!("{} {}", NAME, VERSION); -} diff --git a/src/expr/syntax_tree.rs b/src/expr/syntax_tree.rs deleted file mode 100644 index 53819974d..000000000 --- a/src/expr/syntax_tree.rs +++ /dev/null @@ -1,386 +0,0 @@ -/* - * This file is part of the uutils coreutils package. - * - * (c) Roman Gafiyatullin - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -//! -//! Here we employ shunting-yard algorithm for building AST from tokens according to operators' precedence and associativeness. -//! * https://en.wikipedia.org/wiki/Shunting-yard_algorithm -//! - -use tokens::{Token}; - -type TokenStack = Vec<(usize, Token)>; -type OperandsList = Vec< Box >; - -#[derive(Debug)] -pub enum ASTNode { - Leaf { token_idx: usize, value: String }, - Node { token_idx: usize, op_type: String, operands: OperandsList } -} -impl ASTNode { - fn debug_dump( &self ) { - self.debug_dump_impl( 1 ); - } - fn debug_dump_impl( &self, depth: usize ) { - for _ in 0..depth { - print!("\t", ); - } - match self { - &ASTNode::Leaf{ ref token_idx, ref value } => println!("Leaf( {} ) at #{} ( evaluate -> {:?} )", value, token_idx, self.evaluate()), - &ASTNode::Node{ ref token_idx, ref op_type, ref operands } => { - println!("Node( {} ) at #{} (evaluate -> {:?})", op_type, token_idx, self.evaluate()); - for operand in operands { - operand.debug_dump_impl( depth + 1 ); - } - } - } - } - - fn new_node( token_idx: usize, op_type: &String, operands: OperandsList ) -> Box { - Box::new( ASTNode::Node{ - token_idx: token_idx, - op_type: op_type.clone(), - operands: operands - } ) - } - fn new_leaf( token_idx: usize, value: &String ) -> Box { - Box::new( ASTNode::Leaf{ token_idx: token_idx, value: value.clone() } ) - } - pub fn evaluate( &self ) -> Result { - match self { - &ASTNode::Leaf{ ref value, .. } => Ok( value.clone() ), - &ASTNode::Node{ ref op_type, .. } => - match self.operand_values() { - Err( reason ) => Err( reason ), - Ok( operand_values ) => - match op_type.as_ref() { - "+" => infix_operator_two_ints( |a: i64, b: i64| Ok( a + b ), &operand_values ), - "-" => infix_operator_two_ints( |a: i64, b: i64| Ok( a - b ), &operand_values ), - "*" => infix_operator_two_ints( |a: i64, b: i64| Ok( a * b ), &operand_values ), - "/" => infix_operator_two_ints( - |a: i64, b: i64| - if b == 0 { Err("division by zero".to_string()) } - else { Ok( a / b ) }, - &operand_values ), - "%" => infix_operator_two_ints( - |a: i64, b: i64| - if b == 0 { Err("division by zero".to_string()) } - else { Ok( a % b ) }, - &operand_values ), - - "=" => infix_operator_two_ints_or_two_strings( - |a: i64, b: i64| Ok( bool_as_int(a == b) ), - |a: &String, b: &String| Ok( bool_as_string(a == b) ), - &operand_values - ), - "!=" => infix_operator_two_ints_or_two_strings( - |a: i64, b: i64| Ok( bool_as_int(a != b) ), - |a: &String, b: &String| Ok( bool_as_string(a != b) ), - &operand_values - ), - "<" => infix_operator_two_ints_or_two_strings( - |a: i64, b: i64| Ok( bool_as_int(a < b) ), - |a: &String, b: &String| Ok( bool_as_string(a < b) ), - &operand_values - ), - ">" => infix_operator_two_ints_or_two_strings( - |a: i64, b: i64| Ok( bool_as_int(a > b) ), - |a: &String, b: &String| Ok( bool_as_string(a > b) ), - &operand_values - ), - "<=" => infix_operator_two_ints_or_two_strings( - |a: i64, b: i64| Ok( bool_as_int(a <= b) ), - |a: &String, b: &String| Ok( bool_as_string(a <= b) ), - &operand_values - ), - ">=" => infix_operator_two_ints_or_two_strings( - |a: i64, b: i64| Ok( bool_as_int(a >= b) ), - |a: &String, b: &String| Ok( bool_as_string(a >= b) ), - &operand_values - ), - "length" => prefix_operator_length( &operand_values ), - "index" => prefix_operator_index( &operand_values ), - "substr" => prefix_operator_substr( &operand_values ), - - _ => Err(format!("operation not implemented: {}", op_type)) - } - } - } - } - pub fn operand_values( &self ) -> Result, String> { - if let &ASTNode::Node{ ref operands, .. } = self { - let mut out = Vec::with_capacity( operands.len() ); - for operand in operands { - match operand.evaluate() { - Ok( value ) => out.push( value ), - Err( reason ) => return Err( reason ), - } - } - Ok( out ) - } - else { panic!("Invoked .operand_values(&self) not with ASTNode::Node") } - } -} - -pub fn tokens_to_ast( maybe_tokens: Result< Vec<(usize, Token)>, String > ) -> Result, String> { - if maybe_tokens.is_err() { Err( maybe_tokens.err().unwrap() ) } - else { - let tokens = maybe_tokens.ok().unwrap(); - let mut out_stack: TokenStack = Vec::new(); - let mut op_stack: TokenStack = Vec::new(); - - for (token_idx, token) in tokens { - if let Err( reason ) = push_token_to_either_stack( token_idx, &token, &mut out_stack, &mut op_stack ) { - return Err( reason ) - } - } - if let Err( reason ) = move_rest_of_ops_to_out( &mut out_stack, &mut op_stack ) { - return Err( reason ) - } - assert!( op_stack.is_empty() ); - - maybe_dump_rpn( &out_stack ); - let result = ast_from_rpn( &mut out_stack ); - if !out_stack.is_empty() { - Err( "syntax error (fist RPN token does not represent expression AST's root)".to_string() ) - } - else { - maybe_dump_ast( &result ); - result - } - } -} - -fn maybe_dump_ast( result: &Result< Box, String > ) { - use std::env; - if let Ok( debug_var ) = env::var( "EXPR_DEBUG_AST" ) { - if debug_var == "1" { - println!("EXPR_DEBUG_AST"); - match result { - &Ok( ref ast ) => ast.debug_dump(), - &Err( ref reason ) => println!("\terr: {:?}", reason), - } - } - } -} - -fn maybe_dump_rpn( rpn: &TokenStack ) { - use std::env; - if let Ok( debug_var ) = env::var( "EXPR_DEBUG_RPN" ) { - if debug_var == "1" { - println!("EXPR_DEBUG_RPN"); - for token in rpn { - println!("\t{:?}", token); - } - } - } -} - -fn ast_from_rpn( rpn: &mut TokenStack ) -> Result, String> { - match rpn.pop() { - None => Err( "syntax error (premature end of expression)".to_string() ), - - Some( (token_idx, Token::Value{ value }) ) => - Ok( ASTNode::new_leaf( token_idx, &value ) ), - - Some( (token_idx, Token::InfixOp{ value, .. }) ) => - maybe_ast_node( token_idx, &value, 2, rpn ), - - Some( (token_idx, Token::PrefixOp{ value, arity }) ) => - maybe_ast_node( token_idx, &value, arity, rpn ), - - Some( (token_idx, unexpected_token) ) => - panic!("unexpected token at #{} {:?}", token_idx, unexpected_token), - } -} -fn maybe_ast_node( token_idx: usize, op_type: &String, arity: usize, rpn: &mut TokenStack ) -> Result< Box, String > { - let mut operands = Vec::with_capacity( arity ); - for _ in 0..arity { - match ast_from_rpn( rpn ) { - Err( reason ) => return Err( reason ), - Ok( operand ) => operands.push( operand ), - } - } - operands.reverse(); - Ok( ASTNode::new_node( token_idx, op_type, operands ) ) -} - -fn move_rest_of_ops_to_out( out_stack: &mut TokenStack, op_stack: &mut TokenStack ) -> Result<(), String> { - loop { - match op_stack.pop() { - None => return Ok( () ), - Some( (token_idx, Token::ParOpen) ) => return Err( format!( "syntax error (Mismatched open-parenthesis at #{})", token_idx ) ), - Some( (token_idx, Token::ParClose) ) => return Err( format!( "syntax error (Mismatched close-parenthesis at #{})", token_idx ) ), - Some( other ) => out_stack.push( other ) - } - } -} - -fn push_token_to_either_stack( token_idx: usize, token: &Token, out_stack: &mut TokenStack, op_stack: &mut TokenStack ) -> Result<(), String> { - let result = - match token { - &Token::Value{ .. } => Ok( out_stack.push( (token_idx, token.clone()) ) ), - - &Token::InfixOp{ .. } => - if op_stack.is_empty() { Ok( op_stack.push( (token_idx, token.clone()) ) ) } - else { push_op_to_stack( token_idx, token, out_stack, op_stack ) }, - - &Token::PrefixOp{ .. } => Ok( op_stack.push( (token_idx, token.clone()) ) ), - - &Token::ParOpen => Ok( op_stack.push( (token_idx, token.clone()) ) ), - - &Token::ParClose => move_till_match_paren( out_stack, op_stack ) - }; - maybe_dump_shunting_yard_step( token_idx, token, out_stack, op_stack, &result ); - result -} - -fn maybe_dump_shunting_yard_step( token_idx: usize, token: &Token, out_stack: &TokenStack, op_stack: &TokenStack, result: &Result<(), String> ) { - use std::env; - if let Ok( debug_var ) = env::var( "EXPR_DEBUG_SYA_STEP" ) { - if debug_var == "1" { - println!("EXPR_DEBUG_SYA_STEP"); - println!("\t{} => {:?}", token_idx, token); - println!("\t\tout: {:?}", out_stack); - println!("\t\top : {:?}", op_stack); - println!("\t\tresult: {:?}", result); - } - } -} - -fn push_op_to_stack( token_idx: usize, token: &Token, out_stack: &mut TokenStack, op_stack: &mut TokenStack ) -> Result<(), String> { - if let &Token::InfixOp{ precedence: prec, left_assoc: la, .. } = token { - loop { - match op_stack.last() { - None => - return Ok( op_stack.push( (token_idx, token.clone()) ) ), - - Some( &(_, Token::ParOpen) ) => - return Ok( op_stack.push( (token_idx, token.clone()) ) ), - - Some( &(_, Token::InfixOp{ precedence: prev_prec, .. }) ) => - if la && prev_prec >= prec - || !la && prev_prec > prec { - out_stack.push( op_stack.pop().unwrap() ) - } - else { - return Ok( op_stack.push( (token_idx, token.clone()) ) ) - }, - - Some( &(_, Token::PrefixOp{ .. }) ) => - return Ok( op_stack.push( (token_idx, token.clone()) ) ), - - Some( _ ) => panic!("Non-operator on op_stack") - } - } - } - else { - panic!("Expected infix-op") - } -} - -fn move_till_match_paren( out_stack: &mut TokenStack, op_stack: &mut TokenStack ) -> Result<(), String> { - loop { - match op_stack.pop() { - None => return Err( "syntax error (Mismatched close-parenthesis)".to_string() ), - Some( (_, Token::ParOpen) ) => return Ok( () ), - Some( other ) => out_stack.push( other ) - } - } -} - - -fn infix_operator_two_ints( f: F, values: &Vec ) -> Result - where F : Fn( i64, i64 ) -> Result -{ - assert!( values.len() == 2 ); - if let Some( left ) = values[0].parse::().ok() { - if let Some( right ) = values[1].parse::().ok() { - return match f( left, right ) { - Ok(result) => Ok(result.to_string()), - Err(reason) => Err(reason), - } - } - } - Err( "Expected an integer operand".to_string() ) -} - - -fn infix_operator_two_ints_or_two_strings( fi: FI, fs: FS, values: &Vec ) -> Result - where FI : Fn( i64, i64 ) -> Result, - FS : Fn( &String, &String ) -> Result -{ - assert!( values.len() == 2 ); - if let ( Some( a_int ), Some( b_int ) ) = - ( - values[0].parse::().ok(), - values[1].parse::().ok() - ) { - match fi( a_int, b_int ) { - Ok( result ) => Ok(result.to_string()), - Err( reason ) => Err(reason) - } - } - else { - fs( &values[0], &values[1] ) - } -} - -fn prefix_operator_length( values: &Vec ) -> Result { - assert!( values.len() == 1 ); - Ok( values[0].len().to_string() ) -} - -fn prefix_operator_index( values: &Vec ) -> Result { - assert!( values.len() == 2 ); - let haystack = &values[0]; - let needles = &values[1]; - - let mut current_idx = 0; - for ch_h in haystack.chars() { - current_idx += 1; - - for ch_n in needles.chars() { - if ch_n == ch_h { - return Ok( current_idx.to_string() ) - } - } - } - Ok( "0".to_string() ) -} - -fn prefix_operator_substr( values: &Vec ) -> Result { - assert!( values.len() == 3 ); - let subj = &values[0]; - let mut idx = match values[1].parse::() { - Ok( i ) => i, - Err( _ ) => return Err( "expected integer as POS arg to 'substr'".to_string() ), - }; - let mut len = match values[2].parse::() { - Ok( i ) => i, - Err( _ ) => return Err( "expected integer as LENGTH arg to 'substr'".to_string() ), - }; - - if idx <= 0 || len <= 0 { return Ok( "".to_string() ) } - - let mut out_str = String::new(); - for ch in subj.chars() { - idx -= 1; - if idx <= 0 { - if len <= 0 { break; } - len -= 1; - - out_str.push( ch ); - } - } - Ok( out_str ) -} - -fn bool_as_int( b: bool ) -> i64 { if b { 1 } else { 0 } } -fn bool_as_string( b: bool ) -> String { if b { "1".to_string() } else { "0".to_string() } } - diff --git a/src/expr/tokens.rs b/src/expr/tokens.rs deleted file mode 100644 index f1c0a65bf..000000000 --- a/src/expr/tokens.rs +++ /dev/null @@ -1,160 +0,0 @@ -/* - * This file is part of the uutils coreutils package. - * - * (c) Roman Gafiyatullin - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -//! -//! The following tokens are present in the expr grammar: -//! * integer literal; -//! * string literal; -//! * infix binary operators; -//! * prefix operators. -//! -//! According to the man-page of expr we have expression split into tokens (each token -- separate CLI-argument). -//! Hence all we need is to map the strings into the Token structures, except for some ugly fiddling with +-escaping. -//! - -#[derive(Debug)] -#[derive(Clone)] -pub enum Token { - Value{ value: String }, - - ParOpen, - ParClose, - - InfixOp { - precedence: u8, - left_assoc: bool, - value: String - }, - - PrefixOp { - arity: usize, - value: String - }, -} -impl Token { - fn new_infix_op( v: &String, left_assoc: bool, precedence: u8 ) -> Self { - Token::InfixOp{ - left_assoc: left_assoc, - precedence: precedence, - value: v.clone() - } - } - fn new_value( v: &String ) -> Self { - Token::Value{ - value: v.clone() - } - } - - fn is_infix_plus( &self ) -> bool { - match self { - &Token::InfixOp{ ref value, .. } => value == "+", - _ => false - } - } - fn is_a_number( &self ) -> bool { - match self { - &Token::Value{ ref value, .. } => - match value.parse::() { - Ok( _ ) => true, - Err( _ ) => false - }, - _ => false, - } - } - fn is_a_close_paren( &self ) -> bool { - match self { - &Token::ParClose => true, - _ => false, - } - } -} - -pub fn strings_to_tokens( strings: &Vec ) -> Result< Vec<(usize, Token)>, String > { - let mut tokens_acc = Vec::with_capacity( strings.len() ); - let mut tok_idx = 1; - - for s in strings { - let token_if_not_escaped = - match s.as_ref() { - "(" => Token::ParOpen, - ")" => Token::ParClose, - - "^" => Token::new_infix_op( &s, false, 7 ), - - ":" => Token::new_infix_op( &s, true, 6 ), - - "*" => Token::new_infix_op( &s, true, 5 ), - "/" => Token::new_infix_op( &s, true, 5 ), - "%" => Token::new_infix_op( &s, true, 5 ), - - "+" => Token::new_infix_op( &s, true, 4 ), - "-" => Token::new_infix_op( &s, true, 4 ), - - "=" => Token::new_infix_op( &s, true, 3 ), - "!=" => Token::new_infix_op( &s, true, 3 ), - "<" => Token::new_infix_op( &s, true, 3 ), - ">" => Token::new_infix_op( &s, true, 3 ), - "<=" => Token::new_infix_op( &s, true, 3 ), - ">=" => Token::new_infix_op( &s, true, 3 ), - - "&" => Token::new_infix_op( &s, true, 2 ), - - "|" => Token::new_infix_op( &s, true, 1 ), - - "match" => Token::PrefixOp{ arity: 2, value: s.clone() }, - "substr" => Token::PrefixOp{ arity: 3, value: s.clone() }, - "index" => Token::PrefixOp{ arity: 2, value: s.clone() }, - "length" => Token::PrefixOp{ arity: 1, value: s.clone() }, - - _ => Token::new_value( &s ), - }; - push_token_if_not_escaped( &mut tokens_acc, tok_idx, token_if_not_escaped, &s ); - tok_idx += 1; - } - maybe_dump_tokens_acc( &tokens_acc ); - - Ok( tokens_acc ) -} - -fn maybe_dump_tokens_acc( tokens_acc: &Vec<(usize, Token)> ) { - use std::env; - - if let Ok(debug_var) = env::var( "EXPR_DEBUG_TOKENS" ) { - if debug_var == "1" { - println!("EXPR_DEBUG_TOKENS"); - for token in tokens_acc { - println!("\t{:?}", token); - } - } - } -} - -fn push_token_if_not_escaped( acc: &mut Vec<(usize, Token)>, tok_idx: usize, token: Token, s: &String ) { - // Smells heuristics... :( - let prev_is_plus = - match acc.last() { - None => false, - Some( ref t ) => t.1.is_infix_plus(), - }; - let should_use_as_escaped = - if prev_is_plus && acc.len() >= 2 { - let pre_prev = &acc[acc.len() - 2]; - ! ( pre_prev.1.is_a_number() || pre_prev.1.is_a_close_paren() ) - } - else if prev_is_plus { true } - else { false }; - - if should_use_as_escaped { - acc.pop(); - acc.push( (tok_idx, Token::new_value( s )) ) - } - else { - acc.push( (tok_idx, token) ) - } -} diff --git a/src/factor/Cargo.toml b/src/factor/Cargo.toml deleted file mode 100644 index ab32fae68..000000000 --- a/src/factor/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "factor" -version = "0.0.1" -authors = [] - -[lib] -name = "factor" -path = "factor.rs" - -[dependencies] -getopts = "*" -libc = "*" -rand = "*" diff --git a/src/factor/deps.mk b/src/factor/deps.mk deleted file mode 100644 index ea0f8a6b8..000000000 --- a/src/factor/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += rand diff --git a/src/factor/factor.rs b/src/factor/factor.rs deleted file mode 100644 index b037be020..000000000 --- a/src/factor/factor.rs +++ /dev/null @@ -1,202 +0,0 @@ -#![crate_name = "factor"] - -/* -* This file is part of the uutils coreutils package. -* -* (c) T. Jameson Little -* (c) Wiktor Kuropatwa -* 20150223 added Pollard rho method implementation -* (c) kwantam -* 20150429 sped up trial division by adding table of prime inverses -* -* For the full copyright and license information, please view the LICENSE file -* that was distributed with this source code. -*/ - -extern crate getopts; -extern crate libc; -extern crate rand; - -use numeric::*; -use prime_table::P_INVS_U64; -use rand::weak_rng; -use rand::distributions::{Range, IndependentSample}; -use std::cmp::{max, min}; -use std::io::{stdin, BufRead, BufReader, Write}; -use std::num::Wrapping; -use std::mem::swap; - -#[path="../common/util.rs"] -#[macro_use] -mod util; -mod numeric; -mod prime_table; - -static NAME: &'static str = "factor"; -static VERSION: &'static str = "1.0.0"; - -fn rho_pollard_pseudorandom_function(x: u64, a: u64, b: u64, num: u64) -> u64 { - if num < 1 << 63 { - (sm_mul(a, sm_mul(x, x, num), num) + b) % num - } else { - big_add(big_mul(a, big_mul(x, x, num), num), b, num) - } -} - -fn gcd(mut a: u64, mut b: u64) -> u64 { - while b > 0 { - a %= b; - swap(&mut a, &mut b); - } - a -} - -fn rho_pollard_find_divisor(num: u64) -> u64 { - let range = Range::new(1, num); - let mut rng = rand::weak_rng(); - let mut x = range.ind_sample(&mut rng); - let mut y = x; - let mut a = range.ind_sample(&mut rng); - let mut b = range.ind_sample(&mut rng); - - loop { - x = rho_pollard_pseudorandom_function(x, a, b, num); - y = rho_pollard_pseudorandom_function(y, a, b, num); - y = rho_pollard_pseudorandom_function(y, a, b, num); - let d = gcd(num, max(x, y) - min(x, y)); - if d == num { - // Failure, retry with diffrent function - x = range.ind_sample(&mut rng); - y = x; - a = range.ind_sample(&mut rng); - b = range.ind_sample(&mut rng); - } else if d > 1 { - return d; - } - } -} - -fn rho_pollard_factor(num: u64, factors: &mut Vec) { - if is_prime(num) { - factors.push(num); - return; - } - let divisor = rho_pollard_find_divisor(num); - rho_pollard_factor(divisor, factors); - rho_pollard_factor(num / divisor, factors); -} - -fn table_division(mut num: u64, factors: &mut Vec) { - if num < 2 { - return; - } - while num % 2 == 0 { - num /= 2; - factors.push(2); - } - if num == 1 { - return; - } - if is_prime(num) { - factors.push(num); - return; - } - for &(prime, inv, ceil) in P_INVS_U64 { - if num == 1 { - break; - } - - // inv = prime^-1 mod 2^64 - // ceil = floor((2^64-1) / prime) - // if (num * inv) mod 2^64 <= ceil, then prime divides num - // See http://math.stackexchange.com/questions/1251327/ - // for a nice explanation. - loop { - let Wrapping(x) = Wrapping(num) * Wrapping(inv); // x = num * inv mod 2^64 - if x <= ceil { - num = x; - factors.push(prime); - if is_prime(num) { - factors.push(num); - return; - } - } else { - break; - } - } - } - - // do we still have more factoring to do? - // Decide whether to use Pollard Rho or slow divisibility based on - // number's size: - //if num >= 1 << 63 { - // number is too big to use rho pollard without overflowing - //trial_division_slow(num, factors); - //} else if num > 1 { - // number is still greater than 1, but not so big that we have to worry - rho_pollard_factor(num, factors); - //} -} - -fn print_factors(num: u64) { - print!("{}:", num); - - let mut factors = Vec::new(); - // we always start with table division, and go from there - table_division(num, &mut factors); - factors.sort(); - - for fac in factors.iter() { - print!(" {}", fac); - } - println!(""); -} - -fn print_factors_str(num_str: &str) { - if let Err(e) = num_str.parse::().and_then(|x| Ok(print_factors(x))) { - show_warning!("{}: {}", num_str, e); - } -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - opts.optflag("h", "help", "show this help message"); - opts.optflag("v", "version", "print the version and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "Invalid options\n{}", f) - }; - - if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: -\t{0} [NUMBER]... -\t{0} [OPTION] - -Print the prime factors of the given number(s). If none are specified, -read from standard input.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - return 1; - } - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - if matches.free.is_empty() { - for line in BufReader::new(stdin()).lines() { - for number in line.unwrap().split_whitespace() { - print_factors_str(number); - } - } - } else { - for num_str in matches.free.iter() { - print_factors_str(num_str); - } - } - 0 -} diff --git a/src/factor/gen_table.rs b/src/factor/gen_table.rs deleted file mode 100644 index f4ad03cce..000000000 --- a/src/factor/gen_table.rs +++ /dev/null @@ -1,134 +0,0 @@ -/* -* This file is part of the uutils coreutils package. -* -* (c) kwantam -* -* For the full copyright and license information, please view the LICENSE file -* that was distributed with this source code. -*/ - -//! Generate a table of the multiplicative inverses of p_i mod 2^64 -//! for the first 1027 odd primes (all 13 bit and smaller primes). -//! You can supply a commandline argument to override the default -//! value of 1027 for the number of entries in the table. -//! -//! 2 has no multiplicative inverse mode 2^64 because 2 | 2^64, -//! and in any case divisibility by two is trivial by checking the LSB. - -#![cfg_attr(test, allow(dead_code))] - -use sieve::Sieve; -use std::env::args; -use std::num::Wrapping; -use std::u64::MAX as MAX_U64; - -#[cfg(test)] -use numeric::is_prime; - -#[cfg(test)] -mod numeric; - -mod sieve; - -// extended Euclid algorithm -// precondition: a does not divide 2^64 -fn inv_mod_u64(a: u64) -> Option { - let mut t = 0u64; - let mut newt = 1u64; - let mut r = 0u64; - let mut newr = a; - - while newr != 0 { - let quot = if r == 0 { - // special case when we're just starting out - // This works because we know that - // a does not divide 2^64, so floor(2^64 / a) == floor((2^64-1) / a); - MAX_U64 - } else { - r - } / newr; - - let (tp, Wrapping(newtp)) = - (newt, Wrapping(t) - (Wrapping(quot) * Wrapping(newt))); - t = tp; - newt = newtp; - - let (rp, Wrapping(newrp)) = - (newr, Wrapping(r) - (Wrapping(quot) * Wrapping(newr))); - r = rp; - newr = newrp; - } - - if r > 1 { // not invertible - return None; - } - - Some(t) -} - -#[cfg_attr(test, allow(dead_code))] -fn main() { - // By default, we print the multiplicative inverses mod 2^64 of the first 1k primes - let n = args().skip(1).next().unwrap_or("1027".to_string()).parse::().ok().unwrap_or(1027); - - print!("{}", PREAMBLE); - let mut cols = 3; - - // we want a total of n + 1 values - let mut primes = Sieve::odd_primes().take(n + 1); - - // in each iteration of the for loop, we use the value yielded - // by the previous iteration. This leaves one value left at the - // end, which we call NEXT_PRIME. - let mut x = primes.next().unwrap(); - for next in primes { - // format the table - let outstr = format!("({}, {}, {}),", x, inv_mod_u64(x).unwrap(), MAX_U64 / x); - if cols + outstr.len() > MAX_WIDTH { - print!("\n {}", outstr); - cols = 4 + outstr.len(); - } else { - print!(" {}", outstr); - cols += 1 + outstr.len(); - } - - x = next; - } - - print!("\n];\n\n#[allow(dead_code)]\npub const NEXT_PRIME: u64 = {};\n", x); -} - -#[test] -fn test_inverter() { - let num = 10000; - - let invs = Sieve::odd_primes().map(|x| inv_mod_u64(x).unwrap()); - assert!(Sieve::odd_primes().zip(invs).take(num).all(|(x, y)| { - let Wrapping(z) = Wrapping(x) * Wrapping(y); - is_prime(x) && z == 1 - })); -} - -#[test] -fn test_generator() { - let prime_10001 = Sieve::primes().skip(10000).next(); - assert_eq!(prime_10001, Some(104743)); -} - -const MAX_WIDTH: usize = 102; -const PREAMBLE: &'static str = -r##"/* -* This file is part of the uutils coreutils package. -* -* (c) kwantam -* -* For the full copyright and license information, please view the LICENSE file -* that was distributed with this source code. -*/ - -// *** NOTE: this file was automatically generated. -// Please do not edit by hand. Instead, modify and -// re-run src/factor/gen_tables.rs. - -pub const P_INVS_U64: &'static [(u64, u64, u64)] = &[ - "##; diff --git a/src/factor/numeric.rs b/src/factor/numeric.rs deleted file mode 100644 index 16a0652a1..000000000 --- a/src/factor/numeric.rs +++ /dev/null @@ -1,132 +0,0 @@ -/* -* This file is part of the uutils coreutils package. -* -* (c) Wiktor Kuropatwa -* (c) kwantam -* 20150507 added big_ routines to prevent overflow when num > 2^63 -* -* For the full copyright and license information, please view the LICENSE file -* that was distributed with this source code. -*/ - -use std::u64::MAX as MAX_U64; -use std::num::Wrapping; - -pub fn big_add(a: u64, b: u64, m: u64) -> u64 { - let Wrapping(msb_mod_m) = Wrapping(MAX_U64) - Wrapping(m) + Wrapping(1); - let msb_mod_m = msb_mod_m % m; - - let Wrapping(res) = Wrapping(a) + Wrapping(b); - let res = if b <= MAX_U64 - a { - res - } else { - (res + msb_mod_m) % m - }; - - res -} - -// computes (a + b) % m using the russian peasant algorithm -// CAUTION: Will overflow if m >= 2^63 -pub fn sm_mul(mut a: u64, mut b: u64, m: u64) -> u64 { - let mut result = 0; - while b > 0 { - if b & 1 != 0 { - result = (result + a) % m; - } - a = (a << 1) % m; - b >>= 1; - } - result -} - -// computes (a + b) % m using the russian peasant algorithm -// Only necessary when m >= 2^63; otherwise, just wastes time. -pub fn big_mul(mut a: u64, mut b: u64, m: u64) -> u64 { - // precompute 2^64 mod m, since we expect to wrap - let Wrapping(msb_mod_m) = Wrapping(MAX_U64) - Wrapping(m) + Wrapping(1); - let msb_mod_m = msb_mod_m % m; - - let mut result = 0; - while b > 0 { - if b & 1 != 0 { - let Wrapping(next_res) = Wrapping(result) + Wrapping(a); - let next_res = next_res % m; - result = if result <= MAX_U64 - a { - next_res - } else { - (next_res + msb_mod_m) % m - }; - } - let Wrapping(next_a) = Wrapping(a) << 1; - let next_a = next_a % m; - a = if a < 1 << 63 { - next_a - } else { - (next_a + msb_mod_m) % m - }; - b >>= 1; - } - result -} - -// computes a.pow(b) % m -fn pow(mut a: u64, mut b: u64, m: u64, mul: fn(u64, u64, u64) -> u64) -> u64 { - let mut result = 1; - while b > 0 { - if b & 1 != 0 { - result = mul(result, a, m); - } - a = mul(a, a, m); - b >>= 1; - } - result -} - -fn witness(mut a: u64, exponent: u64, m: u64) -> bool { - if a == 0 { - return false; - } - - let mul = if m < 1 << 63 { - sm_mul as fn(u64, u64, u64) -> u64 - } else { - big_mul as fn(u64, u64, u64) -> u64 - }; - - if pow(a, m-1, m, mul) != 1 { - return true; - } - a = pow(a, exponent, m, mul); - if a == 1 { - return false; - } - loop { - if a == 1 { - return true; - } - if a == m-1 { - return false; - } - a = mul(a, a, m); - } -} - -// uses deterministic (i.e., fixed witness set) Miller-Rabin test -pub fn is_prime(num: u64) -> bool { - if num < 2 { - return false; - } - if num % 2 == 0 { - return num == 2; - } - let mut exponent = num - 1; - while exponent & 1 == 0 { - exponent >>= 1; - } - - // These witnesses detect all composites up to at least 2^64. - // Discovered by Jim Sinclair, according to http://miller-rabin.appspot.com - let witnesses = [2, 325, 9375, 28178, 450775, 9780504, 1795265022]; - ! witnesses.iter().any(|&wit| witness(wit % num, exponent, num)) -} diff --git a/src/factor/prime_table.rs b/src/factor/prime_table.rs deleted file mode 100644 index 43f01eb4b..000000000 --- a/src/factor/prime_table.rs +++ /dev/null @@ -1,532 +0,0 @@ -/* -* This file is part of the uutils coreutils package. -* -* (c) kwantam -* -* For the full copyright and license information, please view the LICENSE file -* that was distributed with this source code. -*/ - -// *** NOTE: this file was automatically generated. -// Please do not edit by hand. Instead, modify and -// re-run src/factor/gen_tables.rs. - -pub const P_INVS_U64: &'static [(u64, u64, u64)] = &[ - (3, 12297829382473034411, 6148914691236517205), (5, 14757395258967641293, 3689348814741910323), - (7, 7905747460161236407, 2635249153387078802), (11, 3353953467947191203, 1676976733973595601), - (13, 5675921253449092805, 1418980313362273201), (17, 17361641481138401521, 1085102592571150095), - (19, 9708812670373448219, 970881267037344821), (23, 15238614669586151335, 802032351030850070), - (29, 3816567739388183093, 636094623231363848), (31, 17256631552825064415, 595056260442243600), - (37, 1495681951922396077, 498560650640798692), (41, 10348173504763894809, 449920587163647600), - (43, 9437869060967677571, 428994048225803525), (47, 5887258746928580303, 392483916461905353), - (53, 2436362424829563421, 348051774975651917), (59, 14694863923124558067, 312656679215416129), - (61, 5745707170499696405, 302405640552615600), (67, 17345445920055250027, 275324538413575397), - (71, 1818693077689674103, 259813296812810586), (73, 9097024474706080249, 252695124297391118), - (79, 11208148297950107311, 233503089540627235), (83, 11779246215742243803, 222249928598910260), - (89, 17617676924329347049, 207266787345051141), (97, 11790702397628785569, 190172619316593315), - (101, 4200743699953660269, 182641030432767837), (103, 15760325033848937303, 179094602657374287), - (107, 8619973866219416643, 172399477324388332), (109, 12015769075535579493, 169236184162472950), - (113, 10447713457676206225, 163245522776190722), (127, 9150747060186627967, 145249953336295682), - (131, 281629680514649643, 140814840257324821), (137, 16292379802327414201, 134647766961383588), - (139, 4246732448623781667, 132710389019493177), (149, 16094474695182830269, 123803651501406386), - (151, 8062815290495565607, 122163868037811600), (157, 6579730370240349621, 117495185182863386), - (163, 2263404180823257867, 113170209041162893), (167, 10162278172342986519, 110459545351554201), - (173, 9809829218388894501, 106628578460748853), (179, 17107036403551874683, 103054436165975148), - (181, 3770881385233444253, 101915713114417412), (191, 2124755861893246783, 96579811904238490), - (193, 8124213711219232577, 95578984837873324), (197, 14513935692512591373, 93638294790403815), - (199, 2780916192016515319, 92697206400550510), (211, 13900627050804827995, 87425327363552377), - (223, 7527595115280579359, 82720825442643729), (227, 1950316554048586955, 81263189752024456), - (229, 2094390156840385773, 80553467570784068), (233, 7204522363551799129, 79170575423646144), - (239, 7255204782128442895, 77183029597111094), (241, 17298606475760824337, 76542506529915151), - (251, 2939720171109091891, 73493004277727297), (257, 18374966859414961921, 71777214294589695), - (263, 15430736487513693367, 70139711306880424), (269, 10354863773718001093, 68575256779589411), - (271, 15383631589145234927, 68069166323651481), (277, 17181443938689762877, 66594743948409933), - (281, 14245350405676059433, 65646776063023315), (283, 5149444458738708755, 65182841249857072), - (293, 2707201348701401773, 62958170900032599), (307, 17305088903023944187, 60087114246610917), - (311, 9134400602415662215, 59314289626075728), (313, 6365010734698503433, 58935284580541698), - (317, 17050145153302519317, 58191621683626345), (331, 3455281367280943203, 55730344633563600), - (337, 9196002980365592497, 54738112978366622), (347, 9941040754419844819, 53160645745560667), - (349, 15751088062938241781, 52856000211202153), (353, 8779186981255537313, 52257065364616293), - (359, 5600822016808749655, 51383688227603207), (367, 9751139919072624015, 50263607830271257), - (373, 3511310534137743069, 49455077945602015), (379, 17181268226964305331, 48672147951740241), - (383, 14834457375202459263, 48163822646761231), (389, 12661389891209383757, 47420935922132523), - (397, 185861401246443845, 46465350311610961), (401, 3220129888178724721, 46001855545410353), - (409, 2074694932495450793, 45102063749901104), (419, 1849076971589024267, 44025642180691053), - (421, 14897608040525528621, 43816494236839790), (431, 8046375605237577039, 42799870240625409), - (433, 7540585914657253201, 42602180308798040), (439, 15379290047785184263, 42019918163347497), - (443, 15615189678648040307, 41640505809728107), (449, 205420312624827969, 41084062524965593), - (457, 686202733595322489, 40364866682077793), (461, 3041111821262312197, 40014629227135686), - (463, 8127723090792113455, 39841779856824085), (467, 15247201739725667931, 39500522641776341), - (479, 8010277176057592351, 38510947961815347), (487, 2386334448960373207, 37878324586672590), - (491, 1051952818867347139, 37569743530976683), (499, 12494988971771199291, 36967422993405915), - (503, 17969989256695189447, 36673447462643243), (509, 5436172123882971989, 36241147492553146), - (521, 1805727346946616377, 35406418567580713), (523, 7195288319381928355, 35271021173440825), - (541, 13911777416032342069, 34097493666745936), (547, 13219604528142859659, 33723480939139948), - (557, 5133295029488295333, 33118032448311582), (563, 18151858289227516155, 32765087164670606), - (569, 6386658317259721737, 32419585366800617), (571, 1873749835858413299, 32306031652731263), - (577, 8184343991108570561, 31970093715267853), (587, 8107768264083584867, 31425458387920871), - (593, 13407330009728190129, 31107494222107169), (599, 16999336775772408167, 30795899956109435), - (601, 10926856722530117097, 30693417759916059), (607, 7810235958720518559, 30390023185682951), - (613, 10111102787547160429, 30092567820080834), (617, 5112468778937331161, 29897478239399597), - (619, 10400506755613301315, 29800878955912038), (631, 14909412801254946631, 29234142747558718), - (641, 18417966001831689601, 28778071877862015), (643, 12450835035754191915, 28688559990217032), - (647, 16650538700226241335, 28511196404496988), (653, 18023005695293558853, 28249225227732850), - (659, 13744083976011213723, 27992024391061535), (661, 3544230707051608253, 27907328401981167), - (673, 7016889276180750689, 27409723735081057), (677, 7711120491668837677, 27247775588935822), - (683, 18338710433453565955, 27008410063996415), (691, 16604739238563445883, 26695722248494285), - (701, 4578792394900801685, 26314898821268975), (709, 17796294705807240205, 26017974716092456), - (719, 7799457855921701935, 25656111368163493), (727, 3501582781529460967, 25373788271952615), - (733, 8027982755134170485, 25166090141486427), (739, 12755461734324196043, 24961764646426998), - (743, 8416482154761154775, 24827380987496031), (751, 73688724661955599, 24562908220651866), - (757, 11233750354002778461, 24368222026036395), (761, 8193166224591101769, 24240136759145271), - (769, 8635666926574042369, 23987963684927895), (773, 11955781087876436429, 23863834506739394), - (787, 1757948926973591323, 23439319026314550), (797, 3332912354597459765, 23145224684704581), - (809, 12062209660064712985, 22801908620160137), (811, 2229076349227541379, 22745677032934095), - (821, 4044353146489304861, 22468628591607249), (823, 5536264624794968711, 22414026821032261), - (827, 9502192231439261171, 22305615566758829), (829, 9813044796750195733, 22251802260204525), - (839, 17941052639030982263, 21986584116459537), (853, 13018686907823153661, 21625725760503577), - (857, 12247604875076703465, 21524788884141833), (859, 858986918449804499, 21474672961245112), - (863, 13637338028999645343, 21375137976488472), (877, 4964004106494246501, 21033915705484095), - (881, 14447506709261737361, 20938415520669184), (883, 17047047751015848379, 20890989890950794), - (887, 15763959422628906567, 20796780240935232), (907, 11979197639928253475, 20338196332645591), - (911, 16462352285319281519, 20248895799900715), (919, 16098246732442938407, 20072626848432591), - (929, 13264181960428396641, 19856559821000593), (937, 11792529028977610905, 19687026759561954), - (941, 1725094026021722149, 19603341204792297), (947, 18271431828024877947, 19479138409408185), - (953, 18137040080866579081, 19356499552685783), (967, 9614435380713147895, 19076260676018150), - (971, 10828675717831559651, 18997676697950104), (977, 12064963626510136625, 18881007240234955), - (983, 9326583728009813991, 18765762028188760), (991, 13160290676198438943, 18614272526447579), - (997, 11785933776281829869, 18502250826188115), (1009, 6965519813759503633, 18282204235589248), - (1013, 7775675932353384541, 18210013893099261), (1019, 10372899268140896051, 18102791043875909), - (1021, 7497942008412795221, 18067330140753723), (1031, 13544311604071901623, 17892089305246897), - (1033, 15464550210873641529, 17857448280454551), (1039, 1881958490676816623, 17754325383743553), - (1049, 8370495880920635433, 17585075380085368), (1051, 15691141010367591955, 17551611868420125), - (1061, 10466484384894580653, 17386186685871396), (1063, 5917535022704569239, 17353475139896097), - (1069, 13511506650808773541, 17256074905247475), (1087, 4836542834413267903, 16970325734783396), - (1091, 12613447368457676907, 16908106392034419), (1093, 12235946434985750157, 16877167496532069), - (1097, 14007418243755748857, 16815628143764404), (1103, 13546566364192871087, 16724156005176384), - (1109, 14687533829653321981, 16633673646266502), (1117, 17043007953507839989, 16514542590608372), - (1123, 10923494932339137867, 16426308168931034), (1129, 8610659102608444377, 16339011579902171), - (1151, 2852754513571068799, 16026710750399262), (1153, 16894849732729650049, 15998910731751562), - (1163, 14877941479913636643, 15861344861315177), (1171, 10554499171123313051, 15752983837497482), - (1181, 9918444103984390581, 15619597014148646), (1187, 6884505159775342347, 15540643701524474), - (1193, 17503532515875282841, 15462484554660143), (1201, 10275496907003905105, 15359487155461741), - (1213, 12439766407497455253, 15207538395473661), (1217, 6745111842892974913, 15157554703130280), - (1223, 5399782811437464823, 15083192210719175), (1229, 11572367518982965253, 15009555796346258), - (1231, 1168843247562424879, 14985169840543908), (1237, 12988774525627339901, 14912485104049758), - (1249, 2171073962238033697, 14769210627469616), (1259, 2754557494723904451, 14651901567680342), - (1277, 8710561218830743637, 14445375155606540), (1279, 10802667170608642815, 14422786609624356), - (1283, 17756608675784330667, 14377820790108769), (1289, 715544766241642809, 14310895324832856), - (1291, 10173572254439349923, 14288725076459761), (1297, 9401154844041645041, 14222624574949538), - (1301, 4069343235322552893, 14178896290322483), (1303, 17455744775812645543, 14157132827098658), - (1307, 11545093077501463827, 14113805718216948), (1319, 7286393982109686423, 13985401117293064), - (1321, 10375420777264342809, 13964227156479600), (1327, 17848997280062595535, 13901088224347815), - (1361, 8864195903163884465, 13553816365694012), (1367, 11915490136858474087, 13494326315808011), - (1373, 7241656996161287925, 13435356208091443), (1381, 10365440551193781357, 13357526483497140), - (1399, 11511084757933122631, 13185664098434275), (1409, 11062809611273648769, 13092082380205501), - (1423, 11991031811792927087, 12963277634370731), (1427, 10910337770294927515, 12926940486131430), - (1429, 4001742941112638909, 12908848197137544), (1433, 6539390083352723113, 12872815124710084), - (1439, 3589359513994909279, 12819141121410390), (1447, 15973580044476895767, 12748268191920906), - (1451, 6496406768894266627, 12713124792356686), (1453, 16301183338364118565, 12695625652931556), - (1459, 12921571242858918267, 12643416088903051), (1471, 15612641993044453951, 12540274693208396), - (1481, 7535638193514030201, 12455600319857901), (1483, 10846635760131307491, 12438802477214802), - (1487, 7517637463798243631, 12405342349502052), (1489, 9155234298503263025, 12388679700275051), - (1493, 17211195240909179773, 12355488328003718), (1499, 11419998999601376851, 12306033404742862), - (1511, 5310611298519956951, 12208301835678061), (1523, 3355054568888736571, 12112110356999048), - (1531, 13325995392242171187, 12048820426982071), (1543, 7651274275550300087, 11955116055547343), - (1549, 15826806245293734085, 11908808310980988), (1553, 14028077753413380849, 11878135269613362), - (1559, 9773579605442007463, 11832420829832938), (1567, 5579934072072959455, 11772012810280505), - (1571, 4004035473669609867, 11742039512227594), (1579, 17874299197451307139, 11682548495066213), - (1583, 11163601277709254863, 11653028473600474), (1597, 8663154699613126933, 11550872932817502), - (1601, 13918592655241185729, 11522013787451312), (1607, 1503748272343466871, 11478994445369976), - (1609, 4574425659049167865, 11464725962529242), (1613, 2904818967589724805, 11436295147991042), - (1619, 3999263230310100443, 11393912337065813), (1621, 9707015851248764669, 11379854456329149), - (1627, 10045368930120874451, 11337888182980670), (1637, 13127951646836669293, 11268628023035767), - (1657, 2237655738573095881, 11132615614791521), (1663, 5291098570751326591, 11092449833860223), - (1667, 12747839935760889899, 11065833277570216), (1669, 12312566146262696525, 11052572842246585), - (1693, 14633182097455361973, 10895891360726256), (1697, 3782832609104846177, 10870208646853006), - (1699, 15080946155610692875, 10857412639028576), (1709, 5137887758388383013, 10793881845353745), - (1721, 4062356771607158665, 10718619450150814), (1723, 2141235527998787187, 10706177639993935), - (1733, 18372233278258907149, 10644399350092066), (1741, 3401151549489239557, 10595487693112895), - (1747, 8806287668845887835, 10559097924275644), (1753, 5387754116223211881, 10522957258248460), - (1759, 4184338195230307615, 10487063145940620), (1777, 7816768873102584337, 10380835156842741), - (1783, 6114428349726497479, 10345902453005917), (1787, 17001559870956704819, 10322744305377477), - (1789, 18085851931406681685, 10311204065796283), (1801, 15916846357881534265, 10242500873797641), - (1811, 13751024019606788891, 10185943718227251), (1823, 16463440816196072671, 10118894170987137), - (1831, 11374316799136037015, 10074682727312698), (1847, 10307005892836089479, 9987408810887683), - (1861, 10526836220461872013, 9912275160510237), (1867, 12903828473628641891, 9880419964493600), - (1871, 5176130752911552431, 9859296672212480), (1873, 10567728986166763953, 9848768859428484), - (1877, 8451891264459357693, 9827780540069020), (1879, 13538084128603231335, 9817319890212640), - (1889, 13896091485912489121, 9765348900852065), (1901, 9383483176894863973, 9703705456975040), - (1907, 2843913349591299515, 9673174658473807), (1913, 12053544219622027977, 9642835375697622), - (1931, 10661090826649331747, 9552948769399042), (1933, 6680145293117788997, 9543064704453984), - (1949, 13790100623599187637, 9464722459573910), (1951, 7043989920509285471, 9455020027529242), - (1973, 17128451669050125981, 9349591522407274), (1979, 736378363730699635, 9321245110515185), - (1987, 11864589293508206827, 9283716192103448), (1993, 11727057070441546361, 9255767222132238), - (1997, 13994400236189269253, 9237227878672784), (1999, 2768395808960913199, 9227986029869710), - (2003, 16319336244939253851, 9209557700304319), (2011, 15043590393278798931, 9172920971511462), - (2017, 493864243916864545, 9145634146608602), (2027, 11384744369122175171, 9100515083231155), - (2029, 5309462069515218405, 9091544639580853), (2039, 9698337247188150727, 9046956387302379), - (2053, 11797649765601871053, 8985262578523892), (2063, 3818109413220542191, 8941708227682768), - (2069, 3798121302755084093, 8915777705997849), (2081, 15698790847928695777, 8864365244454373), - (2083, 13345772116697212811, 8855854092035310), (2087, 12993154666196952983, 8838880725304049), - (2089, 7205621428505023513, 8830418417285568), (2099, 9913257415504704251, 8788348772610553), - (2111, 6859637185154901951, 8738391318668664), (2113, 34920480972474305, 8730120243118576), - (2129, 5588609641870672049, 8664511072667708), (2131, 16317274790681607131, 8656379199300587), - (2137, 13327923654566002665, 8632074905806996), (2141, 15749952436590873589, 8615947722423891), - (2143, 11310789413371138975, 8607906707283971), (2153, 15473673849103321049, 8567925719326312), - (2161, 6700922766248032401, 8536207345538894), (2179, 4893170295825663531, 8465692553331597), - (2203, 10433337773872946579, 8373465308084226), (2207, 10364278500860826463, 8358289113597440), - (2213, 8552354007964753709, 8335627688074808), (2221, 17059708386942556965, 8305602914772423), - (2237, 16393440866577822357, 8246197619002928), (2239, 15110017253766555455, 8238831654180237), - (2243, 14104398611864414187, 8224139132282457), (2251, 6883725020842302691, 8194910739097979), - (2267, 13865572078341894995, 8137072815928342), (2269, 4089339915855400821, 8129900429135985), - (2273, 15021963607759076129, 8115593521209657), (2281, 16036779262676914009, 8087130238364555), - (2287, 14583171528319575567, 8065913455928968), (2293, 13072812524979512157, 8044807707679699), - (2297, 4946971854333950281, 8030798464827841), (2309, 9770622781354171341, 7989061963494825), - (2311, 191571552474698935, 7982148019779122), (2333, 13362622153694445877, 7906877014020382), - (2339, 9984428387052711563, 7886594302569282), (2341, 12907204952044530349, 7879856503079688), - (2347, 10532014085543587203, 7859712004137005), (2351, 17214868778272546255, 7846339461382199), - (2357, 1017427547552923933, 7826365750407107), (2371, 18298921156206185323, 7780153552808752), - (2377, 18058718325419489529, 7760514965801241), (2381, 17276874961937127301, 7747477561406783), - (2383, 10241310285152218543, 7740975272223899), (2389, 13551291690816351229, 7721533726960883), - (2393, 2227793162265800425, 7708626859051212), (2399, 3252593890445660831, 7689347258736786), - (2411, 9357265865676806979, 7651075932687495), (2417, 5975920814941902737, 7632082777703579), - (2423, 2047946411815051335, 7613183687044800), (2437, 499583548980234061, 7569447711821728), - (2441, 15590181492856536249, 7557043864690516), (2447, 5435268687022716271, 7538514129019023), - (2459, 7749282890663670931, 7501725934814783), (2467, 14722999222186504715, 7477399300247082), - (2473, 12524093530027633305, 7459257611690073), (2477, 11342103845078581797, 7447211979697033), - (2503, 16596910768675153911, 7369853804917919), (2521, 18227227087509120617, 7317232873347699), - (2531, 6646950057377760203, 7288322431335263), (2539, 3465575786986788547, 7265358043997460), - (2543, 3358569605240866063, 7253930032917637), (2549, 10949362017858984541, 7236855266265026), - (2551, 16769109959597197255, 7231181526346355), (2557, 13101011825520745301, 7214213560308780), - (2579, 13311124746480603163, 7152673157700485), (2591, 17656474451099840991, 7119546149637032), - (2593, 8330558160552983009, 7114054791249345), (2609, 14154994877564784337, 7070427011770621), - (2617, 2283815468048106505, 7048813172987983), (2621, 15624483725156506901, 7038055732052480), - (2633, 11910165182417864697, 7005979519069332), (2647, 13603341304072929639, 6968924848398017), - (2657, 5963776123190253985, 6942696301734870), (2659, 7978095406079723339, 6937474266156281), - (2663, 4419460277516595543, 6927053726515040), (2671, 3549841427887199375, 6906306279936185), - (2677, 15855793094361478621, 6890827072734236), (2683, 3417082297664423091, 6875417097916344), - (2687, 14849388697965671807, 6865182014778396), (2689, 8472193726675826049, 6860075892045203), - (2693, 575390457553509965, 6849886399446547), (2699, 12705630690265304355, 6834658789814580), - (2707, 16695427772659180443, 6814460315371094), (2711, 10390327628386014503, 6804405781523257), - (2713, 8540033378761222569, 6799389632771674), (2719, 7639218031260373343, 6784385462931059), - (2729, 2142769465506019737, 6759525127779242), (2731, 13509149815971843, 6754574907985921), - (2741, 5155128041029374877, 6729932168445659), (2749, 7414933503619154069, 6710347062098781), - (2753, 8831387101034939713, 6700597193501471), (2767, 16100067559815167023, 6666694641745410), - (2777, 11511777990543267177, 6642687819124793), (2789, 14842055826964587245, 6614106874761402), - (2791, 10931893478292941015, 6609367278290774), (2797, 5111271597112943333, 6595189157565088), - (2801, 3839504389493990929, 6585770822459675), (2803, 14017682795933408827, 6581071735180004), - (2819, 9318255963448883115, 6543719075455676), (2833, 8647114765226362353, 6511381600321055), - (2837, 12601265426453687357, 6502200942442563), (2843, 10822781960938280723, 6488478393847890), - (2851, 1067594799074737291, 6470271509543862), (2857, 17813989114233340185, 6456683259961341), - (2861, 1972982763563482277, 6447656090076739), (2879, 12129102650757964991, 6407344242344408), - (2887, 9181839706934750839, 6389589218465379), (2897, 7144372402727689649, 6367533335764429), - (2903, 2923011461903683687, 6354372743268877), (2909, 16893133795930644725, 6341266439913905), - (2917, 9106380344923467373, 6323875239530185), (2927, 5123745449923425167, 6302269926105074), - (2939, 12345949504248617907, 6276537622902195), (2953, 12487315070553807545, 6246780925739773), - (2957, 386776507463642949, 6238330765542628), (2963, 273930725360519835, 6225698303648178), - (2969, 15172431467833858217, 6213116899194864), (2971, 13150523038746829459, 6208934390343167), - (2999, 8051613201895899655, 6150965012907486), (3001, 12760893267917703817, 6146865735991186), - (3011, 3394053874737659115, 6126451037432597), (3019, 6091886002480431587, 6110216652437744), - (3023, 14938018356745280303, 6102131681676993), (3037, 15847071217750484085, 6074001999904363), - (3041, 16426761904506894369, 6066012520128099), (3049, 3817610859465636953, 6050096449232388), - (3061, 17295705812331399261, 6026378331822787), (3067, 4559058365788014387, 6014588873071259), - (3079, 17218558774875365815, 5991147799191150), (3083, 1352242672934920099, 5983374659004071), - (3089, 13579765627586766065, 5971752694629184), (3109, 5684136642847780781, 5933336787941316), - (3119, 3761503440487103183, 5914313585671545), (3121, 4604297863960186065, 5910523573761471), - (3137, 12819222850075493313, 5880377454163070), (3163, 17274503934975558611, 5832040491213895), - (3167, 14584984894401236895, 5824674478594743), (3169, 10111074299789678497, 5820998445474771), - (3181, 3635997653007195493, 5799039318990742), (3187, 11414176125935122619, 5788121767715579), - (3191, 11781405334446902599, 5780866209247744), (3203, 8730959730172863019, 5759208265285529), - (3209, 1965966492118624697, 5748440035434575), (3217, 17322851677549442161, 5734144878367905), - (3221, 10663718554873388733, 5727023928503431), (3229, 5541449907555981749, 5712834956243280), - (3251, 15479150363912536699, 5674175353340372), (3253, 9611814080829292957, 5670686773350615), - (3257, 10279656276875295113, 5663722466597958), (3259, 3792365305119791219, 5660246724059389), - (3271, 2227595203031266551, 5639481526661434), (3299, 7162861218072729803, 5591616875934995), - (3301, 14054396045252808941, 5588229043838095), (3307, 9131333549640924099, 5578090134172830), - (3313, 11926630185899746321, 5567987948599321), (3319, 17407412605862704327, 5557922287951055), - (3323, 9281659973289909811, 5551232041441333), (3329, 4327698144057422593, 5541226816974932), - (3331, 1030049353860695467, 5537899751939222), (3343, 7432774234904805871, 5518020961325022), - (3347, 16142967849386099995, 5511426373979549), (3359, 15481206175584169695, 5491736848380336), - (3361, 18139389813629892321, 5488468929993915), (3371, 2670427501622741379, 5472187503325289), - (3373, 306260796954561189, 5468942802760021), (3389, 6221489665461793301, 5443123066895707), - (3391, 9770083266405884607, 5439912731851828), (3407, 3021216082515388847, 5414365739274890), - (3413, 12685176777320925181, 5404847369970568), (3433, 445988860506231513, 5373359765135319), - (3449, 8824913807370472649, 5348432610527559), (3457, 1371366279127380609, 5336055560806928), - (3461, 4130663581948830541, 5329888492837200), (3463, 3861937468506908727, 5326810301388839), - (3467, 10822231740964876835, 5320664572745760), (3469, 13655589155746938181, 5317597023265941), - (3491, 1976248147684724235, 5284085956376268), (3499, 13986628187353941251, 5272004593800957), - (3511, 2553437089097932807, 5253985780036898), (3517, 14135335592450168213, 5245022483283921), - (3527, 8849416210013201399, 5230151424357684), (3529, 17944934090406599801, 5227187326072414), - (3533, 13136713300156589829, 5221269197200552), (3539, 10956500718546899547, 5212417087795860), - (3541, 16279603284479624061, 5209473051033479), (3547, 10453328330464110163, 5200660860927417), - (3557, 9894964209344341997, 5186039942004372), (3559, 14139566685327242711, 5183125617788578), - (3571, 16742060359253054267, 5165708225625749), (3581, 13120317552565827413, 5151282902460081), - (3583, 10631461488197104127, 5148407500337580), (3593, 16916788678784573497, 5134078506459658), - (3607, 1493332206687881639, 5114151392766717), (3613, 8536660971835696181, 5105658475978287), - (3617, 17268641258938496481, 5100012185156082), (3623, 12876570732103631255, 5091566125782376), - (3631, 2667182770227902671, 5080348133767433), (3637, 15180397308939424797, 5071967026040569), - (3643, 4501552424245893875, 5063613525585932), (3659, 720930418841340771, 5041471460428956), - (3671, 13738326967453531495, 5024991575513361), (3673, 8708590858647525865, 5022255397143901), - (3677, 10826237071271474677, 5016791970005317), (3691, 11394900159322074691, 4997763227772839), - (3697, 419130782307709585, 4989652170329876), (3701, 3982423268007006685, 4984259409270346), - (3709, 10165851951108741845, 4973508782342828), (3719, 3625859079828363063, 4960135540120879), - (3727, 11992610917788635247, 4949488616503770), (3733, 1319389410040302781, 4941533370937463), - (3739, 17015999013165082515, 4933603657049893), (3761, 13002477675991497297, 4904744502448697), - (3767, 783509172230827783, 4896932326442673), (3769, 9925708936450774921, 4894333795094070), - (3779, 10304598237523382763, 4881382395795065), (3793, 9454381882228148785, 4863365165755220), - (3797, 10522951715474029181, 4858241789230853), (3803, 6330002896710745427, 4850576932345398), - (3821, 16868077412599103205, 4827726792386692), (3823, 14620359545733701647, 4825201170209142), - (3833, 3157073861819323209, 4812612594236773), (3847, 15996448721054084791, 4795098537486236), - (3851, 15850500166165906595, 4790117910597131), (3853, 15722581764355610565, 4787631475138736), - (3863, 16379066055610603687, 4775237917087639), (3877, 7550937024755496109, 4757994344521421), - (3881, 4515435936620477721, 4753090459600502), (3889, 6147333586918894033, 4743312952869517), - (3907, 8753586770580370795, 4721459962556834), (3911, 10055857418856753783, 4716631059501291), - (3917, 18117085639918469509, 4709406197015458), (3919, 5671938404904314799, 4707002825646734), - (3923, 15126988448922668251, 4702203434542327), (3929, 10653006440123943145, 4695022670834703), - (3931, 4368842211300837587, 4692633954136238), (3943, 9408166962269822039, 4678352542153069), - (3947, 15553778636256748867, 4673611369067532), (3967, 9128046033953075327, 4650048922034169), - (3989, 3838254595432170429, 4624403127026711), (4001, 9935699444849808481, 4610533385081117), - (4003, 16838471857440594955, 4608229846042855), (4007, 10680420826305505303, 4603629666510993), - (4013, 14433784298890603557, 4596746592003376), (4019, 8147044222651021179, 4589884069099166), - (4021, 13845380157785482909, 4587601112586309), (4027, 1575783452037766515, 4580765848946995), - (4049, 715272615355001137, 4555876530923574), (4051, 9325828650446102619, 4553627270725636), - (4057, 2259805719653351529, 4546892796083202), (4073, 17463944303516825689, 4529031199044819), - (4079, 10862730881355808527, 4522369226209745), (4091, 1848732600885093171, 4509103904597788), - (4093, 7918624318961075541, 4506900579943696), (4099, 5944900932268923563, 4500303506638095), - (4111, 12196120260847132399, 4487167130554500), (4127, 250307164557241311, 4469770795665023), - (4129, 15189859493972505569, 4467605733521325), (4133, 14023631715363031981, 4463281895405166), - (4139, 13931993712108252803, 4456811808096050), (4153, 1159306574341004809, 4441787641153275), - (4157, 4406451013998937877, 4437513609263784), (4159, 7069995204013711295, 4435379676294674), - (4177, 13182554718703138993, 4416266237421487), (4201, 10204768680623898585, 4391036437445739), - (4211, 6965168149417759931, 4380608899004880), (4217, 12773178253552736713, 4374376114230389), - (4219, 7913867450441879219, 4372302458807668), (4229, 14778332684258207821, 4361963602201360), - (4231, 248514396644160823, 4359901695511593), (4241, 13549070452630335601, 4349621333107651), - (4243, 12334059141436247451, 4347571075585564), (4253, 17570599633810814389, 4337348712369986), - (4259, 15835007357004489483, 4331238336160965), (4261, 15078622297284761389, 4329205368155257), - (4271, 15401800366857471567, 4319069087733446), (4273, 14306695497372678225, 4317047524855968), - (4283, 11396237408133428339, 4306968030284742), (4289, 6829897316169449281, 4300942894313255), - (4297, 10826783466114845049, 4292935553574482), (4327, 3465958616114135767, 4263171729537682), - (4337, 4249088616471257105, 4253341958429686), (4339, 3804986389944698939, 4251381441278993), - (4349, 8788607431760448597, 4241605903359289), (4357, 1752800561513829325, 4233817781434370), - (4363, 4879106729557832355, 4227995432892402), (4373, 14042810661188908605, 4218327023487205), - (4391, 17963625064719208087, 4201034860785595), (4397, 15606524438071305893, 4195302268298738), - (4409, 3782231037113502985, 4183883890612282), (4421, 1969432979595319693, 4172527499142626), - (4423, 1259533508989438071, 4170640758243172), (4441, 1013511721230608105, 4153736562420525), - (4447, 10581885345633700511, 4148132240546334), (4451, 14928144721074321483, 4144404420065053), - (4457, 15160516836885368537, 4138825235294940), (4463, 8303721452852899215, 4133261051693827), - (4481, 14552385695283031681, 4116657905313446), (4483, 8295479824358343979, 4114821341447591), - (4493, 15778063092647631173, 4105663047787569), (4507, 8402743639522012307, 4092909712382860), - (4513, 662169851526910561, 4087468219301917), (4517, 3695882972483317293, 4083848588379356), - (4519, 2249204687898641943, 4082041175859604), (4523, 3597176270840553731, 4078431146077725), - (4547, 4819602366300186347, 4056904348737530), (4549, 1184095245003998477, 4055120702068487), - (4561, 12804733991967647537, 4044451671499572), (4567, 8667990536934683111, 4039138181237037), - (4583, 4512066355362951639, 4025036891492374), (4591, 9422264180537769231, 4018023104706937), - (4597, 13996572401370223197, 4012778784796508), (4603, 5570491910157783347, 4007548136804160), - (4621, 14482749945773264069, 3991937691778738), (4637, 16867413170698403893, 3978163483655283), - (4639, 13106373888110946783, 3976448388383175), (4643, 1326989558608440715, 3973022630564193), - (4649, 5773287293449644569, 3967895047044429), (4651, 16011504155142003843, 3966188792455289), - (4657, 2150865800305837777, 3961078821926036), (4663, 636913102266188679, 3955982001653345), - (4673, 5542313006524333505, 3947516386413342), (4679, 13912921529412482935, 3942454386345277), - (4691, 2355489170784911835, 3932369233363792), (4703, 18325151671777806751, 3922335546185318), - (4721, 2961794536723541649, 3907380655308102), (4723, 13908290418479719099, 3905726037202953), - (4729, 3237639581556127689, 3900770580188105), (4733, 18244075429755844309, 3897473922186678), - (4751, 1615206384900689007, 3882707656011271), (4759, 17136594988415618343, 3876180725721696), - (4783, 3089241480878392399, 3856730937426207), (4787, 11117371350042209403, 3853508266912377), - (4789, 7965727029532543901, 3851898950450939), (4793, 16872632175911261065, 3848684346695086), - (4799, 7976035414241991999, 3843872488791321), (4801, 15891633719821434177, 3842271208854311), - (4813, 13560062441883314693, 3832691475942146), (4817, 4702636853335131697, 3829508838220791), - (4831, 8923626764698659103, 3818411110269002), (4861, 4770120818895886933, 3794845520203569), - (4871, 11845907506171931319, 3787054829338852), (4877, 9005884281218462661, 3782395750196750), - (4889, 14832102874565810473, 3773111898897433), (4903, 17190123123144797335, 3762338175343575), - (4909, 5264593287281947813, 3757739676860776), (4919, 7211443149775049351, 3750100441900701), - (4931, 13205639136117363051, 3740974259523332), (4933, 8869993298771347341, 3739457545856385), - (4937, 15565958235988250361, 3736427805085993), (4943, 8564693030379004847, 3731892387964707), - (4951, 3968043312159295591, 3725862264938305), (4957, 9638302834558753013, 3721352445775580), - (4967, 16541533743568017495, 3713860292673555), (4969, 10357499691215465689, 3712365480722389), - (4973, 5515847262740016741, 3709379463846682), (4987, 7294361201795716019, 3698966126671255), - (4993, 964270018673781889, 3694521144343991), (4999, 13125638861809336887, 3690086832108331), - (5003, 9487002298951564323, 3687136532822216), (5009, 2938810495272553841, 3682719918887912), - (5011, 17154625301035025051, 3681250064599790), (5021, 14901412858587122357, 3673918357639823), - (5023, 8751461502617929823, 3672455519352887), (5039, 7526593731999769423, 3660794616731405), - (5051, 3031240859469199731, 3652097421047228), (5059, 14629044717082965227, 3646322212632842), - (5077, 14050336681708653949, 3633394538843717), (5081, 10953321564727753833, 3630534161328390), - (5087, 4587208817228736543, 3626252029429831), (5099, 15849222550876945603, 3617717998374103), - (5101, 7395332607476187621, 3616299563558037), (5107, 10818092520219327803, 3612050924948022), - (5113, 14341053724427042377, 3607812257717494), (5119, 4551325994353421311, 3603583526803975), - (5147, 12293050742728533523, 3583979808375665), (5153, 2233799398795800545, 3579806728839423), - (5167, 11445763789493482191, 3570107233154548), (5171, 5586463202364950267, 3567345595379917), - (5179, 3344563175364601075, 3561835117534186), (5189, 16850562133240176269, 3554970914185691), - (5197, 4678239116634440837, 3549498571042823), (5209, 4228337958151123945, 3541321572990891), - (5227, 12210777596142155843, 3529126472873455), (5231, 818131260772436623, 3526427848157054), - (5233, 5062014999015271569, 3525080082879715), (5237, 16544654747797167069, 3522387640578489), - (5261, 7296649765707959877, 3506318964780374), (5273, 10047230984201371561, 3498339479178750), - (5279, 6384201822820108127, 3494363340350360), (5281, 2997028292982919009, 3493039968511560), - (5297, 8566922866023314513, 3482488969928176), (5303, 12933244289280051463, 3478548759892429), - (5309, 6038885138464343701, 3474617455963373), (5323, 4168971091616116963, 3465478879148891), - (5333, 15983949815228171389, 3458980700114298), (5347, 6623854240045322443, 3449924083356938), - (5351, 13155069217954709207, 3447345182902177), (5381, 15004905930240978893, 3428125640904952), - (5387, 14803280978401037987, 3424307420402738), (5393, 17827633990761020401, 3420497695848238), - (5399, 7250229843380564647, 3416696438916382), (5407, 17075264303479989983, 3411641219476521), - (5413, 8267467416002100909, 3407859610882976), (5417, 6194319267136362265, 3405343192488379), - (5419, 9225074080042975619, 3404086376399621), (5431, 9948538647007047815, 3396564918746004), - (5437, 11023261264572803605, 3392816640373285), (5441, 6736570570568071873, 3390322380758969), - (5443, 1633534933589565291, 3389076625704492), (5449, 8693565568230157561, 3385344847441650), - (5471, 7279568717810075295, 3371731689583175), (5477, 14122183293968258157, 3368037990452720), - (5479, 17918155130549778007, 3366808555157793), (5483, 9891195983349641027, 3364352375288993), - (5501, 10026497869549456341, 3353343769080085), (5503, 305043378285947519, 3352125036109313), - (5507, 2599359615253061931, 3349690225841574), (5519, 8001722288903907695, 3342406971137806), - (5521, 12486050100244990833, 3341196173466682), (5527, 15569759562846943783, 3337569038123674), - (5531, 2498031334516082835, 3335155319781151), (5557, 15827618453022699677, 3319550850046707), - (5563, 1369495830027331443, 3315970532753829), (5569, 14359245027748411969, 3312397930276450), - (5573, 15080453256741560589, 3310020468995074), (5581, 13835884374224723717, 3305275770240019), - (5591, 16546310414890610151, 3299363991005106), (5623, 13912972010777557959, 3280587599806073), - (5639, 843990064021469111, 3271279317912670), (5641, 4133431042221037625, 3270119495428036), - (5647, 7993480210442229999, 3266644957271038), (5651, 5957407172981761051, 3264332697524252), - (5653, 3899497464723671357, 3263177794747842), (5657, 3759783616225404457, 3260870439050654), - (5659, 6816070305376687123, 3259717984398224), (5669, 14714442882574456237, 3253967908574625), - (5683, 2054687488766170363, 3245951798998689), (5689, 17999275154361350153, 3242528401073923), - (5693, 14694534406160691477, 3240250144688134), (5701, 11150233306087197837, 3235703222892396), - (5711, 16615312820024852655, 3230037484452731), (5717, 10486604554758797053, 3226647555310399), - (5737, 2205763715280591321, 3215399001866751), (5741, 2609084861148259173, 3213158695995393), - (5743, 346900289040681103, 3212039713339639), (5749, 2717758258902763997, 3208687436721090), - (5779, 4197520065223751579, 3192030467850761), (5783, 10344594679412082983, 3189822596180105), - (5791, 8043175407721743711, 3185416003058116), (5801, 10566890287353359769, 3179924853251086), - (5807, 10819633255563067471, 3176639241210530), (5813, 13007604327909074845, 3173360411785575), - (5821, 1191543681792611477, 3168999153703753), (5827, 819925641855289835, 3165736068939342), - (5839, 14295515830370906159, 3159230017761526), (5843, 14490938781161533787, 3157067272584212), - (5849, 649688712460962153, 3153828701266806), (5851, 1588986329370981715, 3152750653513852), - (5857, 16739703730880359713, 3149520927729136), (5861, 13656444725443737325, 3147371450897381), - (5867, 5499123126797001155, 3144152731158948), (5869, 2618186712114509541, 3143081287052232), - (5879, 15525512787330304711, 3137735001481468), (5881, 9798950601303968585, 3136667926153639), - (5897, 6043600059421206329, 3128157380652798), (5903, 9878054890224613359, 3124977820381086), - (5923, 2229928880090501259, 3114425810182264), (5927, 13031300394233489559, 3112323953721874), - (5939, 8684474899830258683, 3106035371899234), (5953, 167331459764877505, 3098730736386620), - (5981, 1761091935477036277, 3084224055126158), (5987, 4159529731001819723, 3081133134075422), - (6007, 5008596568040665671, 3070874658516655), (6011, 1224463630911680435, 3068831155167118), - (6029, 6296798690279359301, 3059668945713974), (6037, 9414347936243022781, 3055614390211951), - (6043, 12027167243159959187, 3052580518568517), (6047, 9465891658792911967, 3050561282240706), - (6053, 5250906994713622573, 3047537431638782), (6067, 12578569347772608379, 3040505039345566), - (6073, 2019938219828231817, 3037501082448468), (6079, 12930017519012403263, 3034503055388970), - (6089, 13023904216271532665, 3029519473429060), (6091, 3534288349042693603, 3028524720687826), - (6101, 4934451127404358013, 3023560739831101), (6113, 14047046239672495137, 3017625400574112), - (6121, 12365134934558126169, 3013681436645899), (6131, 13226535140764506427, 3008765955587922), - (6133, 12392073305671507037, 3007784782929977), (6143, 9690321199065720831, 3002888502964276), - (6151, 17867940365983012279, 2998982941588286), (6163, 5827650610337903131, 2993143610856652), - (6173, 16486422655865154101, 2988294844274996), (6197, 10207178542641609245, 2976721651397378), - (6199, 14244969169357577607, 2975761263705364), (6203, 16347211377266065651, 2973842346237232), - (6211, 13388813763368645739, 2970011926213097), (6217, 2222392039763302905, 2967145580458348), - (6221, 5610229832415764613, 2965237754976619), (6229, 9361078506501186813, 2961429454761526), - (6247, 17153375432076002135, 2952896442085729), (6257, 17739181571281823889, 2948177093448865), - (6263, 3572712847103574343, 2945352718139797), (6269, 15030462390893027541, 2942533749195972), - (6271, 15458083257430026111, 2941595291613706), (6277, 13198076730130571341, 2938783507043102), - (6287, 11343265880222860911, 2934109125768975), (6299, 12282210612023790995, 2928519459233140), - (6301, 3940536029711642037, 2927589918062141), (6311, 14059394548335120151, 2922951049549921), - (6317, 17115144374863334181, 2920174778171529), (6323, 9411544580387001979, 2917403775693429), - (6329, 17248827844558876041, 2914638027130597), (6337, 14927395235913299777, 2910958509343467), - (6343, 6293355537680509175, 2908204961959569), (6353, 3205604510841389105, 2903627274312852), - (6359, 12865436384164469479, 2900887572528628), (6361, 17086655570240005993, 2899975487141888), - (6367, 14680328603971461919, 2897242669029299), (6373, 10177114728254006509, 2894514996659273), - (6379, 9323138876569931715, 2891792455511765), (6389, 11153509525237125981, 2887266250384966), - (6397, 15969684020666483797, 2883655475021033), (6421, 14505156646653095485, 2872877133423072), - (6427, 10054293525782567187, 2870195125830022), (6449, 12242528242437103569, 2860403794961940), - (6451, 8564253371688126971, 2859516985538606), (6469, 15991550589791801741, 2851560376211091), - (6473, 5639750737196230905, 2849798250225483), (6481, 5610018912094048177, 2846280523639801), - (6491, 9128168535627034323, 2841895559037059), (6521, 8557184607111086281, 2828821357722673), - (6529, 14697497728815605377, 2825355195850750), (6547, 518436063779220635, 2817587303147938), - (6551, 13597821268805285415, 2815866901802709), (6553, 17436156385252092585, 2815007488739440), - (6563, 17465803393879499275, 2810718280315336), (6569, 10626043473118730905, 2808151023551461), - (6571, 18101446627192084739, 2807296313150137), (6577, 7505471665082371921, 2804735300852904), - (6581, 1345454665762131101, 2803030553671106), (6599, 7161775771608406007, 2795384766435755), - (6607, 3696608014770916655, 2792000011156281), (6619, 15353242650259241555, 2786938219324603), - (6637, 8357595213145189349, 2779379851395141), (6653, 1186713732684155733, 2772695637112513), - (6659, 12391092692852203691, 2770197337995127), (6661, 4536220806596043469, 2769365571792456), - (6673, 10526779774117484273, 2764385444883793), (6679, 13467034601498394023, 2761902092185888), - (6689, 17961376013166438881, 2757773071267685), (6691, 8973868175149393291, 2756948748125773), - (6701, 16605097784303240613, 2752834513312871), (6703, 14324228390818770127, 2752013139446449), - (6709, 9246743228481923101, 2749551956134975), (6719, 4530008590805292479, 2745459752003207), - (6733, 3843870776090078853, 2739751087733484), (6737, 5292794462591741617, 2738124398650668), - (6761, 3486901187132200409, 2728404684766979), (6763, 8150062293692760643, 2727597822521004), - (6779, 5891311538513228979, 2721160063978396), (6781, 6999479796734209749, 2720357480269805), - (6791, 11036536765054028599, 2716351652732962), (6793, 12073343758532705209, 2715551902503982), - (6803, 4238168600206971803, 2711560204866904), (6823, 627237963520535831, 2703611911726447), - (6827, 1680661317393780739, 2702027841469100), (6829, 6950281520230586661, 2701236502227200), - (6833, 3018214528670756433, 2699655213480104), (6841, 9284043245984795529, 2696498183556432), - (6857, 14225810509227958137, 2690206223378963), (6863, 14941782064075680815, 2687854301866465), - (6869, 9963229074605100669, 2685506489111886), (6871, 15958004187764455655, 2684724796057277), - (6883, 2355758832019569355, 2680044177496665), (6899, 17246194995713379899, 2673828681505950), - (6907, 17672231871396569139, 2670731732113732), (6911, 16193951135175206143, 2669185946130741), - (6917, 370695016082930125, 2666870619301655), (6947, 6718045560167722123, 2655353976350878), - (6949, 5802933162344089773, 2654589735747525), (6959, 7962928466363485135, 2650775121958550), - (6961, 12534563923092397521, 2650013514395855), (6967, 977012855346465415, 2647731315302074), - (6971, 3191331710356293107, 2646212031804554), (6977, 14766384642635494593, 2643936372898029), - (6983, 2826581148341575287, 2641664624618294), (6991, 16045580133346843567, 2638641692706272), - (6997, 9506782782592059901, 2636379030114270), (7001, 5401489123140205801, 2634872742995222), - (7013, 5523764801766727277, 2630364191317489), (7019, 1952689962496964931, 2628115696496588), - (7027, 4502087104939786683, 2625123676349729), (7039, 9670192588718318719, 2620648398026644), - (7043, 12207904888195402539, 2619160027503840), (7057, 13242341714242962801, 2613964017813454), - (7069, 10281535104033899189, 2609526676150735), (7079, 16080641005630970903, 2605840383346454), - (7103, 17083300368416363583, 2597035629129881), (7109, 12639483806870055693, 2594843729597629), - (7121, 11885081001289063729, 2590471011614878), (7127, 16831651004817344487, 2588290174506742), - (7129, 16953719619995087977, 2587564044565794), (7151, 7261583634106053391, 2579603422417780), - (7159, 5158595004269663687, 2576720781353478), (7177, 17238722656035942969, 2570258335475763), - (7187, 10628630472969424411, 2566682075095248), (7193, 9324671409983029289, 2564541091854518), - (7207, 6974799167595189143, 2559559327557867), (7211, 12552790621230449283, 2558139519305165), - (7213, 5431981756905460645, 2557430205699369), (7219, 9740821223019921147, 2555304623037754), - (7229, 13549897777202617109, 2551769826215182), (7237, 779978400795235981, 2548949022206653), - (7243, 1319261829377543523, 2546837508450856), (7247, 6600304592676813487, 2545431775039264), - (7253, 4702609925863637245, 2543326082132848), (7283, 11559925848195852475, 2532849659990327), - (7297, 1266523061659378561, 2527990143032691), (7307, 7389300657417251619, 2524530460340707), - (7309, 9509827838245668421, 2523839659831652), (7321, 7339894206626953129, 2519702782913475), - (7331, 7936302115465819915, 2516265730965700), (7333, 4512949525192272685, 2515579445480642), - (7349, 8313459841083961757, 2510102609022935), (7351, 7613579311608594695, 2509419680820235), - (7369, 10356110765766917497, 2503290008645616), (7393, 13329163646930396961, 2495163543042006), - (7411, 12017390418009676859, 2489103234881871), (7417, 16529197939041887561, 2487089668829655), - (7433, 16411720511158518073, 2481736051891504), (7451, 4867306247337669907, 2475740715838082), - (7457, 13959363927577175777, 2473748702388299), (7459, 7204097799532903051, 2473085410069654), - (7477, 16714817587184995613, 2467131747185977), (7481, 8879391178910318857, 2465812601752379), - (7487, 8327767459481539263, 2463836526473828), (7489, 2943498353329271489, 2463178538350854), - (7499, 7741285984793166947, 2459893862342919), (7507, 6275873766385266395, 2457272422233855), - (7517, 15651634122937278197, 2454003468632373), (7523, 10828236319221238859, 2452046267939592), - (7529, 4687026353168597721, 2450092186706010), (7537, 14956621073960338321, 2447491584676867), - (7541, 1223096676416228061, 2446193352832456), (7547, 11989039311189260723, 2444248585359686), - (7549, 8528167547654833109, 2443601016520009), (7559, 8011729169729919031, 2440368312436770), - (7561, 7380161463162464441, 2439722797739657), (7573, 10532645104281011645, 2435856869630206), - (7577, 8104686686205503145, 2434570948094173), (7583, 11637771811766648415, 2432644609482995), - (7589, 3417594171516092973, 2430721316867775), (7591, 14242704125413210647, 2430080894968983), - (7603, 2938183226787092859, 2426245439130547), (7607, 6697766153751252999, 2424969642922249), - (7621, 10459044894698723597, 2420514902730553), (7639, 12602900552518673895, 2414811372392924), - (7643, 8312257829367486035, 2413547569502754), (7649, 8303325904795657761, 2411654343536351), - (7669, 1820861294014621277, 2405364985488271), (7673, 17468270877045953609, 2404111048313508), - (7681, 13079152223072805377, 2401607092007492), (7687, 12399418060212989879, 2399732545038318), - (7691, 16966879154521046435, 2398484471942471), (7699, 12504683377151597595, 2395992216354013), - (7703, 16902131594475141543, 2394748029820790), (7717, 12155201971596873133, 2390403534237339), - (7723, 5099546626617880707, 2388546429329218), (7727, 11158286760776296655, 2387309961655176), - (7741, 15213023403508820245, 2382992387767672), (7753, 6999912429363278841, 2379304020857674), - (7757, 9407673012194790021, 2378077101161473), (7759, 4426838183431780527, 2377464115699130), - (7789, 8521168978971237221, 2368307109219354), (7793, 10912291823405752977, 2367091501823373), - (7817, 15223224513176451001, 2359823982820717), (7823, 5647443698905071727, 2358014070524038), - (7829, 13225389511525317821, 2356206932393607), (7841, 3761808924099167585, 2352600953157703), - (7853, 14765851680547337509, 2349005994360060), (7867, 16228538926419703411, 2344825737092862), - (7873, 17809437533883691329, 2343038749359780), (7877, 3187256402731839501, 2341848936614136), - (7879, 15749618908978823927, 2341254483273201), (7883, 13069271299209418467, 2340066481505715), - (7901, 7641588830939294069, 2334735359284843), (7907, 12420698804657854155, 2332963712369995), - (7919, 12818844884155027471, 2329428472497733), (7927, 7937661667140567751, 2327077592242910), - (7933, 17988656517612138069, 2325317543641693), (7937, 12066964247284867329, 2324145656256715), - (7949, 10178314191381317573, 2320637070538376), (7951, 5681810619609444335, 2320053335896057), - (7963, 6180574304741565203, 2316557085735219), (7993, 7117447607071219465, 2307862388803897), - (8009, 15818733711853814521, 2303251850881452), (8011, 6594866437037093475, 2302676828574404), - (8017, 12876135691215997361, 2300953483062186), (8039, 16092426444697734231, 2294656558491050), - (8053, 7540876877021214941, 2290667338098789), (8059, 6493784953110063027, 2288961915089905), - (8069, 14763796409470353741, 2286125179540160), (8081, 12739918163021037937, 2282730364275405), - (8087, 10456272391972868135, 2281036734723575), (8089, 11422888004105716905, 2280472749871374), - (8093, 18241602968231501493, 2279345616422779), (8101, 4561020661602299949, 2277094688767997), - (8111, 16802434375116035919, 2274287273296702), (8117, 16051417197561976477, 2272606144352538), - (8123, 11545395404498259315, 2270927498917832), (8147, 11443457045357563995, 2264237642532165), - (8161, 12755174219819017249, 2260353397097114), (8167, 10672323466178233303, 2258692797074758), - (8171, 17536936478347301059, 2257587085266130), (8179, 16031233265182478651, 2255378906187743), - (8191, 18442239924259250175, 2252074725150720), -]; - -#[allow(dead_code)] -pub const NEXT_PRIME: u64 = 8209; diff --git a/src/factor/sieve.rs b/src/factor/sieve.rs deleted file mode 100644 index 6b389ec39..000000000 --- a/src/factor/sieve.rs +++ /dev/null @@ -1,212 +0,0 @@ -/* -* This file is part of the uutils coreutils package. -* -* (c) kwantam -* -* For the full copyright and license information, please view the LICENSE file -* that was distributed with this source code. -*/ - -use std::iter::{Chain, Cycle, Map}; -use std::slice::Iter; - -/// A lazy Sieve of Eratosthenes. -/// -/// This is a reasonably efficient implementation based on -/// O'Neill, M. E. "[The Genuine Sieve of Eratosthenes.](http://dx.doi.org/10.1017%2FS0956796808007004)" -/// Journal of Functional Programming, Volume 19, Issue 1, 2009, pp. 95--106. -pub struct Sieve { - inner: Wheel, - filts: PrimeHeap, -} - -impl Iterator for Sieve { - type Item = u64; - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.inner.size_hint() - } - - #[inline] - fn next(&mut self) -> Option { - while let Some(n) = self.inner.next() { - let mut prime = true; - while let Some((next, inc)) = self.filts.peek() { - // need to keep checking the min element of the heap - // until we've found an element that's greater than n - if next > n { - break; // next heap element is bigger than n - } - - if next == n { - // n == next, and is composite. - prime = false; - } - // Increment the element in the prime heap. - self.filts.replace((next + inc, inc)); - } - - if prime { - // this is a prime; add it to the heap - self.filts.insert(n); - return Some(n); - } - } - None - } -} - -impl Sieve { - fn new() -> Sieve { - Sieve { inner: Wheel::new(), filts: PrimeHeap::new() } - } - - #[allow(dead_code)] - #[inline] - pub fn primes() -> PrimeSieve { - fn deref(x: &u64) -> u64 { *x } - let deref = deref as fn(&u64) -> u64; - INIT_PRIMES.iter().map(deref).chain(Sieve::new()) - } - - #[allow(dead_code)] - #[inline] - pub fn odd_primes() -> PrimeSieve { - fn deref(x: &u64) -> u64 { *x } - let deref = deref as fn(&u64) -> u64; - (&INIT_PRIMES[1..]).iter().map(deref).chain(Sieve::new()) - } -} - -pub type PrimeSieve = Chain, fn(&u64) -> u64>, Sieve>; - -/// An iterator that generates an infinite list of numbers that are -/// not divisible by any of 2, 3, 5, or 7. -struct Wheel { - next: u64, - increment: Cycle>, -} - -impl Iterator for Wheel { - type Item = u64; - - #[inline] - fn size_hint(&self) -> (usize, Option) { - (1, None) - } - - #[inline] - fn next (&mut self) -> Option { - let increment = self.increment.next().unwrap(); // infinite iterator, no check necessary - let ret = self.next; - self.next = ret + increment; - Some(ret) - } -} - -impl Wheel { - #[inline] - fn new() -> Wheel { - Wheel { next: 11u64, increment: WHEEL_INCS.iter().cycle() } - } -} - -/// The increments of a wheel of circumference 210 -/// (i.e., a wheel that skips all multiples of 2, 3, 5, 7) -const WHEEL_INCS: &'static [u64] = &[2,4,2,4,6,2,6,4,2,4,6,6,2,6,4,2,6,4,6,8,4,2,4,2,4,8,6,4,6,2,4,6,2,6,6,4,2,4,6,2,6,4,2,4,2,10,2,10]; -const INIT_PRIMES: &'static [u64] = &[2, 3, 5, 7]; - -/// A min-heap of "infinite lists" of prime multiples, where a list is -/// represented as (head, increment). -#[derive(Debug)] -struct PrimeHeap { - data: Vec<(u64, u64)>, -} - -impl PrimeHeap { - fn new() -> PrimeHeap { - PrimeHeap { data: Vec::new() } - } - - fn peek(&self) -> Option<(u64, u64)> { - if let Some(&(x, y)) = self.data.get(0) { - Some((x, y)) - } else { - None - } - } - - fn insert(&mut self, next: u64) { - let mut idx = self.data.len(); - let key = next * next; - - let item = (key, next); - self.data.push(item); - loop { - // break if we've bubbled to the top - if idx == 0 { - break; - } - - let paridx = (idx - 1) / 2; - let (k, _) = self.data[paridx]; - if key < k { - // bubble up, found a smaller key - self.data.swap(idx, paridx); - idx = paridx; - } else { - // otherwise, parent is smaller, so we're done - break; - } - } - } - - fn remove(&mut self) -> (u64, u64) { - let ret = self.data.swap_remove(0); - - let mut idx = 0; - let len = self.data.len(); - let (key, _) = self.data[0]; - loop { - let child1 = 2*idx + 1; - let child2 = 2*idx + 2; - - // no more children - if child1 >= len { - break; - } - - // find lesser child - let (c1key, _) = self.data[child1]; - let (minidx, minkey) = if child2 >= len { - (child1, c1key) - } else { - let (c2key, _) = self.data[child2]; - if c1key < c2key { - (child1, c1key) - } else { - (child2, c2key) - } - }; - - if minkey < key { - self.data.swap(minidx, idx); - idx = minidx; - continue; - } - - // smaller than both children, so done - break; - } - - ret - } - - /// More efficient than inserting and removing in two steps - /// because we save one traversal of the heap. - fn replace(&mut self, next: (u64, u64)) -> (u64, u64) { - self.data.push(next); - self.remove() - } -} diff --git a/src/false/Cargo.toml b/src/false/Cargo.toml deleted file mode 100644 index e101245ec..000000000 --- a/src/false/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "false" -version = "0.0.1" -authors = [] - -[lib] -name = "false" -path = "false.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/false/false.rs b/src/false/false.rs deleted file mode 100644 index bd19e7dea..000000000 --- a/src/false/false.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![crate_name = "false"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -pub fn uumain(_: Vec) -> i32 { - 1 -} diff --git a/src/fmt/Cargo.toml b/src/fmt/Cargo.toml deleted file mode 100644 index 3c3f3fa93..000000000 --- a/src/fmt/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "fmt" -version = "0.0.1" -authors = [] - -[lib] -name = "fmt" -path = "fmt.rs" - -[dependencies] -getopts = "*" -libc = "*" -unicode-width = "*" diff --git a/src/fmt/deps.mk b/src/fmt/deps.mk deleted file mode 100644 index fb8005c0c..000000000 --- a/src/fmt/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += unicode-width diff --git a/src/fmt/fmt.rs b/src/fmt/fmt.rs deleted file mode 100644 index 9d2b2df2e..000000000 --- a/src/fmt/fmt.rs +++ /dev/null @@ -1,221 +0,0 @@ -#![crate_name = "fmt"] -#![feature(iter_cmp, str_char, unicode)] - -/* - * This file is part of `fmt` from the uutils coreutils package. - * - * (c) kwantam - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate rustc_unicode; -extern crate unicode_width; - -use std::cmp; -use std::io::{Read, BufReader, BufWriter}; -use std::fs::File; -use std::io::{stdin, stdout, Write}; -use linebreak::break_lines; -use parasplit::ParagraphStream; - -macro_rules! silent_unwrap( - ($exp:expr) => ( - match $exp { - Ok(_) => (), - Err(_) => ::std::process::exit(1), - } - ) -); - -#[path = "../common/util.rs"] -#[macro_use] -mod util; -mod linebreak; -mod parasplit; - -// program's NAME and VERSION are used for -V and -h -static NAME: &'static str = "fmt"; -static VERSION: &'static str = "0.0.3"; - -pub type FileOrStdReader = BufReader>; -pub struct FmtOptions { - crown : bool, - tagged : bool, - mail : bool, - split_only : bool, - use_prefix : bool, - prefix : String, - xprefix : bool, - use_anti_prefix : bool, - anti_prefix : String, - xanti_prefix : bool, - uniform : bool, - quick : bool, - width : usize, - goal : usize, - tabwidth : usize, -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("c", "crown-margin", "First and second line of paragraph may have different indentations, in which case the first line's indentation is preserved, and each subsequent line's indentation matches the second line."); - opts.optflag("t", "tagged-paragraph", "Like -c, except that the first and second line of a paragraph *must* have different indentation or they are treated as separate paragraphs."); - opts.optflag("m", "preserve-headers", "Attempt to detect and preserve mail headers in the input. Be careful when combining this flag with -p."); - opts.optflag("s", "split-only", "Split lines only, do not reflow."); - opts.optflag("u", "uniform-spacing", "Insert exactly one space between words, and two between sentences. Sentence breaks in the input are detected as [?!.] followed by two spaces or a newline; other punctuation is not interpreted as a sentence break."); - - opts.optopt("p", "prefix", "Reformat only lines beginning with PREFIX, reattaching PREFIX to reformatted lines. Unless -x is specified, leading whitespace will be ignored when matching PREFIX.", "PREFIX"); - opts.optopt("P", "skip-prefix", "Do not reformat lines beginning with PSKIP. Unless -X is specified, leading whitespace will be ignored when matching PSKIP", "PSKIP"); - - opts.optflag("x", "exact-prefix", "PREFIX must match at the beginning of the line with no preceding whitespace."); - opts.optflag("X", "exact-skip-prefix", "PSKIP must match at the beginning of the line with no preceding whitespace."); - - opts.optopt("w", "width", "Fill output lines up to a maximum of WIDTH columns, default 79.", "WIDTH"); - opts.optopt("g", "goal", "Goal width, default ~0.94*WIDTH. Must be less than WIDTH.", "GOAL"); - - opts.optflag("q", "quick", "Break lines more quickly at the expense of a potentially more ragged appearance."); - - opts.optopt("T", "tab-width", "Treat tabs as TABWIDTH spaces for determining line length, default 8. Note that this is used only for calculating line lengths; tabs are preserved in the output.", "TABWIDTH"); - - opts.optflag("V", "version", "Output version information and exit."); - opts.optflag("h", "help", "Display this help message and exit."); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "{}\nTry `{} --help' for more information.", f, NAME) - }; - - if matches.opt_present("h") { - println!("Usage: {} [OPTION]... [FILE]...\n\n{}", NAME, opts.usage("Reformat paragraphs from input files (or stdin) to stdout.")); - } - - if matches.opt_present("V") || matches.opt_present("h") { - println!("{} {}", NAME, VERSION); - return 0 - } - - let mut fmt_opts = FmtOptions { - crown : false, - tagged : false, - mail : false, - uniform : false, - quick : false, - split_only : false, - use_prefix : false, - prefix : String::new(), - xprefix : false, - use_anti_prefix : false, - anti_prefix : String::new(), - xanti_prefix : false, - width : 79, - goal : 74, - tabwidth : 8, - }; - - if matches.opt_present("t") { fmt_opts.tagged = true; } - if matches.opt_present("c") { fmt_opts.crown = true; fmt_opts.tagged = false; } - if matches.opt_present("m") { fmt_opts.mail = true; } - if matches.opt_present("u") { fmt_opts.uniform = true; } - if matches.opt_present("q") { fmt_opts.quick = true; } - if matches.opt_present("s") { fmt_opts.split_only = true; fmt_opts.crown = false; fmt_opts.tagged = false; } - if matches.opt_present("x") { fmt_opts.xprefix = true; } - if matches.opt_present("X") { fmt_opts.xanti_prefix = true; } - - match matches.opt_str("p") { - Some(s) => { - fmt_opts.prefix = s; - fmt_opts.use_prefix = true; - } - None => () - }; - - match matches.opt_str("P") { - Some(s) => { - fmt_opts.anti_prefix = s; - fmt_opts.use_anti_prefix = true; - } - None => () - }; - - match matches.opt_str("w") { - Some(s) => { - fmt_opts.width = - match s.parse::() { - Ok(t) => t, - Err(e) => { crash!(1, "Invalid WIDTH specification: `{}': {}", s, e); } - }; - fmt_opts.goal = cmp::min(fmt_opts.width * 94 / 100, fmt_opts.width - 3); - } - None => () - }; - - match matches.opt_str("g") { - Some(s) => { - fmt_opts.goal = - match s.parse::() { - Ok(t) => t, - Err(e) => { crash!(1, "Invalid GOAL specification: `{}': {}", s, e); } - }; - if !matches.opt_present("w") { - fmt_opts.width = cmp::max(fmt_opts.goal * 100 / 94, fmt_opts.goal + 3); - } else if fmt_opts.goal > fmt_opts.width { - crash!(1, "GOAL cannot be greater than WIDTH."); - } - } - None => () - }; - - match matches.opt_str("T") { - Some(s) => { - fmt_opts.tabwidth = - match s.parse::() { - Ok(t) => t, - Err(e) => { crash!(1, "Invalid TABWIDTH specification: `{}': {}", s, e); } - }; - } - None => () - }; - - if fmt_opts.tabwidth < 1 { - fmt_opts.tabwidth = 1; - } - - // immutable now - let fmt_opts = fmt_opts; - - let mut files = matches.free; - if files.is_empty() { - files.push("-".to_string()); - } - - let mut ostream = BufWriter::new(stdout()); - - for i in files.iter().map(|x| &x[..]) { - let mut fp = match i { - "-" => BufReader::new(Box::new(stdin()) as Box), - _ => match File::open(i) { - Ok(f) => BufReader::new(Box::new(f) as Box), - Err(e) => { - show_warning!("{}: {}", i, e); - continue; - }, - }, - }; - let p_stream = ParagraphStream::new(&fmt_opts, &mut fp); - for para_result in p_stream { - match para_result { - Err(s) => silent_unwrap!(ostream.write_all(s.as_bytes())), - Ok(para) => break_lines(¶, &fmt_opts, &mut ostream) - } - } - - // flush the output after each file - silent_unwrap!(ostream.flush()); - } - - 0 -} diff --git a/src/fmt/linebreak.rs b/src/fmt/linebreak.rs deleted file mode 100644 index c4394baf9..000000000 --- a/src/fmt/linebreak.rs +++ /dev/null @@ -1,452 +0,0 @@ -/* - * This file is part of `fmt` from the uutils coreutils package. - * - * (c) kwantam - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use FmtOptions; -use parasplit::{Paragraph, ParaWords, WordInfo}; -use std::io::{Write, BufWriter, Stdout}; -use std::i64; -use std::cmp; -use std::mem; - -struct BreakArgs<'a> { - opts : &'a FmtOptions, - init_len : usize, - indent_str : &'a str, - indent_len : usize, - uniform : bool, - ostream : &'a mut BufWriter -} - -impl<'a> BreakArgs<'a> { - #[inline(always)] - fn compute_width<'b>(&self, winfo: &WordInfo<'b>, posn: usize, fresh: bool) -> usize { - if fresh { - 0 - } else { - let post = winfo.after_tab; - match winfo.before_tab { - None => post, - Some(pre) => post + ((pre + posn) / self.opts.tabwidth + 1) * self.opts.tabwidth - posn - } - } - } -} - -pub fn break_lines(para: &Paragraph, opts: &FmtOptions, ostream: &mut BufWriter) { - // indent - let p_indent = ¶.indent_str[..]; - let p_indent_len = para.indent_len; - - // words - let p_words = ParaWords::new(opts, para); - let mut p_words_words = p_words.words(); - - // the first word will *always* appear on the first line - // make sure of this here - let (w, w_len) = match p_words_words.next() { - Some(winfo) => (winfo.word, winfo.word_nchars), - None => { - silent_unwrap!(ostream.write_all("\n".as_bytes())); - return; - } - }; - // print the init, if it exists, and get its length - let p_init_len = w_len + - if opts.crown || opts.tagged { - // handle "init" portion - silent_unwrap!(ostream.write_all(para.init_str.as_bytes())); - para.init_len - } else if !para.mail_header { - // for non-(crown, tagged) that's the same as a normal indent - silent_unwrap!(ostream.write_all(p_indent.as_bytes())); - p_indent_len - } else { - // except that mail headers get no indent at all - 0 - }; - // write first word after writing init - silent_unwrap!(ostream.write_all(w.as_bytes())); - - // does this paragraph require uniform spacing? - let uniform = para.mail_header || opts.uniform; - - let mut break_args = BreakArgs { - opts : opts, - init_len : p_init_len, - indent_str : &p_indent[..], - indent_len : p_indent_len, - uniform : uniform, - ostream : ostream - }; - - if opts.quick || para.mail_header { - break_simple(p_words_words, &mut break_args); - } else { - break_knuth_plass(p_words_words, &mut break_args); - } -} - -// break_simple implements a "greedy" breaking algorithm: print words until -// maxlength would be exceeded, then print a linebreak and indent and continue. -fn break_simple<'a, T: Iterator>>(iter: T, args: &mut BreakArgs<'a>) { - iter.fold((args.init_len, false), |l, winfo| accum_words_simple(args, l, winfo)); - silent_unwrap!(args.ostream.write_all("\n".as_bytes())); -} - -#[inline(always)] -fn accum_words_simple<'a>(args: &mut BreakArgs<'a>, (l, prev_punct): (usize, bool), winfo: &'a WordInfo<'a>) -> (usize, bool) { - // compute the length of this word, considering how tabs will expand at this position on the line - let wlen = winfo.word_nchars + args.compute_width(winfo, l, false); - - let slen = compute_slen(args.uniform, winfo.new_line, winfo.sentence_start, prev_punct); - - if l + wlen + slen > args.opts.width { - write_newline(args.indent_str, args.ostream); - write_with_spaces(&winfo.word[winfo.word_start..], 0, args.ostream); - (args.indent_len + winfo.word_nchars, winfo.ends_punct) - } else { - write_with_spaces(winfo.word, slen, args.ostream); - (l + wlen + slen, winfo.ends_punct) - } -} - -// break_knuth_plass implements an "optimal" breaking algorithm in the style of -// Knuth, D.E., and Plass, M.F. "Breaking Paragraphs into Lines." in Software, -// Practice and Experience. Vol. 11, No. 11, November 1981. -// http://onlinelibrary.wiley.com/doi/10.1002/spe.4380111102/pdf -fn break_knuth_plass<'a, T: Clone + Iterator>>(mut iter: T, args: &mut BreakArgs<'a>) { - // run the algorithm to get the breakpoints - let breakpoints = find_kp_breakpoints(iter.clone(), args); - - // iterate through the breakpoints (note that breakpoints is in reverse break order, so we .rev() it - let (mut prev_punct, mut fresh) = - breakpoints.iter().rev().fold((false, false), |(mut prev_punct, mut fresh), &(next_break, break_before)| { - if fresh { - write_newline(args.indent_str, args.ostream); - } - // at each breakpoint, keep emitting words until we find the word matching this breakpoint - for winfo in &mut iter { - let (slen, word) = slice_if_fresh(fresh, winfo.word, winfo.word_start, args.uniform, - winfo.new_line, winfo.sentence_start, prev_punct); - fresh = false; - prev_punct = winfo.ends_punct; - - // We find identical breakpoints here by comparing addresses of the references. - // This is OK because the backing vector is not mutating once we are linebreaking. - let winfo_ptr = winfo as *const _; - let next_break_ptr = next_break as *const _; - if winfo_ptr == next_break_ptr { - // OK, we found the matching word - if break_before { - write_newline(args.indent_str, args.ostream); - write_with_spaces(&winfo.word[winfo.word_start..], 0, args.ostream); - } else { - // breaking after this word, so that means "fresh" is true for the next iteration - write_with_spaces(word, slen, args.ostream); - fresh = true; - } - break; - } else { - write_with_spaces(word, slen, args.ostream); - } - } - (prev_punct, fresh) - }); - - // after the last linebreak, write out the rest of the final line. - for winfo in iter { - if fresh { - write_newline(args.indent_str, args.ostream); - } - let (slen, word) = slice_if_fresh(fresh, winfo.word, winfo.word_start, args.uniform, - winfo.new_line, winfo.sentence_start, prev_punct); - prev_punct = winfo.ends_punct; - fresh = false; - write_with_spaces(word, slen, args.ostream); - } - silent_unwrap!(args.ostream.write_all("\n".as_bytes())); -} - -struct LineBreak<'a> { - prev : usize, - linebreak : Option<&'a WordInfo<'a>>, - break_before : bool, - demerits : i64, - prev_rat : f32, - length : usize, - fresh : bool -} - -fn find_kp_breakpoints<'a, T: Iterator>>(iter: T, args: &BreakArgs<'a>) -> Vec<(&'a WordInfo<'a>, bool)> { - let mut iter = iter.peekable(); - // set up the initial null linebreak - let mut linebreaks = vec!(LineBreak { - prev : 0, - linebreak : None, - break_before : false, - demerits : 0, - prev_rat : 0.0f32, - length : args.init_len, - fresh : false - }); - // this vec holds the current active linebreaks; next_ holds the breaks that will be active for the next word - let active_breaks = &mut vec!(0); - let next_active_breaks = &mut vec!(); - - let stretch = (args.opts.width - args.opts.goal) as isize; - let minlength = args.opts.goal - stretch as usize; - let mut new_linebreaks = vec!(); - let mut is_sentence_start = false; - let mut least_demerits = 0; - loop { - let w = - match iter.next() { - None => break, - Some(w) => w - }; - - // if this is the last word, we don't add additional demerits for this break - let (is_last_word, is_sentence_end) = - match iter.peek() { - None => (true, true), - Some(&&WordInfo { sentence_start: st, new_line: nl, .. }) => (false, st || (nl && w.ends_punct)) - }; - - // should we be adding extra space at the beginning of the next sentence? - let slen = compute_slen(args.uniform, w.new_line, is_sentence_start, false); - - let mut ld_new = i64::MAX; - let mut ld_next = i64::MAX; - let mut ld_idx = 0; - new_linebreaks.clear(); - next_active_breaks.clear(); - // go through each active break, extending it and possibly adding a new active - // break if we are above the minimum required length - for &i in active_breaks.iter() { - let active = &mut linebreaks[i]; - // normalize demerits to avoid overflow, and record if this is the least - active.demerits -= least_demerits; - if active.demerits < ld_next { - ld_next = active.demerits; - ld_idx = i; - } - - // get the new length - let tlen = w.word_nchars + args.compute_width(w, active.length, active.fresh) + slen + active.length; - - // if tlen is longer than args.opts.width, we drop this break from the active list - // otherwise, we extend the break, and possibly add a new break at this point - if tlen <= args.opts.width { - // this break will still be active next time - next_active_breaks.push(i); - // we can put this word on this line - active.fresh = false; - active.length = tlen; - - // if we're above the minlength, we can also consider breaking here - if tlen >= minlength { - let (new_demerits, new_ratio) = - if is_last_word { - // there is no penalty for the final line's length - (0, 0.0) - } else { - compute_demerits((args.opts.goal - tlen) as isize, stretch, w.word_nchars as isize, active.prev_rat) - }; - - // do not even consider adding a line that has too many demerits - // also, try to detect overflow by checking signum - let total_demerits = new_demerits + active.demerits; - if new_demerits < BAD_INFTY_SQ && total_demerits < ld_new && active.demerits.signum() <= new_demerits.signum() { - ld_new = total_demerits; - new_linebreaks.push(LineBreak { - prev : i, - linebreak : Some(w), - break_before : false, - demerits : total_demerits, - prev_rat : new_ratio, - length : args.indent_len, - fresh : true - }); - } - } - } - } - - // if we generated any new linebreaks, add the last one to the list - // the last one is always the best because we don't add to new_linebreaks unless - // it's better than the best one so far - match new_linebreaks.pop() { - None => (), - Some(lb) => { - next_active_breaks.push(linebreaks.len()); - linebreaks.push(lb); - } - } - - if next_active_breaks.is_empty() { - // every potential linebreak is too long! choose the linebreak with the least demerits, ld_idx - let new_break = restart_active_breaks(args, &linebreaks[ld_idx], ld_idx, w, slen, minlength); - next_active_breaks.push(linebreaks.len()); - linebreaks.push(new_break); - least_demerits = 0; - } else { - // next time around, normalize out the demerits fields - // on active linebreaks to make overflow less likely - least_demerits = cmp::max(ld_next, 0); - } - // swap in new list of active breaks - mem::swap(active_breaks, next_active_breaks); - // If this was the last word in a sentence, the next one must be the first in the next. - is_sentence_start = is_sentence_end; - } - - // return the best path - build_best_path(&linebreaks, active_breaks) -} - -#[inline(always)] -fn build_best_path<'a>(paths: &Vec>, active: &Vec) -> Vec<(&'a WordInfo<'a>, bool)> { - let mut breakwords = vec!(); - // of the active paths, we select the one with the fewest demerits - let mut best_idx = match active.iter().min_by(|&&a| paths[a].demerits) { - None => crash!(1, "Failed to find a k-p linebreak solution. This should never happen."), - Some(&s) => s - }; - - // now, chase the pointers back through the break list, recording - // the words at which we should break - loop { - let ref next_best = paths[best_idx]; - match next_best.linebreak { - None => return breakwords, - Some(prev) => { - breakwords.push((prev, next_best.break_before)); - best_idx = next_best.prev - } - } - } -} - -// "infinite" badness is more like (1+BAD_INFTY)^2 because of how demerits are computed -const BAD_INFTY: i64 = 10000000; -const BAD_INFTY_SQ: i64 = BAD_INFTY * BAD_INFTY; -// badness = BAD_MULT * abs(r) ^ 3 -const BAD_MULT: f32 = 100.0; -// DR_MULT is multiplier for delta-R between lines -const DR_MULT: f32 = 600.0; -// DL_MULT is penalty multiplier for short words at end of line -const DL_MULT: f32 = 300.0; - -#[inline(always)] -fn compute_demerits(delta_len: isize, stretch: isize, wlen: isize, prev_rat: f32) -> (i64, f32) { - // how much stretch are we using? - let ratio = - if delta_len == 0 { - 0.0f32 - } else { - delta_len as f32 / stretch as f32 - }; - - // compute badness given the stretch ratio - let bad_linelen = - if ratio.abs() > 1.0f32 { - BAD_INFTY - } else { - (BAD_MULT * ratio.powf(3f32).abs()) as i64 - }; - - // we penalize lines ending in really short words - let bad_wordlen = - if wlen >= stretch { - 0 - } else { - (DL_MULT * ((stretch - wlen) as f32 / (stretch - 1) as f32).powf(3f32).abs()) as i64 - }; - - // we penalize lines that have very different ratios from previous lines - let bad_delta_r = (DR_MULT * (((ratio - prev_rat) / 2.0).powf(3f32)).abs()) as i64; - - let demerits = i64::pow(1 + bad_linelen + bad_wordlen + bad_delta_r, 2); - - (demerits, ratio) -} - -#[inline(always)] -fn restart_active_breaks<'a>(args: &BreakArgs<'a>, active: &LineBreak<'a>, act_idx: usize, w: &'a WordInfo<'a>, slen: usize, min: usize) -> LineBreak<'a> { - let (break_before, line_length) = - if active.fresh { - // never break before a word if that word would be the first on a line - (false, args.indent_len) - } else { - // choose the lesser evil: breaking too early, or breaking too late - let wlen = w.word_nchars + args.compute_width(w, active.length, active.fresh); - let underlen = (min - active.length) as isize; - let overlen = ((wlen + slen + active.length) - args.opts.width) as isize; - if overlen > underlen { - // break early, put this word on the next line - (true, args.indent_len + w.word_nchars) - } else { - (false, args.indent_len) - } - }; - - // restart the linebreak. This will be our only active path. - LineBreak { - prev : act_idx, - linebreak : Some(w), - break_before : break_before, - demerits : 0, // this is the only active break, so we can reset the demerit count - prev_rat : if break_before { 1.0 } else { -1.0 }, - length : line_length, - fresh : !break_before - } -} - -// Number of spaces to add before a word, based on mode, newline, sentence start. -#[inline(always)] -fn compute_slen(uniform: bool, newline: bool, start: bool, punct: bool) -> usize { - if uniform || newline { - if start || (newline && punct) { - 2 - } else { - 1 - } - } else { - 0 - } -} - -// If we're on a fresh line, slen=0 and we slice off leading whitespace. -// Otherwise, compute slen and leave whitespace alone. -#[inline(always)] -fn slice_if_fresh<'a>(fresh: bool, word: &'a str, start: usize, uniform: bool, newline: bool, sstart: bool, punct: bool) -> (usize, &'a str) { - if fresh { - (0, &word[start..]) - } else { - (compute_slen(uniform, newline, sstart, punct), word) - } -} - -// Write a newline and add the indent. -#[inline(always)] -fn write_newline(indent: &str, ostream: &mut BufWriter) { - silent_unwrap!(ostream.write_all("\n".as_bytes())); - silent_unwrap!(ostream.write_all(indent.as_bytes())); -} - -// Write the word, along with slen spaces. -#[inline(always)] -fn write_with_spaces(word: &str, slen: usize, ostream: &mut BufWriter) { - if slen == 2 { - silent_unwrap!(ostream.write_all(" ".as_bytes())); - } else if slen == 1 { - silent_unwrap!(ostream.write_all(" ".as_bytes())); - } - silent_unwrap!(ostream.write_all(word.as_bytes())); -} diff --git a/src/fmt/parasplit.rs b/src/fmt/parasplit.rs deleted file mode 100644 index 01627f24a..000000000 --- a/src/fmt/parasplit.rs +++ /dev/null @@ -1,570 +0,0 @@ -/* - * This file is part of `fmt` from the uutils coreutils package. - * - * (c) kwantam - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use std::iter::Peekable; -use std::io::{BufRead, Lines}; -use std::slice::Iter; -use std::str::CharRange; -use unicode_width::UnicodeWidthChar; -use FileOrStdReader; -use FmtOptions; - -#[inline(always)] -fn char_width(c: char) -> usize { - if (c as usize) < 0xA0 { - // if it is ASCII, call it exactly 1 wide (including control chars) - // calling control chars' widths 1 is consistent with OpenBSD fmt - 1 - } else { - // otherwise, get the unicode width - // note that we shouldn't actually get None here because only c < 0xA0 - // can return None, but for safety and future-proofing we do it this way - UnicodeWidthChar::width(c).unwrap_or(1) - } -} - -// lines with PSKIP, lacking PREFIX, or which are entirely blank are -// NoFormatLines; otherwise, they are FormatLines -#[derive(Debug)] -pub enum Line { - FormatLine(FileLine), - NoFormatLine(String, bool) -} - -impl Line { - // when we know that it's a FormatLine, as in the ParagraphStream iterator - fn get_formatline(self) -> FileLine { - match self { - Line::FormatLine(fl) => fl, - Line::NoFormatLine(..) => panic!("Found NoFormatLine when expecting FormatLine") - } - } - - // when we know that it's a NoFormatLine, as in the ParagraphStream iterator - fn get_noformatline(self) -> (String, bool) { - match self { - Line::NoFormatLine(s, b) => (s, b), - Line::FormatLine(..) => panic!("Found FormatLine when expecting NoFormatLine") - } - } -} - -// each line's prefix has to be considered to know whether to merge it with -// the next line or not -#[derive(Debug)] -struct FileLine { - line : String, - indent_end : usize, // the end of the indent, always the start of the text - pfxind_end : usize, // the end of the PREFIX's indent, that is, the spaces before the prefix - indent_len : usize, // display length of indent taking into account tabs - prefix_len : usize, // PREFIX indent length taking into account tabs -} - -// iterator that produces a stream of Lines from a file -pub struct FileLines<'a> { - opts : &'a FmtOptions, - lines : Lines<&'a mut FileOrStdReader>, -} - -impl<'a> FileLines<'a> { - fn new<'b>(opts: &'b FmtOptions, lines: Lines<&'b mut FileOrStdReader>) -> FileLines<'b> { - FileLines { opts: opts, lines: lines } - } - - // returns true if this line should be formatted - fn match_prefix(&self, line: &str) -> (bool, usize) { - if !self.opts.use_prefix { return (true, 0); } - - FileLines::match_prefix_generic(&self.opts.prefix[..], line, self.opts.xprefix) - } - - // returns true if this line should be formatted - fn match_anti_prefix(&self, line: &str) -> bool { - if !self.opts.use_anti_prefix { return true; } - - match FileLines::match_prefix_generic(&self.opts.anti_prefix[..], line, self.opts.xanti_prefix) { - (true, _) => false, - (_ , _) => true - } - } - - fn match_prefix_generic(pfx: &str, line: &str, exact: bool) -> (bool, usize) { - if line.starts_with(pfx) { - return (true, 0); - } - - if !exact { - // we do it this way rather than byte indexing to support unicode whitespace chars - let mut i = 0; - while (i < line.len()) && line.char_at(i).is_whitespace() { - i = match line.char_range_at(i) { CharRange { ch: _ , next: nxi } => nxi }; - if line[i..].starts_with(pfx) { - return (true, i); - } - } - } - - (false, 0) - } - - fn compute_indent(&self, string: &str, prefix_end: usize) -> (usize, usize, usize) { - let mut prefix_len = 0; - let mut indent_len = 0; - let mut indent_end = 0; - for (os, c) in string.char_indices() { - if os == prefix_end { - // we found the end of the prefix, so this is the printed length of the prefix here - prefix_len = indent_len; - } - - if (os >= prefix_end) && !c.is_whitespace() { - // found first non-whitespace after prefix, this is indent_end - indent_end = os; - break; - } else if c == '\t' { - // compute tab length - indent_len = (indent_len / self.opts.tabwidth + 1) * self.opts.tabwidth; - } else { - // non-tab character - indent_len += char_width(c); - } - } - (indent_end, prefix_len, indent_len) - } -} - -impl<'a> Iterator for FileLines<'a> { - type Item = Line; - - fn next(&mut self) -> Option { - let n = - match self.lines.next() { - Some(t) => match t { - Ok(tt) => tt, - Err(_) => return None - }, - None => return None - }; - - // if this line is entirely whitespace, - // emit a blank line - // Err(true) indicates that this was a linebreak, - // which is important to know when detecting mail headers - if n.chars().all(|c| c.is_whitespace()) { - return Some(Line::NoFormatLine("\n".to_string(), true)); - } - - // if this line does not match the prefix, - // emit the line unprocessed and iterate again - let (pmatch, poffset) = self.match_prefix(&n[..]); - if !pmatch { - return Some(Line::NoFormatLine(n, false)); - } else if n[poffset + self.opts.prefix.len()..].chars().all(|c| c.is_whitespace()) { - // if the line matches the prefix, but is blank after, - // don't allow lines to be combined through it (that is, - // treat it like a blank line, except that since it's - // not truly blank we will not allow mail headers on the - // following line) - return Some(Line::NoFormatLine(n, false)); - } - - // skip if this line matches the anti_prefix - // (NOTE definition of match_anti_prefix is TRUE if we should process) - if !self.match_anti_prefix(&n[..]) { - return Some(Line::NoFormatLine(n, false)); - } - - // figure out the indent, prefix, and prefixindent ending points - let prefix_end = poffset + self.opts.prefix.len(); - let (indent_end, prefix_len, indent_len) = self.compute_indent(&n[..], prefix_end); - - Some(Line::FormatLine(FileLine { - line : n, - indent_end : indent_end, - pfxind_end : poffset, - indent_len : indent_len, - prefix_len : prefix_len - })) - } -} - -// a paragraph : a collection of FileLines that are to be formatted -// plus info about the paragraph's indentation -// (but we only retain the String from the FileLine; the other info -// is only there to help us in deciding how to merge lines into Paragraphs -#[derive(Debug)] -pub struct Paragraph { - lines : Vec, // the lines of the file - pub init_str : String, // string representing the init, that is, the first line's indent - pub init_len : usize, // printable length of the init string considering TABWIDTH - init_end : usize, // byte location of end of init in first line String - pub indent_str : String, // string representing indent - pub indent_len : usize, // length of above - indent_end : usize, // byte location of end of indent (in crown and tagged mode, only applies to 2nd line and onward) - pub mail_header : bool // we need to know if this is a mail header because we do word splitting differently in that case -} - -// an iterator producing a stream of paragraphs from a stream of lines -// given a set of options. -pub struct ParagraphStream<'a> { - lines : Peekable>, - next_mail : bool, - opts : &'a FmtOptions, -} - -impl<'a> ParagraphStream<'a> { - pub fn new<'b>(opts: &'b FmtOptions, reader: &'b mut FileOrStdReader) -> ParagraphStream<'b> { - let lines = FileLines::new(opts, reader.lines()).peekable(); - // at the beginning of the file, we might find mail headers - ParagraphStream { lines: lines, next_mail: true, opts: opts } - } - - // detect RFC822 mail header - fn is_mail_header(line: &FileLine) -> bool { - // a mail header begins with either "From " (envelope sender line) - // or with a sequence of printable ASCII chars (33 to 126, inclusive, - // except colon) followed by a colon. - if line.indent_end > 0 { - false - } else { - let l_slice = &line.line[..]; - if l_slice.starts_with("From ") { - true - } else { - let colon_posn = - match l_slice.find(':') { - Some(n) => n, - None => return false - }; - - // header field must be nonzero length - if colon_posn == 0 { return false; } - - return l_slice[..colon_posn].chars().all(|x| match x as usize { - y if y < 33 || y > 126 => false, - _ => true - }); - } - } - } -} - -impl<'a> Iterator for ParagraphStream<'a> { - type Item = Result; - - fn next(&mut self) -> Option> { - // return a NoFormatLine in an Err; it should immediately be output - let noformat = - match self.lines.peek() { - None => return None, - Some(l) => match l { - &Line::FormatLine(_) => false, - &Line::NoFormatLine(_, _) => true - } - }; - - // found a NoFormatLine, immediately dump it out - if noformat { - let (s, nm) = self.lines.next().unwrap().get_noformatline(); - self.next_mail = nm; - return Some(Err(s)); - } - - // found a FormatLine, now build a paragraph - let mut init_str = String::new(); - let mut init_end = 0; - let mut init_len = 0; - let mut indent_str = String::new(); - let mut indent_end = 0; - let mut indent_len = 0; - let mut prefix_len = 0; - let mut pfxind_end = 0; - let mut p_lines = Vec::new(); - - let mut in_mail = false; - let mut second_done = false; // for when we use crown or tagged mode - loop { - { // peek ahead - // need to explicitly force fl out of scope before we can call self.lines.next() - let fl = - match self.lines.peek() { - None => break, - Some(l) => { - match l { - &Line::FormatLine(ref x) => x, - &Line::NoFormatLine(..) => break - } - } - }; - - if p_lines.len() == 0 { - // first time through the loop, get things set up - // detect mail header - if self.opts.mail && self.next_mail && ParagraphStream::is_mail_header(fl) { - in_mail = true; - // there can't be any indent or pfxind because otherwise is_mail_header would fail - // since there cannot be any whitespace before the colon in a valid header field - indent_str.push_str(" "); - indent_len = 2; - } else { - if self.opts.crown || self.opts.tagged { - init_str.push_str(&fl.line[..fl.indent_end]); - init_len = fl.indent_len; - init_end = fl.indent_end; - } else { - second_done = true; - } - - // these will be overwritten in the 2nd line of crown or tagged mode, but - // we are not guaranteed to get to the 2nd line, e.g., if the next line - // is a NoFormatLine or None. Thus, we set sane defaults the 1st time around - indent_str.push_str(&fl.line[..fl.indent_end]); - indent_len = fl.indent_len; - indent_end = fl.indent_end; - - // save these to check for matching lines - prefix_len = fl.prefix_len; - pfxind_end = fl.pfxind_end; - - // in tagged mode, add 4 spaces of additional indenting by default - // (gnu fmt's behavior is different: it seems to find the closest column to - // indent_end that is divisible by 3. But honesly that behavior seems - // pretty arbitrary. - // Perhaps a better default would be 1 TABWIDTH? But ugh that's so big. - if self.opts.tagged { - indent_str.push_str(" "); - indent_len += 4; - } - } - } else if in_mail { - // lines following mail headers must begin with spaces - if fl.indent_end == 0 || (self.opts.use_prefix && fl.pfxind_end == 0) { - break; // this line does not begin with spaces - } - } else if !second_done { - // now we have enough info to handle crown margin and tagged mode - if prefix_len != fl.prefix_len || pfxind_end != fl.pfxind_end { - // in both crown and tagged modes we require that prefix_len is the same - break; - } else if self.opts.tagged && indent_len - 4 == fl.indent_len && indent_end == fl.indent_end { - // in tagged mode, indent has to be *different* on following lines - break; - } else { - // this is part of the same paragraph, get the indent info from this line - indent_str.clear(); - indent_str.push_str(&fl.line[..fl.indent_end]); - indent_len = fl.indent_len; - indent_end = fl.indent_end; - } - second_done = true; - } else { - // detect mismatch - if indent_end != fl.indent_end || pfxind_end != fl.pfxind_end || indent_len != fl.indent_len || prefix_len != fl.prefix_len { - break; - } - } - } - - p_lines.push(self.lines.next().unwrap().get_formatline().line); - - // when we're in split-only mode, we never join lines, so stop here - if self.opts.split_only { - break; - } - } - - // if this was a mail header, then the next line can be detected as one. Otherwise, it cannot. - // NOTE next_mail is true at ParagraphStream instantiation, and is set to true after a blank - // NoFormatLine. - self.next_mail = in_mail; - - Some(Ok(Paragraph { - lines : p_lines, - init_str : init_str, - init_len : init_len, - init_end : init_end, - indent_str : indent_str, - indent_len : indent_len, - indent_end : indent_end, - mail_header : in_mail - })) - } -} - -pub struct ParaWords<'a> { - opts : &'a FmtOptions, - para : &'a Paragraph, - words : Vec> -} - -impl<'a> ParaWords<'a> { - pub fn new<'b>(opts: &'b FmtOptions, para: &'b Paragraph) -> ParaWords<'b> { - let mut pw = ParaWords { opts: opts, para: para, words: Vec::new() }; - pw.create_words(); - pw - } - - fn create_words<'r>(&'r mut self) { - if self.para.mail_header { - // no extra spacing for mail headers; always exactly 1 space - // safe to trim_left on every line of a mail header, since the - // first line is guaranteed not to have any spaces - self.words.extend(self.para.lines.iter().flat_map(|x| x.split_whitespace()).map(|x| WordInfo { - word : x, - word_start : 0, - word_nchars : x.len(), // OK for mail headers; only ASCII allowed (unicode is escaped) - before_tab : None, - after_tab : 0, - sentence_start : false, - ends_punct : false, - new_line : false - })); - } else { - // first line - self.words.extend( - if self.opts.crown || self.opts.tagged { - // crown and tagged mode has the "init" in the first line, so slice from there - WordSplit::new(self.opts, &self.para.lines[0][self.para.init_end..]) - } else { - // otherwise we slice from the indent - WordSplit::new(self.opts, &self.para.lines[0][self.para.indent_end..]) - }); - - if self.para.lines.len() > 1 { - let indent_end = self.para.indent_end; - let opts = self.opts; - self.words.extend( - self.para.lines.iter().skip(1).flat_map(|x| WordSplit::new(opts, &x[indent_end..]))); - } - } - } - - pub fn words(&'a self) -> Iter<'a, WordInfo<'a>> { return self.words.iter() } -} - -struct WordSplit<'a> { - opts : &'a FmtOptions, - string : &'a str, - length : usize, - position : usize, - prev_punct : bool -} - -impl<'a> WordSplit<'a> { - fn analyze_tabs(&self, string: &str) -> (Option, usize, Option) { - // given a string, determine (length before tab) and (printed length after first tab) - // if there are no tabs, beforetab = -1 and aftertab is the printed length - let mut beforetab = None; - let mut aftertab = 0; - let mut word_start = None; - for (os, c) in string.char_indices() { - if !c.is_whitespace() { - word_start = Some(os); - break; - } else if c == '\t' { - if beforetab == None { - beforetab = Some(aftertab); - aftertab = 0; - } else { - aftertab = (aftertab / self.opts.tabwidth + 1) * self.opts.tabwidth; - } - } else { - aftertab += 1; - } - } - (beforetab, aftertab, word_start) - } -} - -impl<'a> WordSplit<'a> { - fn new<'b>(opts: &'b FmtOptions, string: &'b str) -> WordSplit<'b> { - // wordsplits *must* start at a non-whitespace character - let trim_string = string.trim_left(); - WordSplit { opts: opts, string: trim_string, length: string.len(), position: 0, prev_punct: false } - } - - fn is_punctuation(c: char) -> bool { - match c { - '!' | '.' | '?' => true, - _ => false - } - } -} - -pub struct WordInfo<'a> { - pub word : &'a str, - pub word_start : usize, - pub word_nchars : usize, - pub before_tab : Option, - pub after_tab : usize, - pub sentence_start : bool, - pub ends_punct : bool, - pub new_line : bool -} - -// returns (&str, is_start_of_sentence) -impl<'a> Iterator for WordSplit<'a> { - type Item = WordInfo<'a>; - - fn next(&mut self) -> Option> { - if self.position >= self.length { - return None - } - - let old_position = self.position; - let new_line = old_position == 0; - - // find the start of the next word, and record if we find a tab character - let (before_tab, after_tab, word_start) = match self.analyze_tabs(&self.string[old_position..]) { - (b, a, Some(s)) => (b, a, s + old_position), - (_, _, None) => { - self.position = self.length; - return None; - } - }; - - // find the beginning of the next whitespace - // note that this preserves the invariant that self.position - // points to whitespace character OR end of string - let mut word_nchars = 0; - self.position = - match self.string[word_start..] - .find(|x: char| if !x.is_whitespace() { word_nchars += char_width(x); false } else { true }) { - None => self.length, - Some(s) => s + word_start - }; - - let word_start_relative = word_start - old_position; - // if the previous sentence was punctuation and this sentence has >2 whitespace or one tab, is a new sentence. - let is_start_of_sentence = self.prev_punct && (before_tab.is_some() || word_start_relative > 1); - - // now record whether this word ends in punctuation - self.prev_punct = match self.string.char_range_at_reverse(self.position) { - CharRange { ch, next: _ } => WordSplit::is_punctuation(ch) - }; - - let (word, word_start_relative, before_tab, after_tab) = - if self.opts.uniform { - (&self.string[word_start..self.position], 0, None, 0) - } else { - (&self.string[old_position..self.position], word_start_relative, before_tab, after_tab) - }; - - Some(WordInfo { - word : word, - word_start : word_start_relative, - word_nchars : word_nchars, - before_tab : before_tab, - after_tab : after_tab, - sentence_start : is_start_of_sentence, - ends_punct : self.prev_punct, - new_line : new_line - }) - } -} diff --git a/src/fold/Cargo.toml b/src/fold/Cargo.toml deleted file mode 100644 index 54bb67150..000000000 --- a/src/fold/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "fold" -version = "0.0.1" -authors = [] - -[lib] -name = "fold" -path = "fold.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/fold/fold.rs b/src/fold/fold.rs deleted file mode 100644 index 5b8da31cd..000000000 --- a/src/fold/fold.rs +++ /dev/null @@ -1,222 +0,0 @@ -#![crate_name = "fold"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Arcterus - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use std::fs::File; -use std::io::{BufRead, BufReader, Read, stdin, Write}; -use std::path::Path; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "fold"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let (args, obs_width) = handle_obsolete(&args[..]); - let mut opts = getopts::Options::new(); - - opts.optflag("b", "bytes", "count using bytes rather than columns (meaning control characters such as newline are not treated specially)"); - opts.optflag("s", "spaces", "break lines at word boundaries rather than a hard cut-off"); - opts.optopt("w", "width", "set WIDTH as the maximum line width rather than 80", "WIDTH"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "{}", f) - }; - - if matches.opt_present("h") { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {} [OPTION]... [FILE]...", NAME); - println!(""); - print!("{}", opts.usage("Writes each file (or standard input if no files are given) to standard output whilst breaking long lines")); - } else if matches.opt_present("V") { - println!("{} {}", NAME, VERSION); - } else { - let bytes = matches.opt_present("b"); - let spaces = matches.opt_present("s"); - let poss_width = - if matches.opt_present("w") { - matches.opt_str("w") - } else { - match obs_width { - Some(v) => Some(v.to_string()), - None => None, - } - }; - let width = match poss_width { - Some(inp_width) => match inp_width.parse::() { - Ok(width) => width, - Err(e) => crash!(1, "illegal width value (\"{}\"): {}", inp_width, e) - }, - None => 80 - }; - let files = if matches.free.is_empty() { - vec!("-".to_string()) - } else { - matches.free - }; - fold(files, bytes, spaces, width); - } - - 0 -} - -fn handle_obsolete(args: &[String]) -> (Vec, Option) { - for (i, arg) in args.iter().enumerate() { - let slice = &arg; - if slice.chars().next().unwrap() == '-' && slice.len() > 1 && slice.chars().nth(1).unwrap().is_digit(10) { - let mut v = args.to_vec(); - v.remove(i); - return (v, Some(slice[1..].to_string())); - } - } - (args.to_vec(), None) -} - -#[inline] -fn fold(filenames: Vec, bytes: bool, spaces: bool, width: usize) { - for filename in filenames.iter() { - let filename: &str = &filename; - let mut stdin_buf; - let mut file_buf; - let buffer = BufReader::new( - if filename == "-" { - stdin_buf = stdin(); - &mut stdin_buf as &mut Read - } else { - file_buf = safe_unwrap!(File::open(Path::new(filename))); - &mut file_buf as &mut Read - } - ); - fold_file(buffer, bytes, spaces, width); - } -} - -#[inline] -fn fold_file(mut file: BufReader, bytes: bool, spaces: bool, width: usize) { - let mut line = String::new(); - while safe_unwrap!(file.read_line(&mut line)) > 0 { - if bytes { - let len = line.len(); - let mut i = 0; - while i < len { - let width = if len - i >= width { width } else { len - i }; - let slice = { - let slice = &line[i..i + width]; - if spaces && i + width < len { - match slice.rfind(|ch: char| ch.is_whitespace()) { - Some(m) => &slice[..m + 1], - None => slice - } - } else { - slice - } - }; - print!("{}", slice); - i += slice.len(); - } - } else { - let mut len = line.chars().count(); - let newline = line.ends_with("\n"); - if newline { - if len == 1 { - println!(""); - continue; - } - len -= 1; - line.truncate(len); - } - let mut output = String::new(); - let mut count = 0; - for (i, ch) in line.chars().enumerate() { - if count >= width { - let (val, ncount) = { - let slice = &output[..]; - let (out, val, ncount) = - if spaces && i + 1 < len { - match rfind_whitespace(slice) { - Some(m) => { - let routput = &slice[m + 1 .. slice.chars().count()]; - let ncount = routput.chars().fold(0, |out, ch: char| { - out + match ch { - '\t' => 8, - '\x08' => if out > 0 { !0 } else { 0 }, - '\r' => return 0, - _ => 1 - } - }); - (&slice[0 .. m + 1], routput, ncount) - }, - None => (slice, "", 0) - } - } else { - (slice, "", 0) - }; - println!("{}", out); - (val.to_string(), ncount) - }; - output = val; - count = ncount; - } - match ch { - '\t' => { - count += 8; - if count > width { - println!("{}", output); - output.truncate(0); - count = 8; - } - } - '\x08' => { - if count > 0 { - count -= 1; - let len = output.len() - 1; - output.truncate(len); - } - continue; - } - '\r' => { - output.truncate(0); - count = 0; - continue; - } - _ => count += 1 - }; - output.push(ch); - } - if count > 0 { - if newline { - println!("{}", output); - } else { - print!("{}", output); - } - } - } - } -} - -#[inline] -fn rfind_whitespace(slice: &str) -> Option { - for (i, ch) in slice.chars().rev().enumerate() { - if ch.is_whitespace() { - return Some(slice.chars().count() - (i + 1)); - } - } - None -} diff --git a/src/groups/Cargo.toml b/src/groups/Cargo.toml deleted file mode 100644 index ad8f0c86d..000000000 --- a/src/groups/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "groups" -version = "0.0.1" -authors = [] - -[lib] -name = "groups" -path = "groups.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/groups/groups.rs b/src/groups/groups.rs deleted file mode 100644 index 167905111..000000000 --- a/src/groups/groups.rs +++ /dev/null @@ -1,52 +0,0 @@ -#![crate_name = "groups"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Alan Andrade - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - */ -extern crate getopts; - -use c_types::{get_pw_from_args, group}; -use std::io::Write; - -#[path = "../common/util.rs"] #[macro_use] mod util; -#[path = "../common/c_types.rs"] mod c_types; - -static NAME: &'static str = "groups"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - opts.optflag("h", "help", "display this help menu and exit"); - opts.optflag("V", "version", "display version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => { m }, - Err(f) => { - show_error!("{}", f); - return 1; - } - }; - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - } else if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: - {0} [OPTION]... [USER]... - -Prints the groups a user is in to standard output.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - } else { - group(get_pw_from_args(&matches.free), true); - } - - 0 -} diff --git a/src/hashsum/Cargo.toml b/src/hashsum/Cargo.toml deleted file mode 100644 index 78111a679..000000000 --- a/src/hashsum/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "hashsum" -version = "0.0.1" -authors = [] - -[lib] -name = "hashsum" -path = "hashsum.rs" - -[dependencies] -getopts = "*" -libc = "*" -regex = "*" -regex-syntax = "*" -rust-crypto = "*" diff --git a/src/hashsum/deps.mk b/src/hashsum/deps.mk deleted file mode 100644 index 83178fa58..000000000 --- a/src/hashsum/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += regex regex-syntax crypto rand rustc-serialize time winapi kernel32 diff --git a/src/hashsum/hashsum.rs b/src/hashsum/hashsum.rs deleted file mode 100644 index a47aa1ca1..000000000 --- a/src/hashsum/hashsum.rs +++ /dev/null @@ -1,309 +0,0 @@ -#![crate_name = "hashsum"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Arcterus - * (c) Vsevolod Velichko - * (c) Gil Cottle - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate crypto; -extern crate getopts; -extern crate regex_syntax; -extern crate regex; - -use crypto::digest::Digest; -use crypto::md5::Md5; -use crypto::sha1::Sha1; -use crypto::sha2::{Sha224, Sha256, Sha384, Sha512}; -use regex::Regex; -use std::ascii::AsciiExt; -use std::fs::File; -use std::io::{self, BufRead, BufReader, Read, stdin, Write}; -use std::path::Path; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "hashsum"; -static VERSION: &'static str = "1.0.0"; - -fn is_custom_binary(program: &str) -> bool { - match program { - "md5sum" | "sha1sum" - | "sha224sum" | "sha256sum" - | "sha384sum" | "sha512sum" => true, - _ => false - } -} - -fn detect_algo(program: &str, matches: &getopts::Matches) -> (&'static str, Box) { - let mut alg: Option> = None; - let mut name: &'static str = ""; - match program { - "md5sum" => ("MD5", Box::new(Md5::new()) as Box), - "sha1sum" => ("SHA1", Box::new(Sha1::new()) as Box), - "sha224sum" => ("SHA224", Box::new(Sha224::new()) as Box), - "sha256sum" => ("SHA256", Box::new(Sha256::new()) as Box), - "sha384sum" => ("SHA384", Box::new(Sha384::new()) as Box), - "sha512sum" => ("SHA512", Box::new(Sha512::new()) as Box), - _ => { - { - let mut set_or_crash = |n, val| -> () { - if alg.is_some() { crash!(1, "You cannot combine multiple hash algorithms!") }; - name = n; - alg = Some(val); - }; - if matches.opt_present("md5") { set_or_crash("MD5", Box::new(Md5::new())) }; - if matches.opt_present("sha1") { set_or_crash("SHA1", Box::new(Sha1::new())) }; - if matches.opt_present("sha224") { set_or_crash("SHA224", Box::new(Sha224::new())) }; - if matches.opt_present("sha256") { set_or_crash("SHA256", Box::new(Sha256::new())) }; - if matches.opt_present("sha384") { set_or_crash("SHA384", Box::new(Sha384::new())) }; - if matches.opt_present("sha512") { set_or_crash("SHA512", Box::new(Sha512::new())) }; - } - if alg.is_none() { crash!(1, "You must specify hash algorithm!") }; - (name, alg.unwrap()) - } - } -} - -pub fn uumain(args: Vec) -> i32 { - let program = &args[0]; - let binary_name = Path::new(program).file_name().unwrap().to_str().unwrap(); - - // Default binary in Windows, text mode otherwise - let binary_flag_default = cfg!(windows); - - let mut opts = getopts::Options::new(); - opts.optflag("b", "binary", &format!("read in binary mode{}", if binary_flag_default { " (default)" } else { "" })); - opts.optflag("c", "check", "read hashsums from the FILEs and check them"); - opts.optflag("", "tag", "create a BSD-style checksum"); - opts.optflag("t", "text", &format!("read in text mode{}", if binary_flag_default { "" } else { " (default)" })); - opts.optflag("q", "quiet", "don't print OK for each successfully verified file"); - opts.optflag("s", "status", "don't output anything, status code shows success"); - opts.optflag("", "strict", "exit non-zero for improperly formatted checksum lines"); - opts.optflag("w", "warn", "warn about improperly formatted checksum lines"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - if !is_custom_binary(program) { - opts.optflag("", "md5", "work with MD5"); - opts.optflag("", "sha1", "work with SHA1"); - opts.optflag("", "sha224", "work with SHA224"); - opts.optflag("", "sha256", "work with SHA256"); - opts.optflag("", "sha384", "work with SHA384"); - opts.optflag("", "sha512", "work with SHA512"); - } - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "{}", f) - }; - - if matches.opt_present("help") { - usage(program, binary_name, &opts); - } else if matches.opt_present("version") { - version(); - } else { - let (name, algo) = detect_algo(binary_name, &matches); - - let binary_flag = matches.opt_present("binary"); - let text_flag = matches.opt_present("text"); - if binary_flag && text_flag { - crash!(1, "cannot set binary and text mode at the same time"); - } - let binary = if binary_flag { true } else if text_flag { false } else { binary_flag_default }; - let check = matches.opt_present("check"); - let tag = matches.opt_present("tag"); - let status = matches.opt_present("status"); - let quiet = matches.opt_present("quiet") || status; - let strict = matches.opt_present("strict"); - let warn = matches.opt_present("warn") && !status; - let files = if matches.free.is_empty() { - vec!("-".to_string()) - } else { - matches.free - }; - match hashsum(name, algo, files, binary, check, tag, status, quiet, strict, warn) { - Ok(()) => return 0, - Err(e) => return e - } - } - - 0 -} - -fn version() { - pipe_println!("{} {}", NAME, VERSION); -} - -fn usage(program: &str, binary_name: &str, opts: &getopts::Options) { - let spec = if is_custom_binary(binary_name) { - format!(" {} [OPTION]... [FILE]...", program) - } else { - format!(" {} {{--md5|--sha1|--sha224|--sha256|--sha384|--sha512}} [OPTION]... [FILE]...", program) - }; - - let msg = format!("{} {} - -Usage: -{} - -Compute and check message digests.", NAME, VERSION, spec); - - pipe_print!("{}", opts.usage(&msg)); -} - -fn hashsum<'a>(algoname: &str, mut digest: Box, files: Vec, binary: bool, check: bool, tag: bool, status: bool, quiet: bool, strict: bool, warn: bool) -> Result<(), i32> { - let mut bad_format = 0; - let mut failed = 0; - let binary_marker = if binary { - "*" - } else { - " " - }; - for filename in files.iter() { - let filename: &str = filename; - let stdin_buf; - let file_buf; - let mut file = BufReader::new( - if filename == "-" { - stdin_buf = stdin(); - Box::new(stdin_buf) as Box - } else { - file_buf = safe_unwrap!(File::open(filename)); - Box::new(file_buf) as Box - } - ); - if check { - // Set up Regexes for line validation and parsing - let bytes = digest.output_bits() / 4; - let gnu_re = safe_unwrap!( - Regex::new( - &format!( - r"^(?P[a-fA-F0-9]{{{}}}) (?P[ \*])(?P.*)", - bytes - ) - ) - ); - let bsd_re = safe_unwrap!( - Regex::new( - &format!( - r"^{algorithm} \((?P.*)\) = (?P[a-fA-F0-9]{{{digest_size}}})", - algorithm = algoname, - digest_size = bytes - ) - ) - ); - - let buffer = file; - for (i, line) in buffer.lines().enumerate() { - let line = safe_unwrap!(line); - let (ck_filename, sum, binary_check) = match gnu_re.captures(&line) { - Some(caps) => (caps.name("fileName").unwrap(), - caps.name("digest").unwrap().to_ascii_lowercase(), - caps.name("binary").unwrap() == "*"), - None => match bsd_re.captures(&line) { - Some(caps) => (caps.name("fileName").unwrap(), - caps.name("digest").unwrap().to_ascii_lowercase(), - true), - None => { - bad_format += 1; - if strict { - return Err(1); - } - if warn { - show_warning!("{}: {}: improperly formatted {} checksum line", filename, i + 1, algoname); - } - continue; - } - } - }; - let f = safe_unwrap!(File::open(ck_filename)); - let mut ckf = BufReader::new(Box::new(f) as Box); - let real_sum = safe_unwrap!(digest_reader(&mut digest, &mut ckf, binary_check)) - .to_ascii_lowercase(); - if sum == real_sum { - if !quiet { - pipe_println!("{}: OK", ck_filename); - } - } else { - if !status { - pipe_println!("{}: FAILED", ck_filename); - } - failed += 1; - } - } - } else { - let sum = safe_unwrap!(digest_reader(&mut digest, &mut file, binary)); - if tag { - pipe_println!("{} ({}) = {}", algoname, filename, sum); - } else { - pipe_println!("{} {}{}", sum, binary_marker, filename); - } - } - } - if !status { - if bad_format == 1 { - show_warning!("{} line is improperly formatted", bad_format); - } else if bad_format > 1 { - show_warning!("{} lines are improperly formatted", bad_format); - } - if failed > 0 { - show_warning!("{} computed checksum did NOT match", failed); - } - } - - Ok(()) -} - -fn digest_reader<'a, T: Read>(digest: &mut Box, reader: &mut BufReader, binary: bool) -> io::Result { - digest.reset(); - - // Digest file, do not hold too much in memory at any given moment - let windows = cfg!(windows); - let mut buffer = Vec::with_capacity(524288); - let mut vec = Vec::with_capacity(524288); - let mut looking_for_newline = false; - loop { - match reader.read_to_end(&mut buffer) { - Ok(0) => { break; }, - Ok(nread) => { - if windows && !binary { - // Windows text mode returns '\n' when reading '\r\n' - for i in 0 .. nread { - if looking_for_newline { - if buffer[i] != ('\n' as u8) { - vec.push('\r' as u8); - } - if buffer[i] != ('\r' as u8) { - vec.push(buffer[i]); - looking_for_newline = false; - } - } else if buffer[i] != ('\r' as u8) { - vec.push(buffer[i]); - } else { - looking_for_newline = true; - } - } - digest.input(&vec); - vec.clear(); - } else { - digest.input(&buffer[..nread]); - } - }, - Err(e) => return Err(e) - } - } - if windows && looking_for_newline { - vec.push('\r' as u8); - digest.input(&vec); - } - - Ok(digest.result_str()) -} diff --git a/src/head/Cargo.toml b/src/head/Cargo.toml deleted file mode 100644 index 42341acc1..000000000 --- a/src/head/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "head" -version = "0.0.1" -authors = [] - -[lib] -name = "head" -path = "head.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/head/head.rs b/src/head/head.rs deleted file mode 100644 index 17790c969..000000000 --- a/src/head/head.rs +++ /dev/null @@ -1,210 +0,0 @@ -#![crate_name = "head"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Alan Andrade - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * Synced with: https://raw.github.com/avsm/src/master/usr.bin/head/head.c - */ - -extern crate getopts; - -use std::io::{BufRead, BufReader, Read, stdin, Write}; -use std::fs::File; -use std::path::Path; -use std::str::from_utf8; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "head"; -static VERSION: &'static str = "1.0.0"; - -enum FilterMode { - Bytes(usize), - Lines(usize), -} - -struct Settings { - mode: FilterMode, - verbose: bool, -} - -impl Default for Settings { - fn default() -> Settings { - Settings { - mode: FilterMode::Lines(10), - verbose: false, - } - } -} - -pub fn uumain(args: Vec) -> i32 { - let mut settings: Settings = Default::default(); - - // handle obsolete -number syntax - let options = match obsolete(&args[1..]) { - (args, Some(n)) => { settings.mode = FilterMode::Lines(n); args }, - (args, None) => args - }; - - let args = options; - - let mut opts = getopts::Options::new(); - - opts.optopt("c", "bytes", "Print the first K bytes. With the leading '-', print all but the last K bytes", "[-]K"); - opts.optopt("n", "lines", "Print the first K lines. With the leading '-', print all but the last K lines", "[-]K"); - opts.optflag("q", "quiet", "never print headers giving file names"); - opts.optflag("v", "verbose", "always print headers giving file names"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args) { - Ok (m) => { m } - Err(_) => { - println!("{}", opts.usage("")); - return 1; - } - }; - - if matches.opt_present("h") { - println!("{}", opts.usage("")); - return 0; - } - if matches.opt_present("V") { version(); return 0 } - - let use_bytes = matches.opt_present("c"); - - // TODO: suffixes (e.g. b, kB, etc.) - match matches.opt_str("n") { - Some(n) => { - if use_bytes { - show_error!("cannot specify both --bytes and --lines."); - return 1; - } - match n.parse::() { - Ok(m) => { settings.mode = FilterMode::Lines(m) } - Err(e) => { - show_error!("invalid line count '{}': {}", n, e); - return 1; - } - } - } - None => match matches.opt_str("c") { - Some(count) => match count.parse::() { - Ok(m) => settings.mode = FilterMode::Bytes(m), - Err(e)=> { - show_error!("invalid byte count '{}': {}", count, e); - return 1; - } - }, - None => {} - } - }; - - let quiet = matches.opt_present("q"); - let verbose = matches.opt_present("v"); - let files = matches.free; - - // GNU implementation allows multiple declarations of "-q" and "-v" with the - // last flag winning. This can't be simulated with the getopts cargo unless - // we manually parse the arguments. Given the declaration of both flags, - // verbose mode always wins. This is a potential future improvement. - if files.len() > 1 && !quiet && !verbose { - settings.verbose = true; - } - if quiet { - settings.verbose = false; - } - if verbose { - settings.verbose = true; - } - - if files.is_empty() { - let mut buffer = BufReader::new(stdin()); - head(&mut buffer, &settings); - } else { - let mut firstime = true; - - for file in files.iter() { - if settings.verbose { - if !firstime { pipe_println!(""); } - pipe_println!("==> {} <==", file); - } - firstime = false; - - let path = Path::new(file); - let reader = File::open(&path).unwrap(); - let mut buffer = BufReader::new(reader); - if !head(&mut buffer, &settings) { - break; - } - } - } - - 0 -} - -// It searches for an option in the form of -123123 -// -// In case is found, the options vector will get rid of that object so that -// getopts works correctly. -fn obsolete(options: &[String]) -> (Vec, Option) { - let mut options: Vec = options.to_vec(); - let mut a = 0; - let b = options.len(); - - while a < b { - let current = options[a].clone(); - let current = current.as_bytes(); - - if current.len() > 1 && current[0] == '-' as u8 { - let len = current.len(); - for pos in 1 .. len { - // Ensure that the argument is only made out of digits - if !(current[pos] as char).is_numeric() { break; } - - // If this is the last number - if pos == len - 1 { - options.remove(a); - let number: Option = from_utf8(¤t[1..len]).unwrap().parse::().ok(); - return (options, Some(number.unwrap())); - } - } - } - - a += 1; - }; - - (options, None) -} - -// TODO: handle errors on read -fn head(reader: &mut BufReader, settings: &Settings) -> bool { - match settings.mode { - FilterMode::Bytes(count) => { - for byte in reader.bytes().take(count) { - if !pipe_print!("{}", byte.unwrap() as char) { - return false; - } - } - }, - FilterMode::Lines(count) => { - for line in reader.lines().take(count) { - if !pipe_println!("{}", line.unwrap()) { - return false; - } - } - } - } - true -} - -fn version() { - println!("{} {}", NAME, VERSION); -} diff --git a/src/hostid/Cargo.toml b/src/hostid/Cargo.toml deleted file mode 100644 index 146c0879e..000000000 --- a/src/hostid/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "hostid" -version = "0.0.1" -authors = [] - -[lib] -name = "hostid" -path = "hostid.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/hostid/hostid.rs b/src/hostid/hostid.rs deleted file mode 100644 index 9cca3d7c5..000000000 --- a/src/hostid/hostid.rs +++ /dev/null @@ -1,90 +0,0 @@ -#![crate_name = "hostid"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Maciej Dziardziel - * - * For the full copyright and license information, please view the LICENSE file - * that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use libc::c_long; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "hostid"; -static VERSION: &'static str = "0.0.1"; - -static EXIT_ERR: i32 = 1; - -pub enum Mode { - HostId, - Help, - Version, -} - -// currently rust libc interface doesn't include gethostid -extern { - pub fn gethostid() -> c_long; -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - opts.optflag("", "help", "display this help and exit"); - opts.optflag("", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(_) => { - help(&opts); - return EXIT_ERR; - }, - }; - - let mode = if matches.opt_present("version") { - Mode::Version - } else if matches.opt_present("help") { - Mode::Help - } else { - Mode::HostId - }; - - match mode { - Mode::HostId => hostid(), - Mode::Help => help(&opts), - Mode::Version => version(), - } - - 0 -} - -fn version() { - println!("{} {}", NAME, VERSION); -} - -fn help(opts: &getopts::Options) { - let msg = format!("Usage:\n {} [options]", NAME); - print!("{}", opts.usage(&msg)); -} - -fn hostid() { - /* - * POSIX says gethostid returns a "32-bit identifier" but is silent - * whether it's sign-extended. Turn off any sign-extension. This - * is a no-op unless unsigned int is wider than 32 bits. - */ - - let mut result:c_long; - unsafe { - result = gethostid(); - } - - result &= 0xffffffff; - println!("{:0>8x}", result); -} diff --git a/src/hostname/Cargo.toml b/src/hostname/Cargo.toml deleted file mode 100644 index 2d2db8ee1..000000000 --- a/src/hostname/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "hostname" -version = "0.0.1" -authors = [] - -[lib] -name = "hostname" -path = "hostname.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/hostname/hostname.rs b/src/hostname/hostname.rs deleted file mode 100644 index d22a8d9e3..000000000 --- a/src/hostname/hostname.rs +++ /dev/null @@ -1,176 +0,0 @@ -#![crate_name = "hostname"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Alan Andrade - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * Synced with: - * - * https://www.opensource.apple.com/source/shell_cmds/shell_cmds-170/hostname/hostname.c?txt - */ - -extern crate getopts; -extern crate libc; - -use std::collections::hash_set::HashSet; -use std::iter::repeat; -use std::str; -use std::io::Write; -use std::net::ToSocketAddrs; -use getopts::Options; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "hostname"; - -extern { - fn gethostname(name: *mut libc::c_char, namelen: libc::size_t) -> libc::c_int; -} - -#[cfg(any(target_os = "macos", target_os = "freebsd"))] -extern { - fn sethostname(name: *const libc::c_char, namelen: libc::c_int) -> libc::c_int; -} - -#[cfg(target_os = "linux")] -extern { - fn sethostname(name: *const libc::c_char, namelen: libc::size_t) -> libc::c_int; -} - -pub fn uumain(args: Vec) -> i32 { - let program = &args[0]; - - let mut opts = Options::new(); - opts.optflag("d", "domain", "Display the name of the DNS domain if possible"); - opts.optflag("i", "ip-address", "Display the network address(es) of the host"); - opts.optflag("f", "fqdn", "Display the FQDN (Fully Qualified Domain Name) (default)"); // TODO: support --long - opts.optflag("s", "short", "Display the short hostname (the portion before the first dot) if possible"); - opts.optflag("h", "help", "Show help"); - opts.optflag("V", "version", "Show program's version"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => { m } - _ => { help_menu(program, opts); return 0; } - }; - - if matches.opt_present("h") { - help_menu(program, opts); - return 0 - } - if matches.opt_present("V") { version(); return 0 } - - match matches.free.len() { - 0 => { - let hostname = xgethostname(); - - if matches.opt_present("i") { - match hostname.to_socket_addrs() { - Ok(addresses) => { - let mut hashset = HashSet::new(); - let mut output = String::new(); - for addr in addresses { - // XXX: not sure why this is necessary... - if !hashset.contains(&addr) { - output.push_str(&format!("{}", addr)); - output.push_str(" "); - hashset.insert(addr.clone()); - } - } - let len = output.len(); - if len > 0 { - println!("{}", &output[0 .. len - 1]); - } - } - Err(f) => { - show_error!("{}", f); - return 1; - } - } - } else { - if matches.opt_present("s") { - let mut it = hostname.char_indices().filter(|&ci| ci.1 == '.'); - let ci = it.next(); - if ci.is_some() { - println!("{}", &hostname[0 .. ci.unwrap().0]); - return 0; - } - } else if matches.opt_present("d") { - let mut it = hostname.char_indices().filter(|&ci| ci.1 == '.'); - let ci = it.next(); - if ci.is_some() { - println!("{}", &hostname[ci.unwrap().0 + 1 .. ]); - return 0; - } - } - - println!("{}", hostname); - } - } - 1 => xsethostname(matches.free.last().unwrap()), - _ => help_menu(program, opts) - }; - - 0 -} - -fn version() { - println!("hostname 1.0.0"); -} - -fn help_menu(program: &str, options: Options) { - version(); - println!(""); - println!("Usage:"); - println!(" {} [OPTION]... [HOSTNAME]", program); - println!(""); - print!("{}", options.usage("Print or set the system's host name.")); -} - -fn xgethostname() -> String { - let namelen = 256usize; - let mut name : Vec = repeat(0).take(namelen).collect(); - let err = unsafe { - gethostname (name.as_mut_ptr() as *mut libc::c_char, - namelen as libc::size_t) - }; - - if err != 0 { - panic!("Cannot determine hostname"); - } - - let last_char = name.iter().position(|byte| *byte == 0).unwrap_or(namelen); - - str::from_utf8(&name[..last_char]).unwrap().to_string() -} - -#[cfg(any(target_os = "macos", target_os = "freebsd"))] -fn xsethostname(name: &str) { - let vec_name: Vec = name.bytes().map(|c| c as libc::c_char).collect(); - - let err = unsafe { - sethostname (vec_name.as_ptr(), vec_name.len() as libc::c_int) - }; - - if err != 0 { - println!("Cannot set hostname to {}", name); - } -} - -#[cfg(target_os = "linux")] -fn xsethostname(name: &str) { - let vec_name: Vec = name.bytes().map(|c| c as libc::c_char).collect(); - - let err = unsafe { - sethostname (vec_name.as_ptr(), vec_name.len() as libc::size_t) - }; - - if err != 0 { - println!("Cannot set hostname to {}", name); - } -} diff --git a/src/id/Cargo.toml b/src/id/Cargo.toml deleted file mode 100644 index 39035c77a..000000000 --- a/src/id/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "id" -version = "0.0.1" -authors = [] - -[lib] -name = "id" -path = "id.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/id/id.rs b/src/id/id.rs deleted file mode 100644 index ca3f07e83..000000000 --- a/src/id/id.rs +++ /dev/null @@ -1,397 +0,0 @@ -#![crate_name = "id"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Alan Andrade - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * Synced with: - * http://ftp-archive.freebsd.org/mirror/FreeBSD-Archive/old-releases/i386/1.0-RELEASE/ports/shellutils/src/id.c - * http://www.opensource.apple.com/source/shell_cmds/shell_cmds-118/id/id.c - */ - -#![allow(non_camel_case_types)] -extern crate getopts; -extern crate libc; - -use libc::{getgid, getuid, uid_t}; -use libc::funcs::posix88::unistd::{getegid, geteuid, getlogin}; -use std::ffi::CStr; -use std::io::Write; -use std::ptr::read; -use c_types::{ - c_passwd, - c_group, - get_groups, - get_group_list, - get_pw_from_args, - getpwuid, - group -}; - -#[path = "../common/util.rs"] #[macro_use] mod util; -#[path = "../common/c_types.rs"] mod c_types; - -#[cfg(not(target_os = "linux"))] -mod audit { - pub use std::mem::uninitialized; - use libc::{uid_t, pid_t, c_int, c_uint, uint64_t, dev_t}; - - pub type au_id_t = uid_t; - pub type au_asid_t = pid_t; - pub type au_event_t = c_uint; - pub type au_emod_t = c_uint; - pub type au_class_t = c_int; - - #[repr(C)] - pub struct au_mask { - pub am_success: c_uint, - pub am_failure: c_uint - } - pub type au_mask_t = au_mask; - - #[repr(C)] - pub struct au_tid_addr { - pub port: dev_t, - } - pub type au_tid_addr_t = au_tid_addr; - - #[repr(C)] - pub struct c_auditinfo_addr { - pub ai_auid: au_id_t, /* Audit user ID */ - pub ai_mask: au_mask_t, /* Audit masks. */ - pub ai_termid: au_tid_addr_t, /* Terminal ID. */ - pub ai_asid: au_asid_t, /* Audit session ID. */ - pub ai_flags: uint64_t /* Audit session flags */ - } - pub type c_auditinfo_addr_t = c_auditinfo_addr; - - extern { - pub fn getaudit(auditinfo_addr: *mut c_auditinfo_addr_t) -> c_int; - } -} - -extern { - fn getgrgid(gid: uid_t) -> *const c_group; -} - -static NAME: &'static str = "id"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - opts.optflag("h", "", "Show help"); - opts.optflag("A", "", "Display the process audit (not available on Linux)"); - opts.optflag("G", "", "Display the different group IDs"); - opts.optflag("g", "", "Display the effective group ID as a number"); - opts.optflag("n", "", "Display the name of the user or group ID for the -G, -g and -u options"); - opts.optflag("P", "", "Display the id as a password file entry"); - opts.optflag("p", "", "Make the output human-readable"); - opts.optflag("r", "", "Display the real ID for the -g and -u options"); - opts.optflag("u", "", "Display the effective user ID as a number"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => { m }, - Err(_) => { - println!("{}", opts.usage(NAME)); - return 1; - } - }; - - if matches.opt_present("h") { - println!("{}", opts.usage(NAME)); - return 0; - } - - if matches.opt_present("A") { - auditid(); - return 0; - } - - let possible_pw = get_pw_from_args(&matches.free); - - let nflag = matches.opt_present("n"); - let uflag = matches.opt_present("u"); - let gflag = matches.opt_present("g"); - let rflag = matches.opt_present("r"); - - if gflag { - let id = if possible_pw.is_some() { - possible_pw.unwrap().pw_gid - } else { - if rflag { - unsafe { getgid() } - } else { - unsafe { getegid() } - } - }; - let gr = unsafe { getgrgid(id) }; - - if nflag && !gr.is_null() { - let gr_name = unsafe { String::from_utf8_lossy(CStr::from_ptr(read(gr).gr_name).to_bytes()).to_string() }; - println!("{}", gr_name); - } else { - println!("{}", id); - } - return 0; - } - - if uflag { - let id = if possible_pw.is_some() { - possible_pw.unwrap().pw_uid - } else if rflag { - unsafe { getgid() } - } else { - unsafe { getegid() } - }; - - let pw = unsafe { getpwuid(id) }; - if nflag && !pw.is_null() { - let pw_name = unsafe { - String::from_utf8_lossy(CStr::from_ptr(read(pw).pw_name).to_bytes()).to_string() - }; - println!("{}", pw_name); - } else { - println!("{}", id); - } - - return 0; - } - - if matches.opt_present("G") { - group(possible_pw, nflag); - return 0; - } - - if matches.opt_present("P") { - pline(possible_pw); - return 0; - }; - - if matches.opt_present("p") { - pretty(possible_pw); - return 0; - } - - if possible_pw.is_some() { - id_print(possible_pw, false, false) - } else { - id_print(possible_pw, true, true) - } - - 0 -} - -fn pretty(possible_pw: Option) { - if possible_pw.is_some() { - let pw = possible_pw.unwrap(); - - let pw_name = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_name).to_bytes()).to_string() }; - print!("uid\t{}\ngroups\t", pw_name); - group(possible_pw, true); - } else { - let login = unsafe { String::from_utf8_lossy(CStr::from_ptr((getlogin() as *const i8)).to_bytes()).to_string() }; - let rid = unsafe { getuid() }; - let pw = unsafe { getpwuid(rid) }; - - let is_same_user = unsafe { - String::from_utf8_lossy(CStr::from_ptr(read(pw).pw_name).to_bytes()).to_string() == login - }; - - if pw.is_null() || is_same_user { - println!("login\t{}", login); - } - - if !pw.is_null() { - println!( - "uid\t{}", - unsafe { String::from_utf8_lossy(CStr::from_ptr(read(pw).pw_name).to_bytes()).to_string() }) - } else { - println!("uid\t{}\n", rid); - } - - let eid = unsafe { getegid() }; - if eid == rid { - let pw = unsafe { getpwuid(eid) }; - if !pw.is_null() { - println!( - "euid\t{}", - unsafe { String::from_utf8_lossy(CStr::from_ptr(read(pw).pw_name).to_bytes()).to_string() }); - } else { - println!("euid\t{}", eid); - } - } - - let rid = unsafe { getgid() }; - - if rid != eid { - let gr = unsafe { getgrgid(rid) }; - if !gr.is_null() { - println!( - "rgid\t{}", - unsafe { String::from_utf8_lossy(CStr::from_ptr(read(gr).gr_name).to_bytes()).to_string() }); - } else { - println!("rgid\t{}", rid); - } - } - - print!("groups\t"); - group(None, true); - } -} - -#[cfg(any(target_os = "macos", target_os = "freebsd"))] -fn pline(possible_pw: Option) { - let pw = if possible_pw.is_none() { - unsafe { read(getpwuid(getuid())) } - } else { - possible_pw.unwrap() - }; - - let pw_name = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_name ).to_bytes()).to_string()}; - let pw_passwd = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_passwd).to_bytes()).to_string()}; - let pw_class = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_class ).to_bytes()).to_string()}; - let pw_gecos = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_gecos ).to_bytes()).to_string()}; - let pw_dir = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_dir ).to_bytes()).to_string()}; - let pw_shell = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_shell ).to_bytes()).to_string()}; - - println!( - "{}:{}:{}:{}:{}:{}:{}:{}:{}:{}", - pw_name, - pw_passwd, - pw.pw_uid, - pw.pw_gid, - pw_class, - pw.pw_change, - pw.pw_expire, - pw_gecos, - pw_dir, - pw_shell); -} - -#[cfg(target_os = "linux")] -fn pline(possible_pw: Option) { - let pw = if possible_pw.is_none() { - unsafe { read(getpwuid(getuid())) } - } else { - possible_pw.unwrap() - }; - - let pw_name = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_name ).to_bytes()).to_string()}; - let pw_passwd = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_passwd).to_bytes()).to_string()}; - let pw_gecos = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_gecos ).to_bytes()).to_string()}; - let pw_dir = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_dir ).to_bytes()).to_string()}; - let pw_shell = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_shell ).to_bytes()).to_string()}; - - println!( - "{}:{}:{}:{}:{}:{}:{}", - pw_name, - pw_passwd, - pw.pw_uid, - pw.pw_gid, - pw_gecos, - pw_dir, - pw_shell); -} - -#[cfg(target_os = "linux")] -fn auditid() { } - -#[cfg(not(target_os = "linux"))] -fn auditid() { - let mut auditinfo: audit::c_auditinfo_addr_t = unsafe { audit::uninitialized() }; - let address = &mut auditinfo as *mut audit::c_auditinfo_addr_t; - if unsafe { audit::getaudit(address) } < 0 { - println!("couldn't retrieve information"); - return; - } - - println!("auid={}", auditinfo.ai_auid); - println!("mask.success=0x{:x}", auditinfo.ai_mask.am_success); - println!("mask.failure=0x{:x}", auditinfo.ai_mask.am_failure); - println!("termid.port=0x{:x}", auditinfo.ai_termid.port); - println!("asid={}", auditinfo.ai_asid); -} - -fn id_print(possible_pw: Option, p_euid: bool, p_egid: bool) { - let uid; - let gid; - - if possible_pw.is_some() { - uid = possible_pw.unwrap().pw_uid; - gid = possible_pw.unwrap().pw_gid; - } else { - uid = unsafe { getuid() }; - gid = unsafe { getgid() }; - } - - let groups = match possible_pw { - Some(pw) => Ok(get_group_list(pw.pw_name, pw.pw_gid)), - None => get_groups(), - }; - - let groups = groups.unwrap_or_else(|errno| { - crash!(1, "failed to get group list (errno={})", errno); - }); - - if possible_pw.is_some() { - print!( - "uid={}({})", - uid, - unsafe { String::from_utf8_lossy(CStr::from_ptr(possible_pw.unwrap().pw_name).to_bytes()).to_string() }); - } else { - print!("uid={}", unsafe { getuid() }); - } - - print!(" gid={}", gid); - let gr = unsafe { getgrgid(gid) }; - if !gr.is_null() { - print!( - "({})", - unsafe { String::from_utf8_lossy(CStr::from_ptr(read(gr).gr_name).to_bytes()).to_string() }); - } - - let euid = unsafe { geteuid() }; - if p_euid && (euid != uid) { - print!(" euid={}", euid); - let pw = unsafe { getpwuid(euid) }; - if !pw.is_null() { - print!( - "({})", - unsafe { String::from_utf8_lossy(CStr::from_ptr(read(pw).pw_name).to_bytes()).to_string() }); - } - } - - let egid = unsafe { getegid() }; - if p_egid && (egid != gid) { - print!(" egid={}", egid); - unsafe { - let grp = getgrgid(egid); - if !grp.is_null() { - print!("({})", String::from_utf8_lossy(CStr::from_ptr(read(grp).gr_name).to_bytes()).to_string()); - } - } - } - - if groups.len() > 0 { - print!(" groups="); - - let mut first = true; - for &gr in groups.iter() { - if !first { print!(",") } - print!("{}", gr); - let group = unsafe { getgrgid(gr) }; - if !group.is_null() { - let name = unsafe { - String::from_utf8_lossy(CStr::from_ptr(read(group).gr_name).to_bytes()).to_string() - }; - print!("({})", name); - } - first = false - } - } - - println!(""); -} diff --git a/src/kill/Cargo.toml b/src/kill/Cargo.toml deleted file mode 100644 index 7f36a1bd6..000000000 --- a/src/kill/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "kill" -version = "0.0.1" -authors = [] - -[lib] -name = "kill" -path = "kill.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/kill/kill.rs b/src/kill/kill.rs deleted file mode 100644 index 1556a2807..000000000 --- a/src/kill/kill.rs +++ /dev/null @@ -1,194 +0,0 @@ -#![crate_name = "kill"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Maciej Dziardziel - * - * For the full copyright and license information, please view the LICENSE file - * that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use libc::{c_int, pid_t}; -use signals::ALL_SIGNALS; -use std::io::{Error, Write}; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[path = "../common/c_types.rs"] -mod c_types; - -#[path = "../common/signals.rs"] -mod signals; - -static NAME: &'static str = "kill"; -static VERSION: &'static str = "0.0.1"; - -static EXIT_OK: i32 = 0; -static EXIT_ERR: i32 = 1; - -#[derive(Clone, Copy)] -pub enum Mode { - Kill, - Table, - List, - Help, - Version, -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - opts.optopt("s", "signal", "specify the to be sent", "SIGNAL"); - opts.optflagopt("l", "list", "list all signal names, or convert one to a name", "LIST"); - opts.optflag("L", "table", "list all signal names in a nice table"); - - let (args, obs_signal) = handle_obsolete(args); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(_) => { - help(&opts); - return EXIT_ERR; - }, - }; - - let mode = if matches.opt_present("version") { - Mode::Version - } else if matches.opt_present("help") { - Mode::Help - } else if matches.opt_present("table") { - Mode::Table - } else if matches.opt_present("list") { - Mode::List - } else { - Mode::Kill - }; - - match mode { - Mode::Kill => return kill(&matches.opt_str("signal").unwrap_or(obs_signal.unwrap_or("9".to_string())), matches.free), - Mode::Table => table(), - Mode::List => list(matches.opt_str("list")), - Mode::Help => help(&opts), - Mode::Version => version(), - } - - 0 -} - -fn version() { - println!("{} {}", NAME, VERSION); -} - -fn handle_obsolete(mut args: Vec) -> (Vec, Option) { - let mut i = 0; - while i < args.len() { - // this is safe because slice is valid when it is referenced - let slice = &args[i].clone(); - if slice.chars().next().unwrap() == '-' && slice.len() > 1 && slice.chars().nth(1).unwrap().is_digit(10) { - let val = &slice[1..]; - match val.parse() { - Ok(num) => { - if signals::is_signal(num) { - args.remove(i); - return (args, Some(val.to_string())); - } - } - Err(_)=> break /* getopts will error out for us */ - } - } - i += 1; - } - (args, None) -} - -fn table() { - let mut name_width = 0; - /* Compute the maximum width of a signal name. */ - for s in ALL_SIGNALS.iter() { - if s.name.len() > name_width { - name_width = s.name.len() - } - } - - for (idx, signal) in ALL_SIGNALS.iter().enumerate() { - print!("{0: >#2} {1: <#8}", idx+1, signal.name); - //TODO: obtain max signal width here - - if (idx+1) % 7 == 0 { - println!(""); - } - } -} - -fn print_signal(signal_name_or_value: &str) { - for signal in ALL_SIGNALS.iter() { - if signal.name == signal_name_or_value || (format!("SIG{}", signal.name)) == signal_name_or_value { - println!("{}", signal.value); - exit!(EXIT_OK as i32) - } else if signal_name_or_value == signal.value.to_string() { - println!("{}", signal.name); - exit!(EXIT_OK as i32) - } - } - crash!(EXIT_ERR, "unknown signal name {}", signal_name_or_value) -} - -fn print_signals() { - let mut pos = 0; - for (idx, signal) in ALL_SIGNALS.iter().enumerate() { - pos += signal.name.len(); - print!("{}", signal.name); - if idx > 0 && pos > 73 { - println!(""); - pos = 0; - } else { - pos += 1; - print!(" "); - } - } -} - -fn list(arg: Option) { - match arg { - Some(ref x) => print_signal(x), - None => print_signals(), - }; -} - -fn help(opts: &getopts::Options) { - let msg = format!("{0} {1} - -Usage: - {0} [options] [...]", NAME, VERSION); - - println!("{}", opts.usage(&msg)); -} - -fn kill(signalname: &str, pids: std::vec::Vec) -> i32 { - let mut status = 0; - let optional_signal_value = signals::signal_by_name_or_value(signalname); - let signal_value = match optional_signal_value { - Some(x) => x, - None => crash!(EXIT_ERR, "unknown signal name {}", signalname) - }; - for pid in pids.iter() { - match pid.parse::() { - Ok(x) => { - if unsafe { libc::funcs::posix88::signal::kill(x as pid_t, signal_value as c_int) } != 0 { - show_error!("{}", Error::last_os_error()); - status = 1; - } - }, - Err(e) => crash!(EXIT_ERR, "failed to parse argument {}: {}", pid, e) - }; - } - status -} diff --git a/src/link/Cargo.toml b/src/link/Cargo.toml deleted file mode 100644 index 84044b784..000000000 --- a/src/link/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "link" -version = "0.0.1" -authors = [] - -[lib] -name = "link" -path = "link.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/link/link.rs b/src/link/link.rs deleted file mode 100644 index a762550b7..000000000 --- a/src/link/link.rs +++ /dev/null @@ -1,66 +0,0 @@ -#![crate_name = "link"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Michael Gehring - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; - -use std::fs::hard_link; -use std::io::Write; -use std::path::Path; - -#[path="../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "link"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(err) => panic!("{}", err), - }; - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - if matches.opt_present("help") || matches.free.len() != 2 { - let msg = format!("{0} {1} - -Usage: - {0} [OPTIONS] FILE1 FILE2 - -Create a link named FILE2 to FILE1.", NAME, VERSION); - - println!("{}", opts.usage(&msg)); - if matches.free.len() != 2 { - return 1; - } - return 0; - } - - let old = Path::new(&matches.free[0]); - let new = Path::new(&matches.free[1]); - - match hard_link(old, new) { - Ok(_) => 0, - Err(err) => { - show_error!("{}", err); - 1 - } - } -} diff --git a/src/ln/Cargo.toml b/src/ln/Cargo.toml deleted file mode 100644 index 8ec3cb1d7..000000000 --- a/src/ln/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "ln" -version = "0.0.1" -authors = [] - -[lib] -name = "ln" -path = "ln.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/ln/ln.rs b/src/ln/ln.rs deleted file mode 100644 index 6a7646e93..000000000 --- a/src/ln/ln.rs +++ /dev/null @@ -1,333 +0,0 @@ -#![crate_name = "ln"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Joseph Crail - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; - -use std::fs; -use std::io::{BufRead, BufReader, Result, stdin, Write}; -#[cfg(unix)] use std::os::unix::fs::symlink as symlink_file; -#[cfg(windows)] use std::os::windows::fs::symlink_file; -use std::path::{Path, PathBuf}; - -#[path="../common/util.rs"] -#[macro_use] -mod util; - -#[path="../common/filesystem.rs"] -mod filesystem; - -use filesystem::UUPathExt; - -static NAME: &'static str = "ln"; -static VERSION: &'static str = "1.0.0"; - -pub struct Settings { - overwrite: OverwriteMode, - backup: BackupMode, - suffix: String, - symbolic: bool, - target_dir: Option, - no_target_dir: bool, - verbose: bool, -} - -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum OverwriteMode { - NoClobber, - Interactive, - Force, -} - -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum BackupMode { - NoBackup, - SimpleBackup, - NumberedBackup, - ExistingBackup, -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("b", "", "make a backup of each file that would otherwise be overwritten or removed"); - opts.optflagopt("", "backup", "make a backup of each file that would otherwise be overwritten or removed", "METHOD"); - // TODO: opts.optflag("d", "directory", "allow users with appropriate privileges to attempt to make hard links to directories"); - opts.optflag("f", "force", "remove existing destination files"); - opts.optflag("i", "interactive", "prompt whether to remove existing destination files"); - // TODO: opts.optflag("L", "logical", "dereference TARGETs that are symbolic links"); - // TODO: opts.optflag("n", "no-dereference", "treat LINK_NAME as a normal file if it is a symbolic link to a directory"); - // TODO: opts.optflag("P", "physical", "make hard links directly to symbolic links"); - // TODO: opts.optflag("r", "relative", "create symbolic links relative to link location"); - opts.optflag("s", "symbolic", "make symbolic links instead of hard links"); - opts.optopt("S", "suffix", "override the usual backup suffix", "SUFFIX"); - opts.optopt("t", "target-directory", "specify the DIRECTORY in which to create the links", "DIRECTORY"); - opts.optflag("T", "no-target-directory", "treat LINK_NAME as a normal file always"); - opts.optflag("v", "verbose", "print name of each linked file"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(e) => crash!(1, "{}", e), - }; - - let overwrite_mode = if matches.opt_present("force") { - OverwriteMode::Force - } else if matches.opt_present("interactive") { - OverwriteMode::Interactive - } else { - OverwriteMode::NoClobber - }; - - let backup_mode = if matches.opt_present("b") { - BackupMode::ExistingBackup - } else if matches.opt_present("backup") { - match matches.opt_str("backup") { - None => BackupMode::ExistingBackup, - Some(mode) => match &mode[..] { - "simple" | "never" => BackupMode::SimpleBackup, - "numbered" | "t" => BackupMode::NumberedBackup, - "existing" | "nil" => BackupMode::ExistingBackup, - "none" | "off" => BackupMode::NoBackup, - x => { - show_error!("invalid argument '{}' for 'backup method'\n\ - Try '{} --help' for more information.", x, NAME); - return 1; - } - } - } - } else { - BackupMode::NoBackup - }; - - let backup_suffix = if matches.opt_present("suffix") { - match matches.opt_str("suffix") { - Some(x) => x, - None => { - show_error!("option '--suffix' requires an argument\n\ - Try '{} --help' for more information.", NAME); - return 1; - } - } - } else { - "~".to_string() - }; - - if matches.opt_present("T") && matches.opt_present("t") { - show_error!("cannot combine --target-directory (-t) and --no-target-directory (-T)"); - return 1; - } - - let settings = Settings { - overwrite: overwrite_mode, - backup: backup_mode, - suffix: backup_suffix, - symbolic: matches.opt_present("s"), - target_dir: matches.opt_str("t"), - no_target_dir: matches.opt_present("T"), - verbose: matches.opt_present("v"), - }; - - let string_to_path = |s: &String| { PathBuf::from(s) }; - let paths: Vec = matches.free.iter().map(string_to_path).collect(); - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - 0 - } else if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: {0} [OPTION]... [-T] TARGET LINK_NAME (1st form) - or: {0} [OPTION]... TARGET (2nd form) - or: {0} [OPTION]... TARGET... DIRECTORY (3rd form) - or: {0} [OPTION]... -t DIRECTORY TARGET... (4th form) - -In the 1st form, create a link to TARGET with the name LINK_NAME. -In the 2nd form, create a link to TARGET in the current directory. -In the 3rd and 4th forms, create links to each TARGET in DIRECTORY. -Create hard links by default, symbolic links with --symbolic. -By default, each destination (name of new link) should not already exist. -When creating hard links, each TARGET must exist. Symbolic links -can hold arbitrary text; if later resolved, a relative link is -interpreted in relation to its parent directory.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - 0 - } else { - exec(&paths[..], &settings) - } -} - -fn exec(files: &[PathBuf], settings: &Settings) -> i32 { - match settings.target_dir { - Some(ref name) => return link_files_in_dir(files, &PathBuf::from(name), &settings), - None => {} - } - match files.len() { - 0 => { - show_error!("missing file operand\nTry '{} --help' for more information.", NAME); - 1 - }, - 1 => match link(&files[0], &files[0], settings) { - Ok(_) => 0, - Err(e) => { - show_error!("{}", e); - 1 - } - }, - 2 => match link(&files[0], &files[1], settings) { - Ok(_) => 0, - Err(e) => { - show_error!("{}", e); - 1 - } - }, - _ => { - if settings.no_target_dir { - show_error!("extra operand '{}'\nTry '{} --help' for more information.", files[2].display(), NAME); - return 1; - } - let (targets, dir) = match settings.target_dir { - Some(ref dir) => (files, PathBuf::from(dir.clone())), - None => (&files[0..files.len()-1], files[files.len()-1].clone()) - }; - link_files_in_dir(targets, &dir, settings) - } - } -} - -fn link_files_in_dir(files: &[PathBuf], target_dir: &PathBuf, settings: &Settings) -> i32 { - if !target_dir.uu_is_dir() { - show_error!("target '{}' is not a directory", target_dir.display()); - return 1; - } - - let mut all_successful = true; - for srcpath in files.iter() { - let targetpath = match srcpath.as_os_str().to_str() { - Some(name) => target_dir.join(name), - None => { - show_error!("cannot stat '{}': No such file or directory", - srcpath.display()); - all_successful = false; - continue; - } - }; - - match link(srcpath, &targetpath, settings) { - Err(e) => { - show_error!("cannot link '{}' to '{}': {}", - targetpath.display(), srcpath.display(), e); - all_successful = false; - }, - _ => {} - } - } - if all_successful { 0 } else { 1 } -} - -fn link(src: &PathBuf, dst: &PathBuf, settings: &Settings) -> Result<()> { - let mut backup_path = None; - - if dst.uu_is_dir() { - if settings.no_target_dir { - try!(fs::remove_dir(dst)); - } - } - - if is_symlink(dst) || dst.uu_exists() { - match settings.overwrite { - OverwriteMode::NoClobber => {}, - OverwriteMode::Interactive => { - print!("{}: overwrite '{}'? ", NAME, dst.display()); - if !read_yes() { - return Ok(()); - } - try!(fs::remove_file(dst)) - }, - OverwriteMode::Force => { - try!(fs::remove_file(dst)) - } - }; - - backup_path = match settings.backup { - BackupMode::NoBackup => None, - BackupMode::SimpleBackup => Some(simple_backup_path(dst, &settings.suffix)), - BackupMode::NumberedBackup => Some(numbered_backup_path(dst)), - BackupMode::ExistingBackup => Some(existing_backup_path(dst, &settings.suffix)) - }; - if let Some(ref p) = backup_path { - try!(fs::rename(dst, p)); - } - } - - if settings.symbolic { - try!(symlink(src, dst)); - } else { - try!(fs::hard_link(src, dst)); - } - - if settings.verbose { - print!("'{}' -> '{}'", dst.display(), src.display()); - match backup_path { - Some(path) => println!(" (backup: '{}')", path.display()), - None => println!("") - } - } - Ok(()) -} - -fn read_yes() -> bool { - let mut s = String::new(); - match BufReader::new(stdin()).read_line(&mut s) { - Ok(_) => match s.char_indices().nth(0) { - Some((_, x)) => x == 'y' || x == 'Y', - _ => false - }, - _ => false - } -} - -fn simple_backup_path(path: &PathBuf, suffix: &String) -> PathBuf { - let mut p = path.as_os_str().to_str().unwrap().to_string(); - p.push_str(suffix); - PathBuf::from(p) -} - -fn numbered_backup_path(path: &PathBuf) -> PathBuf { - let mut i: u64 = 1; - loop { - let new_path = simple_backup_path(path, &format!(".~{}~", i)); - if !new_path.uu_exists() { - return new_path; - } - i += 1; - } -} - -fn existing_backup_path(path: &PathBuf, suffix: &String) -> PathBuf { - let test_path = simple_backup_path(path, &".~1~".to_string()); - if test_path.uu_exists() { - return numbered_backup_path(path); - } - simple_backup_path(path, suffix) -} - -pub fn symlink>(src: P, dst: P) -> Result<()> { - symlink_file(src, dst) -} - -pub fn is_symlink>(path: P) -> bool { - match fs::symlink_metadata(path) { - Ok(m) => m.file_type().is_symlink(), - Err(_) => false - } -} diff --git a/src/logname/Cargo.toml b/src/logname/Cargo.toml deleted file mode 100644 index b207e91bf..000000000 --- a/src/logname/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "logname" -version = "0.0.1" -authors = [] - -[lib] -name = "logname" -path = "logname.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/logname/logname.rs b/src/logname/logname.rs deleted file mode 100644 index c587bf038..000000000 --- a/src/logname/logname.rs +++ /dev/null @@ -1,81 +0,0 @@ -#![crate_name = "logname"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Benoit Benedetti - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/* last synced with: logname (GNU coreutils) 8.22 */ - -extern crate getopts; -extern crate libc; - -use std::ffi::CStr; -use std::io::Write; - -#[path = "../common/util.rs"] #[macro_use] mod util; - -extern { - // POSIX requires using getlogin (or equivalent code) - pub fn getlogin() -> *const libc::c_char; -} - -fn get_userlogin() -> Option { - unsafe { - let login: *const libc::c_char = getlogin(); - if login.is_null() { - None - } else { - Some(String::from_utf8_lossy(CStr::from_ptr(login).to_bytes()).to_string()) - } - } -} - -static NAME: &'static str = "logname"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - // - // Argument parsing - // - let mut opts = getopts::Options::new(); - - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "Invalid options\n{}", f) - }; - - if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: - {0} - -Print user's login name.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - return 0; - } - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - exec(); - - 0 -} - -fn exec() { - match get_userlogin() { - Some(userlogin) => println!("{}", userlogin), - None => println!("{}: no login name", NAME) - } -} diff --git a/src/mkdir/Cargo.toml b/src/mkdir/Cargo.toml deleted file mode 100644 index 11f916bb0..000000000 --- a/src/mkdir/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "mkdir" -version = "0.0.1" -authors = [] - -[lib] -name = "mkdir" -path = "mkdir.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/mkdir/mkdir.rs b/src/mkdir/mkdir.rs deleted file mode 100644 index b68fe0d09..000000000 --- a/src/mkdir/mkdir.rs +++ /dev/null @@ -1,160 +0,0 @@ -#![crate_name = "mkdir"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Nicholas Juszczak - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use std::ffi::CString; -use std::fs; -use std::io::{Error, Write}; -use std::path::{Path, PathBuf}; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[path = "../common/filesystem.rs"] -mod filesystem; - -use filesystem::UUPathExt; - -static NAME: &'static str = "mkdir"; -static VERSION: &'static str = "1.0.0"; - -/** - * Handles option parsing - */ -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - // Linux-specific options, not implemented - // opts.optflag("Z", "context", "set SELinux secutiry context" + - // " of each created directory to CTX"), - opts.optopt("m", "mode", "set file mode", "755"); - opts.optflag("p", "parents", "make parent directories as needed"); - opts.optflag("v", "verbose", "print a message for each printed directory"); - opts.optflag("h", "help", "display this help"); - opts.optflag("V", "version", "display this version"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "Invalid options\n{}", f) - }; - - if args.len() == 1 || matches.opt_present("help") { - print_help(&opts); - return 0; - } - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - let verbose = matches.opt_present("verbose"); - let recursive = matches.opt_present("parents"); - - // Translate a ~str in octal form to u16, default to 755 - // Not tested on Windows - let mode_match = matches.opts_str(&["mode".to_string()]); - let mode: u16 = if mode_match.is_some() { - let m = mode_match.unwrap(); - let res: Option = u16::from_str_radix(&m, 8).ok(); - if res.is_some() { - unsafe { std::mem::transmute(res.unwrap()) } - } else { - crash!(1, "no mode given"); - } - } else { - unsafe { std::mem::transmute(0o755 as u16) } - }; - - let dirs = matches.free; - if dirs.is_empty() { - crash!(1, "missing operand"); - } - exec(dirs, recursive, mode, verbose) -} - -fn print_help(opts: &getopts::Options) { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - print!("{}", opts.usage("Create the given DIRECTORY(ies) if they do not exist")); -} - -/** - * Create the list of new directories - */ -fn exec(dirs: Vec, recursive: bool, mode: u16, verbose: bool) -> i32 { - let mut status = 0; - let empty = Path::new(""); - for dir in dirs.iter() { - let path = Path::new(dir); - if recursive { - let mut pathbuf = PathBuf::new(); - for component in path.components() { - pathbuf.push(component.as_os_str()); - status |= mkdir(pathbuf.as_path(), mode, verbose); - } - } else { - match path.parent() { - Some(parent) => { - if parent != empty && !parent.uu_exists() { - show_info!("cannot create directory '{}': No such file or directory", path.display()); - status = 1; - } else { - status |= mkdir(path, mode, verbose); - } - }, - None => { - status |= mkdir(path, mode, verbose); - } - } - } - } - status -} - -/** - * Wrapper to catch errors, return 1 if failed - */ -fn mkdir(path: &Path, mode: u16, verbose: bool) -> i32 { - if path.uu_exists() { - show_info!("cannot create directory '{}': File exists", path.display()); - return 1; - } - - if let Err(e) = fs::create_dir(path) { - show_info!("{}: {}", path.display(), e.to_string()); - return 1; - } - - if verbose { - show_info!("created directory '{}'", path.display()); - } - - #[cfg(unix)] - fn chmod(path: &Path, mode: u16) -> i32 { - let directory = CString::new(path.as_os_str().to_str().unwrap()).unwrap_or_else(|e| crash!(1, "{}", e)); - let mode = mode as libc::mode_t; - - if unsafe { libc::chmod(directory.as_ptr(), mode) } != 0 { - show_info!("{}: errno {}", path.display(), Error::last_os_error().raw_os_error().unwrap()); - return 1; - } - 0 - } - #[cfg(windows)] - fn chmod(path: &Path, mode: u16) -> i32 { - // chmod on Windows only sets the readonly flag, which isn't even honored on directories - 0 - } - chmod(path, mode) -} diff --git a/src/mkfifo/Cargo.toml b/src/mkfifo/Cargo.toml deleted file mode 100644 index a8b347e2c..000000000 --- a/src/mkfifo/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "mkfifo" -version = "0.0.1" -authors = [] - -[lib] -name = "mkfifo" -path = "mkfifo.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/mkfifo/mkfifo.rs b/src/mkfifo/mkfifo.rs deleted file mode 100644 index 9b496c416..000000000 --- a/src/mkfifo/mkfifo.rs +++ /dev/null @@ -1,79 +0,0 @@ -#![crate_name = "mkfifo"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Michael Gehring - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use libc::funcs::posix88::stat_::mkfifo; -use std::ffi::CString; -use std::io::{Error, Write}; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "mkfifo"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optopt("m", "mode", "file permissions for the fifo", "(default 0666)"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(err) => panic!("{}", err), - }; - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - if matches.opt_present("help") || matches.free.is_empty() { - let msg = format!("{0} {1} - -Usage: - {0} [OPTIONS] NAME... - -Create a FIFO with the given name.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - if matches.free.is_empty() { - return 1; - } - return 0; - } - - let mode = match matches.opt_str("m") { - Some(m) => match usize::from_str_radix(&m, 8) { - Ok(m) => m, - Err(e)=> { - show_error!("invalid mode: {}", e); - return 1; - } - }, - None => 0o666, - }; - - let mut exit_status = 0; - for f in matches.free.iter() { - let err = unsafe { mkfifo(CString::new(f.as_bytes()).unwrap().as_ptr(), mode as libc::mode_t) }; - if err == -1 { - show_error!("creating '{}': {}", f, Error::last_os_error().raw_os_error().unwrap()); - exit_status = 1; - } - } - - exit_status -} diff --git a/src/mv/Cargo.toml b/src/mv/Cargo.toml deleted file mode 100644 index a9e89f11d..000000000 --- a/src/mv/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "mv" -version = "0.0.1" -authors = [] - -[lib] -name = "mv" -path = "mv.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/mv/deps.mk b/src/mv/deps.mk deleted file mode 100644 index 0e162f8f0..000000000 --- a/src/mv/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += kernel32 winapi filetime time diff --git a/src/mv/mv.rs b/src/mv/mv.rs deleted file mode 100644 index f8317ccd9..000000000 --- a/src/mv/mv.rs +++ /dev/null @@ -1,358 +0,0 @@ -#![crate_name = "mv"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Orvar Segerström - * (c) Sokovikov Evgeniy - * - * For the full copyright and license information, please view the LICENSE file - * that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use std::fs; -use std::io::{BufRead, BufReader, Result, stdin, Write}; -use std::os::unix::fs::MetadataExt; -use std::path::{Path, PathBuf}; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[path = "../common/filesystem.rs"] -mod filesystem; - -use filesystem::UUPathExt; - -static NAME: &'static str = "mv"; -static VERSION: &'static str = "0.0.1"; - -pub struct Behaviour { - overwrite: OverwriteMode, - backup: BackupMode, - suffix: String, - update: bool, - target_dir: Option, - no_target_dir: bool, - verbose: bool, -} - -#[derive(Clone, Eq, PartialEq)] -pub enum OverwriteMode { - NoClobber, - Interactive, - Force, -} - -#[derive(Clone, Eq, PartialEq)] -pub enum BackupMode { - NoBackup, - SimpleBackup, - NumberedBackup, - ExistingBackup, -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflagopt("", "backup", "make a backup of each existing destination file", "CONTROL"); - opts.optflag("b", "", "like --backup but does not accept an argument"); - opts.optflag("f", "force", "do not prompt before overwriting"); - opts.optflag("i", "interactive", "prompt before override"); - opts.optflag("n", "no-clobber", "do not overwrite an existing file"); - opts.optflag("", "strip-trailing-slashes", "remove any trailing slashes from each SOURCE\n \ - argument"); - opts.optopt("S", "suffix", "override the usual backup suffix", "SUFFIX"); - opts.optopt("t", "target-directory", "move all SOURCE arguments into DIRECTORY", "DIRECTORY"); - opts.optflag("T", "no-target-directory", "treat DEST as a normal file"); - opts.optflag("u", "update", "move only when the SOURCE file is newer\n \ - than the destination file or when the\n \ - destination file is missing"); - opts.optflag("v", "verbose", "explain what is being done"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - show_error!("Invalid options\n{}", f); - return 1; - } - }; - let usage = opts.usage("Move SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY."); - - /* This does not exactly match the GNU implementation: - * The GNU mv defaults to Force, but if more than one of the - * overwrite options are supplied, only the last takes effect. - * To default to no-clobber in that situation seems safer: - */ - let overwrite_mode = if matches.opt_present("no-clobber") { - OverwriteMode::NoClobber - } else if matches.opt_present("interactive") { - OverwriteMode::Interactive - } else { - OverwriteMode::Force - }; - - let backup_mode = if matches.opt_present("b") { - BackupMode::SimpleBackup - } else if matches.opt_present("backup") { - match matches.opt_str("backup") { - None => BackupMode::SimpleBackup, - Some(mode) => match &mode[..] { - "simple" | "never" => BackupMode::SimpleBackup, - "numbered" | "t" => BackupMode::NumberedBackup, - "existing" | "nil" => BackupMode::ExistingBackup, - "none" | "off" => BackupMode::NoBackup, - x => { - show_error!("invalid argument ‘{}’ for ‘backup type’\n\ - Try '{} --help' for more information.", x, NAME); - return 1; - } - } - } - } else { - BackupMode::NoBackup - }; - - if overwrite_mode == OverwriteMode::NoClobber && backup_mode != BackupMode::NoBackup { - show_error!("options --backup and --no-clobber are mutually exclusive\n\ - Try '{} --help' for more information.", NAME); - return 1; - } - - let backup_suffix = if matches.opt_present("suffix") { - match matches.opt_str("suffix") { - Some(x) => x, - None => { - show_error!("option '--suffix' requires an argument\n\ - Try '{} --help' for more information.", NAME); - return 1; - } - } - } else { - "~".to_string() - }; - - if matches.opt_present("T") && matches.opt_present("t") { - show_error!("cannot combine --target-directory (-t) and --no-target-directory (-T)"); - return 1; - } - - let behaviour = Behaviour { - overwrite: overwrite_mode, - backup: backup_mode, - suffix: backup_suffix, - update: matches.opt_present("u"), - target_dir: matches.opt_str("t"), - no_target_dir: matches.opt_present("T"), - verbose: matches.opt_present("v"), - }; - - let paths: Vec = { - fn string_to_path<'a>(s: &'a String) -> &'a Path { - Path::new(s) - }; - fn strip_slashes<'a>(p: &'a Path) -> &'a Path { - p.components().as_path() - } - let to_owned = |p: &Path| p.to_owned(); - let arguments = matches.free.iter().map(string_to_path); - if matches.opt_present("strip-trailing-slashes") { - arguments.map(strip_slashes).map(to_owned).collect() - } else { - arguments.map(to_owned).collect() - } - }; - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - 0 - } else if matches.opt_present("help") { - help(&usage); - 0 - } else { - exec(&paths[..], behaviour) - } -} - -fn help(usage: &str) { - println!("{0} {1}\n\n\ - Usage: {0} SOURCE DEST\n \ - or: {0} SOURCE... DIRECTORY\n\n\ - {2}", NAME, VERSION, usage); -} - -fn exec(files: &[PathBuf], b: Behaviour) -> i32 { - match b.target_dir { - Some(ref name) => return move_files_into_dir(files, &PathBuf::from(name), &b), - None => {} - } - match files.len() { - 0 | 1 => { - show_error!("missing file operand\n\ - Try '{} --help' for more information.", NAME); - return 1; - }, - 2 => { - let ref source = files[0]; - let ref target = files[1]; - if !source.uu_exists() { - show_error!("cannot stat ‘{}’: No such file or directory", source.display()); - return 1; - } - - if target.uu_is_dir() { - if b.no_target_dir { - if !source.uu_is_dir() { - show_error!("cannot overwrite directory ‘{}’ with non-directory", - target.display()); - return 1; - } - - return match rename(source, target, &b) { - Err(e) => { - show_error!("{}", e); - 1 - }, - _ => 0 - } - } - - return move_files_into_dir(&[source.clone()], target, &b); - } - - match rename(source, target, &b) { - Err(e) => { - show_error!("{}", e); - return 1; - }, - _ => {} - } - } - _ => { - if b.no_target_dir { - show_error!("mv: extra operand ‘{}’\n\ - Try '{} --help' for more information.", files[2].display(), NAME); - return 1; - } - let target_dir = files.last().unwrap(); - move_files_into_dir(&files[0..files.len()-1], target_dir, &b); - } - } - 0 -} - -fn move_files_into_dir(files: &[PathBuf], target_dir: &PathBuf, b: &Behaviour) -> i32 { - if !target_dir.uu_is_dir() { - show_error!("target ‘{}’ is not a directory", target_dir.display()); - return 1; - } - - let mut all_successful = true; - for sourcepath in files.iter() { - let targetpath = match sourcepath.as_os_str().to_str() { - Some(name) => target_dir.join(name), - None => { - show_error!("cannot stat ‘{}’: No such file or directory", - sourcepath.display()); - - all_successful = false; - continue; - } - }; - - match rename(sourcepath, &targetpath, b) { - Err(e) => { - show_error!("mv: cannot move ‘{}’ to ‘{}’: {}", - sourcepath.display(), targetpath.display(), e); - all_successful = false; - }, - _ => {} - } - }; - if all_successful { 0 } else { 1 } -} - -fn rename(from: &PathBuf, to: &PathBuf, b: &Behaviour) -> Result<()> { - let mut backup_path = None; - - if to.uu_exists() { - match b.overwrite { - OverwriteMode::NoClobber => return Ok(()), - OverwriteMode::Interactive => { - print!("{}: overwrite ‘{}’? ", NAME, to.display()); - if !read_yes() { - return Ok(()); - } - }, - OverwriteMode::Force => {} - }; - - backup_path = match b.backup { - BackupMode::NoBackup => None, - BackupMode::SimpleBackup => Some(simple_backup_path(to, &b.suffix)), - BackupMode::NumberedBackup => Some(numbered_backup_path(to)), - BackupMode::ExistingBackup => Some(existing_backup_path(to, &b.suffix)) - }; - if let Some(ref p) = backup_path { - try!(fs::rename(to, p)); - } - - if b.update { - if try!(fs::metadata(from)).mtime() <= try!(fs::metadata(to)).mtime() { - return Ok(()); - } - } - } - - try!(fs::rename(from, to)); - - if b.verbose { - print!("‘{}’ -> ‘{}’", from.display(), to.display()); - match backup_path { - Some(path) => println!(" (backup: ‘{}’)", path.display()), - None => println!("") - } - } - Ok(()) -} - -fn read_yes() -> bool { - let mut s = String::new(); - match BufReader::new(stdin()).read_line(&mut s) { - Ok(_) => match s.char_indices().nth(0) { - Some((_, x)) => x == 'y' || x == 'Y', - _ => false - }, - _ => false - } -} - -fn simple_backup_path(path: &PathBuf, suffix: &String) -> PathBuf { - let mut p = path.as_os_str().to_str().unwrap().to_string(); - p.push_str(suffix); - return PathBuf::from(p); -} - -fn numbered_backup_path(path: &PathBuf) -> PathBuf { - let mut i: u64 = 1; - loop { - let new_path = simple_backup_path(path, &format!(".~{}~", i)); - if !new_path.uu_exists() { - return new_path; - } - i = i + 1; - } -} - -fn existing_backup_path(path: &PathBuf, suffix: &String) -> PathBuf { - let test_path = simple_backup_path(path, &".~1~".to_string()); - if test_path.uu_exists() { - return numbered_backup_path(path); - } - simple_backup_path(path, suffix) -} diff --git a/src/nice/Cargo.toml b/src/nice/Cargo.toml deleted file mode 100644 index 812e0f61b..000000000 --- a/src/nice/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "nice" -version = "0.0.1" -authors = [] - -[lib] -name = "nice" -path = "nice.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/nice/nice.rs b/src/nice/nice.rs deleted file mode 100644 index d5e13576d..000000000 --- a/src/nice/nice.rs +++ /dev/null @@ -1,112 +0,0 @@ -#![crate_name = "nice"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Arcterus - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use libc::{c_char, c_int, execvp}; -use std::ffi::CString; -use std::io::{Error, Write}; - -const NAME: &'static str = "nice"; -const VERSION: &'static str = "1.0.0"; - -// XXX: PRIO_PROCESS is 0 on at least FreeBSD and Linux. Don't know about Mac OS X. -const PRIO_PROCESS: c_int = 0; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -extern { - fn getpriority(which: c_int, who: c_int) -> c_int; - fn setpriority(which: c_int, who: c_int, prio: c_int) -> c_int; -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optopt("n", "adjustment", "add N to the niceness (default is 10)", "N"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(err) => { - show_error!("{}", err); - return 125; - } - }; - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: - {0} [OPTIONS] [COMMAND [ARGS]] - -Run COMMAND with an adjusted niceness, which affects process scheduling. -With no COMMAND, print the current niceness. Niceness values range from at -least -20 (most favorable to the process) to 19 (least favorable to the -process).", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - return 0; - } - - let mut niceness = unsafe { getpriority(PRIO_PROCESS, 0) }; - if Error::last_os_error().raw_os_error().unwrap() != 0 { - show_error!("{}", Error::last_os_error()); - return 125; - } - - let adjustment = match matches.opt_str("adjustment") { - Some(nstr) => { - if matches.free.len() == 0 { - show_error!("A command must be given with an adjustment. - Try \"{} --help\" for more information.", args[0]); - return 125; - } - match nstr.parse() { - Ok(num) => num, - Err(e)=> { - show_error!("\"{}\" is not a valid number: {}", nstr, e); - return 125; - } - } - }, - None => { - if matches.free.len() == 0 { - println!("{}", niceness); - return 0; - } - 10 as c_int - } - }; - - niceness += adjustment; - unsafe { setpriority(PRIO_PROCESS, 0, niceness); } - if Error::last_os_error().raw_os_error().unwrap() != 0 { - show_warning!("{}", Error::last_os_error()); - } - - let cstrs: Vec = matches.free.iter().map(|x| CString::new(x.as_bytes()).unwrap()).collect(); - let mut args: Vec<*const c_char> = cstrs.iter().map(|s| s.as_ptr()).collect(); - args.push(0 as *const c_char); - unsafe { execvp(args[0], args.as_mut_ptr()); } - - show_error!("{}", Error::last_os_error()); - if Error::last_os_error().raw_os_error().unwrap() as c_int == libc::ENOENT { 127 } else { 126 } -} diff --git a/src/nl/Cargo.toml b/src/nl/Cargo.toml deleted file mode 100644 index 3ca33339e..000000000 --- a/src/nl/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "nl" -version = "0.0.1" -authors = [] - -[lib] -name = "nl" -path = "nl.rs" - -[dependencies] -getopts = "*" -libc = "*" -aho-corasick = "*" -memchr = "*" -regex = "*" -regex-syntax = "*" diff --git a/src/nl/deps.mk b/src/nl/deps.mk deleted file mode 100644 index 78a05f8b6..000000000 --- a/src/nl/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += aho-corasick memchr regex regex-syntax diff --git a/src/nl/helper.rs b/src/nl/helper.rs deleted file mode 100644 index 2cdd5d9f5..000000000 --- a/src/nl/helper.rs +++ /dev/null @@ -1,121 +0,0 @@ -extern crate getopts; -extern crate regex; - -// parse_style parses a style string into a NumberingStyle. -fn parse_style(chars: &[char]) -> Result<::NumberingStyle, String> { - if chars.len() == 1 && chars[0] == 'a' { - Ok(::NumberingStyle::NumberForAll) - } else if chars.len() == 1 && chars[0] == 't' { - Ok(::NumberingStyle::NumberForNonEmpty) - } else if chars.len() == 1 && chars[0] == 'n' { - Ok(::NumberingStyle::NumberForNone) - } else if chars.len() > 1 && chars[0] == 'p' { - let s: String = chars[1..].iter().map(|c| *c).collect(); - match regex::Regex::new(&s) { - Ok(re) => Ok(::NumberingStyle::NumberForRegularExpression(re)), - Err(_) => Err(String::from("Illegal regular expression")), - } - } else { - Err(String::from("Illegal style encountered")) - } -} - -// parse_options loads the options into the settings, returning an array of -// error messages. -pub fn parse_options(settings: &mut ::Settings, opts: &getopts::Matches) -> Vec { - // This vector holds error messages encountered. - let mut errs: Vec = vec![]; - settings.renumber = !opts.opt_present("p"); - match opts.opt_str("s") { - None => {}, - Some(val) => { settings.number_separator = val; } - } - match opts.opt_str("n") { - None => {}, - Some(val) => match val.as_ref() { - "ln" => { settings.number_format = ::NumberFormat::Left; }, - "rn" => { settings.number_format = ::NumberFormat::Right; }, - "rz" => { settings.number_format = ::NumberFormat::RightZero; }, - _ => { errs.push(String::from("Illegal value for -n")); }, - } - } - match opts.opt_str("b") { - None => {}, - Some(val) => { - let chars: Vec = val.chars().collect(); - match parse_style(&chars) { - Ok(s) => { settings.body_numbering = s; } - Err(message) => { errs.push(message); } - } - } - } - match opts.opt_str("f") { - None => {}, - Some(val) => { - let chars: Vec = val.chars().collect(); - match parse_style(&chars) { - Ok(s) => { settings.footer_numbering = s; } - Err(message) => { errs.push(message); } - } - } - } - match opts.opt_str("h") { - None => {}, - Some(val) => { - let chars: Vec = val.chars().collect(); - match parse_style(&chars) { - Ok(s) => { settings.header_numbering = s; } - Err(message) => { errs.push(message); } - } - } - } - match opts.opt_str("i") { - None => {} - Some(val) => { - let conv: Option = val.parse().ok(); - match conv { - None => { - errs.push(String::from("Illegal value for -i")); - } - Some(num) => { settings.line_increment = num } - } - } - } - match opts.opt_str("w") { - None => {} - Some(val) => { - let conv: Option = val.parse().ok(); - match conv { - None => { - errs.push(String::from("Illegal value for -w")); - } - Some(num) => { settings.number_width = num } - } - } - } - match opts.opt_str("v") { - None => {} - Some(val) => { - let conv: Option = val.parse().ok(); - match conv { - None => { - errs.push(String::from("Illegal value for -v")); - } - Some(num) => { settings.starting_line_number = num } - } - } - } - match opts.opt_str("l") { - None => {} - Some(val) => { - let conv: Option = val.parse().ok(); - match conv { - None => { - errs.push(String::from("Illegal value for -l")); - } - Some(num) => { settings.join_blank_lines = num } - } - } - } - errs -} diff --git a/src/nl/nl.rs b/src/nl/nl.rs deleted file mode 100644 index b6048d32d..000000000 --- a/src/nl/nl.rs +++ /dev/null @@ -1,330 +0,0 @@ -#![crate_name = "nl"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Tobias Bohumir Schottdorf - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - */ - -extern crate aho_corasick; -extern crate getopts; -extern crate memchr; -extern crate regex_syntax; -extern crate regex; - -use std::fs::File; -use std::io::{BufRead, BufReader, Read, stdin, Write}; -use std::iter::repeat; -use std::path::Path; - -#[path="../common/util.rs"] -#[macro_use] -mod util; -mod helper; - -static NAME: &'static str = "nl"; -static VERSION: &'static str = "1.0.0"; -static USAGE: &'static str = "nl [OPTION]... [FILE]..."; -// A regular expression matching everything. - -// Settings store options used by nl to produce its output. -pub struct Settings { - // The variables corresponding to the options -h, -b, and -f. - header_numbering: NumberingStyle, - body_numbering: NumberingStyle, - footer_numbering: NumberingStyle, - // The variable corresponding to -d - section_delimiter: [char; 2], - // The variables corresponding to the options -v, -i, -l, -w. - starting_line_number: u64, - line_increment: u64, - join_blank_lines: u64, - number_width: usize, // Used with String::from_char, hence usize. - // The format of the number and the (default value for) - // renumbering each page. - number_format: NumberFormat, - renumber: bool, - // The string appended to each line number output. - number_separator: String -} - -// NumberingStyle stores which lines are to be numberd. -// The possible options are: -// 1. Number all lines -// 2. Number only nonempty lines -// 3. Don't number any lines at all -// 4. Number all lines that match a basic regular expression. -enum NumberingStyle { - NumberForAll, - NumberForNonEmpty, - NumberForNone, - NumberForRegularExpression(regex::Regex) -} - -// NumberFormat specifies how line numbers are output within their allocated -// space. They are justified to the left or right, in the latter case with -// the option of having all unused space to its left turned into leading zeroes. -enum NumberFormat { - Left, - Right, - RightZero, -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optopt("b", "body-numbering", "use STYLE for numbering body lines", "STYLE"); - opts.optopt("d", "section-delimiter", "use CC for separating logical pages", "CC"); - opts.optopt("f", "footer-numbering", "use STYLE for numbering footer lines", "STYLE"); - opts.optopt("h", "header-numbering", "use STYLE for numbering header lines", "STYLE"); - opts.optopt("i", "line-increment", "line number increment at each line", ""); - opts.optopt("l", "join-blank-lines", "group of NUMBER empty lines counted as one", "NUMBER"); - opts.optopt("n", "number-format", "insert line numbers according to FORMAT", "FORMAT"); - opts.optflag("p", "no-renumber", "do not reset line numbers at logical pages"); - opts.optopt("s", "number-separator", "add STRING after (possible) line number", "STRING"); - opts.optopt("v", "starting-line-number", "first line number on each logical page", "NUMBER"); - opts.optopt("w", "number-width", "use NUMBER columns for line numbers", "NUMBER"); - opts.optflag("", "help", "display this help and exit"); - opts.optflag("V", "version", "version"); - - // A mutable settings object, initialized with the defaults. - let mut settings = Settings { - header_numbering: NumberingStyle::NumberForNone, - body_numbering: NumberingStyle::NumberForAll, - footer_numbering: NumberingStyle::NumberForNone, - section_delimiter: ['\\', ':'], - starting_line_number: 1, - line_increment: 1, - join_blank_lines: 1, - number_width: 6, - number_format: NumberFormat::Right, - renumber: true, - number_separator: String::from("\t"), - }; - - let given_options = match opts.parse(&args[1..]) { - Ok (m) => { m } - Err(f) => { - show_error!("{}", f); - print_usage(&opts); - return 1 - } - }; - - if given_options.opt_present("help") { - print_usage(&opts); - return 0; - } - if given_options.opt_present("version") { version(); return 0; } - - // Update the settings from the command line options, and terminate the - // program if some options could not successfully be parsed. - let parse_errors = helper::parse_options(&mut settings, &given_options); - if parse_errors.len() > 0 { - show_error!("Invalid arguments supplied."); - for message in parse_errors.iter() { - println!("{}", message); - } - return 1; - } - - let files = given_options.free; - let mut read_stdin = files.is_empty(); - - for file in files.iter() { - if file == "-" { - // If both file names and '-' are specified, we choose to treat first all - // regular files, and then read from stdin last. - read_stdin = true; - continue - } - let path = Path::new(file); - let reader = File::open(path).unwrap(); - let mut buffer = BufReader::new(reader); - nl(&mut buffer, &settings); - } - - if read_stdin { - let mut buffer = BufReader::new(stdin()); - nl(&mut buffer, &settings); - } - 0 -} - -// nl implements the main functionality for an individual buffer. -fn nl (reader: &mut BufReader, settings: &Settings) { - let regexp: regex::Regex = regex::Regex::new(r".?").unwrap(); - let mut line_no = settings.starting_line_number; - // The current line number's width as a string. Using to_string is inefficient - // but since we only do it once, it should not hurt. - let mut line_no_width = line_no.to_string().len(); - let line_no_width_initial = line_no_width; - // Stores the smallest integer with one more digit than line_no, so that - // when line_no >= line_no_threshold, we need to use one more digit. - let mut line_no_threshold = 10u64.pow(line_no_width as u32); - let mut empty_line_count: u64 = 0; - let fill_char = match settings.number_format { - NumberFormat::RightZero => '0', - _ => ' ' - }; - // Initially, we use the body's line counting settings - let mut regex_filter = match settings.body_numbering { - NumberingStyle::NumberForRegularExpression(ref re) => re, - _ => ®exp, - }; - let mut line_filter : fn(&str, ®ex::Regex) -> bool = pass_regex; - for mut l in reader.lines().map(|r| r.unwrap()) { - // Sanitize the string. We want to print the newline ourselves. - if l.len() > 0 && l.chars().rev().next().unwrap() == '\n' { - l.pop(); - } - // Next we iterate through the individual chars to see if this - // is one of the special lines starting a new "section" in the - // document. - let line = l; - let mut odd = false; - // matched_group counts how many copies of section_delimiter - // this string consists of (0 if there's anything else) - let mut matched_groups = 0u8; - for c in line.chars() { - // If this is a newline character, the loop should end. - if c == '\n' { - break; - } - // If we have already seen three groups (corresponding to - // a header) or the current char does not form part of - // a new group, then this line is not a segment indicator. - if matched_groups >= 3 - || settings.section_delimiter[if odd { 1 } else { 0 }] != c { - matched_groups = 0; - break; - } - if odd { - // We have seen a new group and count it. - matched_groups += 1; - } - odd = !odd; - } - - // See how many groups we matched. That will tell us if this is - // a line starting a new segment, and the number of groups - // indicates what type of segment. - if matched_groups > 0 { - // The current line is a section delimiter, so we output - // a blank line. - println!(""); - // However the line does not count as a blank line, so we - // reset the counter used for --join-blank-lines. - empty_line_count = 0; - match *match matched_groups { - 3 => { - // This is a header, so we may need to reset the - // line number and the line width - if settings.renumber { - line_no = settings.starting_line_number; - line_no_width = line_no_width_initial; - line_no_threshold = 10u64.pow(line_no_width as u32); - } - &settings.header_numbering - }, - 1 => { - &settings.footer_numbering - }, - // The only option left is 2, but rust wants - // a catch-all here. - _ => { - &settings.body_numbering - } - } { - NumberingStyle::NumberForAll => { - line_filter = pass_all; - }, - NumberingStyle::NumberForNonEmpty => { - line_filter = pass_nonempty; - }, - NumberingStyle::NumberForNone => { - line_filter = pass_none; - } - NumberingStyle::NumberForRegularExpression(ref re) => { - line_filter = pass_regex; - regex_filter = re; - } - } - continue; - } - // From this point on we format and print a "regular" line. - if line == "" { - // The line is empty, which means that we have to care - // about the --join-blank-lines parameter. - empty_line_count += 1; - } else { - // This saves us from having to check for an empty string - // in the next selector. - empty_line_count = 0; - } - if !line_filter(&line, regex_filter) - || ( empty_line_count > 0 && empty_line_count < settings.join_blank_lines) { - // No number is printed for this line. Either we did not - // want to print one in the first place, or it is a blank - // line but we are still collecting more blank lines via - // the option --join-blank-lines. - println!("{}", line); - continue; - } - // If we make it here, then either we are printing a non-empty - // line or assigning a line number to an empty line. Either - // way, start counting empties from zero once more. - empty_line_count = 0; - // A line number is to be printed. - let mut w: usize = 0; - if settings.number_width > line_no_width { - w = settings.number_width - line_no_width; - } - let fill: String = repeat(fill_char).take(w).collect(); - match settings.number_format { - NumberFormat::Left => { - println!("{1}{0}{2}{3}", fill, line_no, settings.number_separator, line) - }, - _ => { - println!("{0}{1}{2}{3}", fill, line_no, settings.number_separator, line) - } - } - // Now update the variables for the (potential) next - // line. - line_no += settings.line_increment; - while line_no >= line_no_threshold { - // The line number just got longer. - line_no_threshold *= 10; - line_no_width += 1; - } - - } -} - -fn pass_regex(line: &str, re: ®ex::Regex) -> bool { - re.is_match(line) -} - -fn pass_nonempty(line: &str, _: ®ex::Regex) -> bool { - line.len() > 0 -} - -fn pass_none(_: &str, _: ®ex::Regex) -> bool { - false -} - -fn pass_all(_: &str, _: ®ex::Regex) -> bool { - true -} - -fn print_usage(opts: &getopts::Options) { - println!("{}", opts.usage(USAGE)); -} - -fn version() { - println!("{} {}", NAME, VERSION); -} diff --git a/src/nohup/Cargo.toml b/src/nohup/Cargo.toml deleted file mode 100644 index e4d916481..000000000 --- a/src/nohup/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "nohup" -version = "0.0.1" -authors = [] - -[lib] -name = "nohup" -path = "nohup.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/nohup/nohup.rs b/src/nohup/nohup.rs deleted file mode 100644 index 304776d5a..000000000 --- a/src/nohup/nohup.rs +++ /dev/null @@ -1,149 +0,0 @@ -#![crate_name = "nohup"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) 2014 Vsevolod Velichko - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use libc::c_char; -use libc::funcs::posix01::signal::signal; -use libc::funcs::posix88::unistd::{dup2, execvp, isatty}; -use libc::consts::os::posix01::SIG_IGN; -use libc::consts::os::posix88::SIGHUP; -use std::env; -use std::ffi::CString; -use std::fs::{File, OpenOptions}; -use std::io::{Error, Write}; -use std::os::unix::prelude::*; -use std::path::{Path, PathBuf}; - -#[path = "../common/util.rs"] #[macro_use] mod util; -#[path = "../common/c_types.rs"] mod c_types; - -static NAME: &'static str = "nohup"; -static VERSION: &'static str = "1.0.0"; - -#[cfg(target_os = "macos")] -extern { - fn _vprocmgr_detach_from_console(flags: u32) -> *const libc::c_int; -} - -#[cfg(any(target_os = "linux", target_os = "freebsd"))] -unsafe fn _vprocmgr_detach_from_console(_: u32) -> *const libc::c_int { std::ptr::null() } - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("h", "help", "Show help and exit"); - opts.optflag("V", "version", "Show version and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - show_error!("{}", f); - show_usage(&opts); - return 1 - } - }; - - if matches.opt_present("V") { println!("{} {}", NAME, VERSION); return 0 } - if matches.opt_present("h") { show_usage(&opts); return 0 } - - if matches.free.len() == 0 { - show_error!("Missing operand: COMMAND"); - println!("Try `{} --help` for more information.", NAME); - return 1 - } - replace_fds(); - - unsafe { signal(SIGHUP, SIG_IGN) }; - - if unsafe { _vprocmgr_detach_from_console(0) } != std::ptr::null() { crash!(2, "Cannot detach from console")}; - - let cstrs: Vec = matches.free.iter().map(|x| CString::new(x.as_bytes()).unwrap()).collect(); - let mut args: Vec<*const c_char> = cstrs.iter().map(|s| s.as_ptr()).collect(); - args.push(std::ptr::null()); - unsafe { execvp(args[0], args.as_mut_ptr())} -} - -fn replace_fds() { - let replace_stdin = unsafe { isatty(libc::STDIN_FILENO) == 1 }; - let replace_stdout = unsafe { isatty(libc::STDOUT_FILENO) == 1 }; - let replace_stderr = unsafe { isatty(libc::STDERR_FILENO) == 1 }; - - if replace_stdin { - let new_stdin = match File::open(Path::new("/dev/null")) { - Ok(t) => t, - Err(e) => { - crash!(2, "Cannot replace STDIN: {}", e) - } - }; - if unsafe { dup2(new_stdin.as_raw_fd(), 0) } != 0 { - crash!(2, "Cannot replace STDIN: {}", Error::last_os_error()) - } - } - - if replace_stdout { - let new_stdout = find_stdout(); - let fd = new_stdout.as_raw_fd(); - - if unsafe { dup2(fd, 1) } != 1 { - crash!(2, "Cannot replace STDOUT: {}", Error::last_os_error()) - } - } - - if replace_stderr { - if unsafe { dup2(1, 2) } != 2 { - crash!(2, "Cannot replace STDERR: {}", Error::last_os_error()) - } - } -} - -fn find_stdout() -> File { - match OpenOptions::new().write(true).create(true).append(true).open(Path::new("nohup.out")) { - Ok(t) => { - show_warning!("Output is redirected to: nohup.out"); - t - }, - Err(e) => { - let home = match env::var("HOME") { - Err(_) => crash!(2, "Cannot replace STDOUT: {}", e), - Ok(h) => h - }; - let mut homeout = PathBuf::from(home); - homeout.push("nohup.out"); - match OpenOptions::new().write(true).create(true).append(true).open(&homeout) { - Ok(t) => { - show_warning!("Output is redirected to: {:?}", homeout); - t - }, - Err(e) => { - crash!(2, "Cannot replace STDOUT: {}", e) - } - } - } - } -} - -fn show_usage(opts: &getopts::Options) { - let msg = format!("{0} {1} - -Usage: - {0} COMMAND [ARG]... - {0} OPTION - -Run COMMAND ignoring hangup signals. -If standard input is terminal, it'll be replaced with /dev/null. -If standard output is terminal, it'll be appended to nohup.out instead, -or $HOME/nohup.out, if nohup.out open failed. -If standard error is terminal, it'll be redirected to stdout.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); -} diff --git a/src/nproc/Cargo.toml b/src/nproc/Cargo.toml deleted file mode 100644 index 289086eb5..000000000 --- a/src/nproc/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "nproc" -version = "0.0.1" -authors = [] - -[lib] -name = "nproc" -path = "nproc.rs" - -[dependencies] -getopts = "*" -libc = "*" -num_cpus = "*" diff --git a/src/nproc/deps.mk b/src/nproc/deps.mk deleted file mode 100644 index 8bd1a6c62..000000000 --- a/src/nproc/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += num_cpus diff --git a/src/nproc/nproc.rs b/src/nproc/nproc.rs deleted file mode 100644 index 037d2a3e7..000000000 --- a/src/nproc/nproc.rs +++ /dev/null @@ -1,87 +0,0 @@ -#![crate_name = "nproc"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Michael Gehring - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate num_cpus; - -use std::env; -use std::io::Write; - -static NAME : &'static str = "nproc"; -static VERSION : &'static str = "0.0.0"; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("", "all", "print the number of cores available to the system"); - opts.optopt("", "ignore", "ignore up to N cores", "N"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(err) => { - show_error!("{}", err); - return 1; - } - }; - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: - {0} [OPTIONS]... - -Print the number of cores available to the current process.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - return 0; - } - - let mut ignore = match matches.opt_str("ignore") { - Some(numstr) => match numstr.parse() { - Ok(num) => num, - Err(e) => { - show_error!("\"{}\" is not a valid number: {}", numstr, e); - return 1; - } - }, - None => 0 - }; - - if !matches.opt_present("all") { - ignore += match env::var("OMP_NUM_THREADS") { - Ok(threadstr) => match threadstr.parse() { - Ok(num) => num, - Err(_)=> 0 - }, - Err(_) => 0 - }; - } - - let mut cores = num_cpus::get(); - if cores <= ignore { - cores = 1; - } else { - cores -= ignore; - } - println!("{}", cores); - 0 -} diff --git a/src/od/Cargo.toml b/src/od/Cargo.toml deleted file mode 100644 index e6e1d7183..000000000 --- a/src/od/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "od" -version = "0.0.1" -authors = [] - -[lib] -name = "od" -path = "od.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/od/od.rs b/src/od/od.rs deleted file mode 100644 index da9295855..000000000 --- a/src/od/od.rs +++ /dev/null @@ -1,126 +0,0 @@ -#![crate_name = "od"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Ben Hirsch - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; - -use std::fs::File; -use std::io::Read; -use std::mem; -use std::path::Path; - -#[derive(Debug)] -enum Radix { Decimal, Hexadecimal, Octal, Binary } - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optopt("A", "address-radix", - "Select the base in which file offsets are printed.", "RADIX"); - opts.optopt("j", "skip-bytes", - "Skip bytes input bytes before formatting and writing.", "BYTES"); - opts.optopt("N", "read-bytes", - "limit dump to BYTES input bytes", "BYTES"); - opts.optopt("S", "strings", - ("output strings of at least BYTES graphic chars. 3 is assumed when \ - BYTES is not specified."), - "BYTES"); - opts.optopt("t", "format", "select output format or formats", "TYPE"); - opts.optflag("v", "output-duplicates", "do not use * to mark line suppression"); - opts.optopt("w", "width", - ("output BYTES bytes per output line. 32 is implied when BYTES is not \ - specified."), - "BYTES"); - opts.optflag("h", "help", "display this help and exit."); - opts.optflag("", "version", "output version information and exit."); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => panic!("Invalid options\n{}", f) - }; - - let input_offset_base = match parse_radix(matches.opt_str("A")) { - Ok(r) => r, - Err(f) => { panic!("Invalid -A/--address-radix\n{}", f) } - }; - - let fname = match args.last() { - Some(n) => n, - None => { panic!("Need fname for now") ; } - }; - - main(&input_offset_base, &fname); - - 0 -} - -fn main(input_offset_base: &Radix, fname: &str) { - let mut f = match File::open(Path::new(fname)) { - Ok(f) => f, - Err(e) => panic!("file error: {}", e) - }; - - let mut addr = 0; - let bytes = &mut [b'\x00'; 16]; - loop { - match f.read(bytes) { - Ok(n) => { - print_with_radix(input_offset_base, addr); - for b in 0 .. n / mem::size_of::() { - let bs = &bytes[(2 * b) .. (2 * b + 2)]; - let p: u16 = (bs[1] as u16) << 8 | bs[0] as u16; - print!(" {:06o}", p); - } - if n % mem::size_of::() == 1 { - print!(" {:06o}", bytes[n - 1]); - } - print!("\n"); - addr += n; - }, - Err(_) => { - print_with_radix(input_offset_base, addr); - break; - } - }; - }; -} - -fn parse_radix(radix_str: Option) -> Result { - match radix_str { - None => Ok(Radix::Octal), - Some(s) => { - let st = s.into_bytes(); - if st.len() != 1 { - Err("Radix must be one of [d, o, b, x]\n") - } else { - let radix: char = *(st.get(0) - .expect("byte string of length 1 lacks a 0th elem")) as char; - match radix { - 'd' => Ok(Radix::Decimal), - 'x' => Ok(Radix::Hexadecimal), - 'o' => Ok(Radix::Octal), - 'b' => Ok(Radix::Binary), - _ => Err("Radix must be one of [d, o, b, x]\n") - } - } - } - } -} - -fn print_with_radix(r: &Radix, x: usize) { - // TODO(keunwoo): field widths should be based on sizeof(x), or chosen dynamically based on the - // expected range of address values. Binary in particular is not great here. - match *r { - Radix::Decimal => print!("{:07}", x), - Radix::Hexadecimal => print!("{:07X}", x), - Radix::Octal => print!("{:07o}", x), - Radix::Binary => print!("{:07b}", x) - } -} diff --git a/src/paste/Cargo.toml b/src/paste/Cargo.toml deleted file mode 100644 index 9800ef127..000000000 --- a/src/paste/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "paste" -version = "0.0.1" -authors = [] - -[lib] -name = "paste" -path = "paste.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/paste/paste.rs b/src/paste/paste.rs deleted file mode 100644 index 6a8592138..000000000 --- a/src/paste/paste.rs +++ /dev/null @@ -1,130 +0,0 @@ -#![crate_name = "paste"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Arcterus - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use std::io::{BufRead, BufReader, Read, stdin, Write}; -use std::iter::repeat; -use std::fs::File; -use std::path::Path; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "paste"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("s", "serial", "paste one file at a time instead of in parallel"); - opts.optopt("d", "delimiters", "reuse characters from LIST instead of TABs", "LIST"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(e) => crash!(1, "{}", e) - }; - - if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: - {0} [OPTION]... [FILE]... - -Write lines consisting of the sequentially corresponding lines from each -FILE, separated by TABs, to standard output.", NAME, VERSION); - print!("{}", opts.usage(&msg)); - } else if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - } else { - let serial = matches.opt_present("serial"); - let delimiters = matches.opt_str("delimiters").unwrap_or("\t".to_string()); - paste(matches.free, serial, delimiters); - } - - 0 -} - -fn paste(filenames: Vec, serial: bool, delimiters: String) { - let mut files: Vec>> = filenames.into_iter().map(|name| - BufReader::new( - if name == "-" { - Box::new(stdin()) as Box - } else { - let r = crash_if_err!(1, File::open(Path::new(&name))); - Box::new(r) as Box - } - ) - ).collect(); - - let delimiters: Vec = unescape(delimiters).chars().map(|x| x.to_string()).collect(); - let mut delim_count = 0; - - if serial { - for file in files.iter_mut() { - let mut output = String::new(); - loop { - let mut line = String::new(); - match file.read_line(&mut line) { - Ok(0) => break, - Ok(_) => { - output.push_str(line.trim_right()); - output.push_str(&delimiters[delim_count % delimiters.len()]); - } - Err(e) => crash!(1, "{}", e.to_string()) - } - delim_count += 1; - } - println!("{}", &output[..output.len()-1]); - } - } else { - let mut eof: Vec = repeat(false).take(files.len()).collect(); - loop { - let mut output = String::new(); - let mut eof_count = 0; - for (i, file) in files.iter_mut().enumerate() { - if eof[i] { - eof_count += 1; - } else { - let mut line = String::new(); - match file.read_line(&mut line) { - Ok(0) => { - eof[i] = true; - eof_count += 1; - } - Ok(_) => output.push_str(line.trim_right()), - Err(e) => crash!(1, "{}", e.to_string()) - } - } - output.push_str(&delimiters[delim_count % delimiters.len()]); - delim_count += 1; - } - if files.len() == eof_count { - break; - } - println!("{}", &output[..output.len()-1]); - delim_count = 0; - } - } -} - -// Unescape all special characters -// TODO: this will need work to conform to GNU implementation -fn unescape(s: String) -> String { - s.replace("\\n", "\n") - .replace("\\t", "\t") - .replace("\\\\", "\\") - .replace("\\", "") -} diff --git a/src/printenv/Cargo.toml b/src/printenv/Cargo.toml deleted file mode 100644 index 166816d5c..000000000 --- a/src/printenv/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "printenv" -version = "0.0.1" -authors = [] - -[lib] -name = "printenv" -path = "printenv.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/printenv/printenv.rs b/src/printenv/printenv.rs deleted file mode 100644 index d895449f9..000000000 --- a/src/printenv/printenv.rs +++ /dev/null @@ -1,78 +0,0 @@ -#![crate_name = "printenv"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/* last synced with: printenv (GNU coreutils) 8.13 */ - -extern crate getopts; -extern crate libc; - -use std::env; -use std::io::Write; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "printenv"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - opts.optflag("0", "null", "end each output line with 0 byte rather than newline"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - crash!(1, "Invalid options\n{}", f) - } - }; - if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: - {0} [VARIABLE]... [OPTION]... - -Prints the given environment VARIABLE(s), otherwise prints them all.", NAME, VERSION); - print!("{}", opts.usage(&msg)); - return 0; - } - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - let mut separator = "\n"; - if matches.opt_present("null") { - separator = "\x00"; - }; - - exec(matches.free, separator); - - 0 -} - -pub fn exec(args: Vec, separator: &str) { - if args.is_empty() { - for (env_var, value) in env::vars() { - print!("{}={}{}", env_var, value, separator); - } - return; - } - - for env_var in args.iter() { - match env::var(env_var) { - Ok(var) => { - print!("{}{}", var, separator); - } - _ => () - } - } -} diff --git a/src/ptx/Cargo.toml b/src/ptx/Cargo.toml deleted file mode 100644 index 65f0cc7b7..000000000 --- a/src/ptx/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "ptx" -version = "0.0.1" -authors = [] - -[lib] -name = "ptx" -path = "ptx.rs" - -[dependencies] -getopts = "*" -libc = "*" -aho-corasick = "*" -memchr = "*" -regex-syntax = "*" -regex = "*" diff --git a/src/ptx/deps.mk b/src/ptx/deps.mk deleted file mode 100644 index 78a05f8b6..000000000 --- a/src/ptx/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += aho-corasick memchr regex regex-syntax diff --git a/src/ptx/ptx.rs b/src/ptx/ptx.rs deleted file mode 100644 index 0569d130b..000000000 --- a/src/ptx/ptx.rs +++ /dev/null @@ -1,564 +0,0 @@ -#![crate_name = "ptx"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Dorota Kapturkiewicz - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate aho_corasick; -extern crate getopts; -extern crate memchr; -extern crate regex_syntax; -extern crate regex; - -use std::collections::{HashMap, HashSet, BTreeSet}; -use std::default::Default; -use std::fs::File; -use getopts::{Options, Matches}; -use std::io::{stdin, stdout, BufReader, BufWriter, BufRead, Read, Write}; -use regex::Regex; -use std::cmp; - - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "ptx"; -static VERSION: &'static str = "1.0.0"; - -#[derive(Debug)] -enum OutFormat { - Dumb, - Roff, - Tex, -} - -#[derive(Debug)] -struct Config { - format : OutFormat, - gnu_ext : bool, - auto_ref : bool, - input_ref : bool, - right_ref : bool, - ignore_case : bool, - macro_name : String, - trunc_str : String, - context_regex : String, - line_width : usize, - gap_size : usize, -} - -impl Default for Config { - fn default() -> Config { - Config { - format : OutFormat::Dumb, - gnu_ext : true, - auto_ref : false, - input_ref : false, - right_ref : false, - ignore_case : false, - macro_name : "xx".to_string(), - trunc_str : "/".to_string(), - context_regex : "\\w+".to_string(), - line_width : 72, - gap_size : 3 - } - } -} - -fn read_word_filter_file(matches: &Matches, option: &str) -> HashSet { - let filename = matches.opt_str(option).expect("parsing options failed!"); - let reader = BufReader::new(crash_if_err!(1, File::open(filename))); - let mut words: HashSet = HashSet::new(); - for word in reader.lines() { - words.insert(crash_if_err!(1, word)); - } - words -} - -#[derive(Debug)] -struct WordFilter { - only_specified: bool, - ignore_specified: bool, - only_set: HashSet, - ignore_set: HashSet, - word_regex: String, -} - -impl WordFilter { - fn new(matches: &Matches, config: &Config) -> WordFilter { - let (o, oset): (bool, HashSet) = - if matches.opt_present("o") { - (true, read_word_filter_file(matches, "o")) - } else { - (false, HashSet::new()) - }; - let (i, iset): (bool, HashSet) = - if matches.opt_present("i") { - (true, read_word_filter_file(matches, "i")) - } else { - (false, HashSet::new()) - }; - if matches.opt_present("b") { - crash!(1, "-b not implemented yet"); - } - let reg = - if matches.opt_present("W") { - matches.opt_str("W").expect("parsing options failed!") - } else if config.gnu_ext { - "\\w+".to_string() - } else { - "[^ \t\n]+".to_string() - }; - WordFilter { - only_specified: o, - ignore_specified: i, - only_set: oset, - ignore_set: iset, - word_regex: reg - } - } -} - -#[derive(Debug, PartialOrd, PartialEq, Eq, Ord)] -struct WordRef { - word: String, - global_line_nr: usize, - local_line_nr: usize, - position: usize, - position_end: usize, - filename: String, -} - -fn print_version() { - println!("{} {}", NAME, VERSION); -} - -fn print_usage(opts: &Options) { - let brief = "Usage: ptx [OPTION]... [INPUT]... (without -G) or: \ - ptx -G [OPTION]... [INPUT [OUTPUT]] \n Output a permuted index, \ - including context, of the words in the input files. \n\n Mandatory \ - arguments to long options are mandatory for short options too."; - let explaination = "With no FILE, or when FILE is -, read standard input. \ - Default is '-F /'."; - println!("{}\n{}", opts.usage(&brief), explaination); -} - -fn get_config(matches: &Matches) -> Config { - let mut config: Config = Default::default(); - let err_msg = "parsing options failed"; - if matches.opt_present("G") { - config.gnu_ext = false; - config.format = OutFormat::Roff; - config.context_regex = "[^ \t\n]+".to_string(); - } else { - crash!(1, "GNU extensions not implemented yet"); - } - if matches.opt_present("S") { - crash!(1, "-S not implemented yet"); - } - config.auto_ref = matches.opt_present("A"); - config.input_ref = matches.opt_present("r"); - config.right_ref &= matches.opt_present("R"); - config.ignore_case = matches.opt_present("f"); - if matches.opt_present("M") { - config.macro_name = - matches.opt_str("M").expect(err_msg).to_string(); - } - if matches.opt_present("F") { - config.trunc_str = - matches.opt_str("F").expect(err_msg).to_string(); - } - if matches.opt_present("w") { - let width_str = matches.opt_str("w").expect(err_msg); - config.line_width = crash_if_err!( - 1, usize::from_str_radix(&width_str, 10)); - } - if matches.opt_present("g") { - let gap_str = matches.opt_str("g").expect(err_msg); - config.gap_size = crash_if_err!( - 1, usize::from_str_radix(&gap_str, 10)); - } - if matches.opt_present("O") { - config.format = OutFormat::Roff; - } - if matches.opt_present("T") { - config.format = OutFormat::Tex; - } - config -} - -fn read_input(input_files: &Vec, config: &Config) -> - HashMap, usize)> { - let mut file_map : HashMap, usize)> = - HashMap::new(); - let mut files = Vec::new(); - if input_files.is_empty() { - files.push("-"); - } else { - if config.gnu_ext { - for file in input_files { - files.push(&file); - } - } else { - files.push(&input_files[0]); - } - } - let mut lines_so_far: usize = 0; - for filename in files { - let reader: BufReader> = BufReader::new( - if filename == "-" { - Box::new(stdin()) - } else { - let file = crash_if_err!(1, File::open(filename)); - Box::new(file) - }); - let lines: Vec = reader.lines().map(|x| crash_if_err!(1, x)) - .collect(); - let size = lines.len(); - file_map.insert(filename.to_string(), (lines, lines_so_far)); - lines_so_far += size - } - file_map -} - -fn create_word_set(config: &Config, filter: &WordFilter, - file_map: &HashMap, usize)>)-> - BTreeSet { - let reg = Regex::new(&filter.word_regex).unwrap(); - let ref_reg = Regex::new(&config.context_regex).unwrap(); - let mut word_set: BTreeSet = BTreeSet::new(); - for (file, lines) in file_map.iter() { - let mut count: usize = 0; - let offs = lines.1; - for line in (lines.0).iter() { - // if -r, exclude reference from word set - let (ref_beg, ref_end) = match ref_reg.find(line) { - Some(x) => x, - None => (0,0) - }; - // match words with given regex - for (beg, end) in reg.find_iter(line) { - if config.input_ref && ((beg, end) == (ref_beg, ref_end)) { - continue; - } - let mut word = line[beg .. end].to_string(); - if filter.only_specified && - !(filter.only_set.contains(&word)) { - continue; - } - if filter.ignore_specified && - filter.ignore_set.contains(&word) { - continue; - } - if config.ignore_case { - word = word.to_lowercase(); - } - word_set.insert(WordRef{ - word: word, - filename: String::from(file.clone()), - global_line_nr: offs + count, - local_line_nr: count, - position: beg, - position_end: end - }); - } - count += 1; - } - } - word_set -} - -fn get_reference(config: &Config, word_ref: &WordRef, line: &String) -> - String { - if config.auto_ref { - format!("{}:{}", word_ref.filename, word_ref.local_line_nr + 1) - } else if config.input_ref { - let reg = Regex::new(&config.context_regex).unwrap(); - let (beg, end) = match reg.find(line) { - Some(x) => x, - None => (0,0) - }; - format!("{}", &line[beg .. end]) - } else { - String::new() - } -} - -fn assert_str_integrity(s: &Vec, beg: usize, end: usize) { - assert!(beg <= end); - assert!(end <= s.len()); -} - -fn trim_broken_word_left(s: &Vec, beg: usize, end: usize) -> usize { - assert_str_integrity(s, beg, end); - if beg == end || beg == 0 || s[beg].is_whitespace() || - s[beg-1].is_whitespace() { - return beg; - } - let mut b = beg; - while b < end && !s[b].is_whitespace() { - b += 1; - } - b -} - -fn trim_broken_word_right(s: &Vec, beg: usize, end: usize) -> usize { - assert_str_integrity(s, beg, end); - if beg == end || end == s.len() || s[end-1].is_whitespace() || - s[end].is_whitespace() { - return end; - } - let mut e = end; - while beg < e && !s[e-1].is_whitespace() { - e -= 1; - } - e -} - -fn trim_idx(s: &Vec, beg: usize, end: usize) -> (usize, usize) { - assert_str_integrity(s, beg, end); - let mut b = beg; - let mut e = end; - while b < e && s[b].is_whitespace() { - b += 1; - } - while b < e && s[e-1].is_whitespace() { - e -= 1; - } - (b,e) -} - -fn get_output_chunks(all_before: &String, keyword: &String, all_after: &String, - config: &Config) -> (String, String, String, String) { - assert_eq!(all_before.trim().to_string(), *all_before); - assert_eq!(keyword.trim().to_string(), *keyword); - assert_eq!(all_after.trim().to_string(), *all_after); - let mut head = String::new(); - let mut before = String::new(); - let mut after = String::new(); - let mut tail = String::new(); - - let half_line_size = cmp::max((config.line_width/2) as isize - - (2*config.trunc_str.len()) as isize, 0) as usize; - let max_after_size = cmp::max(half_line_size as isize - - keyword.len() as isize - 1, 0) as usize; - let max_before_size = half_line_size; - let all_before_vec: Vec = all_before.chars().collect(); - let all_after_vec: Vec = all_after.chars().collect(); - - // get before - let mut bb_tmp = - cmp::max(all_before.len() as isize - max_before_size as isize, 0) as usize; - bb_tmp = trim_broken_word_left(&all_before_vec, bb_tmp, all_before.len()); - let (before_beg, before_end) = - trim_idx(&all_before_vec, bb_tmp, all_before.len()); - before.push_str(&all_before[before_beg .. before_end]); - assert!(max_before_size >= before.len()); - - // get after - let mut ae_tmp = cmp::min(max_after_size, all_after.len()); - ae_tmp = trim_broken_word_right(&all_after_vec, 0, ae_tmp); - let (after_beg, after_end) = trim_idx(&all_after_vec, 0, ae_tmp); - after.push_str(&all_after[after_beg .. after_end]); - assert!(max_after_size >= after.len()); - - // get tail - let max_tail_size = max_before_size - before.len(); - let (tb, _) = trim_idx(&all_after_vec, after_end, all_after.len()); - let mut te_tmp = cmp::min(tb + max_tail_size, all_after.len()); - te_tmp = trim_broken_word_right(&all_after_vec, tb, te_tmp); - let (tail_beg, tail_end) = trim_idx(&all_after_vec, tb, te_tmp); - tail.push_str(&all_after[tail_beg .. tail_end]); - - // get head - let max_head_size = max_after_size - after.len(); - let (_, he) = trim_idx(&all_before_vec, 0, before_beg); - let mut hb_tmp = - cmp::max(he as isize - max_head_size as isize, 0) as usize; - hb_tmp = trim_broken_word_left(&all_before_vec, hb_tmp, he); - let (head_beg, head_end) = trim_idx(&all_before_vec, hb_tmp, he); - head.push_str(&all_before[head_beg .. head_end]); - - // put right context truncation string if needed - if after_end != all_after.len() && tail_beg == tail_end { - after.push_str(&config.trunc_str); - } else if after_end != all_after.len() && tail_end != all_after.len() { - tail.push_str(&config.trunc_str); - } - - // put left context truncation string if needed - if before_beg != 0 && head_beg == head_end { - before = format!("{}{}", config.trunc_str, before); - } else if before_beg != 0 && head_beg != 0 { - head = format!("{}{}", config.trunc_str, head); - } - - // add space before "after" if needed - if after.len() > 0 { - after = format!(" {}", after); - } - - (tail, before, after, head) -} - -fn tex_mapper(x: char) -> String { - match x { - '\\' => "\\backslash{}".to_string(), - '$' | '%' | '#' | '&' | '_' => format!("\\{}", x), - '}' | '{' => format!("$\\{}$", x), - _ => x.to_string() - } -} - -fn adjust_tex_str(context: &str) -> String { - let ws_reg = Regex::new(r"[\t\n\v\f\r ]").unwrap(); - let mut fix: String = ws_reg.replace_all(context, " ").trim().to_string(); - let mapped_chunks: Vec = fix.chars().map(tex_mapper).collect(); - fix = mapped_chunks.join(""); - fix -} - -fn format_tex_line(config: &Config, word_ref: &WordRef, line: &String, - reference: &String) -> String { - let mut output = String::new(); - output.push_str(&format!("\\{} ", config.macro_name)); - let all_before = if config.input_ref { - let before = &line[0 .. word_ref.position]; - adjust_tex_str(before.trim().trim_left_matches(reference)) - } else { - adjust_tex_str(&line[0 .. word_ref.position]) - }; - let keyword = adjust_tex_str( - &line[word_ref.position .. word_ref.position_end]); - let all_after = adjust_tex_str( - &line[word_ref.position_end .. line.len()]); - let (tail, before, after, head) = - get_output_chunks(&all_before, &keyword, &all_after, &config); - output.push_str(&format!("{5}{0}{6}{5}{1}{6}{5}{2}{6}{5}{3}{6}{5}{4}{6}", - tail, before, keyword, after, head, "{", "}")); - if config.auto_ref || config.input_ref { - output.push_str( - &format!("{}{}{}", "{", adjust_tex_str(&reference), "}")); - } - output -} - -fn adjust_roff_str(context: &str) -> String { - let ws_reg = Regex::new(r"[\t\n\v\f\r]").unwrap(); - ws_reg.replace_all(context, " ").replace("\"", "\"\"").trim().to_string() -} - -fn format_roff_line(config: &Config, word_ref: &WordRef, line: &str, - reference: &str) -> String { - let mut output = String::new(); - output.push_str(&format!(".{}", config.macro_name)); - let all_before = if config.input_ref { - let before = &line[0 .. word_ref.position]; - adjust_roff_str(before.trim().trim_left_matches(reference)) - } else { - adjust_roff_str(&line[0 .. word_ref.position]) - }; - let keyword = adjust_roff_str( - &line[word_ref.position .. word_ref.position_end]); - let all_after = adjust_roff_str( - &line[word_ref.position_end .. line.len()]); - let (tail, before, after, head) = - get_output_chunks(&all_before, &keyword, &all_after, &config); - output.push_str(&format!(" \"{}\" \"{}\" \"{}{}\" \"{}\"", - tail, before, keyword, after, head)); - if config.auto_ref || config.input_ref { - output.push_str(&format!(" \"{}\"", adjust_roff_str(&reference))); - } - output -} - -fn write_traditional_output(config: &Config, - file_map: &HashMap,usize)>, - words: &BTreeSet, output_filename: &String) { - let mut writer: BufWriter> = BufWriter::new( - if output_filename == "-" { - Box::new(stdout()) - } else { - let file = crash_if_err!(1, File::create(output_filename)); - Box::new(file) - }); - for word_ref in words.iter() { - let file_map_value : &(Vec, usize) = - file_map.get(&(word_ref.filename)) - .expect("Missing file in file map"); - let (ref lines, _) = *(file_map_value); - let reference = - get_reference(config, word_ref, &lines[word_ref.local_line_nr]); - let output_line: String = match config.format { - OutFormat::Tex => format_tex_line( - config, word_ref, &lines[word_ref.local_line_nr], &reference), - OutFormat::Roff => format_roff_line( - config, word_ref, &lines[word_ref.local_line_nr], &reference), - OutFormat::Dumb => crash!( - 1, "There is no dumb format with GNU extensions disabled") - }; - crash_if_err!(1, writeln!(writer, "{}", output_line)); - } -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - opts.optflag("A", "auto-reference", - "output automatically generated references"); - opts.optflag("G", "traditional", "behave more like System V 'ptx'"); - opts.optopt("F", "flag-truncation", - "use STRING for flagging line truncations", "STRING"); - opts.optopt("M", "macro-name", "macro name to use instead of 'xx'", - "STRING"); - opts.optflag("O", "format=roff", "generate output as roff directives"); - opts.optflag("R", "right-side-refs", - "put references at right, not counted in -w"); - opts.optopt("S", "sentence-regexp", "for end of lines or end of sentences", - "REGEXP"); - opts.optflag("T", "format=tex", "generate output as TeX directives"); - opts.optopt("W", "word-regexp", "use REGEXP to match each keyword", - "REGEXP"); - opts.optopt("b", "break-file", "word break characters in this FILE", - "FILE"); - opts.optflag("f", "ignore-case", - "fold lower case to upper case for sorting"); - opts.optopt("g", "gap-size", "gap size in columns between output fields", - "NUMBER"); - opts.optopt("i", "ignore-file", "read ignore word list from FILE", "FILE"); - opts.optopt("o", "only-file", "read only word list from this FILE", - "FILE"); - opts.optflag("r", "references", "first field of each line is a reference"); - opts.optopt("w", "width", "output width in columns, reference excluded", - "NUMBER"); - opts.optflag("", "help", "display this help and exit"); - opts.optflag("", "version", "output version information and exit"); - - let matches = return_if_err!(1, opts.parse(&args[1..])); - - if matches.opt_present("help") { - print_usage(&opts); - return 0; - } - if matches.opt_present("version") { - print_version(); - return 0; - } - let config = get_config(&matches); - let word_filter = WordFilter::new(&matches, &config); - let file_map = - read_input(&matches.free, &config); - let word_set = create_word_set(&config, &word_filter, &file_map); - let output_file = if !config.gnu_ext && matches.free.len() == 2 { - matches.free[1].clone() - } else { - "-".to_string() - }; - write_traditional_output(&config, &file_map, &word_set, &output_file); - 0 -} diff --git a/src/pwd/Cargo.toml b/src/pwd/Cargo.toml deleted file mode 100644 index 9b4c9afbd..000000000 --- a/src/pwd/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "pwd" -version = "0.0.1" -authors = [] - -[lib] -name = "pwd" -path = "pwd.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/pwd/pwd.rs b/src/pwd/pwd.rs deleted file mode 100644 index 3205e0c32..000000000 --- a/src/pwd/pwd.rs +++ /dev/null @@ -1,53 +0,0 @@ -#![crate_name = "pwd"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Derek Chiang - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use std::env; -use std::io::Write; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "pwd"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("", "help", "display this help and exit"); - opts.optflag("", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - crash!(1, "Invalid options\n{}", f) - } - }; - - if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: - {0} [OPTION]... - -Print the full filename of the current working directory.", NAME, VERSION); - print!("{}", opts.usage(&msg)); - } else if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - } else { - println!("{}", env::current_dir().unwrap().display()); - } - - 0 -} diff --git a/src/readlink/Cargo.toml b/src/readlink/Cargo.toml deleted file mode 100644 index 42e5db253..000000000 --- a/src/readlink/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "readlink" -version = "0.0.1" -authors = [] - -[lib] -name = "readlink" -path = "readlink.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/readlink/readlink.rs b/src/readlink/readlink.rs deleted file mode 100644 index 58640b97d..000000000 --- a/src/readlink/readlink.rs +++ /dev/null @@ -1,140 +0,0 @@ -#![crate_name = "readlink"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Haitao Li - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; - -use std::fs; -use std::io::Write; -use std::path::PathBuf; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[path = "../common/filesystem.rs"] -mod filesystem; - -use filesystem::{canonicalize, CanonicalizeMode}; - -const NAME: &'static str = "readlink"; -const VERSION: &'static str = "0.0.1"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("f", "canonicalize", - "canonicalize by following every symlink in every component of the \ - given name recursively; all but the last component must exist"); - opts.optflag("e", "canonicalize-existing", - "canonicalize by following every symlink in every component of the \ - given name recursively, all components must exist"); - opts.optflag("m", "canonicalize-missing", - "canonicalize by following every symlink in every component of the \ - given name recursively, without requirements on components existence"); - opts.optflag("n", "no-newline", "do not output the trailing delimiter"); - opts.optflag("q", "quiet", "suppress most error messages"); - opts.optflag("s", "silent", "suppress most error messages"); - opts.optflag("v", "verbose", "report error message"); - opts.optflag("z", "zero", "separate output with NUL rather than newline"); - opts.optflag("", "help", "display this help and exit"); - opts.optflag("", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "Invalid options\n{}", f) - }; - if matches.opt_present("help") { - show_usage(&opts); - return 0; - } - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - let mut no_newline = matches.opt_present("no-newline"); - let use_zero = matches.opt_present("zero"); - let silent = matches.opt_present("silent") || matches.opt_present("quiet"); - let verbose = matches.opt_present("verbose"); - - let mut can_mode = CanonicalizeMode::None; - if matches.opt_present("canonicalize") { - can_mode = CanonicalizeMode::Normal; - } - - if matches.opt_present("canonicalize-existing") { - can_mode = CanonicalizeMode::Existing; - } - - if matches.opt_present("canonicalize-missing") { - can_mode = CanonicalizeMode::Missing; - } - - let files = matches.free; - if files.len() == 0 { - crash!(1, "missing operand\nTry {} --help for more information", NAME); - } - - if no_newline && files.len() > 1 { - if !silent { - eprintln!("{}: ignoring --no-newline with multiple arguments", NAME); - no_newline = false; - } - } - - for f in files.iter() { - let p = PathBuf::from(f); - if can_mode == CanonicalizeMode::None { - match fs::read_link(&p) { - Ok(path) => show(&path, no_newline, use_zero), - Err(err) => { - if verbose { - eprintln!("{}: {}: errno {}", NAME, f, err.raw_os_error().unwrap()); - } - return 1 - } - } - } else { - match canonicalize(&p, can_mode) { - Ok(path) => show(&path, no_newline, use_zero), - Err(err) => { - if verbose { - eprintln!("{}: {}: errno {:?}", NAME, f, err.raw_os_error().unwrap()); - } - return 1 - } - } - } - } - - 0 -} - -fn show(path: &PathBuf, no_newline: bool, use_zero: bool) { - let path = path.as_path().to_str().unwrap(); - if use_zero { - print!("{}\0", path); - } else if no_newline { - print!("{}", path); - } else { - println!("{}", path); - } - pipe_flush!(); -} - -fn show_usage(opts: &getopts::Options) { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage: {0} [OPTION]... [FILE]...", NAME); - print!("Print value of a symbolic link or canonical file name"); - print!("{}", opts.usage("")); -} diff --git a/src/realpath/Cargo.toml b/src/realpath/Cargo.toml deleted file mode 100644 index b481bf0a0..000000000 --- a/src/realpath/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "realpath" -version = "0.0.1" -authors = [] - -[lib] -name = "realpath" -path = "realpath.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/realpath/realpath.rs b/src/realpath/realpath.rs deleted file mode 100644 index 62b1f951b..000000000 --- a/src/realpath/realpath.rs +++ /dev/null @@ -1,142 +0,0 @@ -#![crate_name= "realpath"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) 2014 Vsevolod Velichko - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use std::fs; -use std::io::Write; -use std::path::{Path, PathBuf}; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[path = "../common/filesystem.rs"] -mod filesystem; - -use filesystem::{canonicalize, CanonicalizeMode}; - -static NAME: &'static str = "realpath"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("h", "help", "Show help and exit"); - opts.optflag("V", "version", "Show version and exit"); - opts.optflag("s", "strip", "Only strip '.' and '..' components, but don't resolve symbolic links"); - opts.optflag("z", "zero", "Separate output filenames with \\0 rather than newline"); - opts.optflag("q", "quiet", "Do not print warnings for invalid paths"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - show_error!("{}", f); - show_usage(&opts); - return 1 - } - }; - - if matches.opt_present("V") { version(); return 0 } - if matches.opt_present("h") { show_usage(&opts); return 0 } - - if matches.free.len() == 0 { - show_error!("Missing operand: FILENAME, at least one is required"); - println!("Try `{} --help` for more information.", NAME); - return 1 - } - - let strip = matches.opt_present("s"); - let zero = matches.opt_present("z"); - let quiet = matches.opt_present("q"); - let mut retcode = 0; - for path in matches.free.iter() { - if !resolve_path(path, strip, zero, quiet) { - retcode = 1 - }; - } - retcode -} - -fn resolve_path(path: &str, strip: bool, zero: bool, quiet: bool) -> bool { - let p = Path::new(path).to_path_buf(); - let abs = canonicalize(p, CanonicalizeMode::Normal).unwrap(); - - if strip { - if zero { - print!("{}\0", abs.display()); - } else { - println!("{}", abs.display()) - } - return true - } - - let mut result = PathBuf::new(); - let mut links_left = 256; - - for part in abs.components() { - result.push(part.as_ref()); - loop { - if links_left == 0 { - if !quiet { show_error!("Too many symbolic links: {}", path) }; - return false - } - match fs::metadata(result.as_path()) { - Err(_) => break, - Ok(ref m) if !m.file_type().is_symlink() => break, - Ok(_) => { - links_left -= 1; - match fs::read_link(result.as_path()) { - Ok(x) => { - result.pop(); - result.push(x.as_path()); - }, - _ => { - if !quiet { - show_error!("Invalid path: {}", path) - }; - return false - }, - } - } - } - } - } - - if zero { - print!("{}\0", result.display()); - } else { - println!("{}", result.display()); - } - - true -} - -fn version() { - println!("{} {}", NAME, VERSION) -} - -fn show_usage(opts: &getopts::Options) { - version(); - println!(""); - println!("Usage:"); - println!(" {} [-s|--strip] [-z|--zero] FILENAME...", NAME); - println!(" {} -V|--version", NAME); - println!(" {} -h|--help", NAME); - println!(""); - print!("{}", opts.usage( - "Convert each FILENAME to the absolute path.\n\ - All the symbolic links will be resolved, resulting path will contain no special components like '.' or '..'.\n\ - Each path component must exist or resolution will fail and non-zero exit status returned.\n\ - Each resolved FILENAME will be written to the standard output, one per line.") - ); -} diff --git a/src/relpath/Cargo.toml b/src/relpath/Cargo.toml deleted file mode 100644 index c45a18deb..000000000 --- a/src/relpath/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "relpath" -version = "0.0.1" -authors = [] - -[lib] -name = "relpath" -path = "relpath.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/relpath/relpath.rs b/src/relpath/relpath.rs deleted file mode 100644 index 1f4cebcbc..000000000 --- a/src/relpath/relpath.rs +++ /dev/null @@ -1,107 +0,0 @@ -#![crate_name = "relpath"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) 2014 Vsevolod Velichko - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use std::env; -use std::io::Write; -use std::path::{Path, PathBuf}; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[path = "../common/filesystem.rs"] -mod filesystem; - -use filesystem::{canonicalize, CanonicalizeMode}; - -static NAME: &'static str = "relpath"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("h", "help", "Show help and exit"); - opts.optflag("V", "version", "Show version and exit"); - opts.optopt("d", "", "If any of FROM and TO is not subpath of DIR, output absolute path instead of relative", "DIR"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - show_error!("{}", f); - show_usage(&opts); - return 1 - } - }; - - if matches.opt_present("V") { version(); return 0 } - if matches.opt_present("h") { show_usage(&opts); return 0 } - - if matches.free.len() == 0 { - show_error!("Missing operand: TO"); - println!("Try `{} --help` for more information.", NAME); - return 1 - } - - let to = Path::new(&matches.free[0]); - let from = if matches.free.len() > 1 { - Path::new(&matches.free[1]).to_path_buf() - } else { - env::current_dir().unwrap() - }; - let absto = canonicalize(to, CanonicalizeMode::Normal).unwrap(); - let absfrom = canonicalize(from, CanonicalizeMode::Normal).unwrap(); - - if matches.opt_present("d") { - let base = Path::new(&matches.opt_str("d").unwrap()).to_path_buf(); - let absbase = canonicalize(base, CanonicalizeMode::Normal).unwrap(); - if !absto.as_path().starts_with(absbase.as_path()) || !absfrom.as_path().starts_with(absbase.as_path()) { - println!("{}", absto.display()); - return 0 - } - } - - let mut suffix_pos = 0; - for (f, t) in absfrom.components().zip(absto.components()) { - if f == t { - suffix_pos += 1; - } else { - break; - } - } - - let mut result = PathBuf::new(); - absfrom.components().skip(suffix_pos).map(|_| result.push("..")).last(); - absto.components().skip(suffix_pos).map(|x| result.push(x.as_ref())).last(); - - println!("{}", result.display()); - 0 -} - -fn version() { - println!("{} {}", NAME, VERSION) -} - -fn show_usage(opts: &getopts::Options) { - version(); - println!(""); - println!("Usage:"); - println!(" {} [-d DIR] TO [FROM]", NAME); - println!(" {} -V|--version", NAME); - println!(" {} -h|--help", NAME); - println!(""); - print!("{}", opts.usage( - "Convert TO destination to the relative path from the FROM dir.\n\ - If FROM path is omitted, current working dir will be used.") - ); -} diff --git a/src/rm/Cargo.toml b/src/rm/Cargo.toml deleted file mode 100644 index 953e7caf0..000000000 --- a/src/rm/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "rm" -version = "0.0.1" -authors = [] - -[lib] -name = "rm" -path = "rm.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/rm/rm.rs b/src/rm/rm.rs deleted file mode 100644 index f8a9c8d44..000000000 --- a/src/rm/rm.rs +++ /dev/null @@ -1,292 +0,0 @@ -#![crate_name = "rm"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Arcterus - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use std::collections::VecDeque; -use std::fs; -use std::io::{stdin, stderr, BufRead, Write}; -use std::ops::BitOr; -use std::path::{Path, PathBuf}; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[path = "../common/filesystem.rs"] -mod filesystem; - -use filesystem::UUPathExt; - -#[derive(Eq, PartialEq, Clone, Copy)] -enum InteractiveMode { - InteractiveNone, - InteractiveOnce, - InteractiveAlways -} - -static NAME: &'static str = "rm"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - // TODO: make getopts support -R in addition to -r - let mut opts = getopts::Options::new(); - - opts.optflag("f", "force", "ignore nonexistent files and arguments, never prompt"); - opts.optflag("i", "", "prompt before every removal"); - opts.optflag("I", "", "prompt once before removing more than three files, or when removing recursively. Less intrusive than -i, while still giving some protection against most mistakes"); - opts.optflagopt("", "interactive", "prompt according to WHEN: never, once (-I), or always (-i). Without WHEN, prompts always", "WHEN"); - opts.optflag("", "one-file-system", "when removing a hierarchy recursively, skip any directory that is on a file system different from that of the corresponding command line argument (NOT IMPLEMENTED)"); - opts.optflag("", "no-preserve-root", "do not treat '/' specially"); - opts.optflag("", "preserve-root", "do not remove '/' (default)"); - opts.optflag("r", "recursive", "remove directories and their contents recursively"); - opts.optflag("d", "dir", "remove empty directories"); - opts.optflag("v", "verbose", "explain what is being done"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "{}", f) - }; - if matches.opt_present("help") { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {0} [OPTION]... [FILE]...", NAME); - println!(""); - println!("{}", opts.usage("Remove (unlink) the FILE(s).")); - println!("By default, rm does not remove directories. Use the --recursive (-r)"); - println!("option to remove each listed directory, too, along with all of its contents"); - println!(""); - println!("To remove a file whose name starts with a '-', for example '-foo',"); - println!("use one of these commands:"); - println!("rm -- -foo"); - println!(""); - println!("rm ./-foo"); - println!(""); - println!("Note that if you use rm to remove a file, it might be possible to recover"); - println!("some of its contents, given sufficient expertise and/or time. For greater"); - println!("assurance that the contents are truly unrecoverable, consider using shred."); - } else if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - } else if matches.free.is_empty() { - show_error!("missing an argument"); - show_error!("for help, try '{0} --help'", NAME); - return 1; - } else { - let force = matches.opt_present("force"); - let interactive = - if matches.opt_present("i") { - InteractiveMode::InteractiveAlways - } else if matches.opt_present("I") { - InteractiveMode::InteractiveOnce - } else if matches.opt_present("interactive") { - match &matches.opt_str("interactive").unwrap()[..] { - "none" => InteractiveMode::InteractiveNone, - "once" => InteractiveMode::InteractiveOnce, - "always" => InteractiveMode::InteractiveAlways, - val => { - crash!(1, "Invalid argument to interactive ({})", val) - } - } - } else { - InteractiveMode::InteractiveNone - }; - let one_fs = matches.opt_present("one-file-system"); - let preserve_root = !matches.opt_present("no-preserve-root"); - let recursive = matches.opt_present("recursive"); - let dir = matches.opt_present("dir"); - let verbose = matches.opt_present("verbose"); - if interactive == InteractiveMode::InteractiveOnce && (recursive || matches.free.len() > 3) { - let msg = - if recursive { - "Remove all arguments recursively? " - } else { - "Remove all arguments? " - }; - if !prompt(msg) { - return 0; - } - } - - if remove(matches.free, force, interactive, one_fs, preserve_root, recursive, dir, verbose) { - return 1; - } - } - - 0 -} - -// TODO: implement one-file-system -#[allow(unused_variables)] -fn remove(files: Vec, force: bool, interactive: InteractiveMode, one_fs: bool, preserve_root: bool, recursive: bool, dir: bool, verbose: bool) -> bool { - let mut had_err = false; - - for filename in files.iter() { - let filename = &filename[..]; - let file = Path::new(filename); - if file.uu_exists() { - if file.uu_is_dir() { - if recursive && (filename != "/" || !preserve_root) { - if interactive != InteractiveMode::InteractiveAlways { - match fs::remove_dir_all(file) { - Err(e) => { - had_err = true; - show_error!("could not remove '{}': {}", filename, e); - }, - _ => (), - }; - } else { - let mut dirs: VecDeque = VecDeque::new(); - let mut files: Vec = Vec::new(); - let mut rmdirstack: Vec = Vec::new(); - dirs.push_back(file.to_path_buf()); - - while !dirs.is_empty() { - let dir = dirs.pop_front().unwrap(); - if !prompt(&(format!("rm: descend into directory '{}'? ", dir.display()))[..]) { - continue; - } - - // iterate over items in this directory, adding to either file or - // directory queue - match fs::read_dir(dir.as_path()) { - Ok(rdir) => { - for ent in rdir { - match ent { - Ok(ref f) => match f.file_type() { - Ok(t) => { - if t.is_dir() { - dirs.push_back(f.path()); - } else { - files.push(f.path()); - } - }, - Err(e) => { - had_err = true; - show_error!("reading '{}': {}", f.path().display(), e); - }, - }, - Err(ref e) => { - had_err = true; - show_error!("recursing into '{}': {}", filename, e); - }, - }; - } - }, - Err(e) => { - had_err = true; - show_error!("could not recurse into '{}': {}", dir.display(), e); - continue; - }, - }; - - for f in files.iter() { - had_err = remove_file(f.as_path(), interactive, verbose).bitor(had_err); - } - - files.clear(); - rmdirstack.push(dir); - } - - for d in rmdirstack.iter().rev() { - had_err = remove_dir(d.as_path(), interactive, verbose).bitor(had_err); - } - } - } else if dir && (filename != "/" || !preserve_root) { - had_err = remove_dir(&file, interactive, verbose).bitor(had_err); - } else { - if recursive { - show_error!("could not remove directory '{}'", filename); - had_err = true; - } else { - show_error!("could not remove directory '{}' (did you mean to pass '-r'?)", filename); - had_err = true; - } - } - } else { - had_err = remove_file(&file, interactive, verbose).bitor(had_err); - } - } else if !force { - show_error!("no such file or directory '{}'", filename); - had_err = true; - } - } - - had_err -} - -fn remove_dir(path: &Path, interactive: InteractiveMode, verbose: bool) -> bool { - let response = - if interactive == InteractiveMode::InteractiveAlways { - prompt_file(path, true) - } else { - true - }; - if response { - match fs::remove_dir(path) { - Ok(_) => if verbose { println!("removed '{}'", path.display()); }, - Err(e) => { - show_error!("removing '{}': {}", path.display(), e); - return true; - } - } - } - - false -} - -fn remove_file(path: &Path, interactive: InteractiveMode, verbose: bool) -> bool { - let response = - if interactive == InteractiveMode::InteractiveAlways { - prompt_file(path, false) - } else { - true - }; - if response { - match fs::remove_file(path) { - Ok(_) => if verbose { println!("removed '{}'", path.display()); }, - Err(e) => { - show_error!("removing '{}': {}", path.display(), e); - return true; - } - } - } - - false -} - -fn prompt_file(path: &Path, is_dir: bool) -> bool { - if is_dir { - prompt(&(format!("rm: remove directory '{}'? ", path.display()))[..]) - } else { - prompt(&(format!("rm: remove file '{}'? ", path.display()))[..]) - } -} - -fn prompt(msg: &str) -> bool { - stderr().write_all(msg.as_bytes()).unwrap_or(()); - stderr().flush().unwrap_or(()); - let mut buf = Vec::new(); - let stdin = stdin(); - let mut stdin = stdin.lock(); - match stdin.read_until('\n' as u8, &mut buf) { - Ok(x) if x > 0 => { - match buf[0] { - 0x59 | 0x79 => true, - _ => false, - } - } - _ => false, - } -} diff --git a/src/rmdir/Cargo.toml b/src/rmdir/Cargo.toml deleted file mode 100644 index ec6dc3639..000000000 --- a/src/rmdir/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "rmdir" -version = "0.0.1" -authors = [] - -[lib] -name = "rmdir" -path = "rmdir.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/rmdir/rmdir.rs b/src/rmdir/rmdir.rs deleted file mode 100644 index 56df54c3c..000000000 --- a/src/rmdir/rmdir.rs +++ /dev/null @@ -1,126 +0,0 @@ -#![crate_name = "rmdir"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Arcterus - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use std::fs; -use std::io::Write; -use std::path::Path; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "rmdir"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("", "ignore-fail-on-non-empty", "ignore each failure that is solely because a directory is non-empty"); - opts.optflag("p", "parents", "remove DIRECTORY and its ancestors; e.g., 'rmdir -p a/b/c' is similar to rmdir a/b/c a/b a"); - opts.optflag("v", "verbose", "output a diagnostic for every directory processed"); - opts.optflag("h", "help", "print this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - show_error!("{}", f); - return 1; - } - }; - - if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: - {0} [OPTION]... DIRECTORY... - -Remove the DIRECTORY(ies), if they are empty.", NAME, VERSION); - print!("{}", opts.usage(&msg)); - } else if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - } else if matches.free.is_empty() { - show_error!("missing an argument"); - show_error!("for help, try '{0} --help'", NAME); - return 1; - } else { - let ignore = matches.opt_present("ignore-fail-on-non-empty"); - let parents = matches.opt_present("parents"); - let verbose = matches.opt_present("verbose"); - match remove(matches.free, ignore, parents, verbose) { - Ok(()) => ( /* pass */ ), - Err(e) => return e - } - } - - 0 -} - -fn remove(dirs: Vec, ignore: bool, parents: bool, verbose: bool) -> Result<(), i32> { - let mut r = Ok(()); - - for dir in dirs.iter() { - let path = Path::new(&dir[..]); - r = remove_dir(&path, ignore, verbose).and(r); - if parents { - let mut p = path; - loop { - let new_p = match p.parent() { - Some(p) => p, - None => break, - }; - p = new_p; - - match p.as_os_str().to_str() { - None => break, - Some(s) => match s { - "" | "." | "/" => break, - _ => (), - }, - }; - r = remove_dir(p, ignore, verbose).and(r); - } - } - } - - r -} - -fn remove_dir(path: &Path, ignore: bool, verbose: bool) -> Result<(), i32> { - let mut read_dir = match fs::read_dir(path) { - Ok(m) => m, - Err(e) => { - show_error!("reading directory '{}': {}", path.display(), e); - return Err(1); - } - }; - - let mut r = Ok(()); - - if read_dir.next().is_none() { - match fs::remove_dir(path) { - Err(e) => { - show_error!("removing directory '{}': {}", path.display(), e); - r = Err(1); - }, - Ok(_) if verbose => println!("Removed directory '{}'", path.display()), - _ => (), - } - } else if !ignore { - show_error!("failed to remove '{}': Directory not empty", path.display()); - r = Err(1); - } - - r -} diff --git a/src/seq/Cargo.toml b/src/seq/Cargo.toml deleted file mode 100644 index 4b56530a8..000000000 --- a/src/seq/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "seq" -version = "0.0.1" -authors = [] - -[lib] -name = "seq" -path = "seq.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/seq/seq.rs b/src/seq/seq.rs deleted file mode 100644 index 88fcb2e71..000000000 --- a/src/seq/seq.rs +++ /dev/null @@ -1,260 +0,0 @@ -#![crate_name = "seq"] - -// TODO: Make -w flag work with decimals -// TODO: Support -f flag - -extern crate getopts; -extern crate libc; - -use std::cmp; -use std::io::Write; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "seq"; -static VERSION: &'static str = "1.0.0"; - -#[derive(Clone)] -struct SeqOptions { - separator: String, - terminator: Option, - widths: bool -} - -fn parse_float(mut s: &str) -> Result { - if s.starts_with("+") { - s = &s[1..]; - } - match s.parse() { - Ok(n) => Ok(n), - Err(e) => Err(format!("seq: invalid floating point argument `{}`: {}", s, e)) - } -} - -fn escape_sequences(s: &str) -> String { - s.replace("\\n", "\n") - .replace("\\t", "\t") -} - -fn parse_options(args: Vec, options: &mut SeqOptions) -> Result, i32> { - let mut seq_args = vec!(); - let mut iter = args.into_iter().skip(1); - loop { - match iter.next() { - Some(arg) => match &arg[..] { - "--help" | "-h" => { - print_help(); - return Err(0); - } - "--version" | "-V" => { - print_version(); - return Err(0); - } - "-s" | "--separator" => match iter.next() { - Some(sep) => options.separator = sep, - None => { - show_error!("expected a separator after {}", arg); - return Err(1); - } - }, - "-t" | "--terminator" => match iter.next() { - Some(term) => options.terminator = Some(term), - None => { - show_error!("expected a terminator after '{}'", arg); - return Err(1); - } - }, - "-w" | "--widths" => options.widths = true, - "--" => { - seq_args.extend(iter); - break; - }, - _ => { - if arg.len() > 1 && arg.chars().next().unwrap() == '-' { - let argptr: *const String = &arg; // escape from the borrow checker - let mut chiter = unsafe { &(*argptr)[..] }.chars().skip(1); - let mut ch = ' '; - while match chiter.next() { Some(m) => { ch = m; true } None => false } { - match ch { - 'h' => { - print_help(); - return Err(0); - } - 'V' => { - print_version(); - return Err(0); - } - 's' => match iter.next() { - Some(sep) => { - options.separator = sep; - let next = chiter.next(); - if next.is_some() { - show_error!("unexpected character ('{}')", next.unwrap()); - return Err(1); - } - } - None => { - show_error!("expected a separator after {}", arg); - return Err(1); - } - }, - 't' => match iter.next() { - Some(term) => { - options.terminator = Some(term); - let next = chiter.next(); - if next.is_some() { - show_error!("unexpected character ('{}')", next.unwrap()); - return Err(1); - } - } - None => { - show_error!("expected a terminator after {}", arg); - return Err(1); - } - }, - 'w' => options.widths = true, - _ => { seq_args.push(arg); break } - } - } - } else { - seq_args.push(arg); - } - } - }, - None => break - } - } - Ok(seq_args) -} - -fn print_help() { - let mut opts = getopts::Options::new(); - - opts.optopt("s", "separator", "Separator character (defaults to \\n)", ""); - opts.optopt("t", "terminator", "Terminator character (defaults to separator)", ""); - opts.optflag("w", "widths", "Equalize widths of all numbers by padding with zeros"); - opts.optflag("h", "help", "print this help text and exit"); - opts.optflag("V", "version", "print version and exit"); - - println!("{} {}\n", NAME, VERSION); - println!("Usage:\n {} [-w] [-s string] [-t string] [first [step]] last\n", NAME); - println!("{}", opts.usage("Print sequences of numbers")); -} - -fn print_version() { - println!("{} {}", NAME, VERSION); -} - -pub fn uumain(args: Vec) -> i32 { - let mut options = SeqOptions { - separator: "\n".to_string(), - terminator: None, - widths: false - }; - let free = match parse_options(args, &mut options) { - Ok(m) => m, - Err(f) => return f - }; - if free.len() < 1 || free.len() > 3 { - crash!(1, "too {} operands.\nTry '{} --help' for more information.", - if free.len() < 1 { "few" } else { "many" }, NAME); - } - let mut largest_dec = 0; - let mut padding = 0; - let first = if free.len() > 1 { - let slice = &free[0][..]; - let len = slice.len(); - let dec = slice.find('.').unwrap_or(len); - largest_dec = len - dec; - padding = dec; - match parse_float(slice) { - Ok(n) => n, - Err(s) => { show_error!("{}", s); return 1; } - } - } else { - 1.0 - }; - let step = if free.len() > 2 { - let slice = &free[1][..]; - let len = slice.len(); - let dec = slice.find('.').unwrap_or(len); - largest_dec = cmp::max(largest_dec, len - dec); - padding = cmp::max(padding, dec); - match parse_float(slice) { - Ok(n) => n, - Err(s) => { show_error!("{}", s); return 1; } - } - } else { - 1.0 - }; - let last = { - let slice = &free[free.len() - 1][..]; - padding = cmp::max(padding, slice.find('.').unwrap_or(slice.len())); - match parse_float(slice) { - Ok(n) => n, - Err(s) => { show_error!("{}", s); return 1; } - } - }; - let separator = escape_sequences(&options.separator[..]); - let terminator = match options.terminator { - Some(term) => escape_sequences(&term[..]), - None => separator.clone() - }; - print_seq(first, step, last, largest_dec, separator, terminator, options.widths, padding); - - 0 -} - -#[inline(always)] -fn done_printing(next: f64, step: f64, last: f64) -> bool { - if step >= 0f64 { - next > last - } else { - next < last - } -} - -fn print_seq(first: f64, step: f64, last: f64, largest_dec: usize, separator: String, terminator: String, pad: bool, padding: usize) { - let mut i = 0isize; - let mut value = first + i as f64 * step; - while !done_printing(value, step, last) { - let istr = value.to_string(); - let ilen = istr.len(); - let before_dec = istr.find('.').unwrap_or(ilen); - if pad && before_dec < padding { - for _ in 0..(padding - before_dec) { - if !pipe_print!("0") { - return; - } - } - } - pipe_print!("{}", istr); - let mut idec = ilen - before_dec; - if idec < largest_dec { - if idec == 0 { - if !pipe_print!(".") { - return; - } - idec += 1; - } - for _ in idec..largest_dec { - if !pipe_print!("0") { - return; - } - } - } - i += 1; - value = first + i as f64 * step; - if !done_printing(value, step, last) { - if !pipe_print!("{}", separator) { - return; - } - } - } - if (first >= last && step < 0f64) || (first <= last && step > 0f64) { - pipe_print!("{}", terminator); - } - pipe_flush!(); -} diff --git a/src/shuf/Cargo.toml b/src/shuf/Cargo.toml deleted file mode 100644 index 81101d39f..000000000 --- a/src/shuf/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "shuf" -version = "0.0.1" -authors = [] - -[lib] -name = "shuf" -path = "shuf.rs" - -[dependencies] -getopts = "*" -libc = "*" -rand = "*" diff --git a/src/shuf/deps.mk b/src/shuf/deps.mk deleted file mode 100644 index ea0f8a6b8..000000000 --- a/src/shuf/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += rand diff --git a/src/shuf/shuf.rs b/src/shuf/shuf.rs deleted file mode 100644 index b4ea0ebbe..000000000 --- a/src/shuf/shuf.rs +++ /dev/null @@ -1,269 +0,0 @@ -#![crate_name = "shuf"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Arcterus - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; -extern crate rand; - -use rand::{Rng, ThreadRng}; -use rand::read::ReadRng; -use std::fs::File; -use std::io::{stdin, stdout, BufReader, BufWriter, Read, Write}; -use std::usize::MAX as MAX_USIZE; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -enum Mode { - Default, - Echo, - InputRange((usize, usize)) -} - -static NAME: &'static str = "shuf"; -static VERSION: &'static str = "0.0.1"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - opts.optflag("e", "echo", "treat each ARG as an input line"); - opts.optopt("i", "input-range", "treat each number LO through HI as an input line", "LO-HI"); - opts.optopt("n", "head-count", "output at most COUNT lines", "COUNT"); - opts.optopt("o", "output", "write result to FILE instead of standard output", "FILE"); - opts.optopt("", "random-source", "get random bytes from FILE", "FILE"); - opts.optflag("r", "repeat", "output lines can be repeated"); - opts.optflag("z", "zero-terminated", "end lines with 0 byte, not newline"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - let mut matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - crash!(1, "{}", f) - } - }; - if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: - {0} [OPTION]... [FILE] - {0} -e [OPTION]... [ARG]... - {0} -i LO-HI [OPTION]... - -Write a random permutation of the input lines to standard output. -With no FILE, or when FILE is -, read standard input.", NAME, VERSION); - print!("{}", opts.usage(&msg)); - } else if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - } else { - let echo = matches.opt_present("echo"); - let mode = match matches.opt_str("input-range") { - Some(range) => { - if echo { - show_error!("cannot specify more than one mode"); - return 1; - } - match parse_range(range) { - Ok(m) => Mode::InputRange(m), - Err(msg) => { - crash!(1, "{}", msg); - }, - } - } - None => { - if echo { - Mode::Echo - } else { - if matches.free.len() == 0 { - matches.free.push("-".to_string()); - } else if matches.free.len() > 1 { - show_error!("extra operand '{}'", &matches.free[1][..]); - } - Mode::Default - } - } - }; - let repeat = matches.opt_present("repeat"); - let sep = if matches.opt_present("zero-terminated") { - 0x00 as u8 - } else { - 0x0a as u8 - }; - let count = match matches.opt_str("head-count") { - Some(cnt) => match cnt.parse::() { - Ok(val) => val, - Err(e) => { - show_error!("'{}' is not a valid count: {}", cnt, e); - return 1; - } - }, - None => MAX_USIZE, - }; - let output = matches.opt_str("output"); - let random = matches.opt_str("random-source"); - - match mode { - Mode::Echo => { - // XXX: this doesn't correctly handle non-UTF-8 cmdline args - let mut evec = matches.free.iter().map(|a| a.as_bytes()).collect::>(); - find_seps(&mut evec, sep); - shuf_bytes(&mut evec, repeat, count, sep, output, random); - }, - Mode::InputRange((b, e)) => { - let rvec = (b..e).map(|x| format!("{}", x)).collect::>(); - let mut rvec = rvec.iter().map(|a| a.as_bytes()).collect::>(); - shuf_bytes(&mut rvec, repeat, count, sep, output, random); - }, - Mode::Default => { - let fdata = read_input_file(&matches.free[0][..]); - let mut fdata = vec!(&fdata[..]); - find_seps(&mut fdata, sep); - shuf_bytes(&mut fdata, repeat, count, sep, output, random); - } - } - } - - 0 -} - -fn read_input_file(filename: &str) -> Vec { - let mut file = BufReader::new( - if filename == "-" { - Box::new(stdin()) as Box - } else { - match File::open(filename) { - Ok(f) => Box::new(f) as Box, - Err(e) => crash!(1, "failed to open '{}': {}", filename, e), - } - }); - - let mut data = Vec::new(); - match file.read_to_end(&mut data) { - Err(e) => crash!(1, "failed reading '{}': {}", filename, e), - Ok(_) => (), - }; - - data -} - -fn find_seps(data: &mut Vec<&[u8]>, sep: u8) { - // need to use for loop so we don't borrow the vector as we modify it in place - // basic idea: - // * We don't care about the order of the result. This lets us slice the slices - // without making a new vector. - // * Starting from the end of the vector, we examine each element. - // * If that element contains the separator, we remove it from the vector, - // and then sub-slice it into slices that do not contain the separator. - // * We maintain the invariant throughout that each element in the vector past - // the ith element does not have any separators remaining. - for i in (0..data.len()).rev() { - if data[i].contains(&sep) { - let this = data.swap_remove(i); - let mut p = 0; - let mut i = 1; - loop { - if i == this.len() { - break; - } - - if this[i] == sep { - data.push(&this[p..i]); - p = i + 1; - } - i += 1; - } - if p < this.len() { - data.push(&this[p..i]); - } - } - } -} - -fn shuf_bytes(input: &mut Vec<&[u8]>, repeat: bool, count: usize, sep: u8, output: Option, random: Option) { - let mut output = BufWriter::new( - match output { - None => Box::new(stdout()) as Box, - Some(s) => match File::create(&s[..]) { - Ok(f) => Box::new(f) as Box, - Err(e) => crash!(1, "failed to open '{}' for writing: {}", &s[..], e), - }, - }); - - let mut rng = match random { - Some(r) => WrappedRng::RngFile(rand::read::ReadRng::new(match File::open(&r[..]) { - Ok(f) => f, - Err(e) => crash!(1, "failed to open random source '{}': {}", &r[..], e), - })), - None => WrappedRng::RngDefault(rand::thread_rng()), - }; - - // we're generating a random usize. To keep things fair, we take this number mod ceil(log2(length+1)) - let mut len_mod = 1; - let mut len = input.len(); - while len > 0 { - len >>= 1; - len_mod <<= 1; - } - drop(len); - - let mut count = count; - while count > 0 && input.len() > 0 { - let mut r = input.len(); - while r >= input.len() { - r = rng.next_usize() % len_mod; - } - - // write the randomly chosen value and the separator - output.write_all(input[r]).unwrap_or_else(|e| crash!(1, "write failed: {}", e)); - output.write_all(&[sep]).unwrap_or_else(|e| crash!(1, "write failed: {}", e)); - - // if we do not allow repeats, remove the chosen value from the input vector - if !repeat { - // shrink the mask if we will drop below a power of 2 - if input.len() % 2 == 0 && len_mod > 2 { - len_mod >>= 1; - } - input.swap_remove(r); - } - - count -= 1; - } -} - -fn parse_range(input_range: String) -> Result<(usize, usize), String> { - let split: Vec<&str> = input_range.split('-').collect(); - if split.len() != 2 { - Err("invalid range format".to_string()) - } else { - let begin = match split[0].parse::() { - Ok(m) => m, - Err(e)=> return Err(format!("{} is not a valid number: {}", split[0], e)), - }; - let end = match split[1].parse::() { - Ok(m) => m, - Err(e)=> return Err(format!("{} is not a valid number: {}", split[1], e)), - }; - Ok((begin, end + 1)) - } -} - -enum WrappedRng { - RngFile(rand::read::ReadRng), - RngDefault(rand::ThreadRng), -} - -impl WrappedRng { - fn next_usize(&mut self) -> usize { - match self { - &mut WrappedRng::RngFile(ref mut r) => r.next_u32() as usize, - &mut WrappedRng::RngDefault(ref mut r) => r.next_u32() as usize, - } - } -} diff --git a/src/sleep/Cargo.toml b/src/sleep/Cargo.toml deleted file mode 100644 index 6c29d728d..000000000 --- a/src/sleep/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "sleep" -version = "0.0.1" -authors = [] - -[lib] -name = "sleep" -path = "sleep.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/sleep/sleep.rs b/src/sleep/sleep.rs deleted file mode 100644 index 70abc233e..000000000 --- a/src/sleep/sleep.rs +++ /dev/null @@ -1,81 +0,0 @@ -#![crate_name = "sleep"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Arcterus - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use std::io::Write; -use std::thread::sleep_ms; -use std::u32::MAX as U32_MAX; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[path = "../common/parse_time.rs"] -mod parse_time; - -static NAME: &'static str = "sleep"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - show_error!("{}", f); - return 1; - } - }; - - if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: - {0} NUMBER[SUFFIX] -or - {0} OPTION - -Pause for NUMBER seconds. SUFFIX may be 's' for seconds (the default), -'m' for minutes, 'h' for hours or 'd' for days. Unlike most implementations -that require NUMBER be an integer, here NUMBER may be an arbitrary floating -point number. Given two or more arguments, pause for the amount of time -specified by the sum of their values.", NAME, VERSION); - print!("{}", opts.usage(&msg)); - } else if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - } else if matches.free.is_empty() { - show_error!("missing an argument"); - show_error!("for help, try '{0} --help'", NAME); - return 1; - } else { - sleep(matches.free); - } - - 0 -} - -fn sleep(args: Vec) { - let sleep_time = args.iter().fold(0.0, |result, arg| - match parse_time::from_str(&arg[..]) { - Ok(m) => m + result, - Err(f) => crash!(1, "{}", f), - }); - - let sleep_dur = if sleep_time > (U32_MAX as f64) { - U32_MAX - } else { - (1000.0 * sleep_time) as u32 - }; - sleep_ms(sleep_dur); -} diff --git a/src/sort/Cargo.toml b/src/sort/Cargo.toml deleted file mode 100644 index c88e0b7fb..000000000 --- a/src/sort/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "sort" -version = "0.0.1" -authors = [] - -[lib] -name = "sort" -path = "sort.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/sort/sort.rs b/src/sort/sort.rs deleted file mode 100644 index 03b830593..000000000 --- a/src/sort/sort.rs +++ /dev/null @@ -1,210 +0,0 @@ -#![crate_name = "sort"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Michael Yin - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -#![allow(dead_code)] - -extern crate getopts; -extern crate libc; - -use libc::consts::os::posix88::STDIN_FILENO; -use libc::funcs::posix88::unistd::isatty; -use libc::types::os::arch::c95::c_int; -use std::cmp::Ordering; -use std::fs::File; -use std::io::{BufRead, BufReader, Read, stdin, Write}; -use std::path::Path; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "sort"; -static VERSION: &'static str = "0.0.1"; - -static DECIMAL_PT: char = '.'; -static THOUSANDS_SEP: char = ','; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("n", "numeric-sort", "compare according to string numerical value"); - opts.optflag("H", "human-readable-sort", "compare according to human readable sizes, eg 1M > 100k"); - opts.optflag("r", "reverse", "reverse the output"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "Invalid options\n{}", f) - }; - if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: - {0} [OPTION]... [FILE]... - -Write the sorted concatenation of all FILE(s) to standard output. - -Mandatory arguments for long options are mandatory for short options too. - -With no FILE, or when FILE is -, read standard input.", NAME, VERSION); - print!("{}", opts.usage(&msg)); - return 0; - } - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - let numeric = matches.opt_present("numeric-sort"); - let human_readable = matches.opt_present("human-readable-sort"); - let reverse = matches.opt_present("reverse"); - - let mut files = matches.free; - if files.is_empty() { - /* if no file, default to stdin */ - files.push("-".to_string()); - } - - exec(files, numeric, human_readable, reverse); - - 0 -} - -fn exec(files: Vec, numeric: bool, human_readable: bool, reverse: bool) { - for path in files.iter() { - let (reader, _) = match open(path) { - Some(x) => x, - None => continue, - }; - - let buf_reader = BufReader::new(reader); - let mut lines = Vec::new(); - - for line in buf_reader.lines() { - match line { - Ok(n) => { - lines.push(n); - }, - _ => break - } - } - - if numeric { - lines.sort_by(numeric_compare); - } else if human_readable { - lines.sort_by(human_readable_size_compare); - } else { - lines.sort(); - } - - let iter = lines.iter(); - if reverse { - print_sorted(iter.rev()); - } else { - print_sorted(iter) - }; - } -} - -/// Parse the beginning string into an f64, returning -inf instead of NaN on errors. -fn permissive_f64_parse(a: &String) -> f64{ - //Maybe should be split on non-digit, but then 10e100 won't parse properly. - //On the flip side, this will give NEG_INFINITY for "1,234", which might be OK - //because there's no way to handle both CSV and thousands separators without a new flag. - //GNU sort treats "1,234" as "1" in numeric, so maybe it's fine. - let sa: &str = a.split_whitespace().next().unwrap(); - match sa.parse::() { - Ok(a) => a, - Err(_) => std::f64::NEG_INFINITY - } -} - -/// Compares two floating point numbers, with errors being assumned to be -inf. -/// Stops coercing at the first whitespace char, so 1e2 will parse as 100 but -/// 1,000 will parse as -inf. -fn numeric_compare(a: &String, b: &String) -> Ordering { - let fa = permissive_f64_parse(a); - let fb = permissive_f64_parse(b); - //f64::cmp isn't implemented because NaN messes with it - //but we sidestep that with permissive_f64_parse so just fake it - if fa > fb { - return Ordering::Greater; - } - else if fa < fb { - return Ordering::Less; - } - else { - return Ordering::Equal; - } -} - -fn human_readable_convert(a: &String) -> f64 { - let int_iter = a.chars(); - let suffix_iter = a.chars(); - let int_str: String = int_iter.take_while(|c| c.is_numeric()).collect(); - let suffix = suffix_iter.skip_while(|c| c.is_numeric()).next(); - let int_part = match int_str.parse::() { - Ok(i) => i, - Err(_) => -1f64 - } as f64; - let suffix: f64 = match suffix.unwrap_or('\0') { - 'K' => 1000f64, - 'M' => 1E6, - 'G' => 1E9, - 'T' => 1E12, - 'P' => 1E15, - _ => 1f64 - }; - return int_part * suffix; -} - -/// Compare two strings as if they are human readable sizes. -/// AKA 1M > 100k -fn human_readable_size_compare(a: &String, b: &String) -> Ordering { - let fa = human_readable_convert(a); - let fb = human_readable_convert(b); - if fa > fb { - return Ordering::Greater; - } - else if fa < fb { - return Ordering::Less; - } - else { - return Ordering::Equal; - } - -} - -#[inline(always)] -fn print_sorted>(iter: T) where S: std::fmt::Display { - for line in iter { - println!("{}", line); - } -} - -// from cat.rs -fn open<'a>(path: &str) -> Option<(Box, bool)> { - if path == "-" { - let stdin = stdin(); - let interactive = unsafe { isatty(STDIN_FILENO) } != 0 as c_int; - return Some((Box::new(stdin) as Box, interactive)); - } - - match File::open(Path::new(path)) { - Ok(f) => Some((Box::new(f) as Box, false)), - Err(e) => { - show_error!("sort: {0}: {1}", path, e.to_string()); - None - }, - } -} diff --git a/src/split/Cargo.toml b/src/split/Cargo.toml deleted file mode 100644 index 3c0d0de3b..000000000 --- a/src/split/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "split" -version = "0.0.1" -authors = [] - -[lib] -name = "split" -path = "split.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/split/README.md b/src/split/README.md deleted file mode 100644 index 582c9970a..000000000 --- a/src/split/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Rudimentary "split" Implementation - -## Missing Features - -### Flags -* `--verbose` - created file printing is implemented, don't know if there is anything else - -## Possible Optimizations -* Use slice (`[u8]`) directly as the `control.current_line`. diff --git a/src/split/deps.mk b/src/split/deps.mk deleted file mode 100644 index 62b0140cc..000000000 --- a/src/split/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += aho-corasick memchr rand regex regex-syntax diff --git a/src/split/split.rs b/src/split/split.rs deleted file mode 100644 index 08d57cd18..000000000 --- a/src/split/split.rs +++ /dev/null @@ -1,317 +0,0 @@ -#![crate_name = "split"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Akira Hayakawa - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use std::char; -use std::fs::{File, OpenOptions}; -use std::io::{BufRead, BufReader, BufWriter, Read, stdin, stdout, Write}; -use std::path::Path; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "split"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optopt("a", "suffix-length", "use suffixes of length N (default 2)", "N"); - opts.optopt("b", "bytes", "put SIZE bytes per output file", "SIZE"); - opts.optopt("C", "line-bytes", "put at most SIZE bytes of lines per output file", "SIZE"); - opts.optflag("d", "numeric-suffixes", "use numeric suffixes instead of alphabetic"); - opts.optopt("l", "lines", "put NUMBER lines per output file", "NUMBER"); - opts.optflag("", "verbose", "print a diagnostic just before each output file is opened"); - opts.optflag("h", "help", "display help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "{}", f) - }; - - if matches.opt_present("h") { - let msg = format!("{0} {1} - -Usage: - {0} [OPTION]... [INPUT [PREFIX]] - -Output fixed-size pieces of INPUT to PREFIXaa, PREFIX ab, ...; default -size is 1000, and default PREFIX is 'x'. With no INPUT, or when INPUT is --, read standard input.", NAME, VERSION); - - println!("{}\nSIZE may have a multiplier suffix: b for 512, k for 1K, m for 1 Meg.", opts.usage(&msg)); - return 0; - } - - if matches.opt_present("V") { - println!("{} {}", NAME, VERSION); - return 0; - } - - let mut settings = Settings { - prefix: "".to_string(), - numeric_suffix: false, - suffix_length: 0, - input: "".to_string(), - strategy: "".to_string(), - strategy_param: "".to_string(), - verbose: false, - }; - - settings.numeric_suffix = if matches.opt_present("d") { true } else { false }; - - settings.suffix_length = match matches.opt_str("a") { - Some(n) => match n.parse() { - Ok(m) => m, - Err(e) => crash!(1, "cannot parse num: {}", e) - }, - None => 2 - }; - - settings.verbose = if matches.opt_present("verbose") { true } else { false }; - - settings.strategy = "l".to_string(); - settings.strategy_param = "1000".to_string(); - let strategies = vec!["b", "C", "l"]; - for e in strategies.iter() { - match matches.opt_str(*e) { - Some(a) => { - if settings.strategy == "l" { - settings.strategy = e.to_string(); - settings.strategy_param = a; - } else { - crash!(1, "{}: cannot split in more than one way", NAME) - } - }, - None => {} - } - } - - let mut v = matches.free.iter(); - let (input, prefix) = match (v.next(), v.next()) { - (Some(a), None) => (a.to_string(), "x".to_string()), - (Some(a), Some(b)) => (a.to_string(), b.to_string()), - (None, _) => ("-".to_string(), "x".to_string()), - }; - settings.input = input; - settings.prefix = prefix; - - split(&settings) -} - -struct Settings { - prefix: String, - numeric_suffix: bool, - suffix_length: usize, - input: String, - strategy: String, - strategy_param: String, - verbose: bool, -} - -struct SplitControl { - current_line: String, // Don't touch - request_new_file: bool, // Splitter implementation requests new file -} - -trait Splitter { - // Consume the current_line and return the consumed string - fn consume(&mut self, &mut SplitControl) -> String; -} - -struct LineSplitter { - saved_lines_to_write: usize, - lines_to_write: usize, -} - -impl LineSplitter { - fn new(settings: &Settings) -> Box { - let n = match settings.strategy_param.parse() { - Ok(a) => a, - Err(e) => crash!(1, "invalid number of lines: {}", e) - }; - Box::new(LineSplitter { - saved_lines_to_write: n, - lines_to_write: n, - }) as Box - } - -} - -impl Splitter for LineSplitter { - fn consume(&mut self, control: &mut SplitControl) -> String { - self.lines_to_write -= 1; - if self.lines_to_write == 0 { - self.lines_to_write = self.saved_lines_to_write; - control.request_new_file = true; - } - control.current_line.clone() - } -} - -struct ByteSplitter { - saved_bytes_to_write: usize, - bytes_to_write: usize, - break_on_line_end: bool, - require_whole_line: bool, -} - -impl ByteSplitter { - fn new(settings: &Settings) -> Box { - let mut strategy_param : Vec = settings.strategy_param.chars().collect(); - let suffix = strategy_param.pop().unwrap(); - let multiplier = match suffix { - '0'...'9' => 1usize, - 'b' => 512usize, - 'k' => 1024usize, - 'm' => 1024usize * 1024usize, - _ => crash!(1, "invalid number of bytes") - }; - let n = if suffix.is_alphabetic() { - match strategy_param.iter().map(|c| *c).collect::().parse::() { - Ok(a) => a, - Err(e) => crash!(1, "invalid number of bytes: {}", e) - } - } else { - match settings.strategy_param.parse::() { - Ok(a) => a, - Err(e) => crash!(1, "invalid number of bytes: {}", e) - } - }; - Box::new(ByteSplitter { - saved_bytes_to_write: n * multiplier, - bytes_to_write: n * multiplier, - break_on_line_end: if settings.strategy == "b" { false } else { true }, - require_whole_line: false, - }) as Box - } -} - -impl Splitter for ByteSplitter { - fn consume(&mut self, control: &mut SplitControl) -> String { - let line = control.current_line.clone(); - let n = std::cmp::min(line.chars().count(), self.bytes_to_write); - if self.require_whole_line && n < line.chars().count() { - self.bytes_to_write = self.saved_bytes_to_write; - control.request_new_file = true; - self.require_whole_line = false; - return line[0..0].to_string(); - } - self.bytes_to_write -= n; - if n == 0 { - self.bytes_to_write = self.saved_bytes_to_write; - control.request_new_file = true; - } - if self.break_on_line_end && n == line.chars().count() { - self.require_whole_line = self.break_on_line_end; - } - line[..n].to_string() - } -} - -// (1, 3) -> "aab" -fn str_prefix(i: usize, width: usize) -> String { - let mut c = "".to_string(); - let mut n = i; - let mut w = width; - while w > 0 { - w -= 1; - let div = 26usize.pow(w as u32); - let r = n / div; - n -= r * div; - c.push(char::from_u32((r as u32) + 97).unwrap()); - } - c -} - -// (1, 3) -> "001" -fn num_prefix(i: usize, width: usize) -> String { - let mut c = "".to_string(); - let mut n = i; - let mut w = width; - while w > 0 { - w -= 1; - let div = 10usize.pow(w as u32); - let r = n / div; - n -= r * div; - c.push(char::from_digit(r as u32, 10).unwrap()); - } - c -} - -fn split(settings: &Settings) -> i32 { - let mut reader = BufReader::new( - if settings.input == "-" { - Box::new(stdin()) as Box - } else { - let r = match File::open(Path::new(&settings.input)) { - Ok(a) => a, - Err(_) => crash!(1, "cannot open '{}' for reading: No such file or directory", settings.input) - }; - Box::new(r) as Box - } - ); - - let mut splitter: Box = - match settings.strategy.as_ref() { - "l" => LineSplitter::new(settings), - "b" | "C" => ByteSplitter::new(settings), - a @ _ => crash!(1, "strategy {} not supported", a) - }; - - let mut control = SplitControl { - current_line: "".to_string(), // Request new line - request_new_file: true, // Request new file - }; - - let mut writer = BufWriter::new(Box::new(stdout()) as Box); - let mut fileno = 0; - loop { - if control.current_line.chars().count() == 0 { - match reader.read_line(&mut control.current_line) { - Ok(0) | Err(_) => break, - _ => {} - } - } - - if control.request_new_file { - let mut filename = settings.prefix.clone(); - filename.push_str(if settings.numeric_suffix { - num_prefix(fileno, settings.suffix_length) - } else { - str_prefix(fileno, settings.suffix_length) - }.as_ref()); - - if fileno != 0 { - crash_if_err!(1, writer.flush()); - } - fileno += 1; - writer = BufWriter::new(Box::new(OpenOptions::new().write(true).create(true).open(Path::new(&filename)).unwrap()) as Box); - control.request_new_file = false; - if settings.verbose { - println!("creating file '{}'", filename); - } - } - - let consumed = splitter.consume(&mut control); - crash_if_err!(1, writer.write_all(consumed.as_bytes())); - - let advance = consumed.chars().count(); - let clone = control.current_line.clone(); - let sl = clone; - control.current_line = sl[advance..sl.chars().count()].to_string(); - } - 0 -} diff --git a/src/stdbuf/libstdbuf.c b/src/stdbuf/libstdbuf.c deleted file mode 100644 index b7ee1370f..000000000 --- a/src/stdbuf/libstdbuf.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "libstdbuf.h" - -void __attribute ((constructor)) -stdbuf_init (void) -{ - stdbuf(); -} diff --git a/src/stdbuf/libstdbuf.h b/src/stdbuf/libstdbuf.h deleted file mode 100644 index d8ae3c70a..000000000 --- a/src/stdbuf/libstdbuf.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef UUTILS_LIBSTDBUF_H -#define UUTILS_LIBSTDBUF_H - -void stdbuf(void); - -#endif diff --git a/src/stdbuf/libstdbuf.rs b/src/stdbuf/libstdbuf.rs deleted file mode 100644 index 6ff620a99..000000000 --- a/src/stdbuf/libstdbuf.rs +++ /dev/null @@ -1,57 +0,0 @@ -#![crate_name = "libstdbuf"] -#![crate_type = "staticlib"] - -extern crate libc; - -use libc::{c_int, size_t, c_char, FILE, _IOFBF, _IONBF, _IOLBF, setvbuf}; -use std::env; -use std::io::Write; -use std::ptr; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -extern { - static stdin: *mut FILE; - static stdout: *mut FILE; - static stderr: *mut FILE; -} - -static NAME: &'static str = "libstdbuf"; - -fn set_buffer(stream: *mut FILE, value: &str) { - let (mode, size): (c_int, size_t) = match value { - "0" => (_IONBF, 0 as size_t), - "L" => (_IOLBF, 0 as size_t), - input => { - let buff_size: usize = match input.parse() { - Ok(num) => num, - Err(e) => crash!(1, "incorrect size of buffer!: {}", e) - }; - (_IOFBF, buff_size as size_t) - } - }; - let res: c_int; - unsafe { - let buffer: *mut c_char = ptr::null_mut(); - assert!(buffer.is_null()); - res = libc::setvbuf(stream, buffer, mode, size); - } - if res != 0 { - crash!(res, "error while calling setvbuf!"); - } -} - -#[no_mangle] -pub extern fn stdbuf() { - if let Ok(val) = env::var("_STDBUF_E") { - set_buffer(stderr, &val); - } - if let Ok(val) = env::var("_STDBUF_I") { - set_buffer(stdin, &val); - } - if let Ok(val) = env::var("_STDBUF_O") { - set_buffer(stdout, &val); - } -} diff --git a/src/stdbuf/stdbuf.rs b/src/stdbuf/stdbuf.rs deleted file mode 100644 index ecb30fa76..000000000 --- a/src/stdbuf/stdbuf.rs +++ /dev/null @@ -1,272 +0,0 @@ -#![crate_name = "stdbuf"] - -/* -* This file is part of the uutils coreutils package. -* -* (c) Dorota Kapturkiewicz -* -* For the full copyright and license information, please view the LICENSE -* file that was distributed with this source code. -*/ - -extern crate getopts; -extern crate libc; - -use getopts::{Matches, Options}; -use std::env; -use std::io::{self, Write}; -use std::os::unix::process::ExitStatusExt; -use std::path::PathBuf; -use std::process::Command; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[path = "../common/filesystem.rs"] -mod filesystem; - -use filesystem::{canonicalize, CanonicalizeMode, UUPathExt}; - -static NAME: &'static str = "stdbuf"; -static VERSION: &'static str = "1.0.0"; -static LIBSTDBUF: &'static str = "libstdbuf"; - -enum BufferType { - Default, - Line, - Size(u64) -} - -struct ProgramOptions { - stdin: BufferType, - stdout: BufferType, - stderr: BufferType, -} - -enum ErrMsg { - Retry, - Fatal -} - -enum OkMsg { - Buffering, - Help, - Version -} - -#[cfg(target_os = "linux")] -fn preload_strings() -> (&'static str, &'static str) { - ("LD_PRELOAD", ".so") -} - -#[cfg(target_os = "macos")] -fn preload_strings() -> (&'static str, &'static str) { - ("DYLD_LIBRARY_PATH", ".dylib") -} - -#[cfg(not(any(target_os = "linux", target_os = "macos")))] -fn preload_strings() -> (&'static str, &'static str) { - crash!(1, "Command not supported for this operating system!") -} - -fn print_version() { - println!("{} {}", NAME, VERSION); -} - -fn print_usage(opts: &Options) { - let brief = - "Run COMMAND, with modified buffering operations for its standard streams\n \ - Mandatory arguments to long options are mandatory for short options too."; - let explanation = - "If MODE is 'L' the corresponding stream will be line buffered.\n \ - This option is invalid with standard input.\n\n \ - If MODE is '0' the corresponding stream will be unbuffered.\n\n \ - Otherwise MODE is a number which may be followed by one of the following:\n\n \ - KB 1000, K 1024, MB 1000*1000, M 1024*1024, and so on for G, T, P, E, Z, Y.\n \ - In this case the corresponding stream will be fully buffered with the buffer size set to MODE bytes.\n\n \ - NOTE: If COMMAND adjusts the buffering of its standard streams ('tee' does for e.g.) then that will override \ - corresponding settings changed by 'stdbuf'.\n \ - Also some filters (like 'dd' and 'cat' etc.) don't use streams for I/O, \ - and are thus unaffected by 'stdbuf' settings.\n"; - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage: stdbuf OPTION... COMMAND"); - println!(""); - println!("{}\n{}", opts.usage(brief), explanation); -} - -fn parse_size(size: &str) -> Option { - let ext = size.trim_left_matches(|c: char| c.is_digit(10)); - let num = size.trim_right_matches(|c: char| c.is_alphabetic()); - let mut recovered = num.to_string(); - recovered.push_str(ext); - if recovered != size { - return None; - } - let buf_size: u64 = match num.parse().ok() { - Some(m) => m, - None => return None, - }; - let (power, base): (u32, u64) = match ext { - "" => (0, 0), - "KB" => (1, 1024), - "K" => (1, 1000), - "MB" => (2, 1024), - "M" => (2, 1000), - "GB" => (3, 1024), - "G" => (3, 1000), - "TB" => (4, 1024), - "T" => (4, 1000), - "PB" => (5, 1024), - "P" => (5, 1000), - "EB" => (6, 1024), - "E" => (6, 1000), - "ZB" => (7, 1024), - "Z" => (7, 1000), - "YB" => (8, 1024), - "Y" => (8, 1000), - _ => return None, - }; - Some(buf_size * base.pow(power)) -} - -fn check_option(matches: &Matches, name: &str, modified: &mut bool) -> Option { - match matches.opt_str(name) { - Some(value) => { - *modified = true; - match &value[..] { - "L" => { - if name == "input" { - show_info!("line buffering stdin is meaningless"); - None - } else { - Some(BufferType::Line) - } - }, - x => { - let size = match parse_size(x) { - Some(m) => m, - None => { show_error!("Invalid mode {}", x); return None } - }; - Some(BufferType::Size(size)) - }, - } - }, - None => Some(BufferType::Default), - } -} - -fn parse_options(args: &[String], options: &mut ProgramOptions, optgrps: &Options) -> Result { - let matches = match optgrps.parse(args) { - Ok(m) => m, - Err(_) => return Err(ErrMsg::Retry) - }; - if matches.opt_present("help") { - return Ok(OkMsg::Help); - } - if matches.opt_present("version") { - return Ok(OkMsg::Version); - } - let mut modified = false; - options.stdin = try!(check_option(&matches, "input", &mut modified).ok_or(ErrMsg::Fatal)); - options.stdout = try!(check_option(&matches, "output", &mut modified).ok_or(ErrMsg::Fatal)); - options.stderr = try!(check_option(&matches, "error", &mut modified).ok_or(ErrMsg::Fatal)); - - if matches.free.len() != 1 { - return Err(ErrMsg::Retry); - } - if !modified { - show_error!("you must specify a buffering mode option"); - return Err(ErrMsg::Fatal); - } - Ok(OkMsg::Buffering) -} - -fn set_command_env(command: &mut Command, buffer_name: &str, buffer_type: BufferType) { - match buffer_type { - BufferType::Size(m) => { command.env(buffer_name, m.to_string()); }, - BufferType::Line => { command.env(buffer_name, "L"); }, - BufferType::Default => {}, - } -} - -fn exe_path() -> io::Result { - let exe_path = try!(env::current_exe()); - let absolute_path = try!(canonicalize(exe_path, CanonicalizeMode::Normal)); - Ok(match absolute_path.parent() { - Some(p) => p.to_path_buf(), - None => absolute_path.clone() - }) -} - -fn get_preload_env() -> (String, String) { - let (preload, extension) = preload_strings(); - let mut libstdbuf = LIBSTDBUF.to_string(); - libstdbuf.push_str(extension); - // First search for library in directory of executable. - let mut path = exe_path().unwrap_or_else(|_| crash!(1, "Impossible to fetch the path of this executable.")); - path.push(libstdbuf.clone()); - if path.uu_exists() { - match path.as_os_str().to_str() { - Some(s) => { return (preload.to_string(), s.to_string()); }, - None => crash!(1, "Error while converting path.") - }; - } - // We assume library is in LD_LIBRARY_PATH/ DYLD_LIBRARY_PATH. - (preload.to_string(), libstdbuf) -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - - opts.optopt("i", "input", "adjust standard input stream buffering", "MODE"); - opts.optopt("o", "output", "adjust standard output stream buffering", "MODE"); - opts.optopt("e", "error", "adjust standard error stream buffering", "MODE"); - opts.optflag("", "help", "display this help and exit"); - opts.optflag("", "version", "output version information and exit"); - - let mut options = ProgramOptions {stdin: BufferType::Default, stdout: BufferType::Default, stderr: BufferType::Default}; - let mut command_idx: i32 = -1; - for i in 1 .. args.len()+1 { - match parse_options(&args[1 .. i], &mut options, &opts) { - Ok(OkMsg::Buffering) => { - command_idx = (i as i32) - 1; - break; - }, - Ok(OkMsg::Help) => { - print_usage(&opts); - return 0; - }, - Ok(OkMsg::Version) => { - print_version(); - return 0; - }, - Err(ErrMsg::Fatal) => break, - Err(ErrMsg::Retry) => continue, - } - }; - if command_idx == -1 { - crash!(125, "Invalid options\nTry 'stdbuf --help' for more information."); - } - let ref command_name = args[command_idx as usize]; - let mut command = Command::new(command_name); - let (preload_env, libstdbuf) = get_preload_env(); - command.args(&args[(command_idx as usize) + 1 ..]).env(preload_env, libstdbuf); - set_command_env(&mut command, "_STDBUF_I", options.stdin); - set_command_env(&mut command, "_STDBUF_O", options.stdout); - set_command_env(&mut command, "_STDBUF_E", options.stderr); - let mut process = match command.spawn() { - Ok(p) => p, - Err(e) => crash!(1, "failed to execute process: {}", e) - }; - match process.wait() { - Ok(status) => { - match status.code() { - Some(i) => return i, - None => crash!(1, "process killed by signal {}", status.signal().unwrap()), - } - }, - Err(e) => crash!(1, "{}", e) - }; -} diff --git a/src/sum/Cargo.toml b/src/sum/Cargo.toml deleted file mode 100644 index 7655fd221..000000000 --- a/src/sum/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "sum" -version = "0.0.1" -authors = [] - -[lib] -name = "sum" -path = "sum.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/sum/sum.rs b/src/sum/sum.rs deleted file mode 100644 index 75f25adee..000000000 --- a/src/sum/sum.rs +++ /dev/null @@ -1,140 +0,0 @@ -#![crate_name = "sum"] - -/* -* This file is part of the uutils coreutils package. -* -* (c) T. Jameson Little -* -* For the full copyright and license information, please view the LICENSE file -* that was distributed with this source code. -*/ - -extern crate getopts; -extern crate libc; - -use std::fs::File; -use std::io::{Read, Result, stdin, Write}; -use std::path::Path; - -#[path="../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "sum"; -static VERSION: &'static str = "1.0.0"; - -fn bsd_sum(mut reader: Box) -> (usize, u16) { - let mut buf = [0; 1024]; - let mut blocks_read = 0; - let mut checksum: u16 = 0; - loop { - match reader.read(&mut buf) { - Ok(n) if n != 0 => { - blocks_read += 1; - for &byte in buf[..n].iter() { - checksum = (checksum >> 1) + ((checksum & 1) << 15); - checksum += byte as u16; - } - }, - _ => break, - } - } - - (blocks_read, checksum) -} - -fn sysv_sum(mut reader: Box) -> (usize, u16) { - let mut buf = [0; 512]; - let mut blocks_read = 0; - let mut ret = 0; - - loop { - match reader.read(&mut buf) { - Ok(n) if n != 0 => { - blocks_read += 1; - for &byte in buf[..n].iter() { - ret += byte as u32; - } - }, - _ => break, - } - } - - ret = (ret & 0xffff) + (ret >> 16); - ret = (ret & 0xffff) + (ret >> 16); - - (blocks_read, ret as u16) -} - -fn open(name: &str) -> Result> { - match name { - "-" => Ok(Box::new(stdin()) as Box), - _ => { - let f = try!(File::open(&Path::new(name))); - Ok(Box::new(f) as Box) - } - } -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("r", "", "use the BSD compatible algorithm (default)"); - opts.optflag("s", "sysv", "use System V compatible algorithm"); - opts.optflag("h", "help", "show this help message"); - opts.optflag("v", "version", "print the version and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "Invalid options\n{}", f) - }; - - if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: - {0} [OPTION]... [FILE]... - -Checksum and count the blocks in a file.", NAME, VERSION); - println!("{}\nWith no FILE, or when FILE is -, read standard input.", opts.usage(&msg)); - return 0; - } - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - let sysv = matches.opt_present("sysv"); - - let files = if matches.free.is_empty() { - vec!["-".to_string()] - } else { - matches.free - }; - - let print_names = if sysv { - files.len() > 1 || files[0] != "-" - } else { - files.len() > 1 - }; - - for file in files.iter() { - let reader = match open(file) { - Ok(f) => f, - _ => crash!(1, "unable to open file") - }; - let (blocks, sum) = if sysv { - sysv_sum(reader) - } else { - bsd_sum(reader) - }; - - if print_names { - println!("{} {} {}", sum, blocks, file); - } else { - println!("{} {}", sum, blocks); - } - } - - 0 -} diff --git a/src/sync/Cargo.toml b/src/sync/Cargo.toml deleted file mode 100644 index 2c17e5550..000000000 --- a/src/sync/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "sync" -version = "0.0.1" -authors = [] - -[lib] -name = "sync" -path = "sync.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/sync/deps.mk b/src/sync/deps.mk deleted file mode 100644 index bd85e154d..000000000 --- a/src/sync/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += winapi kernel32 diff --git a/src/sync/sync.rs b/src/sync/sync.rs deleted file mode 100644 index 3f3834774..000000000 --- a/src/sync/sync.rs +++ /dev/null @@ -1,146 +0,0 @@ -#![crate_name = "sync"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Alexander Fomin - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - - /* Last synced with: sync (GNU coreutils) 8.13 */ - -extern crate getopts; -extern crate libc; - -#[path = "../common/util.rs"] #[macro_use] mod util; -#[cfg(windows)] #[path = "../common/wide.rs"] mod wide; - -static NAME: &'static str = "sync"; -static VERSION: &'static str = "1.0.0"; - -#[cfg(unix)] -mod platform { - use super::libc; - - extern { - fn sync() -> libc::c_void; - } - - pub unsafe fn do_sync() -> isize { - sync(); - 0 - } -} - -#[cfg(windows)] -mod platform { - extern crate winapi; - extern crate kernel32; - use std::{mem}; - use std::fs::OpenOptions; - use std::io::{Write}; - use std::os::windows::prelude::*; - use wide::{FromWide, ToWide}; - - unsafe fn flush_volume(name: &str) { - let name_wide = name.to_wide_null(); - if kernel32::GetDriveTypeW(name_wide.as_ptr()) == winapi::DRIVE_FIXED { - let sliced_name = &name[..name.len() - 1]; // eliminate trailing backslash - match OpenOptions::new().write(true).open(sliced_name) { - Ok(file) => if kernel32::FlushFileBuffers(file.as_raw_handle()) == 0 { - crash!(kernel32::GetLastError() as i32, "failed to flush file buffer"); - }, - Err(e) => crash!(e.raw_os_error().unwrap_or(1), "failed to create volume handle") - } - } - } - - unsafe fn find_first_volume() -> (String, winapi::HANDLE) { - let mut name: [winapi::WCHAR; winapi::MAX_PATH] = mem::uninitialized(); - let handle = kernel32::FindFirstVolumeW(name.as_mut_ptr(), name.len() as winapi::DWORD); - if handle == winapi::INVALID_HANDLE_VALUE { - crash!(kernel32::GetLastError() as i32, "failed to find first volume"); - } - (String::from_wide_null(&name), handle) - } - - unsafe fn find_all_volumes() -> Vec { - let (first_volume, next_volume_handle) = find_first_volume(); - let mut volumes = vec![first_volume]; - loop { - let mut name: [winapi::WCHAR; winapi::MAX_PATH] = mem::uninitialized(); - if kernel32::FindNextVolumeW( - next_volume_handle, name.as_mut_ptr(), name.len() as winapi::DWORD - ) == 0 { - match kernel32::GetLastError() { - winapi::ERROR_NO_MORE_FILES => { - kernel32::FindVolumeClose(next_volume_handle); - return volumes - }, - err => crash!(err as i32, "failed to find next volume"), - } - } else { - volumes.push(String::from_wide_null(&name)); - } - } - } - - pub unsafe fn do_sync() -> isize { - let volumes = find_all_volumes(); - for vol in &volumes { - flush_volume(vol); - } - 0 - } -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => { m } - _ => { help(&opts); return 1 } - }; - - if matches.opt_present("h") { - help(&opts); - return 0 - } - - if matches.opt_present("V") { - version(); - return 0 - } - - sync(); - 0 -} - -fn version() { - println!("{} (uutils) {}", NAME, VERSION); - println!("The MIT License"); - println!(""); - println!("Author -- Alexander Fomin."); -} - -fn help(opts: &getopts::Options) { - let msg = format!("{0} {1} - -Usage: - {0} [OPTION] - -Force changed blocks to disk, update the super block.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); -} - -fn sync() -> isize { - unsafe { - platform::do_sync() - } -} diff --git a/src/tac/Cargo.toml b/src/tac/Cargo.toml deleted file mode 100644 index 2a4dd498f..000000000 --- a/src/tac/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "tac" -version = "0.0.1" -authors = [] - -[lib] -name = "tac" -path = "tac.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/tac/tac.rs b/src/tac/tac.rs deleted file mode 100644 index 995d5c2d7..000000000 --- a/src/tac/tac.rs +++ /dev/null @@ -1,149 +0,0 @@ -#![crate_name = "tac"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Arcterus - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use std::fs::File; -use std::io::{BufReader, Read, stdin, stdout, Stdout, Write}; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "tac"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("b", "before", "attach the separator before instead of after"); - opts.optflag("r", "regex", "interpret the sequence as a regular expression (NOT IMPLEMENTED)"); - opts.optopt("s", "separator", "use STRING as the separator instead of newline", "STRING"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "{}", f) - }; - if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: - {0} [OPTION]... [FILE]... - -Write each file to standard output, last line first.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - } else if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - } else { - let before = matches.opt_present("b"); - let regex = matches.opt_present("r"); - let separator = match matches.opt_str("s") { - Some(m) => { - if m.len() == 0 { - crash!(1, "separator cannot be empty") - } else { - m - } - } - None => "\n".to_string() - }; - let files = if matches.free.is_empty() { - vec!("-".to_string()) - } else { - matches.free - }; - tac(files, before, regex, &separator[..]); - } - - 0 -} - -fn tac(filenames: Vec, before: bool, _: bool, separator: &str) { - let mut out = stdout(); - let sbytes = separator.as_bytes(); - let slen = sbytes.len(); - - for filename in filenames.iter() { - let mut file = BufReader::new( - if filename == "-" { - Box::new(stdin()) as Box - } else { - match File::open(filename) { - Ok(f) => Box::new(f) as Box, - Err(e) => { - show_warning!("failed to open '{}' for reading: {}", filename, e); - continue; - }, - } - }); - - let mut data = Vec::new(); - match file.read_to_end(&mut data) { - Err(e) => { - show_warning!("failed to read '{}': {}", filename, e); - continue; - }, - Ok(_) => (), - }; - - // find offsets in string of all separators - let mut offsets = Vec::new(); - let mut i = 0; - loop { - if i + slen > data.len() { - break; - } - - if &data[i..i+slen] == sbytes { - offsets.push(i); - i += slen; - } else { - i += 1; - } - } - drop(i); - - // if there isn't a separator at the end of the file, fake it - if offsets.len() == 0 || *offsets.last().unwrap() < data.len() - slen { - offsets.push(data.len()); - } - - let mut prev = *offsets.last().unwrap(); - let mut start = true; - for off in offsets.iter().rev().skip(1) { - // correctly handle case of no final separator in file - if start && prev == data.len() { - show_line(&mut out, &[], &data[*off+slen..prev], before); - start = false; - } else { - show_line(&mut out, sbytes, &data[*off+slen..prev], before); - } - prev = *off; - } - show_line(&mut out, sbytes, &data[0..prev], before); - } -} - -fn show_line(out: &mut Stdout, sep: &[u8], dat: &[u8], before: bool) { - if before { - out.write_all(sep).unwrap_or_else(|e| crash!(1, "failed to write to stdout: {}", e)); - } - - out.write_all(dat).unwrap_or_else(|e| crash!(1, "failed to write to stdout: {}", e)); - - if !before { - out.write_all(sep).unwrap_or_else(|e| crash!(1, "failed to write to stdout: {}", e)); - } -} diff --git a/src/tail/Cargo.toml b/src/tail/Cargo.toml deleted file mode 100644 index beac774b1..000000000 --- a/src/tail/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "tail" -version = "0.0.1" -authors = [] - -[lib] -name = "tail" -path = "tail.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/tail/README.md b/src/tail/README.md deleted file mode 100644 index a31dd0702..000000000 --- a/src/tail/README.md +++ /dev/null @@ -1,16 +0,0 @@ -Rudimentary tail implementation. - -##Missing features: - -### Flags with features -* `--max-unchanged-stats` : with `--follow=name`, reopen a FILE which has not changed size after N (default 5) iterations to see if it has been unlinked or renamed (this is the usual case of rotated log files). With inotify, this option is rarely useful. -* `--pid` : with `-f`, terminate after process ID, PID dies -* `--quiet` : never output headers giving file names -* `--retry` : keep trying to open a file even when it is or becomes inaccessible; useful when follow‐ing by name, i.e., with `--follow=name` -* `--verbose` : always output headers giving file names - -### Others -The current implementation does not handle `-` as an alias for stdin. - -##Possible optimizations: -* Don't read the whole file if not using `-f` and input is regular file. Read in chunks from the end going backwards, reading each individual chunk forward. diff --git a/src/tail/tail.rs b/src/tail/tail.rs deleted file mode 100644 index 8b64760a5..000000000 --- a/src/tail/tail.rs +++ /dev/null @@ -1,300 +0,0 @@ -#![crate_name = "tail"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Morten Olsen Lysgaard - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - */ - -extern crate getopts; - -use std::collections::VecDeque; -use std::fs::File; -use std::io::{BufRead, BufReader, Read, stdin, stdout, Write}; -use std::path::Path; -use std::str::from_utf8; -use std::thread::sleep_ms; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "tail"; -static VERSION: &'static str = "0.0.1"; - -pub fn uumain(args: Vec) -> i32 { - let mut beginning = false; - let mut lines = true; - let mut byte_count = 0usize; - let mut line_count = 10usize; - let mut sleep_msec = 1000u32; - - // handle obsolete -number syntax - let options = match obsolete(&args[1..]) { - (args, Some(n)) => { line_count = n; args }, - (args, None) => args - }; - - let args = options; - - let mut opts = getopts::Options::new(); - - opts.optopt("c", "bytes", "Number of bytes to print", "k"); - opts.optopt("n", "lines", "Number of lines to print", "k"); - opts.optflag("f", "follow", "Print the file as it grows"); - opts.optopt("s", "sleep-interval", "Number or seconds to sleep between polling the file when running with -f", "n"); - opts.optflag("h", "help", "help"); - opts.optflag("V", "version", "version"); - - let given_options = match opts.parse(&args) { - Ok (m) => { m } - Err(_) => { - println!("{}", opts.usage("")); - return 1; - } - }; - - if given_options.opt_present("h") { - println!("{}", opts.usage("")); - return 0; - } - if given_options.opt_present("V") { version(); return 0 } - - let follow = given_options.opt_present("f"); - if follow { - match given_options.opt_str("s") { - Some(n) => { - let parsed: Option = n.parse().ok(); - match parsed { - Some(m) => { sleep_msec = m * 1000 } - None => {} - } - } - None => {} - }; - } - - match given_options.opt_str("n") { - Some(n) => { - let mut slice: &str = n.as_ref(); - if slice.chars().next().unwrap_or('_') == '+' { - beginning = true; - slice = &slice[1..]; - } - line_count = match parse_size(slice) { - Some(m) => m, - None => { - show_error!("invalid number of lines ({})", slice); - return 1; - } - }; - } - None => match given_options.opt_str("c") { - Some(n) => { - let mut slice: &str = n.as_ref(); - if slice.chars().next().unwrap_or('_') == '+' { - beginning = true; - slice = &slice[1..]; - } - byte_count = match parse_size(slice) { - Some(m) => m, - None => { - show_error!("invalid number of bytes ({})", slice); - return 1; - } - }; - lines = false; - } - None => { } - } - }; - - let files = given_options.free; - - if files.is_empty() { - let mut buffer = BufReader::new(stdin()); - tail(&mut buffer, line_count, byte_count, beginning, lines, follow, sleep_msec); - } else { - let mut multiple = false; - let mut firstime = true; - - if files.len() > 1 { - multiple = true; - } - - - for file in files.iter() { - if multiple { - if !firstime { println!(""); } - println!("==> {} <==", file); - } - firstime = false; - - let path = Path::new(file); - let reader = File::open(&path).unwrap(); - let mut buffer = BufReader::new(reader); - tail(&mut buffer, line_count, byte_count, beginning, lines, follow, sleep_msec); - } - } - - 0 -} - -fn parse_size(mut size_slice: &str) -> Option { - let mut base = - if size_slice.chars().last().unwrap_or('_') == 'B' { - size_slice = &size_slice[..size_slice.len() - 1]; - 1000usize - } else { - 1024usize - }; - let exponent = - if size_slice.len() > 0 { - let mut has_suffix = true; - let exp = match size_slice.chars().last().unwrap_or('_') { - 'K' => 1usize, - 'M' => 2usize, - 'G' => 3usize, - 'T' => 4usize, - 'P' => 5usize, - 'E' => 6usize, - 'Z' => 7usize, - 'Y' => 8usize, - 'b' => { - base = 512usize; - 1usize - } - _ => { - has_suffix = false; - 0usize - } - }; - if has_suffix { - size_slice = &size_slice[..size_slice.len() - 1]; - } - exp - } else { - 0usize - }; - - let mut multiplier = 1usize; - for _ in 0usize .. exponent { - multiplier *= base; - } - if base == 1000usize && exponent == 0usize { - // sole B is not a valid suffix - None - } else { - let value: Option = size_slice.parse().ok(); - match value { - Some(v) => Some(multiplier * v), - _ => None - } - } -} - -// It searches for an option in the form of -123123 -// -// In case is found, the options vector will get rid of that object so that -// getopts works correctly. -fn obsolete(options: &[String]) -> (Vec, Option) { - let mut options: Vec = options.to_vec(); - let mut a = 0; - let b = options.len(); - - while a < b { - let current = options[a].clone(); - let current = current.as_bytes(); - - if current.len() > 1 && current[0] == '-' as u8 { - let len = current.len(); - for pos in 1 .. len { - // Ensure that the argument is only made out of digits - if !(current[pos] as char).is_numeric() { break; } - - // If this is the last number - if pos == len - 1 { - options.remove(a); - let number: Option = from_utf8(¤t[1..len]).unwrap().parse().ok(); - return (options, Some(number.unwrap())); - } - } - } - - a += 1; - }; - - (options, None) -} - -macro_rules! tail_impl ( - ($kind:ty, $kindfn:ident, $kindprint:ident, $reader:ident, $count:ident, $beginning:ident) => ({ - // read through each line and store them in a ringbuffer that always contains - // count lines/chars. When reaching the end of file, output the data in the - // ringbuf. - let mut ringbuf: VecDeque<$kind> = VecDeque::new(); - let data = $reader.$kindfn().skip( - if $beginning { - let temp = $count; - $count = ::std::usize::MAX; - temp - 1 - } else { - 0 - } - ); - for io_datum in data { - match io_datum { - Ok(datum) => { - if $count <= ringbuf.len() { - ringbuf.pop_front(); - } - ringbuf.push_back(datum); - } - Err(err) => panic!(err) - } - } - let mut stdout = stdout(); - for datum in ringbuf.iter() { - $kindprint(&mut stdout, datum); - } - }) -); - -fn tail(reader: &mut BufReader, mut line_count: usize, mut byte_count: usize, beginning: bool, lines: bool, follow: bool, sleep_msec: u32) { - if lines { - tail_impl!(String, lines, print_string, reader, line_count, beginning); - } else { - tail_impl!(u8, bytes, print_byte, reader, byte_count, beginning); - } - - // if we follow the file, sleep a bit and print the rest if the file has grown. - while follow { - sleep_ms(sleep_msec); - for io_line in reader.lines() { - match io_line { - Ok(line) => print!("{}", line), - Err(err) => panic!(err) - } - } - } -} - -#[inline] -fn print_byte(stdout: &mut T, ch: &u8) { - if let Err(err) = stdout.write(&[*ch]) { - crash!(1, "{}", err); - } -} - -#[inline] -fn print_string(_: &mut T, s: &String) { - print!("{}", s); -} - -fn version () { - println!("{} {}", NAME, VERSION); -} diff --git a/src/tee/Cargo.toml b/src/tee/Cargo.toml deleted file mode 100644 index d91409f52..000000000 --- a/src/tee/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "tee" -version = "0.0.1" -authors = [] - -[lib] -name = "tee" -path = "tee.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/tee/tee.rs b/src/tee/tee.rs deleted file mode 100644 index 52279708f..000000000 --- a/src/tee/tee.rs +++ /dev/null @@ -1,174 +0,0 @@ -#![crate_name = "tee"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Aleksander Bielawski - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; - -use std::fs::OpenOptions; -use std::io::{copy, Error, ErrorKind, Read, Result, sink, stdin, stdout, Write}; -use std::path::{Path, PathBuf}; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "tee"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - match options(&args).and_then(exec) { - Ok(_) => 0, - Err(_) => 1 - } -} - -#[allow(dead_code)] -struct Options { - program: String, - append: bool, - ignore_interrupts: bool, - print_and_exit: Option, - files: Vec -} - -fn options(args: &Vec) -> Result { - let mut opts = getopts::Options::new(); - - opts.optflag("a", "append", "append to the given FILEs, do not overwrite"); - opts.optflag("i", "ignore-interrupts", "ignore interrupt signals"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - opts.parse(&args[1..]).map_err(|e| Error::new(ErrorKind::Other, format!("{}", e))).and_then(|m| { - let version = format!("{} {}", NAME, VERSION); - let arguments = "[OPTION]... [FILE]..."; - let brief = "Copy standard input to each FILE, and also to standard output."; - let comment = "If a FILE is -, copy again to standard output."; - let help = format!("{}\n\nUsage:\n {} {}\n\n{}\n{}", - version, NAME, arguments, opts.usage(brief), - comment); - let mut names: Vec = m.free.clone().into_iter().collect(); - names.push("-".to_string()); - let to_print = if m.opt_present("help") { Some(help) } - else if m.opt_present("version") { Some(version) } - else { None }; - Ok(Options { - program: NAME.to_string(), - append: m.opt_present("append"), - ignore_interrupts: m.opt_present("ignore-interrupts"), - print_and_exit: to_print, - files: names - }) - }).map_err(|message| warn(format!("{}", message).as_ref())) -} - -fn exec(options: Options) -> Result<()> { - match options.print_and_exit { - Some(text) => Ok(println!("{}", text)), - None => tee(options) - } -} - -fn tee(options: Options) -> Result<()> { - let writers: Vec> = options.files.clone().into_iter().map(|file| open(file, options.append)).collect(); - let output = &mut MultiWriter { writers: writers }; - let input = &mut NamedReader { inner: Box::new(stdin()) as Box }; - if copy(input, output).is_err() || output.flush().is_err() { - Err(Error::new(ErrorKind::Other, "")) - } else { - Ok(()) - } -} - -fn open(name: String, append: bool) -> Box { - let is_stdout = name == "-"; - let path = PathBuf::from(name); - let inner: Box = if is_stdout { - Box::new(stdout()) - } else { - let mut options = OpenOptions::new(); - let mode = if append { options.append(true) } else { options.truncate(true) }; - match mode.write(true).create(true).open(path.as_path()) { - Ok(file) => Box::new(file), - Err(_) => Box::new(sink()) - } - }; - Box::new(NamedWriter { inner: inner, path: path }) as Box -} - -struct MultiWriter { - writers: Vec> -} - -impl Write for MultiWriter { - fn write(&mut self, buf: &[u8]) -> Result { - for writer in self.writers.iter_mut() { - try!(writer.write_all(buf)); - } - Ok(buf.len()) - } - - fn flush(&mut self) -> Result<()> { - for writer in self.writers.iter_mut() { - try!(writer.flush()); - } - Ok(()) - } -} - -struct NamedWriter { - inner: Box, - path: PathBuf -} - -impl Write for NamedWriter { - fn write(&mut self, buf: &[u8]) -> Result { - match self.inner.write(buf) { - Err(f) => { - self.inner = Box::new(sink()) as Box; - warn(format!("{}: {}", self.path.display(), f.to_string()).as_ref()); - Err(f) - } - okay => okay - } - } - - fn flush(&mut self) -> Result<()> { - match self.inner.flush() { - Err(f) => { - self.inner = Box::new(sink()) as Box; - warn(format!("{}: {}", self.path.display(), f.to_string()).as_ref()); - Err(f) - } - okay => okay - } - } -} - -struct NamedReader { - inner: Box -} - -impl Read for NamedReader { - fn read(&mut self, buf: &mut [u8]) -> Result { - match self.inner.read(buf) { - Err(f) => { - warn(format!("{}: {}", Path::new("stdin").display(), f.to_string()).as_ref()); - Err(f) - } - okay => okay - } - } -} - -fn warn(message: &str) -> Error { - eprintln!("{}: {}", NAME, message); - Error::new(ErrorKind::Other, format!("{}: {}", NAME, message)) -} diff --git a/src/test/Cargo.toml b/src/test/Cargo.toml deleted file mode 100644 index 38acc688a..000000000 --- a/src/test/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "test" -version = "0.0.1" -authors = [] - -[lib] -name = "test" -path = "test.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/test/test.rs b/src/test/test.rs deleted file mode 100644 index 7cd446e69..000000000 --- a/src/test/test.rs +++ /dev/null @@ -1,408 +0,0 @@ -#![crate_name = "test"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) mahkoh (ju.orth [at] gmail [dot] com) - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate libc; - -use std::collections::HashMap; -use std::ffi::{CString, OsString}; -use std::env::{args_os}; -use std::str::{from_utf8}; - -static NAME: &'static str = "test"; - -// TODO: decide how to handle non-UTF8 input for all the utils -// Definitely don't use [u8], try keeping it as OsStr or OsString instead -pub fn uumain(_: Vec) -> i32 { - let args = args_os().collect::>(); - // This is completely disregarding valid windows paths that aren't valid unicode - let args = args.iter().map(|a| a.to_str().unwrap().as_bytes()).collect::>(); - if args.len() == 0 { - return 2; - } - let args = - if !args[0].ends_with(NAME.as_bytes()) { - &args[1..] - } else { - &args[..] - }; - let args = match args[0] { - b"[" => match args[args.len() - 1] { - b"]" => &args[1..args.len() - 1], - _ => return 2, - }, - _ => &args[1..args.len()], - }; - let mut error = false; - let retval = 1 - parse_expr(args, &mut error) as i32; - if error { - 2 - } else { - retval - } -} - -fn one(args: &[&[u8]]) -> bool { - args[0].len() > 0 -} - -fn two(args: &[&[u8]], error: &mut bool) -> bool { - match args[0] { - b"!" => !one(&args[1..]), - b"-b" => path(args[1], PathCondition::BlockSpecial), - b"-c" => path(args[1], PathCondition::CharacterSpecial), - b"-d" => path(args[1], PathCondition::Directory), - b"-e" => path(args[1], PathCondition::Exists), - b"-f" => path(args[1], PathCondition::Regular), - b"-g" => path(args[1], PathCondition::GroupIDFlag), - b"-h" => path(args[1], PathCondition::SymLink), - b"-L" => path(args[1], PathCondition::SymLink), - b"-n" => one(&args[1..]), - b"-p" => path(args[1], PathCondition::FIFO), - b"-r" => path(args[1], PathCondition::Readable), - b"-S" => path(args[1], PathCondition::Socket), - b"-s" => path(args[1], PathCondition::NonEmpty), - b"-t" => isatty(args[1]), - b"-u" => path(args[1], PathCondition::UserIDFlag), - b"-w" => path(args[1], PathCondition::Writable), - b"-x" => path(args[1], PathCondition::Executable), - b"-z" => !one(&args[1..]), - _ => { - *error = true; - false - } - } -} - -fn three(args: &[&[u8]], error: &mut bool) -> bool { - match args[1] { - b"=" => args[0] == args[2], - b"==" => args[0] == args[2], - b"!=" => args[0] != args[2], - b"-eq" => integers(args[0], args[2], IntegerCondition::Equal), - b"-ne" => integers(args[0], args[2], IntegerCondition::Unequal), - b"-gt" => integers(args[0], args[2], IntegerCondition::Greater), - b"-ge" => integers(args[0], args[2], IntegerCondition::GreaterEqual), - b"-lt" => integers(args[0], args[2], IntegerCondition::Less), - b"-le" => integers(args[0], args[2], IntegerCondition::LessEqual), - _ => match args[0] { - b"!" => !two(&args[1..], error), - _ => { - *error = true; - false - } - } - } -} - -fn four(args: &[&[u8]], error: &mut bool) -> bool { - match args[0] { - b"!" => { - !three(&args[1..], error) - } - _ => { - *error = true; - false - } - } -} - -enum IntegerCondition { - Equal, - Unequal, - Greater, - GreaterEqual, - Less, - LessEqual, -} - -fn integers(a: &[u8], b: &[u8], cond: IntegerCondition) -> bool { - let (a, b): (&str, &str) = match (from_utf8(a), from_utf8(b)) { - (Ok(a), Ok(b)) => (a, b), - _ => return false, - }; - let (a, b): (i64, i64) = match (a.parse(), b.parse()) { - (Ok(a), Ok(b)) => (a, b), - _ => return false, - }; - match cond { - IntegerCondition::Equal => a == b, - IntegerCondition::Unequal => a != b, - IntegerCondition::Greater => a > b, - IntegerCondition::GreaterEqual => a >= b, - IntegerCondition::Less => a < b, - IntegerCondition::LessEqual => a <= b, - } -} - -fn isatty(fd: &[u8]) -> bool { - use libc::{isatty}; - from_utf8(fd).ok().and_then(|s| s.parse().ok()) - .map(|i| unsafe { isatty(i) == 1 }).unwrap_or(false) -} - -fn dispatch(args: &mut &[&[u8]], error: &mut bool) -> bool { - let (val, idx) = match args.len() { - 0 => { - *error = true; - (false, 0) - } - 1 => (one(*args), 1), - 2 => dispatch_two(args, error), - 3 => dispatch_three(args, error), - _ => dispatch_four(args, error) - }; - *args = &(*args)[idx..]; - val -} - -fn dispatch_two(args: &mut &[&[u8]], error: &mut bool) -> (bool, usize) { - let val = two(*args, error); - if *error { - *error = false; - (one(*args), 1) - } else { - (val, 2) - } -} - -fn dispatch_three(args: &mut &[&[u8]], error: &mut bool) -> (bool, usize) { - let val = three(*args, error); - if *error { - *error = false; - dispatch_two(args, error) - } else { - (val, 3) - } -} - -fn dispatch_four(args: &mut &[&[u8]], error: &mut bool) -> (bool, usize) { - let val = four(*args, error); - if *error { - *error = false; - dispatch_three(args, error) - } else { - (val, 4) - } -} - -#[derive(Clone, Copy)] -enum Precedence { - Unknown = 0, - Paren, // FIXME: this is useless (parentheses have not been implemented) - Or, - And, - BUnOp, - BinOp, - UnOp -} - -fn parse_expr(mut args: &[&[u8]], error: &mut bool) -> bool { - if args.len() == 0 { - false - } else { - let hashmap = setup_hashmap(); - let lhs = dispatch(&mut args, error); - - if args.len() > 0 { - parse_expr_helper(&hashmap, &mut args, lhs, Precedence::Unknown, error) - } else { - lhs - } - } -} - -fn parse_expr_helper<'a>(hashmap: &HashMap<&'a [u8], Precedence>, - args: &mut &[&'a [u8]], - mut lhs: bool, - min_prec: Precedence, - error: &mut bool) -> bool { - let mut prec = *hashmap.get(&args[0]).unwrap_or_else(|| { - *error = true; - &min_prec - }); - while !*error && args.len() > 0 && prec as usize >= min_prec as usize { - let op = args[0]; - *args = &(*args)[1..]; - let mut rhs = dispatch(args, error); - while args.len() > 0 { - let subprec = *hashmap.get(&args[0]).unwrap_or_else(|| { - *error = true; - &min_prec - }); - if subprec as usize <= prec as usize || *error { - break; - } - rhs = parse_expr_helper(hashmap, args, rhs, subprec, error); - } - lhs = match prec { - Precedence::UnOp | Precedence::BUnOp => { - *error = true; - false - } - Precedence::And => lhs && rhs, - Precedence::Or => lhs || rhs, - Precedence::BinOp => three(&[if lhs { b" " } else { b"" }, op, if rhs { b" " } else { b"" }], error), - Precedence::Paren => unimplemented!(), // TODO: implement parentheses - _ => unreachable!() - }; - if args.len() > 0 { - prec = *hashmap.get(&args[0]).unwrap_or_else(|| { - *error = true; - &min_prec - }); - } - } - lhs -} - -#[inline] -fn setup_hashmap<'a>() -> HashMap<&'a [u8], Precedence> { - let mut hashmap = HashMap::<&'a [u8], Precedence>::new(); - - hashmap.insert(b"-b", Precedence::UnOp); - hashmap.insert(b"-c", Precedence::UnOp); - hashmap.insert(b"-d", Precedence::UnOp); - hashmap.insert(b"-e", Precedence::UnOp); - hashmap.insert(b"-f", Precedence::UnOp); - hashmap.insert(b"-g", Precedence::UnOp); - hashmap.insert(b"-h", Precedence::UnOp); - hashmap.insert(b"-L", Precedence::UnOp); - hashmap.insert(b"-n", Precedence::UnOp); - hashmap.insert(b"-p", Precedence::UnOp); - hashmap.insert(b"-r", Precedence::UnOp); - hashmap.insert(b"-S", Precedence::UnOp); - hashmap.insert(b"-s", Precedence::UnOp); - hashmap.insert(b"-t", Precedence::UnOp); - hashmap.insert(b"-u", Precedence::UnOp); - hashmap.insert(b"-w", Precedence::UnOp); - hashmap.insert(b"-x", Precedence::UnOp); - hashmap.insert(b"-z", Precedence::UnOp); - - hashmap.insert(b"=", Precedence::BinOp); - hashmap.insert(b"!=", Precedence::BinOp); - hashmap.insert(b"-eq", Precedence::BinOp); - hashmap.insert(b"-ne", Precedence::BinOp); - hashmap.insert(b"-gt", Precedence::BinOp); - hashmap.insert(b"-ge", Precedence::BinOp); - hashmap.insert(b"-lt", Precedence::BinOp); - hashmap.insert(b"-le", Precedence::BinOp); - - hashmap.insert(b"!", Precedence::BUnOp); - - hashmap.insert(b"-a", Precedence::And); - hashmap.insert(b"-o", Precedence::Or); - - hashmap.insert(b"(", Precedence::Paren); - hashmap.insert(b")", Precedence::Paren); - - hashmap -} - -#[derive(Eq, PartialEq)] -enum PathCondition { - BlockSpecial, - CharacterSpecial, - Directory, - Exists, - Regular, - GroupIDFlag, - SymLink, - FIFO, - Readable, - Socket, - NonEmpty, - UserIDFlag, - Writable, - Executable, -} - -#[cfg(not(windows))] -fn path(path: &[u8], cond: PathCondition) -> bool { - use libc::{stat, lstat, S_IFMT, S_IFLNK, S_IFBLK, S_IFCHR, S_IFDIR, S_IFREG}; - use libc::{S_IFIFO, mode_t}; - static S_ISUID: mode_t = 0o4000; - static S_ISGID: mode_t = 0o2000; - static S_IFSOCK: mode_t = 0o140000; - - enum Permission { - Read = 0o4, - Write = 0o2, - Execute = 0o1, - } - let perm = |stat: stat, p: Permission| { - use libc::{getgid, getuid}; - let (uid, gid) = unsafe { (getuid(), getgid()) }; - if uid == stat.st_uid { - stat.st_mode & ((p as mode_t) << 6) != 0 - } else if gid == stat.st_gid { - stat.st_mode & ((p as mode_t) << 3) != 0 - } else { - stat.st_mode & ((p as mode_t) << 0) != 0 - } - }; - - let path = CString::new(path).unwrap(); - let mut stat = unsafe { std::mem::zeroed() }; - if cond == PathCondition::SymLink { - if unsafe { lstat(path.as_ptr(), &mut stat) } == 0 { - if stat.st_mode & S_IFMT == S_IFLNK { - return true; - } - } - return false; - } - if unsafe { libc::stat(path.as_ptr(), &mut stat) } != 0 { - return false; - } - let file_type = stat.st_mode & S_IFMT; - match cond { - PathCondition::BlockSpecial => file_type == S_IFBLK, - PathCondition::CharacterSpecial => file_type == S_IFCHR, - PathCondition::Directory => file_type == S_IFDIR, - PathCondition::Exists => true, - PathCondition::Regular => file_type == S_IFREG, - PathCondition::GroupIDFlag => stat.st_mode & S_ISGID != 0, - PathCondition::SymLink => true, - PathCondition::FIFO => file_type == S_IFIFO, - PathCondition::Readable => perm(stat, Permission::Read), - PathCondition::Socket => file_type == S_IFSOCK, - PathCondition::NonEmpty => stat.st_size > 0, - PathCondition::UserIDFlag => stat.st_mode & S_ISUID != 0, - PathCondition::Writable => perm(stat, Permission::Write), - PathCondition::Executable => perm(stat, Permission::Execute), - } -} - -#[cfg(windows)] -fn path(path: &[u8], cond: PathCondition) -> bool { - use std::fs::metadata; - let path = from_utf8(path).unwrap(); - let stat = match metadata(path) { - Ok(s) => s, - _ => return false, - }; - match cond { - PathCondition::BlockSpecial => false, - PathCondition::CharacterSpecial => false, - PathCondition::Directory => stat.is_dir(), - PathCondition::Exists => true, - PathCondition::Regular => stat.is_file(), - PathCondition::GroupIDFlag => false, - PathCondition::SymLink => false, - PathCondition::FIFO => false, - PathCondition::Readable => false, // TODO - PathCondition::Socket => false, - PathCondition::NonEmpty => stat.len() > 0, - PathCondition::UserIDFlag => false, - PathCondition::Writable => false, // TODO - PathCondition::Executable => false, // TODO - } -} diff --git a/src/timeout/Cargo.toml b/src/timeout/Cargo.toml deleted file mode 100644 index 18d3c3ba2..000000000 --- a/src/timeout/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "timeout" -version = "0.0.1" -authors = [] - -[lib] -name = "timeout" -path = "timeout.rs" - -[dependencies] -getopts = "*" -libc = "*" -time = "*" diff --git a/src/timeout/deps.mk b/src/timeout/deps.mk deleted file mode 100644 index b6534caec..000000000 --- a/src/timeout/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += time diff --git a/src/timeout/timeout.rs b/src/timeout/timeout.rs deleted file mode 100644 index 8a16c2b38..000000000 --- a/src/timeout/timeout.rs +++ /dev/null @@ -1,159 +0,0 @@ -#![crate_name = "timeout"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Arcterus - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; -extern crate time; - -use libc::pid_t; -use std::io::{ErrorKind, Write}; -use std::process::{Command, Stdio}; -use std::os::unix::process::ExitStatusExt; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[path = "../common/parse_time.rs"] -mod parse_time; - -#[path = "../common/signals.rs"] -mod signals; - -#[path = "../common/process.rs"] -mod process; -use process::ChildExt; - -extern { - pub fn setpgid(_: libc::pid_t, _: libc::pid_t) -> libc::c_int; -} - -static NAME: &'static str = "timeout"; -static VERSION: &'static str = "1.0.0"; - -static ERR_EXIT_STATUS: i32 = 125; - -pub fn uumain(args: Vec) -> i32 { - let program = args[0].clone(); - - let mut opts = getopts::Options::new(); - opts.optflag("", "preserve-status", "exit with the same status as COMMAND, even when the command times out"); - opts.optflag("", "foreground", "when not running timeout directly from a shell prompt, allow COMMAND to read from the TTY and get TTY signals; in this mode, children of COMMAND will not be timed out"); - opts.optopt("k", "kill-after", "also send a KILL signal if COMMAND is still running this long after the initial signal was sent", "DURATION"); - opts.optflag("s", "signal", "specify the signal to be sent on timeout; SIGNAL may be a name like 'HUP' or a number; see 'kill -l' for a list of signals"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - crash!(ERR_EXIT_STATUS, "{}", f) - } - }; - if matches.opt_present("help") { - print!("{} {} - -Usage: - {} [OPTION] DURATION COMMAND [ARG]... - -{}", NAME, VERSION, program, &opts.usage("Start COMMAND, and kill it if still running after DURATION.")); - } else if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - } else if matches.free.len() < 2 { - show_error!("missing an argument"); - show_error!("for help, try '{0} --help'", program); - return ERR_EXIT_STATUS; - } else { - let status = matches.opt_present("preserve-status"); - let foreground = matches.opt_present("foreground"); - let kill_after = match matches.opt_str("kill-after") { - Some(tstr) => match parse_time::from_str(&tstr) { - Ok(time) => time, - Err(f) => { - show_error!("{}", f); - return ERR_EXIT_STATUS; - } - }, - None => 0f64 - }; - let signal = match matches.opt_str("signal") { - Some(sigstr) => match signals::signal_by_name_or_value(&sigstr) { - Some(sig) => sig, - None => { - show_error!("invalid signal '{}'", sigstr); - return ERR_EXIT_STATUS; - } - }, - None => signals::signal_by_name_or_value("TERM").unwrap() - }; - let duration = match parse_time::from_str(&matches.free[0]) { - Ok(time) => time, - Err(f) => { - show_error!("{}", f); - return ERR_EXIT_STATUS; - } - }; - return timeout(&matches.free[1], &matches.free[2..], duration, signal, kill_after, foreground, status); - } - - 0 -} - -fn timeout(cmdname: &str, args: &[String], duration: f64, signal: usize, kill_after: f64, foreground: bool, preserve_status: bool) -> i32 { - if !foreground { - unsafe { setpgid(0, 0) }; - } - let mut process = match Command::new(cmdname).args(args) - .stdin(Stdio::inherit()) - .stdout(Stdio::inherit()) - .stderr(Stdio::inherit()) - .spawn() { - Ok(p) => p, - Err(err) => { - show_error!("failed to execute process: {}", err); - if err.kind() == ErrorKind::NotFound { - // XXX: not sure which to use - return 127; - } else { - // XXX: this may not be 100% correct... - return 126; - } - } - }; - match process.wait_or_timeout(duration) { - Ok(Some(status)) => status.code().unwrap_or_else(|| status.signal().unwrap()), - Ok(None) => { - return_if_err!(ERR_EXIT_STATUS, process.send_signal(signal)); - match process.wait_or_timeout(kill_after) { - Ok(Some(status)) => { - if preserve_status { - status.code().unwrap_or_else(|| status.signal().unwrap()) - } else { - 124 - } - }, - Ok(None) => { - if kill_after == 0f64 { - // XXX: this may not be right - return 124; - } - return_if_err!(ERR_EXIT_STATUS, process.send_signal(signals::signal_by_name_or_value("KILL").unwrap())); - return_if_err!(ERR_EXIT_STATUS, process.wait()); - 137 - }, - Err(_) => return 124, - } - }, - Err(_) => { - return_if_err!(ERR_EXIT_STATUS, process.send_signal(signal)); - ERR_EXIT_STATUS - }, - } -} diff --git a/src/touch/Cargo.toml b/src/touch/Cargo.toml deleted file mode 100644 index 4c2c7c509..000000000 --- a/src/touch/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "touch" -version = "0.0.1" -authors = [] - -[lib] -name = "touch" -path = "touch.rs" - -[dependencies] -filetime = "*" -getopts = "*" -libc = "*" -time = "*" diff --git a/src/touch/deps.mk b/src/touch/deps.mk deleted file mode 100644 index 0e162f8f0..000000000 --- a/src/touch/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += kernel32 winapi filetime time diff --git a/src/touch/touch.rs b/src/touch/touch.rs deleted file mode 100644 index 9f51f9837..000000000 --- a/src/touch/touch.rs +++ /dev/null @@ -1,211 +0,0 @@ -#![crate_name = "touch"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Nick Platt - * - * For the full copyright and license information, please view the LICENSE file - * that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; -extern crate time; -extern crate filetime; - -use filetime::*; -use std::fs::{self, File}; -use std::io::{Error, Write}; -use std::path::Path; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[path = "../common/filesystem.rs"] -mod filesystem; - -use filesystem::UUPathExt; - -static NAME: &'static str = "touch"; -static VERSION: &'static str = "1.0.0"; - -// Since touch's date/timestamp parsing doesn't account for timezone, the -// returned value from time::strptime() is UTC. We get system's timezone to -// localize the time. -macro_rules! to_local( - ($exp:expr) => ({ - let mut tm = $exp; - tm.tm_utcoff = time::now().tm_utcoff; - tm - }) -); - -macro_rules! local_tm_to_filetime( - ($exp:expr) => ({ - let ts = $exp.to_timespec(); - FileTime::from_seconds_since_1970(ts.sec as u64, ts.nsec as u32) - }) -); - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("a", "", "change only the access time"); - opts.optflag("c", "no-create", "do not create any files"); - opts.optopt( "d", "date", "parse argument and use it instead of current time", "STRING"); - opts.optflag("h", "no-dereference", "affect each symbolic link instead of any referenced file \ - (only for systems that can change the timestamps of a symlink)"); - opts.optflag("m", "", "change only the modification time"); - opts.optopt( "r", "reference", "use this file's times instead of the current time", "FILE"); - opts.optopt( "t", "", "use [[CC]YY]MMDDhhmm[.ss] instead of the current time", "STAMP"); - opts.optopt( "", "time", "change only the specified time: \"access\", \"atime\", or \ - \"use\" are equivalent to -a; \"modify\" or \"mtime\" are \ - equivalent to -m", "WORD"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(e) => panic!("Invalid options\n{}", e) - }; - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - if matches.opt_present("help") || matches.free.is_empty() { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage: {} [OPTION]... FILE...", NAME); - println!(""); - println!("{}", opts.usage("Update the access and modification times of \ - each FILE to the current time.")); - if matches.free.is_empty() { - return 1; - } - return 0; - } - - if matches.opt_present("date") && matches.opts_present(&["reference".to_string(), "t".to_string()]) || - matches.opt_present("reference") && matches.opts_present(&["date".to_string(), "t".to_string()]) || - matches.opt_present("t") && matches.opts_present(&["date".to_string(), "reference".to_string()]) { - panic!("Invalid options: cannot specify reference time from more than one source"); - } - - let (mut atime, mut mtime) = - if matches.opt_present("reference") { - stat(&matches.opt_str("reference").unwrap()[..], !matches.opt_present("no-dereference")) - } else if matches.opts_present(&["date".to_string(), "t".to_string()]) { - let timestamp = if matches.opt_present("date") { - parse_date(matches.opt_str("date").unwrap().as_ref()) - } else { - parse_timestamp(matches.opt_str("t").unwrap().as_ref()) - }; - (timestamp, timestamp) - } else { - let now = local_tm_to_filetime!(time::now()); - (now, now) - }; - - for filename in matches.free.iter() { - let path = &filename[..]; - - if !Path::new(path).uu_exists() { - // no-dereference included here for compatibility - if matches.opts_present(&["no-create".to_string(), "no-dereference".to_string()]) { - continue; - } - - match File::create(path) { - Err(e) => { - show_warning!("cannot touch '{}': {}", path, e); - continue; - }, - _ => (), - }; - - // Minor optimization: if no reference time was specified, we're done. - if !matches.opts_present(&["date".to_string(), "reference".to_string(), "t".to_string()]) { - continue; - } - } - - // If changing "only" atime or mtime, grab the existing value of the other. - // Note that "-a" and "-m" may be passed together; this is not an xor. - if matches.opts_present(&["a".to_string(), "m".to_string(), "time".to_string()]) { - let st = stat(path, !matches.opt_present("no-dereference")); - let time = matches.opt_strs("time"); - - if !(matches.opt_present("a") || - time.contains(&"access".to_string()) || - time.contains(&"atime".to_string()) || - time.contains(&"use".to_string())) { - atime = st.0; - } - - if !(matches.opt_present("m") || - time.contains(&"modify".to_string()) || - time.contains(&"mtime".to_string())) { - mtime = st.1; - } - } - - // this follows symlinks and thus does not work correctly for the -h flag - // need to use lutimes() c function on supported platforms - match filetime::set_file_times(path, atime, mtime) { - Err(e) => show_warning!("cannot touch '{}': {}", path, e), - _ => (), - }; - } - - 0 -} - -fn stat(path: &str, follow: bool) -> (FileTime, FileTime) { - let metadata = if follow { - fs::symlink_metadata(path) - } else { - fs::metadata(path) - }; - - match metadata { - Ok(m) => ( - FileTime::from_last_access_time(&m), - FileTime::from_last_modification_time(&m) - ), - Err(_) => crash!(1, "failed to get attributes of '{}': {}", path, Error::last_os_error()) - } -} - -fn parse_date(str: &str) -> FileTime { - // This isn't actually compatible with GNU touch, but there doesn't seem to - // be any simple specification for what format this parameter allows and I'm - // not about to implement GNU parse_datetime. - // http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob_plain;f=lib/parse-datetime.y - match time::strptime(str, "%c") { - Ok(tm) => local_tm_to_filetime!(to_local!(tm)), - Err(e) => panic!("Unable to parse date\n{}", e) - } -} - -fn parse_timestamp(s: &str) -> FileTime { - let now = time::now(); - let (format, ts) = match s.chars().count() { - 15 => ("%Y%m%d%H%M.%S", s.to_string()), - 12 => ("%Y%m%d%H%M", s.to_string()), - 13 => ("%y%m%d%H%M.%S", s.to_string()), - 10 => ("%y%m%d%H%M", s.to_string()), - 11 => ("%Y%m%d%H%M.%S", format!("{}{}", now.tm_year + 1900, s)), - 8 => ("%Y%m%d%H%M", format!("{}{}", now.tm_year + 1900, s)), - _ => panic!("Unknown timestamp format") - }; - - match time::strptime(&ts, format) { - Ok(tm) => local_tm_to_filetime!(to_local!(tm)), - Err(e) => panic!("Unable to parse timestamp\n{}", e) - } -} - diff --git a/src/tr/Cargo.toml b/src/tr/Cargo.toml deleted file mode 100644 index 0c47ab424..000000000 --- a/src/tr/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "tr" -version = "0.0.1" -authors = [] - -[lib] -name = "tr" -path = "tr.rs" - -[dependencies] -getopts = "*" -libc = "*" -bit-set = "*" -vec_map = "*" diff --git a/src/tr/deps.mk b/src/tr/deps.mk deleted file mode 100644 index 5e9f37b70..000000000 --- a/src/tr/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += bit-vec bit-set vec_map diff --git a/src/tr/expand.rs b/src/tr/expand.rs deleted file mode 100644 index fd8f885ff..000000000 --- a/src/tr/expand.rs +++ /dev/null @@ -1,117 +0,0 @@ -/* - * This file is part of the uutils coreutils package. - * - * (c) Michael Gehring - * (c) kwantam - * 20150428 created `expand` module to eliminate most allocs during setup - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use std::char::from_u32; -use std::cmp::min; -use std::iter::Peekable; -use std::ops::Range; - -#[inline] -fn unescape_char(c: char) -> char { - match c { - 'a' => 0x07u8 as char, - 'b' => 0x08u8 as char, - 'f' => 0x0cu8 as char, - 'v' => 0x0bu8 as char, - 'n' => '\n', - 'r' => '\r', - 't' => '\t', - _ => c, - } -} - -struct Unescape<'a> { - string: &'a str, -} - -impl<'a> Iterator for Unescape<'a> { - type Item = char; - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let slen = self.string.len(); - (min(slen, 1), None) - } - - #[inline] - fn next(&mut self) -> Option { - if self.string.len() == 0 { - return None; - } - - // is the next character an escape? - let (ret, idx) = match self.string.chars().next().unwrap() { - '\\' if self.string.len() > 1 => { - // yes---it's \ and it's not the last char in a string - // we know that \ is 1 byte long so we can index into the string safely - let c = self.string[1..].chars().next().unwrap(); - (Some(unescape_char(c)), 1 + c.len_utf8()) - }, - c => (Some(c), c.len_utf8()), // not an escape char - }; - - self.string = &self.string[idx..]; // advance the pointer to the next char - ret - } -} - -pub struct ExpandSet<'a> { - range: Range, - unesc: Peekable>, -} - -impl<'a> Iterator for ExpandSet<'a> { - type Item = char; - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.unesc.size_hint() - } - - #[inline] - fn next(&mut self) -> Option { - // while the Range has elements, try to return chars from it - // but make sure that they actually turn out to be Chars! - while let Some(n) = self.range.next() { - match from_u32(n) { - Some(c) => return Some(c), - _ => (), - } - } - - if let Some(first) = self.unesc.next() { - // peek ahead - if self.unesc.peek() == Some(&'-') && match self.unesc.size_hint() { - (x, _) if x > 1 => true, // there's a range here; record it in our internal Range struct - _ => false, - } { - self.unesc.next(); // this is the '-' - let last = self.unesc.next().unwrap(); // this is the end of the range - - self.range = first as u32 + 1 .. last as u32 + 1; - } - - return Some(first); // in any case, return the next char - } - - None - } -} - -impl<'a> ExpandSet<'a> { - #[inline] - pub fn new(s: &'a str) -> ExpandSet<'a> { - ExpandSet { - range: 0 .. 0, - unesc: Unescape { string: s }.peekable(), - } - } -} diff --git a/src/tr/tr.rs b/src/tr/tr.rs deleted file mode 100644 index 7ec6627ff..000000000 --- a/src/tr/tr.rs +++ /dev/null @@ -1,164 +0,0 @@ -#![crate_name = "tr"] -#![feature(io)] -/* - * This file is part of the uutils coreutils package. - * - * (c) Michael Gehring - * (c) kwantam - * 20150428 created `expand` module to eliminate most allocs during setup - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate bit_set; -extern crate getopts; -extern crate vec_map; - -use bit_set::BitSet; -use getopts::Options; -use std::io::{stdin, stdout, BufReader, Read, Write}; -use vec_map::VecMap; - -use expand::ExpandSet; - -#[path="../common/util.rs"] -#[macro_use] -mod util; - -mod expand; - -static NAME: &'static str = "tr"; -static VERSION: &'static str = "1.0.0"; -const BUFFER_LEN: usize = 1024; - -fn delete<'a>(set: ExpandSet<'a>, complement: bool) { - let mut bset = BitSet::new(); - let mut stdout = stdout(); - let mut buf = String::with_capacity(BUFFER_LEN + 4); - - for c in set { - bset.insert(c as usize); - } - - let is_allowed = |c : char| { - if complement { - bset.contains(&(c as usize)) - } else { - !bset.contains(&(c as usize)) - } - }; - - for c in BufReader::new(stdin()).chars() { - match c { - Ok(c) if is_allowed(c) => buf.push(c), - Ok(_) => (), - Err(err) => panic!("{}", err), - }; - if buf.len() >= BUFFER_LEN { - safe_unwrap!(stdout.write_all(&buf[..].as_bytes())); - } - } - if buf.len() > 0 { - safe_unwrap!(stdout.write_all(&buf[..].as_bytes())); - pipe_flush!(); - } -} - -fn tr<'a>(set1: ExpandSet<'a>, mut set2: ExpandSet<'a>) { - let mut map = VecMap::new(); - let mut stdout = stdout(); - let mut buf = String::with_capacity(BUFFER_LEN + 4); - - let mut s2_prev = '_'; - for i in set1 { - s2_prev = set2.next().unwrap_or(s2_prev); - - map.insert(i as usize, s2_prev); - } - - for c in BufReader::new(stdin()).chars() { - match c { - Ok(inc) => { - let trc = match map.get(&(inc as usize)) { - Some(t) => *t, - None => inc, - }; - buf.push(trc); - if buf.len() >= BUFFER_LEN { - safe_unwrap!(stdout.write_all(&buf[..].as_bytes())); - buf.truncate(0); - } - } - Err(err) => { - panic!("{}", err); - } - } - } - if buf.len() > 0 { - safe_unwrap!(stdout.write_all(&buf[..].as_bytes())); - pipe_flush!(); - } -} - -fn usage(opts: &Options) { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {} [OPTIONS] SET1 [SET2]", NAME); - println!(""); - println!("{}", opts.usage("Translate or delete characters.")); -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - - opts.optflag("c", "complement", "use the complement of SET1"); - opts.optflag("C", "", "same as -c"); - opts.optflag("d", "delete", "delete characters in SET1"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(err) => { - show_error!("{}", err); - return 1; - } - }; - - if matches.opt_present("help") { - usage(&opts); - return 0; - } - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - if matches.free.len() == 0 { - usage(&opts); - return 1; - } - - let dflag = matches.opt_present("d"); - let cflag = matches.opts_present(&["c".to_string(), "C".to_string()]); - let sets = matches.free; - - if cflag && !dflag { - show_error!("-c is only supported with -d"); - return 1; - } - - if dflag { - let set1 = ExpandSet::new(sets[0].as_ref()); - delete(set1, cflag); - } else { - let set1 = ExpandSet::new(sets[0].as_ref()); - let set2 = ExpandSet::new(sets[1].as_ref()); - tr(set1, set2); - } - - 0 -} diff --git a/src/true/Cargo.toml b/src/true/Cargo.toml deleted file mode 100644 index d5b7fe5cc..000000000 --- a/src/true/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "true" -version = "0.0.1" -authors = [] - -[lib] -name = "true" -path = "true.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/true/true.rs b/src/true/true.rs deleted file mode 100644 index 772870f54..000000000 --- a/src/true/true.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![crate_name= "true"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -pub fn uumain(_: Vec) -> i32 { - 0 -} diff --git a/src/truncate/Cargo.toml b/src/truncate/Cargo.toml deleted file mode 100644 index 2795af9fb..000000000 --- a/src/truncate/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "truncate" -version = "0.0.1" -authors = [] - -[lib] -name = "truncate" -path = "truncate.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/truncate/truncate.rs b/src/truncate/truncate.rs deleted file mode 100644 index 7cffc301b..000000000 --- a/src/truncate/truncate.rs +++ /dev/null @@ -1,215 +0,0 @@ -#![crate_name = "truncate"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Arcterus - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use std::ascii::AsciiExt; -use std::fs::{File, metadata, OpenOptions}; -use std::io::{Result, Write}; -use std::path::Path; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[derive(Eq, PartialEq)] -enum TruncateMode { - Reference, - Extend, - Reduce, - AtMost, - AtLeast, - RoundDown, - RoundUp -} - -static NAME: &'static str = "truncate"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("c", "no-create", "do not create files that do not exist"); - opts.optflag("o", "io-blocks", "treat SIZE as the number of I/O blocks of the file rather than bytes (NOT IMPLEMENTED)"); - opts.optopt("r", "reference", "base the size of each file on the size of RFILE", "RFILE"); - opts.optopt("s", "size", "set or adjust the size of each file according to SIZE, which is in bytes unless --io-blocks is specified", "SIZE"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { crash!(1, "{}", f) } - }; - - if matches.opt_present("help") { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {} [OPTION]... FILE...", NAME); - println!(""); - print!("{}", opts.usage("Shrink or extend the size of each file to the specified size.")); - print!(" -SIZE is an integer with an optional prefix and optional unit. -The available units (K, M, G, T, P, E, Z, and Y) use the following format: - 'KB' => 1000 (kilobytes) - 'K' => 1024 (kibibytes) - 'MB' => 1000*1000 (megabytes) - 'M' => 1024*1024 (mebibytes) - 'GB' => 1000*1000*1000 (gigabytes) - 'G' => 1024*1024*1024 (gibibytes) -SIZE may also be prefixed by one of the following to adjust the size of each -file based on its current size: - '+' => extend by - '-' => reduce by - '<' => at most - '>' => at least - '/' => round down to multiple of - '%' => round up to multiple of -"); - } else if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - } else if matches.free.is_empty() { - show_error!("missing an argument"); - return 1; - } else { - let no_create = matches.opt_present("no-create"); - let io_blocks = matches.opt_present("io-blocks"); - let reference = matches.opt_str("reference"); - let size = matches.opt_str("size"); - if reference.is_none() && size.is_none() { - crash!(1, "you must specify either --reference or --size"); - } else { - match truncate(no_create, io_blocks, reference, size, matches.free) { - Ok(()) => ( /* pass */ ), - Err(_) => return 1 - } - } - } - - 0 -} - -fn truncate(no_create: bool, _: bool, reference: Option, size: Option, filenames: Vec) -> Result<()> { - let (refsize, mode) = match reference { - Some(rfilename) => { - let _ = match File::open(Path::new(&rfilename)) { - Ok(m) => m, - Err(f) => { - crash!(1, "{}", f.to_string()) - } - }; - match metadata(rfilename) { - Ok(meta) => (meta.len(), TruncateMode::Reference), - Err(f) => { - crash!(1, "{}", f.to_string()) - } - } - } - None => parse_size(size.unwrap().as_ref()) - }; - for filename in filenames.iter() { - let path = Path::new(filename); - match OpenOptions::new().read(true).write(true).create(!no_create).open(path) { - Ok(file) => { - let fsize = match metadata(filename) { - Ok(meta) => meta.len(), - Err(f) => { - show_warning!("{}", f.to_string()); - continue; - } - }; - let tsize: u64 = match mode { - TruncateMode::Reference => refsize, - TruncateMode::Extend => fsize + refsize, - TruncateMode::Reduce => fsize - refsize, - TruncateMode::AtMost => if fsize > refsize { refsize } else { fsize }, - TruncateMode::AtLeast => if fsize < refsize { refsize } else { fsize }, - TruncateMode::RoundDown => fsize - fsize % refsize, - TruncateMode::RoundUp => fsize + fsize % refsize - }; - let _ = match file.set_len(tsize) { - Ok(_) => {}, - Err(f) => { - crash!(1, "{}", f.to_string()) - } - }; - } - Err(f) => { - crash!(1, "{}", f.to_string()) - } - } - } - Ok(()) -} - -fn parse_size(size: &str) -> (u64, TruncateMode) { - let mode = match size.chars().next().unwrap() { - '+' => TruncateMode::Extend, - '-' => TruncateMode::Reduce, - '<' => TruncateMode::AtMost, - '>' => TruncateMode::AtLeast, - '/' => TruncateMode::RoundDown, - '*' => TruncateMode::RoundUp, - _ => TruncateMode::Reference /* assume that the size is just a number */ - }; - let bytes = { - let mut slice = - if mode == TruncateMode::Reference { - let size: &str = size; - size - } else { - &size[1..] - }; - if slice.chars().last().unwrap().is_alphabetic() { - slice = &slice[..slice.len() - 1]; - if slice.len() > 0 && slice.chars().last().unwrap().is_alphabetic() { - slice = &slice[..slice.len() - 1]; - } - } - slice - }.to_string(); - let mut number: u64 = match bytes.parse() { - Ok(num) => num, - Err(e) => { - crash!(1, "'{}' is not a valid number: {}", size, e) - } - }; - if size.chars().last().unwrap().is_alphabetic() { - number *= match size.chars().last().unwrap().to_ascii_uppercase() { - 'B' => match size.chars().nth(size.len() - 2).unwrap().to_ascii_uppercase() { - 'K' => 1000u64, - 'M' => 1000u64.pow(2), - 'G' => 1000u64.pow(3), - 'T' => 1000u64.pow(4), - 'P' => 1000u64.pow(5), - 'E' => 1000u64.pow(6), - 'Z' => 1000u64.pow(7), - 'Y' => 1000u64.pow(8), - letter => { - crash!(1, "'{}B' is not a valid suffix.", letter) - } - }, - 'K' => 1024u64, - 'M' => 1024u64.pow(2), - 'G' => 1024u64.pow(3), - 'T' => 1024u64.pow(4), - 'P' => 1024u64.pow(5), - 'E' => 1024u64.pow(6), - 'Z' => 1024u64.pow(7), - 'Y' => 1024u64.pow(8), - letter => { - crash!(1, "'{}' is not a valid suffix.", letter) - } - }; - } - (number, mode) -} diff --git a/src/tsort/Cargo.toml b/src/tsort/Cargo.toml deleted file mode 100644 index 877cf9707..000000000 --- a/src/tsort/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "tsort" -version = "0.0.1" -authors = [] - -[lib] -name = "tsort" -path = "tsort.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/tsort/tsort.rs b/src/tsort/tsort.rs deleted file mode 100644 index 6f43aaebb..000000000 --- a/src/tsort/tsort.rs +++ /dev/null @@ -1,196 +0,0 @@ -#![crate_name = "tsort"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Ben Eggers - * (c) Akira Hayakawa - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use std::collections::{HashMap, HashSet}; -use std::fs::File; -use std::io::{BufRead, BufReader, Read, stdin, Write}; -use std::path::Path; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "tsort"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "{}", f) - }; - - if matches.opt_present("h") { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {} [OPTIONS] FILE", NAME); - println!(""); - println!("{}", opts.usage("Topological sort the strings in FILE. Strings are defined as any sequence of tokens separated by whitespace (tab, space, or newline). If FILE is not passed in, stdin is used instead.")); - return 0; - } - - if matches.opt_present("V") { - println!("{} {}", NAME, VERSION); - return 0; - } - - let files = matches.free.clone(); - let input = if files.len() > 1 { - crash!(1, "{}, extra operand '{}'", NAME, matches.free[1]); - } else if files.is_empty() { - "-".to_string() - } else { - files[0].to_string() - }; - - let mut stdin_buf; - let mut file_buf; - let mut reader = BufReader::new( - if input == "-" { - stdin_buf = stdin(); - &mut stdin_buf as &mut Read - } else { - file_buf = match File::open(Path::new(&input)) { - Ok(a) => a, - _ => { - show_error!("{}: No such file or directory", input); - return 1; - } - }; - &mut file_buf as &mut Read - } - ); - - let mut g = Graph::new(); - loop { - let mut line = String::new(); - match reader.read_line(&mut line) { - Ok(_) => { - let tokens: Vec = line.trim_right().split_whitespace().map(|s| s.to_string()).collect(); - if tokens.len() == 0 { - break - } - for ab in tokens.chunks(2) { - match ab.len() { - 2 => g.add_edge(&ab[0], &ab[1]), - _ => crash!(1, "{}: input contains an odd number of tokens", input) - } - } - }, - _ => break - } - } - - g.run_tsort(); - - if !g.is_acyclic() { - crash!(1, "{}, input contains a loop:", input); - } - - for x in g.result.iter() { - println!("{}", x); - } - - 0 -} - -// We use String as a representation of node here -// but using integer may improve performance. -struct Graph { - in_edges: HashMap>, - out_edges: HashMap>, - result: Vec -} - -impl Graph { - fn new() -> Graph { - Graph { - in_edges: HashMap::new(), - out_edges: HashMap::new(), - result: vec!(), - } - } - - fn has_node(&self, n: &String) -> bool { - self.in_edges.contains_key(n) - } - - fn has_edge(&self, from: &String, to: &String) -> bool { - self.in_edges.get(to).unwrap().contains(from) - } - - fn init_node(&mut self, n: &String) { - self.in_edges.insert(n.clone(), HashSet::new()); - self.out_edges.insert(n.clone(), vec!()); - } - - fn add_edge(&mut self, from: &String, to: &String) { - if !self.has_node(to) { - self.init_node(to); - } - - if !self.has_node(from) { - self.init_node(from); - } - - if !self.has_edge(from, to) { - self.in_edges.get_mut(to).unwrap().insert(from.clone()); - self.out_edges.get_mut(from).unwrap().push(to.clone()); - } - } - - // Kahn's algorithm - // O(|V|+|E|) - fn run_tsort(&mut self) { - let mut start_nodes = vec!(); - for (n, edges) in self.in_edges.iter() { - if edges.is_empty() { - start_nodes.push(n.clone()); - } - } - - while !start_nodes.is_empty() { - let n = start_nodes.remove(0); - - self.result.push(n.clone()); - - let n_out_edges = self.out_edges.get_mut(&n).unwrap(); - for m in n_out_edges.iter() { - let m_in_edges = self.in_edges.get_mut(m).unwrap(); - m_in_edges.remove(&n); - - // If m doesn't have other in-coming edges add it to start_nodes - if m_in_edges.is_empty() { - start_nodes.push(m.clone()); - } - } - n_out_edges.clear(); - } - } - - fn is_acyclic(&self) -> bool { - for (_, edges) in self.out_edges.iter() { - if !edges.is_empty() { - return false - } - } - true - } -} diff --git a/src/tty/Cargo.toml b/src/tty/Cargo.toml deleted file mode 100644 index 40e4f8a82..000000000 --- a/src/tty/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "tty" -version = "0.0.1" -authors = [] - -[lib] -name = "tty" -path = "tty.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/tty/tty.rs b/src/tty/tty.rs deleted file mode 100644 index 7bac51a0f..000000000 --- a/src/tty/tty.rs +++ /dev/null @@ -1,83 +0,0 @@ -#![crate_name = "tty"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * Synced with http://lingrok.org/xref/coreutils/src/tty.c - */ - -extern crate getopts; -extern crate libc; - -use std::ffi::CStr; -use std::io::Write; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -extern { - fn ttyname(filedesc: libc::c_int) -> *const libc::c_char; - fn isatty(filedesc: libc::c_int) -> libc::c_int; -} - -static NAME: &'static str = "tty"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("s", "silent", "print nothing, only return an exit status"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { crash!(2, "{}", f) } - }; - - if matches.opt_present("help") { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {} [OPTION]...", NAME); - println!(""); - print!("{}", opts.usage("Print the file name of the terminal connected to standard input.")); - } else if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - } else { - let silent = matches.opt_present("s"); - - let tty = unsafe { - let ptr = ttyname(libc::STDIN_FILENO); - if !ptr.is_null() { - String::from_utf8_lossy(CStr::from_ptr(ptr).to_bytes()).to_string() - } else { - "".to_string() - } - }; - - if !silent { - if !tty.chars().all(|c| c.is_whitespace()) { - println!("{}", tty); - } else { - println!("not a tty"); - } - } - - return unsafe { - if isatty(libc::STDIN_FILENO) == 1 { - libc::EXIT_SUCCESS - } else { - libc::EXIT_FAILURE - } - }; - } - - 0 -} diff --git a/src/uname/Cargo.toml b/src/uname/Cargo.toml deleted file mode 100644 index 4f10bc75a..000000000 --- a/src/uname/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "uname" -version = "0.0.1" -authors = [] - -[lib] -name = "uname" -path = "uname.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/uname/uname.rs b/src/uname/uname.rs deleted file mode 100644 index 7b5700f85..000000000 --- a/src/uname/uname.rs +++ /dev/null @@ -1,108 +0,0 @@ -#![crate_name = "uname"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Joao Oliveira - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/* last synced with: uname (GNU coreutils) 8.21 */ - -extern crate getopts; -extern crate libc; - -use c_types::utsname; -use std::ffi::CStr; -use std::io::Write; -use std::mem::uninitialized; - -#[path = "../common/util.rs"] #[macro_use] mod util; -#[path = "../common/c_types.rs"] mod c_types; - -struct Uts { - sysname: String, - nodename: String, - release: String, - version: String, - machine: String -} - -extern { - fn uname(uts: *mut utsname); -} - -unsafe fn string_from_c_str(ptr: *const i8) -> String { - String::from_utf8_lossy(CStr::from_ptr(ptr).to_bytes()).to_string() -} - -unsafe fn getuname() -> Uts { - let mut uts: utsname = uninitialized(); - uname(&mut uts); - Uts { - sysname: string_from_c_str(uts.sysname.as_ptr() as *const i8), - nodename: string_from_c_str(uts.nodename.as_ptr() as *const i8), - release: string_from_c_str(uts.release.as_ptr() as *const i8), - version: string_from_c_str(uts.version.as_ptr() as *const i8), - machine: string_from_c_str(uts.machine.as_ptr() as *const i8) - } -} - -static NAME: &'static str = "uname"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("a", "all", "Behave as though all of the options -mnrsv were specified."); - opts.optflag("m", "machine", "print the machine hardware name."); - opts.optflag("n", "nodename", "print the nodename (the nodename may be a name that the system is known by to a communications network)."); - opts.optflag("p", "processor", "print the machine processor architecture name."); - opts.optflag("r", "release", "print the operating system release."); - opts.optflag("s", "sysname", "print the operating system name."); - opts.optflag("v", "version", "print the operating system version."); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "{}", f), - }; - if matches.opt_present("help") { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {} [OPTIONS]", NAME); - println!(""); - print!("{}", opts.usage("The uname utility writes symbols representing one or more system characteristics to the standard output.")); - return 0; - } - let uname = unsafe { getuname() }; - let mut output = String::new(); - if matches.opt_present("sysname") || matches.opt_present("all") - || !matches.opts_present(&["nodename".to_string(), "release".to_string(), "version".to_string(), "machine".to_string()]) { - output.push_str(uname.sysname.as_ref()); - output.push_str(" "); - } - - if matches.opt_present("nodename") || matches.opt_present("all") { - output.push_str(uname.nodename.as_ref()); - output.push_str(" "); - } - if matches.opt_present("release") || matches.opt_present("all") { - output.push_str(uname.release.as_ref()); - output.push_str(" "); - } - if matches.opt_present("version") || matches.opt_present("all") { - output.push_str(uname.version.as_ref()); - output.push_str(" "); - } - if matches.opt_present("machine") || matches.opt_present("all") { - output.push_str(uname.machine.as_ref()); - output.push_str(" "); - } - println!("{}", output.trim()); - - 0 -} diff --git a/src/unexpand/Cargo.toml b/src/unexpand/Cargo.toml deleted file mode 100644 index 4e631f138..000000000 --- a/src/unexpand/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "unexpand" -version = "0.0.1" -authors = [] - -[lib] -name = "unexpand" -path = "unexpand.rs" - -[dependencies] -getopts = "*" -libc = "*" -unicode-width = "*" diff --git a/src/unexpand/deps.mk b/src/unexpand/deps.mk deleted file mode 100644 index fb8005c0c..000000000 --- a/src/unexpand/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += unicode-width diff --git a/src/unexpand/unexpand.rs b/src/unexpand/unexpand.rs deleted file mode 100644 index af138dcef..000000000 --- a/src/unexpand/unexpand.rs +++ /dev/null @@ -1,283 +0,0 @@ -#![crate_name = "unexpand"] -#![feature(unicode)] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Virgile Andreani - * (c) kwantam - * 20150428 updated to work with both UTF-8 and non-UTF-8 encodings - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; -extern crate rustc_unicode; -extern crate unicode_width; - -use std::fs::File; -use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Stdout, Write}; -use std::str::from_utf8; -use rustc_unicode::str::utf8_char_width; -use unicode_width::UnicodeWidthChar; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "unexpand"; -static VERSION: &'static str = "0.0.1"; - -static DEFAULT_TABSTOP: usize = 8; - -fn tabstops_parse(s: String) -> Vec { - let words = s.split(',').collect::>(); - - let nums = words.into_iter() - .map(|sn| sn.parse() - .unwrap_or_else( - |_| crash!(1, "{}\n", "tab size contains invalid character(s)")) - ) - .collect::>(); - - if nums.iter().any(|&n| n == 0) { - crash!(1, "{}\n", "tab size cannot be 0"); - } - - match nums.iter().fold((true, 0), |(acc, last), &n| (acc && last <= n, n)) { - (false, _) => crash!(1, "{}\n", "tab sizes must be ascending"), - _ => {} - } - - nums -} - -struct Options { - files: Vec, - tabstops: Vec, - aflag: bool, - uflag: bool, -} - -impl Options { - fn new(matches: getopts::Matches) -> Options { - let tabstops = match matches.opt_str("t") { - None => vec!(DEFAULT_TABSTOP), - Some(s) => tabstops_parse(s) - }; - - let aflag = (matches.opt_present("all") || matches.opt_present("tabs")) - && !matches.opt_present("first-only"); - let uflag = !matches.opt_present("U"); - - let files = - if matches.free.is_empty() { - vec!("-".to_string()) - } else { - matches.free - }; - - Options { files: files, tabstops: tabstops, aflag: aflag, uflag: uflag } - } -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("a", "all", "convert all blanks, instead of just initial blanks"); - opts.optflag("", "first-only", "convert only leading sequences of blanks (overrides -a)"); - opts.optopt("t", "tabs", "have tabs N characters apart instead of 8 (enables -a)", "N"); - opts.optopt("t", "tabs", "use comma separated LIST of tab positions (enables -a)", "LIST"); - opts.optflag("U", "no-utf8", "interpret input file as 8-bit ASCII rather than UTF-8"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "{}", f) - }; - - if matches.opt_present("help") { - println!("{} {}\n", NAME, VERSION); - println!("Usage: {} [OPTION]... [FILE]...\n", NAME); - println!("{}", opts.usage( - "Convert blanks in each FILE to tabs, writing to standard output.\n\ - With no FILE, or when FILE is -, read standard input.")); - return 0; - } - - if matches.opt_present("V") { - println!("{} {}", NAME, VERSION); - return 0; - } - - unexpand(Options::new(matches)); - - 0 -} - -fn open(path: String) -> BufReader> { - let file_buf; - if path == "-" { - BufReader::new(Box::new(stdin()) as Box) - } else { - file_buf = match File::open(&path[..]) { - Ok(a) => a, - Err(e) => crash!(1, "{}: {}", &path[..], e), - }; - BufReader::new(Box::new(file_buf) as Box) - } -} - -fn next_tabstop(tabstops: &[usize], col: usize) -> Option { - if tabstops.len() == 1 { - Some(tabstops[0] - col % tabstops[0]) - } else { - // find next larger tab - match tabstops.iter().skip_while(|&&t| t <= col).next() { - Some(t) => Some(t - col), - None => None, // if there isn't one in the list, tab becomes a single space - } - } -} - -fn write_tabs(mut output: &mut BufWriter, tabstops: &[usize], - mut scol: usize, col: usize, prevtab: bool, init: bool, amode: bool) { - // This conditional establishes the following: - // We never turn a single space before a non-blank into - // a tab, unless it's at the start of the line. - let ai = init || amode; - if (ai && !prevtab && col > scol + 1) || - (col > scol && (init || ai && prevtab)) { - while let Some(nts) = next_tabstop(tabstops, scol) { - if col < scol + nts { - break; - } - - safe_unwrap!(output.write_all("\t".as_bytes())); - scol += nts; - } - } - - while col > scol { - safe_unwrap!(output.write_all(" ".as_bytes())); - scol += 1; - } -} - -#[derive(PartialEq, Eq, Debug)] -enum CharType { - Backspace, - Space, - Tab, - Other, -} - -fn unexpand(options: Options) { - use self::CharType::*; - - let mut output = BufWriter::new(stdout()); - let ts = &options.tabstops[..]; - let mut buf = Vec::new(); - let lastcol = if ts.len() > 1 { - *ts.last().unwrap() - } else { - 0 - }; - - for file in options.files.into_iter() { - let mut fh = open(file); - - while match fh.read_until('\n' as u8, &mut buf) { - Ok(s) => s > 0, - Err(_) => buf.len() > 0, - } { - let mut byte = 0; // offset into the buffer - let mut col = 0; // the current column - let mut scol = 0; // the start col for the current span, i.e., the already-printed width - let mut init = true; // are we at the start of the line? - let mut pctype = Other; - - while byte < buf.len() { - // when we have a finite number of columns, never convert past the last column - if lastcol > 0 && col >= lastcol { - write_tabs(&mut output, ts, scol, col, pctype == Tab, init, true); - safe_unwrap!(output.write_all(&buf[byte..])); - scol = col; - break; - } - - let (ctype, cwidth, nbytes) = if options.uflag { - let nbytes = utf8_char_width(buf[byte]); - - // figure out how big the next char is, if it's UTF-8 - if byte + nbytes > buf.len() { - // make sure we don't overrun the buffer because of invalid UTF-8 - (Other, 1, 1) - } else if let Ok(t) = from_utf8(&buf[byte..byte+nbytes]) { - // Now that we think it's UTF-8, figure out what kind of char it is - match t.chars().next() { - Some(' ') => (Space, 0, 1), - Some('\t') => (Tab, 0, 1), - Some('\x08') => (Backspace, 0, 1), - Some(c) => (Other, UnicodeWidthChar::width(c).unwrap_or(0), nbytes), - None => { // invalid char snuck past the utf8_validation_iterator somehow??? - (Other, 1, 1) - }, - } - } else { - // otherwise, it's not valid - (Other, 1, 1) // implicit assumption: non-UTF8 char has display width 1 - } - } else { - (match buf[byte] { // always take exactly 1 byte in strict ASCII mode - 0x20 => Space, - 0x09 => Tab, - 0x08 => Backspace, - _ => Other, - }, 1, 1) - }; - - // now figure out how many columns this char takes up, and maybe print it - let tabs_buffered = init || options.aflag; - match ctype { - Space | Tab => { // compute next col, but only write space or tab chars if not buffering - col += if ctype == Space { - 1 - } else { - next_tabstop(ts, col).unwrap_or(1) - }; - - if !tabs_buffered { - safe_unwrap!(output.write_all(&buf[byte..byte+nbytes])); - scol = col; // now printed up to this column - } - }, - Other | Backspace => { // always - write_tabs(&mut output, ts, scol, col, pctype == Tab, init, options.aflag); - init = false; // no longer at the start of a line - col = if ctype == Other { // use computed width - col + cwidth - } else if col > 0 { // Backspace case, but only if col > 0 - col - 1 - } else { - 0 - }; - safe_unwrap!(output.write_all(&buf[byte..byte+nbytes])); - scol = col; // we've now printed up to this column - }, - } - - byte += nbytes; // move on to next char - pctype = ctype; // save the previous type - } - - // write out anything remaining - write_tabs(&mut output, ts, scol, col, pctype == Tab, init, true); - buf.truncate(0); // clear out the buffer - } - } - pipe_flush!(output); -} diff --git a/src/uniq/Cargo.toml b/src/uniq/Cargo.toml deleted file mode 100644 index 81245beb1..000000000 --- a/src/uniq/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "uniq" -version = "0.0.1" -authors = [] - -[lib] -name = "uniq" -path = "uniq.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/uniq/uniq.rs b/src/uniq/uniq.rs deleted file mode 100644 index b70b0881a..000000000 --- a/src/uniq/uniq.rs +++ /dev/null @@ -1,242 +0,0 @@ -#![crate_name = "uniq"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Chirag B Jadwani - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - */ - -extern crate getopts; - -use getopts::{Matches, Options}; -use std::cmp::min; -use std::fs::File; -use std::io::{BufRead, BufReader, BufWriter, Read, stdin, stdout, Write}; -use std::path::Path; -use std::str::FromStr; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "uniq"; -static VERSION: &'static str = "1.0.0"; - -struct Uniq { - repeats_only: bool, - uniques_only: bool, - all_repeated: bool, - delimiters: String, - show_counts: bool, - skip_fields: Option, - slice_start: Option, - slice_stop: Option, - ignore_case: bool, -} - -impl Uniq { - pub fn print_uniq(&self, reader: &mut BufReader, writer: &mut BufWriter) { - let mut lines: Vec = vec!(); - let mut first_line_printed = false; - let delimiters = &self.delimiters[..]; - - for io_line in reader.lines() { - let line = crash_if_err!(1, io_line); - if !lines.is_empty() && self.cmp_key(&self.skip_fields(&lines[0])) != self.cmp_key(&self.skip_fields(&line)) { - let print_delimiter = delimiters == "prepend" || (delimiters == "separate" && first_line_printed); - first_line_printed |= self.print_lines(writer, &lines, print_delimiter); - lines.truncate(0); - } - lines.push(line); - } - if !lines.is_empty() { - let print_delimiter = delimiters == "prepend" || (delimiters == "separate" && first_line_printed); - self.print_lines(writer, &lines, print_delimiter); - } - } - - fn skip_fields(&self, line: &String) -> String { - match self.skip_fields { - Some(skip_fields) => - if line.split_whitespace().count() > skip_fields { - let mut field = 0; - let mut i = 0; - while field < skip_fields && i < line.len() { - while i < line.len() && line.chars().nth(i).unwrap().is_whitespace() { - i = i + 1; - } - while i < line.len() && !line.chars().nth(i).unwrap().is_whitespace() { - i = i + 1; - } - field = field + 1; - } - line[i..].to_string() - } else { - "".to_string() - }, - None => line[..].to_string() - } - } - - fn cmp_key(&self, line: &String) -> String { - let len = line.len(); - if len > 0 { - let slice_start = match self.slice_start { - Some(i) => min(i, len - 1), - None => 0 - }; - let slice_stop = match self.slice_stop { - Some(i) => min(slice_start + i, len), - None => len - }; - - line[slice_start..slice_stop].chars() - .map(|c| match c { - 'a' ... 'z' if self.ignore_case => ((c as u8) - 32) as char, - _ => c, - }).collect() - } else { - line.clone() - } - } - - fn print_lines(&self, writer: &mut BufWriter, lines: &Vec, print_delimiter: bool) -> bool { - let mut first_line_printed = false; - let mut count = if self.all_repeated { 1 } else { lines.len() }; - if lines.len() == 1 && !self.repeats_only - || lines.len() > 1 && !self.uniques_only { - self.print_line(writer, &lines[0], count, print_delimiter); - first_line_printed = true; - count += 1; - } - if self.all_repeated { - for line in lines[1..].iter() { - self.print_line(writer, line, count, print_delimiter && !first_line_printed); - first_line_printed = true; - count += 1; - } - } - first_line_printed - } - - fn print_line(&self, writer: &mut BufWriter, line: &String, count: usize, print_delimiter: bool) { - if print_delimiter { - crash_if_err!(1, writer.write_all(&['\n' as u8])); - } - - crash_if_err!(1, if self.show_counts { - writer.write_all(format!("{:7} {}", count, line).as_bytes()) - } else { - writer.write_all(line.as_bytes()) - }); - crash_if_err!(1, writer.write_all("\n".as_bytes())); - } -} - -fn opt_parsed(opt_name: &str, matches: &Matches) -> Option { - matches.opt_str(opt_name).map(|arg_str| { - let opt_val: Option = arg_str.parse().ok(); - opt_val.unwrap_or_else(|| - crash!(1, "Invalid argument for {}: {}", opt_name, arg_str)) - }) -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - - opts.optflag("c", "count", "prefix lines by the number of occurrences"); - opts.optflag("d", "repeated", "only print duplicate lines"); - opts.optflagopt( - "D", - "all-repeated", - "print all duplicate lines delimit-method={none(default),prepend,separate} Delimiting is done with blank lines", - "delimit-method" - ); - opts.optopt("f", "skip-fields", "avoid comparing the first N fields", "N"); - opts.optopt("s", "skip-chars", "avoid comparing the first N characters", "N"); - opts.optopt("w", "check-chars", "compare no more than N characters in lines", "N"); - opts.optflag("i", "ignore-case", "ignore differences in case when comparing"); - opts.optflag("u", "unique", "only print unique lines"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "{}", f) - }; - - if matches.opt_present("help") { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {0} [OPTION]... [FILE]...", NAME); - println!(""); - print!("{}", opts.usage("Filter adjacent matching lines from INPUT (or standard input),\n\ - writing to OUTPUT (or standard output).")); - println!(""); - println!("Note: '{0}' does not detect repeated lines unless they are adjacent.\n\ - You may want to sort the input first, or use 'sort -u' without '{0}'.\n", NAME); - } else if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - } else { - let (in_file_name, out_file_name) = match matches.free.len() { - 0 => ("-".to_string(), "-".to_string()), - 1 => (matches.free[0].clone(), "-".to_string()), - 2 => (matches.free[0].clone(), matches.free[1].clone()), - _ => { - crash!(1, "Extra operand: {}", matches.free[2]); - } - }; - let uniq = Uniq { - repeats_only: matches.opt_present("repeated") || matches.opt_present("all-repeated"), - uniques_only: matches.opt_present("unique"), - all_repeated: matches.opt_present("all-repeated"), - delimiters: match matches.opt_default("all-repeated", "none") { - Some(ref opt_arg) if opt_arg != "none" => { - let rep_args = ["prepend".to_string(), "separate".to_string()]; - if !rep_args.contains(opt_arg) { - crash!(1, "Incorrect argument for all-repeated: {}", opt_arg.clone()); - } - opt_arg.clone() - }, - _ => "".to_string() - }, - show_counts: matches.opt_present("count"), - skip_fields: opt_parsed("skip-fields", &matches), - slice_start: opt_parsed("skip-chars", &matches), - slice_stop: opt_parsed("check-chars", &matches), - ignore_case: matches.opt_present("ignore-case"), - }; - uniq.print_uniq(&mut open_input_file(in_file_name), - &mut open_output_file(out_file_name)); - } - 0 -} - -fn open_input_file(in_file_name: String) -> BufReader> { - let in_file = if in_file_name == "-" { - Box::new(stdin()) as Box - } else { - let path = Path::new(&in_file_name[..]); - let in_file = File::open(&path); - let r = crash_if_err!(1, in_file); - Box::new(r) as Box - }; - BufReader::new(in_file) -} - -fn open_output_file(out_file_name: String) -> BufWriter> { - let out_file = if out_file_name == "-" { - Box::new(stdout()) as Box - } else { - let path = Path::new(&out_file_name[..]); - let in_file = File::create(&path); - let w = crash_if_err!(1, in_file); - Box::new(w) as Box - }; - BufWriter::new(out_file) -} diff --git a/src/unlink/Cargo.toml b/src/unlink/Cargo.toml deleted file mode 100644 index 11c4a5a33..000000000 --- a/src/unlink/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "unlink" -version = "0.0.1" -authors = [] - -[lib] -name = "unlink" -path = "unlink.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/unlink/unlink.rs b/src/unlink/unlink.rs deleted file mode 100644 index 1c9a5e02d..000000000 --- a/src/unlink/unlink.rs +++ /dev/null @@ -1,96 +0,0 @@ -#![crate_name = "unlink"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Colin Warren - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/* last synced with: unlink (GNU coreutils) 8.21 */ - -extern crate getopts; -extern crate libc; - -use getopts::Options; -use libc::consts::os::posix88::{S_IFMT, S_IFLNK, S_IFREG}; -use libc::funcs::posix01::stat_::lstat; -use libc::funcs::posix88::unistd::unlink; -use libc::types::os::arch::c95::c_char; -use libc::types::os::arch::posix01::stat; -use std::io::{Error, ErrorKind, Write}; -use std::mem::uninitialized; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "unlink"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "invalid options\n{}", f) - }; - - if matches.opt_present("help") { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {} [FILE]... [OPTION]...", NAME); - println!(""); - println!("{}", opts.usage("Unlink the file at [FILE].")); - return 0; - } - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - if matches.free.len() == 0 { - crash!(1, "missing operand\nTry '{0} --help' for more information.", NAME); - } else if matches.free.len() > 1 { - crash!(1, "extra operand: '{1}'\nTry '{0} --help' for more information.", NAME, matches.free[1]); - } - - let st_mode = { - let mut buf: stat = unsafe { uninitialized() }; - let result = unsafe { lstat(matches.free[0].as_ptr() as *const c_char, &mut buf as *mut stat) }; - - if result < 0 { - crash!(1, "Cannot stat '{}': {}", matches.free[0], Error::last_os_error()); - } - - buf.st_mode & S_IFMT - }; - - let result = if st_mode != S_IFREG && st_mode != S_IFLNK { - Err(Error::new(ErrorKind::Other, "Not a regular file or symlink")) - } else { - let result = unsafe { unlink(matches.free[0].as_ptr() as *const c_char) }; - - if result < 0 { - Err(Error::last_os_error()) - } else { - Ok(()) - } - }; - - match result { - Ok(_) => (), - Err(e) => { - crash!(1, "cannot unlink '{0}': {1}", matches.free[0], e); - } - } - - 0 -} diff --git a/src/uptime/Cargo.toml b/src/uptime/Cargo.toml deleted file mode 100644 index 9572f295f..000000000 --- a/src/uptime/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "uptime" -version = "0.0.1" -authors = [] - -[lib] -name = "uptime" -path = "uptime.rs" - -[dependencies] -getopts = "*" -libc = "*" -time = "*" diff --git a/src/uptime/deps.mk b/src/uptime/deps.mk deleted file mode 100644 index b6534caec..000000000 --- a/src/uptime/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += time diff --git a/src/uptime/uptime.rs b/src/uptime/uptime.rs deleted file mode 100644 index 7b3730ef5..000000000 --- a/src/uptime/uptime.rs +++ /dev/null @@ -1,207 +0,0 @@ -#![crate_name = "uptime"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/* last synced with: cat (GNU coreutils) 8.13 */ - -extern crate getopts; -extern crate libc; -extern crate time as rtime; - -use getopts::Options; -use libc::{time_t, c_double, c_int, c_char}; -use std::ffi::CString; -use std::fs::File; -use std::io::{Read, Write}; -use std::mem::transmute; -use std::ptr::null; -use utmpx::*; - -#[path = "../common/util.rs"] #[macro_use] mod util; - -#[path = "../common/c_types.rs"] mod c_types; - -#[path = "../common/utmpx.rs"] mod utmpx; - -static NAME: &'static str = "uptime"; -static VERSION: &'static str = "1.0.0"; - -#[cfg(unix)] -extern { - fn getloadavg(loadavg: *mut c_double, nelem: c_int) -> c_int; - - fn getutxent() -> *const c_utmp; - fn setutxent(); - fn endutxent(); - - #[cfg(any(target_os = "macos", target_os = "linux"))] - fn utmpxname(file: *const c_char) -> c_int; -} - -#[cfg(windows)] -extern { - fn GetTickCount() -> libc::uint32_t; -} - -#[cfg(target_os = "freebsd")] -unsafe extern fn utmpxname(_file: *const c_char) -> c_int { - 0 -} - -pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - - opts.optflag("v", "version", "output version information and exit"); - opts.optflag("h", "help", "display this help and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "Invalid options\n{}", f) - }; - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - if matches.opt_present("help") || matches.free.len() > 0 { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {0} [OPTION]", NAME); - println!(""); - println!("{}", opts.usage("Print the current time, the length of time the system has been up,\n\ - the number of users on the system, and the average number of jobs\n\ - in the run queue over the last 1, 5 and 15 minutes.")); - return 0; - } - - print_time(); - let (boot_time, user_count) = process_utmpx(); - let upsecs = get_uptime(boot_time) / 100; - print_uptime(upsecs); - print_nusers(user_count); - print_loadavg(); - - 0 -} - -fn print_loadavg() { - let mut avg: [c_double; 3] = [0.0; 3]; - let loads: i32 = unsafe { transmute(getloadavg(avg.as_mut_ptr(), 3)) }; - - if loads == -1 { - print!("\n"); - } - else { - print!("load average: "); - for n in 0..loads { - print!("{:.2}{}", avg[n as usize], if n == loads - 1 { "\n" } - else { ", " } ); - } - } -} - -#[cfg(unix)] -fn process_utmpx() -> (Option, usize) { - unsafe { - utmpxname(CString::new(DEFAULT_FILE).unwrap().as_ptr()); - } - - let mut nusers = 0; - let mut boot_time = None; - - unsafe { - setutxent(); - - loop { - let line = getutxent(); - - if line == null() { - break; - } - - match (*line).ut_type { - USER_PROCESS => nusers += 1, - BOOT_TIME => { - let t = (*line).ut_tv; - if t.tv_sec > 0 { - boot_time = Some(t.tv_sec); - } - }, - _ => continue - } - } - - endutxent(); - } - - (boot_time, nusers) -} - -#[cfg(windows)] -fn process_utmpx() -> (Option, usize) { - (None, 0) // TODO: change 0 to number of users -} - -fn print_nusers(nusers: usize) { - if nusers == 1 { - print!("1 user, "); - } else if nusers > 1 { - print!("{} users, ", nusers); - } -} - -fn print_time() { - let local_time = rtime::now(); - - print!(" {:02}:{:02}:{:02} ", local_time.tm_hour, - local_time.tm_min, local_time.tm_sec); -} - -#[cfg(unix)] -fn get_uptime(boot_time: Option) -> i64 { - let mut proc_uptime = String::new(); - - if let Some(n) = - File::open("/proc/uptime").ok() - .and_then(|mut f| f.read_to_string(&mut proc_uptime).ok()) - .and_then(|_| proc_uptime.split_whitespace().next()) - .and_then(|s| s.replace(".", "").parse().ok()) { - n - } else { - match boot_time { - Some(t) => { - let now = rtime::get_time().sec; - let time = t as i64; - ((now - time) * 100) - }, - _ => -1, - } - } -} - -#[cfg(windows)] -fn get_uptime(boot_time: Option) -> i64 { - unsafe { GetTickCount() as i64 } -} - -fn print_uptime(upsecs: i64) { - let updays = upsecs / 86400; - let uphours = (upsecs - (updays * 86400)) / 3600; - let upmins = (upsecs - (updays * 86400) - (uphours * 3600)) / 60; - if updays == 1 { - print!("up {:1} day, {:2}:{:02}, ", updays, uphours, upmins); - } - else if updays > 1 { - print!("up {:1} days, {:2}:{:02}, ", updays, uphours, upmins); - } - else { - print!("up {:2}:{:02}, ", uphours, upmins); - } -} diff --git a/src/users/Cargo.toml b/src/users/Cargo.toml deleted file mode 100644 index ce7cea1f5..000000000 --- a/src/users/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "users" -version = "0.0.1" -authors = [] - -[lib] -name = "users" -path = "users.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/users/users.rs b/src/users/users.rs deleted file mode 100644 index d46092f8b..000000000 --- a/src/users/users.rs +++ /dev/null @@ -1,122 +0,0 @@ -#![crate_name = "users"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) KokaKiwi - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/* last synced with: whoami (GNU coreutils) 8.22 */ - -// Allow dead code here in order to keep all fields, constants here, for consistency. -#![allow(dead_code)] - -extern crate getopts; -extern crate libc; - -use getopts::Options; -use std::ffi::{CStr, CString}; -use std::mem; -use std::ptr; -use utmpx::*; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[path = "../common/utmpx.rs"] -mod utmpx; - -extern { - fn getutxent() -> *const c_utmp; - fn getutxid(ut: *const c_utmp) -> *const c_utmp; - fn getutxline(ut: *const c_utmp) -> *const c_utmp; - - fn pututxline(ut: *const c_utmp) -> *const c_utmp; - - fn setutxent(); - fn endutxent(); - - #[cfg(any(target_os = "macos", target_os = "linux"))] - fn utmpxname(file: *const libc::c_char) -> libc::c_int; -} - -#[cfg(target_os = "freebsd")] -unsafe extern fn utmpxname(_file: *const libc::c_char) -> libc::c_int { - 0 -} - -static NAME: &'static str = "users"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => panic!("{}", f), - }; - - if matches.opt_present("help") { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {} [OPTION]... [FILE]", NAME); - println!(""); - println!("{}", opts.usage("Output who is currently logged in according to FILE.")); - return 0; - } - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - let filename = if matches.free.len() > 0 { - matches.free[0].as_ref() - } else { - DEFAULT_FILE - }; - - exec(filename); - - 0 -} - -fn exec(filename: &str) { - unsafe { - utmpxname(CString::new(filename).unwrap().as_ptr()); - } - - let mut users = vec!(); - - unsafe { - setutxent(); - - loop { - let line = getutxent(); - - if line == ptr::null() { - break; - } - - if (*line).ut_type == USER_PROCESS { - let user = String::from_utf8_lossy(CStr::from_ptr(mem::transmute(&(*line).ut_user)).to_bytes()).to_string(); - users.push(user); - } - } - - endutxent(); - } - - if users.len() > 0 { - users.sort(); - println!("{}", users.join(" ")); - } -} diff --git a/src/uutils/uutils.rs b/src/uutils/uutils.rs deleted file mode 100644 index 934acede4..000000000 --- a/src/uutils/uutils.rs +++ /dev/null @@ -1,105 +0,0 @@ -#![crate_name = "uutils"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Michael Gehring - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -@CRATES@ - -use std::env; -use std::collections::hash_map::HashMap; -use std::path::Path; - -static NAME: &'static str = "uutils"; -static VERSION: &'static str = "1.0.0"; - -type UtilityMap = HashMap<&'static str, fn(Vec) -> i32>; - -fn util_map() -> UtilityMap { - let mut map: UtilityMap = HashMap::new(); - @UTIL_MAP@ - map -} - -fn usage(cmap: &UtilityMap) { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {} [util [arguments...]]\n", NAME); - println!("Currently defined functions:"); - let mut utils: Vec<&str> = cmap.keys().map(|&s| s).collect(); - utils.sort(); - for util in utils.iter() { - println!("\t{}", util); - } -} - -fn main() { - let umap = util_map(); - let mut args : Vec = env::args().collect(); - - // try binary name as util name. - let args0 = args[0].clone(); - let binary = Path::new(&args0[..]); - let binary_as_util = binary.file_name().unwrap().to_str().unwrap(); - - match umap.get(binary_as_util) { - Some(&uumain) => { - std::process::exit(uumain(args)); - } - None => (), - } - - if binary_as_util.ends_with("uutils") || binary_as_util.starts_with("uutils") || - binary_as_util.ends_with("busybox") || binary_as_util.starts_with("busybox") { - // uutils can be called as either "uutils", "busybox" - // "uutils-suffix" or "busybox-suffix". Not sure - // what busybox uses the -suffix pattern for. - } else { - println!("{}: applet not found", binary_as_util); - std::process::exit(1); - } - - // try first arg as util name. - if args.len() >= 2 { - args.remove(0); - let util = &args[0][..]; - - match umap.get(util) { - Some(&uumain) => { - std::process::exit(uumain(args.clone())); - } - None => { - if &args[0][..] == "--help" { - // see if they want help on a specific util - if args.len() >= 2 { - let util = &args[1][..]; - match umap.get(util) { - Some(&uumain) => { - std::process::exit(uumain(vec![util.to_string(), "--help".to_string()])); - } - None => { - println!("{}: applet not found", util); - std::process::exit(1); - } - } - } - usage(&umap); - std::process::exit(0); - } else { - println!("{}: applet not found", util); - std::process::exit(1); - } - } - } - } else { - // no arguments provided - usage(&umap); - std::process::exit(0); - } -} diff --git a/src/uutils/uutils_cargo.rs b/src/uutils/uutils_cargo.rs deleted file mode 100644 index 275459147..000000000 --- a/src/uutils/uutils_cargo.rs +++ /dev/null @@ -1,99 +0,0 @@ -#![crate_name = "uutils"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Michael Gehring - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -include!(concat!(env!("OUT_DIR"), "/uutils_crates.rs")); - -use std::env; -use std::collections::hash_map::HashMap; -use std::path::Path; - -static NAME: &'static str = "uutils"; -static VERSION: &'static str = "0.0.1"; - -include!(concat!(env!("OUT_DIR"), "/uutils_map.rs")); - -fn usage(cmap: &UtilityMap) { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {} [util [arguments...]]\n", NAME); - println!("Currently defined functions:"); - let mut utils: Vec<&str> = cmap.keys().map(|&s| s).collect(); - utils.sort(); - for util in utils.iter() { - println!("\t{}", util); - } -} - -fn main() { - let umap = util_map(); - let mut args : Vec = env::args().collect(); - - // try binary name as util name. - let args0 = args[0].clone(); - let binary = Path::new(&args0[..]); - let binary_as_util = binary.file_name().unwrap().to_str().unwrap(); - - match umap.get(binary_as_util) { - Some(&uumain) => { - std::process::exit(uumain(args)); - } - None => (), - } - - if binary_as_util.ends_with("uutils") || binary_as_util.starts_with("uutils") || - binary_as_util.ends_with("busybox") || binary_as_util.starts_with("busybox") { - // uutils can be called as either "uutils", "busybox" - // "uutils-suffix" or "busybox-suffix". Not sure - // what busybox uses the -suffix pattern for. - } else { - println!("{}: applet not found", binary_as_util); - std::process::exit(1); - } - - // try first arg as util name. - if args.len() >= 2 { - args.remove(0); - let util = &args[0][..]; - - match umap.get(util) { - Some(&uumain) => { - std::process::exit(uumain(args.clone())); - } - None => { - if &args[0][..] == "--help" { - // see if they want help on a specific util - if args.len() >= 2 { - let util = &args[1][..]; - match umap.get(util) { - Some(&uumain) => { - std::process::exit(uumain(vec![util.to_string(), "--help".to_string()])); - } - None => { - println!("{}: applet not found", util); - std::process::exit(1); - } - } - } - usage(&umap); - std::process::exit(0); - } else { - println!("{}: applet not found", util); - std::process::exit(1); - } - } - } - } else { - // no arguments provided - usage(&umap); - std::process::exit(0); - } -} diff --git a/src/wc/Cargo.toml b/src/wc/Cargo.toml deleted file mode 100644 index cb46772b6..000000000 --- a/src/wc/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "wc" -version = "0.0.1" -authors = [] - -[lib] -name = "wc" -path = "wc.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/wc/wc.rs b/src/wc/wc.rs deleted file mode 100644 index a4215b88c..000000000 --- a/src/wc/wc.rs +++ /dev/null @@ -1,284 +0,0 @@ -#![crate_name = "wc"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Boden Garman - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate getopts; -extern crate libc; - -use getopts::{Matches, Options}; -use std::ascii::AsciiExt; -use std::fs::File; -use std::io::{stdin, BufRead, BufReader, Read, Write}; -use std::path::Path; -use std::result::Result as StdResult; -use std::str::from_utf8; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -#[path = "../common/filesystem.rs"] -mod filesystem; - -use filesystem::UUPathExt; - -struct Settings { - show_bytes: bool, - show_chars: bool, - show_lines: bool, - show_words: bool, - show_max_line_length: bool, -} - -impl Settings { - fn new(matches: &Matches) -> Settings { - let settings = Settings { - show_bytes: matches.opt_present("bytes"), - show_chars: matches.opt_present("chars"), - show_lines: matches.opt_present("lines"), - show_words: matches.opt_present("words"), - show_max_line_length: matches.opt_present("L"), - }; - - if settings.show_bytes - || settings.show_chars - || settings.show_lines - || settings.show_words - || settings.show_max_line_length { - return settings; - } - - Settings { - show_bytes: true, - show_chars: false, - show_lines: true, - show_words: true, - show_max_line_length: false, - } - } -} - -struct Result { - title: String, - bytes: usize, - chars: usize, - lines: usize, - words: usize, - max_line_length: usize, -} - -static NAME: &'static str = "wc"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - - opts.optflag("c", "bytes", "print the byte counts"); - opts.optflag("m", "chars", "print the character counts"); - opts.optflag("l", "lines", "print the newline counts"); - opts.optflag("L", "max-line-length", "print the length of the longest line"); - opts.optflag("w", "words", "print the word counts"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let mut matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "Invalid options\n{}", f) - }; - - if matches.opt_present("help") { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {0} [OPTION]... [FILE]...", NAME); - println!(""); - println!("{}", opts.usage("Print newline, word and byte counts for each FILE")); - println!("With no FILE, or when FILE is -, read standard input."); - return 0; - } - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - if matches.free.is_empty() { - matches.free.push("-".to_string()); - } - - let settings = Settings::new(&matches); - - match wc(matches.free, &settings) { - Ok(()) => ( /* pass */ ), - Err(e) => return e - } - - 0 -} - -const CR: u8 = '\r' as u8; -const LF: u8 = '\n' as u8; -const SPACE: u8 = ' ' as u8; -const TAB: u8 = '\t' as u8; -const SYN: u8 = 0x16 as u8; -const FF: u8 = 0x0C as u8; - -#[inline(always)] -fn is_word_seperator(byte: u8) -> bool { - byte == SPACE || byte == TAB || byte == CR || byte == SYN || byte == FF -} - -fn wc(files: Vec, settings: &Settings) -> StdResult<(), i32> { - let mut total_line_count: usize = 0; - let mut total_word_count: usize = 0; - let mut total_char_count: usize = 0; - let mut total_byte_count: usize = 0; - let mut total_longest_line_length: usize = 0; - - let mut results = vec!(); - let mut max_width: usize = 0; - - for path in files.iter() { - let mut reader = try!(open(&path[..])); - - let mut line_count: usize = 0; - let mut word_count: usize = 0; - let mut byte_count: usize = 0; - let mut char_count: usize = 0; - let mut longest_line_length: usize = 0; - let mut raw_line = Vec::new(); - - // reading from a TTY seems to raise a condition on, rather than return Some(0) like a file. - // hence the option wrapped in a result here - while match reader.read_until(LF, &mut raw_line) { - Ok(n) if n > 0 => true, - Err(ref e) if raw_line.len() > 0 => { - show_warning!("Error while reading {}: {}", path, e); - raw_line.len() > 0 - }, - _ => false, - } { - // GNU 'wc' only counts lines that end in LF as lines - if *raw_line.last().unwrap() == LF { - line_count += 1; - } - - byte_count += raw_line.len(); - - // try and convert the bytes to UTF-8 first - let current_char_count; - match from_utf8(&raw_line[..]) { - Ok(line) => { - word_count += line.split_whitespace().count(); - current_char_count = line.chars().count(); - }, - Err(..) => { - word_count += raw_line.split(|&x| is_word_seperator(x)).count(); - current_char_count = raw_line.iter().filter(|c|c.is_ascii()).count() - } - } - char_count += current_char_count; - - if current_char_count > longest_line_length { - // we subtract one here because `line.len()` includes the LF - // matches GNU 'wc' behaviour - longest_line_length = current_char_count - 1; - } - - raw_line.truncate(0); - } - - results.push(Result { - title: path.to_string(), - bytes: byte_count, - chars: char_count, - lines: line_count, - words: word_count, - max_line_length: longest_line_length, - }); - - total_line_count += line_count; - total_word_count += word_count; - total_char_count += char_count; - total_byte_count += byte_count; - - if longest_line_length > total_longest_line_length { - total_longest_line_length = longest_line_length; - } - - // used for formatting - max_width = total_byte_count.to_string().len() + 1; - } - - for result in results.iter() { - print_stats(settings, &result, max_width); - } - - if files.len() > 1 { - let result = Result { - title: "total".to_string(), - bytes: total_byte_count, - chars: total_char_count, - lines: total_line_count, - words: total_word_count, - max_line_length: total_longest_line_length, - }; - print_stats(settings, &result, max_width); - } - - Ok(()) -} - -fn print_stats(settings: &Settings, result: &Result, max_width: usize) { - if settings.show_lines { - print!("{:1$}", result.lines, max_width); - } - if settings.show_words { - print!("{:1$}", result.words, max_width); - } - if settings.show_bytes { - print!("{:1$}", result.bytes, max_width); - } - if settings.show_chars { - print!("{:1$}", result.chars, max_width); - } - if settings.show_max_line_length { - print!("{:1$}", result.max_line_length, max_width); - } - - if result.title != "-" { - println!(" {}", result.title); - } - else { - println!(""); - } -} - -fn open(path: &str) -> StdResult>, i32> { - if "-" == path { - let reader = Box::new(stdin()) as Box; - return Ok(BufReader::new(reader)); - } - - let fpath = Path::new(path); - if fpath.uu_is_dir() { - show_info!("{}: is a directory", path); - } - match File::open(&fpath) { - Ok(fd) => { - let reader = Box::new(fd) as Box; - Ok(BufReader::new(reader)) - } - Err(e) => { - show_error!("wc: {}: {}", path, e); - Err(1) - } - } -} diff --git a/src/whoami/Cargo.toml b/src/whoami/Cargo.toml deleted file mode 100644 index 91ee10c24..000000000 --- a/src/whoami/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "whoami" -version = "0.0.1" -authors = [] - -[lib] -name = "whoami" -path = "whoami.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/whoami/deps.mk b/src/whoami/deps.mk deleted file mode 100644 index dab27f417..000000000 --- a/src/whoami/deps.mk +++ /dev/null @@ -1 +0,0 @@ -DEPLIBS += winapi advapi32 kernel32 diff --git a/src/whoami/platform/mod.rs b/src/whoami/platform/mod.rs deleted file mode 100644 index 12d85ec08..000000000 --- a/src/whoami/platform/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This file is part of the uutils coreutils package. - * - * (c) Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -#[cfg(unix)] -pub use self::unix::getusername; - -#[cfg(windows)] -pub use self::windows::getusername; - -#[cfg(unix)] -mod unix; - -#[cfg(windows)] -mod windows; diff --git a/src/whoami/platform/unix.rs b/src/whoami/platform/unix.rs deleted file mode 100644 index 009a7ef6b..000000000 --- a/src/whoami/platform/unix.rs +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of the uutils coreutils package. - * - * (c) Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use std::io::{Result, Error}; -use ::libc; -use self::c_types::{c_passwd, getpwuid}; - -#[path = "../../common/c_types.rs"] mod c_types; - -extern { - pub fn geteuid() -> libc::uid_t; -} - -pub unsafe fn getusername() -> Result { - // Get effective user id - let uid = geteuid(); - - // Try to find username for uid - let passwd: *const c_passwd = getpwuid(uid); - if passwd.is_null() { - return Err(Error::last_os_error()) - } - - // Extract username from passwd struct - let pw_name: *const libc::c_char = (*passwd).pw_name; - let username = String::from_utf8_lossy(::std::ffi::CStr::from_ptr(pw_name).to_bytes()).to_string(); - Ok(username) -} diff --git a/src/whoami/platform/windows.rs b/src/whoami/platform/windows.rs deleted file mode 100644 index 28d36cbfc..000000000 --- a/src/whoami/platform/windows.rs +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of the uutils coreutils package. - * - * (c) Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -extern crate winapi; -extern crate advapi32; - -use std::io::{Result, Error}; - -#[path = "../../common/wide.rs"] #[macro_use] mod wide; - -use std::mem; -use std::io::Write; -use std::ffi::OsString; -use std::os::windows::ffi::OsStringExt; -use self::wide::FromWide; - -pub unsafe fn getusername() -> Result { - let mut buffer: [winapi::WCHAR; winapi::UNLEN as usize + 1] = mem::uninitialized(); - let mut len = buffer.len() as winapi::DWORD; - if advapi32::GetUserNameW(buffer.as_mut_ptr(), &mut len) == 0 { - return Err(Error::last_os_error()) - } - let username = String::from_wide(&buffer[..len as usize - 1]); - Ok(username) -} diff --git a/src/whoami/whoami.rs b/src/whoami/whoami.rs deleted file mode 100644 index fbcf90f27..000000000 --- a/src/whoami/whoami.rs +++ /dev/null @@ -1,65 +0,0 @@ -#![crate_name = "whoami"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/* last synced with: whoami (GNU coreutils) 8.21 */ - -extern crate getopts; -extern crate libc; - -use getopts::Options; -use std::io::Write; - -#[path = "../common/util.rs"] #[macro_use] mod util; -mod platform; - -static NAME: &'static str = "whoami"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "{}", f), - }; - if matches.opt_present("help") { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {} [OPTIONS]", NAME); - println!(""); - println!("{}", opts.usage("print effective userid")); - return 0; - } - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - exec(); - - 0 -} - -pub fn exec() { - unsafe { - match platform::getusername() { - Ok(username) => println!("{}", username), - Err(err) => match err.raw_os_error() { - Some(0) | None => crash!(1, "failed to get username"), - Some(_) => crash!(1, "failed to get username: {}", err), - } - } - } -} diff --git a/src/yes/Cargo.toml b/src/yes/Cargo.toml deleted file mode 100644 index e5280f83e..000000000 --- a/src/yes/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "yes" -version = "0.0.1" -authors = [] - -[lib] -name = "yes" -path = "yes.rs" - -[dependencies] -getopts = "*" -libc = "*" diff --git a/src/yes/yes.rs b/src/yes/yes.rs deleted file mode 100644 index 52af0f53a..000000000 --- a/src/yes/yes.rs +++ /dev/null @@ -1,63 +0,0 @@ -#![crate_name = "yes"] - -/* - * This file is part of the uutils coreutils package. - * - * (c) Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/* last synced with: yes (GNU coreutils) 8.13 */ - -extern crate getopts; -extern crate libc; - -use getopts::Options; -use std::io::Write; - -#[path = "../common/util.rs"] -#[macro_use] -mod util; - -static NAME: &'static str = "yes"; -static VERSION: &'static str = "1.0.0"; - -pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "invalid options\n{}", f) - }; - if matches.opt_present("help") { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {0} [STRING]... [OPTION]...", NAME); - println!(""); - print!("{}", opts.usage("Repeatedly output a line with all specified STRING(s), or 'y'.")); - return 0; - } - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - let string = if matches.free.is_empty() { - "y".to_string() - } else { - matches.free.join(" ") - }; - - exec(&string[..]); - - 0 -} - -pub fn exec(string: &str) { - while pipe_println!("{}", string) { } -} diff --git a/test/base64.rs b/test/base64.rs deleted file mode 100644 index 106a42de5..000000000 --- a/test/base64.rs +++ /dev/null @@ -1,62 +0,0 @@ -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./base64"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_encode() { - let input = "hello, world!"; - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd, input.as_bytes()); - - assert_empty_stderr!(result); - assert!(result.success); - assert_eq!(result.stdout, "aGVsbG8sIHdvcmxkIQ==\n"); -} - -#[test] -fn test_decode() { - let input = "aGVsbG8sIHdvcmxkIQ=="; - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.arg("-d"), input.as_bytes()); - - assert_empty_stderr!(result); - assert!(result.success); - assert_eq!(result.stdout, "hello, world!"); -} - -#[test] -fn test_garbage() { - let input = "aGVsbG8sIHdvcmxkIQ==\0"; - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.arg("-d"), input.as_bytes()); - - assert!(!result.success); - assert_eq!(result.stderr, "base64: error: invalid character (Invalid character '0' at position 20)\n"); -} - -#[test] -fn test_ignore_garbage() { - let input = "aGVsbG8sIHdvcmxkIQ==\0"; - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.arg("-d").arg("-i"), input.as_bytes()); - - assert_empty_stderr!(result); - assert!(result.success); - assert_eq!(result.stdout, "hello, world!"); -} - -#[test] -fn test_wrap() { - let input = "The quick brown fox jumps over the lazy dog."; - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.arg("-w").arg("20"), input.as_bytes()); - - assert_empty_stderr!(result); - assert!(result.success); - assert_eq!(result.stdout, "VGhlIHF1aWNrIGJyb3du\nIGZveCBqdW1wcyBvdmVy\nIHRoZSBsYXp5IGRvZy4=\n"); -} diff --git a/test/basename.rs b/test/basename.rs deleted file mode 100644 index 6ecf224c0..000000000 --- a/test/basename.rs +++ /dev/null @@ -1,54 +0,0 @@ -use std::process::Command; -use std::str; - -static PROGNAME: &'static str = "./basename"; - -#[test] -fn test_directory() { - let dir = "/root/alpha/beta/gamma/delta/epsilon/omega/"; - let po = Command::new(PROGNAME) - .arg(dir) - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap().trim_right(); - assert_eq!(out, "omega"); -} - -#[test] -fn test_file() { - let file = "/etc/passwd"; - let po = Command::new(PROGNAME) - .arg(file) - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap().trim_right(); - assert_eq!(out, "passwd"); -} - -#[test] -fn test_remove_suffix() { - let path = "/usr/local/bin/reallylongexecutable.exe"; - let po = Command::new(PROGNAME) - .arg(path) - .arg(".exe") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap().trim_right(); - assert_eq!(out, "reallylongexecutable"); -} - -#[test] -fn test_dont_remove_suffix() { - let path = "/foo/bar/baz"; - let po = Command::new(PROGNAME) - .arg(path) - .arg("baz") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap().trim_right(); - assert_eq!(out, "baz"); -} diff --git a/test/cat.rs b/test/cat.rs deleted file mode 100644 index 41fdb9eb6..000000000 --- a/test/cat.rs +++ /dev/null @@ -1,60 +0,0 @@ -use std::io::Write; -use std::process::Command; -use std::process::Stdio; -use std::str; - -static PROGNAME: &'static str = "./cat"; - -#[test] -fn test_output_multi_files_print_all_chars() { - let po = match Command::new(PROGNAME) - .arg("alpha.txt") - .arg("256.txt") - .arg("-A") - .arg("-n").output() { - - Ok(p) => p, - Err(err) => panic!("{}", err), - }; - - let out = str::from_utf8(&po.stdout[..]).unwrap(); - assert_eq!(out, - " 1\tabcde$\n 2\tfghij$\n 3\tklmno$\n 4\tpqrst$\n 5\tuvwxyz$\n 6\t^@^A^B^C^D^E^F^G^H^I$\n 7\t^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\\^]^^^_ !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~^?M-^@M-^AM-^BM-^CM-^DM-^EM-^FM-^GM-^HM-^IM-^JM-^KM-^LM-^MM-^NM-^OM-^PM-^QM-^RM-^SM-^TM-^UM-^VM-^WM-^XM-^YM-^ZM-^[M-^\\M-^]M-^^M-^_M- M-!M-\"M-#M-$M-%M-&M-\'M-(M-)M-*M-+M-,M--M-.M-/M-0M-1M-2M-3M-4M-5M-6M-7M-8M-9M-:M-;M-M-?M-@M-AM-BM-CM-DM-EM-FM-GM-HM-IM-JM-KM-LM-MM-NM-OM-PM-QM-RM-SM-TM-UM-VM-WM-XM-YM-ZM-[M-\\M-]M-^M-_M-`M-aM-bM-cM-dM-eM-fM-gM-hM-iM-jM-kM-lM-mM-nM-oM-pM-qM-rM-sM-tM-uM-vM-wM-xM-yM-zM-{M-|M-}M-~M-^?"); -} - -#[test] -fn test_stdin_squeeze() { - let mut process = Command::new(PROGNAME) - .arg("-A") - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .unwrap_or_else(|e| panic!("{}", e)); - - process.stdin.take().unwrap_or_else(|| panic!("Could not grab child process stdin")) - .write_all("\x00\x01\x02".as_bytes()).unwrap_or_else(|e| panic!("{}", e)); - - let po = process.wait_with_output().unwrap_or_else(|e| panic!("{}", e)); - let out = str::from_utf8(&po.stdout[..]).unwrap_or_else(|e| panic!("{}", e)); - - assert_eq!(out, "^@^A^B"); -} - -#[test] -fn test_stdin_number_non_blank() { - let mut process = Command::new(PROGNAME) - .arg("-b") - .arg("-") - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .unwrap_or_else(|e| panic!("{}", e)); - - process.stdin.take().unwrap_or_else(|| panic!("Could not grab child process stdin")) - .write_all("\na\nb\n\n\nc".as_bytes()).unwrap_or_else(|e| panic!("{}", e)); - - let po = process.wait_with_output().unwrap_or_else(|e| panic!("{}", e)); - let out = str::from_utf8(&po.stdout[..]).unwrap_or_else(|e| panic!("{}", e)); - - assert_eq!(out, "\n 1\ta\n 2\tb\n\n\n 3\tc"); -} diff --git a/test/cksum.rs b/test/cksum.rs deleted file mode 100644 index c5ecdf3be..000000000 --- a/test/cksum.rs +++ /dev/null @@ -1,39 +0,0 @@ -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./cksum"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_single_file() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.arg("lorem_ipsum.txt")); - - assert_empty_stderr!(result); - assert!(result.success); - assert_eq!(result.stdout, get_file_contents("single_file.expected")); -} - -#[test] -fn test_multiple_files() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.arg("lorem_ipsum.txt").arg("alice_in_wonderland.txt")); - - assert_empty_stderr!(result); - assert!(result.success); - assert_eq!(result.stdout, get_file_contents("multiple_files.expected")); -} - -#[test] -fn test_stdin() { - let input = get_file_contents("lorem_ipsum.txt"); - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd, input); - - assert_empty_stderr!(result); - assert!(result.success); - assert_eq!(result.stdout, get_file_contents("stdin.expected")); -} diff --git a/test/common/util.rs b/test/common/util.rs deleted file mode 100644 index cb4a99c83..000000000 --- a/test/common/util.rs +++ /dev/null @@ -1,152 +0,0 @@ -#![allow(dead_code)] - -use std::env; -use std::fs::{self, File}; -use std::io::{Read, Write}; -#[cfg(unix)] -use std::os::unix::fs::symlink as symlink_file; -#[cfg(windows)] -use std::os::windows::fs::symlink_file; -use std::path::Path; -use std::process::{Command, Stdio}; -use std::str::from_utf8; - -#[macro_export] -macro_rules! assert_empty_stderr( - ($cond:expr) => ( - if $cond.stderr.len() > 0 { - panic!(format!("stderr: {}", $cond.stderr)) - } - ); -); - -pub struct CmdResult { - pub success: bool, - pub stdout: String, - pub stderr: String, -} - -pub fn run(cmd: &mut Command) -> CmdResult { - let prog = cmd.output().unwrap(); - CmdResult { - success: prog.status.success(), - stdout: from_utf8(&prog.stdout).unwrap().to_string(), - stderr: from_utf8(&prog.stderr).unwrap().to_string(), - } -} - -pub fn run_piped_stdin>(cmd: &mut Command, input: T)-> CmdResult { - let mut command = cmd - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn() - .unwrap(); - - command.stdin - .take() - .unwrap_or_else(|| panic!("Could not take child process stdin")) - .write_all(input.as_ref()) - .unwrap_or_else(|e| panic!("{}", e)); - - let prog = command.wait_with_output().unwrap(); - CmdResult { - success: prog.status.success(), - stdout: from_utf8(&prog.stdout).unwrap().to_string(), - stderr: from_utf8(&prog.stderr).unwrap().to_string(), - } -} - -pub fn get_file_contents(name: &str) -> String { - let mut f = File::open(Path::new(name)).unwrap(); - let mut contents = String::new(); - let _ = f.read_to_string(&mut contents); - contents -} - -pub fn set_file_contents(name: &str, contents: &str) { - let mut f = File::open(Path::new(name)).unwrap(); - let _ = f.write(contents.as_bytes()); -} - -pub fn mkdir(dir: &str) { - fs::create_dir(Path::new(dir)).unwrap(); -} - -pub fn mkdir_all(dir: &str) { - fs::create_dir_all(Path::new(dir)).unwrap(); -} - -pub fn make_file(name: &str) -> File { - match File::create(Path::new(name)) { - Ok(f) => f, - Err(e) => panic!("{}", e) - } -} - -pub fn touch(file: &str) { - File::create(Path::new(file)).unwrap(); -} - -pub fn symlink(src: &str, dst: &str) { - symlink_file(src, dst).unwrap(); -} - -pub fn is_symlink(path: &str) -> bool { - match fs::symlink_metadata(path) { - Ok(m) => m.file_type().is_symlink(), - Err(_) => false - } -} - -pub fn resolve_link(path: &str) -> String { - match fs::read_link(path) { - Ok(p) => p.to_str().unwrap().to_owned(), - Err(_) => "".to_string() - } -} - -pub fn metadata(path: &str) -> fs::Metadata { - match fs::metadata(path) { - Ok(m) => m, - Err(e) => panic!("{}", e) - } -} - -pub fn file_exists(path: &str) -> bool { - match fs::metadata(path) { - Ok(m) => m.is_file(), - Err(_) => false - } -} - -pub fn dir_exists(path: &str) -> bool { - match fs::metadata(path) { - Ok(m) => m.is_dir(), - Err(_) => false - } -} - -pub fn cleanup(path: &'static str) { - let p = Path::new(path); - match fs::metadata(p) { - Ok(m) => if m.is_file() { - fs::remove_file(&p).unwrap(); - } else { - fs::remove_dir(&p).unwrap(); - }, - Err(_) => {} - } -} - -pub fn current_directory() -> String { - env::current_dir().unwrap().into_os_string().into_string().unwrap() -} - -pub fn repeat_str(s: &str, n: u32) -> String { - let mut repeated = String::new(); - for _ in 0 .. n { - repeated.push_str(s); - } - repeated -} diff --git a/test/cp.rs b/test/cp.rs deleted file mode 100644 index d82c9af49..000000000 --- a/test/cp.rs +++ /dev/null @@ -1,35 +0,0 @@ -use std::fs::File; -use std::io::Read; -use std::path::Path; -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./cp"; -static TEST_HELLO_WORLD_SOURCE: &'static str = "hello_world.txt"; -static TEST_HELLO_WORLD_DEST: &'static str = "copy_of_hello_world.txt"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_cp_cp() { - // Invoke our binary to make the copy. - let prog = Command::new(PROGNAME) - .arg(TEST_HELLO_WORLD_SOURCE) - .arg(TEST_HELLO_WORLD_DEST) - .status(); - - // Check that the exit code represents a successful copy. - let exit_success = prog.unwrap().success(); - assert_eq!(exit_success, true); - - // Check the content of the destination file that was copied. - let mut contents = String::new(); - let mut f = File::open(Path::new(TEST_HELLO_WORLD_DEST)).unwrap(); - let _ = f.read_to_string(&mut contents); - assert_eq!(contents, "Hello, World!\n"); - - cleanup(TEST_HELLO_WORLD_SOURCE); - cleanup(TEST_HELLO_WORLD_DEST); -} diff --git a/test/cut.rs b/test/cut.rs deleted file mode 100644 index baf32b9f0..000000000 --- a/test/cut.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./cut"; -static INPUT: &'static str = "lists.txt"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_prefix() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-c", "-10", INPUT])); - assert_eq!(result.stdout, get_file_contents("lists_prefix.expected")); -} - -#[test] -fn test_char_range() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-c", "4-10", INPUT])); - assert_eq!(result.stdout, get_file_contents("lists_char_range.expected")); -} - -#[test] -fn test_column_to_end_of_line() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-d", ":", "-f", "5-", INPUT])); - assert_eq!(result.stdout, get_file_contents("lists_column_to_end_of_line.expected")); -} - -#[test] -fn test_specific_field() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-d", " ", "-f", "3", INPUT])); - assert_eq!(result.stdout, get_file_contents("lists_specific_field.expected")); -} - -#[test] -fn test_multiple_fields() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-d", ":", "-f", "1,3", INPUT])); - assert_eq!(result.stdout, get_file_contents("lists_multiple_fields.expected")); -} - -#[test] -fn test_tail() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-d", ":", "--complement", "-f", "1", INPUT])); - assert_eq!(result.stdout, get_file_contents("lists_tail.expected")); -} - -#[test] -fn test_change_delimiter() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-d", ":", "--complement", "--output-delimiter=#", "-f", "1", INPUT])); - assert_eq!(result.stdout, get_file_contents("lists_change_delimiter.expected")); -} diff --git a/test/dirname.rs b/test/dirname.rs deleted file mode 100644 index f0309ce9e..000000000 --- a/test/dirname.rs +++ /dev/null @@ -1,28 +0,0 @@ -use std::process::Command; -use std::str; - -static PROGNAME: &'static str = "./dirname"; - -#[test] -fn test_path_with_trailing_slashes() { - let dir = "/root/alpha/beta/gamma/delta/epsilon/omega//"; - let po = Command::new(PROGNAME) - .arg(dir) - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap().trim_right(); - assert_eq!(out, "/root/alpha/beta/gamma/delta/epsilon"); -} - -#[test] -fn test_path_without_trailing_slashes() { - let dir = "/root/alpha/beta/gamma/delta/epsilon/omega"; - let po = Command::new(PROGNAME) - .arg(dir) - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap().trim_right(); - assert_eq!(out, "/root/alpha/beta/gamma/delta/epsilon"); -} diff --git a/test/echo.rs b/test/echo.rs deleted file mode 100644 index b107fd4c4..000000000 --- a/test/echo.rs +++ /dev/null @@ -1,50 +0,0 @@ -use std::process::Command; -use std::str; - -static PROGNAME: &'static str = "./echo"; - -#[test] -fn test_default() { - let po = Command::new(PROGNAME) - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap(); - assert_eq!(out, "\n"); -} - -#[test] -fn test_no_trailing_newline() { - let po = Command::new(PROGNAME) - .arg("-n") - .arg("hello_world") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap(); - assert_eq!(out, "hello_world"); -} - -#[test] -fn test_enable_escapes() { - let po = Command::new(PROGNAME) - .arg("-e") - .arg("\\\\\\t\\r") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap(); - assert_eq!(out, "\\\t\r\n"); -} - -#[test] -fn test_disable_escapes() { - let po = Command::new(PROGNAME) - .arg("-E") - .arg("\\b\\c\\e") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap(); - assert_eq!(out, "\\b\\c\\e\n"); -} diff --git a/test/env.rs b/test/env.rs deleted file mode 100644 index aa2825f29..000000000 --- a/test/env.rs +++ /dev/null @@ -1,74 +0,0 @@ -use std::process::Command; -use std::str; - -static PROGNAME: &'static str = "./env"; - -#[test] -fn test_single_name_value_pair() { - let po = Command::new(PROGNAME) - .arg("FOO=bar") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap(); - assert!(out.lines().any(|line| line == "FOO=bar")); -} - -#[test] -fn test_multiple_name_value_pairs() { - let po = Command::new(PROGNAME) - .arg("FOO=bar") - .arg("ABC=xyz") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap(); - assert_eq!(out.lines().filter(|&line| line == "FOO=bar" || line == "ABC=xyz").count(), 2); -} - -#[test] -fn test_ignore_environment() { - let po = Command::new(PROGNAME) - .arg("-i") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap(); - assert_eq!(out, ""); - - let po = Command::new(PROGNAME) - .arg("-") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap(); - assert_eq!(out, ""); -} - -#[test] -fn test_null_delimiter() { - let po = Command::new(PROGNAME) - .arg("-i") - .arg("--null") - .arg("FOO=bar") - .arg("ABC=xyz") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap(); - assert_eq!(out, "FOO=bar\0ABC=xyz\0"); -} - -#[test] -fn test_unset_variable() { - // This test depends on the HOME variable being pre-defined by the - // default shell - let po = Command::new(PROGNAME) - .arg("-u") - .arg("HOME") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap(); - assert_eq!(out.lines().any(|line| line.starts_with("HOME=")), false); -} diff --git a/test/factor.rs b/test/factor.rs deleted file mode 100644 index 6eadf3469..000000000 --- a/test/factor.rs +++ /dev/null @@ -1,534 +0,0 @@ -/* -* This file is part of the uutils coreutils package. -* -* (c) kwantam -* -* For the full copyright and license information, please view the LICENSE file -* that was distributed with this source code. -*/ - -extern crate libc; -extern crate rand; - -use rand::{weak_rng, Rng}; -use rand::distributions::{IndependentSample, Range}; -use sieve::Sieve; -use std::io::Write; -use std::process::{Command, Stdio}; - -#[path="../src/factor/sieve.rs"] -mod sieve; - -const NUM_PRIMES: usize = 10000; -const LOG_PRIMES: f64 = 14.0; // ceil(log2(NUM_PRIMES)) - -const NUM_TESTS: usize = 100; -const PROGNAME: &'static str = "./factor"; - -#[test] -fn test_random() { - let primes = Sieve::primes().take(NUM_PRIMES).collect::>(); - - let mut rng = weak_rng(); - let mut rand_gt = move |min: u64| { - let mut product = 1u64; - let mut factors = Vec::new(); - while product < min { - // log distribution---higher probability for lower numbers - let factor; - loop { - let next = rng.gen_range(0f64, LOG_PRIMES).exp2().floor() as usize; - if next < NUM_PRIMES { - factor = primes[next]; - break; - } - } - let factor = factor; - - match product.checked_mul(factor) { - Some(p) => { - product = p; - factors.push(factor); - }, - None => break, - }; - } - - factors.sort(); - (product, factors) - }; - - // build an input and expected output string from factor - let mut instring = String::new(); - let mut outstring = String::new(); - for _ in 0..NUM_TESTS { - let (product, factors) = rand_gt(1 << 63); - instring.push_str(&(format!("{} ", product))[..]); - - outstring.push_str(&(format!("{}:", product))[..]); - for factor in factors { - outstring.push_str(&(format!(" {}", factor))[..]); - } - outstring.push_str("\n"); - } - - run(instring.as_bytes(), outstring.as_bytes()); -} - -#[test] -fn test_random_big() { - let mut rng = weak_rng(); - let bitrange_1 = Range::new(14usize, 51); - let mut rand_64 = move || { - // first, choose a random number of bits for the first factor - let f_bit_1 = bitrange_1.ind_sample(&mut rng); - // how many more bits do we need? - let rem = 64 - f_bit_1; - - // we will have a number of additional factors equal to nfacts + 1 - // where nfacts is in [0, floor(rem/14) ) NOTE half-open interval - // Each prime factor is at least 14 bits, hence floor(rem/14) - let nfacts = Range::new(0usize, rem / 14).ind_sample(&mut rng); - // we have to distribute extrabits among the (nfacts + 1) values - let extrabits = rem - (nfacts + 1) * 14; - // (remember, a Range is a half-open interval) - let extrarange = Range::new(0usize, extrabits + 1); - - // to generate an even split of this range, generate n-1 random elements - // in the range, add the desired total value to the end, sort this list, - // and then compute the sequential differences. - let mut f_bits = Vec::new(); - for _ in 0..nfacts { - f_bits.push(extrarange.ind_sample(&mut rng)); - } - f_bits.push(extrabits); - f_bits.sort(); - - // compute sequential differences here. We leave off the +14 bits - // so we can just index PRIMES_BY_BITS - let mut f_bits = f_bits.iter().scan(0, |st,&x| { - let ret = x - *st; // + 14 would give actual number of bits - *st = x; - Some(ret) - }).collect::>(); - // finally, add f_bit_1 in there - f_bits.push(f_bit_1 - 14); // index of f_bit_1 in PRIMES_BY_BITS - let f_bits = f_bits; - - let mut nbits = 0; - let mut product = 1u64; - let mut factors = Vec::new(); - for bit in f_bits { - assert!(bit < 37); - nbits += 14 + bit; - let elm = Range::new(0, PRIMES_BY_BITS[bit].len()).ind_sample(&mut rng); - let factor = PRIMES_BY_BITS[bit][elm]; - factors.push(factor); - product *= factor; - } - assert_eq!(nbits, 64); - - factors.sort(); - (product, factors) - }; - - let mut instring = String::new(); - let mut outstring = String::new(); - for _ in 0..NUM_TESTS { - let (product, factors) = rand_64(); - instring.push_str(&(format!("{} ", product))[..]); - - outstring.push_str(&(format!("{}:", product))[..]); - for factor in factors { - outstring.push_str(&(format!(" {}", factor))[..]); - } - outstring.push_str("\n"); - } - - run(instring.as_bytes(), outstring.as_bytes()); -} - -#[test] -fn test_big_primes() { - let mut instring = String::new(); - let mut outstring = String::new(); - for prime in PRIMES64 { - instring.push_str(&(format!("{} ", prime))[..]); - outstring.push_str(&(format!("{0}: {0}\n", prime))[..]); - } - - run(instring.as_bytes(), outstring.as_bytes()); -} - -fn run(instring: &[u8], outstring: &[u8]) { - // now run factor - let mut process = Command::new(PROGNAME) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .unwrap_or_else(|e| panic!("{}", e)); - - process.stdin.take().unwrap_or_else(|| panic!("Could not take child process stdin")) - .write_all(instring).unwrap_or_else(|e| panic!("{}", e)); - - let output = process.wait_with_output().unwrap_or_else(|e| panic!("{}", e)); - assert_eq!(&output.stdout[..], outstring); -} - -const PRIMES_BY_BITS: &'static [&'static [u64]] = &[PRIMES14, PRIMES15, PRIMES16, PRIMES17, - PRIMES18, PRIMES19, PRIMES20, PRIMES21, PRIMES22, PRIMES23, PRIMES24, PRIMES25, PRIMES26, - PRIMES27, PRIMES28, PRIMES29, PRIMES30, PRIMES31, PRIMES32, PRIMES33, PRIMES34, PRIMES35, - PRIMES36, PRIMES37, PRIMES38, PRIMES39, PRIMES40, PRIMES41, PRIMES42, PRIMES43, PRIMES44, - PRIMES45, PRIMES46, PRIMES47, PRIMES48, PRIMES49, PRIMES50, -]; - -const PRIMES64: &'static [u64] = &[18446744073709551557, 18446744073709551533, - 18446744073709551521, 18446744073709551437, 18446744073709551427, 18446744073709551359, - 18446744073709551337, 18446744073709551293, 18446744073709551263, 18446744073709551253, - 18446744073709551191, 18446744073709551163, 18446744073709551113, 18446744073709550873, - 18446744073709550791, 18446744073709550773, 18446744073709550771, 18446744073709550719, - 18446744073709550717, 18446744073709550681, 18446744073709550671, 18446744073709550593, - 18446744073709550591, 18446744073709550539, 18446744073709550537, 18446744073709550381, - 18446744073709550341, 18446744073709550293, 18446744073709550237, 18446744073709550147, - 18446744073709550141, 18446744073709550129, 18446744073709550111, 18446744073709550099, - 18446744073709550047, 18446744073709550033, 18446744073709550009, 18446744073709549951, - 18446744073709549861, 18446744073709549817, 18446744073709549811, 18446744073709549777, - 18446744073709549757, 18446744073709549733, 18446744073709549667, 18446744073709549621, - 18446744073709549613, 18446744073709549583, 18446744073709549571, -]; - -const PRIMES14: &'static [u64] = &[16381, 16369, 16363, 16361, 16349, 16339, 16333, 16319, - 16301, 16273, 16267, 16253, 16249, 16231, 16229, 16223, 16217, 16193, 16189, 16187, 16183, - 16141, 16139, 16127, 16111, 16103, 16097, 16091, 16087, 16073, 16069, 16067, 16063, 16061, - 16057, 16033, 16007, 16001, 15991, 15973, 15971, 15959, 15937, 15923, 15919, 15913, 15907, - 15901, 15889, 15887, 15881, 15877, 15859, 15823, 15817, 15809, 15803, 15797, 15791, 15787, - 15773, 15767, 15761, 15749, 15739, 15737, 15733, 15731, 15727, 15683, 15679, 15671, 15667, - 15661, 15649, 15647, 15643, 15641, 15629, 15619, 15607, 15601, 15583, 15581, 15569, 15559, - 15551, 15541, 15527, 15511, 15497, 15493, 15473, 15467, 15461, 15451, 15443, 15439, 15427, - 15413, 15401, 15391, 15383, 15377, 15373, -]; - -const PRIMES15: &'static [u64] = &[32749, 32719, 32717, 32713, 32707, 32693, 32687, 32653, - 32647, 32633, 32621, 32611, 32609, 32603, 32587, 32579, 32573, 32569, 32563, 32561, 32537, - 32533, 32531, 32507, 32503, 32497, 32491, 32479, 32467, 32443, 32441, 32429, 32423, 32413, - 32411, 32401, 32381, 32377, 32371, 32369, 32363, 32359, 32353, 32341, 32327, 32323, 32321, - 32309, 32303, 32299, 32297, 32261, 32257, 32251, 32237, 32233, 32213, 32203, 32191, 32189, - 32183, 32173, 32159, 32143, 32141, 32119, 32117, 32099, 32089, 32083, 32077, 32069, 32063, - 32059, 32057, 32051, 32029, 32027, 32009, 32003, 31991, 31981, 31973, 31963, 31957, 31907, - 31891, 31883, 31873, 31859, 31849, 31847, 31817, 31799, 31793, 31771, 31769, 31751, -]; - -const PRIMES16: &'static [u64] = &[65521, 65519, 65497, 65479, 65449, 65447, 65437, 65423, - 65419, 65413, 65407, 65393, 65381, 65371, 65357, 65353, 65327, 65323, 65309, 65293, 65287, - 65269, 65267, 65257, 65239, 65213, 65203, 65183, 65179, 65173, 65171, 65167, 65147, 65141, - 65129, 65123, 65119, 65111, 65101, 65099, 65089, 65071, 65063, 65053, 65033, 65029, 65027, - 65011, 65003, 64997, 64969, 64951, 64937, 64927, 64921, 64919, 64901, 64891, 64879, 64877, - 64871, 64853, 64849, 64817, 64811, 64793, 64783, 64781, 64763, 64747, 64717, 64709, 64693, - 64679, 64667, 64663, 64661, 64633, 64627, 64621, 64613, 64609, 64601, 64591, 64579, 64577, - 64567, 64553, -]; - -const PRIMES17: &'static [u64] = &[131071, 131063, 131059, 131041, 131023, 131011, 131009, - 130987, 130981, 130973, 130969, 130957, 130927, 130873, 130859, 130843, 130841, 130829, - 130817, 130811, 130807, 130787, 130783, 130769, 130729, 130699, 130693, 130687, 130681, - 130657, 130651, 130649, 130643, 130639, 130633, 130631, 130621, 130619, 130589, 130579, - 130553, 130547, 130531, 130523, 130517, 130513, 130489, 130483, 130477, 130469, 130457, - 130447, 130439, 130423, 130411, 130409, 130399, 130379, 130369, 130367, 130363, 130349, - 130343, 130337, 130307, 130303, 130279, 130267, 130261, 130259, 130253, 130241, 130223, - 130211, 130201, 130199, 130183, 130171, 130147, 130127, 130121, 130099, 130087, 130079, - 130073, 130069, 130057, 130051, -]; - -const PRIMES18: &'static [u64] = &[262139, 262133, 262127, 262121, 262111, 262109, 262103, - 262079, 262069, 262051, 262049, 262027, 262007, 261983, 261977, 261973, 261971, 261959, - 261917, 261887, 261881, 261847, 261823, 261799, 261791, 261787, 261773, 261761, 261757, - 261739, 261721, 261713, 261707, 261697, 261673, 261643, 261641, 261637, 261631, 261619, - 261601, 261593, 261587, 261581, 261577, 261563, 261557, 261529, 261523, 261509, 261467, - 261463, 261451, 261439, 261433, 261431, 261427, 261407, 261389, 261379, 261353, 261347, - 261337, 261329, 261323, 261301, 261281, 261271, 261251, 261241, 261229, 261223, 261169, - 261167, 261127, -]; - -const PRIMES19: &'static [u64] = &[524287, 524269, 524261, 524257, 524243, 524231, 524221, - 524219, 524203, 524201, 524197, 524189, 524171, 524149, 524123, 524119, 524113, 524099, - 524087, 524081, 524071, 524063, 524057, 524053, 524047, 523997, 523987, 523969, 523949, - 523937, 523927, 523907, 523903, 523877, 523867, 523847, 523829, 523801, 523793, 523777, - 523771, 523763, 523759, 523741, 523729, 523717, 523681, 523673, 523669, 523667, 523657, - 523639, 523637, 523631, 523603, 523597, 523577, 523573, 523571, 523553, 523543, 523541, - 523519, 523511, 523493, 523489, 523487, 523463, 523459, 523433, 523427, 523417, 523403, - 523387, 523357, 523351, 523349, 523333, 523307, 523297, -]; - -const PRIMES20: &'static [u64] = &[1048573, 1048571, 1048559, 1048549, 1048517, 1048507, - 1048447, 1048433, 1048423, 1048391, 1048387, 1048367, 1048361, 1048357, 1048343, 1048309, - 1048291, 1048273, 1048261, 1048219, 1048217, 1048213, 1048193, 1048189, 1048139, 1048129, - 1048127, 1048123, 1048063, 1048051, 1048049, 1048043, 1048027, 1048013, 1048009, 1048007, - 1047997, 1047989, 1047979, 1047971, 1047961, 1047941, 1047929, 1047923, 1047887, 1047883, - 1047881, 1047859, 1047841, 1047833, 1047821, 1047779, 1047773, 1047763, 1047751, 1047737, - 1047721, 1047713, 1047703, 1047701, 1047691, 1047689, 1047671, 1047667, 1047653, 1047649, - 1047647, 1047589, 1047587, 1047559, -]; - -const PRIMES21: &'static [u64] = &[2097143, 2097133, 2097131, 2097097, 2097091, 2097083, - 2097047, 2097041, 2097031, 2097023, 2097013, 2096993, 2096987, 2096971, 2096959, 2096957, - 2096947, 2096923, 2096911, 2096909, 2096893, 2096881, 2096873, 2096867, 2096851, 2096837, - 2096807, 2096791, 2096789, 2096777, 2096761, 2096741, 2096737, 2096713, 2096693, 2096687, - 2096681, 2096639, 2096629, 2096621, 2096599, 2096597, 2096569, 2096539, 2096533, 2096483, - 2096449, 2096431, 2096429, 2096411, 2096407, 2096401, 2096399, 2096377, 2096357, 2096291, - 2096273, 2096261, 2096233, 2096231, 2096221, 2096209, 2096191, 2096183, 2096147, -]; - -const PRIMES22: &'static [u64] = &[4194301, 4194287, 4194277, 4194271, 4194247, 4194217, - 4194199, 4194191, 4194187, 4194181, 4194173, 4194167, 4194143, 4194137, 4194131, 4194107, - 4194103, 4194023, 4194011, 4194007, 4193977, 4193971, 4193963, 4193957, 4193939, 4193929, - 4193909, 4193869, 4193807, 4193803, 4193801, 4193789, 4193759, 4193753, 4193743, 4193701, - 4193663, 4193633, 4193573, 4193569, 4193551, 4193549, 4193531, 4193513, 4193507, 4193459, - 4193447, 4193443, 4193417, 4193411, 4193393, 4193389, 4193381, 4193377, 4193369, 4193359, - 4193353, 4193327, 4193309, 4193303, 4193297, -]; - -const PRIMES23: &'static [u64] = &[8388593, 8388587, 8388581, 8388571, 8388547, 8388539, - 8388473, 8388461, 8388451, 8388449, 8388439, 8388427, 8388421, 8388409, 8388377, 8388371, - 8388319, 8388301, 8388287, 8388283, 8388277, 8388239, 8388209, 8388187, 8388113, 8388109, - 8388091, 8388071, 8388059, 8388019, 8388013, 8387999, 8387993, 8387959, 8387957, 8387947, - 8387933, 8387921, 8387917, 8387891, 8387879, 8387867, 8387861, 8387857, 8387839, 8387831, - 8387809, 8387807, 8387741, 8387737, 8387723, 8387707, 8387671, 8387611, 8387609, 8387591, -]; - -const PRIMES24: &'static [u64] = &[16777213, 16777199, 16777183, 16777153, 16777141, 16777139, - 16777127, 16777121, 16777099, 16777049, 16777027, 16776989, 16776973, 16776971, 16776967, - 16776961, 16776941, 16776937, 16776931, 16776919, 16776901, 16776899, 16776869, 16776857, - 16776839, 16776833, 16776817, 16776763, 16776731, 16776719, 16776713, 16776691, 16776689, - 16776679, 16776659, 16776631, 16776623, 16776619, 16776607, 16776593, 16776581, 16776547, - 16776521, 16776491, 16776481, 16776469, 16776451, 16776401, 16776391, 16776379, 16776371, - 16776367, 16776343, 16776337, 16776317, 16776313, 16776289, 16776217, 16776211, -]; - -const PRIMES25: &'static [u64] = &[33554393, 33554383, 33554371, 33554347, 33554341, 33554317, - 33554291, 33554273, 33554267, 33554249, 33554239, 33554221, 33554201, 33554167, 33554159, - 33554137, 33554123, 33554093, 33554083, 33554077, 33554051, 33554021, 33554011, 33554009, - 33553999, 33553991, 33553969, 33553967, 33553909, 33553901, 33553879, 33553837, 33553799, - 33553787, 33553771, 33553769, 33553759, 33553747, 33553739, 33553727, 33553697, 33553693, - 33553679, 33553661, 33553657, 33553651, 33553649, 33553633, 33553613, 33553607, 33553577, - 33553549, 33553547, 33553537, 33553519, 33553517, 33553511, 33553489, 33553463, 33553451, - 33553417, -]; - -const PRIMES26: &'static [u64] = &[67108859, 67108837, 67108819, 67108777, 67108763, - 67108757, 67108753, 67108747, 67108739, 67108729, 67108721, 67108709, 67108693, 67108669, - 67108667, 67108661, 67108649, 67108633, 67108597, 67108579, 67108529, 67108511, 67108507, - 67108493, 67108471, 67108463, 67108453, 67108439, 67108387, 67108373, 67108369, 67108351, - 67108331, 67108313, 67108303, 67108289, 67108271, 67108219, 67108207, 67108201, 67108199, - 67108187, 67108183, 67108177, 67108127, 67108109, 67108081, 67108049, 67108039, 67108037, - 67108033, 67108009, 67108007, 67108003, 67107983, 67107977, 67107967, 67107941, 67107919, - 67107913, 67107883, 67107881, 67107871, 67107863, -]; - -const PRIMES27: &'static [u64] = &[134217689, 134217649, 134217617, 134217613, 134217593, - 134217541, 134217529, 134217509, 134217497, 134217493, 134217487, 134217467, 134217439, - 134217437, 134217409, 134217403, 134217401, 134217367, 134217361, 134217353, 134217323, - 134217301, 134217277, 134217257, 134217247, 134217221, 134217199, 134217173, 134217163, - 134217157, 134217131, 134217103, 134217089, 134217079, 134217049, 134217047, 134217043, - 134217001, 134216987, 134216947, 134216939, 134216933, 134216911, 134216899, 134216881, - 134216869, 134216867, 134216861, 134216837, 134216827, 134216807, 134216801, 134216791, - 134216783, 134216777, 134216759, 134216737, 134216729, -]; - -const PRIMES28: &'static [u64] = &[268435399, 268435367, 268435361, 268435337, 268435331, - 268435313, 268435291, 268435273, 268435243, 268435183, 268435171, 268435157, 268435147, - 268435133, 268435129, 268435121, 268435109, 268435091, 268435067, 268435043, 268435039, - 268435033, 268435019, 268435009, 268435007, 268434997, 268434979, 268434977, 268434961, - 268434949, 268434941, 268434937, 268434857, 268434841, 268434827, 268434821, 268434787, - 268434781, 268434779, 268434773, 268434731, 268434721, 268434713, 268434707, 268434703, - 268434697, 268434659, 268434623, 268434619, 268434581, 268434577, 268434563, 268434557, - 268434547, 268434511, 268434499, 268434479, 268434461, -]; - -const PRIMES29: &'static [u64] = &[536870909, 536870879, 536870869, 536870849, 536870839, - 536870837, 536870819, 536870813, 536870791, 536870779, 536870767, 536870743, 536870729, - 536870723, 536870717, 536870701, 536870683, 536870657, 536870641, 536870627, 536870611, - 536870603, 536870599, 536870573, 536870569, 536870563, 536870561, 536870513, 536870501, - 536870497, 536870473, 536870401, 536870363, 536870317, 536870303, 536870297, 536870273, - 536870267, 536870239, 536870233, 536870219, 536870171, 536870167, 536870153, 536870123, - 536870063, 536870057, 536870041, 536870027, 536869999, 536869951, 536869943, 536869937, - 536869919, 536869901, 536869891, -]; - -const PRIMES30: &'static [u64] = &[1073741789, 1073741783, 1073741741, 1073741723, 1073741719, - 1073741717, 1073741689, 1073741671, 1073741663, 1073741651, 1073741621, 1073741567, 1073741561, - 1073741527, 1073741503, 1073741477, 1073741467, 1073741441, 1073741419, 1073741399, 1073741387, - 1073741381, 1073741371, 1073741329, 1073741311, 1073741309, 1073741287, 1073741237, 1073741213, - 1073741197, 1073741189, 1073741173, 1073741101, 1073741077, 1073741047, 1073740963, 1073740951, - 1073740933, 1073740909, 1073740879, 1073740853, 1073740847, 1073740819, 1073740807, -]; - -const PRIMES31: &'static [u64] = &[2147483647, 2147483629, 2147483587, 2147483579, 2147483563, - 2147483549, 2147483543, 2147483497, 2147483489, 2147483477, 2147483423, 2147483399, 2147483353, - 2147483323, 2147483269, 2147483249, 2147483237, 2147483179, 2147483171, 2147483137, 2147483123, - 2147483077, 2147483069, 2147483059, 2147483053, 2147483033, 2147483029, 2147482951, 2147482949, - 2147482943, 2147482937, 2147482921, 2147482877, 2147482873, 2147482867, 2147482859, 2147482819, - 2147482817, 2147482811, 2147482801, 2147482763, 2147482739, 2147482697, 2147482693, 2147482681, - 2147482663, 2147482661, -]; - -const PRIMES32: &'static [u64] = &[4294967291, 4294967279, 4294967231, 4294967197, 4294967189, - 4294967161, 4294967143, 4294967111, 4294967087, 4294967029, 4294966997, 4294966981, 4294966943, - 4294966927, 4294966909, 4294966877, 4294966829, 4294966813, 4294966769, 4294966667, 4294966661, - 4294966657, 4294966651, 4294966639, 4294966619, 4294966591, 4294966583, 4294966553, 4294966477, - 4294966447, 4294966441, 4294966427, 4294966373, 4294966367, 4294966337, 4294966297, -]; - -const PRIMES33: &'static [u64] = &[8589934583, 8589934567, 8589934543, 8589934513, 8589934487, - 8589934307, 8589934291, 8589934289, 8589934271, 8589934237, 8589934211, 8589934207, 8589934201, - 8589934187, 8589934151, 8589934141, 8589934139, 8589934117, 8589934103, 8589934099, 8589934091, - 8589934069, 8589934049, 8589934027, 8589934007, 8589933973, 8589933971, 8589933967, 8589933931, - 8589933917, 8589933907, 8589933853, 8589933827, 8589933823, 8589933787, 8589933773, 8589933733, - 8589933731, 8589933721, 8589933683, 8589933647, 8589933641, 8589933637, 8589933631, 8589933629, - 8589933619, 8589933601, 8589933581, -]; - -const PRIMES34: &'static [u64] = &[17179869143, 17179869107, 17179869071, 17179869053, - 17179869041, 17179869019, 17179868999, 17179868977, 17179868957, 17179868903, 17179868899, - 17179868887, 17179868879, 17179868873, 17179868869, 17179868861, 17179868843, 17179868833, - 17179868809, 17179868807, 17179868777, 17179868759, 17179868729, 17179868711, 17179868683, - 17179868681, 17179868597, 17179868549, 17179868543, 17179868521, 17179868513, 17179868479, - 17179868443, 17179868437, 17179868429, 17179868383, 17179868369, 17179868357, 17179868353, - 17179868351, 17179868333, 17179868317, 17179868309, 17179868297, 17179868287, 17179868249, - 17179868243, 17179868183, -]; - -const PRIMES35: &'static [u64] = &[34359738337, 34359738319, 34359738307, 34359738299, - 34359738289, 34359738247, 34359738227, 34359738121, 34359738059, 34359738043, 34359738011, - 34359737917, 34359737869, 34359737849, 34359737837, 34359737821, 34359737813, 34359737791, - 34359737777, 34359737771, 34359737717, 34359737591, 34359737567, 34359737549, 34359737519, - 34359737497, 34359737479, 34359737407, 34359737393, 34359737371, -]; - -const PRIMES36: &'static [u64] = &[68719476731, 68719476719, 68719476713, 68719476671, - 68719476619, 68719476599, 68719476577, 68719476563, 68719476547, 68719476503, 68719476493, - 68719476479, 68719476433, 68719476407, 68719476391, 68719476389, 68719476377, 68719476361, - 68719476323, 68719476307, 68719476281, 68719476271, 68719476257, 68719476247, 68719476209, - 68719476197, 68719476181, 68719476169, 68719476157, 68719476149, 68719476109, 68719476053, - 68719476047, 68719476019, 68719475977, 68719475947, 68719475933, 68719475911, 68719475893, - 68719475879, 68719475837, 68719475827, 68719475809, 68719475791, 68719475779, 68719475771, - 68719475767, 68719475731, 68719475729, -]; - -const PRIMES37: &'static [u64] = &[137438953447, 137438953441, 137438953427, 137438953403, - 137438953349, 137438953331, 137438953273, 137438953271, 137438953121, 137438953097, - 137438953037, 137438953009, 137438952953, 137438952901, 137438952887, 137438952869, - 137438952853, 137438952731, 137438952683, 137438952611, 137438952529, 137438952503, - 137438952491, -]; - -const PRIMES38: &'static [u64] = &[274877906899, 274877906857, 274877906837, 274877906813, - 274877906791, 274877906759, 274877906753, 274877906717, 274877906713, 274877906687, - 274877906647, 274877906629, 274877906627, 274877906573, 274877906543, 274877906491, - 274877906477, 274877906473, 274877906431, 274877906419, 274877906341, 274877906333, - 274877906327, 274877906321, 274877906309, 274877906267, 274877906243, 274877906213, - 274877906209, 274877906203, 274877906179, 274877906167, 274877906119, 274877906063, - 274877906053, 274877906021, 274877905931, -]; - -const PRIMES39: &'static [u64] = &[549755813881, 549755813869, 549755813821, 549755813797, - 549755813753, 549755813723, 549755813669, 549755813657, 549755813647, 549755813587, - 549755813561, 549755813513, 549755813507, 549755813461, 549755813417, 549755813401, - 549755813371, 549755813359, 549755813357, 549755813351, 549755813339, 549755813317, - 549755813311, 549755813281, 549755813239, 549755813231, 549755813213, 549755813207, - 549755813197, 549755813183, 549755813161, 549755813149, 549755813147, 549755813143, - 549755813141, 549755813059, 549755813027, 549755813003, 549755812951, 549755812937, - 549755812933, 549755812889, 549755812867, -]; - -const PRIMES40: &'static [u64] = &[1099511627689, 1099511627609, 1099511627581, 1099511627573, - 1099511627563, 1099511627491, 1099511627483, 1099511627477, 1099511627387, 1099511627339, - 1099511627321, 1099511627309, 1099511627297, 1099511627293, 1099511627261, 1099511627213, - 1099511627191, 1099511627177, 1099511627173, 1099511627143, 1099511627089, 1099511626987, - 1099511626949, 1099511626937, 1099511626793, 1099511626781, 1099511626771, -]; - -const PRIMES41: &'static [u64] = &[2199023255531, 2199023255521, 2199023255497, 2199023255489, - 2199023255479, 2199023255477, 2199023255461, 2199023255441, 2199023255419, 2199023255413, - 2199023255357, 2199023255327, 2199023255291, 2199023255279, 2199023255267, 2199023255243, - 2199023255203, 2199023255171, 2199023255137, 2199023255101, 2199023255087, 2199023255081, - 2199023255069, 2199023255027, 2199023255021, 2199023254979, 2199023254933, 2199023254913, - 2199023254907, 2199023254903, 2199023254843, 2199023254787, 2199023254699, 2199023254693, - 2199023254657, 2199023254567, -]; - -const PRIMES42: &'static [u64] = &[4398046511093, 4398046511087, 4398046511071, 4398046511051, - 4398046511039, 4398046510961, 4398046510943, 4398046510939, 4398046510889, 4398046510877, - 4398046510829, 4398046510787, 4398046510771, 4398046510751, 4398046510733, 4398046510721, - 4398046510643, 4398046510639, 4398046510597, 4398046510577, 4398046510547, 4398046510531, - 4398046510463, 4398046510397, 4398046510391, 4398046510379, 4398046510357, 4398046510331, - 4398046510327, 4398046510313, 4398046510283, 4398046510279, 4398046510217, 4398046510141, - 4398046510133, 4398046510103, 4398046510093, -]; - -const PRIMES43: &'static [u64] = &[8796093022151, 8796093022141, 8796093022091, 8796093022033, - 8796093021953, 8796093021941, 8796093021917, 8796093021899, 8796093021889, 8796093021839, - 8796093021803, 8796093021791, 8796093021769, 8796093021763, 8796093021743, 8796093021671, - 8796093021607, 8796093021587, 8796093021533, 8796093021523, 8796093021517, 8796093021493, - 8796093021467, 8796093021461, 8796093021449, 8796093021409, 8796093021407, 8796093021371, - 8796093021347, 8796093021337, 8796093021281, 8796093021269, -]; - -const PRIMES44: &'static [u64] = &[17592186044399, 17592186044299, 17592186044297, 17592186044287, - 17592186044273, 17592186044267, 17592186044129, 17592186044089, 17592186044057, 17592186044039, - 17592186043987, 17592186043921, 17592186043889, 17592186043877, 17592186043841, 17592186043829, - 17592186043819, 17592186043813, 17592186043807, 17592186043741, 17592186043693, 17592186043667, - 17592186043631, 17592186043591, 17592186043577, 17592186043547, 17592186043483, 17592186043451, - 17592186043433, 17592186043409, -]; - -const PRIMES45: &'static [u64] = &[35184372088777, 35184372088763, 35184372088751, 35184372088739, - 35184372088711, 35184372088699, 35184372088693, 35184372088673, 35184372088639, 35184372088603, - 35184372088571, 35184372088517, 35184372088493, 35184372088471, 35184372088403, 35184372088391, - 35184372088379, 35184372088363, 35184372088321, 35184372088319, 35184372088279, 35184372088259, - 35184372088249, 35184372088241, 35184372088223, 35184372088183, 35184372088097, 35184372088081, - 35184372088079, 35184372088051, 35184372088043, 35184372088039, 35184372087937, 35184372087929, - 35184372087923, 35184372087881, 35184372087877, 35184372087869, -]; - -const PRIMES46: &'static [u64] = &[70368744177643, 70368744177607, 70368744177601, 70368744177587, - 70368744177497, 70368744177467, 70368744177427, 70368744177377, 70368744177359, 70368744177353, - 70368744177331, 70368744177289, 70368744177283, 70368744177271, 70368744177257, 70368744177227, - 70368744177167, 70368744177113, 70368744177029, 70368744176959, 70368744176921, 70368744176909, - 70368744176879, 70368744176867, 70368744176833, 70368744176827, 70368744176807, 70368744176779, - 70368744176777, 70368744176729, 70368744176719, 70368744176711, -]; - -const PRIMES47: &'static [u64] = &[140737488355213, 140737488355201, 140737488355181, - 140737488355049, 140737488355031, 140737488354989, 140737488354893, 140737488354787, - 140737488354709, 140737488354679, 140737488354613, 140737488354557, 140737488354511, - 140737488354431, 140737488354413, 140737488354409, 140737488354373, 140737488354347, - 140737488354329, -]; - -const PRIMES48: &'static [u64] = &[281474976710597, 281474976710591, 281474976710567, - 281474976710563, 281474976710509, 281474976710491, 281474976710467, 281474976710423, - 281474976710413, 281474976710399, 281474976710339, 281474976710327, 281474976710287, - 281474976710197, 281474976710143, 281474976710131, 281474976710129, 281474976710107, - 281474976710089, 281474976710087, 281474976710029, 281474976709987, 281474976709891, - 281474976709859, 281474976709831, 281474976709757, 281474976709741, 281474976709711, - 281474976709649, 281474976709637, -]; - -const PRIMES49: &'static [u64] = &[562949953421231, 562949953421201, 562949953421189, - 562949953421173, 562949953421131, 562949953421111, 562949953421099, 562949953421047, - 562949953421029, 562949953420973, 562949953420871, 562949953420867, 562949953420837, - 562949953420793, 562949953420747, 562949953420741, 562949953420733, 562949953420727, - 562949953420609, 562949953420571, 562949953420559, 562949953420553, 562949953420523, - 562949953420507, 562949953420457, 562949953420403, 562949953420373, 562949953420369, - 562949953420343, 562949953420303, 562949953420297, -]; - -const PRIMES50: &'static [u64] = &[1125899906842597, 1125899906842589, 1125899906842573, - 1125899906842553, 1125899906842511, 1125899906842507, 1125899906842493, 1125899906842463, - 1125899906842429, 1125899906842391, 1125899906842357, 1125899906842283, 1125899906842273, - 1125899906842247, 1125899906842201, 1125899906842177, 1125899906842079, 1125899906842033, - 1125899906842021, 1125899906842013, 1125899906841973, 1125899906841971, 1125899906841959, - 1125899906841949, 1125899906841943, 1125899906841917, 1125899906841901, 1125899906841883, - 1125899906841859, 1125899906841811, 1125899906841803, 1125899906841751, 1125899906841713, - 1125899906841673, 1125899906841653, 1125899906841623, 1125899906841613, -]; diff --git a/test/false.rs b/test/false.rs deleted file mode 100644 index 2cd6a327d..000000000 --- a/test/false.rs +++ /dev/null @@ -1,9 +0,0 @@ -use std::process::Command; - -static PROGNAME: &'static str = "./false"; - -#[test] -fn test_exit_code() { - let exit_status = Command::new(PROGNAME).status().unwrap().success(); - assert_eq!(exit_status, false); -} diff --git a/test/fixtures/cat/256.txt b/test/fixtures/cat/256.txt deleted file mode 100644 index c86626638e0bc8cf47ca49bb1525b40e9737ee64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmZQzWMXDvWn<^yMC+6cQE@6%&_`l#-T_m6KOcR8m$^Ra4i{)Y8_`)zddH zG%_|ZH8Z!cw6eCbwX=6{baHlab#wRd^z!!c_45x13RUz zF>}`JIdkXDU$Ah|;w4L$Enl&6)#^2C*R9{Mant54TeofBv2)k%J$v` lorem_ipsum.txt <== -Lorem ipsum dolor sit amet, -consectetur adipiscing elit. -Nunc interdum suscipit sem vel ornare. -Proin euismod, -justo sed mollis dictum, -eros urna ultricies augue, -eu pharetra mi ex id ante. -Duis convallis porttitor aliquam. -Nunc vitae tincidunt ex. -Suspendisse iaculis ligula ac diam consectetur lacinia. diff --git a/test/fixtures/mv/hello_world.txt b/test/fixtures/mv/hello_world.txt deleted file mode 100644 index 8ab686eaf..000000000 --- a/test/fixtures/mv/hello_world.txt +++ /dev/null @@ -1 +0,0 @@ -Hello, World! diff --git a/test/fixtures/nl/joinblanklines.txt b/test/fixtures/nl/joinblanklines.txt deleted file mode 100644 index 197859644..000000000 --- a/test/fixtures/nl/joinblanklines.txt +++ /dev/null @@ -1,27 +0,0 @@ -Nonempty -Nonempty -Followed by 10x empty - - - - - - - - - - -Followed by 5x empty - - - - - -Followed by 4x empty - - - - -Nonempty -Nonempty -Nonempty. diff --git a/test/fixtures/nl/section.txt b/test/fixtures/nl/section.txt deleted file mode 100644 index 62359e7bf..000000000 --- a/test/fixtures/nl/section.txt +++ /dev/null @@ -1,18 +0,0 @@ -\:\:\: -HEADER1 -HEADER2 -\:\: -BODY1 -BODY2 -\: -FOOTER1 -FOOTER2 -\:\:\: -NEXTHEADER1 -NEXTHEADER2 -\:\: -NEXTBODY1 -NEXTBODY2 -\: -NEXTFOOTER1 -NEXTFOOTER2 diff --git a/test/fixtures/nl/simple.txt b/test/fixtures/nl/simple.txt deleted file mode 100644 index b168ae840..000000000 --- a/test/fixtures/nl/simple.txt +++ /dev/null @@ -1,15 +0,0 @@ -L1 -L2 -L3 -L4 -L5 -L6 -L7 -L8 -L9 -L10 -L11 -L12 -L13 -L14 -L15 diff --git a/test/fixtures/paste/html_colors.expected b/test/fixtures/paste/html_colors.expected deleted file mode 100644 index 4fb65d6aa..000000000 --- a/test/fixtures/paste/html_colors.expected +++ /dev/null @@ -1,16 +0,0 @@ -white #FFFFFF -silver #C0C0C0 -gray #808080 -black #000000 -red #FF0000 -maroon #800000 -yellow #FFFF00 -olive #808000 -lime #00FF00 -green #008000 -aqua #00FFFF -teal #008080 -blue #0000FF -navy #000080 -fuchsia #FF00FF -purple #800080 diff --git a/test/fixtures/paste/html_colors.txt b/test/fixtures/paste/html_colors.txt deleted file mode 100644 index 290303ff0..000000000 --- a/test/fixtures/paste/html_colors.txt +++ /dev/null @@ -1,32 +0,0 @@ -white -#FFFFFF -silver -#C0C0C0 -gray -#808080 -black -#000000 -red -#FF0000 -maroon -#800000 -yellow -#FFFF00 -olive -#808000 -lime -#00FF00 -green -#008000 -aqua -#00FFFF -teal -#008080 -blue -#0000FF -navy -#000080 -fuchsia -#FF00FF -purple -#800080 diff --git a/test/fixtures/ptx/gnu_ext_disabled_ignore_and_only_file.expected b/test/fixtures/ptx/gnu_ext_disabled_ignore_and_only_file.expected deleted file mode 100644 index d57017253..000000000 --- a/test/fixtures/ptx/gnu_ext_disabled_ignore_and_only_file.expected +++ /dev/null @@ -1,2 +0,0 @@ -.xx "" """quotes"", for" "roff" "" -.xx "" "{brackets} for" "tex" "" diff --git a/test/fixtures/ptx/gnu_ext_disabled_roff_auto_ref.expected b/test/fixtures/ptx/gnu_ext_disabled_roff_auto_ref.expected deleted file mode 100644 index eefba851b..000000000 --- a/test/fixtures/ptx/gnu_ext_disabled_roff_auto_ref.expected +++ /dev/null @@ -1,24 +0,0 @@ -.xx "" "" """quotes"", for roff" "" "input:3" -.xx "" "and some other like" "%a, b#, c$c" "" "input:5" -.xx "" "maybe" "also~or^" "" "input:6" -.xx "" "" "and some other like %a, b#, c$c" "" "input:5" -.xx "" "oh," "and back\slash" "" "input:7" -.xx "" "and some other like %a," "b#, c$c" "" "input:5" -.xx "" "oh, and" "back\slash" "" "input:7" -.xx "" "and some other like %a, b#," "c$c" "" "input:5" -.xx "" "let's check special" "characters:" "" "input:2" -.xx "" "let's" "check special characters:" "" "input:2" -.xx "" """quotes""," "for roff" "" "input:3" -.xx "" "{brackets}" "for tex" "" "input:4" -.xx "" "" "hello world!" "" "input:1" -.xx "" "" "let's check special characters:" "" "input:2" -.xx "" "and some other" "like %a, b#, c$c" "" "input:5" -.xx "" "" "maybe also~or^" "" "input:6" -.xx "" "" "oh, and back\slash" "" "input:7" -.xx "" "and some" "other like %a, b#, c$c" "" "input:5" -.xx "" """quotes"", for" "roff" "" "input:3" -.xx "" "and" "some other like %a, b#, c$c" "" "input:5" -.xx "" "let's check" "special characters:" "" "input:2" -.xx "" "{brackets} for" "tex" "" "input:4" -.xx "" "hello" "world!" "" "input:1" -.xx "" "" "{brackets} for tex" "" "input:4" diff --git a/test/fixtures/ptx/gnu_ext_disabled_roff_input_ref.expected b/test/fixtures/ptx/gnu_ext_disabled_roff_input_ref.expected deleted file mode 100644 index f2f3f9160..000000000 --- a/test/fixtures/ptx/gnu_ext_disabled_roff_input_ref.expected +++ /dev/null @@ -1,17 +0,0 @@ -.xx "" "some other like" "%a, b#, c$c" "" "and" -.xx "" "" "also~or^" "" "maybe" -.xx "" "" "and back\slash" "" "oh," -.xx "" "some other like %a," "b#, c$c" "" "and" -.xx "" "and" "back\slash" "" "oh," -.xx "" "some other like %a, b#," "c$c" "" "and" -.xx "" "check special" "characters:" "" "let's" -.xx "" "" "check special characters:" "" "let's" -.xx "" "" "for roff" "" """quotes""," -.xx "" "" "for tex" "" "{brackets}" -.xx "" "some other" "like %a, b#, c$c" "" "and" -.xx "" "some" "other like %a, b#, c$c" "" "and" -.xx "" "for" "roff" "" """quotes""," -.xx "" "" "some other like %a, b#, c$c" "" "and" -.xx "" "check" "special characters:" "" "let's" -.xx "" "for" "tex" "" "{brackets}" -.xx "" "" "world!" "" "hello" diff --git a/test/fixtures/ptx/gnu_ext_disabled_roff_no_ref.expected b/test/fixtures/ptx/gnu_ext_disabled_roff_no_ref.expected deleted file mode 100644 index 3886e087d..000000000 --- a/test/fixtures/ptx/gnu_ext_disabled_roff_no_ref.expected +++ /dev/null @@ -1,24 +0,0 @@ -.xx "" "" """quotes"", for roff" "" -.xx "" "and some other like" "%a, b#, c$c" "" -.xx "" "maybe" "also~or^" "" -.xx "" "" "and some other like %a, b#, c$c" "" -.xx "" "oh," "and back\slash" "" -.xx "" "and some other like %a," "b#, c$c" "" -.xx "" "oh, and" "back\slash" "" -.xx "" "and some other like %a, b#," "c$c" "" -.xx "" "let's check special" "characters:" "" -.xx "" "let's" "check special characters:" "" -.xx "" """quotes""," "for roff" "" -.xx "" "{brackets}" "for tex" "" -.xx "" "" "hello world!" "" -.xx "" "" "let's check special characters:" "" -.xx "" "and some other" "like %a, b#, c$c" "" -.xx "" "" "maybe also~or^" "" -.xx "" "" "oh, and back\slash" "" -.xx "" "and some" "other like %a, b#, c$c" "" -.xx "" """quotes"", for" "roff" "" -.xx "" "and" "some other like %a, b#, c$c" "" -.xx "" "let's check" "special characters:" "" -.xx "" "{brackets} for" "tex" "" -.xx "" "hello" "world!" "" -.xx "" "" "{brackets} for tex" "" diff --git a/test/fixtures/ptx/gnu_ext_disabled_tex_auto_ref.expected b/test/fixtures/ptx/gnu_ext_disabled_tex_auto_ref.expected deleted file mode 100644 index f0b0f41c7..000000000 --- a/test/fixtures/ptx/gnu_ext_disabled_tex_auto_ref.expected +++ /dev/null @@ -1,24 +0,0 @@ -\xx {}{}{"quotes",}{ for roff}{}{input:3} -\xx {}{and some other like}{\%a,}{ b\#, c\$c}{}{input:5} -\xx {}{maybe}{also~or^}{}{}{input:6} -\xx {}{}{and}{ some other like \%a, b\#, c\$c}{}{input:5} -\xx {}{oh,}{and}{ back\backslash{}slash}{}{input:7} -\xx {}{and some other like \%a,}{b\#,}{ c\$c}{}{input:5} -\xx {}{oh, and}{back\backslash{}slash}{}{}{input:7} -\xx {}{and some other like \%a, b\#,}{c\$c}{}{}{input:5} -\xx {}{let's check special}{characters:}{}{}{input:2} -\xx {}{let's}{check}{ special characters:}{}{input:2} -\xx {}{"quotes",}{for}{ roff}{}{input:3} -\xx {}{$\{$brackets$\}$}{for}{ tex}{}{input:4} -\xx {}{}{hello}{ world!}{}{input:1} -\xx {}{}{let's}{ check special characters:}{}{input:2} -\xx {}{and some other}{like}{ \%a, b\#, c\$c}{}{input:5} -\xx {}{}{maybe}{ also~or^}{}{input:6} -\xx {}{}{oh,}{ and back\backslash{}slash}{}{input:7} -\xx {}{and some}{other}{ like \%a, b\#, c\$c}{}{input:5} -\xx {}{"quotes", for}{roff}{}{}{input:3} -\xx {}{and}{some}{ other like \%a, b\#, c\$c}{}{input:5} -\xx {}{let's check}{special}{ characters:}{}{input:2} -\xx {}{$\{$brackets$\}$ for}{tex}{}{}{input:4} -\xx {}{hello}{world!}{}{}{input:1} -\xx {}{}{$\{$brackets$\}$}{ for tex}{}{input:4} diff --git a/test/fixtures/ptx/gnu_ext_disabled_tex_input_ref.expected b/test/fixtures/ptx/gnu_ext_disabled_tex_input_ref.expected deleted file mode 100644 index 8e345339a..000000000 --- a/test/fixtures/ptx/gnu_ext_disabled_tex_input_ref.expected +++ /dev/null @@ -1,17 +0,0 @@ -\xx {}{some other like}{\%a,}{ b\#, c\$c}{}{and} -\xx {}{}{also~or^}{}{}{maybe} -\xx {}{}{and}{ back\backslash{}slash}{}{oh,} -\xx {}{some other like \%a,}{b\#,}{ c\$c}{}{and} -\xx {}{and}{back\backslash{}slash}{}{}{oh,} -\xx {}{some other like \%a, b\#,}{c\$c}{}{}{and} -\xx {}{check special}{characters:}{}{}{let's} -\xx {}{}{check}{ special characters:}{}{let's} -\xx {}{}{for}{ roff}{}{"quotes",} -\xx {}{}{for}{ tex}{}{$\{$brackets$\}$} -\xx {}{some other}{like}{ \%a, b\#, c\$c}{}{and} -\xx {}{some}{other}{ like \%a, b\#, c\$c}{}{and} -\xx {}{for}{roff}{}{}{"quotes",} -\xx {}{}{some}{ other like \%a, b\#, c\$c}{}{and} -\xx {}{check}{special}{ characters:}{}{let's} -\xx {}{for}{tex}{}{}{$\{$brackets$\}$} -\xx {}{}{world!}{}{}{hello} diff --git a/test/fixtures/ptx/gnu_ext_disabled_tex_no_ref.expected b/test/fixtures/ptx/gnu_ext_disabled_tex_no_ref.expected deleted file mode 100644 index dad32b5f1..000000000 --- a/test/fixtures/ptx/gnu_ext_disabled_tex_no_ref.expected +++ /dev/null @@ -1,24 +0,0 @@ -\xx {}{}{"quotes",}{ for roff}{} -\xx {}{and some other like}{\%a,}{ b\#, c\$c}{} -\xx {}{maybe}{also~or^}{}{} -\xx {}{}{and}{ some other like \%a, b\#, c\$c}{} -\xx {}{oh,}{and}{ back\backslash{}slash}{} -\xx {}{and some other like \%a,}{b\#,}{ c\$c}{} -\xx {}{oh, and}{back\backslash{}slash}{}{} -\xx {}{and some other like \%a, b\#,}{c\$c}{}{} -\xx {}{let's check special}{characters:}{}{} -\xx {}{let's}{check}{ special characters:}{} -\xx {}{"quotes",}{for}{ roff}{} -\xx {}{$\{$brackets$\}$}{for}{ tex}{} -\xx {}{}{hello}{ world!}{} -\xx {}{}{let's}{ check special characters:}{} -\xx {}{and some other}{like}{ \%a, b\#, c\$c}{} -\xx {}{}{maybe}{ also~or^}{} -\xx {}{}{oh,}{ and back\backslash{}slash}{} -\xx {}{and some}{other}{ like \%a, b\#, c\$c}{} -\xx {}{"quotes", for}{roff}{}{} -\xx {}{and}{some}{ other like \%a, b\#, c\$c}{} -\xx {}{let's check}{special}{ characters:}{} -\xx {}{$\{$brackets$\}$ for}{tex}{}{} -\xx {}{hello}{world!}{}{} -\xx {}{}{$\{$brackets$\}$}{ for tex}{} diff --git a/test/fixtures/ptx/ignore b/test/fixtures/ptx/ignore deleted file mode 100644 index d671622f8..000000000 --- a/test/fixtures/ptx/ignore +++ /dev/null @@ -1,2 +0,0 @@ -maybe -about diff --git a/test/fixtures/ptx/input b/test/fixtures/ptx/input deleted file mode 100644 index 6ba595bc0..000000000 --- a/test/fixtures/ptx/input +++ /dev/null @@ -1,7 +0,0 @@ -hello world! -let's check special characters: -"quotes", for roff -{brackets} for tex -and some other like %a, b#, c$c -maybe also~or^ -oh, and back\slash diff --git a/test/fixtures/ptx/only b/test/fixtures/ptx/only deleted file mode 100644 index 917aa2431..000000000 --- a/test/fixtures/ptx/only +++ /dev/null @@ -1,5 +0,0 @@ -roff -tex -world -maybe -about diff --git a/test/fixtures/sort/human1.ans b/test/fixtures/sort/human1.ans deleted file mode 100644 index 74fad9fdf..000000000 --- a/test/fixtures/sort/human1.ans +++ /dev/null @@ -1,11 +0,0 @@ -844K -981K -11M -13M -14M -16M -18M -19M -20M -981T -20P diff --git a/test/fixtures/sort/human1.txt b/test/fixtures/sort/human1.txt deleted file mode 100644 index 803666dbe..000000000 --- a/test/fixtures/sort/human1.txt +++ /dev/null @@ -1,11 +0,0 @@ -14M -20M -20P -11M -981T -16M -18M -19M -844K -981K -13M diff --git a/test/fixtures/sort/numeric1.ans b/test/fixtures/sort/numeric1.ans deleted file mode 100644 index c61659bcd..000000000 --- a/test/fixtures/sort/numeric1.ans +++ /dev/null @@ -1,2 +0,0 @@ -0 -.02 diff --git a/test/fixtures/sort/numeric1.txt b/test/fixtures/sort/numeric1.txt deleted file mode 100644 index b2cc3ea1a..000000000 --- a/test/fixtures/sort/numeric1.txt +++ /dev/null @@ -1,2 +0,0 @@ -.02 -0 diff --git a/test/fixtures/sort/numeric2.ans b/test/fixtures/sort/numeric2.ans deleted file mode 100644 index 99ff9b359..000000000 --- a/test/fixtures/sort/numeric2.ans +++ /dev/null @@ -1,2 +0,0 @@ -.02 -.03 diff --git a/test/fixtures/sort/numeric2.txt b/test/fixtures/sort/numeric2.txt deleted file mode 100644 index 25eb8cfbd..000000000 --- a/test/fixtures/sort/numeric2.txt +++ /dev/null @@ -1,2 +0,0 @@ -.03 -.02 diff --git a/test/fixtures/sort/numeric3.ans b/test/fixtures/sort/numeric3.ans deleted file mode 100644 index ce65c1f73..000000000 --- a/test/fixtures/sort/numeric3.ans +++ /dev/null @@ -1,2 +0,0 @@ -.000 -.01 diff --git a/test/fixtures/sort/numeric3.txt b/test/fixtures/sort/numeric3.txt deleted file mode 100644 index 7d772028a..000000000 --- a/test/fixtures/sort/numeric3.txt +++ /dev/null @@ -1,2 +0,0 @@ -.01 -.000 diff --git a/test/fixtures/sort/numeric4.ans b/test/fixtures/sort/numeric4.ans deleted file mode 100644 index 7d5f4d647..000000000 --- a/test/fixtures/sort/numeric4.ans +++ /dev/null @@ -1,2 +0,0 @@ -.00 -.01 diff --git a/test/fixtures/sort/numeric4.txt b/test/fixtures/sort/numeric4.txt deleted file mode 100644 index 490de8590..000000000 --- a/test/fixtures/sort/numeric4.txt +++ /dev/null @@ -1,2 +0,0 @@ -.01 -.00 diff --git a/test/fixtures/sort/numeric5.ans b/test/fixtures/sort/numeric5.ans deleted file mode 100644 index 4c59f5cda..000000000 --- a/test/fixtures/sort/numeric5.ans +++ /dev/null @@ -1,2 +0,0 @@ -.022 -.024 diff --git a/test/fixtures/sort/numeric5.txt b/test/fixtures/sort/numeric5.txt deleted file mode 100644 index 4c59f5cda..000000000 --- a/test/fixtures/sort/numeric5.txt +++ /dev/null @@ -1,2 +0,0 @@ -.022 -.024 diff --git a/test/fixtures/sort/numeric6.ans b/test/fixtures/sort/numeric6.ans deleted file mode 100644 index 190423f88..000000000 --- a/test/fixtures/sort/numeric6.ans +++ /dev/null @@ -1,100 +0,0 @@ -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 diff --git a/test/fixtures/sort/numeric6.txt b/test/fixtures/sort/numeric6.txt deleted file mode 100644 index d3c2bb861..000000000 --- a/test/fixtures/sort/numeric6.txt +++ /dev/null @@ -1,100 +0,0 @@ -33 -16 -35 -56 -72 -37 -21 -49 -70 -48 -90 -83 -44 -79 -10 -20 -4 -26 -27 -63 -29 -47 -51 -85 -88 -46 -30 -61 -93 -81 -78 -53 -87 -18 -98 -38 -13 -39 -23 -71 -5 -100 -96 -8 -24 -14 -28 -15 -25 -43 -36 -67 -75 -66 -31 -57 -34 -80 -40 -86 -17 -55 -9 -1 -62 -12 -74 -58 -69 -76 -11 -73 -68 -59 -41 -45 -52 -97 -82 -6 -7 -77 -42 -84 -95 -94 -89 -19 -64 -2 -22 -50 -60 -32 -92 -3 -99 -65 -54 -91 diff --git a/test/fixtures/sum/alice_in_wonderland.txt b/test/fixtures/sum/alice_in_wonderland.txt deleted file mode 100644 index a95562a1c..000000000 --- a/test/fixtures/sum/alice_in_wonderland.txt +++ /dev/null @@ -1,5 +0,0 @@ -Alice was beginning to get very tired of sitting by -her sister on the bank, and of having nothing to do: once or twice -she had peeped into the book her sister was reading, but it had no -pictures or conversations in it, "and what is the use of a book," -thought Alice "without pictures or conversation?" diff --git a/test/fixtures/sum/bsd_multiple_files.expected b/test/fixtures/sum/bsd_multiple_files.expected deleted file mode 100644 index 1b05ee27f..000000000 --- a/test/fixtures/sum/bsd_multiple_files.expected +++ /dev/null @@ -1,2 +0,0 @@ -8109 1 lorem_ipsum.txt -1814 1 alice_in_wonderland.txt diff --git a/test/fixtures/sum/bsd_single_file.expected b/test/fixtures/sum/bsd_single_file.expected deleted file mode 100644 index 3cffc4337..000000000 --- a/test/fixtures/sum/bsd_single_file.expected +++ /dev/null @@ -1 +0,0 @@ -8109 1 diff --git a/test/fixtures/sum/bsd_stdin.expected b/test/fixtures/sum/bsd_stdin.expected deleted file mode 100644 index 3cffc4337..000000000 --- a/test/fixtures/sum/bsd_stdin.expected +++ /dev/null @@ -1 +0,0 @@ -8109 1 diff --git a/test/fixtures/sum/lorem_ipsum.txt b/test/fixtures/sum/lorem_ipsum.txt deleted file mode 100644 index 16752446c..000000000 --- a/test/fixtures/sum/lorem_ipsum.txt +++ /dev/null @@ -1,13 +0,0 @@ -Lorem ipsum dolor sit amet, consectetur adipiscing -elit. Nunc interdum suscipit sem vel ornare. Proin euismod, justo -sed mollis dictum, eros urna ultricies augue, eu pharetra mi ex id -ante. Duis convallis porttitor aliquam. Nunc vitae tincidunt ex. -Suspendisse iaculis ligula ac diam consectetur lacinia. Donec vel -velit dui. Etiam fringilla, dolor quis tempor vehicula, lacus -turpis bibendum velit, et pellentesque elit odio a magna. Cras -vulputate tortor non libero vehicula euismod. Aliquam tincidunt -nisl eget enim cursus, viverra sagittis magna commodo. Cras rhoncus -egestas leo nec blandit. Suspendisse potenti. Etiam ullamcorper -leo vel lacus vestibulum, cursus semper eros efficitur. In hac -habitasse platea dictumst. Phasellus scelerisque vehicula -fringilla. diff --git a/test/fixtures/sum/sysv_multiple_files.expected b/test/fixtures/sum/sysv_multiple_files.expected deleted file mode 100644 index 83a6d6d83..000000000 --- a/test/fixtures/sum/sysv_multiple_files.expected +++ /dev/null @@ -1,2 +0,0 @@ -6985 2 lorem_ipsum.txt -27441 1 alice_in_wonderland.txt diff --git a/test/fixtures/sum/sysv_single_file.expected b/test/fixtures/sum/sysv_single_file.expected deleted file mode 100644 index e0f7252cb..000000000 --- a/test/fixtures/sum/sysv_single_file.expected +++ /dev/null @@ -1 +0,0 @@ -6985 2 lorem_ipsum.txt diff --git a/test/fixtures/sum/sysv_stdin.expected b/test/fixtures/sum/sysv_stdin.expected deleted file mode 100644 index f0fba8c81..000000000 --- a/test/fixtures/sum/sysv_stdin.expected +++ /dev/null @@ -1 +0,0 @@ -6985 2 diff --git a/test/fixtures/tac/delimited_primes.expected b/test/fixtures/tac/delimited_primes.expected deleted file mode 100644 index cf58c9015..000000000 --- a/test/fixtures/tac/delimited_primes.expected +++ /dev/null @@ -1 +0,0 @@ -9789:83:79:73:71:67:61:59:53:47:43:41:37:31:29:23:19:17:13:11:7:5:3:2: \ No newline at end of file diff --git a/test/fixtures/tac/delimited_primes.txt b/test/fixtures/tac/delimited_primes.txt deleted file mode 100644 index 867a26610..000000000 --- a/test/fixtures/tac/delimited_primes.txt +++ /dev/null @@ -1 +0,0 @@ -2:3:5:7:11:13:17:19:23:29:31:37:41:43:47:53:59:61:67:71:73:79:83:89:97 \ No newline at end of file diff --git a/test/fixtures/tac/delimited_primes_before.expected b/test/fixtures/tac/delimited_primes_before.expected deleted file mode 100644 index 13cb1be06..000000000 --- a/test/fixtures/tac/delimited_primes_before.expected +++ /dev/null @@ -1 +0,0 @@ -97:89:83:79:73:71:67:61:59:53:47:43:41:37:31:29:23:19:17:13:11:7:5:3:2 \ No newline at end of file diff --git a/test/fixtures/tac/prime_per_line.expected b/test/fixtures/tac/prime_per_line.expected deleted file mode 100644 index 72413442f..000000000 --- a/test/fixtures/tac/prime_per_line.expected +++ /dev/null @@ -1,25 +0,0 @@ -97 -89 -83 -79 -73 -71 -67 -61 -59 -53 -47 -43 -41 -37 -31 -29 -23 -19 -17 -13 -11 -7 -5 -3 -2 diff --git a/test/fixtures/tac/prime_per_line.txt b/test/fixtures/tac/prime_per_line.txt deleted file mode 100644 index afc67fd93..000000000 --- a/test/fixtures/tac/prime_per_line.txt +++ /dev/null @@ -1,25 +0,0 @@ -2 -3 -5 -7 -11 -13 -17 -19 -23 -29 -31 -37 -41 -43 -47 -53 -59 -61 -67 -71 -73 -79 -83 -89 -97 diff --git a/test/fixtures/tsort/call_graph.expected b/test/fixtures/tsort/call_graph.expected deleted file mode 100644 index e33aa72bd..000000000 --- a/test/fixtures/tsort/call_graph.expected +++ /dev/null @@ -1,17 +0,0 @@ -main -parse_options -tail_file -tail_forever -tail -recheck -write_header -tail_lines -tail_bytes -pretty_name -start_lines -file_lines -pipe_lines -xlseek -start_bytes -pipe_bytes -dump_remainder diff --git a/test/fixtures/tsort/call_graph.txt b/test/fixtures/tsort/call_graph.txt deleted file mode 100644 index c6f94e5b6..000000000 --- a/test/fixtures/tsort/call_graph.txt +++ /dev/null @@ -1,22 +0,0 @@ -main parse_options -main tail_file -main tail_forever -tail_file pretty_name -tail_file write_header -tail_file tail -tail_forever recheck -tail_forever pretty_name -tail_forever write_header -tail_forever dump_remainder -tail tail_lines -tail tail_bytes -tail_lines start_lines -tail_lines dump_remainder -tail_lines file_lines -tail_lines pipe_lines -tail_bytes xlseek -tail_bytes start_bytes -tail_bytes dump_remainder -tail_bytes pipe_bytes -file_lines dump_remainder -recheck pretty_name diff --git a/test/fixtures/wc/alice_in_wonderland.txt b/test/fixtures/wc/alice_in_wonderland.txt deleted file mode 100644 index a95562a1c..000000000 --- a/test/fixtures/wc/alice_in_wonderland.txt +++ /dev/null @@ -1,5 +0,0 @@ -Alice was beginning to get very tired of sitting by -her sister on the bank, and of having nothing to do: once or twice -she had peeped into the book her sister was reading, but it had no -pictures or conversations in it, "and what is the use of a book," -thought Alice "without pictures or conversation?" diff --git a/test/fixtures/wc/lorem_ipsum.txt b/test/fixtures/wc/lorem_ipsum.txt deleted file mode 100644 index 16752446c..000000000 --- a/test/fixtures/wc/lorem_ipsum.txt +++ /dev/null @@ -1,13 +0,0 @@ -Lorem ipsum dolor sit amet, consectetur adipiscing -elit. Nunc interdum suscipit sem vel ornare. Proin euismod, justo -sed mollis dictum, eros urna ultricies augue, eu pharetra mi ex id -ante. Duis convallis porttitor aliquam. Nunc vitae tincidunt ex. -Suspendisse iaculis ligula ac diam consectetur lacinia. Donec vel -velit dui. Etiam fringilla, dolor quis tempor vehicula, lacus -turpis bibendum velit, et pellentesque elit odio a magna. Cras -vulputate tortor non libero vehicula euismod. Aliquam tincidunt -nisl eget enim cursus, viverra sagittis magna commodo. Cras rhoncus -egestas leo nec blandit. Suspendisse potenti. Etiam ullamcorper -leo vel lacus vestibulum, cursus semper eros efficitur. In hac -habitasse platea dictumst. Phasellus scelerisque vehicula -fringilla. diff --git a/test/fixtures/wc/moby_dick.txt b/test/fixtures/wc/moby_dick.txt deleted file mode 100644 index 193dc8e35..000000000 --- a/test/fixtures/wc/moby_dick.txt +++ /dev/null @@ -1,18 +0,0 @@ -Call me Ishmael. Some years ago - never mind how long -precisely - having little or no money in my purse, and nothing -particular to interest me on shore, I thought I would sail about a -little and see the watery part of the world. It is a way I have of -driving off the spleen and regulating the circulation. Whenever I -find myself growing grim about the mouth; whenever it is a damp, -drizzly November in my soul; whenever I find myself involuntarily -pausing before coffin warehouses, and bringing up the rear of every -funeral I meet; and especially whenever my hypos get such an upper -hand of me, that it requires a strong moral principle to prevent me -from deliberately stepping into the street, and methodically -knocking people's hats off - then, I account it high time to get to -sea as soon as I can. This is my substitute for pistol and ball. -With a philosophical flourish Cato throws himself upon his sword; I -quietly take to the ship. There is nothing surprising in this. If -they but knew it, almost all men in their degree, some time or -other, cherish very nearly the same feelings towards the ocean with -me. diff --git a/test/fold.rs b/test/fold.rs deleted file mode 100644 index ecae80303..000000000 --- a/test/fold.rs +++ /dev/null @@ -1,53 +0,0 @@ -use std::fs::File; -use std::io::Read; -use std::path::Path; -use std::process::Command; - -static PROGNAME: &'static str = "./fold"; - -#[test] -fn test_default_80_column_wrap() { - let po = Command::new(PROGNAME) - .arg("lorem_ipsum.txt") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - fold_helper(po.stdout, "lorem_ipsum_80_column.expected"); -} - -#[test] -fn test_40_column_hard_cutoff() { - let po = Command::new(PROGNAME) - .arg("-w") - .arg("40") - .arg("lorem_ipsum.txt") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - fold_helper(po.stdout, "lorem_ipsum_40_column_hard.expected"); -} - -#[test] -fn test_40_column_word_boundary() { - let po = Command::new(PROGNAME) - .arg("-s") - .arg("-w") - .arg("40") - .arg("lorem_ipsum.txt") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - fold_helper(po.stdout, "lorem_ipsum_40_column_word.expected"); -} - -fn fold_helper(output: Vec, filename: &str) { - let mut f = File::open(Path::new(filename)).unwrap_or_else(|err| { - panic!("{}", err) - }); - let mut expected = vec!(); - match f.read_to_end(&mut expected) { - Ok(_) => {}, - Err(err) => panic!("{}", err) - } - assert_eq!(String::from_utf8(output).unwrap(), String::from_utf8(expected).unwrap()); -} diff --git a/test/hashsum.rs b/test/hashsum.rs deleted file mode 100644 index 38f300303..000000000 --- a/test/hashsum.rs +++ /dev/null @@ -1,47 +0,0 @@ -static PROGNAME: &'static str = "./hashsum"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -macro_rules! get_hash( - ($str:expr) => ( - $str.split(' ').collect::>()[0] - ); -); - -macro_rules! test_digest { - ($($t:ident)*) => ($( - - mod $t { - use std::process::Command; - use util::*; - - static DIGEST_ARG: &'static str = concat!("--", stringify!($t)); - static EXPECTED_FILE: &'static str = concat!(stringify!($t), ".expected"); - - #[test] - fn test_single_file() { - let mut cmd = Command::new(::PROGNAME); - let result = run(&mut cmd.arg(DIGEST_ARG).arg("input.txt")); - - assert_empty_stderr!(result); - assert!(result.success); - assert_eq!(get_hash!(result.stdout), get_file_contents(EXPECTED_FILE)); - } - - #[test] - fn test_stdin() { - let input = get_file_contents("input.txt"); - let mut cmd = Command::new(::PROGNAME); - let result = run_piped_stdin(&mut cmd.arg(DIGEST_ARG), input); - - assert_empty_stderr!(result); - assert!(result.success); - assert_eq!(get_hash!(result.stdout), get_file_contents(EXPECTED_FILE)); - } - } - )*) -} - -test_digest! { md5 sha1 sha224 sha256 sha384 sha512 } diff --git a/test/head.rs b/test/head.rs deleted file mode 100644 index 4368225b3..000000000 --- a/test/head.rs +++ /dev/null @@ -1,72 +0,0 @@ -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./head"; -static INPUT: &'static str = "lorem_ipsum.txt"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_stdin_default() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd, get_file_contents(INPUT)); - assert_eq!(result.stdout, get_file_contents("lorem_ipsum_default.expected")); -} - -#[test] -fn test_stdin_1_line_obsolete() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-1"]), get_file_contents(INPUT)); - assert_eq!(result.stdout, get_file_contents("lorem_ipsum_1_line.expected")); -} - -#[test] -fn test_stdin_1_line() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-n", "1"]), get_file_contents(INPUT)); - assert_eq!(result.stdout, get_file_contents("lorem_ipsum_1_line.expected")); -} - -#[test] -fn test_stdin_5_chars() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-c", "5"]), get_file_contents(INPUT)); - assert_eq!(result.stdout, get_file_contents("lorem_ipsum_5_chars.expected")); -} - -#[test] -fn test_single_default() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.arg(INPUT)); - assert_eq!(result.stdout, get_file_contents("lorem_ipsum_default.expected")); -} - -#[test] -fn test_single_1_line_obsolete() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-1", INPUT])); - assert_eq!(result.stdout, get_file_contents("lorem_ipsum_1_line.expected")); -} - -#[test] -fn test_single_1_line() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-n", "1", INPUT])); - assert_eq!(result.stdout, get_file_contents("lorem_ipsum_1_line.expected")); -} - -#[test] -fn test_single_5_chars() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-c", "5", INPUT])); - assert_eq!(result.stdout, get_file_contents("lorem_ipsum_5_chars.expected")); -} - -#[test] -fn test_verbose() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-v", INPUT])); - assert_eq!(result.stdout, get_file_contents("lorem_ipsum_verbose.expected")); -} diff --git a/test/link.rs b/test/link.rs deleted file mode 100644 index 44ce2c2bd..000000000 --- a/test/link.rs +++ /dev/null @@ -1,49 +0,0 @@ -extern crate libc; - -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./link"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_link_existing_file() { - let file = "test_link_existing_file"; - let link = "test_link_existing_file_link"; - - touch(file); - set_file_contents(file, "foobar"); - assert!(file_exists(file)); - - let result = run(Command::new(PROGNAME).args(&[file, link])); - assert_empty_stderr!(result); - assert!(result.success); - assert!(file_exists(file)); - assert!(file_exists(link)); - assert_eq!(get_file_contents(file), get_file_contents(link)); -} - -#[test] -fn test_link_no_circular() { - let link = "test_link_no_circular"; - - let result = run(Command::new(PROGNAME).args(&[link, link])); - assert_eq!(result.stderr, "link: error: No such file or directory (os error 2)\n"); - assert!(!result.success); - assert!(!file_exists(link)); -} - -#[test] -fn test_link_nonexistent_file() { - let file = "test_link_nonexistent_file"; - let link = "test_link_nonexistent_file_link"; - - let result = run(Command::new(PROGNAME).args(&[file, link])); - assert_eq!(result.stderr, "link: error: No such file or directory (os error 2)\n"); - assert!(!result.success); - assert!(!file_exists(file)); - assert!(!file_exists(link)); -} diff --git a/test/ln.rs b/test/ln.rs deleted file mode 100644 index 9020dc0c5..000000000 --- a/test/ln.rs +++ /dev/null @@ -1,354 +0,0 @@ -extern crate libc; - -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./ln"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_symlink_existing_file() { - let file = "test_symlink_existing_file"; - let link = "test_symlink_existing_file_link"; - - touch(file); - - let result = run(Command::new(PROGNAME).args(&["-s", file, link])); - assert_empty_stderr!(result); - assert!(result.success); - assert!(file_exists(file)); - assert!(is_symlink(link)); - assert_eq!(resolve_link(link), file); -} - -#[test] -fn test_symlink_dangling_file() { - let file = "test_symlink_dangling_file"; - let link = "test_symlink_dangling_file_link"; - - let result = run(Command::new(PROGNAME).args(&["-s", file, link])); - assert_empty_stderr!(result); - assert!(result.success); - assert!(!file_exists(file)); - assert!(is_symlink(link)); - assert_eq!(resolve_link(link), file); -} - -#[test] -fn test_symlink_existing_directory() { - let dir = "test_symlink_existing_dir"; - let link = "test_symlink_existing_dir_link"; - - mkdir(dir); - - let result = run(Command::new(PROGNAME).args(&["-s", dir, link])); - assert_empty_stderr!(result); - assert!(result.success); - assert!(dir_exists(dir)); - assert!(is_symlink(link)); - assert_eq!(resolve_link(link), dir); -} - -#[test] -fn test_symlink_dangling_directory() { - let dir = "test_symlink_dangling_dir"; - let link = "test_symlink_dangling_dir_link"; - - let result = run(Command::new(PROGNAME).args(&["-s", dir, link])); - assert_empty_stderr!(result); - assert!(result.success); - assert!(!dir_exists(dir)); - assert!(is_symlink(link)); - assert_eq!(resolve_link(link), dir); -} - -#[test] -fn test_symlink_circular() { - let link = "test_symlink_circular"; - - let result = run(Command::new(PROGNAME).args(&["-s", link])); - assert_empty_stderr!(result); - assert!(result.success); - assert!(is_symlink(link)); - assert_eq!(resolve_link(link), link); -} - -#[test] -fn test_symlink_dont_overwrite() { - let file = "test_symlink_dont_overwrite"; - let link = "test_symlink_dont_overwrite_link"; - - touch(file); - touch(link); - - let result = run(Command::new(PROGNAME).args(&["-s", file, link])); - assert!(!result.success); - assert!(file_exists(file)); - assert!(file_exists(link)); - assert!(!is_symlink(link)); -} - -#[test] -fn test_symlink_overwrite_force() { - let file_a = "test_symlink_overwrite_force_a"; - let file_b = "test_symlink_overwrite_force_b"; - let link = "test_symlink_overwrite_force_link"; - - // Create symlink - symlink(file_a, link); - assert!(is_symlink(link)); - assert_eq!(resolve_link(link), file_a); - - // Force overwrite of existing symlink - let result = run(Command::new(PROGNAME).args(&["--force", "-s", file_b, link])); - assert!(result.success); - assert!(is_symlink(link)); - assert_eq!(resolve_link(link), file_b); -} - -#[test] -fn test_symlink_interactive() { - let file = "test_symlink_interactive_file"; - let link = "test_symlink_interactive_file_link"; - - touch(file); - touch(link); - - let result1 = run_piped_stdin(Command::new(PROGNAME).args(&["-i", "-s", file, link]), b"n"); - - assert_empty_stderr!(result1); - assert!(result1.success); - - assert!(file_exists(file)); - assert!(!is_symlink(link)); - - let result2 = run_piped_stdin(Command::new(PROGNAME).args(&["-i", "-s", file, link]), b"Yesh"); - - assert_empty_stderr!(result2); - assert!(result2.success); - - assert!(file_exists(file)); - assert!(is_symlink(link)); - assert_eq!(resolve_link(link), file); -} - -#[test] -fn test_symlink_simple_backup() { - let file = "test_symlink_simple_backup"; - let link = "test_symlink_simple_backup_link"; - - touch(file); - symlink(file, link); - assert!(file_exists(file)); - assert!(is_symlink(link)); - assert_eq!(resolve_link(link), file); - - let result = run(Command::new(PROGNAME).args(&["-b", "-s", file, link])); - - assert_empty_stderr!(result); - assert!(result.success); - assert!(file_exists(file)); - - assert!(is_symlink(link)); - assert_eq!(resolve_link(link), file); - - let backup = &format!("{}~", link); - assert!(is_symlink(backup)); - assert_eq!(resolve_link(backup), file); -} - -#[test] -fn test_symlink_custom_backup_suffix() { - let file = "test_symlink_custom_backup_suffix"; - let link = "test_symlink_custom_backup_suffix_link"; - let suffix = "super-suffix-of-the-century"; - - touch(file); - symlink(file, link); - assert!(file_exists(file)); - assert!(is_symlink(link)); - assert_eq!(resolve_link(link), file); - - let arg = &format!("--suffix={}", suffix); - let result = run(Command::new(PROGNAME).args(&["-b", arg, "-s", file, link])); - - assert_empty_stderr!(result); - assert!(result.success); - assert!(file_exists(file)); - - assert!(is_symlink(link)); - assert_eq!(resolve_link(link), file); - - let backup = &format!("{}{}", link, suffix); - assert!(is_symlink(backup)); - assert_eq!(resolve_link(backup), file); -} - -#[test] -fn test_symlink_backup_numbering() { - let file = "test_symlink_backup_numbering"; - let link = "test_symlink_backup_numbering_link"; - - touch(file); - symlink(file, link); - assert!(file_exists(file)); - assert!(is_symlink(link)); - assert_eq!(resolve_link(link), file); - - let result = run(Command::new(PROGNAME).args(&["-s", "--backup=t", file, link])); - - assert_empty_stderr!(result); - assert!(result.success); - assert!(file_exists(file)); - - assert!(is_symlink(link)); - assert_eq!(resolve_link(link), file); - - let backup = &format!("{}.~1~", link); - assert!(is_symlink(backup)); - assert_eq!(resolve_link(backup), file); -} - -#[test] -fn test_symlink_existing_backup() { - let file = "test_symlink_existing_backup"; - let link = "test_symlink_existing_backup_link"; - let link_backup = "test_symlink_existing_backup_link.~1~"; - let resulting_backup = "test_symlink_existing_backup_link.~2~"; - - // Create symlink and verify - touch(file); - symlink(file, link); - assert!(file_exists(file)); - assert!(is_symlink(link)); - assert_eq!(resolve_link(link), file); - - // Create backup symlink and verify - symlink(file, link_backup); - assert!(file_exists(file)); - assert!(is_symlink(link_backup)); - assert_eq!(resolve_link(link_backup), file); - - let result = run(Command::new(PROGNAME).args(&["-s", "--backup=nil", file, link])); - - assert_empty_stderr!(result); - assert!(result.success); - assert!(file_exists(file)); - - assert!(is_symlink(link_backup)); - assert_eq!(resolve_link(link_backup), file); - - assert!(is_symlink(resulting_backup)); - assert_eq!(resolve_link(resulting_backup), file); -} - -#[test] -fn test_symlink_target_dir() { - let dir = "test_ln_target_dir_dir"; - let file_a = "test_ln_target_dir_file_a"; - let file_b = "test_ln_target_dir_file_b"; - - touch(file_a); - touch(file_b); - mkdir(dir); - - let result = run(Command::new(PROGNAME).args(&["-s", "-t", dir, file_a, file_b])); - - assert_empty_stderr!(result); - assert!(result.success); - - let file_a_link = &format!("{}/{}", dir, file_a); - assert!(is_symlink(file_a_link)); - assert_eq!(resolve_link(file_a_link), file_a); - - let file_b_link = &format!("{}/{}", dir, file_b); - assert!(is_symlink(file_b_link)); - assert_eq!(resolve_link(file_b_link), file_b); -} - -#[test] -fn test_symlink_overwrite_dir() { - let path_a = "test_symlink_overwrite_dir_a"; - let path_b = "test_symlink_overwrite_dir_b"; - - touch(path_a); - mkdir(path_b); - - let result = run(Command::new(PROGNAME).args(&["-s", "-T", path_a, path_b])); - - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(path_a)); - assert!(is_symlink(path_b)); - assert_eq!(resolve_link(path_b), path_a); -} - -#[test] -fn test_symlink_overwrite_nonempty_dir() { - let path_a = "test_symlink_overwrite_nonempty_dir_a"; - let path_b = "test_symlink_overwrite_nonempty_dir_b"; - let dummy = "test_symlink_overwrite_nonempty_dir_b/file"; - - touch(path_a); - mkdir(path_b); - touch(dummy); - - let result = run(Command::new(PROGNAME).args(&["-v", "-T", "-s", path_a, path_b])); - - // Not same error as GNU; the error message is a Rust builtin - // TODO: test (and implement) correct error message (or at least decide whether to do so) - // Current: "ln: error: Directory not empty (os error 66)" - // GNU: "ln: cannot link 'a' to 'b': Directory not empty" - assert!(result.stderr.len() > 0); - - // Verbose output for the link should not be shown on failure - assert!(result.stdout.len() == 0); - - assert!(!result.success); - assert!(file_exists(path_a)); - assert!(dir_exists(path_b)); -} - -#[test] -fn test_symlink_errors() { - let dir = "test_symlink_errors_dir"; - let file_a = "test_symlink_errors_file_a"; - let file_b = "test_symlink_errors_file_b"; - - mkdir(dir); - touch(file_a); - touch(file_b); - - // $ ln -T -t a b - // ln: cannot combine --target-directory (-t) and --no-target-directory (-T) - let result = run(Command::new(PROGNAME).args(&["-T", "-t", dir, file_a, file_b])); - assert_eq!(result.stderr, - "ln: error: cannot combine --target-directory (-t) and --no-target-directory (-T)\n"); - assert!(!result.success); -} - -#[test] -fn test_symlink_verbose() { - let file_a = "test_symlink_verbose_file_a"; - let file_b = "test_symlink_verbose_file_b"; - - touch(file_a); - - let result = run(Command::new(PROGNAME).args(&["-v", file_a, file_b])); - assert_empty_stderr!(result); - assert_eq!(result.stdout, - format!("'{}' -> '{}'\n", file_b, file_a)); - assert!(result.success); - - touch(file_b); - - let result = run(Command::new(PROGNAME).args(&["-v", "-b", file_a, file_b])); - assert_empty_stderr!(result); - assert_eq!(result.stdout, - format!("'{}' -> '{}' (backup: '{}~')\n", file_b, file_a, file_b)); - assert!(result.success); -} diff --git a/test/mkdir.rs b/test/mkdir.rs deleted file mode 100644 index 463688dc1..000000000 --- a/test/mkdir.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./mkdir"; -static TEST_DIR1: &'static str = "mkdir_test1"; -static TEST_DIR2: &'static str = "mkdir_test2"; -static TEST_DIR3: &'static str = "mkdir_test3"; -static TEST_DIR4: &'static str = "mkdir_test4/mkdir_test4_1"; -static TEST_DIR5: &'static str = "mkdir_test5/mkdir_test5_1"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_mkdir_mkdir() { - let mut cmd = Command::new(PROGNAME); - let exit_success = run(&mut cmd.arg(TEST_DIR1)).success; - cleanup(TEST_DIR1); - assert_eq!(exit_success, true); -} - -#[test] -fn test_mkdir_dup_dir() { - let mut cmd = Command::new(PROGNAME); - let exit_success = run(&mut cmd.arg(TEST_DIR2)).success; - if !exit_success { - cleanup(TEST_DIR2); - panic!(); - } - let exit_success2 = run(&mut cmd.arg(TEST_DIR2)).success; - cleanup(TEST_DIR2); - assert_eq!(exit_success2, false); -} - -#[test] -fn test_mkdir_mode() { - let mut cmd = Command::new(PROGNAME); - let exit_success = run(&mut cmd.arg("-m").arg("755").arg(TEST_DIR3)).success; - cleanup(TEST_DIR3); - assert_eq!(exit_success, true); -} - -#[test] -fn test_mkdir_parent() { - let mut cmd = Command::new(PROGNAME); - let exit_success = run(&mut cmd.arg("-p").arg(TEST_DIR4)).success; - cleanup(TEST_DIR4); - assert_eq!(exit_success, true); -} - -#[test] -fn test_mkdir_no_parent() { - let mut cmd = Command::new(PROGNAME); - let exit_success = run(&mut cmd.arg(TEST_DIR5)).success; - cleanup(TEST_DIR5); - assert_eq!(exit_success, false); -} diff --git a/test/mv.rs b/test/mv.rs deleted file mode 100644 index 9ab811ae9..000000000 --- a/test/mv.rs +++ /dev/null @@ -1,446 +0,0 @@ -extern crate libc; -extern crate time; -extern crate kernel32; -extern crate winapi; -extern crate filetime; - -use filetime::*; -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./mv"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_mv_rename_dir() { - let dir1 = "test_mv_rename_dir"; - let dir2 = "test_mv_rename_dir2"; - - mkdir(dir1); - - let result = run(Command::new(PROGNAME).arg(dir1).arg(dir2)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(dir_exists(dir2)); -} - -#[test] -fn test_mv_rename_file() { - let file1 = "test_mv_rename_file"; - let file2 = "test_mv_rename_file2"; - - touch(file1); - - let result = run(Command::new(PROGNAME).arg(file1).arg(file2)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(file2)); -} - -#[test] -fn test_mv_move_file_into_dir() { - let dir = "test_mv_move_file_into_dir_dir"; - let file = "test_mv_move_file_into_dir_file"; - - mkdir(dir); - touch(file); - - let result = run(Command::new(PROGNAME).arg(file).arg(dir)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(&format!("{}/{}", dir, file))); -} - -#[test] -fn test_mv_strip_slashes() { - let dir = "test_mv_strip_slashes_dir"; - let file = "test_mv_strip_slashes_file"; - let mut source = file.to_owned(); - source.push_str("/"); - - mkdir(dir); - touch(file); - - let result = run(Command::new(PROGNAME).arg(&source).arg(dir)); - assert!(!result.success); - - assert!(!file_exists(&format!("{}/{}", dir, file))); - - let result = run(Command::new(PROGNAME).arg("--strip-trailing-slashes").arg(source).arg(dir)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(&format!("{}/{}", dir, file))); -} - -#[test] -fn test_mv_multiple_files() { - let target_dir = "test_mv_multiple_files_dir"; - let file_a = "test_mv_multiple_file_a"; - let file_b = "test_mv_multiple_file_b"; - - mkdir(target_dir); - touch(file_a); - touch(file_b); - - let result = run(Command::new(PROGNAME).arg(file_a).arg(file_b).arg(target_dir)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(&format!("{}/{}", target_dir, file_a))); - assert!(file_exists(&format!("{}/{}", target_dir, file_b))); -} - -#[test] -fn test_mv_multiple_folders() { - let target_dir = "test_mv_multiple_dirs_dir"; - let dir_a = "test_mv_multiple_dir_a"; - let dir_b = "test_mv_multiple_dir_b"; - - mkdir(target_dir); - mkdir(dir_a); - mkdir(dir_b); - - let result = run(Command::new(PROGNAME).arg(dir_a).arg(dir_b).arg(target_dir)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(dir_exists(&format!("{}/{}", target_dir, dir_a))); - assert!(dir_exists(&format!("{}/{}", target_dir, dir_b))); -} - -#[test] -fn test_mv_interactive() { - let file_a = "test_mv_interactive_file_a"; - let file_b = "test_mv_interactive_file_b"; - - touch(file_a); - touch(file_b); - - - let result1 = run_piped_stdin(Command::new(PROGNAME).arg("-i").arg(file_a).arg(file_b), b"n"); - - assert_empty_stderr!(result1); - assert!(result1.success); - - assert!(file_exists(file_a)); - assert!(file_exists(file_b)); - - - let result2 = run_piped_stdin(Command::new(PROGNAME).arg("-i").arg(file_a).arg(file_b), b"Yesh"); - - assert_empty_stderr!(result2); - assert!(result2.success); - - assert!(!file_exists(file_a)); - assert!(file_exists(file_b)); -} - -#[test] -fn test_mv_no_clobber() { - let file_a = "test_mv_no_clobber_file_a"; - let file_b = "test_mv_no_clobber_file_b"; - - touch(file_a); - touch(file_b); - - let result = run(Command::new(PROGNAME).arg("-n").arg(file_a).arg(file_b)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(file_a)); - assert!(file_exists(file_b)); -} - -#[test] -fn test_mv_replace_file() { - let file_a = "test_mv_replace_file_a"; - let file_b = "test_mv_replace_file_b"; - - touch(file_a); - touch(file_b); - - let result = run(Command::new(PROGNAME).arg(file_a).arg(file_b)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(!file_exists(file_a)); - assert!(file_exists(file_b)); -} - -#[test] -fn test_mv_force_replace_file() { - let file_a = "test_mv_force_replace_file_a"; - let file_b = "test_mv_force_replace_file_b"; - - touch(file_a); - touch(file_b); - - let result = run(Command::new(PROGNAME).arg("--force").arg(file_a).arg(file_b)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(!file_exists(file_a)); - assert!(file_exists(file_b)); -} - -#[test] -fn test_mv_simple_backup() { - let file_a = "test_mv_simple_backup_file_a"; - let file_b = "test_mv_simple_backup_file_b"; - - touch(file_a); - touch(file_b); - let result = run(Command::new(PROGNAME).arg("-b").arg(file_a).arg(file_b)); - - assert_empty_stderr!(result); - assert!(result.success); - - assert!(!file_exists(file_a)); - assert!(file_exists(file_b)); - assert!(file_exists(&format!("{}~", file_b))); -} - -#[test] -fn test_mv_custom_backup_suffix() { - let file_a = "test_mv_custom_backup_suffix_file_a"; - let file_b = "test_mv_custom_backup_suffix_file_b"; - let suffix = "super-suffix-of-the-century"; - - touch(file_a); - touch(file_b); - let result = run(Command::new(PROGNAME) - .arg("-b").arg(format!("--suffix={}", suffix)) - .arg(file_a).arg(file_b)); - - assert_empty_stderr!(result); - assert!(result.success); - - assert!(!file_exists(file_a)); - assert!(file_exists(file_b)); - assert!(file_exists(&format!("{}{}", file_b, suffix))); -} - -#[test] -fn test_mv_backup_numbering() { - let file_a = "test_mv_backup_numbering_file_a"; - let file_b = "test_mv_backup_numbering_file_b"; - - touch(file_a); - touch(file_b); - let result = run(Command::new(PROGNAME).arg("--backup=t").arg(file_a).arg(file_b)); - - assert_empty_stderr!(result); - assert!(result.success); - - assert!(!file_exists(file_a)); - assert!(file_exists(file_b)); - assert!(file_exists(&format!("{}.~1~", file_b))); -} - -#[test] -fn test_mv_existing_backup() { - let file_a = "test_mv_existing_backup_file_a"; - let file_b = "test_mv_existing_backup_file_b"; - let file_b_backup = "test_mv_existing_backup_file_b.~1~"; - let resulting_backup = "test_mv_existing_backup_file_b.~2~"; - - touch(file_a); - touch(file_b); - touch(file_b_backup); - let result = run(Command::new(PROGNAME).arg("--backup=nil").arg(file_a).arg(file_b)); - - assert_empty_stderr!(result); - assert!(result.success); - - assert!(!file_exists(file_a)); - assert!(file_exists(file_b)); - assert!(file_exists(file_b_backup)); - assert!(file_exists(resulting_backup)); -} - -#[test] -fn test_mv_update_option() { - let file_a = "test_mv_update_option_file_a"; - let file_b = "test_mv_update_option_file_b"; - - touch(file_a); - touch(file_b); - let ts = time::now().to_timespec(); - let now = FileTime::from_seconds_since_1970(ts.sec as u64, ts.nsec as u32); - let later = FileTime::from_seconds_since_1970(ts.sec as u64 + 3600, ts.nsec as u32); - filetime::set_file_times(file_a, now, now).unwrap(); - filetime::set_file_times(file_b, now, later).unwrap(); - - let result1 = run(Command::new(PROGNAME).arg("--update").arg(file_a).arg(file_b)); - - assert_empty_stderr!(result1); - assert!(result1.success); - - assert!(file_exists(file_a)); - assert!(file_exists(file_b)); - - let result2 = run(Command::new(PROGNAME).arg("--update").arg(file_b).arg(file_a)); - - assert_empty_stderr!(result2); - assert!(result2.success); - - assert!(file_exists(file_a)); - assert!(!file_exists(file_b)); -} - -#[test] -fn test_mv_target_dir() { - let dir = "test_mv_target_dir_dir"; - let file_a = "test_mv_target_dir_file_a"; - let file_b = "test_mv_target_dir_file_b"; - - touch(file_a); - touch(file_b); - mkdir(dir); - let result = run(Command::new(PROGNAME).arg("-t").arg(dir).arg(file_a).arg(file_b)); - - assert_empty_stderr!(result); - assert!(result.success); - - assert!(!file_exists(file_a)); - assert!(!file_exists(file_b)); - assert!(file_exists(&format!("{}/{}", dir, file_a))); - assert!(file_exists(&format!("{}/{}", dir, file_b))); -} - -#[test] -fn test_mv_overwrite_dir() { - let dir_a = "test_mv_overwrite_dir_a"; - let dir_b = "test_mv_overwrite_dir_b"; - - mkdir(dir_a); - mkdir(dir_b); - let result = run(Command::new(PROGNAME).arg("-T").arg(dir_a).arg(dir_b)); - - assert_empty_stderr!(result); - assert!(result.success); - - assert!(!dir_exists(dir_a)); - assert!(dir_exists(dir_b)); -} - -#[test] -fn test_mv_overwrite_nonempty_dir() { - let dir_a = "test_mv_overwrite_nonempty_dir_a"; - let dir_b = "test_mv_overwrite_nonempty_dir_b"; - let dummy = "test_mv_overwrite_nonempty_dir_b/file"; - - mkdir(dir_a); - mkdir(dir_b); - touch(dummy); - let result = run(Command::new(PROGNAME).arg("-vT").arg(dir_a).arg(dir_b)); - - // Not same error as GNU; the error message is a rust builtin - // TODO: test (and implement) correct error message (or at least decide whether to do so) - // Current: "mv: error: couldn't rename path (Directory not empty; from=a; to=b)" - // GNU: "mv: cannot move ‘a’ to ‘b’: Directory not empty" - assert!(result.stderr.len() > 0); - - // Verbose output for the move should not be shown on failure - assert!(result.stdout.len() == 0); - - assert!(!result.success); - assert!(dir_exists(dir_a)); - assert!(dir_exists(dir_b)); -} - -#[test] -fn test_mv_backup_dir() { - let dir_a = "test_mv_backup_dir_dir_a"; - let dir_b = "test_mv_backup_dir_dir_b"; - - mkdir(dir_a); - mkdir(dir_b); - let result = run(Command::new(PROGNAME).arg("-vbT").arg(dir_a).arg(dir_b)); - - assert_empty_stderr!(result); - assert_eq!(result.stdout, - format!("‘{}’ -> ‘{}’ (backup: ‘{}~’)\n", dir_a, dir_b, dir_b)); - assert!(result.success); - - assert!(!dir_exists(dir_a)); - assert!(dir_exists(dir_b)); - assert!(dir_exists(&format!("{}~", dir_b))); -} - -#[test] -fn test_mv_errors() { - let dir = "test_mv_errors_dir"; - let file_a = "test_mv_errors_file_a"; - let file_b = "test_mv_errors_file_b"; - mkdir(dir); - touch(file_a); - touch(file_b); - - // $ mv -T -t a b - // mv: cannot combine --target-directory (-t) and --no-target-directory (-T) - let result = run(Command::new(PROGNAME).arg("-T").arg("-t").arg(dir).arg(file_a).arg(file_b)); - assert_eq!(result.stderr, - "mv: error: cannot combine --target-directory (-t) and --no-target-directory (-T)\n"); - assert!(!result.success); - - - // $ touch file && mkdir dir - // $ mv -T file dir - // err == mv: cannot overwrite directory ‘dir’ with non-directory - let result = run(Command::new(PROGNAME).arg("-T").arg(file_a).arg(dir)); - assert_eq!(result.stderr, - format!("mv: error: cannot overwrite directory ‘{}’ with non-directory\n", dir)); - assert!(!result.success); - - // $ mkdir dir && touch file - // $ mv dir file - // err == mv: cannot overwrite non-directory ‘file’ with directory ‘dir’ - let result = run(Command::new(PROGNAME).arg(dir).arg(file_a)); - assert!(result.stderr.len() > 0); - assert!(!result.success); -} - -#[test] -fn test_mv_verbose() { - let dir = "test_mv_verbose_dir"; - let file_a = "test_mv_verbose_file_a"; - let file_b = "test_mv_verbose_file_b"; - mkdir(dir); - touch(file_a); - touch(file_b); - - let result = run(Command::new(PROGNAME).arg("-v").arg(file_a).arg(file_b)); - assert_empty_stderr!(result); - assert_eq!(result.stdout, - format!("‘{}’ -> ‘{}’\n", file_a, file_b)); - assert!(result.success); - - - touch(file_a); - let result = run(Command::new(PROGNAME).arg("-vb").arg(file_a).arg(file_b)); - assert_empty_stderr!(result); - assert_eq!(result.stdout, - format!("‘{}’ -> ‘{}’ (backup: ‘{}~’)\n", file_a, file_b, file_b)); - assert!(result.success); -} - -// Todo: - -// $ touch a b -// $ chmod -w b -// $ ll -// total 0 -// -rw-rw-r-- 1 user user 0 okt 25 11:21 a -// -r--r--r-- 1 user user 0 okt 25 11:21 b -// $ -// $ mv -v a b -// mv: try to overwrite ‘b’, overriding mode 0444 (r--r--r--)? y -// ‘a’ -> ‘b’ diff --git a/test/nl.rs b/test/nl.rs deleted file mode 100644 index 29626908a..000000000 --- a/test/nl.rs +++ /dev/null @@ -1,53 +0,0 @@ -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./nl"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_stdin_nonewline() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd, "No Newline".as_bytes()); - assert_eq!(result.stdout, " 1\tNo Newline\n"); -} -#[test] -fn test_stdin_newline() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-s", "-", "-w", "1"]), "Line One\nLine Two\n".as_bytes()); - assert_eq!(result.stdout, "1-Line One\n2-Line Two\n"); -} - -#[test] -fn test_padding_without_overflow() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-i", "1000", "-s", "x", "-n", "rz", "simple.txt"])); - assert_eq!(result.stdout, "000001xL1\n001001xL2\n002001xL3\n003001xL4\n004001xL5\n005001xL6\n006001xL7\n007001xL8\n008001xL9\n009001xL10\n010001xL11\n011001xL12\n012001xL13\n013001xL14\n014001xL15\n"); -} - -#[test] -fn test_padding_with_overflow() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-i", "1000", "-s", "x", "-n", "rz", "-w", "4", "simple.txt"])); - assert_eq!(result.stdout, "0001xL1\n1001xL2\n2001xL3\n3001xL4\n4001xL5\n5001xL6\n6001xL7\n7001xL8\n8001xL9\n9001xL10\n10001xL11\n11001xL12\n12001xL13\n13001xL14\n14001xL15\n"); -} - -#[test] -fn test_sections_and_styles() { - for &(fixture, output) in [ - ( - "section.txt", - "\nHEADER1\nHEADER2\n\n1 |BODY1\n2 |BODY2\n\nFOOTER1\nFOOTER2\n\nNEXTHEADER1\nNEXTHEADER2\n\n1 |NEXTBODY1\n2 |NEXTBODY2\n\nNEXTFOOTER1\nNEXTFOOTER2\n" - ), - ( - "joinblanklines.txt", - "1 |Nonempty\n2 |Nonempty\n3 |Followed by 10x empty\n\n\n\n\n4 |\n\n\n\n\n5 |\n6 |Followed by 5x empty\n\n\n\n\n7 |\n8 |Followed by 4x empty\n\n\n\n\n9 |Nonempty\n10 |Nonempty\n11 |Nonempty.\n" - ), - ].iter() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-s", "|", "-n", "ln", "-w", "3", "-b", "a", "-l", "5", fixture])); - assert_eq!(result.stdout, output); - } -} diff --git a/test/paste.rs b/test/paste.rs deleted file mode 100644 index b66ed01e7..000000000 --- a/test/paste.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::fs::File; -use std::io::Read; -use std::path::Path; -use std::process::Command; - -static PROGNAME: &'static str = "./paste"; - -#[test] -fn test_combine_pairs_of_lines() { - let po = Command::new(PROGNAME) - .arg("-s") - .arg("-d") - .arg("\t\n") - .arg("html_colors.txt") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let mut f = File::open(Path::new("html_colors.expected")).unwrap_or_else(|err| { - panic!("{}", err) - }); - let mut expected = vec!(); - match f.read_to_end(&mut expected) { - Ok(_) => {}, - Err(err) => panic!("{}", err) - } - assert_eq!(String::from_utf8(po.stdout).unwrap(), String::from_utf8(expected).unwrap()); -} diff --git a/test/ptx.rs b/test/ptx.rs deleted file mode 100644 index 1c4d4e730..000000000 --- a/test/ptx.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./ptx"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn gnu_ext_disabled_roff_no_ref() { - let opts = vec!["-G", "-R"]; - test_ptx(&opts, "gnu_ext_disabled_roff_no_ref.expected"); -} - -#[test] -fn gnu_ext_disabled_roff_input_ref() { - let opts = vec!["-G", "-r", "-R"]; - test_ptx(&opts, "gnu_ext_disabled_roff_input_ref.expected"); -} - -#[test] -fn gnu_ext_disabled_roff_auto_ref() { - let opts = vec!["-G", "-A", "-R"]; - test_ptx(&opts, "gnu_ext_disabled_roff_auto_ref.expected"); -} - -#[test] -fn gnu_ext_disabled_tex_no_ref() { - let opts = vec!["-G", "-T", "-R"]; - test_ptx(&opts, "gnu_ext_disabled_tex_no_ref.expected"); -} - -#[test] -fn gnu_ext_disabled_tex_input_ref() { - let opts = vec!["-G", "-T", "-r", "-R"]; - test_ptx(&opts, "gnu_ext_disabled_tex_input_ref.expected"); -} - -#[test] -fn gnu_ext_disabled_tex_auto_ref() { - let opts = vec!["-G", "-T", "-A", "-R"]; - test_ptx(&opts, "gnu_ext_disabled_tex_auto_ref.expected"); -} - -#[test] -fn gnu_ext_disabled_ignore_and_only_file() { - let opts = vec!["-G", "-o", "only", "-i", "ignore"]; - test_ptx(&opts, "gnu_ext_disabled_ignore_and_only_file.expected"); -} - -fn test_ptx(opts: &Vec<&str>, expected: &str) { - let mut ptx = Command::new(PROGNAME); - let result = run(&mut ptx.args(opts).arg("input")); - assert!(result.success); - assert_eq!(result.stdout, get_file_contents(expected)); - assert_empty_stderr!(&result); -} diff --git a/test/pwd.rs b/test/pwd.rs deleted file mode 100644 index 0800b3ae4..000000000 --- a/test/pwd.rs +++ /dev/null @@ -1,16 +0,0 @@ -use std::env; -use std::process::Command; -use std::str; - -static PROGNAME: &'static str = "./pwd"; - -#[test] -fn test_default() { - let po = Command::new(PROGNAME) - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap().trim_right(); - let expected = env::current_dir().unwrap().into_os_string().into_string().unwrap(); - assert_eq!(out, expected); -} diff --git a/test/readlink.rs b/test/readlink.rs deleted file mode 100644 index 6471d1d92..000000000 --- a/test/readlink.rs +++ /dev/null @@ -1,80 +0,0 @@ -use std::process::Command; -use std::str; -use util::*; - -static PROGNAME: &'static str = "./readlink"; -static GIBBERISH: &'static str = "supercalifragilisticexpialidocious"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_canonicalize() { - let po = Command::new(PROGNAME) - .arg("-f") - .arg(".") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap().trim_right(); - assert_eq!(out, current_directory()); -} - -#[test] -fn test_canonicalize_existing() { - let po = Command::new(PROGNAME) - .arg("-e") - .arg(".") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap().trim_right(); - assert_eq!(out, current_directory()); -} - -#[test] -fn test_canonicalize_missing() { - let mut expected = current_directory(); - expected.push_str("/"); - expected.push_str(GIBBERISH); - - let po = Command::new(PROGNAME) - .arg("-m") - .arg(GIBBERISH) - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap().trim_right(); - assert_eq!(out, expected); -} - -#[test] -fn test_long_redirection_to_current_dir() { - // Create a 256-character path to current directory - let dir = repeat_str("./", 128); - let po = Command::new(PROGNAME) - .arg("-n") - .arg("-m") - .arg(dir) - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap(); - assert_eq!(out, current_directory()); -} - -#[test] -fn test_long_redirection_to_root() { - // Create a 255-character path to root - let dir = repeat_str("../", 85); - let po = Command::new(PROGNAME) - .arg("-n") - .arg("-m") - .arg(dir) - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap(); - assert_eq!(out, "/"); -} diff --git a/test/realpath.rs b/test/realpath.rs deleted file mode 100644 index 53cd539da..000000000 --- a/test/realpath.rs +++ /dev/null @@ -1,46 +0,0 @@ -use std::process::Command; -use std::str; -use util::*; - -static PROGNAME: &'static str = "./realpath"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_current_directory() { - let po = Command::new(PROGNAME) - .arg(".") - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap().trim_right(); - assert_eq!(out, current_directory()); -} - -#[test] -fn test_long_redirection_to_current_dir() { - // Create a 256-character path to current directory - let dir = repeat_str("./", 128); - let po = Command::new(PROGNAME) - .arg(dir) - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap().trim_right(); - assert_eq!(out, current_directory()); -} - -#[test] -fn test_long_redirection_to_root() { - // Create a 255-character path to root - let dir = repeat_str("../", 85); - let po = Command::new(PROGNAME) - .arg(dir) - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - let out = str::from_utf8(&po.stdout[..]).unwrap().trim_right(); - assert_eq!(out, "/"); -} diff --git a/test/rm.rs b/test/rm.rs deleted file mode 100644 index 5eede78b9..000000000 --- a/test/rm.rs +++ /dev/null @@ -1,140 +0,0 @@ -extern crate libc; - -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./rm"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_rm_one_file() { - let file = "test_rm_one_file"; - - touch(file); - - let result = run(Command::new(PROGNAME).arg(file)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(!file_exists(file)); -} - -#[test] -fn test_rm_multiple_files() { - let file_a = "test_rm_multiple_file_a"; - let file_b = "test_rm_multiple_file_b"; - - touch(file_a); - touch(file_b); - - let result = run(Command::new(PROGNAME).arg(file_a).arg(file_b)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(!file_exists(file_a)); - assert!(!file_exists(file_b)); -} - -#[test] -fn test_rm_interactive() { - let file_a = "test_rm_interactive_file_a"; - let file_b = "test_rm_interactive_file_b"; - - touch(file_a); - touch(file_b); - - let result1 = run_piped_stdin(Command::new(PROGNAME).arg("-i").arg(file_a).arg(file_b), b"n"); - - assert!(result1.success); - - assert!(file_exists(file_a)); - assert!(file_exists(file_b)); - - let result2 = run_piped_stdin(Command::new(PROGNAME).arg("-i").arg(file_a).arg(file_b), b"Yesh"); - - assert!(result2.success); - - assert!(!file_exists(file_a)); - assert!(file_exists(file_b)); -} - -#[test] -fn test_rm_force() { - let file_a = "test_rm_force_a"; - let file_b = "test_rm_force_b"; - - let result = run(Command::new(PROGNAME).arg("-f").arg(file_a).arg(file_b)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(!file_exists(file_a)); - assert!(!file_exists(file_b)); -} - -#[test] -fn test_rm_empty_directory() { - let dir = "test_rm_empty_directory"; - - mkdir(dir); - - let result = run(Command::new(PROGNAME).arg("-d").arg(dir)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(!dir_exists(dir)); -} - -#[test] -fn test_rm_recursive() { - let dir = "test_rm_recursive_directory"; - let file_a = "test_rm_recursive_directory/test_rm_recursive_file_a"; - let file_b = "test_rm_recursive_directory/test_rm_recursive_file_b"; - - mkdir(dir); - touch(file_a); - touch(file_b); - - let result = run(Command::new(PROGNAME).arg("-r").arg(dir)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(!dir_exists(dir)); - assert!(!file_exists(file_a)); - assert!(!file_exists(file_b)); -} - -#[test] -fn test_rm_errors() { - let dir = "test_rm_errors_directory"; - let file_a = "test_rm_errors_directory/test_rm_errors_file_a"; - let file_b = "test_rm_errors_directory/test_rm_errors_file_b"; - - mkdir(dir); - touch(file_a); - touch(file_b); - - // $ rm test_rm_errors_directory - // rm: error: could not remove directory 'test_rm_errors_directory' (did you mean to pass '-r'?) - let result = run(Command::new(PROGNAME).arg(dir)); - assert_eq!(result.stderr, - "rm: error: could not remove directory 'test_rm_errors_directory' (did you mean to pass '-r'?)\n"); - assert!(!result.success); -} - -#[test] -fn test_rm_verbose() { - let file_a = "test_rm_verbose_file_a"; - let file_b = "test_rm_verbose_file_b"; - - touch(file_a); - touch(file_b); - - let result = run(Command::new(PROGNAME).arg("-v").arg(file_a).arg(file_b)); - assert_empty_stderr!(result); - assert_eq!(result.stdout, - format!("removed '{}'\nremoved '{}'\n", file_a, file_b)); - assert!(result.success); -} diff --git a/test/rmdir.rs b/test/rmdir.rs deleted file mode 100644 index d85265d74..000000000 --- a/test/rmdir.rs +++ /dev/null @@ -1,114 +0,0 @@ -extern crate libc; - -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./rmdir"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_rmdir_empty_directory_no_parents() { - let dir = "test_rmdir_empty_no_parents"; - - mkdir(dir); - assert!(dir_exists(dir)); - - let result = run(Command::new(PROGNAME).arg(dir)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(!dir_exists(dir)); -} - -#[test] -fn test_rmdir_empty_directory_with_parents() { - let dir = "test_rmdir_empty/with/parents"; - - mkdir_all(dir); - assert!(dir_exists(dir)); - - let result = run(Command::new(PROGNAME).arg("-p").arg(dir)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(!dir_exists(dir)); -} - -#[test] -fn test_rmdir_nonempty_directory_no_parents() { - let dir = "test_rmdir_nonempty_no_parents"; - let file = "test_rmdir_nonempty_no_parents/foo"; - - mkdir(dir); - assert!(dir_exists(dir)); - - touch(file); - assert!(file_exists(file)); - - let result = run(Command::new(PROGNAME).arg(dir)); - assert_eq!(result.stderr, - "rmdir: error: failed to remove 'test_rmdir_nonempty_no_parents': Directory not empty\n"); - assert!(!result.success); - - assert!(dir_exists(dir)); -} - -#[test] -fn test_rmdir_nonempty_directory_with_parents() { - let dir = "test_rmdir_nonempty/with/parents"; - let file = "test_rmdir_nonempty/with/parents/foo"; - - mkdir_all(dir); - assert!(dir_exists(dir)); - - touch(file); - assert!(file_exists(file)); - - let result = run(Command::new(PROGNAME).arg("-p").arg(dir)); - assert_eq!(result.stderr, - "rmdir: error: failed to remove 'test_rmdir_nonempty/with/parents': Directory not empty\n\ - rmdir: error: failed to remove 'test_rmdir_nonempty/with': Directory not empty\n\ - rmdir: error: failed to remove 'test_rmdir_nonempty': Directory not empty\n"); - assert!(!result.success); - - assert!(dir_exists(dir)); -} - -#[test] -fn test_rmdir_ignore_nonempty_directory_no_parents() { - let dir = "test_rmdir_ignore_nonempty_no_parents"; - let file = "test_rmdir_ignore_nonempty_no_parents/foo"; - - mkdir(dir); - assert!(dir_exists(dir)); - - touch(file); - assert!(file_exists(file)); - - let result = run(Command::new(PROGNAME).arg("--ignore-fail-on-non-empty").arg(dir)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(dir_exists(dir)); -} - -#[test] -fn test_rmdir_ignore_nonempty_directory_with_parents() { - let dir = "test_rmdir_ignore_nonempty/with/parents"; - let file = "test_rmdir_ignore_nonempty/with/parents/foo"; - - mkdir_all(dir); - assert!(dir_exists(dir)); - - touch(file); - assert!(file_exists(file)); - - let result = run(Command::new(PROGNAME).arg("--ignore-fail-on-non-empty").arg("-p").arg(dir)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(dir_exists(dir)); -} diff --git a/test/seq.rs b/test/seq.rs deleted file mode 100644 index 806435f33..000000000 --- a/test/seq.rs +++ /dev/null @@ -1,32 +0,0 @@ -use std::process::Command; -use std::str; - -static PROGNAME: &'static str = "./seq"; - -#[test] -fn test_count_up() { - let p = Command::new(PROGNAME).args(&["10"]).output().unwrap(); - let out = str::from_utf8(&p.stdout).unwrap(); - assert_eq!(out, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n"); -} - -#[test] -fn test_count_down() { - let p = Command::new(PROGNAME).args(&["--", "5", "-1", "1"]).output().unwrap(); - let out = str::from_utf8(&p.stdout).unwrap(); - assert_eq!(out, "5\n4\n3\n2\n1\n"); -} - -#[test] -fn test_separator_and_terminator() { - let p = Command::new(PROGNAME).args(&["-s", ",", "-t", "!", "2", "6"]).output().unwrap(); - let out = str::from_utf8(&p.stdout).unwrap(); - assert_eq!(out, "2,3,4,5,6!"); -} - -#[test] -fn test_equalize_widths() { - let p = Command::new(PROGNAME).args(&["-w", "5", "10"]).output().unwrap(); - let out = str::from_utf8(&p.stdout).unwrap(); - assert_eq!(out, "05\n06\n07\n08\n09\n10\n"); -} diff --git a/test/sort.rs b/test/sort.rs deleted file mode 100644 index aa630210c..000000000 --- a/test/sort.rs +++ /dev/null @@ -1,65 +0,0 @@ -use std::fs::File; -use std::io::Read; -use std::path::Path; -use std::process::Command; - -static PROGNAME: &'static str = "./sort"; - -#[test] -fn numeric1() { - numeric_helper(1); -} - -#[test] -fn numeric2() { - numeric_helper(2); -} - -#[test] -fn numeric3() { - numeric_helper(3); -} - -#[test] -fn numeric4() { - numeric_helper(4); -} - -#[test] -fn numeric5() { - numeric_helper(5); -} - -#[test] -fn numeric6() { - numeric_helper(6); -} - -#[test] -fn human1() { - test_helper(&String::from("human1"), &String::from("-H")); -} - -fn numeric_helper(test_num: isize) { - test_helper(&format!("numeric{}", test_num), &String::from("-n")) -} - -fn test_helper(file_name: &String, args: &String) { - let mut cmd = Command::new(PROGNAME); - cmd.arg(args); - let po = match cmd.arg(format!("{}{}", file_name, ".txt")).output() { - Ok(p) => p, - Err(err) => panic!("{}", err) - }; - - let filename = format!("{}{}", file_name, ".ans"); - let mut f = File::open(Path::new(&filename)).unwrap_or_else(|err| { - panic!("{}", err) - }); - let mut answer = vec!(); - match f.read_to_end(&mut answer) { - Ok(_) => {}, - Err(err) => panic!("{}", err) - } - assert_eq!(String::from_utf8(po.stdout).unwrap(), String::from_utf8(answer).unwrap()); -} diff --git a/test/split.rs b/test/split.rs deleted file mode 100644 index 682860100..000000000 --- a/test/split.rs +++ /dev/null @@ -1,160 +0,0 @@ -extern crate libc; -extern crate memchr; -extern crate aho_corasick; -extern crate rand; -extern crate regex_syntax; -extern crate regex; - -use std::fs::{File, read_dir, remove_file}; -use std::io::{Read, Write}; -use std::path::Path; -use std::process::Command; -use rand::{Rng, thread_rng}; -use regex::Regex; -use util::*; - -static PROGNAME: &'static str = "./split"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -fn random_chars(n: usize) -> String { - thread_rng().gen_ascii_chars().take(n).collect::() -} - -struct Glob { - directory: String, - regex: Regex -} - -impl Glob { - fn new(directory: &str, regex: &str) -> Glob { - Glob { - directory: directory.to_string(), - regex: Regex::new(regex).unwrap() - } - } - - fn count(&self) -> usize { - self.collect().len() - } - - fn collect(&self) -> Vec { - read_dir(Path::new(&self.directory)).unwrap().filter_map(|entry| { - let path = entry.unwrap().path(); - let name = path.as_path().to_str().unwrap_or(""); - if self.regex.is_match(name) { Some(name.to_string()) } else { None } - }).collect() - } - - fn collate(&self) -> Vec { - let mut files = self.collect(); - files.sort(); - let mut data: Vec = vec!(); - for name in files.iter() { - data.extend(get_file_contents(name).into_bytes()); - } - data - } - - fn remove_all(&self) { - for name in self.collect().iter() { - let _ = remove_file(name); - } - } -} - -struct RandomFile { - inner: File -} - -impl RandomFile { - fn new(name: &str) -> RandomFile { - RandomFile { inner: File::create(Path::new(name)).unwrap() } - } - - fn add_bytes(&mut self, bytes: usize) { - let chunk_size: usize = if bytes >= 1024 { 1024 } else { bytes }; - let mut n = bytes; - while n > chunk_size { - let _ = write!(self.inner, "{}", random_chars(chunk_size)); - n -= chunk_size; - } - let _ = write!(self.inner, "{}", random_chars(n)); - } - - fn add_lines(&mut self, lines: usize) { - let line_size: usize = 32; - let mut n = lines; - while n > 0 { - let _ = writeln!(self.inner, "{}", random_chars(line_size)); - n -= 1; - } - } -} - -#[test] -fn test_split_default() { - let name = "split_default"; - let glob = Glob::new(".", r"x[:alpha:][:alpha:]$"); - RandomFile::new(name).add_lines(2000); - if !Command::new(PROGNAME).args(&[name]).status().unwrap().success() { - panic!(); - } - assert_eq!(glob.count(), 2); - assert_eq!(glob.collate(), get_file_contents(name).into_bytes()); - glob.remove_all(); -} - -#[test] -fn test_split_num_prefixed_chunks_by_bytes() { - let name = "split_num_prefixed_chunks_by_bytes"; - let glob = Glob::new(".", r"a\d\d$"); - RandomFile::new(name).add_bytes(10000); - if !Command::new(PROGNAME).args(&["-d", "-b", "1000", name, "a"]).status().unwrap().success() { - panic!(); - } - assert_eq!(glob.count(), 10); - assert_eq!(glob.collate(), get_file_contents(name).into_bytes()); - glob.remove_all(); -} - -#[test] -fn test_split_str_prefixed_chunks_by_bytes() { - let name = "split_str_prefixed_chunks_by_bytes"; - let glob = Glob::new(".", r"b[:alpha:][:alpha:]$"); - RandomFile::new(name).add_bytes(10000); - if !Command::new(PROGNAME).args(&["-b", "1000", name, "b"]).status().unwrap().success() { - panic!(); - } - assert_eq!(glob.count(), 10); - assert_eq!(glob.collate(), get_file_contents(name).into_bytes()); - glob.remove_all(); -} - -#[test] -fn test_split_num_prefixed_chunks_by_lines() { - let name = "split_num_prefixed_chunks_by_lines"; - let glob = Glob::new(".", r"c\d\d$"); - RandomFile::new(name).add_lines(10000); - if !Command::new(PROGNAME).args(&["-d", "-l", "1000", name, "c"]).status().unwrap().success() { - panic!(); - } - assert_eq!(glob.count(), 10); - assert_eq!(glob.collate(), get_file_contents(name).into_bytes()); - glob.remove_all(); -} - -#[test] -fn test_split_str_prefixed_chunks_by_lines() { - let name = "split_str_prefixed_chunks_by_lines"; - let glob = Glob::new(".", r"d[:alpha:][:alpha:]$"); - RandomFile::new(name).add_lines(10000); - if !Command::new(PROGNAME).args(&["-l", "1000", name, "d"]).status().unwrap().success() { - panic!(); - } - assert_eq!(glob.count(), 10); - assert_eq!(glob.collate(), get_file_contents(name).into_bytes()); - glob.remove_all(); -} diff --git a/test/stdbuf.rs b/test/stdbuf.rs deleted file mode 100644 index ff7d5259f..000000000 --- a/test/stdbuf.rs +++ /dev/null @@ -1,16 +0,0 @@ -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./stdbuf"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_stdbuf_unbuffered_stdout() { - // This is a basic smoke test - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-o0", "head"]), "The quick brown fox jumps over the lazy dog."); - assert_eq!(result.stdout, "The quick brown fox jumps over the lazy dog."); -} diff --git a/test/sum.rs b/test/sum.rs deleted file mode 100644 index fb4abbf2d..000000000 --- a/test/sum.rs +++ /dev/null @@ -1,70 +0,0 @@ -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./sum"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_bsd_single_file() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.arg("lorem_ipsum.txt")); - - assert_empty_stderr!(result); - assert!(result.success); - assert_eq!(result.stdout, get_file_contents("bsd_single_file.expected")); -} - -#[test] -fn test_bsd_multiple_files() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.arg("lorem_ipsum.txt").arg("alice_in_wonderland.txt")); - - assert_empty_stderr!(result); - assert!(result.success); - assert_eq!(result.stdout, get_file_contents("bsd_multiple_files.expected")); -} - -#[test] -fn test_bsd_stdin() { - let input = get_file_contents("lorem_ipsum.txt"); - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd, input); - - assert_empty_stderr!(result); - assert!(result.success); - assert_eq!(result.stdout, get_file_contents("bsd_stdin.expected")); -} - -#[test] -fn test_sysv_single_file() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.arg("-s").arg("lorem_ipsum.txt")); - - assert_empty_stderr!(result); - assert!(result.success); - assert_eq!(result.stdout, get_file_contents("sysv_single_file.expected")); -} - -#[test] -fn test_sysv_multiple_files() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.arg("-s").arg("lorem_ipsum.txt").arg("alice_in_wonderland.txt")); - - assert_empty_stderr!(result); - assert!(result.success); - assert_eq!(result.stdout, get_file_contents("sysv_multiple_files.expected")); -} - -#[test] -fn test_sysv_stdin() { - let input = get_file_contents("lorem_ipsum.txt"); - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.arg("-s"), input); - - assert_empty_stderr!(result); - assert!(result.success); - assert_eq!(result.stdout, get_file_contents("sysv_stdin.expected")); -} diff --git a/test/tac.rs b/test/tac.rs deleted file mode 100644 index 5ec5a26b4..000000000 --- a/test/tac.rs +++ /dev/null @@ -1,50 +0,0 @@ -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./tac"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_stdin_default() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd, "100\n200\n300\n400\n500"); - assert_eq!(result.stdout, "500400\n300\n200\n100\n"); -} - -#[test] -fn test_stdin_non_newline_separator() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-s", ":"]), "100:200:300:400:500"); - assert_eq!(result.stdout, "500400:300:200:100:"); -} - -#[test] -fn test_stdin_non_newline_separator_before() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-b", "-s", ":"]), "100:200:300:400:500"); - assert_eq!(result.stdout, "500:400:300:200:100"); -} - -#[test] -fn test_single_default() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.arg("prime_per_line.txt")); - assert_eq!(result.stdout, get_file_contents("prime_per_line.expected")); -} - -#[test] -fn test_single_non_newline_separator() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-s", ":", "delimited_primes.txt"])); - assert_eq!(result.stdout, get_file_contents("delimited_primes.expected")); -} - -#[test] -fn test_single_non_newline_separator_before() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-b", "-s", ":", "delimited_primes.txt"])); - assert_eq!(result.stdout, get_file_contents("delimited_primes_before.expected")); -} diff --git a/test/test.rs b/test/test.rs deleted file mode 100644 index af6758ae6..000000000 --- a/test/test.rs +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is part of the uutils coreutils package. - * - * (c) mahkoh (ju.orth [at] gmail [dot] com) - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use std::process::Command; - -static PROGNAME: &'static str = "./test"; - -#[test] -fn test_op_prec_and_or_1() { - let status = Command::new(PROGNAME).arg(" ").arg("-o").arg("").arg("-a").arg("").status(); - assert_eq!(true, status.unwrap().success()); -} - -#[test] -fn test_op_prec_and_or_2() { - let status = Command::new(PROGNAME).arg("") - .arg("-a") - .arg("") - .arg("-o") - .arg(" ") - .arg("-a") - .arg(" ") - .status(); - assert_eq!(true, status.unwrap().success()); -} - -#[test] -fn test_or_as_filename() { - let status = Command::new(PROGNAME).arg("x").arg("-a").arg("-z").arg("-o").status(); - assert_eq!(status.unwrap().code(), Some(1)); -} diff --git a/test/touch.rs b/test/touch.rs deleted file mode 100644 index 642844f18..000000000 --- a/test/touch.rs +++ /dev/null @@ -1,258 +0,0 @@ -extern crate libc; -extern crate time; -extern crate kernel32; -extern crate winapi; -extern crate filetime; - -use filetime::FileTime; -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./touch"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -fn get_file_times(path: &str) -> (FileTime, FileTime) { - let m = metadata(path); - (FileTime::from_last_access_time(&m), FileTime::from_last_modification_time(&m)) -} - -fn set_file_times(path: &str, atime: FileTime, mtime: FileTime) { - filetime::set_file_times(path, atime, mtime).unwrap() -} - -// Adjusts for local timezone -fn str_to_filetime(format: &str, s: &str) -> FileTime { - let mut tm = time::strptime(s, format).unwrap(); - tm.tm_utcoff = time::now().tm_utcoff; - let ts = tm.to_timespec(); - FileTime::from_seconds_since_1970(ts.sec as u64, ts.nsec as u32) -} - -#[test] -fn test_touch_default() { - let file = "test_touch_default_file"; - - let result = run(Command::new(PROGNAME).arg(file)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(file)); -} - -#[test] -fn test_touch_no_create_file_absent() { - let file = "test_touch_no_create_file_absent"; - - let result = run(Command::new(PROGNAME).arg("-c").arg(file)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(!file_exists(file)); -} - -#[test] -fn test_touch_no_create_file_exists() { - let file = "test_touch_no_create_file_exists"; - - touch(file); - assert!(file_exists(file)); - - let result = run(Command::new(PROGNAME).arg("-c").arg(file)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(file)); -} - -#[test] -fn test_touch_set_mdhm_time() { - let file = "test_touch_set_mdhm_time"; - - let result = run(Command::new(PROGNAME).args(&["-t", "01011234", file])); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(file)); - - let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000"); - let (atime, mtime) = get_file_times(file); - assert_eq!(atime, mtime); - assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240); - assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240); -} - -#[test] -fn test_touch_set_mdhms_time() { - let file = "test_touch_set_mdhms_time"; - - let result = run(Command::new(PROGNAME).args(&["-t", "01011234.56", file])); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(file)); - - let start_of_year = str_to_filetime("%Y%m%d%H%M.%S", "201501010000.00"); - let (atime, mtime) = get_file_times(file); - assert_eq!(atime, mtime); - assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45296); - assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45296); -} - -#[test] -fn test_touch_set_ymdhm_time() { - let file = "test_touch_set_ymdhm_time"; - - let result = run(Command::new(PROGNAME).args(&["-t", "1501011234", file])); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(file)); - - let start_of_year = str_to_filetime("%y%m%d%H%M", "1501010000"); - let (atime, mtime) = get_file_times(file); - assert_eq!(atime, mtime); - assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240); - assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240); -} - -#[test] -fn test_touch_set_ymdhms_time() { - let file = "test_touch_set_ymdhms_time"; - - let result = run(Command::new(PROGNAME).args(&["-t", "1501011234.56", file])); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(file)); - - let start_of_year = str_to_filetime("%y%m%d%H%M.%S", "1501010000.00"); - let (atime, mtime) = get_file_times(file); - assert_eq!(atime, mtime); - assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45296); - assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45296); -} - -#[test] -fn test_touch_set_cymdhm_time() { - let file = "test_touch_set_cymdhm_time"; - - let result = run(Command::new(PROGNAME).args(&["-t", "201501011234", file])); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(file)); - - let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000"); - let (atime, mtime) = get_file_times(file); - assert_eq!(atime, mtime); - assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240); - assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240); -} - -#[test] -fn test_touch_set_cymdhms_time() { - let file = "test_touch_set_cymdhms_time"; - - let result = run(Command::new(PROGNAME).args(&["-t", "201501011234.56", file])); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(file)); - - let start_of_year = str_to_filetime("%Y%m%d%H%M.%S", "201501010000.00"); - let (atime, mtime) = get_file_times(file); - assert_eq!(atime, mtime); - assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45296); - assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45296); -} - -#[test] -fn test_touch_set_only_atime() { - let file = "test_touch_set_only_atime"; - - let result = run(Command::new(PROGNAME).args(&["-t", "201501011234", "-a", file])); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(file)); - - let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000"); - let (atime, mtime) = get_file_times(file); - assert!(atime != mtime); - assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240); -} - -#[test] -fn test_touch_set_only_mtime() { - let file = "test_touch_set_only_mtime"; - - let result = run(Command::new(PROGNAME).args(&["-t", "201501011234", "-m", file])); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(file)); - - let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000"); - let (atime, mtime) = get_file_times(file); - assert!(atime != mtime); - assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240); -} - -#[test] -fn test_touch_set_both() { - let file = "test_touch_set_both"; - - let result = run(Command::new(PROGNAME).args(&["-t", "201501011234", "-a", "-m", file])); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(file)); - - let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000"); - let (atime, mtime) = get_file_times(file); - assert_eq!(atime, mtime); - assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240); - assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240); -} - -#[test] -fn test_touch_reference() { - let file_a = "test_touch_reference_a"; - let file_b = "test_touch_reference_b"; - let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000"); - - touch(file_a); - set_file_times(file_a, start_of_year, start_of_year); - assert!(file_exists(file_a)); - - let result = run(Command::new(PROGNAME).args(&["-r", file_a, file_b])); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(file_b)); - - let (atime, mtime) = get_file_times(file_b); - assert_eq!(atime, mtime); - assert_eq!(atime, start_of_year); - assert_eq!(mtime, start_of_year); -} - -#[test] -fn test_touch_set_date() { - let file = "test_touch_set_date"; - - let result = run(Command::new(PROGNAME).args(&["-d", "Thu Jan 01 12:34:00 2015", file])); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(file_exists(file)); - - let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501011234"); - let (atime, mtime) = get_file_times(file); - assert_eq!(atime, mtime); - assert_eq!(atime, start_of_year); - assert_eq!(mtime, start_of_year); -} diff --git a/test/tr.rs b/test/tr.rs deleted file mode 100644 index 3da1b9605..000000000 --- a/test/tr.rs +++ /dev/null @@ -1,43 +0,0 @@ -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./tr"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_toupper() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["a-z", "A-Z"]), b"!abcd!"); - assert_eq!(result.stdout, "!ABCD!"); -} - -#[test] -fn test_small_set2() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["0-9", "X"]), b"@0123456789"); - assert_eq!(result.stdout, "@XXXXXXXXXX"); -} - -#[test] -fn test_unicode() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&[", ┬─┬", "╯︵┻━┻"]), "(,°□°), ┬─┬".as_bytes()); - assert_eq!(result.stdout, "(╯°□°)╯︵┻━┻"); -} - -#[test] -fn test_delete() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-d", "a-z"]), b"aBcD"); - assert_eq!(result.stdout, "BD"); -} - -#[test] -fn test_delete_complement() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-d", "-c", "a-z"]), b"aBcD"); - assert_eq!(result.stdout, "ac"); -} diff --git a/test/true.rs b/test/true.rs deleted file mode 100644 index fba9fff36..000000000 --- a/test/true.rs +++ /dev/null @@ -1,9 +0,0 @@ -use std::process::Command; - -static PROGNAME: &'static str = "./true"; - -#[test] -fn test_exit_code() { - let exit_status = Command::new(PROGNAME).status().unwrap().success(); - assert_eq!(exit_status, true); -} diff --git a/test/truncate.rs b/test/truncate.rs deleted file mode 100644 index 3461fcbf9..000000000 --- a/test/truncate.rs +++ /dev/null @@ -1,41 +0,0 @@ -use std::fs; -use std::io::{Seek, SeekFrom, Write}; -use std::path::Path; -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./truncate"; -static TFILE1: &'static str = "truncate_test_1"; -static TFILE2: &'static str = "truncate_test_2"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_increase_file_size() { - let mut file = make_file(TFILE1); - if !Command::new(PROGNAME).args(&["-s", "+5K", TFILE1]).status().unwrap().success() { - panic!(); - } - file.seek(SeekFrom::End(0)).unwrap(); - if file.seek(SeekFrom::Current(0)).unwrap() != 5 * 1024 { - panic!(); - } - fs::remove_file(Path::new(TFILE1)).unwrap(); -} - -#[test] -fn test_decrease_file_size() { - let mut file = make_file(TFILE2); - file.write_all(b"1234567890").unwrap(); - if !Command::new(PROGNAME).args(&["--size=-4", TFILE2]).status().unwrap().success() { - panic!(); - } - file.seek(SeekFrom::End(0)).unwrap(); - if file.seek(SeekFrom::Current(0)).unwrap() != 6 { - println!("{:?}", file.seek(SeekFrom::Current(0))); - panic!(); - } - fs::remove_file(Path::new(TFILE2)).unwrap(); -} diff --git a/test/tsort.rs b/test/tsort.rs deleted file mode 100644 index 18648f3ad..000000000 --- a/test/tsort.rs +++ /dev/null @@ -1,21 +0,0 @@ -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./tsort"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_sort_call_graph() { - let input = "call_graph.txt"; - let output = "call_graph.expected"; - - let po = Command::new(PROGNAME) - .arg(input) - .output() - .unwrap_or_else(|err| panic!("{}", err)); - - assert_eq!(String::from_utf8(po.stdout).unwrap(), String::from_utf8(get_file_contents(output).into_bytes()).unwrap()); -} diff --git a/test/unexpand.rs b/test/unexpand.rs deleted file mode 100644 index c68057730..000000000 --- a/test/unexpand.rs +++ /dev/null @@ -1,115 +0,0 @@ -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./unexpand"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn unexpand_init_0() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-t4"]), " 1\n 2\n 3\n 4\n"); - assert_eq!(result.stdout, " 1\n 2\n 3\n\t4\n"); -} - -#[test] -fn unexpand_init_1() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-t4"]), " 5\n 6\n 7\n 8\n"); - assert_eq!(result.stdout, "\t 5\n\t 6\n\t 7\n\t\t8\n"); -} - -#[test] -fn unexpand_init_list_0() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-t2,4"]), " 1\n 2\n 3\n 4\n"); - assert_eq!(result.stdout, " 1\n\t2\n\t 3\n\t\t4\n"); -} - -#[test] -fn unexpand_init_list_1() { - // Once the list is exhausted, spaces are not converted anymore - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-t2,4"]), " 5\n 6\n 7\n 8\n"); - assert_eq!(result.stdout, "\t\t 5\n\t\t 6\n\t\t 7\n\t\t 8\n"); -} - -#[test] -fn unexpand_aflag_0() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["--"]), "e E\nf F\ng G\nh H\n"); - assert_eq!(result.stdout, "e E\nf F\ng G\nh H\n"); -} - -#[test] -fn unexpand_aflag_1() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-a"]), "e E\nf F\ng G\nh H\n"); - assert_eq!(result.stdout, "e E\nf F\ng\tG\nh\t H\n"); -} - -#[test] -fn unexpand_aflag_2() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-t8"]), "e E\nf F\ng G\nh H\n"); - assert_eq!(result.stdout, "e E\nf F\ng\tG\nh\t H\n"); -} - -#[test] -fn unexpand_first_only_0() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-t3"]), " A B"); - assert_eq!(result.stdout, "\t\t A\t B"); -} - -#[test] -fn unexpand_first_only_1() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-t3", "--first-only"]), " A B"); - assert_eq!(result.stdout, "\t\t A B"); -} - -#[test] -fn unexpand_trailing_space_0() { // evil - // Individual spaces before fields starting with non blanks should not be - // converted, unless they are at the beginning of the line. - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-t4"]), "123 \t1\n123 1\n123 \n123 "); - assert_eq!(result.stdout, "123\t\t1\n123 1\n123 \n123 "); -} - -#[test] -fn unexpand_trailing_space_1() { // super evil - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-t1"]), " abc d e f g "); - assert_eq!(result.stdout, "\tabc d e\t\tf\t\tg "); -} - -#[test] -fn unexpand_spaces_follow_tabs_0() { - // The two first spaces can be included into the first tab. - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd, " \t\t A"); - assert_eq!(result.stdout, "\t\t A"); -} - -#[test] -fn unexpand_spaces_follow_tabs_1() { // evil - // Explanation of what is going on here: - // 'a' -> 'a' // first tabstop (1) - // ' \t' -> '\t' // second tabstop (4) - // ' ' -> '\t' // third tabstop (5) - // ' B \t' -> ' B \t' // after the list is exhausted, nothing must change - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-t1,4,5"]), "a \t B \t"); - assert_eq!(result.stdout, "a\t\t B \t"); -} - -#[test] -fn unexpand_spaces_after_fields() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-a"]), " \t A B C D A\t\n"); - assert_eq!(result.stdout, "\t\tA B C D\t\t A\t\n"); -} diff --git a/test/unlink.rs b/test/unlink.rs deleted file mode 100644 index 1d18d9baf..000000000 --- a/test/unlink.rs +++ /dev/null @@ -1,59 +0,0 @@ -extern crate libc; - -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./unlink"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_unlink_file() { - let file = "test_unlink_file"; - - touch(file); - - let result = run(Command::new(PROGNAME).arg(file)); - assert_empty_stderr!(result); - assert!(result.success); - - assert!(!file_exists(file)); -} - -#[test] -fn test_unlink_multiple_files() { - let file_a = "test_unlink_multiple_file_a"; - let file_b = "test_unlink_multiple_file_b"; - - touch(file_a); - touch(file_b); - - let result = run(Command::new(PROGNAME).arg(file_a).arg(file_b)); - assert_eq!(result.stderr, - "unlink: error: extra operand: 'test_unlink_multiple_file_b'\nTry 'unlink --help' for more information.\n"); - assert!(!result.success); -} - -#[test] -fn test_unlink_directory() { - let dir = "test_unlink_empty_directory"; - - mkdir(dir); - - let result = run(Command::new(PROGNAME).arg(dir)); - assert_eq!(result.stderr, - "unlink: error: cannot unlink 'test_unlink_empty_directory': Not a regular file or symlink\n"); - assert!(!result.success); -} - -#[test] -fn test_unlink_nonexistent() { - let file = "test_unlink_nonexistent"; - - let result = run(Command::new(PROGNAME).arg(file)); - assert_eq!(result.stderr, - "unlink: error: Cannot stat 'test_unlink_nonexistent': No such file or directory (os error 2)\n"); - assert!(!result.success); -} diff --git a/test/wc.rs b/test/wc.rs deleted file mode 100644 index 5cb8f3b59..000000000 --- a/test/wc.rs +++ /dev/null @@ -1,57 +0,0 @@ -use std::process::Command; -use util::*; - -static PROGNAME: &'static str = "./wc"; - -#[path = "common/util.rs"] -#[macro_use] -mod util; - -#[test] -fn test_stdin_default() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd, get_file_contents("lorem_ipsum.txt")); - assert_eq!(result.stdout, " 13 109 772\n"); -} - -#[test] -fn test_stdin_only_bytes() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-c"]), get_file_contents("lorem_ipsum.txt")); - assert_eq!(result.stdout, " 772\n"); -} - -#[test] -fn test_stdin_all_counts() { - let mut cmd = Command::new(PROGNAME); - let result = run_piped_stdin(&mut cmd.args(&["-c", "-m", "-l", "-L", "-w"]), get_file_contents("alice_in_wonderland.txt")); - assert_eq!(result.stdout, " 5 57 302 302 66\n"); -} - -#[test] -fn test_single_default() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.arg("moby_dick.txt")); - assert_eq!(result.stdout, " 18 204 1115 moby_dick.txt\n"); -} - -#[test] -fn test_single_only_lines() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-l", "moby_dick.txt"])); - assert_eq!(result.stdout, " 18 moby_dick.txt\n"); -} - -#[test] -fn test_single_all_counts() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["-c", "-l", "-L", "-m", "-w", "alice_in_wonderland.txt"])); - assert_eq!(result.stdout, " 5 57 302 302 66 alice_in_wonderland.txt\n"); -} - -#[test] -fn test_multiple_default() { - let mut cmd = Command::new(PROGNAME); - let result = run(&mut cmd.args(&["lorem_ipsum.txt", "moby_dick.txt", "alice_in_wonderland.txt"])); - assert_eq!(result.stdout, " 13 109 772 lorem_ipsum.txt\n 18 204 1115 moby_dick.txt\n 5 57 302 alice_in_wonderland.txt\n 36 370 2189 total\n"); -}