├── .git.go
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE.txt
├── README.md
├── THANKS.md
├── arch
├── .gitignore
└── arch.go
├── base64
├── .gitignore
├── base64.go
└── base64_test.go
├── basename
├── .gitignore
├── basename.go
└── basename_test.go
├── build.bash
├── cal
├── .gitignore
└── cal.go
├── cat
├── .gitignore
├── cat.go
├── cat_test.go
├── cat_unix.go
├── cat_windows.go
└── test_files
│ ├── coreutils_man_en.txt
│ ├── dict_en.txt
│ ├── file_list.txt
│ ├── lang_ru.txt
│ └── spaces_en.txt
├── chcon
├── .gitignore
└── chcon.go
├── chgrp
├── .gitignore
└── chgrp.go
├── chmod
├── .gitignore
└── chmod.go
├── chown
├── .gitignore
├── README.md
├── checksum
├── chown
├── chown.go
├── chown_core.go
├── chown_types.go
├── patch.sh
└── patch101310044_20001.tar.bz2
├── chroot
├── .gitignore
└── chroot.go
├── cksum
├── .gitignore
└── cksum.go
├── comm
├── .gitignore
└── comm.go
├── coreutils.go
├── cp
├── .gitignore
├── cp.go
├── foo.txt
└── idk.go
├── csplit
├── .gitignore
├── boyermoore.go
├── csplit.go
├── mmap.go
├── read.go
└── test.txt
├── cut
├── .gitignore
└── cut.go
├── date
├── .gitignore
└── date.go
├── dd
├── .gitignore
└── dd.go
├── df
├── .gitignore
└── df.go
├── dir
├── .gitignore
└── dir.go
├── dircolors
├── .gitignore
└── dircolors.go
├── dirname
├── .gitignore
└── dirname.go
├── du
├── .gitignore
└── du.go
├── echo
├── .gitignore
└── echo.go
├── editlicensedates.bash
├── env
├── .gitignore
└── env.go
├── expand
├── .gitignore
└── expand.go
├── expr
├── .gitignore
└── expr.go
├── factor
├── .gitignore
└── factor.go
├── false
├── .gitignore
└── false.go
├── fmt
├── .gitignore
└── fmt.go
├── fold
├── .gitignore
└── fold.go
├── groups
├── .gitignore
└── groups.go
├── head
├── .gitignore
└── head.go
├── hostid
├── .gitignore
└── hostid.go
├── id
├── .gitignore
└── id.go
├── install
├── .gitignore
└── install.go
├── join
├── .gitignore
└── join.go
├── link
├── .gitignore
└── link.go
├── ln
├── .gitignore
└── ln.go
├── logname
├── .gitignore
└── logname.go
├── ls
├── .gitignore
└── ls.go
├── md5sum
├── .gitignore
├── checksum_common
│ ├── calc_sum.go
│ ├── check_sum.go
│ ├── checksum_test.go
│ ├── output.go
│ └── testdata
│ │ ├── aad33efasdf.txt
│ │ ├── checksum.md5
│ │ ├── checksum.sha1
│ │ ├── checksum.sha224
│ │ ├── checksum.sha256
│ │ ├── checksum.sha384
│ │ ├── checksum.sha512
│ │ ├── d333dasdf3.txt
│ │ └── rgsdfsdfewerwf.txt
└── md5sum.go
├── mkdir
├── .gitignore
└── mkdir.go
├── mkfifo
├── .gitignore
└── mkfifo.go
├── mknod
├── .gitignore
└── mknod.go
├── mktemp
├── .gitignore
└── mktemp.go
├── mv
├── .gitignore
└── mv.go
├── nice
├── .gitignore
└── nice.go
├── nl
├── .gitignore
└── nl.go
├── nohup
├── .gitignore
└── nohup.go
├── nproc
├── .gitignore
└── nproc.go
├── numfmt
├── .gitignore
└── numfmt.go
├── od
├── .gitignore
└── od.go
├── paste
├── .gitignore
└── paste.go
├── pathchk
├── .gitignore
└── pathchk.go
├── pinky
├── .gitignore
└── pinky.go
├── pr
├── .gitignore
└── pr.go
├── printenv
├── .gitignore
└── printenv.go
├── printf
├── .gitignore
└── printf.go
├── ptx
├── .gitignore
└── ptx.go
├── pwd
├── .gitignore
└── pwd.go
├── readlink
├── .gitignore
└── readlink.go
├── realpath
├── .gitignore
└── realpath.go
├── rm
├── .gitignore
├── cmd.go
├── internal
│ └── sys
│ │ ├── sys_unix.go
│ │ └── sys_windows.go
└── rm.go
├── rmdir
├── .gitignore
└── rmdir.go
├── runcon
├── .gitignore
└── runcon.go
├── seq
├── .gitignore
└── seq.go
├── sha1sum
├── .gitignore
└── sha1sum.go
├── sha224sum
├── .gitignore
└── sha224sum.go
├── sha256sum
├── .gitignore
└── sha256sum.go
├── sha384sum
├── .gitignore
└── sha384sum.go
├── sha512sum
├── .gitignore
└── sha512sum.go
├── shred
├── .gitignore
└── shred.go
├── shuf
├── .gitignore
└── shuf.go
├── sleep
├── .gitignore
└── sleep.go
├── sort
├── .gitignore
└── sort.go
├── split
├── .gitignore
└── split.go
├── stat
├── .gitignore
└── stat.go
├── stdbuf
├── .gitignore
└── stdbuf.go
├── stty
├── .gitignore
└── stty.go
├── sum
├── .gitignore
└── sum.go
├── sync
├── .gitignore
├── sync_linux.go
└── sync_windows.go
├── tac
├── .gitignore
└── tac.go
├── tail
├── .gitignore
└── tail.go
├── tee
├── .gitignore
└── tee.go
├── test
├── .gitignore
└── test.go
├── timeout
├── .gitignore
└── timeout.go
├── touch
├── .gitignore
└── touch.go
├── tr
├── .gitignore
└── tr.go
├── true
├── .gitignore
└── true.go
├── truncate
├── .gitignore
└── truncate.go
├── tsort
├── .gitignore
├── tsort.go
└── tsort_test.go
├── tty
├── .gitignore
└── tty.go
├── uname
├── .gitignore
├── README.md
├── generate.go
├── host_os.go
├── host_os_darwin.go
├── host_os_dragonfly.go
├── host_os_freebsd.go
├── host_os_linux.go
├── host_os_netbsd.go
├── host_os_openbsd.go
├── host_os_plan9.go
├── host_os_solaris.go
├── host_os_windows.go
├── ostypes.go
├── uname.go
├── uname_freebsd.go
├── uname_linux.go
└── uname_windows.go
├── unexpand
├── .gitignore
└── unexpand.go
├── uniq
├── .gitignore
└── uniq.go
├── unlink
├── .gitignore
└── unlink.go
├── uptime
├── .gitignore
├── uptime.go
├── uptime_freebsd.go
└── uptime_linux.go
├── users
├── .gitignore
└── users.go
├── vdir
├── .gitignore
└── vdir.go
├── wc
├── _testdata
│ ├── coreutils_man_en.txt
│ ├── dict_en.txt
│ ├── file_list.txt
│ ├── lang_ru.txt
│ └── spaces_en.txt
├── cmd.go
├── internal
│ └── sys
│ │ ├── fadv.go
│ │ └── fadv_unix.go
├── wc.go
└── wc_test.go
├── who
├── .gitignore
└── who.go
├── whoami
├── .gitignore
├── whoami
├── whoami.go
├── whoami_test.go
├── whoami_unix.go
└── whoami_windows.go
├── xxd
├── xxd.go
└── xxd_test.go
└── yes
└── yes.go
/.git.go:
--------------------------------------------------------------------------------
1 | package main
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files, Static and Dynamic libs (Shared Objects)
2 | *.o
3 | *.a
4 | *.so
5 | # Folders
6 | _obj
7 | _test
8 | # Architecture specific extensions/prefixes
9 | *.[568vq]
10 | [568vq].out
11 | *.cgo1.go
12 | *.cgo2.c
13 | _cgo_defun.c
14 | _cgo_gotypes.go
15 | _cgo_export.*
16 | _testmain.go
17 | *.exe
18 | *.test
19 | *.prof
20 |
21 | # Testing
22 | /testing/
23 |
24 | # etc
25 | lst
26 | .c # because I test in C
27 | .out # same
28 | .tags
29 |
30 | # binary
31 | go-coreutils
32 |
33 | coreutils
34 | glibc
35 | .tags
36 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | ## Goals:
4 |
5 | - Cross platform (on all platforms Go offically supports)
6 | - Fully implements GNU's coreutils (drop-in replacement)
7 | - Idiomatic Go
8 | - As fast as or faster than GNU's coreutils
9 |
10 | ## Tips
11 |
12 | - clone https://www.github.com/coreutils/coreutils and work side-by-side
13 | - get familiar with https://www.github.com/coreutils/gnulib
14 | - get familiar with https://www.github.com/EricLagergren/go-gnulib
15 |
16 | ## Licensing
17 |
18 | - All future changes will be licensed under GPLv3 or later.
19 | - If you edit a file append your name under the previous contributor(s).
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Go coreutils
2 |
3 | [](http://forthebadge.com)
4 | [](http://forthebadge.com)
5 |
6 | This is a port of GNU's coreutils (http://www.gnu.org/software/coreutils/)
7 | that aims to be a drop-in, cross-platform replacement.
8 |
9 | **It's currently under development.**
10 |
11 | Because it imports from `github.com/EricLagergren/go-gnulib`, and I'm constantly
12 | refactoring, parts could break from day-to-day.
13 |
14 | I'd recommend running `go get -u ...` before you file a bug report!
15 |
16 | *Pull requests are more than welcome.*
17 |
18 | Also, see https://www.github.com/EricLagergren/go-gnulib for a similar project that this project depends on.
19 |
20 | ### Completed:
21 |
22 | * 100% Completion
23 | * 15/100
24 | * Partial Completion
25 | * 2/100
26 |
27 | | Utility | Completeness | Cross Platform | Need Refactor|
28 | |:--------|:---------------|:--------------------|:-------------|
29 | | cat | 100% | Yes (Unix/Windows) | No |
30 | | chown | 0% (* see note #1) | No | Yes (-R) |
31 | | env | 100% | Yes (Unix/Windows) | No |
32 | | false | 100% | Yes (Unix/Windows) | No |
33 | | logname | 100% | No | No |
34 | | pwd | 100% | Yes (Unknown) | No |
35 | | sync | 100% | Yes (Unix/Windows) | No |
36 | | true | 100% | Yes (Unix/Windows) | No |
37 | | tsort | 100% | Yes (Unix/Windows) | No |
38 | | tty | 100% | Yes (Unix/Windows) | No |
39 | | uname | 100% | No | No |
40 | | uptime | 90% | Yes (Unix/Windows, no FreeBSD) | No |
41 | | users | 100% | No | No |
42 | | wc | 100% | Yes (Unix/Windows) | No |
43 | | whoami | 100% | Yes (Unix/Windows | No |
44 | | xxd | 100% | Yes (Unix/Windows) | No |
45 | | yes | 100% | Yes (Unix/Windows) | No |
46 |
47 | * chown note: Currently refactoring from the ground-up.
48 |
49 | **Side notes:**
50 | - Unix *should* include OS X unless otherwise specified.
51 | - Gofmt means it needs its styling changes (e.g. variable names, formatting, etc.)
52 | - Idiomatic means it needs to be changed to more idiomatic Go
53 | - Windows coverage will increase when I get a Windows laptop
54 |
55 | ### Information:
56 |
57 | #### Performance:
58 |
59 | Obviously there's some things Go can do better (parallelism and concurrency),
60 | but for the most part these tools should have nearly the same speed,
61 | with Go being slightly slower.
62 |
63 | ```
64 | eric@archbox $ time ./wc_go -lwmc one_gigabyte_file.txt
65 | 32386258 146084896 1182425560 1183778772 one_gigabyte_file.txt
66 |
67 | real 0m25.206s
68 | user 0m24.900s
69 | sys 0m0.313s
70 | eric@archbox $ time wc_c -lwmc one_gigabyte_file.txt
71 | 32386258 146084896 1182425560 1183778772 one_gigabyte_file.txt
72 |
73 | real 0m22.841s
74 | user 0m22.570s
75 | sys 0m0.257s
76 | ```
77 |
78 | #### Behavior:
79 |
80 | These utilities should be nearly identical to GNU's coreutils.
81 |
82 | Since parsing the output of shell commands isn't uncommon (even if
83 | it *is* bad behavior), most of the commands should have output that
84 | is nearly identical to the original GNU commands.
85 |
86 | Do note that sometimes the results could differ a little for select commands.
87 |
88 | For example, GNU's `wc` utility relies on the current locale to determine
89 | whether it should parse multi-byte characters or not.
90 |
91 | The Go version, on the other hand, uses the `unicode/utf8` package
92 | which natively detects multi-byte sequences. The trade-off is this: the
93 | Go version is technically more correct, while the C version is faster.
94 |
95 | Our implementation of `xxd` is actually much faster than the native `xxd`
96 | implementation found on most *nix machines -- try it out!
97 |
98 | ### REQUIRES:
99 |
100 | (Depends on platform and command...)
101 | - go get github.com/EricLagergren/ostypes
102 | - go get golang.org/x/sys/unix
103 | - go get github.com/EricLagergren/go-gnulib/ttyname
104 | - go get github.com/EricLagergren/go-gnulib/sysinfo
105 | - go get github.com/EricLagergren/go-gnulib/posix
106 | - go get github.com/EricLagergren/go-gnulib/general
107 | - go get github.com/EricLagergren/go-gnulib/login
108 |
109 | ### LICENSE:
110 |
111 | ```
112 | Copyright (C) 2014-2016 Eric Lagergren
113 |
114 | This program is free software: you can redistribute it and/or modify
115 | it under the terms of the GNU General Public License as published by
116 | the Free Software Foundation, either version 3 of the License, or
117 | (at your option) any later version.
118 |
119 | This program is distributed in the hope that it will be useful,
120 | but WITHOUT ANY WARRANTY; without even the implied warranty of
121 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
122 | GNU General Public License for more details.
123 |
124 | You should have received a copy of the GNU General Public License
125 | along with this program. If not, see .
126 | ```
127 |
128 | #### License subnotes:
129 | It (as a whole) is licensed under the GPLv3 because it's mostly a
130 | transliteration of GNU's coreutils, which are licensed under the GPLv3.
131 |
132 | However, certain parts have their own licenses (e.g., `xxd` is public domain).
133 |
--------------------------------------------------------------------------------
/THANKS.md:
--------------------------------------------------------------------------------
1 | # Thanks
2 |
3 | Thanks to...
4 |
5 | - gonix contributors
6 | - vanhalt
7 | - iamthemuffinman
8 | - mattn
--------------------------------------------------------------------------------
/arch/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/arch/.gitignore
--------------------------------------------------------------------------------
/arch/arch.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/base64/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/base64/.gitignore
--------------------------------------------------------------------------------
/base64/base64.go:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License version 3 as
4 | published by the Free Software Foundation.
5 |
6 | This program is distributed in the hope that it will be useful,
7 | but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 | GNU General Public License for more details.
10 |
11 | You should have received a copy of the GNU General Public License
12 | along with this program. If not, see .
13 | */
14 |
15 | package main
16 |
17 | import (
18 | "encoding/base64"
19 | "fmt"
20 | "io"
21 | "io/ioutil"
22 | "log"
23 | "os"
24 | "unicode"
25 |
26 | flag "github.com/ogier/pflag"
27 | )
28 |
29 | const (
30 | Help = `
31 | Usage: base64 [OPTION]... [FILE]
32 | Base64 encode or decode FILE, or standard input, to standard output.
33 |
34 | Mandatory arguments to long options are mandatory for short options too.
35 | -d, --decode decode data
36 | -i, --ignore-garbage when decoding, ignore non-alphabet characters
37 | -w, --wrap=COLS wrap encoded lines after COLS character (default 76).
38 | Use 0 to disable line wrapping
39 |
40 | --help display this help and exit
41 | --version output version information and exit
42 |
43 | With no FILE, or when FILE is -, read standard input.
44 |
45 | The data are encoded as described for the base64 alphabet in RFC 3548.
46 | When decoding, the input may contain newlines in addition to the bytes of
47 | the formal base64 alphabet. Use --ignore-garbage to attempt to recover
48 | from any other non-alphabet bytes in the encoded stream.
49 |
50 | `
51 | Version = `
52 | base64 (Go coreutils) 0.1
53 | Copyright (C) 2015 Robert Deusser
54 | License GPLv3+: GNU GPL version 3 or later .
55 | This is free software: you are free to change and redistribute it.
56 | There is NO WARRANTY, to the extent permitted by law.
57 |
58 | `
59 | )
60 |
61 | var (
62 | decode = flag.BoolP("decode", "d", false, "")
63 | ignore = flag.BoolP("ignore-garbage", "i", false, "")
64 | wrap = flag.IntP("wrap", "w", 76, "")
65 | version = flag.BoolP("version", "v", false, "")
66 | )
67 |
68 | func base64Encode(src []byte) []byte {
69 | return []byte(base64.StdEncoding.EncodeToString(src))
70 | }
71 |
72 | func base64Decode(src []byte) ([]byte, error) {
73 | return base64.StdEncoding.DecodeString(string(src))
74 | }
75 |
76 | func readData(reader io.Reader) ([]byte, error) {
77 | return ioutil.ReadAll(reader)
78 | }
79 |
80 | func isAlpha(ch byte) bool {
81 | return unicode.IsLetter(rune(ch))
82 | }
83 |
84 | func readAndHandle(reader io.Reader, decode *bool, ignore *bool, wrap *int) {
85 | src, err := readData(reader)
86 | if err != nil {
87 | log.Fatal(err)
88 | }
89 | var toHandle []byte
90 | if *ignore {
91 | //It seems that the effect of "base64 -i" in *nix
92 | //is not filter the non-alphabet charater.
93 | //This flag cannot work as the original *nix command flag.
94 | for i := 0; i < len(src); i++ {
95 | if isAlpha(src[i]) {
96 | toHandle = append(toHandle, src[i])
97 | }
98 | }
99 | } else {
100 | toHandle = src
101 | }
102 | if *decode {
103 | decoded, err := base64Decode(toHandle)
104 | if err != nil {
105 | log.Fatal(err)
106 | }
107 | fmt.Printf("%s", string(decoded))
108 | } else {
109 | encoded := base64Encode(toHandle)
110 | wrapPrint(encoded, *wrap)
111 | }
112 | }
113 |
114 | func wrapPrint(output []byte, wrap int) {
115 | if wrap == 0 {
116 | fmt.Printf("%s\n", string(output))
117 | return
118 | }
119 |
120 | length := len(output)
121 | if length <= wrap {
122 | fmt.Printf("%s\n", string(output))
123 | return
124 | }
125 |
126 | index, end := 0, 0
127 | for index < length {
128 | end += wrap
129 | if end > length {
130 | end = length
131 | }
132 | fmt.Printf("%s\n", string(output[index:end]))
133 | index += wrap
134 | }
135 | }
136 |
137 | func main() {
138 | flag.Usage = func() {
139 | fmt.Fprintf(os.Stderr, "%s", Help)
140 | os.Exit(1)
141 | }
142 | flag.Parse()
143 |
144 | switch {
145 | case *version:
146 | fmt.Fprintf(os.Stdout, "%s", Version)
147 | os.Exit(0)
148 | case *wrap < 0:
149 | log.Fatalf("invalid wrap size: %d", *wrap)
150 | default:
151 | if len(flag.Args()) == 0 {
152 | readAndHandle(os.Stdin, decode, ignore, wrap)
153 | } else {
154 | for i := 0; i < len(flag.Args()); i++ {
155 | file, err := os.Open(flag.Args()[i])
156 | if err != nil {
157 | log.Fatal(err)
158 | }
159 | readAndHandle(file, decode, ignore, wrap)
160 | }
161 | }
162 | }
163 |
164 | }
165 |
--------------------------------------------------------------------------------
/base64/base64_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "testing"
6 | )
7 |
8 | func TestBase64Decode(t *testing.T) {
9 |
10 | cases := []struct {
11 | in, want string
12 | }{
13 | {"aGVsbG8gd29ybGQK", "hello world\n"},
14 | {"cGxlYXNlLCBkZWNvZGUgbWUK", "please, decode me\n"},
15 | }
16 |
17 | for _, c := range cases {
18 |
19 | decodedBytes, err := base64Decode([]byte(c.in))
20 | if err != nil {
21 | log.Fatal(err)
22 | }
23 | got := string(decodedBytes)
24 |
25 | if got != c.want {
26 | t.Errorf("base64 (%q) == %q, want %q", c.in, got, c.want)
27 | }
28 | }
29 | }
30 |
31 | func TestBase64Encode(t *testing.T) {
32 | cases := []struct {
33 | in, want string
34 | }{
35 | {"hello world\n", "aGVsbG8gd29ybGQK"},
36 | {"please, decode me\n", "cGxlYXNlLCBkZWNvZGUgbWUK"},
37 | }
38 |
39 | for _, c := range cases {
40 |
41 | encodedBytes := base64Encode([]byte(c.in))
42 | got := string(encodedBytes)
43 |
44 | if got != c.want {
45 | t.Errorf("base64 (%q) == %q, want %q", c.in, got, c.want)
46 | }
47 | }
48 | }
49 |
50 | func main() {}
51 |
--------------------------------------------------------------------------------
/basename/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/basename/.gitignore
--------------------------------------------------------------------------------
/basename/basename.go:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License version 3 as
4 | published by the Free Software Foundation.
5 |
6 | This program is distributed in the hope that it will be useful,
7 | but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 | GNU General Public License for more details.
10 |
11 | You should have received a copy of the GNU General Public License
12 | along with this program. If not, see .
13 | */
14 |
15 | package main
16 |
17 | import (
18 | "fmt"
19 | "os"
20 | "path/filepath"
21 | "strings"
22 |
23 | flag "github.com/ogier/pflag"
24 | )
25 |
26 | const (
27 | Help = `
28 | Usage: basename NAME [SUFFIX]
29 | or: basename OPTION... NAME...
30 | Print NAME with any leading directory components removed.
31 | If specified, also remove a trailing SUFFIX.
32 |
33 | Mandatory arguments to long options are mandatory for short options too.
34 | -a, --multiple support multiple arguments and treat each as a NAME
35 | -s, --suffix=SUFFIX remove a trailing SUFFIX; implies -a
36 | -z, --zero end each output line with NUL, not newline
37 | --help display this help and exit
38 | --version output version information and exit
39 |
40 | Examples:
41 | basename /usr/bin/sort -> "sort"
42 | basename include/stdio.h .h -> "stdio"
43 | basename -s .h include/stdio.h -> "stdio"
44 | basename -a any/str1 any/str2 -> "str1" followed by "str2"
45 |
46 | `
47 | Version = `
48 | basename (Go coreutils) 0.1
49 | Copyright (C) 2015 Robert Deusser
50 | License GPLv3+: GNU GPL version 3 or later .
51 | This is free software: you are free to change and redistribute it.
52 | There is NO WARRANTY, to the extent permitted by law.
53 |
54 | `
55 | )
56 |
57 | var (
58 | multiple = flag.BoolP("multiple", "a", false, "")
59 | suffix = flag.StringP("suffix", "s", "", "")
60 | zero = flag.BoolP("zero", "z", false, "")
61 | version = flag.BoolP("version", "v", false, "")
62 | )
63 |
64 | func baseName(path, suffix string, null bool) string {
65 | dir := filepath.Base(path)
66 |
67 | if strings.HasSuffix(dir, suffix) {
68 | dir = dir[:len(dir)-len(suffix)]
69 | }
70 |
71 | if !null {
72 | dir += "\n"
73 | }
74 |
75 | return dir
76 | }
77 |
78 | func main() {
79 | flag.Usage = func() {
80 | fmt.Fprintf(os.Stderr, "%s", Help)
81 | os.Exit(1)
82 | }
83 | flag.Parse()
84 |
85 | switch {
86 | case *version:
87 | fmt.Fprintf(os.Stdout, "%s", Version)
88 | os.Exit(0)
89 | case *multiple:
90 | for _, v := range flag.Args() {
91 | dir := baseName(v, *suffix, *zero)
92 | fmt.Print(dir)
93 | }
94 | case *suffix != "":
95 | // Implies --multiple/-a
96 | for _, v := range flag.Args() {
97 | dir := baseName(v, *suffix, *zero)
98 | fmt.Print(dir)
99 | }
100 | default:
101 | dir := baseName(flag.Args()[0], *suffix, *zero)
102 | fmt.Print(dir)
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/basename/basename_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "log"
6 | "os/exec"
7 | "testing"
8 | )
9 |
10 | func TestPerformBasename(t *testing.T) {
11 |
12 | cases := []struct {
13 | in []string
14 | want string
15 | }{
16 | {[]string{"/usr/bin/sort", ""}, "sort\n"},
17 | {[]string{"include/stdio.h", ""}, "stdio.h\n"},
18 | {[]string{"include/stdio.h", ".h"}, "stdio\n"},
19 | }
20 |
21 | for _, c := range cases {
22 | got := performBasename(c.in[0], c.in[1], false)
23 |
24 | if got != c.want {
25 | t.Errorf("basename (%q) == %q, want %q", c.in, got, c.want)
26 | }
27 | }
28 | }
29 |
30 | func TestBasename(t *testing.T) {
31 |
32 | cases := []struct {
33 | in []string
34 | want string
35 | }{
36 | {[]string{"-a", "any/str1 any/str2"}, "str1\nstr2\n"},
37 | {[]string{"-a", "any/str1 any/str2"}, "str1\nstr2\n"},
38 | {[]string{"-a", "/a//b //a/b"}, "b\nb\n"},
39 | {[]string{"-s", ".h", "include/stdio.h"}, "stdio\n"},
40 | {[]string{"-s", ".h", "-a", "any/lib.h any/lib2.h"}, "lib\nlib2\n"},
41 | {[]string{"-z", "any/str1"}, "str1"},
42 | {[]string{"-z", "-a", "any/str1 any/str2"}, "str1str2"},
43 | {[]string{"-z", "-s", ".h", "-a", "any/lib.h any/lib2.h"}, "liblib2"},
44 | }
45 |
46 | for _, c := range cases {
47 | var out bytes.Buffer
48 | cmd := exec.Command("./basename", c.in...)
49 | cmd.Stdout = &out
50 | err := cmd.Run()
51 | if err != nil {
52 | log.Fatal(err)
53 | }
54 |
55 | got := out.String()
56 | if got != c.want {
57 | t.Errorf("basename (%q) == %q, want %q", c.in, got, c.want)
58 | }
59 | }
60 |
61 | }
62 |
63 | func main() {}
64 |
--------------------------------------------------------------------------------
/build.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright (c) 2015 Eric Lagergren
4 | # This is public domain.
5 |
6 | # No set -e because we expect some installs to fail.
7 | set -uo pipefail
8 |
9 | : > build.log
10 |
11 | for d in *; do
12 | if [ -d "${d}" ]; then
13 |
14 | cd "${d}"
15 | go generate >> ../build.log 2>&1
16 | go install -a -v -x -gcflags '-m' >> ../build.log 2>&1
17 | cd ../
18 |
19 | fi
20 | done
--------------------------------------------------------------------------------
/cal/.gitignore:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/cal/cal.go:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License version 3 as
4 | published by the Free Software Foundation.
5 |
6 | This program is distributed in the hope that it will be useful,
7 | but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 | GNU General Public License for more details.
10 |
11 | You should have received a copy of the GNU General Public License
12 | along with this program. If not, see .
13 | */
14 |
15 | package main
16 |
17 | import "fmt"
18 | import flag "github.com/ogier/pflag"
19 | import "strconv"
20 | import "log"
21 | import "time"
22 |
23 | func leapyear(year int) int {
24 | //Return 1 if leapyear, 0 if not
25 | if year%4 == 0 && (year%100 != 0 || year%400 == 0) {
26 | return 1
27 | }
28 | return 0
29 | }
30 |
31 | func monthlen(month int, year int) int {
32 | //Return length of month in days
33 | switch month {
34 | case 1:
35 | return 31
36 | case 2:
37 | return 28 + leapyear(year)
38 | case 3:
39 | return 31
40 | case 4:
41 | return 30
42 | case 5:
43 | return 31
44 | case 6:
45 | return 30
46 | case 7:
47 | return 31
48 | case 8:
49 | return 31
50 | case 9:
51 | return 30
52 | case 10:
53 | return 31
54 | case 11:
55 | return 30
56 | case 12:
57 | return 31
58 | }
59 | return 0
60 | }
61 |
62 | func calendar(month int, year int) {
63 | weekday := int(time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC).Weekday())
64 | fmt.Printf("%s %d\n", time.Month(month).String(), year)
65 | fmt.Printf("Su Mo Tu We Th Fr Sa\n")
66 | for i := 0; i < weekday; i++ {
67 | fmt.Printf(" ")
68 | }
69 | for day := 1; day <= monthlen(month, year); day++ {
70 | if weekday == 6 {
71 | fmt.Printf("%2d\n", day)
72 | weekday = 0
73 | } else {
74 | fmt.Printf("%2d ", day)
75 | weekday++
76 | }
77 | }
78 | if weekday != 6 {
79 | fmt.Printf("\n")
80 | }
81 | }
82 |
83 | func main() {
84 | flag.Parse()
85 | if len(flag.Args()) == 0 {
86 | year := int(time.Now().Year())
87 | month := int(time.Now().Month())
88 | calendar(month, year)
89 | } else if len(flag.Args()) == 1 {
90 | year, err := strconv.Atoi(flag.Arg(0))
91 | if err != nil {
92 | log.Fatal(err)
93 | }
94 | for month := 1; month <= 12; month++ {
95 | calendar(month, year)
96 | fmt.Println()
97 | }
98 | } else if len(flag.Args()) == 2 {
99 | month, err := strconv.Atoi(flag.Arg(0))
100 | if err != nil {
101 | log.Fatal(err)
102 | }
103 | year, err := strconv.Atoi(flag.Arg(1))
104 | if err != nil {
105 | log.Fatal(err)
106 | }
107 | calendar(month, year)
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/cat/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/cat/.gitignore
--------------------------------------------------------------------------------
/cat/cat_test.go:
--------------------------------------------------------------------------------
1 | // +build linux
2 |
3 | package main
4 |
5 | import (
6 | "bufio"
7 | "bytes"
8 | "io"
9 | "os"
10 | "os/exec"
11 | "syscall"
12 | "testing"
13 | )
14 |
15 | var flist = [...]string{
16 | "test_files/lang_ru.txt",
17 | "test_files/dict_en.txt",
18 | "test_files/spaces_en.txt",
19 | "test_files/coreutils_man_en.txt",
20 | }
21 |
22 | var buf bytes.Buffer
23 |
24 | func TestCat(t *testing.T) {
25 |
26 | showNonPrinting = true
27 | *nonPrint = true
28 | *npEnds = true
29 | *npTabs = true
30 |
31 | for i, f := range flist {
32 |
33 | // set up our capture of stdout
34 | stdout := os.Stdout
35 | r, w, err := os.Pipe()
36 | if err != nil {
37 | t.Fatal(err)
38 | }
39 | os.Stdout = w
40 |
41 | file, err := os.Open(f)
42 | if err != nil {
43 | t.Error(err)
44 | }
45 |
46 | inStat, err := file.Stat()
47 | if err != nil {
48 | t.Error(err)
49 | }
50 | if inStat.IsDir() {
51 | t.Errorf("%s: is a directory\n", file.Name())
52 | }
53 |
54 | inBsize := int(inStat.Sys().(*syscall.Stat_t).Blksize)
55 | size := 20 + inBsize*4
56 | outBuf := bufio.NewWriterSize(os.Stdout, size)
57 | inBuf := make([]byte, inBsize+1)
58 |
59 | cat(file, inBuf, outBuf)
60 | file.Close()
61 |
62 | // capture the stdout
63 | outC := make(chan string)
64 | go func() {
65 | var b bytes.Buffer
66 | _, err := io.Copy(&b, r)
67 |
68 | r.Close()
69 | if err != nil {
70 | t.Fatal(err)
71 | }
72 | outC <- b.String()
73 | }()
74 |
75 | // now get stdout of native cat
76 | cat := exec.Command("cat", "-A", flist[i])
77 |
78 | b, err := cat.Output()
79 | if err != nil {
80 | t.Fatal(err)
81 | }
82 | buf.Write(b)
83 |
84 | // stop capturing of stdout
85 | w.Close()
86 | os.Stdout = stdout
87 | out := <-outC
88 |
89 | // check strings
90 | if out != buf.String() {
91 | t.Fatalf("Got:\n%s\n\nExpected:\n%s\n", out, buf.String())
92 | }
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/cat/cat_unix.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014-2016 Eric Lagergren
2 | // Use of this source code is governed by the GPL v3 or later.
3 |
4 | package main
5 |
6 | import (
7 | "bufio"
8 | "log"
9 | "os"
10 |
11 | "github.com/EricLagergren/go-coreutils/internal/flag"
12 |
13 | "golang.org/x/sys/unix"
14 | )
15 |
16 | func bsize(info os.FileInfo) int {
17 | stat, ok := info.Sys().(*unix.Stat_t)
18 | if !ok {
19 | log.Fatalln("cat: (bug) inf.Sys().(*unix.Stat_t) is false")
20 | }
21 | // (Taken from ioblksize.h)
22 | // bufSize is determined by:
23 | //
24 | // for i in $(seq 0 10); do
25 | // bs=$((1024*2**$i))
26 | // printf "%7s=" $bs
27 | // timeout --foreground -sINT 2 \
28 | // dd bs=$bs if=/dev/zero of=/dev/null 2>&1 \
29 | // | sed -n 's/.* \([0-9.]* [GM]B\/s\)/\1/p'
30 | // done
31 | const bufSize = 128 * 1024
32 | return max(bufSize, int(stat.Blksize))
33 | }
34 |
35 | func main() {
36 | var ok int // return status
37 |
38 | outStat, err := os.Stdout.Stat()
39 | if err != nil {
40 | fatal.Fatalln(err)
41 | }
42 | outReg := outStat.Mode().IsRegular()
43 | outBsize := bsize(outStat)
44 |
45 | // catch (./cat) < /etc/group
46 | args := flag.Args()
47 | if flag.NArg() == 0 {
48 | args = []string{"-"}
49 | }
50 |
51 | var file *os.File
52 | for _, arg := range args {
53 | file = os.Stdin
54 | if arg != "-" {
55 | file, err = os.Open(arg)
56 | if err != nil {
57 | fatal.Fatalln(err)
58 | }
59 | }
60 |
61 | inStat, err := file.Stat()
62 | if err != nil {
63 | fatal.Fatalln(err)
64 | }
65 | if inStat.IsDir() {
66 | fatal.Printf("%s: is a directory\n", file.Name())
67 | }
68 | inBsize := bsize(inStat)
69 |
70 | // prefetch! prefetch! prefetch!
71 | unix.Fadvise(int(file.Fd()), 0, 0, unix.FADV_SEQUENTIAL)
72 |
73 | // Make sure we're not catting a file to itself,
74 | // provided it's a regular file. Catting a non-reg
75 | // file to itself is cool.
76 | // e.g. cat file > file
77 | if outReg && os.SameFile(outStat, inStat) {
78 | if n, _ := file.Seek(0, os.SEEK_CUR); n < inStat.Size() {
79 | fatal.Fatalf("%s: input file is output file\n", file.Name())
80 | }
81 | }
82 |
83 | pageSize := os.Getpagesize()
84 | if simple {
85 | // Select larger block size
86 | size := max(inBsize, outBsize)
87 | outBuf := bufio.NewWriterSize(os.Stdout, size+pageSize-1)
88 | ok ^= simpleCat(file, outBuf)
89 |
90 | // Flush because we don't have a chance to in
91 | // simpleCat() because we use io.Copy()
92 | outBuf.Flush()
93 | } else {
94 | // If you want to know why, exactly, I chose
95 | // outBsize -1 + inBsize*4 + 20, read GNU's cat
96 | // source code. The tl;dr is the 20 is the counter
97 | // buffer, inBsize*4 is from potentially prepending
98 | // the control characters (M-^), and outBsize is
99 | // due to new tests for newlines.
100 | size := outBsize - 1 + inBsize*4 + 20
101 | outBuf := bufio.NewWriterSize(os.Stdout, size)
102 | inBuf := make([]byte, inBsize+pageSize-1)
103 | ok ^= cat(file, inBuf, outBuf)
104 | }
105 |
106 | file.Close()
107 | }
108 |
109 | os.Exit(ok)
110 | }
111 |
--------------------------------------------------------------------------------
/cat/cat_windows.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014-2016 Eric Lagergren
2 | // Use of this source code is governed by the GPL v3 or later.
3 |
4 | package main
5 |
6 | import (
7 | "bufio"
8 | "os"
9 | "syscall"
10 |
11 | k32 "github.com/EricLagergren/go-gnulib/windows"
12 | flag "github.com/ogier/pflag"
13 | )
14 |
15 | func main() {
16 | var ok int // return status
17 |
18 | outHandle := syscall.Handle(os.Stdout.Fd())
19 | outType, err := syscall.GetFileType(outHandle)
20 | if err != nil {
21 | fatal.Fatalln(err)
22 | }
23 | outBsize := 4096
24 |
25 | // catch (./cat) < /etc/group
26 | var args []string
27 | if flag.NArg() == 0 {
28 | args = []string{"-"}
29 | } else {
30 | args = flag.Args()
31 | }
32 |
33 | // the main loop
34 | var file *os.File
35 | for _, arg := range args {
36 | var inStat os.FileInfo
37 |
38 | if arg == "-" {
39 | file = os.Stdin
40 | } else {
41 | file, err = os.Open(arg)
42 | if err != nil {
43 | fatal.Fatalln(err)
44 | }
45 |
46 | inStat, err = file.Stat()
47 | if err != nil {
48 | fatal.Fatalln(err)
49 | }
50 | if inStat.IsDir() {
51 | fatal.Printf("%s: Is a directory\n", file.Name())
52 | }
53 | }
54 |
55 | inHandle := syscall.Handle(file.Fd())
56 | inBsize := 4096
57 |
58 | // See http://stackoverflow.com/q/29360969/2967113
59 | // for why this differs from the Unix versions.
60 | //
61 | // Make sure we're not catting a file to itself,
62 | // provided it's a regular file. Catting a non-reg
63 | // file to itself is cool, e.g. cat file > file
64 | if outType == syscall.FILE_TYPE_DISK {
65 |
66 | inPath := make([]byte, syscall.MAX_PATH)
67 | outPath := make([]byte, syscall.MAX_PATH)
68 |
69 | err = k32.GetFinalPathNameByHandleA(inHandle, inPath, 0)
70 | if err != nil {
71 | fatal.Fatalln(err)
72 | }
73 |
74 | err = k32.GetFinalPathNameByHandleA(outHandle, outPath, 0)
75 | if err != nil {
76 | fatal.Fatalln(err)
77 | }
78 |
79 | if string(inPath) == string(outPath) {
80 | if n, _ := file.Seek(0, os.SEEK_CUR); n < inStat.Size() {
81 | fatal.Fatalf("%s: input file is output file\n", file.Name())
82 | }
83 | }
84 | }
85 |
86 | if simple {
87 | outBuf := bufio.NewWriterSize(os.Stdout, 4096)
88 | ok ^= simpleCat(file, outBuf)
89 |
90 | // Flush because we don't have a chance to in
91 | // simpleCat() because we use io.Copy()
92 | outBuf.Flush()
93 | } else {
94 | // If you want to know why, exactly, I chose
95 | // outBsize -1 + inBsize*4 + 20, read GNU's cat
96 | // source code. The tl;dr is the 20 is the counter
97 | // buffer, inBsize*4 is from potentially prepending
98 | // the control characters (M-^), and outBsize is
99 | // due to new tests for newlines.
100 | size := outBsize - 1 + inBsize*4 + 20
101 | outBuf := bufio.NewWriterSize(os.Stdout, size)
102 | inBuf := make([]byte, inBsize+1)
103 | ok ^= cat(file, inBuf, outBuf)
104 | }
105 |
106 | file.Close()
107 | }
108 |
109 | os.Exit(ok)
110 | }
111 |
--------------------------------------------------------------------------------
/cat/test_files/coreutils_man_en.txt:
--------------------------------------------------------------------------------
1 | Next: sum invocation, Up: Summarizing files
2 |
3 | 6.1 wc: Print newline, word, and byte counts
4 |
5 | wc counts the number of bytes, characters, whitespace-separated words, and newlines in each given file, or standard input if none are given or for a file of ‘-’. Synopsis:
6 |
7 | wc [option]... [file]...
8 | wc prints one line of counts for each file, and if the file was given as an argument, it prints the file name following the counts. If more than one file is given, wc prints a final line containing the cumulative counts, with the file name total. The counts are printed in this order: newlines, words, characters, bytes, maximum line length. Each count is printed right-justified in a field with at least one space between fields so that the numbers and file names normally line up nicely in columns. The width of the count fields varies depending on the inputs, so you should not depend on a particular field width. However, as a GNU extension, if only one count is printed, it is guaranteed to be printed without leading spaces.
9 |
10 | By default, wc prints three counts: the newline, words, and byte counts. Options can specify that only certain counts be printed. Options do not undo others previously given, so
11 |
12 | wc --bytes --words
13 | prints both the byte counts and the word counts.
14 |
15 | With the --max-line-length option, wc prints the length of the longest line per file, and if there is more than one file it prints the maximum (not the sum) of those lengths. The line lengths here are measured in screen columns, according to the current locale and assuming tab positions in every 8th column.
16 |
17 | The program accepts the following options. Also see Common options.
18 |
19 | ‘-c’
20 | ‘--bytes’
21 | Print only the byte counts.
22 | ‘-m’
23 | ‘--chars’
24 | Print only the character counts.
25 | ‘-w’
26 | ‘--words’
27 | Print only the word counts.
28 | ‘-l’
29 | ‘--lines’
30 | Print only the newline counts.
31 | ‘-L’
32 | ‘--max-line-length’
33 | Print only the maximum line lengths.
34 | ‘--files0-from=file’
35 | Disallow processing files named on the command line, and instead process those named in file file; each name being terminated by a zero byte (ASCII NUL). This is useful when the list of file names is so long that it may exceed a command line length limitation. In such cases, running wc via xargs is undesirable because it splits the list into pieces and makes wc print a total for each sublist rather than for the entire list. One way to produce a list of ASCII NUL terminated file names is with GNU find, using its -print0 predicate. If file is ‘-’ then the ASCII NUL terminated file names are read from standard input.
36 | For example, to find the length of the longest line in any .c or .h file in the current hierarchy, do this:
37 |
38 | find . -name '*.[ch]' -print0 |
39 | wc -L --files0-from=- | tail -n1
40 | An exit status of zero indicates success, and a nonzero value indicates failure.
--------------------------------------------------------------------------------
/cat/test_files/file_list.txt:
--------------------------------------------------------------------------------
1 | ./test_files/file_list.txt ./test_files/spaces_en.txt ./test_files/dict_en.txt ./test_files/lang_ru.txt ./test_files/coreutils_man_en.txt
--------------------------------------------------------------------------------
/cat/test_files/spaces_en.txt:
--------------------------------------------------------------------------------
1 | Hello, world!
2 | This is a test file to see if1 my wc utilit y
3 |
4 | is
5 | able
6 |
7 | to det
8 | ermine the correct counts for different fi
9 | les.
10 |
--------------------------------------------------------------------------------
/chcon/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/chcon/.gitignore
--------------------------------------------------------------------------------
/chcon/chcon.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/chgrp/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/chgrp/.gitignore
--------------------------------------------------------------------------------
/chgrp/chgrp.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/chmod/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/chmod/.gitignore
--------------------------------------------------------------------------------
/chmod/chmod.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/chown/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/chown/.gitignore
--------------------------------------------------------------------------------
/chown/README.md:
--------------------------------------------------------------------------------
1 | **See https://codereview.appspot.com/101310044/ for more information about why
2 | we need to install a patch**
3 |
4 | ### IMPORTANT NOTES:
5 |
6 | - (1) `-R` could get stuck on looped symlinks (e.g. foo -> bar -> foo -> bar)
7 |
8 | ### PATCH NOTES:
9 | - (1) fixed `--from=` on 03 Dec, 2014
--------------------------------------------------------------------------------
/chown/checksum:
--------------------------------------------------------------------------------
1 | 8cb8c7de1776a5badf4f0070eb009363 patch101310044_20001.tar.bz2
--------------------------------------------------------------------------------
/chown/chown:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/chown/chown
--------------------------------------------------------------------------------
/chown/chown.go:
--------------------------------------------------------------------------------
1 | /*
2 | Go chown -- change ownership of a file
3 |
4 | Copyright (c) 2014-2015 Eric Lagergren
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | /*
21 | Written by Eric Lagergren
22 | */
23 |
24 | // BUG(eric): -R flag could get stuck in an infinite loop
25 |
26 | package main
27 |
28 | import (
29 | "fmt"
30 | "os"
31 |
32 | flag "github.com/EricLagergren/pflag"
33 | )
34 |
35 | const (
36 | Help = "help"
37 | Version = "version"
38 | )
39 |
40 | var (
41 | recursive = flag.BoolP("recursive", "R", false, "")
42 | changes = flag.BoolP("changes", "c", false, "")
43 | dereference = flag.Bool("dereference", false, "")
44 | from = flag.Bool("from", false, "")
45 | noDereference = flag.BoolP("no-dereference", "h", false, "")
46 | noPreserveRoot = flag.Bool("no-preserve-root", false, "")
47 | quiet = flag.Bool("quiet", false, "")
48 | silent = flag.Bool("silent", false, "")
49 | reference = flag.Bool("reference", false, "")
50 | verbose = flag.BoolP("verbose", "v", false, "")
51 |
52 | version = flag.Bool("version", false, "")
53 | )
54 |
55 | func main() {
56 | flag.Usage = func() {
57 | fmt.Fprintf(os.Stderr, "%s", Help)
58 | os.Exit(1)
59 | }
60 | flag.Parse()
61 |
62 | if *version {
63 | fmt.Printf("%s\n", Version)
64 | os.Exit(0)
65 | }
66 |
67 | // 1 if --dereference, 0 if --no-dereference, -1 if neither
68 | // has been specified.
69 | // deref := -1
70 | // bitFlags := 12 // todo
71 | }
72 |
--------------------------------------------------------------------------------
/chown/chown_core.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "syscall"
7 | // "strconv"
8 | )
9 |
10 | func newChownOption() *ChownOption {
11 | // Rest fall back to their zero-value.
12 | return &ChownOption{
13 | verbosity: VOff,
14 | affectSymlinkReferent: true,
15 | }
16 | }
17 |
18 | // func gidToName(gid uint32) (string, error) {
19 | // id, err := user.LookupGroupId(strconv.FormatUint(uint64(gid), 10))
20 | // if err != nil {
21 | // return "", err
22 | // }
23 | // return id.Name, nil
24 | // }
25 |
26 | // func uidToName(uid uint32) (string, error) {
27 | // id, err := user.LookupId(strconv.FormatUint(uint64(uid), 10))
28 | // if err != nil {
29 | // return "", err
30 | // }
31 | // return id.Name, nil
32 | // }
33 |
34 | func UserGroupString(user, group string) string {
35 | var spec string
36 | if user != "" {
37 | if group != "" {
38 | spec = fmt.Sprintf("%s:%s", user, group)
39 | } else {
40 | spec = user
41 | }
42 | } else if group != "" {
43 | spec = group
44 | }
45 | return spec
46 | }
47 |
48 | func DescribeChange(file string, changed ChangeStatus, oldUser, oldGroup, user, group string) {
49 |
50 | if changed == CHNotApplied {
51 | fmt.Printf("neither symbolic link %q nor referent has been changed\n", file)
52 | return
53 | }
54 |
55 | spec := UserGroupString(user, group)
56 | var oldSpec string
57 | if user != "" {
58 | if group != "" {
59 | oldSpec = UserGroupString(oldUser, oldGroup)
60 | } else {
61 | oldSpec = UserGroupString(oldUser, "")
62 | }
63 | } else if group != "" {
64 | oldSpec = UserGroupString("", oldGroup)
65 | } else {
66 | oldSpec = UserGroupString("", "")
67 | }
68 |
69 | var format string
70 | switch changed {
71 | case CHSucceeded:
72 | if user != "" {
73 | format = "changed ownership of %q from %s to %s\n"
74 | } else if group != "" {
75 | format = "changed group of %q from %s to %s\n"
76 | } else {
77 | format = "no change to ownership of %s\n"
78 | }
79 | case CHFailed:
80 | if oldSpec != "" {
81 | if user != "" {
82 | format = "failed to change ownership of %q from %s to %s\n"
83 | } else if group != "" {
84 | format = "failed to change group of %q from %s to %s\n"
85 | } else {
86 | format = "failed to change ownership of %q\n"
87 | }
88 | }
89 | case CHNoChangeRequested:
90 | if user != "" {
91 | format = "ownership of %q retained as %s\n"
92 | } else if group != "" {
93 | format = "group of %q retained as %s\n"
94 | } else {
95 | format = "ownership of %q retained\n"
96 | }
97 | default:
98 | os.Exit(1)
99 | }
100 |
101 | fmt.Printf(format, file, oldSpec, spec)
102 | }
103 |
104 | func RestrictedChown(cwdFd int, file string, origStat os.FileInfo, uid, gid, reqUid, reqGid int) RCHStatus {
105 |
106 | status := RCOK
107 | openflags := syscall.O_NONBLOCK | syscall.O_NOCTTY
108 |
109 | if reqUid == -1 && reqGid == 1 {
110 | return RCDoOrdinaryChown
111 | }
112 |
113 | if !origStat.Mode().IsRegular() {
114 | if !origStat.Mode().IsDir() {
115 | return RCDoOrdinaryChown
116 | }
117 | openflags |= syscall.O_DIRECTORY
118 | }
119 |
120 | fd, err := syscall.Openat(cwdFd, file, syscall.O_RDONLY|openflags, 0)
121 |
122 | if !(0 <= fd ||
123 | err == syscall.EACCES &&
124 | origStat.Mode().IsRegular()) {
125 |
126 | if fd, err = syscall.Openat(cwdFd, file, syscall.O_WRONLY|openflags, 0); 0 > fd {
127 |
128 | if err == syscall.EACCES {
129 | return RCDoOrdinaryChown
130 | }
131 | return RCError
132 | }
133 | }
134 |
135 | var stat syscall.Stat_t
136 | if err := syscall.Fstat(fd, &stat); err != nil {
137 | status = RCError
138 | } else if !sameFile(origStat.Sys().(*syscall.Stat_t), &stat) {
139 | status = RCInodeChanged
140 | } else if reqUid == -1 || uint32(reqUid) == stat.Uid &&
141 | (reqGid == -1 || uint32(reqGid) == stat.Gid) {
142 | if syscall.Fchown(fd, uid, gid) == nil {
143 | if syscall.Close(fd) == nil {
144 | return RCOK
145 | }
146 | return RCError
147 | } else {
148 | status = RCError
149 | }
150 | }
151 |
152 | return status
153 | }
154 |
155 | // Basically borrowed from os/stat_linux.go but there's no
156 | // other way to do it.
157 | func sameFile(st1, st2 *syscall.Stat_t) bool {
158 | return st1.Dev == st2.Dev && st1.Ino == st2.Ino
159 | }
160 |
161 | func ChangeFileOwner(uid, gid, reqUid, reqGid uint32, chopt ChownOption) bool {
162 |
163 | }
164 |
--------------------------------------------------------------------------------
/chown/chown_types.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | type ChangeStatus int
4 |
5 | const (
6 | _ = iota
7 |
8 | CHNotApplied ChangeStatus = iota
9 | CHSucceeded
10 | CHFailed
11 | CHNoChangeRequested
12 | )
13 |
14 | type Verbosity int
15 |
16 | const (
17 | VHigh Verbosity = iota
18 | VChangesOnly
19 | VOff
20 | )
21 |
22 | type ChownOption struct {
23 | verbosity Verbosity
24 | recurse bool
25 | // rootDevIno *devIno
26 | affectSymlinkReferent bool
27 | forceSilent bool
28 | userName string
29 | groupName string
30 | }
31 |
32 | type RCHStatus int
33 |
34 | const (
35 | _ = iota
36 | _ = iota
37 |
38 | RCOK RCHStatus = iota
39 | RCExcluded
40 | RCInodeChanged
41 | RCDoOrdinaryChown
42 | RCError
43 | )
44 |
--------------------------------------------------------------------------------
/chown/patch.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -euf -o pipefail
3 |
4 |
5 | ORIG=$PWD
6 |
7 | # You don't need wget the tarball unless you don't trust mine...
8 | # MD5: 8cb8c7de1776a5badf4f0070eb009363 patch101310044_20001.tar.bz2
9 |
10 | #PATCH=https://codereview.appspot.com/tarball/101310044/20001
11 | FNAME=patch101310044_20001.tar.bz2
12 | #wget -O $FNAME $PATCH
13 |
14 | # If this fails then either the downloaded tarball was downloaded incorrectly
15 | # or something else weird happened. In any case, go to
16 | # https://codereview.appspot.com/101310044/ and find the correct patch,
17 | # download the tarball, and place it inside this directory under the name
18 | # patch101310044_20001.tar.bz2 and then run this script
19 | # Or just do it yourself
20 | md5sum -c checksum
21 | if [[ $? != 0 ]]; then
22 | echo "checksum did not match."
23 | exit 1
24 | fi
25 |
26 | tar -xjf $FNAME
27 |
28 | if [ ! $GOROOT ]; then
29 | GOROOT="$(dirname "$(which go)")"
30 | fi
31 |
32 | cd $GOROOT && cd ../
33 | cd src/pkg/os/
34 | rm --preserve-root -r a/
35 | cp -r $ORIG/b/src/pkg/os/user/* user/
36 | if [[ $? != 0 ]]; then
37 | if [[ $EUID -ne 0 ]]; then
38 | echo "If 'permission denied', then this script must be run as root" 1>&2
39 | exit 1
40 | fi
41 | fi
42 | cd ../../
43 | ./all.bash
44 | if [[ $? != 0 ]]; then
45 | if [[ $EUID -ne 0 ]]; then
46 | echo "If 'permission denied', then this script must be run as root" 1>&2
47 | exit 1
48 | fi
49 | fi
50 | cd $ORIG
51 | rm --preserve-root -r b/
52 |
53 | exit 0
54 |
--------------------------------------------------------------------------------
/chown/patch101310044_20001.tar.bz2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/chown/patch101310044_20001.tar.bz2
--------------------------------------------------------------------------------
/chroot/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/chroot/.gitignore
--------------------------------------------------------------------------------
/chroot/chroot.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/cksum/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/cksum/.gitignore
--------------------------------------------------------------------------------
/cksum/cksum.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/comm/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/comm/.gitignore
--------------------------------------------------------------------------------
/comm/comm.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/coreutils.go:
--------------------------------------------------------------------------------
1 | package coreutils
2 |
3 | import (
4 | "context"
5 | "errors"
6 | "io"
7 | "sync"
8 | )
9 |
10 | var cmdsMu sync.Mutex
11 | var cmds = make(map[string]Runnable)
12 |
13 | func Register(name string, r Runnable) {
14 | cmdsMu.Lock()
15 | defer cmdsMu.Unlock()
16 | if _, ok := cmds[name]; ok {
17 | panic("Register called with identical name: " + name)
18 | }
19 | cmds[name] = r
20 | }
21 |
22 | type Runnable func(ctx Context, args ...string) error
23 |
24 | type Context struct {
25 | context.Context
26 | Dir string
27 | GetEnv func(string) string
28 | Stdin io.Reader
29 | Stdout io.Writer
30 | Stderr io.Writer
31 | }
32 |
33 | func Run(ctx Context, name string, args ...string) error {
34 | cmdsMu.Lock()
35 | fn := cmds[name]
36 | cmdsMu.Unlock()
37 | if fn == nil {
38 | return errors.New("invalid function ...")
39 | }
40 | return fn(ctx, args...)
41 | }
42 |
--------------------------------------------------------------------------------
/cp/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/cp/.gitignore
--------------------------------------------------------------------------------
/cp/foo.txt:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "io"
6 | "log"
7 | "os"
8 | "syscall"
9 | )
10 |
11 | type Options struct {
12 | AsRegular bool
13 | Dereference bool // check type
14 | UnlinkBefore bool
15 | UnlinkAfterFailed bool
16 | HardLink bool
17 | Interactive bool
18 | MoveMode bool
19 | OneFS bool
20 | RefLinkMode bool // check type
21 |
22 | PreserveOwnership bool
23 | PreserveLinks bool
24 | PreserveMode bool
25 | PreserveTimestamps bool
26 | ExplicitNoPreserve bool
27 | PreserveSecurityContex bool // -a or --preserve=context
28 | RequirePreserveContext bool // --preserve=contex
29 | SetSecurityContext bool // -Z, set sys default contex
30 | PreserveXattr bool
31 | ReduceDiagnostics bool
32 | RequirePreserveXattr bool
33 |
34 | DataCopyRequired bool
35 | RequirePreserve bool
36 | Recursive bool
37 | SparseMode bool // check type
38 | SymbolicLink bool
39 | SetMode bool
40 | Mode int
41 |
42 | Update bool
43 | Verbose bool
44 | }
45 |
46 | func newOptions() *Options {
47 | return &Options{
48 | AsRegular: true,
49 | Dereference: true, // check type
50 | //HardLink: ? //check type
51 | //Interactive: ? //check type
52 | //RefLinkMode: ? //checktype
53 | }
54 | }
55 |
56 | func isDir(file string) (bool, *os.FileInfo) {
57 | info, err := os.Stat(file)
58 | if err != nil {
59 | if err.(*os.PathError).Err != syscall.ENOENT {
60 | log.Fatalf("%s failed to access %s", err, file)
61 | }
62 | return false, nil
63 | }
64 | return info.Mode().IsDir(), &info
65 | }
66 |
67 | func cp(n int, file []string, dir string, options *Options) {
68 | if n <= 0 {
69 | log.Fatalln("missing file operand")
70 | }
71 |
72 | if noDir {
73 |
74 | }
75 | }
76 |
77 | func main() {
78 | }
79 |
--------------------------------------------------------------------------------
/cp/idk.go:
--------------------------------------------------------------------------------
1 | package main
2 |
--------------------------------------------------------------------------------
/csplit/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/csplit/.gitignore
--------------------------------------------------------------------------------
/csplit/boyermoore.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | var BuffSize = 7
4 |
5 | func main() {
6 | pattern := "eric"
7 | test := "america"
8 | }
9 |
10 | func preBad(x string, m int, badChar []int) {
11 | for i := 0; i < BuffSize; i++ {
12 | badChar[i] = m
13 | }
14 |
15 | for i := 0; i < m-1; i++ {
16 | badChar[x[i]] = m - i - 1
17 | }
18 | }
19 |
20 | func suffix(x string, m int, suff []int) {
21 | var f int
22 |
23 | suff[m-1] = m
24 | g := m - 1
25 |
26 | for i := m - 2; i >= 0; i-- {
27 | if i > g && suff[i+m-1-f] < i-g {
28 | suff[i] = suff[i+m-1-f]
29 | } else {
30 | if i > g {
31 | g = i
32 | }
33 | f = i
34 | for g >= 0 && x[g] == x[g+m-1-f] {
35 | g--
36 | }
37 | suff[i] = f - g
38 | }
39 | }
40 | }
41 |
42 | func preGood(x string, m int, goodChar []int) {
43 | suff := make([]int, BuffSize)
44 | suffix(x, m, suff)
45 | }
46 |
--------------------------------------------------------------------------------
/csplit/csplit.go:
--------------------------------------------------------------------------------
1 | package main
2 |
--------------------------------------------------------------------------------
/csplit/mmap.go:
--------------------------------------------------------------------------------
1 | package main
2 |
--------------------------------------------------------------------------------
/csplit/read.go:
--------------------------------------------------------------------------------
1 | package main
2 |
--------------------------------------------------------------------------------
/csplit/test.txt:
--------------------------------------------------------------------------------
1 | I. HELLO
2 | II. THIS
3 | III. IS
4 | IV. A
5 | V. TEST
--------------------------------------------------------------------------------
/cut/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/cut/.gitignore
--------------------------------------------------------------------------------
/cut/cut.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/date/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/date/.gitignore
--------------------------------------------------------------------------------
/date/date.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/dd/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/dd/.gitignore
--------------------------------------------------------------------------------
/dd/dd.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/df/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/df/.gitignore
--------------------------------------------------------------------------------
/df/df.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/dir/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/dir/.gitignore
--------------------------------------------------------------------------------
/dir/dir.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/dircolors/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/dircolors/.gitignore
--------------------------------------------------------------------------------
/dircolors/dircolors.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/dirname/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/dirname/.gitignore
--------------------------------------------------------------------------------
/dirname/dirname.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/du/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/du/.gitignore
--------------------------------------------------------------------------------
/du/du.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/echo/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/echo/.gitignore
--------------------------------------------------------------------------------
/echo/echo.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/editlicensedates.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright (c) 2015 Eric Lagergren
4 | # This is public domain.
5 |
6 | set -euo pipefail
7 |
8 | shopt -s globstar nullglob extglob
9 | for f in **/*.@(go); do
10 | if [[ -f $f ]]; then
11 | sed -i 's/Copyright (C) 2014 /Copyright (c) 2014-2015 /g' "$f"
12 | fi
13 | done
--------------------------------------------------------------------------------
/env/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/env/.gitignore
--------------------------------------------------------------------------------
/env/env.go:
--------------------------------------------------------------------------------
1 | /*
2 | Go env - run a program in a modified environment
3 | Copyright (C) 1986-2015 Eric Lagergren
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | package main
20 |
21 | import (
22 | "fmt"
23 | "log"
24 | "os"
25 | "os/exec"
26 | "strings"
27 |
28 | flag "github.com/ogier/pflag"
29 | )
30 |
31 | const (
32 | help = `
33 | Usage: env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]
34 | Set each NAME to VALUE in the environment and run COMMAND.
35 |
36 | Mandatory arguments to long options are mandatory for short options too.
37 | -i, --ignore-environment start with an empty environment
38 | -0, --null end each output line with NUL, not newline
39 | -u, --unset=NAME remove variable from the environment
40 | -s, --set=NAME set variable in the environment
41 | --help display this help and exit
42 | --version output version information and exit
43 |
44 | A mere - implies -i. If no COMMAND, print the resulting environment.
45 |
46 | Report wc bugs to ericscottlagergren@gmail.com
47 | Go coreutils home page:
48 | `
49 | version = `env (Go coreutils) 1.0
50 | Copyright (C) 2015 Eric Lagergren
51 | License GPLv3+: GNU GPL version 3 or later .
52 | This is free software: you are free to change and redistribute it.
53 | There is NO WARRANTY, to the extent permitted by law.
54 | `
55 | )
56 |
57 | var (
58 | unset string
59 | set string
60 | nullEol bool
61 | ignore bool
62 |
63 | // fatal = log.New(os.Stderr, "", log.Lshortfile)
64 | fatal = log.New(os.Stderr, "", 0)
65 |
66 | env = os.Environ()
67 | )
68 |
69 | // Run a command, waiting for it to finish. Will first run CMD's path;
70 | // failing that, will lookup the path and attempt to do the same.
71 | func execvp(cmd exec.Cmd) error {
72 | if err := cmd.Start(); err == nil {
73 |
74 | // Wait for command to finish
75 | return cmd.Wait()
76 |
77 | }
78 |
79 | // Didn't work? Search for the executable's path
80 | path, err := exec.LookPath(cmd.Path)
81 | if err != nil {
82 | return err
83 | }
84 |
85 | // Reset our path
86 | cmd.Path = path
87 |
88 | // Try again with the executable found in $PATH
89 | if err = cmd.Start(); err != nil {
90 | return err
91 | }
92 | return cmd.Wait()
93 | }
94 |
95 | func parseFlags(argv []string) (args []string) {
96 | for i := 1; i < len(argv); i++ {
97 | switch v := argv[i]; v {
98 | case "-i", "--ignore-environment":
99 | ignore = true
100 | case "-0", "--null":
101 | nullEol = true
102 | case "-u", "--unset":
103 | i++
104 | unset = argv[i]
105 | case "-s", "--set":
106 | i++
107 | set = argv[i]
108 | case "--help":
109 | fmt.Fprintf(os.Stderr, "%s", help)
110 | os.Exit(1)
111 | case "--version":
112 | fmt.Printf("%s", version)
113 | os.Exit(0)
114 | default:
115 | args = append(args, v)
116 | }
117 | }
118 | return args
119 | }
120 |
121 | func main() {
122 | args := parseFlags(os.Args)
123 |
124 | if unset != "" {
125 | os.Unsetenv(unset)
126 | }
127 |
128 | cmd := exec.Cmd{Env: env}
129 |
130 | // Check for "-" as an argument, because it means the same as "-i"
131 | if flag.Arg(0) == "-" {
132 | cmd.Env = []string{}
133 | }
134 |
135 | for i, arg := range args {
136 | if strings.Index(arg, "=") > 0 {
137 | cmd.Env = append(cmd.Env, arg)
138 | } else if arg != "-" {
139 | if nullEol {
140 | fatal.Fatalln("cannot specify --null (-0) with command")
141 | }
142 |
143 | cmd.Path = arg
144 |
145 | cmd.Args = append(cmd.Args, args[i:]...)
146 | cmd.Stdin = os.Stdin
147 | cmd.Stdout = os.Stdout
148 | cmd.Stderr = os.Stderr
149 |
150 | if err := execvp(cmd); err != nil {
151 | fatal.Fatalln(err)
152 | }
153 | return
154 | }
155 | }
156 |
157 | eol := '\n'
158 | if nullEol {
159 | eol = '\x00'
160 | }
161 |
162 | for _, e := range env {
163 | fmt.Printf("%s%c", e, eol)
164 | }
165 |
166 | return
167 | }
168 |
--------------------------------------------------------------------------------
/expand/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/expand/.gitignore
--------------------------------------------------------------------------------
/expand/expand.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/expr/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/expr/.gitignore
--------------------------------------------------------------------------------
/expr/expr.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/factor/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/factor/.gitignore
--------------------------------------------------------------------------------
/factor/factor.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/false/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/false/.gitignore
--------------------------------------------------------------------------------
/false/false.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | )
7 |
8 | const (
9 | Help = `Usage: /usr/bin/false [ignored command line arguments]
10 | or: /usr/bin/false OPTION
11 | Exit with a status code indicating success.
12 |
13 | --help display this help and exit
14 | --version output version information and exit
15 |
16 | NOTE: your shell may have its own version of false, which usually supersedes
17 | the version described here. Please refer to your shell's documentation
18 | for details about the options it supports.
19 | `
20 | Version = `false (Go coreutils) 1.0
21 | Copyright (C) 2015 Eric Lagergren
22 | License GPLv3+: GNU GPL version 3 or later .
23 | This is free software: you are free to change and redistribute it.
24 | There is NO WARRANTY, to the extent permitted by law.
25 | `
26 | )
27 |
28 | func main() {
29 | if len(os.Args) == 2 {
30 | if os.Args[1] == "--help" {
31 | fmt.Printf("%s", Help)
32 | }
33 |
34 | if os.Args[1] == "--version" {
35 | fmt.Printf("%s", Version)
36 | }
37 | }
38 | os.Exit(1)
39 | }
40 |
--------------------------------------------------------------------------------
/fmt/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/fmt/.gitignore
--------------------------------------------------------------------------------
/fmt/fmt.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/fold/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/fold/.gitignore
--------------------------------------------------------------------------------
/fold/fold.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/groups/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/groups/.gitignore
--------------------------------------------------------------------------------
/groups/groups.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/head/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/head/.gitignore
--------------------------------------------------------------------------------
/head/head.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/hostid/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/hostid/.gitignore
--------------------------------------------------------------------------------
/hostid/hostid.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/id/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/id/.gitignore
--------------------------------------------------------------------------------
/id/id.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/install/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/install/.gitignore
--------------------------------------------------------------------------------
/install/install.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/join/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/join/.gitignore
--------------------------------------------------------------------------------
/join/join.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/link/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/link/.gitignore
--------------------------------------------------------------------------------
/link/link.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/ln/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/ln/.gitignore
--------------------------------------------------------------------------------
/ln/ln.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/logname/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/logname/.gitignore
--------------------------------------------------------------------------------
/logname/logname.go:
--------------------------------------------------------------------------------
1 | /*
2 | Go logname -- print user's login name
3 |
4 | Copyright (C) 2015 Eric Lagergren
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | /* Written by Eric Lagergren */
21 |
22 | package main
23 |
24 | import (
25 | "fmt"
26 | "log"
27 | "os"
28 |
29 | "github.com/EricLagergren/go-gnulib/login"
30 |
31 | flag "github.com/ogier/pflag"
32 | )
33 |
34 | const (
35 | HELP = `Usage: logname [OPTION]...
36 | Print the name of the current user.
37 |
38 | --help display this help and exit
39 | --version output version information and exit
40 |
41 | Report logname bugs to ericscottlagergren@gmail.com
42 | Go coreutils home page:
43 | `
44 |
45 | VERSION = `logname (Go coreutils) 1.0
46 | Copyright (C) 2015 Eric Lagergren
47 | License GPLv3+: GNU GPL version 3 or later .
48 | This is free software: you are free to change and redistribute it.
49 | There is NO WARRANTY, to the extent permitted by law.
50 |
51 | Written by Eric Lagergren
52 | `
53 | )
54 |
55 | var (
56 | version = flag.BoolP("version", "v", false, "print program version")
57 |
58 | fatal = log.New(os.Stderr, "", 0)
59 | //fatal = log.New(os.Stderr, "", log.Lshortfile)
60 | )
61 |
62 | func main() {
63 | flag.Usage = func() {
64 | fmt.Fprintf(os.Stderr, "%s", HELP)
65 | os.Exit(0)
66 | }
67 | flag.Parse()
68 |
69 | if *version {
70 | fmt.Fprintf(os.Stderr, "%s", VERSION)
71 | os.Exit(0)
72 | }
73 |
74 | name, err := login.GetLogin()
75 | if err != nil {
76 | // POSIX prohibits using a fallback
77 | fatal.Fatalln("no login name")
78 | }
79 |
80 | fmt.Println(name)
81 | }
82 |
--------------------------------------------------------------------------------
/ls/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/ls/.gitignore
--------------------------------------------------------------------------------
/ls/ls.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/md5sum/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/md5sum/.gitignore
--------------------------------------------------------------------------------
/md5sum/checksum_common/calc_sum.go:
--------------------------------------------------------------------------------
1 | /*
2 | go checksum common
3 |
4 | Copyright (c) 2014-2015 Dingjun Fang
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License version 3 as
8 | published by the Free Software Foundation.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | package checksum_common
20 |
21 | import (
22 | "crypto/md5"
23 | "crypto/sha1"
24 | "crypto/sha256"
25 | "crypto/sha512"
26 | "fmt"
27 | //flag "github.com/ogier/pflag"
28 | "hash"
29 | "io"
30 | "os"
31 | "path/filepath"
32 | )
33 |
34 | /*
35 | read from os.File and return the whole file's checksum
36 | */
37 | func calc_checksum(fp io.Reader, t string) string {
38 | var m hash.Hash
39 | switch t {
40 | case "md5":
41 | m = md5.New()
42 | case "sha1":
43 | m = sha1.New()
44 | case "sha512":
45 | m = sha512.New()
46 | case "sha256":
47 | m = sha256.New()
48 | case "sha224":
49 | m = sha256.New224()
50 | case "sha384":
51 | m = sha512.New384()
52 | default:
53 | output_e("unknown type: %s\n", t)
54 | return ""
55 | }
56 |
57 | /* issue:
58 | if fp is os.Stdin, there is no way to trigger EOF
59 | */
60 | _, err := io.Copy(m, fp)
61 |
62 | if err != nil {
63 | output_e("%ssum: %s\n", t, err.Error())
64 | return ""
65 | }
66 |
67 | return fmt.Sprintf("%x", m.Sum(nil))
68 | }
69 |
70 | /*
71 | generate the checksum for all of files from cmdline
72 | */
73 | func gen_checksum(files []string, t string) bool {
74 |
75 | has_error := false
76 |
77 | for i := 0; i < len(files); i++ {
78 | fn := files[i]
79 |
80 | /* stdin */
81 | if fn == "-" {
82 | sum := calc_checksum(os.Stdin, t)
83 | if sum != "" {
84 | fmt.Fprintf(os.Stdout, "%s *%s\n", sum, fn)
85 | } else {
86 | has_error = true
87 | }
88 | continue
89 | }
90 |
91 | /* file */
92 |
93 | /* extends file lists when filename contains '*' */
94 | filenames, _ := filepath.Glob(fn)
95 | if filenames == nil {
96 | filenames = append(filenames, fn)
97 | }
98 |
99 | for _, f := range filenames {
100 | file, err := os.Open(f)
101 | if err != nil {
102 | has_error = true
103 | fmt.Fprintf(os.Stderr, "%ssum: %s\n", t, err.Error())
104 | continue
105 | }
106 | sum := calc_checksum(file, t)
107 | file.Close()
108 | if sum != "" {
109 | fmt.Fprintf(os.Stdout, "%s *%s\n", sum, f)
110 | } else {
111 | has_error = true
112 | }
113 | }
114 | }
115 |
116 | return !has_error
117 | }
118 |
119 | /*
120 | generate the checksum for given file list.
121 |
122 | files: the file name lists to generate checksum
123 |
124 | t: the type of checksum, md5 or sha1...
125 |
126 | return false if there are some errors.
127 |
128 | return true if there is no error.
129 | */
130 | func GenerateChecksum(files []string, t string) bool {
131 | return gen_checksum(files, t)
132 | }
133 |
--------------------------------------------------------------------------------
/md5sum/checksum_common/check_sum.go:
--------------------------------------------------------------------------------
1 | /*
2 | go checksum common
3 |
4 | Copyright (c) 2014-2015 Dingjun Fang
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License version 3 as
8 | published by the Free Software Foundation.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | /*
20 | the core checksum implements of md5, sha1, sha224, sha256, sha384, sha512.
21 | */
22 | package checksum_common
23 |
24 | import (
25 | "bufio"
26 | //flag "github.com/ogier/pflag"
27 | "io"
28 | "os"
29 | "path/filepath"
30 | "strings"
31 | )
32 |
33 | /*
34 | check the checksum for all of files
35 | */
36 | func check_checksum(files []string, t string) bool {
37 |
38 | has_err := false
39 |
40 | for i := 0; i < len(files); i++ {
41 |
42 | /* stdin */
43 | if files[i] == "-" {
44 | if b := check_checksum_f(os.Stdin, t); !b {
45 | has_err = true
46 | }
47 | continue
48 | }
49 |
50 | /* file */
51 | file, err := os.Open(files[i])
52 | if err != nil {
53 | output_e("%ssum: %s\n", t, err.Error())
54 | has_err = true
55 | continue
56 | }
57 | if b := check_checksum_f(file, t); !b {
58 | has_err = true
59 | }
60 | file.Close()
61 | }
62 |
63 | return !has_err
64 | }
65 |
66 | /*
67 | process single checksum list file
68 | */
69 | func check_checksum_f(fp io.Reader, t string) bool {
70 | has_err := false
71 | reader := bufio.NewReader(fp)
72 |
73 | /* total file */
74 | total := 0
75 |
76 | /* failed number */
77 | failed := 0
78 |
79 | /* error number */
80 | errored := 0
81 |
82 | /* line number */
83 | line_num := 0
84 |
85 | for {
86 | line_num += 1
87 | l, _, err := reader.ReadLine()
88 | if err != nil {
89 | if err != io.EOF {
90 | has_err = true
91 | output_e("%ssum: %s\n", t, err.Error())
92 | }
93 | break
94 | }
95 |
96 | ll := strings.TrimSpace(string(l))
97 |
98 | if ll == "" {
99 | continue
100 | }
101 |
102 | /* strip the '\' at beginning */
103 | if ll[0] == '\\' {
104 | ll = ll[1:]
105 | }
106 |
107 | fields := strings.Fields(ll)
108 |
109 | if len(fields) != 2 {
110 | if show_warn {
111 | output_e("%ssum: line: %d: improperly formatted %s checksum line\n",
112 | t, line_num, strings.ToUpper(t))
113 | }
114 | continue
115 | }
116 |
117 | sum, fn := fields[0], fields[1]
118 |
119 | /* strip the '*' from filename */
120 | if fn[0] == '*' {
121 | fn = fn[1:]
122 | }
123 |
124 | fn = filepath.Clean(fn)
125 |
126 | file, err := os.Open(fn)
127 | if err != nil {
128 | output_e("%ssum: %s\n", t, err.Error())
129 | has_err = true
130 | errored += 1
131 | continue
132 | }
133 |
134 | sum1 := calc_checksum(file, t)
135 | file.Close()
136 |
137 | total += 1
138 |
139 | if sum1 != "" {
140 | if sum1 != sum { // failed
141 | failed += 1
142 | output_e("%s: FAILED\n", fn)
143 | has_err = true
144 | } else { // success
145 | output_n("%s: OK\n", fn)
146 | }
147 | } else { // error
148 | errored += 1
149 | has_err = true
150 | }
151 | }
152 |
153 | if failed > 0 && show_warn {
154 | output_e("%ssum: WARNING: %d of %d computed checksums did NOT match\n",
155 | t, failed, total)
156 | }
157 |
158 | if errored > 0 && show_warn {
159 | output_e("%ssum: WARNING: %d of %d listed files could not be read\n",
160 | t, errored, total)
161 | }
162 |
163 | return !has_err
164 | }
165 |
166 | /*
167 | read the file contains the checksum and check it
168 |
169 | files: file name lists which contains the checksums.
170 |
171 | t: the type of checksum, md5 or sha1...
172 |
173 | return true if everything is ok
174 |
175 | return false if there are some errors.
176 | */
177 | func CompareChecksum(files []string, t string, output_message, output_warn bool) bool {
178 | no_output = !output_message
179 | show_warn = output_warn
180 | return check_checksum(files, t)
181 | }
182 |
--------------------------------------------------------------------------------
/md5sum/checksum_common/checksum_test.go:
--------------------------------------------------------------------------------
1 | package checksum_common
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "io"
7 | "os"
8 | "testing"
9 | )
10 |
11 | func TestCalc_checksum(t *testing.T) {
12 | cases := []struct {
13 | in, want, t string
14 | }{
15 | /* md5 */
16 | {"hello, world", "e4d7f1b4ed2e42d15898f4b27b019da4", "md5"},
17 | {"ad3344412123123fasdfasdf", "353a3336352ae74136ef5b37e4091c4c", "md5"},
18 | {"333dddf213sfasdfasdfasfd\n", "106f56f032f7d29af6af98eeb24d5d2c", "md5"},
19 |
20 | /* sha1 */
21 | {"hello, world", "b7e23ec29af22b0b4e41da31e868d57226121c84", "sha1"},
22 | {"ad3344412123123fasdfasdf", "76758123ef52b09899546142393c32db7f53a022", "sha1"},
23 | {"333dddf213sfasdfasdfasfd\n", "0d966748d89029d547f3e36e63af9839f3b9ce6b", "sha1"},
24 |
25 | /* sha224 */
26 | {"hello, world", "6e1a93e32fb44081a401f3db3ef2e6e108b7bbeeb5705afdaf01fb27", "sha224"},
27 | {"ad3344412123123fasdfasdf", "372b81303da6fd1418041af497d53b9434891b9c93954e929d4ee7a3", "sha224"},
28 | {"333dddf213sfasdfasdfasfd\n", "cc92bf4cc34f856bfedc056f943afc68121f74620ca158f42920765f", "sha224"},
29 |
30 | /* sh256 */
31 | {"hello, world", "09ca7e4eaa6e8ae9c7d261167129184883644d07dfba7cbfbc4c8a2e08360d5b", "sha256"},
32 | {"ad3344412123123fasdfasdf", "a1962c3391c5580497624394b3b156637ec0e33d6705938c505b4a20e7e73fce", "sha256"},
33 | {"333dddf213sfasdfasdfasfd\n", "19bacc61eb1896d9865d77f62c19a325b704a7a23ef43e2cb46d9b406c01ab28", "sha256"},
34 |
35 | /* sha384 */
36 | {"hello, world", "1fcdb6059ce05172a26bbe2a3ccc88ed5a8cd5fc53edfd9053304d429296a6da23b1cd9e5c9ed3bb34f00418a70cdb7e", "sha384"},
37 | {"ad3344412123123fasdfasdf", "494dd728eeccfa6cc27815538ab432c4dbb19d0f7157654fb3fc945fd2f6535535d4af8dbefbefbd51d608b4423c9508", "sha384"},
38 | {"333dddf213sfasdfasdfasfd\n", "8823b5ac0abaa00b665525e74072f233a6a8f0291cf6974d04ab548acbb11e860f13b156a787987cd9cd799306d4b138", "sha384"},
39 |
40 | /* sha512 */
41 | {"hello, world", "8710339dcb6814d0d9d2290ef422285c9322b7163951f9a0ca8f883d3305286f44139aa374848e4174f5aada663027e4548637b6d19894aec4fb6c46a139fbf9", "sha512"},
42 | {"ad3344412123123fasdfasdf", "e08719391e0e3592db97bf24084ea5230f645da3cb5747aa10e504feafc53426348a61ea9b392be255ac89c28a2ed9092d433b377292827a65a897a2a7687a07", "sha512"},
43 | {"333dddf213sfasdfasdfasfd\n", "c7fb59d56d18f86c6838a3a504dcc939e11eec832338f5ef998f222f7cd66527536499dcfac5b8649381adf7665e0557e3574febca7d605a0798b8f737d05f54", "sha512"},
44 | }
45 |
46 | for _, v := range cases {
47 | buf := bytes.NewBufferString(v.in)
48 | sum := calc_checksum(buf, v.t)
49 | if sum != v.want {
50 | t.Errorf("%ssum (%#v) == %#v, want %#v", v.t, v.in, sum, v.want)
51 | } else {
52 | t.Logf("%ssum (%#v), expect %#v, got %#v\n", v.t, v.in, v.want, sum)
53 | }
54 | }
55 | }
56 |
57 | func TestCheck_checksum(t *testing.T) {
58 |
59 | old_stdout := os.Stdout
60 |
61 | /* capture output */
62 | r, w, _ := os.Pipe()
63 | os.Stdout = w
64 |
65 | outC := make(chan string)
66 |
67 | defer func() {
68 | w.Close()
69 | os.Stdout = old_stdout
70 | output := <-outC
71 | t.Logf("%s\n", output)
72 | }()
73 |
74 | go func() {
75 | var buf bytes.Buffer
76 | io.Copy(&buf, r)
77 | outC <- buf.String()
78 | }()
79 |
80 | sum_methods := []string{"md5", "sha1", "sha224", "sha256", "sha384", "sha512"}
81 | for _, m := range sum_methods {
82 | fn := fmt.Sprintf("testdata/checksum.%s", m)
83 | sum_f_lists := []string{fn}
84 | if r := CompareChecksum(sum_f_lists, m, true, true); !r {
85 | t.Fail()
86 | } else {
87 | t.Logf("check %s for %s: success\n", fn, m)
88 | }
89 | }
90 | }
91 |
92 | func TestGenChecksum(t *testing.T) {
93 |
94 | old_stdout := os.Stdout
95 |
96 | /* capture output */
97 | r, w, _ := os.Pipe()
98 | os.Stdout = w
99 |
100 | outC := make(chan string)
101 |
102 | defer func() {
103 | w.Close()
104 | os.Stdout = old_stdout
105 | output := <-outC
106 | t.Logf("\n%s\n", output)
107 | }()
108 |
109 | go func() {
110 | var buf bytes.Buffer
111 | io.Copy(&buf, r)
112 | outC <- buf.String()
113 | }()
114 |
115 | sum_methods := []string{"md5", "sha1", "sha224", "sha256", "sha384", "sha512"}
116 | for _, m := range sum_methods {
117 | flists := []string{"testdata/*.txt"}
118 | if r := GenerateChecksum(flists, m); !r {
119 | t.Fail()
120 | } else {
121 | t.Logf("generate %sum: success\n", m)
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/md5sum/checksum_common/output.go:
--------------------------------------------------------------------------------
1 | /*
2 | go checksum common
3 |
4 | Copyright (c) 2014-2015 Dingjun Fang
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License version 3 as
8 | published by the Free Software Foundation.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | package checksum_common
20 |
21 | import (
22 | "fmt"
23 | "os"
24 | )
25 |
26 | var no_output bool = false
27 | var show_warn bool = true
28 |
29 | /*
30 | output to stdout
31 | */
32 | func output_n(s string, s1 ...interface{}) {
33 | if no_output != true {
34 | fmt.Fprintf(os.Stdout, s, s1...)
35 | }
36 | }
37 |
38 | /*
39 | output to stderr
40 | */
41 | func output_e(s string, s1 ...interface{}) {
42 | if no_output != true {
43 | fmt.Fprintf(os.Stderr, s, s1...)
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/md5sum/checksum_common/testdata/aad33efasdf.txt:
--------------------------------------------------------------------------------
1 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
2 | ffffffffffffffffffffffffffffffffffffffffffffffffffffff
3 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
4 | ddddddddddddddddddddddddd
5 | f3444444444444444444444444444444444444444444444444
6 | 5555555555555555555555555555555555
7 | 3333333333333333333333
8 | 3333333333333333333333
--------------------------------------------------------------------------------
/md5sum/checksum_common/testdata/checksum.md5:
--------------------------------------------------------------------------------
1 | 87baa79eee939e85645b0985683f2d17 *testdata/aad33efasdf.txt
2 | 05d52ce6dc54a594790686d383b4f766 *testdata/d333dasdf3.txt
3 | 6e83af947fa5d0ff4838d91fdc1c5819 *testdata/rgsdfsdfewerwf.txt
4 |
--------------------------------------------------------------------------------
/md5sum/checksum_common/testdata/checksum.sha1:
--------------------------------------------------------------------------------
1 | 10aa2454094c9b4c6f92dfbfe643a6176cf1f534 *testdata/aad33efasdf.txt
2 | bb4671ffb2e316634ee5ed38ca2d5c8afea48425 *testdata/d333dasdf3.txt
3 | eaf81c56f2d7ebb66064e38e4237e2158001c6a4 *testdata/rgsdfsdfewerwf.txt
4 |
--------------------------------------------------------------------------------
/md5sum/checksum_common/testdata/checksum.sha224:
--------------------------------------------------------------------------------
1 | 3f6f5dafef1c3b250ef71b3f3e133738a4cb4b8f54bf860396a48bcc *testdata/aad33efasdf.txt
2 | ccbcc955e155fd479a06aa91c713b9868105afa34a4eec5ef1eae49d *testdata/d333dasdf3.txt
3 | f001b48669e9ef021d7ae54969bf1a4b4ddae49f701a6bb5ccc3a210 *testdata/rgsdfsdfewerwf.txt
4 |
--------------------------------------------------------------------------------
/md5sum/checksum_common/testdata/checksum.sha256:
--------------------------------------------------------------------------------
1 | c45212cc8468c69ec29c8283810182005109db11d5795f3cf7576321072223c5 *testdata/aad33efasdf.txt
2 | c03431fd8606f6afbc3d780e62847e723c918a5292ae96b5f9fbc3ae96f792c6 *testdata/d333dasdf3.txt
3 | cc64281c6e6e4c0a0c57ef2b3a38299c47114ca014334e09a76281fd82a8845d *testdata/rgsdfsdfewerwf.txt
4 |
--------------------------------------------------------------------------------
/md5sum/checksum_common/testdata/checksum.sha384:
--------------------------------------------------------------------------------
1 | f3cfa1ea2a5b98630b141448ad420e7e49ec01113ec67bf9ea2d945dda8090b109ec16c90eb064ce7efd754778571ce8 *testdata/aad33efasdf.txt
2 | 23652f1dacba1e2fe3ff79b3df02e3f5d53af71a5e5c7a91f5d4873975161955dc8eda34818a57d719b29b8844f4e8f4 *testdata/d333dasdf3.txt
3 | 1146cc8e078a65c3c96c6551d78b68224a4cd25352dc8215294b8b7a390b8d5b5b46174ca44ea800fbff10aede5781cf *testdata/rgsdfsdfewerwf.txt
4 |
--------------------------------------------------------------------------------
/md5sum/checksum_common/testdata/checksum.sha512:
--------------------------------------------------------------------------------
1 | 1987cb5f81681165781df2e8a74417e7c78d63aebfd9fb959970d8455aad151af5683a049bcb54732a3143f5c6ce34d5d092de7d6b07ad0a661d955e0c7cebb4 *testdata/aad33efasdf.txt
2 | ad85f6622035b001fdce7cee100e2ae5aefb26dd4d86291355cd2403e872f7ca37771ea41304eb10e4ab8cb38f0b0fe39e5cbe8b816da40f73e010462008564f *testdata/d333dasdf3.txt
3 | 9d469a012e241672e2f7bcdf3a64d6d782e554fa2daf1e9a3b875d4c42243b824ed6e7b25d4b271ef6e34a5cb33ebb14b9dccfb2fb1379ba77cc873dcda91c20 *testdata/rgsdfsdfewerwf.txt
4 |
--------------------------------------------------------------------------------
/md5sum/checksum_common/testdata/d333dasdf3.txt:
--------------------------------------------------------------------------------
1 | aaaaaaaaaaaaaaaaaaaaaaaaaaa
2 | ffffffffffffffffffffffff
3 | aaaaaaaaaaaaaaaaaaa
4 | ffffffffffffffffffffff
5 | ffffffffffffffffff
6 | aaaaaaaaa
7 | ;;;;;;;;;;;;;;;;;;;........3333333333333333fg
8 | asddddddddddddddddddd
--------------------------------------------------------------------------------
/md5sum/checksum_common/testdata/rgsdfsdfewerwf.txt:
--------------------------------------------------------------------------------
1 | teasdf
2 | asdfffffffffffffffffffffffffffffffffffffffff
3 | asfda
4 | sdfa
5 | sdfa
6 | asdf
7 | asfaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
8 | das
9 | dfasfd
10 |
--------------------------------------------------------------------------------
/md5sum/md5sum.go:
--------------------------------------------------------------------------------
1 | /*
2 | go md5sum
3 |
4 | Copyright (c) 2014-2015 Dingjun Fang
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License version 3 as
8 | published by the Free Software Foundation.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | /*
20 |
21 | Md5sum util implement by go.
22 |
23 | Usage: md5sum [OPTION]... [FILE]...
24 |
25 | Print or check MD5 (128-bit) checksums.
26 |
27 | With no FILE, or when FILE is -, read standard input.
28 |
29 | -b, --binary read in binary mode(default)
30 | -c, --check read MD5 sums from the FILEs and check them
31 | -t, --text read in text mode
32 | Note: there is no difference between text and binary mode option.
33 |
34 | The following three options are useful only when verifying checksums:
35 | --quiet don't print OK for each successfully verified file
36 | --status don't output anything, status code shows success
37 | -w, --warn warn about improperly formated checksum lines
38 |
39 | --help show help and exit
40 | --version show version and exit
41 |
42 | The sums are computed as described in RFC 1321. When checking, the input
43 | should be a former output of this program. The default mode is to print
44 | a line with checksum, a character indicating type ('*' for binary, ' ' for
45 | text), and name for each FILE.
46 | */
47 | package main
48 |
49 | import (
50 | "fmt"
51 | cc "github.com/fangdingjun/go-coreutils/md5sum/checksum_common"
52 | flag "github.com/ogier/pflag"
53 | "os"
54 | )
55 |
56 | const (
57 | Help = `Usage: md5sum [OPTION]... [FILE]...
58 | Print or check MD5 (128-bit) checksums.
59 | With no FILE, or when FILE is -, read standard input.
60 |
61 | -b, --binary read in binary mode(default)
62 | -c, --check read MD5 sums from the FILEs and check them
63 | -t, --text read in text mode
64 | Note: there is no difference between text and binary mode option.
65 |
66 | The following three options are useful only when verifying checksums:
67 | --quiet don't print OK for each successfully verified file
68 | --status don't output anything, status code shows success
69 | -w, --warn warn about improperly formated checksum lines
70 |
71 | --help show help and exit
72 | --version show version and exit
73 |
74 | The sums are computed as described in RFC 1321. When checking, the input
75 | should be a former output of this program. The default mode is to print
76 | a line with checksum, a character indicating type ('*' for binary, ' ' for
77 | text), and name for each FILE.
78 | `
79 | Version = `md5sum (Go coreutils) 0.1
80 | Copyright (C) 2015 Dingjun Fang
81 | License GPLv3+: GNU GPL version 3 or later .
82 | This is free software: you are free to change and redistribute it.
83 | There is NO WARRANTY, to the extent permitted by law.
84 | `
85 | )
86 |
87 | var (
88 | check_sum = flag.BoolP("check", "c", false, "")
89 | no_output = flag.BoolP("quiet", "q", false, "")
90 | no_output_s = flag.BoolP("status", "", false, "")
91 | show_warn = flag.BoolP("warn", "w", true, "")
92 | show_version = flag.BoolP("version", "v", false, "")
93 | text_mode = flag.BoolP("text", "t", false, "")
94 | binary_mode = flag.BoolP("binary", "b", false, "")
95 | )
96 |
97 | func main() {
98 | flag.Usage = func() {
99 | fmt.Fprintf(os.Stderr, "%s", Help)
100 | os.Exit(1)
101 | }
102 |
103 | flag.Parse()
104 |
105 | /* trust --status and --quiet as the same */
106 | if *no_output_s == true {
107 | *no_output = true
108 | }
109 |
110 | has_error := false
111 |
112 | file_lists := flag.Args()
113 | if len(file_lists) == 0 {
114 | file_lists = append(file_lists, "-")
115 | }
116 |
117 | switch {
118 | case *show_version:
119 | fmt.Fprintf(os.Stdout, "%s", Version)
120 | os.Exit(0)
121 | case *check_sum:
122 | if r := cc.CompareChecksum(file_lists, "md5",
123 | !(*no_output), *show_warn); !r {
124 | has_error = true
125 | }
126 | default:
127 | if r := cc.GenerateChecksum(file_lists, "md5"); !r {
128 | has_error = true
129 | }
130 | }
131 |
132 | if has_error {
133 | os.Exit(1)
134 | }
135 |
136 | os.Exit(0)
137 | }
138 |
--------------------------------------------------------------------------------
/mkdir/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/mkdir/.gitignore
--------------------------------------------------------------------------------
/mkdir/mkdir.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/mkfifo/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/mkfifo/.gitignore
--------------------------------------------------------------------------------
/mkfifo/mkfifo.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/mknod/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/mknod/.gitignore
--------------------------------------------------------------------------------
/mknod/mknod.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/mktemp/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/mktemp/.gitignore
--------------------------------------------------------------------------------
/mktemp/mktemp.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/mv/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/mv/.gitignore
--------------------------------------------------------------------------------
/mv/mv.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/nice/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/nice/.gitignore
--------------------------------------------------------------------------------
/nice/nice.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/nl/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/nl/.gitignore
--------------------------------------------------------------------------------
/nl/nl.go:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License version 3 as
4 | published by the Free Software Foundation.
5 |
6 | This program is distributed in the hope that it will be useful,
7 | but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 | GNU General Public License for more details.
10 |
11 | You should have received a copy of the GNU General Public License
12 | along with this program. If not, see .
13 | */
14 |
15 | package main
16 |
17 | import "os"
18 | import "fmt"
19 | import "io/ioutil"
20 | import "strings"
21 | import flag "github.com/ogier/pflag"
22 |
23 | func main() {
24 | bFlag := flag.StringP("body-numbering", "b", "t", "style")
25 | flag.Parse()
26 | if len(flag.Args()) == 0 {
27 | bytes, _ := ioutil.ReadAll(os.Stdin)
28 | lines := strings.Split(string(bytes), "\n")
29 | linecount := 0
30 | for i := 0; i < len(lines)-1; i++ {
31 | if *bFlag == "t" {
32 | if len(strings.TrimSpace(lines[i])) > 0 {
33 | linecount++
34 | fmt.Printf("%6d %s\n", linecount, lines[i])
35 | } else {
36 | fmt.Println(lines[i])
37 | }
38 | } else {
39 | linecount++
40 | fmt.Printf("%6d %s\n", linecount, lines[i])
41 | }
42 | }
43 | } else if len(flag.Args()) > 0 {
44 | linecount := 0
45 | for j := 0; j < len(flag.Args()); j++ {
46 | bytes, _ := ioutil.ReadFile(flag.Arg(j))
47 | lines := strings.Split(string(bytes), "\n")
48 | for i := 0; i < len(lines)-1; i++ {
49 | if *bFlag == "t" {
50 | if len(strings.TrimSpace(lines[i])) > 0 {
51 | linecount++
52 | fmt.Printf("%6d %s\n", linecount, lines[i])
53 | } else {
54 | fmt.Println(lines[i])
55 | }
56 | } else {
57 | linecount++
58 | fmt.Printf("%6d %s\n", linecount, lines[i])
59 | }
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/nohup/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/nohup/.gitignore
--------------------------------------------------------------------------------
/nohup/nohup.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/nproc/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/nproc/.gitignore
--------------------------------------------------------------------------------
/nproc/nproc.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/numfmt/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/numfmt/.gitignore
--------------------------------------------------------------------------------
/numfmt/numfmt.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/od/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/od/.gitignore
--------------------------------------------------------------------------------
/od/od.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/paste/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/paste/.gitignore
--------------------------------------------------------------------------------
/paste/paste.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/pathchk/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/pathchk/.gitignore
--------------------------------------------------------------------------------
/pathchk/pathchk.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/pinky/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/pinky/.gitignore
--------------------------------------------------------------------------------
/pinky/pinky.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/pr/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/pr/.gitignore
--------------------------------------------------------------------------------
/pr/pr.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/printenv/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/printenv/.gitignore
--------------------------------------------------------------------------------
/printenv/printenv.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/printf/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/printf/.gitignore
--------------------------------------------------------------------------------
/printf/printf.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/ptx/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/ptx/.gitignore
--------------------------------------------------------------------------------
/ptx/ptx.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/pwd/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/pwd/.gitignore
--------------------------------------------------------------------------------
/readlink/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/readlink/.gitignore
--------------------------------------------------------------------------------
/readlink/readlink.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/realpath/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/realpath/.gitignore
--------------------------------------------------------------------------------
/realpath/realpath.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/rm/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/rm/.gitignore
--------------------------------------------------------------------------------
/rm/cmd.go:
--------------------------------------------------------------------------------
1 | package rm
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | "io"
7 |
8 | coreutils "github.com/ericlagergren/go-coreutils"
9 | flag "github.com/spf13/pflag"
10 | )
11 |
12 | func init() {
13 | coreutils.Register("rm", run)
14 | }
15 |
16 | // Sentinal flags for default values or flags with single-character options and
17 | // without multi-character options. (e.g., if we want -i but not --i.)
18 | const (
19 | uniNonChar = 0xFDD0
20 | interDefault = string(uniNonChar + 1)
21 | bad1 = string(uniNonChar + 2)
22 | bad2 = string(uniNonChar + 3)
23 | bad3 = string(uniNonChar + 4)
24 | )
25 |
26 | func newCommand() *cmd {
27 | var c cmd
28 | c.f.BoolVarP(&c.force, "force", "f", false, "ignore non-existent files and arguments; never prompt prior to removal")
29 | c.f.BoolVarP(&c.moreInter, bad1, "i", false, "prompt before each removal")
30 | c.f.BoolVarP(&c.lessInter, bad2, "I", false, "prompt (once) prior to removing more than three files or when removing recursively")
31 | c.f.StringVar(&c.interactive, "interactive", interDefault, "prompt: 'never', 'once' (-i), 'always' (-I)")
32 | c.f.BoolVar(&c.oneFileSystem, "one-file-system", false, "when recursing, skip directories that are on a different filesystem")
33 | c.f.BoolVar(&c.preserveRoot, "preserve-root", true, "do not remove '/'")
34 | c.f.BoolVar(&c.noPreserveRoot, "no-preserve-root", false, "do not special-case '/'")
35 | c.f.BoolVarP(&c.recursive, "recursive", "r", false, "remove directories and their contents recursively")
36 | c.f.BoolVarP(&c.recursive, bad3, "R", false, "remove directories and their contents recursively")
37 | c.f.BoolVarP(&c.rmdir, "dir", "d", false, "remove empty directories")
38 | c.f.BoolVarP(&c.verbose, "verbose", "v", false, "explain what's occurring")
39 | c.f.BoolVar(&c.version, "version", false, "print version information and exit")
40 | return &c
41 | }
42 |
43 | type cmd struct {
44 | f flag.FlagSet
45 | force bool
46 | moreInter, lessInter bool
47 | interactive string
48 | preserveRoot bool
49 | noPreserveRoot bool
50 | oneFileSystem bool
51 | recursive bool
52 | rmdir bool
53 | verbose bool
54 | version bool
55 | }
56 |
57 | func run(ctx coreutils.Context, args ...string) error {
58 | c := newCommand()
59 | if err := c.f.Parse(args); err != nil {
60 | return err
61 | }
62 |
63 | if c.version {
64 | fmt.Fprintf(ctx.Stdout, "rm (go-coreutils) 1.0")
65 | return nil
66 | }
67 |
68 | var opts RemoveOption
69 | if c.noPreserveRoot && !c.preserveRoot {
70 | opts |= NoPreserveRoot
71 | }
72 | if c.force {
73 | opts |= Force
74 | }
75 | if c.recursive {
76 | opts |= Recursive
77 | }
78 | if c.rmdir {
79 | opts |= RemoveEmpty
80 | }
81 | if c.oneFileSystem {
82 | opts |= OneFileSystem
83 | }
84 | if c.verbose {
85 | opts |= Verbose
86 | }
87 | switch c.interactive {
88 | case interDefault:
89 | if c.moreInter {
90 | opts |= PromptAlways
91 | c.lessInter = false
92 | }
93 | case "never", "no", "none":
94 | opts &= PromptAlways
95 | case "once":
96 | c.lessInter = true
97 | opts &= IgnoreMissing
98 | case "always", "yes", "":
99 | opts |= PromptAlways
100 | opts &= IgnoreMissing
101 | default:
102 | return errors.New("unknown interactive option: " + c.interactive)
103 | }
104 |
105 | if c.lessInter && (opts&Recursive != 0 || c.f.NArg() >= 3) {
106 | n := c.f.NArg()
107 | arg := "arguments"
108 | adj := ""
109 | if opts&Recursive != 0 {
110 | adj = " recursively "
111 | if n == 1 {
112 | arg = "argument"
113 | }
114 | }
115 | fmt.Fprintf(ctx.Stderr, "rm: remove %d %s%s? ", n, arg, adj)
116 | switch yes, err := getYesNo(ctx.Stdin); {
117 | case err != nil:
118 | return err
119 | case !yes:
120 | return nil
121 | }
122 | }
123 |
124 | r := NewRemover(opts)
125 |
126 | if r.opts&PromptAlways != 0 {
127 | r.Prompt = func(name string, opts PromptOption) bool {
128 |
129 | wp := " "
130 | if opts&WriteProtected != 0 {
131 | wp = " write-protected "
132 | }
133 |
134 | msg := "rm: remove%s%s %q? "
135 | typ := "file"
136 | if opts&(Descend|Directory) != 0 {
137 | typ = "directory"
138 | if opts&Descend != 0 {
139 | msg = "rm: descend into%s%s %q? "
140 | }
141 | }
142 |
143 | fmt.Fprintf(ctx.Stderr, msg, wp, typ, name)
144 | yes, err := getYesNo(ctx.Stdin)
145 | return yes && err == nil
146 | }
147 | }
148 |
149 | if r.Log != nil {
150 | defer close(r.Log)
151 | go func() {
152 | for msg := range r.Log {
153 | fmt.Fprintln(ctx.Stdout, msg)
154 | }
155 | }()
156 | }
157 |
158 | var nerrs int
159 | for _, name := range c.f.Args() {
160 | switch err := r.Remove(name); err.(type) {
161 | case nil:
162 | // OK
163 | case rmError:
164 | fmt.Fprintf(ctx.Stderr, "rm: %v\n", err)
165 | default:
166 | fmt.Fprintf(ctx.Stderr, "rm: %v\n", err)
167 | return err
168 | }
169 | }
170 | if nerrs > 0 {
171 | return errNonFatal
172 | }
173 | return nil
174 | }
175 |
176 | var errNonFatal = errors.New("at least one non-fatal error occurred")
177 |
178 | func getYesNo(r io.Reader) (yes bool, err error) {
179 | var resp string
180 | fmt.Fscanln(r, &resp)
181 | switch resp {
182 | case "yes", "Y", "y":
183 | return true, nil
184 | case "no", "N", "n":
185 | return false, nil
186 | default:
187 | return false, errors.New("unknown response (must be 'yes' or 'no')")
188 | }
189 | }
190 |
--------------------------------------------------------------------------------
/rm/internal/sys/sys_unix.go:
--------------------------------------------------------------------------------
1 | // +build !windows
2 |
3 | package sys
4 |
5 | import (
6 | "os"
7 | "syscall"
8 | )
9 |
10 | var root *syscall.Stat_t
11 |
12 | func init() {
13 | if info, err := os.Lstat("/"); err == nil {
14 | root = info.Sys().(*syscall.Stat_t)
15 | }
16 | }
17 |
18 | func IsRoot(info os.FileInfo) bool {
19 | stat := info.Sys().(*syscall.Stat_t)
20 | return root.Ino == stat.Ino && root.Dev == stat.Dev
21 | }
22 |
23 | func DiffFS(orig, test os.FileInfo) bool {
24 | return orig.Sys().(*syscall.Stat_t).Dev != test.Sys().(*syscall.Stat_t).Dev
25 | }
26 |
--------------------------------------------------------------------------------
/rm/internal/sys/sys_windows.go:
--------------------------------------------------------------------------------
1 | // +build windows
2 |
3 | package sys
4 |
5 | import "os"
6 |
7 | func IsRoot(_ os.FileInfo) bool { return false }
8 | func DiffFS(_, _ os.FileInfo) bool { return false }
9 |
--------------------------------------------------------------------------------
/rm/rm.go:
--------------------------------------------------------------------------------
1 | package rm
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | "os"
7 | "path/filepath"
8 | "runtime"
9 |
10 | "github.com/ericlagergren/go-coreutils/rm/internal/sys"
11 | "golang.org/x/sys/unix"
12 | )
13 |
14 | type RemoveOption uint8
15 |
16 | const (
17 | NoPreserveRoot = 1 << iota
18 | Force
19 | Recursive
20 | RemoveEmpty
21 | IgnoreMissing
22 | OneFileSystem
23 | Verbose
24 | PromptAlways
25 | )
26 |
27 | type PromptOption uint8
28 |
29 | const (
30 | // WriteProtected signals that the object to be removed or descended upon
31 | // has write protection.
32 | WriteProtected PromptOption = 1 << iota
33 | // Directory indicates the action is on a directory.
34 | Directory
35 | // Descend indicates the action is to descend into an object.
36 | Descend
37 | // Remove indicates the action is to remove an object.
38 | Remove
39 | )
40 |
41 | func NewRemover(opts RemoveOption) *Remover {
42 | r := Remover{opts: opts}
43 | if opts&Verbose != 0 {
44 | r.Log = make(chan string)
45 | }
46 | return &r
47 | }
48 |
49 | type Remover struct {
50 | opts RemoveOption
51 | root os.FileInfo
52 |
53 | // Prompt, if non-nil, will be called depending on the Remover's configured
54 | // options. If it returns true, the action continues, otherwise it stops.
55 | Prompt func(name string, opts PromptOption) bool
56 |
57 | Log chan string
58 |
59 | stack []node
60 | }
61 |
62 | type node struct {
63 | path string
64 | info os.FileInfo
65 | kids int
66 | }
67 |
68 | func (r *Remover) Remove(path string) (err error) {
69 | r.root, err = os.Lstat(path)
70 | if err != nil {
71 | return err
72 | }
73 |
74 | if r.opts&Recursive == 0 || !r.root.Mode().IsDir() {
75 | if err := r.remove(path, r.root); err != nil && err != errRefused {
76 | return err
77 | }
78 | return nil
79 | }
80 |
81 | // GNU rm uses a DFS that, once it reaches a leaf node (doesn't contain any
82 | // further directories), clears out all files and "walks back" to the most
83 | // recently seen non-leaf node. This is typicall DFS behavior, but the
84 | // walking back is important: it allows the prompt for interactive usage to
85 | // look like this:
86 | //
87 | // $ mkdir a/b/c
88 | // $ touch a/b/c/d.txt
89 | // $ rm a/
90 | // rm: descend into 'a'?
91 | // rm: descend into 'a/b'?
92 | // rm: descend into 'a/b/c'?
93 | // rm: remove file 'a/b/c/d.txt'?
94 | // rm: remove directory 'a/b/c'?
95 | // rm: remove directory 'a/b'?
96 | // rm: remove directory 'a'?
97 | //
98 | // Unfortunately, filepath.Walk doesn't allow us to walk back, so we're
99 | // forced to do a little state management ourselves. We push each directory
100 | // we encounter onto a stack. Once we hit a leaf node, we manually work our
101 | // way back by popping every consecutive leaf node off the stack, removing
102 | // it as we go. Since filepath.Walk doesn't work backwards, this works.
103 | //
104 | // A major downside is the requirement of determining how many objects are
105 | // in a directory. This means Stat will be called twice for each directory:
106 | // once for filepath.Walk, once for us. Same goes for Readdirnames.
107 | return filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
108 | if err != nil {
109 | return err
110 | }
111 |
112 | if info.IsDir() {
113 | if !r.prompt(path, Descend) {
114 | return filepath.SkipDir
115 | }
116 | dir, err := os.Open(path)
117 | if err != nil {
118 | return err
119 | }
120 | files, err := dir.Readdirnames(-1)
121 | if err != nil {
122 | return err
123 | }
124 | r.stack = append(r.stack, node{path: path, info: info, kids: len(files)})
125 | return dir.Close()
126 | }
127 |
128 | err = r.remove(path, info)
129 |
130 | // Work our way down the r.stack.
131 | for i := len(r.stack) - 1; i >= 0; i-- {
132 | s := &r.stack[i]
133 | s.kids--
134 | if s.kids != 0 {
135 | r.stack = r.stack[:i+1]
136 | break
137 | }
138 | if err := r.remove(s.path, s.info); err != nil && err != errRefused {
139 | return err
140 | }
141 | }
142 |
143 | if err != nil && err != errRefused {
144 | return err
145 | }
146 | return nil
147 | })
148 | }
149 |
150 | var errRefused = errors.New("user refused prompt")
151 |
152 | type rmError struct{ msg string }
153 |
154 | func (r rmError) Error() string { return r.msg }
155 |
156 | func (r *Remover) prompt(name string, opts PromptOption) bool {
157 | if r.opts&PromptAlways != 0 && r.Prompt != nil {
158 | return r.Prompt(name, opts)
159 | }
160 | return true
161 | }
162 |
163 | func (r *Remover) rm(name string, dir bool) (err error) {
164 | opts := Remove
165 | if dir {
166 | opts |= Directory
167 | }
168 | if !r.prompt(name, opts) {
169 | return errRefused
170 | }
171 |
172 | switch runtime.GOOS {
173 | case "windows", "plan9":
174 | err = os.Remove(name)
175 | default:
176 | // For unix systems, os.Remove is a call to Unlink followed by a call to
177 | // Rmdir. Since os.Remove doesn't know whether the object is a file or
178 | // directory, this provides better performance in the common case. But,
179 | // since we know the type of the object ahead of time, we can simply call
180 | // the proper syscall.
181 | if !dir {
182 | err = unix.Unlink(name)
183 | } else {
184 | err = unix.Rmdir(name)
185 | }
186 | if err != nil {
187 | err = &os.PathError{Op: "remove", Path: name, Err: err}
188 | }
189 | }
190 | if err != nil && (r.opts&IgnoreMissing == 0 || !os.IsNotExist(err)) {
191 | return err
192 | }
193 | if r.opts&Verbose != 0 {
194 | if dir {
195 | r.Log <- fmt.Sprintf("removed directory %s")
196 | } else {
197 | r.Log <- fmt.Sprintf("removed %s")
198 | }
199 | }
200 | return nil
201 | }
202 |
203 | func (r *Remover) remove(path string, info os.FileInfo) error {
204 | if info.Mode()&os.ModeDir != 0 {
205 | switch info.Name() {
206 | // POSIX doesn't let us do anything with . or ..
207 | case ".", "..":
208 | return rmError{msg: "cannot remove '.' or '..'"}
209 | case "/":
210 | return rmError{msg: "cannot remove root directory"}
211 | default:
212 | if r.opts&NoPreserveRoot == 0 && sys.IsRoot(info) {
213 | return rmError{msg: "cannot remove root directory"}
214 | }
215 | }
216 | if r.opts&Recursive == 0 && (r.opts&RemoveEmpty == 0 || isEmpty(path)) {
217 | return rmError{msg: fmt.Sprintf("cannot remove directory: %q", path)}
218 | }
219 | return r.rm(path, true)
220 | }
221 | if r.opts&OneFileSystem != 0 && sys.DiffFS(r.root, info) {
222 | return rmError{msg: "cannot recurse into a different filesystem"}
223 | }
224 | return r.rm(path, false)
225 | }
226 |
227 | func isEmpty(path string) bool {
228 | file, err := os.Open(path)
229 | if err != nil {
230 | return false
231 | }
232 | defer file.Close()
233 | names, err := file.Readdirnames(1)
234 | return len(names) != 0 && err == nil
235 | }
236 |
--------------------------------------------------------------------------------
/rmdir/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/rmdir/.gitignore
--------------------------------------------------------------------------------
/rmdir/rmdir.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/runcon/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/runcon/.gitignore
--------------------------------------------------------------------------------
/runcon/runcon.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/seq/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/seq/.gitignore
--------------------------------------------------------------------------------
/seq/seq.go:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License version 3 as
4 | published by the Free Software Foundation.
5 |
6 | This program is distributed in the hope that it will be useful,
7 | but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 | GNU General Public License for more details.
10 |
11 | You should have received a copy of the GNU General Public License
12 | along with this program. If not, see .
13 | */
14 |
15 | package main
16 |
17 | import (
18 | "os"
19 | "strconv"
20 | )
21 | import "fmt"
22 |
23 | func main() {
24 | // TODO: Also handle floats.
25 | start, inc, end := 1, 1, 0
26 | nargs := len(os.Args)
27 | switch nargs {
28 | case 4:
29 | inc = parseInt(os.Args[2])
30 | fallthrough
31 | case 3:
32 | start = parseInt(os.Args[1])
33 | fallthrough
34 | case 2:
35 | end = parseInt(os.Args[nargs-1])
36 | default:
37 | msg := "missing operand"
38 | if nargs > 4 {
39 | msg = fmt.Sprintf("extra operand '%s'", os.Args[4])
40 | }
41 | fmt.Println("seq:", msg)
42 | os.Exit(1)
43 | }
44 |
45 | for i := start; i <= end; i += inc {
46 | fmt.Println(i)
47 | }
48 | }
49 |
50 | func parseInt(a string) int {
51 | i, err := strconv.Atoi(a)
52 | if err != nil {
53 | fmt.Println("seq:", err)
54 | os.Exit(1)
55 | }
56 | return i
57 | }
58 |
--------------------------------------------------------------------------------
/sha1sum/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/sha1sum/.gitignore
--------------------------------------------------------------------------------
/sha1sum/sha1sum.go:
--------------------------------------------------------------------------------
1 | /*
2 | go sha1sum
3 |
4 | Copyright (c) 2014-2015 Dingjun Fang
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License version 3 as
8 | published by the Free Software Foundation.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | /*
20 |
21 | Sha1sum util implement by go.
22 |
23 | Usage: sha1sum [OPTION]... [FILE]...
24 |
25 | Print or check SHA1 (160-bit) checksums.
26 |
27 | With no FILE, or when FILE is -, read standard input.
28 |
29 | -b, --binary read in binary mode(default)
30 | -c, --check read SHA1 sums from the FILEs and check them
31 | -t, --text read in text mode
32 | Note: there is no difference between text and binary mode option.
33 |
34 | The following three options are useful only when verifying checksums:
35 | --quiet don't print OK for each successfully verified file
36 | --status don't output anything, status code shows success
37 | -w, --warn warn about improperly formated checksum lines
38 |
39 | --help show help and exit
40 | --version show version and exit
41 |
42 | The sums are computed as described in FIPS-180-1. When checking, the input
43 | should be a former output of this program. The default mode is to print
44 | a line with checksum, a character indicating type ('*' for binary, ' ' for
45 | text), and name for each FILE.
46 | */
47 | package main
48 |
49 | import (
50 | "fmt"
51 | cc "github.com/fangdingjun/go-coreutils/md5sum/checksum_common"
52 | flag "github.com/ogier/pflag"
53 | "os"
54 | )
55 |
56 | const (
57 | Help = `Usage: sha1sum [OPTION]... [FILE]...
58 | Print or check SHA1 (160-bit) checksums.
59 | With no FILE, or when FILE is -, read standard input.
60 |
61 | -b, --binary read in binary mode(default)
62 | -c, --check read SHA1 sums from the FILEs and check them
63 | -t, --text read in text mode
64 | Note: there is no difference between text and binary mode option.
65 |
66 | The following three options are useful only when verifying checksums:
67 | --quiet don't print OK for each successfully verified file
68 | --status don't output anything, status code shows success
69 | -w, --warn warn about improperly formated checksum lines
70 |
71 | --help show help and exit
72 | --version show version and exit
73 |
74 | The sums are computed as described in FIPS-180-1. When checking, the input
75 | should be a former output of this program. The default mode is to print
76 | a line with checksum, a character indicating type ('*' for binary, ' ' for
77 | text), and name for each FILE.
78 | `
79 | Version = `sha1sum (Go coreutils) 0.1
80 | Copyright (C) 2015 Dingjun Fang
81 | License GPLv3+: GNU GPL version 3 or later .
82 | This is free software: you are free to change and redistribute it.
83 | There is NO WARRANTY, to the extent permitted by law.
84 | `
85 | )
86 |
87 | var (
88 | check_sum = flag.BoolP("check", "c", false, "")
89 | no_output = flag.BoolP("quiet", "q", false, "")
90 | no_output_s = flag.BoolP("status", "", false, "")
91 | show_warn = flag.BoolP("warn", "w", true, "")
92 | show_version = flag.BoolP("version", "v", false, "")
93 | text_mode = flag.BoolP("text", "t", false, "")
94 | binary_mode = flag.BoolP("binary", "b", false, "")
95 | )
96 |
97 | func main() {
98 | flag.Usage = func() {
99 | fmt.Fprintf(os.Stderr, "%s", Help)
100 | os.Exit(1)
101 | }
102 |
103 | flag.Parse()
104 |
105 | /* trust --status and --quiet as the same */
106 | if *no_output_s == true {
107 | *no_output = true
108 | }
109 |
110 | has_error := false
111 |
112 | file_lists := flag.Args()
113 | if len(file_lists) == 0 {
114 | file_lists = append(file_lists, "-")
115 | }
116 |
117 | switch {
118 | case *show_version:
119 | fmt.Fprintf(os.Stdout, "%s", Version)
120 | os.Exit(0)
121 | case *check_sum:
122 | if r := cc.CompareChecksum(file_lists, "sha1",
123 | !(*no_output), *show_warn); !r {
124 | has_error = true
125 | }
126 | default:
127 | if r := cc.GenerateChecksum(file_lists, "sha1"); !r {
128 | has_error = true
129 | }
130 | }
131 |
132 | if has_error {
133 | os.Exit(1)
134 | }
135 |
136 | os.Exit(0)
137 | }
138 |
--------------------------------------------------------------------------------
/sha224sum/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/sha224sum/.gitignore
--------------------------------------------------------------------------------
/sha224sum/sha224sum.go:
--------------------------------------------------------------------------------
1 | /*
2 | go sha224sum
3 |
4 | Copyright (c) 2014-2015 Dingjun Fang
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License version 3 as
8 | published by the Free Software Foundation.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | /*
20 |
21 | Sha224sum util implement by go.
22 |
23 | Usage: sha224sum [OPTION]... [FILE]...
24 |
25 | Print or check SHA224 (224-bit) checksums.
26 |
27 | With no FILE, or when FILE is -, read standard input.
28 |
29 | -b, --binary read in binary mode(default)
30 | -c, --check read SHA224 sums from the FILEs and check them
31 | -t, --text read in text mode
32 | Note: there is no difference between text and binary mode option.
33 |
34 | The following three options are useful only when verifying checksums:
35 | --quiet don't print OK for each successfully verified file
36 | --status don't output anything, status code shows success
37 | -w, --warn warn about improperly formated checksum lines
38 |
39 | --help show help and exit
40 | --version show version and exit
41 |
42 | The sums are computed as described in RFC 3874. When checking, the input
43 | should be a former output of this program. The default mode is to print
44 | a line with checksum, a character indicating type ('*' for binary, ' ' for
45 | text), and name for each FILE.
46 | */
47 | package main
48 |
49 | import (
50 | "fmt"
51 | cc "github.com/fangdingjun/go-coreutils/md5sum/checksum_common"
52 | flag "github.com/ogier/pflag"
53 | "os"
54 | )
55 |
56 | const (
57 | Help = `Usage: sha224sum [OPTION]... [FILE]...
58 | Print or check SHA224 (224-bit) checksums.
59 | With no FILE, or when FILE is -, read standard input.
60 |
61 | -b, --binary read in binary mode(default)
62 | -c, --check read SHA224 sums from the FILEs and check them
63 | -t, --text read in text mode
64 | Note: there is no difference between text and binary mode option.
65 |
66 | The following three options are useful only when verifying checksums:
67 | --quiet don't print OK for each successfully verified file
68 | --status don't output anything, status code shows success
69 | -w, --warn warn about improperly formated checksum lines
70 |
71 | --help show help and exit
72 | --version show version and exit
73 |
74 | The sums are computed as described in RFC 3874. When checking, the input
75 | should be a former output of this program. The default mode is to print
76 | a line with checksum, a character indicating type ('*' for binary, ' ' for
77 | text), and name for each FILE.
78 | `
79 | Version = `sha224sum (Go coreutils) 0.1
80 | Copyright (C) 2015 Dingjun Fang
81 | License GPLv3+: GNU GPL version 3 or later .
82 | This is free software: you are free to change and redistribute it.
83 | There is NO WARRANTY, to the extent permitted by law.
84 | `
85 | )
86 |
87 | var (
88 | check_sum = flag.BoolP("check", "c", false, "")
89 | no_output = flag.BoolP("quiet", "q", false, "")
90 | no_output_s = flag.BoolP("status", "", false, "")
91 | show_warn = flag.BoolP("warn", "w", true, "")
92 | show_version = flag.BoolP("version", "v", false, "")
93 | text_mode = flag.BoolP("text", "t", false, "")
94 | binary_mode = flag.BoolP("binary", "b", false, "")
95 | )
96 |
97 | func main() {
98 | flag.Usage = func() {
99 | fmt.Fprintf(os.Stderr, "%s", Help)
100 | os.Exit(1)
101 | }
102 |
103 | flag.Parse()
104 |
105 | /* trust --status and --quiet as the same */
106 | if *no_output_s == true {
107 | *no_output = true
108 | }
109 |
110 | has_error := false
111 |
112 | file_lists := flag.Args()
113 | if len(file_lists) == 0 {
114 | file_lists = append(file_lists, "-")
115 | }
116 |
117 | switch {
118 | case *show_version:
119 | fmt.Fprintf(os.Stdout, "%s", Version)
120 | os.Exit(0)
121 | case *check_sum:
122 | if r := cc.CompareChecksum(file_lists, "sha224",
123 | !(*no_output), *show_warn); !r {
124 | has_error = true
125 | }
126 | default:
127 | if r := cc.GenerateChecksum(file_lists, "sha224"); !r {
128 | has_error = true
129 | }
130 | }
131 |
132 | if has_error {
133 | os.Exit(1)
134 | }
135 |
136 | os.Exit(0)
137 | }
138 |
--------------------------------------------------------------------------------
/sha256sum/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/sha256sum/.gitignore
--------------------------------------------------------------------------------
/sha256sum/sha256sum.go:
--------------------------------------------------------------------------------
1 | /*
2 | go sha256sum
3 |
4 | Copyright (c) 2014-2015 Dingjun Fang
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License version 3 as
8 | published by the Free Software Foundation.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | /*
20 |
21 | Sha256sum util implement by go.
22 |
23 | Usage: sha256sum [OPTION]... [FILE]...
24 |
25 | Print or check SHA256 (256-bit) checksums.
26 |
27 | With no FILE, or when FILE is -, read standard input.
28 |
29 | -b, --binary read in binary mode(default)
30 | -c, --check read SHA256 sums from the FILEs and check them
31 | -t, --text read in text mode
32 | Note: there is no difference between text and binary mode option.
33 |
34 | The following three options are useful only when verifying checksums:
35 | --quiet don't print OK for each successfully verified file
36 | --status don't output anything, status code shows success
37 | -w, --warn warn about improperly formated checksum lines
38 |
39 | --help show help and exit
40 | --version show version and exit
41 |
42 | The sums are computed as described in FIPS-180-2. When checking, the input
43 | should be a former output of this program. The default mode is to print
44 | a line with checksum, a character indicating type ('*' for binary, ' ' for
45 | text), and name for each FILE.
46 | */
47 | package main
48 |
49 | import (
50 | "fmt"
51 | cc "github.com/fangdingjun/go-coreutils/md5sum/checksum_common"
52 | flag "github.com/ogier/pflag"
53 | "os"
54 | )
55 |
56 | const (
57 | Help = `Usage: sha256sum [OPTION]... [FILE]...
58 | Print or check SHA256 (256-bit) checksums.
59 | With no FILE, or when FILE is -, read standard input.
60 |
61 | -b, --binary read in binary mode(default)
62 | -c, --check read SHA256 sums from the FILEs and check them
63 | -t, --text read in text mode
64 | Note: there is no difference between text and binary mode option.
65 |
66 | The following three options are useful only when verifying checksums:
67 | --quiet don't print OK for each successfully verified file
68 | --status don't output anything, status code shows success
69 | -w, --warn warn about improperly formated checksum lines
70 |
71 | --help show help and exit
72 | --version show version and exit
73 |
74 | The sums are computed as described in FIPS-180-2. When checking, the input
75 | should be a former output of this program. The default mode is to print
76 | a line with checksum, a character indicating type ('*' for binary, ' ' for
77 | text), and name for each FILE.
78 | `
79 | Version = `sha256sum (Go coreutils) 0.1
80 | Copyright (C) 2015 Dingjun Fang
81 | License GPLv3+: GNU GPL version 3 or later .
82 | This is free software: you are free to change and redistribute it.
83 | There is NO WARRANTY, to the extent permitted by law.
84 | `
85 | )
86 |
87 | var (
88 | check_sum = flag.BoolP("check", "c", false, "")
89 | no_output = flag.BoolP("quiet", "q", false, "")
90 | no_output_s = flag.BoolP("status", "", false, "")
91 | show_warn = flag.BoolP("warn", "w", true, "")
92 | show_version = flag.BoolP("version", "v", false, "")
93 | text_mode = flag.BoolP("text", "t", false, "")
94 | binary_mode = flag.BoolP("binary", "b", false, "")
95 | )
96 |
97 | func main() {
98 | flag.Usage = func() {
99 | fmt.Fprintf(os.Stderr, "%s", Help)
100 | os.Exit(1)
101 | }
102 |
103 | flag.Parse()
104 |
105 | /* trust --status and --quiet as the same */
106 | if *no_output_s == true {
107 | *no_output = true
108 | }
109 |
110 | has_error := false
111 |
112 | file_lists := flag.Args()
113 | if len(file_lists) == 0 {
114 | file_lists = append(file_lists, "-")
115 | }
116 |
117 | switch {
118 | case *show_version:
119 | fmt.Fprintf(os.Stdout, "%s", Version)
120 | os.Exit(0)
121 | case *check_sum:
122 | if r := cc.CompareChecksum(file_lists, "sha256",
123 | !(*no_output), *show_warn); !r {
124 | has_error = true
125 | }
126 | default:
127 | if r := cc.GenerateChecksum(file_lists, "sha256"); !r {
128 | has_error = true
129 | }
130 | }
131 |
132 | if has_error {
133 | os.Exit(1)
134 | }
135 |
136 | os.Exit(0)
137 | }
138 |
--------------------------------------------------------------------------------
/sha384sum/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/sha384sum/.gitignore
--------------------------------------------------------------------------------
/sha384sum/sha384sum.go:
--------------------------------------------------------------------------------
1 | /*
2 | go sha384sum
3 |
4 | Copyright (c) 2014-2015 Dingjun Fang
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License version 3 as
8 | published by the Free Software Foundation.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | /*
20 |
21 | Sha384sum util implement by go.
22 |
23 | Usage: sha384sum [OPTION]... [FILE]...
24 |
25 | Print or check SHA384 (384-bit) checksums.
26 |
27 | With no FILE, or when FILE is -, read standard input.
28 |
29 | -b, --binary read in binary mode(default)
30 | -c, --check read SHA384 sums from the FILEs and check them
31 | -t, --text read in text mode
32 | Note: there is no difference between text and binary mode option.
33 |
34 | The following three options are useful only when verifying checksums:
35 | --quiet don't print OK for each successfully verified file
36 | --status don't output anything, status code shows success
37 | -w, --warn warn about improperly formated checksum lines
38 |
39 | --help show help and exit
40 | --version show version and exit
41 |
42 | The sums are computed as described in FIPS-180-2. When checking, the input
43 | should be a former output of this program. The default mode is to print
44 | a line with checksum, a character indicating type ('*' for binary, ' ' for
45 | text), and name for each FILE.
46 | */
47 | package main
48 |
49 | import (
50 | "fmt"
51 | cc "github.com/fangdingjun/go-coreutils/md5sum/checksum_common"
52 | flag "github.com/ogier/pflag"
53 | "os"
54 | )
55 |
56 | const (
57 | Help = `Usage: sha384sum [OPTION]... [FILE]...
58 | Print or check SHA384 (384-bit) checksums.
59 | With no FILE, or when FILE is -, read standard input.
60 |
61 | -b, --binary read in binary mode(default)
62 | -c, --check read SHA384 sums from the FILEs and check them
63 | -t, --text read in text mode
64 | Note: there is no difference between text and binary mode option.
65 |
66 | The following three options are useful only when verifying checksums:
67 | --quiet don't print OK for each successfully verified file
68 | --status don't output anything, status code shows success
69 | -w, --warn warn about improperly formated checksum lines
70 |
71 | --help show help and exit
72 | --version show version and exit
73 |
74 | The sums are computed as described in FIPS-180-2. When checking, the input
75 | should be a former output of this program. The default mode is to print
76 | a line with checksum, a character indicating type ('*' for binary, ' ' for
77 | text), and name for each FILE.
78 | `
79 | Version = `sha384sum (Go coreutils) 0.1
80 | Copyright (C) 2015 Dingjun Fang
81 | License GPLv3+: GNU GPL version 3 or later .
82 | This is free software: you are free to change and redistribute it.
83 | There is NO WARRANTY, to the extent permitted by law.
84 | `
85 | )
86 |
87 | var (
88 | check_sum = flag.BoolP("check", "c", false, "")
89 | no_output = flag.BoolP("quiet", "q", false, "")
90 | no_output_s = flag.BoolP("status", "", false, "")
91 | show_warn = flag.BoolP("warn", "w", true, "")
92 | show_version = flag.BoolP("version", "v", false, "")
93 | text_mode = flag.BoolP("text", "t", false, "")
94 | binary_mode = flag.BoolP("binary", "b", false, "")
95 | )
96 |
97 | func main() {
98 | flag.Usage = func() {
99 | fmt.Fprintf(os.Stderr, "%s", Help)
100 | os.Exit(1)
101 | }
102 |
103 | flag.Parse()
104 |
105 | /* trust --status and --quiet as the same */
106 | if *no_output_s == true {
107 | *no_output = true
108 | }
109 |
110 | has_error := false
111 |
112 | file_lists := flag.Args()
113 | if len(file_lists) == 0 {
114 | file_lists = append(file_lists, "-")
115 | }
116 |
117 | switch {
118 | case *show_version:
119 | fmt.Fprintf(os.Stdout, "%s", Version)
120 | os.Exit(0)
121 | case *check_sum:
122 | if r := cc.CompareChecksum(file_lists, "sha384",
123 | !(*no_output), *show_warn); !r {
124 | has_error = true
125 | }
126 | default:
127 | if r := cc.GenerateChecksum(file_lists, "sha384"); !r {
128 | has_error = true
129 | }
130 | }
131 |
132 | if has_error {
133 | os.Exit(1)
134 | }
135 |
136 | os.Exit(0)
137 | }
138 |
--------------------------------------------------------------------------------
/sha512sum/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/sha512sum/.gitignore
--------------------------------------------------------------------------------
/sha512sum/sha512sum.go:
--------------------------------------------------------------------------------
1 | /*
2 | go sha512sum
3 |
4 | Copyright (c) 2014-2015 Dingjun Fang
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License version 3 as
8 | published by the Free Software Foundation.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | /*
20 |
21 | Sha512sum util implement by go.
22 |
23 | Usage: sha512sum [OPTION]... [FILE]...
24 |
25 | Print or check SHA512 (512-bit) checksums.
26 |
27 | With no FILE, or when FILE is -, read standard input.
28 |
29 | -b, --binary read in binary mode(default)
30 | -c, --check read SHA512 sums from the FILEs and check them
31 | -t, --text read in text mode
32 | Note: there is no difference between text and binary mode option.
33 |
34 | The following three options are useful only when verifying checksums:
35 | --quiet don't print OK for each successfully verified file
36 | --status don't output anything, status code shows success
37 | -w, --warn warn about improperly formated checksum lines
38 |
39 | --help show help and exit
40 | --version show version and exit
41 |
42 | The sums are computed as described in FIPS-180-2. When checking, the input
43 | should be a former output of this program. The default mode is to print
44 | a line with checksum, a character indicating type ('*' for binary, ' ' for
45 | text), and name for each FILE.
46 | */
47 | package main
48 |
49 | import (
50 | "fmt"
51 | cc "github.com/fangdingjun/go-coreutils/md5sum/checksum_common"
52 | flag "github.com/ogier/pflag"
53 | "os"
54 | )
55 |
56 | const (
57 | Help = `Usage: sha512sum [OPTION]... [FILE]...
58 | Print or check SHA512 (512-bit) checksums.
59 | With no FILE, or when FILE is -, read standard input.
60 |
61 | -b, --binary read in binary mode(default)
62 | -c, --check read SHA512 sums from the FILEs and check them
63 | -t, --text read in text mode
64 | Note: there is no difference between text and binary mode option.
65 |
66 | The following three options are useful only when verifying checksums:
67 | --quiet don't print OK for each successfully verified file
68 | --status don't output anything, status code shows success
69 | -w, --warn warn about improperly formated checksum lines
70 |
71 | --help show help and exit
72 | --version show version and exit
73 |
74 | The sums are computed as described in FIPS-180-2. When checking, the input
75 | should be a former output of this program. The default mode is to print
76 | a line with checksum, a character indicating type ('*' for binary, ' ' for
77 | text), and name for each FILE.
78 | `
79 | Version = `sha512sum (Go coreutils) 0.1
80 | Copyright (C) 2015 Dingjun Fang
81 | License GPLv3+: GNU GPL version 3 or later .
82 | This is free software: you are free to change and redistribute it.
83 | There is NO WARRANTY, to the extent permitted by law.
84 | `
85 | )
86 |
87 | var (
88 | check_sum = flag.BoolP("check", "c", false, "")
89 | no_output = flag.BoolP("quiet", "q", false, "")
90 | no_output_s = flag.BoolP("status", "", false, "")
91 | show_warn = flag.BoolP("warn", "w", true, "")
92 | show_version = flag.BoolP("version", "v", false, "")
93 | text_mode = flag.BoolP("text", "t", false, "")
94 | binary_mode = flag.BoolP("binary", "b", false, "")
95 | )
96 |
97 | func main() {
98 | flag.Usage = func() {
99 | fmt.Fprintf(os.Stderr, "%s", Help)
100 | os.Exit(1)
101 | }
102 |
103 | flag.Parse()
104 |
105 | /* trust --status and --quiet as the same */
106 | if *no_output_s == true {
107 | *no_output = true
108 | }
109 |
110 | has_error := false
111 |
112 | file_lists := flag.Args()
113 | if len(file_lists) == 0 {
114 | file_lists = append(file_lists, "-")
115 | }
116 |
117 | switch {
118 | case *show_version:
119 | fmt.Fprintf(os.Stdout, "%s", Version)
120 | os.Exit(0)
121 | case *check_sum:
122 | if r := cc.CompareChecksum(file_lists, "sha512",
123 | !(*no_output), *show_warn); !r {
124 | has_error = true
125 | }
126 | default:
127 | if r := cc.GenerateChecksum(file_lists, "sha512"); !r {
128 | has_error = true
129 | }
130 | }
131 |
132 | if has_error {
133 | os.Exit(1)
134 | }
135 |
136 | os.Exit(0)
137 | }
138 |
--------------------------------------------------------------------------------
/shred/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/shred/.gitignore
--------------------------------------------------------------------------------
/shred/shred.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/shuf/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/shuf/.gitignore
--------------------------------------------------------------------------------
/shuf/shuf.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/sleep/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/sleep/.gitignore
--------------------------------------------------------------------------------
/sleep/sleep.go:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License version 3 as
4 | published by the Free Software Foundation.
5 |
6 | This program is distributed in the hope that it will be useful,
7 | but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 | GNU General Public License for more details.
10 |
11 | You should have received a copy of the GNU General Public License
12 | along with this program. If not, see .
13 | */
14 |
15 | package main
16 |
17 | import "time"
18 | import "os"
19 | import "strconv"
20 |
21 | func main() {
22 | if len(os.Args) >= 2 {
23 | duration, err := strconv.ParseInt(os.Args[1], 0, 64)
24 | if err != nil || duration < 0 {
25 | os.Exit(1)
26 | }
27 | time.Sleep(time.Duration(duration) * time.Second)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/sort/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/sort/.gitignore
--------------------------------------------------------------------------------
/sort/sort.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/split/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/split/.gitignore
--------------------------------------------------------------------------------
/split/split.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/stat/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/stat/.gitignore
--------------------------------------------------------------------------------
/stat/stat.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/stdbuf/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/stdbuf/.gitignore
--------------------------------------------------------------------------------
/stdbuf/stdbuf.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/stty/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/stty/.gitignore
--------------------------------------------------------------------------------
/stty/stty.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/sum/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/sum/.gitignore
--------------------------------------------------------------------------------
/sum/sum.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/sync/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/sync/.gitignore
--------------------------------------------------------------------------------
/sync/sync_linux.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "syscall"
7 |
8 | flag "github.com/ogier/pflag"
9 | )
10 |
11 | const (
12 | Help = `Usage: sync [OPTION]
13 | Force changed blocks to disk, update the super block.
14 |
15 | --help display this help and exit
16 | --version output version information and exit
17 |
18 | Report wc bugs to ericscottlagergren@gmail.com
19 | Go coreutils home page:
20 | `
21 | Version = `sync (coreutils) 1
22 | Copyright (C) 2015 Eric Lagergren.
23 | License GPLv3+: GNU GPL version 3 or later .
24 | This is free software: you are free to change and redistribute it.
25 | There is NO WARRANTY, to the extent permitted by law.
26 |
27 | Written by Eric Lagergren
28 | `
29 | )
30 |
31 | var version = flag.BoolP("version", "v", false, "")
32 |
33 | func main() {
34 | flag.Usage = func() {
35 | fmt.Fprintf(os.Stderr, "%s", Help)
36 | os.Exit(1)
37 | }
38 | flag.Parse()
39 |
40 | // Nothing can fail.
41 | syscall.Sync()
42 | }
43 |
--------------------------------------------------------------------------------
/sync/sync_windows.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | "os"
7 | "path/filepath"
8 | "syscall"
9 |
10 | flag "github.com/ogier/pflag"
11 | )
12 |
13 | const (
14 | Help = `Usage: sync [OPTION]
15 | Force changed blocks to disk, update the super block.
16 |
17 | --help display this help and exit
18 | --version output version information and exit
19 |
20 | Report wc bugs to ericscottlagergren@gmail.com
21 | Go coreutils home page:
22 | `
23 | Version = `sync (coreutils) 1
24 | Copyright (C) 2015 Eric Lagergren.
25 | License GPLv3+: GNU GPL version 3 or later .
26 | This is free software: you are free to change and redistribute it.
27 | There is NO WARRANTY, to the extent permitted by law.
28 |
29 | Written by Eric Lagergren
30 | `
31 | )
32 |
33 | var (
34 | version = flag.BoolP("version", "v", false, "")
35 | fatal = log.New(os.Stderr, "", 0)
36 | )
37 |
38 | func main() {
39 | flag.Usage = func() {
40 | fmt.Fprintf(os.Stderr, "%s", Help)
41 | os.Exit(1)
42 | }
43 | flag.Parse()
44 |
45 | dir, err := os.Getwd()
46 | if err != nil {
47 | fatal.Fatalln(err)
48 | }
49 |
50 | // "To flush all open files on a volume, call FlushFileBuffers with a handle to the volume.
51 | // The caller must have administrative privileges. For more information, see Running with Special Privileges."
52 | // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364439(v=vs.85).aspx
53 | fp := filepath.VolumeName(dir)
54 | file, err := os.Open(fp)
55 | if err != nil {
56 | fatal.Fatalln(err)
57 | }
58 |
59 | err = syscall.Fsync(syscall.Handle(file.Fd()))
60 | if err != nil {
61 | fatal.Fatalln(err)
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/tac/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/tac/.gitignore
--------------------------------------------------------------------------------
/tac/tac.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/tail/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/tail/.gitignore
--------------------------------------------------------------------------------
/tail/tail.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/tee/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/tee/.gitignore
--------------------------------------------------------------------------------
/tee/tee.go:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License version 3 as
4 | published by the Free Software Foundation.
5 |
6 | This program is distributed in the hope that it will be useful,
7 | but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 | GNU General Public License for more details.
10 |
11 | You should have received a copy of the GNU General Public License
12 | along with this program. If not, see .
13 | */
14 |
15 | package main
16 |
17 | import "os"
18 | import "fmt"
19 | import "io/ioutil"
20 | import flag "github.com/ogier/pflag"
21 | import "log"
22 |
23 | func main() {
24 | flagAppend := flag.BoolP("append", "a", false, "append to file")
25 | flag.Parse()
26 | bytes, _ := ioutil.ReadAll(os.Stdin)
27 | for i := 0; i < len(flag.Args()); i++ {
28 | if *flagAppend {
29 | f, err := os.OpenFile(flag.Args()[i], os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
30 | if err != nil {
31 | log.Fatal(err)
32 | }
33 | f.Write(bytes)
34 | f.Close()
35 | } else {
36 | f, err := os.OpenFile(flag.Args()[i], os.O_WRONLY|os.O_CREATE, 0644)
37 | if err != nil {
38 | log.Fatal(err)
39 | }
40 | f.Write(bytes)
41 | f.Close()
42 | }
43 | }
44 | fmt.Printf("%s", string(bytes))
45 | }
46 |
--------------------------------------------------------------------------------
/test/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/test/.gitignore
--------------------------------------------------------------------------------
/test/test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/timeout/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/timeout/.gitignore
--------------------------------------------------------------------------------
/timeout/timeout.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/touch/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/touch/.gitignore
--------------------------------------------------------------------------------
/touch/touch.go:
--------------------------------------------------------------------------------
1 | /*
2 | Go touch - prints the current working directory.
3 | Copyright (C) 2015 Robert Deusser
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 3 of the License, or
7 | (at your option) any later version.
8 | This program is distributed in the hope that it will be useful,
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | GNU General Public License for more details.
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see .
14 | */
15 |
16 | /*
17 | Written by Robert Deusser
18 | */
19 |
20 | package main
21 |
22 | import (
23 | "fmt"
24 | "log"
25 | "os"
26 | "time"
27 |
28 | flag "github.com/ogier/pflag"
29 | )
30 |
31 | const (
32 | Help = `
33 | Usage: touch [OPTION]... FILE...
34 | Update the access and modification times of each FILE to the current time.
35 |
36 | A FILE argument that does not exist is created empty, unless -c or -h
37 | is supplied.
38 |
39 | A FILE argument string of - is handled specially and causes touch to
40 | change the times of the file associated with standard output.
41 |
42 | Mandatory arguments to long options are mandatory for short options too.
43 | -a change only the access time
44 | -c, --no-create do not create any files
45 | -d, --date=STRING parse STRING and use it instead of current time
46 | -f (ignored)
47 | -h, --no-dereference affect each symbolic link instead of any referenced
48 | file (useful only on systems that can change the
49 | timestamps of a symlink)
50 | -m change only the modification time
51 | -r, --reference=FILE use this file's times instead of current time
52 | -t STAMP use [[CC]YY]MMDDhhmm[.ss] instead of current time
53 | --time=WORD change the specified time:
54 | WORD is access, atime, or use: equivalent to -a
55 | WORD is modify or mtime: equivalent to -m
56 | --help display this help and exit
57 | --version output version information and exit
58 |
59 | Note that the -d and -t options accept different time-date formats.
60 |
61 | `
62 | Version = `
63 | touch (Go coreutils) 0.1
64 | Copyright (C) 2015 Robert Deusser
65 | License GPLv3+: GNU GPL version 3 or later .
66 | This is free software: you are free to change and redistribute it.
67 | There is NO WARRANTY, to the extent permitted by law.
68 |
69 | `
70 | )
71 |
72 | var (
73 | nocreate = flag.BoolP("no-create", "c", false, "")
74 | version = flag.BoolP("version", "v", false, "")
75 | )
76 |
77 | func main() {
78 | flag.Usage = func() {
79 | fmt.Fprintf(os.Stderr, "%s", Help)
80 | os.Exit(1)
81 | }
82 | flag.Parse()
83 |
84 | if *version {
85 | fmt.Fprintf(os.Stdout, "%s", Version)
86 | os.Exit(0)
87 | }
88 |
89 | if len(flag.Args()) > 0 {
90 | for i := 0; i < len(flag.Args()); i++ {
91 | filename := flag.Arg(i)
92 | _, err := os.Stat(filename)
93 | if err == nil {
94 | now := time.Now()
95 | os.Chtimes(filename, now, now)
96 | } else if !(*nocreate) {
97 | f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0644)
98 | f.Close()
99 | if err != nil {
100 | log.Fatal(err)
101 | }
102 | }
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/tr/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/tr/.gitignore
--------------------------------------------------------------------------------
/tr/tr.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/true/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/true/.gitignore
--------------------------------------------------------------------------------
/true/true.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | )
7 |
8 | const (
9 | Help = `Usage: /usr/bin/true [ignored command line arguments]
10 | or: /usr/bin/true OPTION
11 | Exit with a status code indicating success.
12 |
13 | --help display this help and exit
14 | --version output version information and exit
15 |
16 | NOTE: your shell may have its own version of true, which usually supersedes
17 | the version described here. Please refer to your shell's documentation
18 | for details about the options it supports.
19 | `
20 | Version = `true (Go coreutils) 1.0
21 | Copyright (C) 2015 Eric Lagergren
22 | License GPLv3+: GNU GPL version 3 or later .
23 | This is free software: you are free to change and redistribute it.
24 | There is NO WARRANTY, to the extent permitted by law.
25 | `
26 | )
27 |
28 | func main() {
29 | if len(os.Args) == 2 {
30 | if os.Args[1] == "--help" {
31 | fmt.Printf("%s", Help)
32 | }
33 |
34 | if os.Args[1] == "--version" {
35 | fmt.Printf("%s", Version)
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/truncate/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/truncate/.gitignore
--------------------------------------------------------------------------------
/truncate/truncate.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/tsort/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/tsort/.gitignore
--------------------------------------------------------------------------------
/tsort/tsort_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 | )
7 |
8 | var (
9 | nums = map[string]string{
10 | `3 8
11 | 3 10
12 | 5 11
13 | 7 8
14 | 7 11
15 | 8 9
16 | 11 2
17 | 11 9
18 | 11 10`: `3
19 | 5
20 | 7
21 | 11
22 | 8
23 | 10
24 | 2
25 | 9
26 | `, `8 9
27 | 1 4
28 | 1 2
29 | 4 2
30 | 4 3
31 | 3 2
32 | 5 2
33 | 3 5
34 | 8 2
35 | 8 6`: `1
36 | 8
37 | 4
38 | 6
39 | 9
40 | 3
41 | 5
42 | 2
43 | `,
44 | `4 4
45 | 2 4
46 | 4 1
47 | 3 1`: `2
48 | 3
49 | 4
50 | 1
51 | `}
52 | )
53 |
54 | func TestTsort(t *testing.T) {
55 |
56 | for unsorted, sorted := range nums {
57 | var buf bytes.Buffer
58 |
59 | buf.WriteString(unsorted)
60 |
61 | tsort(&buf)
62 |
63 | if buf.String() != sorted {
64 | t.Errorf("Got: %q\n\nWanted: %q", buf.String(), sorted)
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/tty/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/tty/.gitignore
--------------------------------------------------------------------------------
/tty/tty.go:
--------------------------------------------------------------------------------
1 | /*
2 | Go tty -- print the name of the terminal connected to standard input
3 |
4 | Copyright (C) 2015 Eric Lagergren
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | package main
21 |
22 | import (
23 | "fmt"
24 | "os"
25 |
26 | "github.com/EricLagergren/go-gnulib/ttyname"
27 | flag "github.com/ogier/pflag"
28 | )
29 |
30 | const (
31 | VERSION = `tty (Go coreutils) 1.0
32 | Copyright (C) 2015 Eric Lagergren
33 | License GPLv3+: GNU GPL version 3 or later .
34 | This is free software: you are free to change and redistribute it.
35 | There is NO WARRANTY, to the extent permitted by law.
36 |
37 | Written by Eric Lagergren
38 | Inspired by David MacKenzie.`
39 | HELP = `Usage: tty [OPTION]...
40 | Print the file name of the terminal connected to standard input.
41 |
42 | -s, --silent, --quiet print nothing, only return an exit status
43 | --help display this help and exit
44 | --version output version information and exit
45 |
46 | Report uname bugs to ericscottlagergren@gmail.com
47 | Go coreutils home page: `
48 | )
49 |
50 | var (
51 | version = flag.Bool("version", false, "print version")
52 | quiet1 = flag.BoolP("silent", "s", false, "no output")
53 | quiet2 = flag.Bool("quiet", false, "no output")
54 | )
55 |
56 | func main() {
57 | flag.Usage = func() {
58 | fmt.Fprintf(os.Stderr, "%s\n", HELP)
59 | return
60 | }
61 | flag.Parse()
62 |
63 | if *version {
64 | fmt.Printf("%s\n", VERSION)
65 | return
66 | }
67 |
68 | silent := *quiet1 || *quiet2
69 |
70 | si := os.Stdin.Fd()
71 | tty, err := ttyname.TtyName(si)
72 | if !silent {
73 | if err == ttyname.NotTty {
74 | fmt.Println("not a tty")
75 | os.Exit(1)
76 | }
77 | if tty != "" {
78 | fmt.Println(tty)
79 | return
80 | } else {
81 | fmt.Println("tty")
82 | }
83 | }
84 |
85 | if err != nil {
86 | os.Exit(1)
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/uname/.gitignore:
--------------------------------------------------------------------------------
1 | # binary
2 | uname
--------------------------------------------------------------------------------
/uname/README.md:
--------------------------------------------------------------------------------
1 | The -o, --operating-system switch should work just fine for most
2 | standard OSs.
3 |
4 | If you need to set a custom value, please install the tool as such:
5 |
6 | `go install --tags=ostypes -ldflags '-X main.hostOS=FOO'`
7 |
8 | If you do not know the value you need to set, please run `go generate` prior
9 | to installing this command.
--------------------------------------------------------------------------------
/uname/generate.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | //go:generate go run ostypes.go
4 |
--------------------------------------------------------------------------------
/uname/host_os.go:
--------------------------------------------------------------------------------
1 | // +build ostypes
2 |
3 | package main
4 |
5 | var hostOS = unknown
6 |
--------------------------------------------------------------------------------
/uname/host_os_darwin.go:
--------------------------------------------------------------------------------
1 | // +build darwin,!ostypes
2 |
3 | package main
4 |
5 | const hostOS = "Darwin"
6 |
--------------------------------------------------------------------------------
/uname/host_os_dragonfly.go:
--------------------------------------------------------------------------------
1 | // +build dragonfly,!ostypes
2 |
3 | package main
4 |
5 | const hostOS = "Dragonfly"
6 |
--------------------------------------------------------------------------------
/uname/host_os_freebsd.go:
--------------------------------------------------------------------------------
1 | // +build linux,!ostypes
2 |
3 | package main
4 |
5 | const hostOS = "GNU/Linux"
6 |
--------------------------------------------------------------------------------
/uname/host_os_linux.go:
--------------------------------------------------------------------------------
1 | // +build linux,!ostypes
2 |
3 | package main
4 |
5 | const hostOS = "GNU/Linux"
6 |
--------------------------------------------------------------------------------
/uname/host_os_netbsd.go:
--------------------------------------------------------------------------------
1 | // +build netbsd,!ostypes
2 |
3 | package main
4 |
5 | const hostOS = "NetBSD"
6 |
--------------------------------------------------------------------------------
/uname/host_os_openbsd.go:
--------------------------------------------------------------------------------
1 | // +build openbsd,!ostypes
2 |
3 | package main
4 |
5 | const hostOS = "OpenBSD"
6 |
--------------------------------------------------------------------------------
/uname/host_os_plan9.go:
--------------------------------------------------------------------------------
1 | // +build plan9,!ostypes
2 |
3 | package main
4 |
5 | const hostOS = "Plan 9"
6 |
--------------------------------------------------------------------------------
/uname/host_os_solaris.go:
--------------------------------------------------------------------------------
1 | // +build solaris,!ostypes
2 |
3 | package main
4 |
5 | const hostOS = "Solaris"
6 |
--------------------------------------------------------------------------------
/uname/host_os_windows.go:
--------------------------------------------------------------------------------
1 | // +build windows,!ostypes
2 |
3 | package main
4 |
5 | const hostOS = "Windows NT"
6 |
--------------------------------------------------------------------------------
/uname/ostypes.go:
--------------------------------------------------------------------------------
1 | // +build ignore
2 |
3 | package main
4 |
5 | import (
6 | "fmt"
7 | "os"
8 | "os/exec"
9 | "path/filepath"
10 | "strings"
11 | )
12 |
13 | // globs are stolen from GNU coreutils' host-os.m4 file.
14 | // see GNU-LICENSE.txt
15 | var globs = map[string]string{
16 | "winnt*": "Windows NT",
17 | "vos*": "VOS",
18 | "sysv*": "Unix System V",
19 | "superux*": "SUPER-UX",
20 | "sunos*": "SunOS",
21 | "stop*": "STOP",
22 | "sco*": "SCO Unix",
23 | "riscos*": "RISC OS",
24 | "riscix*": "RISCiX",
25 | "qnx*": "QNX",
26 | "pw32*": "PW32",
27 | "ptx*": "ptx",
28 | "plan9*": "Plan 9",
29 | "osf*": "Tru64",
30 | "os2*": "OS/2",
31 | "openbsd*": "OpenBSD",
32 | "nsk*": "NonStop Kernel",
33 | "nonstopux*": "NonStop-UX",
34 | "netbsd*-gnu*": "GNU/NetBSD",
35 | "netbsd*": "NetBSD",
36 | "mirbsd*": "MirBSD",
37 | "knetbsd*-gnu": "GNU/kNetBSD",
38 | "kfreebsd*-gnu": "GNU/kFreeBSD",
39 | "msdosdjgpp*": "DJGPP",
40 | "mpeix*": "MPE/iX",
41 | "mint*": "MiNT",
42 | "mingw*": "MinGW",
43 | "lynxos*": "LynxOS",
44 | "linux*": "GNU/Linux",
45 | "hpux*": "HP-UX",
46 | "hiux*": "HI-UX",
47 | "gnu*": "GNU",
48 | "freebsd*": "FreeBSD",
49 | "dgux*": "DG/UX",
50 | "bsdi*": "BSD/OS",
51 | "bsd*": "BSD",
52 | "beos*": "BeOS",
53 | "aux*": "A/UX",
54 | "atheos*": "AtheOS",
55 | "amigaos*": "Amiga OS",
56 | "aix*": "AIX",
57 | }
58 |
59 | func match(pattern, name string) bool {
60 | ok, err := filepath.Match(pattern, name)
61 | return ok && err == nil
62 | }
63 |
64 | func main() {
65 | const pkg = "main"
66 |
67 | // Shell locals...
68 | out, err := exec.Command("sh", "-c", "echo $OSTYPE").Output()
69 | if err != nil {
70 | panic(err)
71 | }
72 |
73 | if len(out) > 0 && out[len(out)-1] == '\n' {
74 | out = out[:len(out)-1]
75 | }
76 |
77 | file, err := os.Create("host_os.go")
78 | if err != nil {
79 | panic(err)
80 | }
81 | defer file.Close()
82 |
83 | rawHostOS := string(out)
84 |
85 | fmt.Fprintln(file, "// +build ostypes")
86 | fmt.Fprintf(file, "// generated by ostypes. DO NOT EDIT.\n\n")
87 | fmt.Fprintf(file, "package %s\n\nconst hostOS = ", pkg)
88 |
89 | // This is what uname does.
90 | if rawHostOS == "" {
91 | fmt.Fprintf(file, "%q\n\n", "unknown")
92 | return
93 | }
94 |
95 | var realHostOS string
96 | for glob, val := range globs {
97 | if match(glob, rawHostOS) {
98 | realHostOS = val
99 | break
100 | }
101 | }
102 |
103 | // No matches found, so apply the default heuristic.
104 | if realHostOS == "" {
105 | if match("[A-Za-z]*", rawHostOS) {
106 | realHostOS := strings.ToUpper(string(rawHostOS[0]))
107 | if len(rawHostOS) > 1 {
108 | realHostOS += rawHostOS[1:]
109 | }
110 | } else {
111 | realHostOS = rawHostOS
112 | }
113 | }
114 |
115 | fmt.Fprintf(file, "%q\n\n", realHostOS)
116 | }
117 |
--------------------------------------------------------------------------------
/uname/uname.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014-2016 Eric Lagergren
2 | // Use of this source code is governed by the GPL v3 or later.
3 |
4 | package main
5 |
6 | import (
7 | "fmt"
8 | "log"
9 | "os"
10 |
11 | "github.com/EricLagergren/go-coreutils/internal/flag"
12 | )
13 |
14 | const (
15 | unknown = "unknown"
16 | procCPU = "/proc/cpuinfo"
17 | maxUint = ^printer(0)
18 | )
19 |
20 | var (
21 | all = flag.BoolP("all", "a", false, `print all information, in the following order,
22 | except omit -p and -i if unknown:`)
23 | kernelName = flag.BoolP("kernel-name", "s", false, "print the kernel name")
24 | nodeName = flag.BoolP("nodename", "n", false, "print the network node hostname")
25 | release = flag.BoolP("kernel-release", "r", false, "print the kernel release")
26 | version = flag.BoolP("kernel-version", "v", false, "print the kernel version")
27 | machine = flag.BoolP("machine", "m", false, "print the machine hardware name")
28 | processor = flag.BoolP("processor", "p", false, "print the processor tyoe or \"unknown\"")
29 | hwPlatform = flag.BoolP("hardware-platform", "i", false, "print the hardware platform or \"unknown\"")
30 | operatingSystem = flag.BoolP("operating-system", "o", false, "print the operating system")
31 |
32 | fatal = log.New(os.Stderr, "", 0)
33 | )
34 |
35 | type printer uint
36 |
37 | // Enumerated printing options.
38 | const (
39 | printKernelName printer = 1 << iota
40 | printNodeName
41 | printKernelRelease
42 | printKernelVersion
43 | printMachine
44 | printProcessor
45 | printHardwarePlatform
46 | printOperatingSystem
47 | )
48 |
49 | func (p printer) isSet(val printer) bool {
50 | return p&val != 0
51 | }
52 |
53 | var printed bool
54 |
55 | func print(element string) {
56 | if printed {
57 | fmt.Print(" ")
58 | }
59 | printed = true
60 | fmt.Printf("%s", element)
61 | }
62 |
63 | func decode(b bool, flag printer) printer {
64 | if b {
65 | return flag
66 | }
67 | return 0
68 | }
69 |
70 | func decodeFlags() printer {
71 | var toprint printer
72 | toprint |= decode(*all, maxUint)
73 | toprint |= decode(*kernelName, printKernelName)
74 | toprint |= decode(*nodeName, printNodeName)
75 | toprint |= decode(*release, printKernelRelease)
76 | toprint |= decode(*version, printKernelVersion)
77 | toprint |= decode(*machine, printMachine)
78 | toprint |= decode(*processor, printProcessor)
79 | toprint |= decode(*hwPlatform, printHardwarePlatform)
80 | toprint |= decode(*operatingSystem, printOperatingSystem)
81 | return toprint
82 | }
83 |
84 | func main() {
85 | flag.Usage = func() {
86 | fmt.Printf(`Usage: %s [OPTION]...
87 | Print certain system information. With no OPTION, same as -s.
88 |
89 | `, flag.Program)
90 | flag.DBE()
91 | }
92 | flag.ProgVersion = "1.1"
93 | flag.Parse()
94 |
95 | toprint := decodeFlags()
96 | if toprint == 0 {
97 | toprint = printKernelName
98 | }
99 |
100 | if toprint.isSet(
101 | (printKernelName | printNodeName | printKernelRelease |
102 | printKernelVersion | printMachine)) {
103 |
104 | name, err := genInfo()
105 | if err != nil {
106 | fatal.Fatalln("cannot get system name")
107 | }
108 |
109 | if toprint.isSet(printKernelName) {
110 | print(name.sysname)
111 | }
112 | if toprint.isSet(printNodeName) {
113 | print(name.nodename)
114 | }
115 | if toprint.isSet(printKernelRelease) {
116 | print(name.release)
117 | }
118 | if toprint.isSet(printKernelVersion) {
119 | print(name.version)
120 | }
121 | if toprint.isSet(printMachine) {
122 | print(name.machine)
123 | }
124 | }
125 |
126 | if toprint.isSet(printProcessor) {
127 | element := unknown
128 | if toprint != maxUint || element != unknown {
129 | print(element)
130 | }
131 | }
132 |
133 | if toprint.isSet(printHardwarePlatform) {
134 | element := unknown
135 | if toprint != maxUint || hostOS != unknown {
136 | print(element)
137 | }
138 | }
139 |
140 | if toprint.isSet(printOperatingSystem) {
141 | print(hostOS)
142 | }
143 |
144 | os.Stdout.WriteString("\n")
145 | }
146 |
--------------------------------------------------------------------------------
/uname/uname_freebsd.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014-2016 Eric Lagergren
2 | // Use of this source code is governed by the GPL v3 or later.
3 |
4 | package main
5 |
--------------------------------------------------------------------------------
/uname/uname_linux.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014-2016 Eric Lagergren
2 | // Use of this source code is governed by the GPL v3 or later.
3 |
4 | package main
5 |
6 | import "golang.org/x/sys/unix"
7 |
8 | type info struct {
9 | sysname string
10 | nodename string
11 | release string
12 | version string
13 | machine string
14 | }
15 |
16 | func intToString(a [65]int8) string {
17 | var (
18 | tmp [65]byte
19 | i int
20 | )
21 | for i = 0; a[i] != 0; i++ {
22 | tmp[i] = byte(a[i])
23 | }
24 | return string(tmp[:i])
25 | }
26 |
27 | func genInfo() (info, error) {
28 | var name unix.Utsname
29 | err := unix.Uname(&name)
30 | return info{
31 | sysname: intToString(name.Sysname),
32 | nodename: intToString(name.Nodename),
33 | release: intToString(name.Release),
34 | version: intToString(name.Version),
35 | machine: intToString(name.Machine),
36 | }, err
37 | }
38 |
--------------------------------------------------------------------------------
/uname/uname_windows.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014-2016 Eric Lagergren
2 | // Use of this source code is governed by the GPL v3 or later.
3 |
4 | package main
5 |
--------------------------------------------------------------------------------
/unexpand/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/unexpand/.gitignore
--------------------------------------------------------------------------------
/unexpand/unexpand.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/uniq/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/uniq/.gitignore
--------------------------------------------------------------------------------
/uniq/uniq.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/unlink/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/unlink/.gitignore
--------------------------------------------------------------------------------
/unlink/unlink.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/uptime/.gitignore:
--------------------------------------------------------------------------------
1 | untitled.*
2 |
--------------------------------------------------------------------------------
/uptime/uptime.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "os"
6 |
7 | "github.com/EricLagergren/go-gnulib/utmp"
8 |
9 | flag "github.com/ogier/pflag"
10 | )
11 |
12 | func main() {
13 | flag.Usage = func() {
14 | // This is a little weird because I want to insert the correct
15 | // UTMP/WTMP file names into the Help output, but usually my
16 | // Help constants are raw string literals, so I had to
17 | // break it up into a couple chunks and move around some formatting.
18 | fmt.Fprintf(os.Stderr, "%s %s. %s %s",
19 | Help1, utmp.UtmpFile, utmp.WtmpFile, Help2)
20 | os.Exit(1)
21 | }
22 | flag.Parse()
23 |
24 | if *version {
25 | fmt.Printf("%s\n", Version)
26 | os.Exit(0)
27 | }
28 |
29 | switch flag.NArg() {
30 | case 0:
31 | uptime(utmp.UtmpFile, utmp.CheckPIDs)
32 | case 1:
33 | uptime(flag.Arg(0), 0)
34 | default:
35 | fatal.Fatalf("extra operand %s\n", flag.Arg(1))
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/uptime/uptime_freebsd.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "io"
7 | "log"
8 | "math"
9 | "os"
10 | "strconv"
11 | "syscall"
12 | "time"
13 |
14 | "github.com/EricLagergren/go-gnulib/stdlib"
15 | "github.com/EricLagergren/go-gnulib/utmp"
16 |
17 | flag "github.com/ogier/pflag"
18 | )
19 |
20 | const (
21 | Help1 = `Usage: uptime [OPTION]... [FILE]
22 | Print the current time, the length of time the system has been up,
23 | the number of users on the system, and the average number of jobs
24 | in the run queue over the last 1, 5 and 15 minutes. Processes in
25 | an uninterruptible sleep state also contribute to the load average.
26 | If FILE is not specified, use`
27 | Help2 = `as FILE is common.
28 |
29 | --help display this help and exit
30 | --version output version information and exit
31 |
32 | Report wc bugs to ericscottlagergren@gmail.com
33 | Go coreutils home page:
34 | `
35 |
36 | Version = `
37 | uptime (Go coreutils) 1.0
38 | Copyright (C) 2015 Eric Lagergren
39 | License GPLv3+: GNU GPL version 3 or later .
40 | This is free software: you are free to change and redistribute it.
41 | There is NO WARRANTY, to the extent permitted by law.
42 | `
43 |
44 | delim = " "
45 | )
46 |
47 | var (
48 | version = flag.BoolP("version", "v", false, "")
49 |
50 | // fatal = log.New(os.Stderr, "", log.Lshortfile)
51 | fatal = log.New(os.Stderr, "", 0)
52 | )
53 |
54 | func printUptime(us []utmp.Utmp) {
55 |
56 | var (
57 | bootTime int32
58 | entries int64
59 | now utmp.TimeVal
60 |
61 | days, hours, mins int
62 | uptime float64
63 | )
64 |
65 | request := "kern.boottime"
66 | secs, err := syscall.SysctlUint32(request)
67 | if err != nil {
68 | panic(err)
69 | }
70 | secs = float64(secs)
71 |
72 | if 0 <= secs || secs < math.MaxFloat64 {
73 | uptime = secs
74 | } else {
75 | uptime = -1
76 | }
77 |
78 | for _, v := range us {
79 |
80 | if v.IsUserProcess() {
81 | entries++
82 | }
83 |
84 | if v.Type == utmp.BootTime {
85 | bootTime = v.Time.Sec
86 | }
87 | }
88 |
89 | now.GetTimeOfDay()
90 | if uptime == 0 {
91 | if bootTime == 0 {
92 | fatal.Fatalln("couldn't get boot time")
93 | }
94 |
95 | uptime = float64(now.Sec - bootTime)
96 | }
97 |
98 | days = int(uptime) / 86400
99 | hours = (int(uptime) - (days * 86400)) / 3600
100 | mins = (int(uptime) - (days * 86400) - (hours * 3600)) / 60
101 |
102 | fmt.Print(time.Now().Local().Format(" 15:04pm "))
103 |
104 | if uptime == -1 {
105 | fmt.Print("up ???? days ??:??, ")
106 | } else {
107 | if 0 < days {
108 | if days > 1 {
109 | fmt.Printf("up %d days %2d:%02d, ", days, hours, mins)
110 | } else {
111 | fmt.Printf("up %d day %2d:%02d, ", days, hours, mins)
112 | }
113 | } else {
114 | fmt.Printf("up %2d:%02d, ", hours, mins)
115 | }
116 | }
117 |
118 | if len(us) > 1 || len(us) == 0 {
119 | fmt.Printf("%d users", entries)
120 | } else {
121 | fmt.Printf("%d user", entries)
122 | }
123 |
124 | var avg [3]float64
125 | loads := stdlib.GetLoadAvg(&avg)
126 |
127 | if loads == -1 {
128 | fmt.Printf("%s", "\n")
129 | } else {
130 | if loads > 0 {
131 | fmt.Printf(", load average: %.2f", avg[0])
132 | }
133 |
134 | if loads > 1 {
135 | fmt.Printf(", %.2f", avg[1])
136 | }
137 |
138 | if loads > 2 {
139 | fmt.Printf(", %.2f", avg[2])
140 | }
141 |
142 | if loads > 0 {
143 | fmt.Printf("%s", "\n")
144 | }
145 | }
146 | }
147 |
148 | func uptime(fname string, opts int) {
149 | var u utmp.Utmpx
150 |
151 | const usize = int64(unsafe.Sizeof(u))
152 | entries := uint64(0)
153 |
154 | size := stat.Size()
155 | us := make([]utmp.Utmpx, size/usize)
156 |
157 | stat, err := os.Stat(fname)
158 | if err != nil {
159 | fatal.Fatalln(err)
160 | }
161 |
162 | i := 0
163 | for {
164 | u = utmp.GetUtxEnt()
165 | if u == nil {
166 | break
167 | }
168 |
169 | if len(*us) <= int(i) {
170 | *us = append(*us, u)
171 | } else {
172 | (*us)[i] = u
173 | }
174 | i++
175 | }
176 |
177 | printUptime(us)
178 | }
179 |
--------------------------------------------------------------------------------
/uptime/uptime_linux.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "io"
7 | "log"
8 | "math"
9 | "os"
10 | "strconv"
11 | "time"
12 |
13 | "github.com/EricLagergren/go-gnulib/stdlib"
14 | "github.com/EricLagergren/go-gnulib/utmp"
15 |
16 | flag "github.com/ogier/pflag"
17 | )
18 |
19 | const (
20 | Help1 = `Usage: uptime [OPTION]... [FILE]
21 | Print the current time, the length of time the system has been up,
22 | the number of users on the system, and the average number of jobs
23 | in the run queue over the last 1, 5 and 15 minutes. Processes in
24 | an uninterruptible sleep state also contribute to the load average.
25 | If FILE is not specified, use`
26 | Help2 = `as FILE is common.
27 |
28 | --help display this help and exit
29 | --version output version information and exit
30 |
31 | Report wc bugs to ericscottlagergren@gmail.com
32 | Go coreutils home page:
33 | `
34 |
35 | Version = `
36 | uptime (Go coreutils) 1.0
37 | Copyright (C) 2015 Eric Lagergren
38 | License GPLv3+: GNU GPL version 3 or later .
39 | This is free software: you are free to change and redistribute it.
40 | There is NO WARRANTY, to the extent permitted by law.
41 | `
42 |
43 | delim = " "
44 | )
45 |
46 | var (
47 | version = flag.BoolP("version", "v", false, "")
48 |
49 | // fatal = log.New(os.Stderr, "", log.Lshortfile)
50 | fatal = log.New(os.Stderr, "", 0)
51 | )
52 |
53 | func printUptime(us []*utmp.Utmp) {
54 |
55 | var (
56 | bootTime int32
57 | entries int64
58 | now utmp.TimeVal
59 |
60 | days, hours, mins int
61 | uptime float64
62 | )
63 |
64 | file, err := os.Open("/proc/uptime")
65 | if err != nil {
66 | fatal.Fatalln(err)
67 | }
68 | defer file.Close()
69 |
70 | buf := make([]byte, utmp.BufSiz)
71 |
72 | n, err := file.Read(buf)
73 | if err != nil && err != io.EOF {
74 | fatal.Fatalln(err)
75 | }
76 |
77 | // /proc/uptime's output is in the format of "%f %f\n"
78 | // The first space in the buffer will be the end of the first number.
79 | line := string(buf[:bytes.IndexByte(buf[:n], ' ')])
80 |
81 | secs, err := strconv.ParseFloat(line, 64)
82 | if err != nil {
83 | fatal.Fatalln(err)
84 | }
85 |
86 | uptime = -1
87 | if 0 <= secs || secs < math.MaxFloat64 {
88 | uptime = secs
89 | }
90 |
91 | for _, v := range us {
92 |
93 | if v.IsUserProcess() {
94 | entries++
95 | }
96 |
97 | if v.TypeEquals(utmp.BootTime) {
98 | bootTime = v.Time.Sec
99 | }
100 | }
101 |
102 | now.GetTimeOfDay()
103 | if uptime == 0 {
104 | if bootTime == 0 {
105 | fatal.Fatalln("can't get boot time")
106 | }
107 |
108 | uptime = float64(now.Sec - bootTime)
109 | }
110 |
111 | days = int(uptime) / 86400
112 | hours = (int(uptime) - (days * 86400)) / 3600
113 | mins = (int(uptime) - (days * 86400) - (hours * 3600)) / 60
114 |
115 | os.Stdout.WriteString(time.Now().Local().Format(" 15:04pm "))
116 |
117 | if uptime == -1 {
118 | os.Stdout.WriteString("up ???? days ??:??, ")
119 | } else {
120 | if 0 < days {
121 | fmt.Printf(GetPlural("up %d day %2d:%02d, ",
122 | "up %d days %2d:%02d, ", uint64(days)), days, hours, mins)
123 | } else {
124 | fmt.Printf("up %2d:%02d, ", hours, mins)
125 | }
126 | }
127 |
128 | fmt.Printf(GetPlural("%d user", "%d users", uint64(entries)), entries)
129 |
130 | var avg [3]float64
131 | loads := stdlib.GetLoadAvg(&avg)
132 |
133 | if loads == -1 {
134 | fmt.Printf("%s", "\n")
135 | } else {
136 | if loads > 0 {
137 | fmt.Printf(", load average: %.2f", avg[0])
138 | }
139 |
140 | if loads > 1 {
141 | fmt.Printf(", %.2f", avg[1])
142 | }
143 |
144 | if loads > 2 {
145 | fmt.Printf(", %.2f", avg[2])
146 | }
147 |
148 | if loads > 0 {
149 | fmt.Printf("%s", "\n")
150 | }
151 | }
152 | }
153 |
154 | func uptime(fname string, opts int) {
155 | entries := uint64(0)
156 | us, err := utmp.ReadUtmp(fname, &entries, 0, opts)
157 | if err != nil {
158 | fatal.Fatalln(err)
159 | }
160 |
161 | printUptime(us)
162 | }
163 |
164 | func selectPlural(n uint64) uint64 {
165 | const pluralReducer = 1000000
166 | if n <= math.MaxUint64 {
167 | return n
168 | }
169 | return n%pluralReducer + pluralReducer
170 | }
171 |
172 | func GetPlural(msg1, msg2 string, n uint64) string {
173 | if n == 1 {
174 | return msg1
175 | }
176 | return msg2
177 | }
178 |
--------------------------------------------------------------------------------
/users/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/users/.gitignore
--------------------------------------------------------------------------------
/users/users.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | "os"
7 | "sort"
8 |
9 | "github.com/EricLagergren/go-coreutils/internal/flag"
10 |
11 | "github.com/EricLagergren/go-gnulib/utmp"
12 | )
13 |
14 | func main() {
15 | flag.Usage = func() {
16 | fmt.Printf("Usage: %s [OPTION]... [FILE]\n", flag.Program)
17 | fmt.Printf(`Output who is currently logged in according to FILE.
18 | If FILE is not specified, use %s. %s as FILE is common.
19 |
20 | `,
21 | utmp.UtmpxFile, utmp.Wtmpxfile)
22 | flag.PrintDefaults()
23 | fmt.Printf(`
24 | Report %s bugs to ericscottlagergren@gmail.com
25 | Go coreutils home page:
26 | `, flag.Program)
27 | os.Exit(0)
28 | }
29 |
30 | flag.Parse()
31 |
32 | switch flag.NArg() {
33 | case 0:
34 | users(utmp.UtmpxFile, utmp.CheckPIDs)
35 | case 1:
36 | users(flag.Arg(0), 0)
37 | default:
38 | log.Fatalf("extra operand(s) %v", flag.Args()[1:])
39 | }
40 |
41 | }
42 |
43 | func users(file string, opts int) {
44 | utmps, err := utmp.ReadUtmp(utmp.UtmpxFile, utmp.CheckPIDs)
45 | if err != nil {
46 | log.Fatalln(err)
47 | }
48 |
49 | var names []string
50 | for _, u := range utmps {
51 | if u.IsUserProcess() {
52 | names = append(names, u.ExtractTrimmedName())
53 | }
54 | }
55 | sort.Strings(names)
56 | for _, name := range names {
57 | fmt.Println(name)
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/vdir/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/vdir/.gitignore
--------------------------------------------------------------------------------
/vdir/vdir.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {}
4 |
--------------------------------------------------------------------------------
/wc/_testdata/coreutils_man_en.txt:
--------------------------------------------------------------------------------
1 | Next: sum invocation, Up: Summarizing files
2 |
3 | 6.1 wc: Print newline, word, and byte counts
4 |
5 | wc counts the number of bytes, characters, whitespace-separated words, and newlines in each given file, or standard input if none are given or for a file of ‘-’. Synopsis:
6 |
7 | wc [option]... [file]...
8 | wc prints one line of counts for each file, and if the file was given as an argument, it prints the file name following the counts. If more than one file is given, wc prints a final line containing the cumulative counts, with the file name total. The counts are printed in this order: newlines, words, characters, bytes, maximum line length. Each count is printed right-justified in a field with at least one space between fields so that the numbers and file names normally line up nicely in columns. The width of the count fields varies depending on the inputs, so you should not depend on a particular field width. However, as a GNU extension, if only one count is printed, it is guaranteed to be printed without leading spaces.
9 |
10 | By default, wc prints three counts: the newline, words, and byte counts. Options can specify that only certain counts be printed. Options do not undo others previously given, so
11 |
12 | wc --bytes --words
13 | prints both the byte counts and the word counts.
14 |
15 | With the --max-line-length option, wc prints the length of the longest line per file, and if there is more than one file it prints the maximum (not the sum) of those lengths. The line lengths here are measured in screen columns, according to the current locale and assuming tab positions in every 8th column.
16 |
17 | The program accepts the following options. Also see Common options.
18 |
19 | ‘-c’
20 | ‘--bytes’
21 | Print only the byte counts.
22 | ‘-m’
23 | ‘--chars’
24 | Print only the character counts.
25 | ‘-w’
26 | ‘--words’
27 | Print only the word counts.
28 | ‘-l’
29 | ‘--lines’
30 | Print only the newline counts.
31 | ‘-L’
32 | ‘--max-line-length’
33 | Print only the maximum line lengths.
34 | ‘--files0-from=file’
35 | Disallow processing files named on the command line, and instead process those named in file file; each name being terminated by a zero byte (ASCII NUL). This is useful when the list of file names is so long that it may exceed a command line length limitation. In such cases, running wc via xargs is undesirable because it splits the list into pieces and makes wc print a total for each sublist rather than for the entire list. One way to produce a list of ASCII NUL terminated file names is with GNU find, using its -print0 predicate. If file is ‘-’ then the ASCII NUL terminated file names are read from standard input.
36 | For example, to find the length of the longest line in any .c or .h file in the current hierarchy, do this:
37 |
38 | find . -name '*.[ch]' -print0 |
39 | wc -L --files0-from=- | tail -n1
40 | An exit status of zero indicates success, and a nonzero value indicates failure.
--------------------------------------------------------------------------------
/wc/_testdata/file_list.txt:
--------------------------------------------------------------------------------
1 | ./test_files/file_list.txt ./test_files/spaces_en.txt ./test_files/dict_en.txt ./test_files/lang_ru.txt ./test_files/coreutils_man_en.txt
--------------------------------------------------------------------------------
/wc/_testdata/spaces_en.txt:
--------------------------------------------------------------------------------
1 | Hello, world!
2 | This is a test file to see if1 my wc utilit y
3 |
4 | is
5 | able
6 |
7 | to det
8 | ermine the correct counts for different fi
9 | les.
10 |
--------------------------------------------------------------------------------
/wc/cmd.go:
--------------------------------------------------------------------------------
1 | package wc
2 |
3 | import (
4 | "bufio"
5 | "bytes"
6 | "errors"
7 | "fmt"
8 | "io"
9 | "math"
10 | "math/bits"
11 | "os"
12 | "unicode"
13 |
14 | coreutils "github.com/ericlagergren/go-coreutils"
15 | flag "github.com/spf13/pflag"
16 | )
17 |
18 | func init() {
19 | coreutils.Register("wc", run)
20 | }
21 |
22 | func newCommand() *cmd {
23 | var c cmd
24 | c.f.BoolVarP(&c.lines, "lines", "l", false, "print the newline counts")
25 | c.f.BoolVarP(&c.words, "words", "w", false, "print the word counts")
26 | c.f.BoolVarP(&c.chars, "chars", "m", false, "print the character counts")
27 | c.f.BoolVarP(&c.bytes, "bytes", "c", false, "print the byte counts")
28 | c.f.BoolVarP(&c.maxLength, "max-line-length", "L", false, "print the length of the longest line")
29 | c.f.StringVar(&c.filesFrom, "files0-from", "", `read input from the files specified by
30 | NUL-terminated names in file F;
31 | If F is - then read names from standard input`)
32 | c.f.Int64VarP(&c.tabWidth, "tab", "t", 8, "change the tab width")
33 | c.f.BoolVarP(&c.unicode, "unicode-version", "u", false, "display unicode version and exit")
34 | c.f.BoolVar(&c.version, "version", false, "display version information and exit")
35 | return &c
36 | }
37 |
38 | type cmd struct {
39 | f flag.FlagSet
40 | lines, words, chars, bytes, maxLength bool
41 | filesFrom string
42 | tabWidth int64
43 | unicode bool
44 | version bool
45 | }
46 |
47 | var errMixedArgs = errors.New("file operands cannot be combined with --files0-from")
48 |
49 | func run(ctx coreutils.Context, args ...string) error {
50 | c := newCommand()
51 |
52 | if err := c.f.Parse(args); err != nil {
53 | return err
54 | }
55 |
56 | if c.version {
57 | fmt.Fprintf(ctx.Stdout, "wc (go-coreutils) 1.0")
58 | return nil
59 | }
60 |
61 | if c.unicode {
62 | fmt.Fprintf(ctx.Stdout, "Unicode version: %s\n", unicode.Version)
63 | return nil
64 | }
65 |
66 | var opts uint8
67 | if c.lines {
68 | opts |= Lines
69 | }
70 | if c.words {
71 | opts |= Words
72 | }
73 | if c.chars {
74 | opts |= Chars
75 | }
76 | if c.bytes {
77 | opts |= Bytes
78 | }
79 | if c.maxLength {
80 | opts |= MaxLength
81 | }
82 |
83 | if opts == 0 {
84 | opts = Lines | Words | Bytes
85 | }
86 |
87 | ctr := NewCounter(opts)
88 | ctr.TabWidth = c.tabWidth
89 |
90 | var s interface {
91 | Scan() bool
92 | Text() string
93 | }
94 | var hint int // To keep from allocating, if possible.
95 | if c.filesFrom == "" {
96 | if c.f.NArg() == 0 {
97 | res, err := ctr.Count(ctx.Stdin)
98 | if err != nil {
99 | fmt.Fprintln(ctx.Stderr, err)
100 | return err
101 | }
102 | width := 7
103 | if opts&(opts-1) == 0 { // power of 2, so 1 argument set.
104 | width = 1
105 | }
106 | writeCounts(ctx.Stdout, width, opts, res, "")
107 | return nil
108 | }
109 | s = &sliceScanner{s: c.f.Args()}
110 | hint = c.f.NArg()
111 | } else {
112 | if c.f.NArg() > 0 {
113 | fmt.Fprintln(ctx.Stderr, errMixedArgs)
114 | return errMixedArgs
115 | }
116 | file, err := os.Open(c.filesFrom)
117 | if err != nil {
118 | fmt.Fprintln(ctx.Stderr, err)
119 | return err
120 | }
121 | defer file.Close()
122 | s = bufio.NewScanner(file)
123 | s.(*bufio.Scanner).Split(filesFromSplit)
124 | }
125 |
126 | var (
127 | results = make([]Results, 0, hint)
128 | names = make([]string, 0, hint)
129 | total Results
130 | maxBytes int64
131 | minWidth = 1
132 | )
133 |
134 | for s.Scan() {
135 | fname := s.Text()
136 |
137 | file, err := os.Open(fname)
138 | if err != nil {
139 | fmt.Fprintln(ctx.Stderr, err)
140 | return err
141 | }
142 |
143 | stat, err := file.Stat()
144 | if err != nil || (err == nil && !stat.Mode().IsRegular()) {
145 | minWidth = 7
146 | }
147 |
148 | res, err := ctr.Count(file)
149 | if err != nil {
150 | fmt.Fprintln(ctx.Stderr, err)
151 | return err
152 | }
153 | results = append(results, res)
154 | names = append(names, fname)
155 |
156 | total.Lines += res.Lines
157 | total.Words += res.Words
158 | total.Chars += res.Chars
159 | total.Bytes += res.Bytes
160 |
161 | if res.Bytes > maxBytes {
162 | maxBytes = res.Bytes
163 | }
164 |
165 | if res.MaxLength > total.MaxLength {
166 | total.MaxLength = res.MaxLength
167 | }
168 |
169 | if err := file.Close(); err != nil {
170 | fmt.Fprintln(ctx.Stderr, err)
171 | return err
172 | }
173 | }
174 |
175 | // Fast integer log 10. The call to math.Pow and subsequent comparison can
176 | // be dropped in favor of simply adding +1 to width if it's alright for the
177 | // result to be +1 too large for some numbers.
178 | width := int((bits.Len64(uint64(maxBytes)) * 1233) >> 12)
179 | if int64(math.Pow10(width)) < maxBytes {
180 | width++
181 | }
182 | if width < minWidth {
183 | width = minWidth
184 | }
185 | for i, r := range results {
186 | writeCounts(ctx.Stdout, width, opts, r, names[i])
187 | }
188 | if len(results) > 1 {
189 | writeCounts(ctx.Stdout, width, opts, total, "total")
190 | }
191 | return nil
192 | }
193 |
194 | type sliceScanner struct{ s []string }
195 |
196 | func (s *sliceScanner) Scan() bool { return len(s.s) > 0 }
197 | func (s *sliceScanner) Text() string {
198 | t := s.s[0]
199 | s.s = s.s[1:]
200 | return t
201 | }
202 |
203 | func filesFromSplit(data []byte, atEOF bool) (adv int, token []byte, err error) {
204 | if atEOF && len(data) == 0 {
205 | return 0, nil, nil
206 | }
207 | if i := bytes.IndexByte(data, 0x00); i >= 0 {
208 | return i + 1, dropNull(data[0:i]), nil
209 | }
210 | if atEOF {
211 | return len(data), dropNull(data), nil
212 | }
213 | return 0, nil, nil
214 | }
215 |
216 | func dropNull(data []byte) []byte {
217 | if len(data) > 0 && data[len(data)-1] == 0x00 {
218 | return data[0 : len(data)-1]
219 | }
220 | return data
221 | }
222 |
223 | func writeCounts(w io.Writer, width int, opts uint8, r Results, fname string) {
224 | const fmtSpInt = " %*d"
225 |
226 | fmtInt := "%*d"
227 | if opts&Lines != 0 {
228 | fmt.Fprintf(w, fmtInt, width, r.Lines)
229 | fmtInt = fmtSpInt
230 | }
231 | if opts&Words != 0 {
232 | fmt.Fprintf(w, fmtInt, width, r.Words)
233 | fmtInt = fmtSpInt
234 | }
235 | if opts&Chars != 0 {
236 | fmt.Fprintf(w, fmtInt, width, r.Chars)
237 | fmtInt = fmtSpInt
238 | }
239 | if opts&Bytes != 0 {
240 | fmt.Fprintf(w, fmtInt, width, r.Bytes)
241 | fmtInt = fmtSpInt
242 | }
243 | if opts&MaxLength != 0 {
244 | fmt.Fprintf(w, fmtInt, width, r.MaxLength)
245 | }
246 | fmt.Fprintf(w, " %s\n", fname)
247 | }
248 |
--------------------------------------------------------------------------------
/wc/internal/sys/fadv.go:
--------------------------------------------------------------------------------
1 | // +build !linux,!freebsd
2 |
3 | package sys
4 |
5 | func Fadvise(_ int) error { return nil }
6 |
--------------------------------------------------------------------------------
/wc/internal/sys/fadv_unix.go:
--------------------------------------------------------------------------------
1 | // +build linux freebsd
2 |
3 | package sys
4 |
5 | import "golang.org/x/sys/unix"
6 |
7 | func Fadvise(fd int) error {
8 | return unix.Fadvise(fd, 0, 0, unix.FADV_SEQUENTIAL)
9 | }
10 |
--------------------------------------------------------------------------------
/wc/wc.go:
--------------------------------------------------------------------------------
1 | package wc
2 |
3 | import (
4 | "bytes"
5 | "io"
6 | "os"
7 | "unicode"
8 | "unicode/utf8"
9 |
10 | "github.com/ericlagergren/go-coreutils/wc/internal/sys"
11 | )
12 |
13 | type Results struct {
14 | Lines int64
15 | Words int64
16 | Chars int64
17 | Bytes int64
18 | MaxLength int64
19 | }
20 |
21 | type Counter struct {
22 | TabWidth int64
23 |
24 | buf [1 << 17]byte
25 | opts uint8
26 | }
27 |
28 | const (
29 | Lines = 1 << iota // count lines
30 | Words // count words
31 | Chars // count chars
32 | Bytes // count bytes
33 | MaxLength // find max line length
34 | )
35 |
36 | func NewCounter(opts uint8) *Counter {
37 | return &Counter{opts: opts, TabWidth: 8}
38 | }
39 |
40 | func (c *Counter) read(r io.Reader) (int64, error) {
41 | n, err := r.Read(c.buf[:])
42 | if err != nil {
43 | return 0, err
44 | }
45 | return int64(n), nil
46 | }
47 |
48 | var newLine = []byte{'\n'}
49 |
50 | func (c *Counter) Count(r io.Reader) (res Results, err error) {
51 | if file, ok := r.(*os.File); ok {
52 | if c.opts == Bytes {
53 | if n, ok := statSize(file); ok {
54 | return Results{Bytes: n}, nil
55 | }
56 | }
57 | sys.Fadvise(int(file.Fd()))
58 | }
59 | switch c.opts {
60 | case Bytes:
61 | for {
62 | n, err := c.read(r)
63 | res.Bytes += n
64 | if err != nil {
65 | if err == io.EOF {
66 | return res, nil
67 | }
68 | return res, err
69 | }
70 | }
71 | case Lines, Lines | Bytes:
72 | for {
73 | n, err := c.read(r)
74 | res.Bytes += n
75 | res.Lines += int64(bytes.Count(c.buf[:n], newLine))
76 | if err != nil {
77 | if err == io.EOF {
78 | return res, nil
79 | }
80 | return res, err
81 | }
82 | }
83 | default:
84 | return c.countComplicated(r)
85 | }
86 | }
87 |
88 | func (c *Counter) countComplicated(r io.Reader) (res Results, err error) {
89 | var (
90 | pos int64
91 | inWord bool
92 | )
93 |
94 | for {
95 | n, err := c.read(r)
96 | res.Bytes += n
97 | if err != nil {
98 | if err == io.EOF {
99 | break
100 | }
101 | return res, err
102 | }
103 |
104 | for bp := 0; int64(bp) < n; {
105 | r, s := utf8.DecodeRune(c.buf[bp:])
106 | switch r {
107 | case '\n':
108 | res.Lines++
109 | fallthrough
110 | case '\r', '\f':
111 | if pos > res.MaxLength {
112 | res.MaxLength = pos
113 | }
114 | pos = 0
115 | if inWord {
116 | res.Words++
117 | }
118 | inWord = false
119 | case '\t':
120 | pos += c.TabWidth - (pos % c.TabWidth)
121 | if inWord {
122 | res.Words++
123 | }
124 | inWord = false
125 | case ' ':
126 | pos++
127 | fallthrough
128 | case '\v':
129 | if inWord {
130 | res.Words++
131 | }
132 | inWord = false
133 | default:
134 | if !unicode.IsPrint(r) {
135 | break
136 | }
137 |
138 | pos++
139 | if unicode.IsSpace(r) {
140 | if inWord {
141 | res.Words++
142 | }
143 | inWord = false
144 | } else {
145 | inWord = true
146 | }
147 | }
148 | res.Chars++
149 | bp += s
150 | }
151 | }
152 | if pos > res.MaxLength {
153 | res.MaxLength = pos
154 | }
155 | if inWord {
156 | res.Words++
157 | }
158 | return res, nil
159 | }
160 |
161 | func statSize(file *os.File) (n int64, ok bool) {
162 | stat, err := file.Stat()
163 | if err != nil {
164 | return 0, false
165 | }
166 |
167 | const badMode = os.ModeDir | os.ModeNamedPipe | os.ModeSocket
168 | if stat.Mode()&badMode != 0 {
169 | return 0, false
170 | }
171 |
172 | // NOTE(eric): GNU's wc says we should seek 1 block size from EOF because it
173 | // works better on proc-like systems. I like the idea, but I don't want this
174 | // code to be under the GPL.
175 |
176 | return stat.Size(), true
177 | }
178 |
--------------------------------------------------------------------------------
/wc/wc_test.go:
--------------------------------------------------------------------------------
1 | // +build ignore
2 |
3 | package wc
4 |
5 | import (
6 | "bytes"
7 | "io"
8 | "os"
9 | "os/exec"
10 | "testing"
11 | )
12 |
13 | var flist = []string{
14 | "_testdata/lang_ru.txt",
15 | "_testdata/dict_en.txt",
16 | "_testdata/spaces_en.txt",
17 | "_testdata/coreutils_man_en.txt",
18 | }
19 |
20 | var buf bytes.Buffer
21 |
22 | func TestWC(t *testing.T) {
23 |
24 | fs := getFileStatus(flist)
25 | numberWidth = findNumberWidth(fs)
26 |
27 | *printLines = true
28 | *printWords = true
29 | *printChars = true
30 | *printBytes = true
31 | *printLineLength = true
32 |
33 | // set up our capture of stdout
34 | stdout := os.Stdout
35 | r, w, err := os.Pipe()
36 | if err != nil {
37 | t.Fatal(err)
38 | }
39 | os.Stdout = w
40 |
41 | // now output stdout
42 | for i, file := range flist {
43 | wcFile(file, fs[i])
44 | }
45 | writeCounts(totalLines, totalWords,
46 | totalChars, totalBytes, maxLineLength, "total")
47 |
48 | // capture the stdout
49 | outC := make(chan string)
50 | go func() {
51 | var b bytes.Buffer
52 | _, err := io.Copy(&b, r)
53 | r.Close()
54 | if err != nil {
55 | t.Fatal(err)
56 | }
57 | outC <- b.String()
58 | }()
59 |
60 | // now get stdout of native wc
61 | wc := exec.Command("wc", "-lwmcL",
62 | flist[0], flist[1], flist[2], flist[3])
63 |
64 | b, err := wc.Output()
65 | if err != nil {
66 | t.Fatal(err)
67 | }
68 | buf.Write(b)
69 |
70 | // stop capturing of stdout
71 | w.Close()
72 | os.Stdout = stdout
73 | out := <-outC
74 |
75 | // check strings
76 | if out != buf.String() {
77 | t.Fatalf("Got:\n%s\n\nExpected:\n%s\n", out, buf.String())
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/who/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/who/.gitignore
--------------------------------------------------------------------------------
/whoami/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/whoami/.gitignore
--------------------------------------------------------------------------------
/whoami/whoami:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ericlagergren/go-coreutils/70e5762048c92a7ec35b97bac8bcb38a0d00f413/whoami/whoami
--------------------------------------------------------------------------------
/whoami/whoami.go:
--------------------------------------------------------------------------------
1 | /*
2 | Go whoami -- print effective userid
3 |
4 | Copyright (c) 2015 Eric Lagergren
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | /* Equivalent to 'id -un'. */
21 | /* Written by Eric Lagergren and mattn */
22 |
23 | package main
24 |
25 | import (
26 | "fmt"
27 | "log"
28 | "os"
29 |
30 | flag "github.com/ogier/pflag"
31 | )
32 |
33 | const (
34 | Help = `Usage: whoami [OPTION]...
35 | Print the user name associated with the current effective user ID.
36 | Same as id -un.
37 |
38 | --help display this help and exit
39 | --version output version information and exit
40 |
41 | Report whoami bugs to ericscottlagergren@gmail.com
42 | Go coreutils home page: `
43 |
44 | Version = `whoami (Go coreutils) 1.0
45 | Copyright (C) 2015 Eric Lagergren
46 | License GPLv3+: GNU GPL version 3 or later .
47 | This is free software: you are free to change and redistribute it.
48 | There is NO WARRANTY, to the extent permitted by law.
49 |
50 | Written by Eric Lagergren`
51 | )
52 |
53 | var (
54 | version = flag.BoolP("version", "v", false, "")
55 | fatal = log.New(os.Stderr, "", 0)
56 | )
57 |
58 | func main() {
59 | flag.Usage = func() {
60 | fmt.Fprintf(os.Stderr, "%s", Help)
61 | os.Exit(0)
62 | }
63 | flag.Parse()
64 |
65 | if *version {
66 | fmt.Fprintf(os.Stderr, "%s", Version)
67 | os.Exit(0)
68 | }
69 |
70 | // This function call *should* be inlined on both
71 | // Windows and Unix
72 | fmt.Println(getUser())
73 | }
74 |
--------------------------------------------------------------------------------
/whoami/whoami_test.go:
--------------------------------------------------------------------------------
1 | // +build !windows
2 |
3 | package main
4 |
5 | import (
6 | "os"
7 | "os/exec"
8 | "os/user"
9 | "strconv"
10 | "testing"
11 | )
12 |
13 | func TestWhoami(t *testing.T) {
14 |
15 | cmd := exec.Command("whoami")
16 | b, err := cmd.Output()
17 | if err != nil {
18 | t.Fatalf("%s\n", err.Error())
19 | }
20 |
21 | uid := strconv.Itoa(os.Geteuid())
22 | u, err := user.LookupId(uid)
23 | if err != nil {
24 | t.Fatalf("%s\n", err.Error())
25 | }
26 |
27 | if string(b[:len(b)-1]) != u.Username {
28 | t.Errorf("got: %q, want: %q", b, u.Username)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/whoami/whoami_unix.go:
--------------------------------------------------------------------------------
1 | // +build !windows
2 |
3 | /*
4 | Go whoami -- print effective userid
5 |
6 | Copyright (c) 2015 Eric Lagergren
7 |
8 | This program is free software: you can redistribute it and/or modify
9 | it under the terms of the GNU General Public License as published by
10 | the Free Software Foundation, either version 3 of the License, or
11 | (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have received a copy of the GNU General Public License
19 | along with this program. If not, see .
20 | */
21 |
22 | /* Equivalent to 'id -un'. */
23 | /* Written by Eric Lagergren */
24 |
25 | package main
26 |
27 | import (
28 | "os"
29 | "os/user"
30 | "strconv"
31 | )
32 |
33 | func getUser() string {
34 | uid := strconv.Itoa(os.Geteuid())
35 | u, err := user.LookupId(uid)
36 | if err != nil {
37 | fatal.Fatalf("cannot find name for user ID %s\n", uid)
38 | }
39 | return u.Username
40 | }
41 |
--------------------------------------------------------------------------------
/whoami/whoami_windows.go:
--------------------------------------------------------------------------------
1 | /*
2 | Go whoami -- print effective userid
3 |
4 | Copyright (c) 2015 Eric Lagergren
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | /* Equivalent to 'id -un'. */
21 | /* Written by Eric Lagergren and mattn */
22 |
23 | package main
24 |
25 | import "os/user"
26 |
27 | func getUser() string {
28 | u, err := user.Current()
29 | // TODO(eric): Have this output match whoami_unix.go
30 | if err != nil {
31 | fatal.Fatalln("cannot find name for current user")
32 | }
33 | return u.Username
34 | }
35 |
--------------------------------------------------------------------------------
/xxd/xxd_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "crypto/rand"
6 | "flag"
7 | "fmt"
8 | "io"
9 | "io/ioutil"
10 | "os/exec"
11 | "strings"
12 | "testing"
13 | "testing/quick"
14 | )
15 |
16 | var xxdFile = flag.String("xxdFile", "", "File to test against.")
17 |
18 | func TestXXD(t *testing.T) {
19 | if *xxdFile == "" {
20 | t.Skip("-xxdFile argument not given")
21 | }
22 | data, err := ioutil.ReadFile(*xxdFile)
23 | if err != nil {
24 | t.Fatal(err)
25 | }
26 | test := func(fn func(r io.Reader, w io.Writer, s string) error) func(n uint64) []string {
27 | return func(n uint64) []string {
28 | size := n % uint64(len(data))
29 | fmt.Printf("%d\n", size)
30 | var out bytes.Buffer
31 | if err := fn(&pathologicalReader{data[0:size]}, &out, ""); err != nil {
32 | return []string{err.Error()}
33 | }
34 | return strings.Split(out.String(), "\n")
35 | }
36 | }
37 | if err := quick.CheckEqual(test(xxd), test(xxdNative), nil); err != nil {
38 | cErr := err.(*quick.CheckEqualError)
39 | size := cErr.In[0].(uint64) % uint64(len(data))
40 | for i := range cErr.Out1[0].([]string) {
41 | got := cErr.Out1[0].([]string)[i]
42 | want := cErr.Out2[0].([]string)[i]
43 | if got != want {
44 | t.Errorf("size: %d\n\ngot : %s\nwant: %s\n", size, got, want)
45 | break
46 | }
47 | }
48 | }
49 | }
50 |
51 | type pathologicalReader struct {
52 | data []byte
53 | }
54 |
55 | func (p *pathologicalReader) Read(b []byte) (int, error) {
56 | n := len(b)
57 | if n > len(p.data) {
58 | n = len(p.data)
59 | }
60 | if n > 1 {
61 | n--
62 | }
63 | copy(b, p.data[0:n])
64 | p.data = p.data[n:]
65 | if len(p.data) == 0 {
66 | return n, io.EOF
67 | }
68 | return n, nil
69 | }
70 |
71 | func BenchmarkXXD(b *testing.B) {
72 | b.StopTimer()
73 | data := make([]byte, b.N)
74 | if _, err := io.ReadFull(rand.Reader, data); err != nil {
75 | b.Fatal(err)
76 | }
77 | buf := bytes.NewBuffer(data)
78 | b.StartTimer()
79 | if err := xxd(buf, ioutil.Discard, ""); err != nil {
80 | b.Fatal(err)
81 | }
82 | }
83 |
84 | func xxdNative(r io.Reader, w io.Writer, s string) error {
85 | xxd := exec.Command("xxd.bak", "-")
86 | xxd.Stdin = r
87 | xxd.Stdout = w
88 | xxd.Stderr = w
89 | return xxd.Run()
90 | }
91 |
92 | func main() {}
93 |
--------------------------------------------------------------------------------
/yes/yes.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "flag"
6 | "fmt"
7 | "os"
8 | )
9 |
10 | var version bool
11 |
12 | func main() {
13 | flag.BoolVar(&version, "version", false, "")
14 | flag.BoolVar(&version, "v", false, "")
15 |
16 | flag.Usage = func() {
17 | fmt.Printf(`Usage: yes [STRING]...
18 | or: yes OPTION
19 | Repeatedly output a line with all specified STRING(s), or 'y'.
20 |
21 | --help display this help and exit
22 | --version output version information and exit
23 |
24 | Report yes bugs to eric@ericlagergren.com
25 | Go coreutils home page:
26 | `)
27 | }
28 | flag.Parse()
29 |
30 | if version {
31 | fmt.Printf(`yes (Go coreutils) 1.1
32 | Copyright (C) 2015-2017 Eric Lagergren.
33 | License GPLv3+: GNU GPL version 3 or later .
34 | This is free software: you are free to change and redistribute it.
35 | There is NO WARRANTY, to the extent permitted by law.
36 | `)
37 | return
38 | }
39 |
40 | var buf []byte
41 | if flag.NArg() == 0 {
42 | buf = bytes.Repeat([]byte{'y', '\n'}, 4096)
43 | } else {
44 | for _, arg := range flag.Args() {
45 | buf = append(buf, arg...)
46 | buf = append(buf, ' ')
47 | }
48 | buf = append(buf, '\n')
49 | }
50 |
51 | for {
52 | os.Stdout.Write(buf)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------