1 // meta4ra -- Metalink 4.0 utilities
2 // Copyright (C) 2021-2024 Sergey Matveev <stargrave@stargrave.org>
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, version 3 of the License.
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.
13 // You should have received a copy of the GNU General Public License
14 // along with this program. If not, see <http://www.gnu.org/licenses/>.
33 func NewHasher(hashes string) (*Hasher, error) {
35 for _, hc := range strings.Split(hashes, ",") {
36 cols := strings.SplitN(hc, ":", 2)
37 name, cmdline := cols[0], cols[1]
38 if cmdline == BuiltinCmd {
39 newHash, exists := BuiltinHashes[name]
41 return nil, errors.New("no builtin hash: " + name)
43 b := &BuiltinHasher{h: newHash()}
44 h.Names = append(h.Names, name)
45 h.Ins = append(h.Ins, b)
46 h.Outs = append(h.Outs, b)
47 h.Cmds = append(h.Cmds, nil)
49 cmd := exec.Command("/bin/sh", "-e", "-c", cmdline)
50 in, err := cmd.StdinPipe()
54 out, err := cmd.StdoutPipe()
58 h.Names = append(h.Names, name)
59 h.Ins = append(h.Ins, in)
60 h.Outs = append(h.Outs, out)
61 h.Cmds = append(h.Cmds, cmd)
67 func (h *Hasher) Start() (err error) {
68 for _, cmd := range h.Cmds {
80 func (h *Hasher) Stop() {
81 for _, cmd := range h.Cmds {
82 if cmd == nil || cmd.Process == nil {
90 func (h *Hasher) Write(p []byte) (n int, rerr error) {
91 errs := make(chan error)
92 for _, in := range h.Ins {
93 go func(in io.WriteCloser) {
94 _, err := io.Copy(in, bytes.NewReader(p))
98 for i := 0; i < len(h.Names); i++ {
99 if err := <-errs; err != nil {
107 func (h *Hasher) Sums() (sums []Hash, err error) {
108 sums = make([]Hash, 0, len(h.Names))
109 for i, name := range h.Names {
110 if err = h.Ins[i].Close(); err != nil {
114 out, err = io.ReadAll(h.Outs[i])
118 if cmd := h.Cmds[i]; cmd != nil {
119 if err = h.Cmds[i].Wait(); err != nil {
123 cols := strings.Fields(strings.TrimSuffix(string(out), "\n"))
124 sums = append(sums, Hash{Type: name, Hash: cols[0]})