• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / mender-artifact / 1279561887

06 May 2024 07:18AM UTC coverage: 73.657% (-3.8%) from 77.428%
1279561887

Pull #605

gitlab-ci

alfrunes
chore(make): Refactor `coverage` target and disable pkcs11 on non-linux

Signed-off-by: Alf-Rune Siqveland <alf.rune@northern.tech>
Pull Request #605: Allow using mender-artifact without `cgo`

4 of 6 new or added lines in 1 file covered. (66.67%)

271 existing lines in 13 files now uncovered.

5469 of 7425 relevant lines covered (73.66%)

77.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.55
/artifact/checksum.go
1
// Copyright 2020 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14

15
package artifact
16

17
import (
18
        "bytes"
19
        "encoding/hex"
20
        "fmt"
21
        "hash"
22
        "io"
23
        "os"
24
        "strings"
25
        "syscall"
26

27
        "github.com/minio/sha256-simd"
28
        "github.com/pkg/errors"
29
)
30

31
type Checksum struct {
32
        w io.Writer // underlying writer
33
        h hash.Hash // writer calculated hash
34

35
        r io.Reader
36
        c []byte // reader pre-loaded checksum
37
}
38

39
func NewWriterChecksum(w io.Writer) *Checksum {
5✔
40
        if w == nil {
7✔
41
                return new(Checksum)
2✔
42
        }
2✔
43

44
        h := sha256.New()
3✔
45
        return &Checksum{
3✔
46
                w: io.MultiWriter(h, w),
3✔
47
                h: h,
3✔
48
        }
3✔
49
}
50

51
func NewReaderChecksum(r io.Reader, sum []byte) *Checksum {
10✔
52
        if r == nil {
12✔
53
                return new(Checksum)
2✔
54
        }
2✔
55

56
        h := sha256.New()
8✔
57
        return &Checksum{
8✔
58
                r: io.TeeReader(r, h),
8✔
59
                c: sum,
8✔
60
                h: h,
8✔
61
        }
8✔
62
}
63

64
func (c *Checksum) Write(p []byte) (int, error) {
5✔
65
        if c.w == nil {
7✔
66
                return 0, syscall.EBADF
2✔
67
        }
2✔
68
        return c.w.Write(p)
3✔
69
}
70

71
// Do not call Read directly; use io.Copy instead as we are
72
// calculating checksum only after receiving io.EOF.
73
func (c *Checksum) Read(p []byte) (int, error) {
32✔
74
        if c.r == nil {
34✔
75
                return 0, syscall.EBADF
2✔
76
        }
2✔
77
        n, err := c.r.Read(p)
30✔
78
        if err == io.EOF {
38✔
79
                // verify checksum
8✔
80
                if verErr := c.Verify(); verErr != nil {
10✔
81
                        return 0, verErr
2✔
82
                }
2✔
83
        }
84
        return n, err
28✔
85
}
86

87
func (c *Checksum) Checksum() []byte {
13✔
88
        if c.h == nil {
15✔
89
                return nil
2✔
90
        }
2✔
91
        sum := c.h.Sum(nil)
11✔
92
        checksum := make([]byte, hex.EncodedLen(len(sum)))
11✔
93
        hex.Encode(checksum, sum)
11✔
94
        return checksum
11✔
95
}
96

97
func (c *Checksum) Verify() error {
8✔
98
        sum := c.Checksum()
8✔
99
        if !bytes.Equal(c.c, sum) {
10✔
100
                return errors.Errorf("invalid checksum; expected: [%s]; actual: [%s]",
2✔
101
                        c.c, sum)
2✔
102
        }
2✔
103
        return nil
6✔
104
}
105

106
type ChecksumStore struct {
107
        // raw is storing raw data that is read from manifest file;
108
        // we need to keep raw data as iterating over sums map may produce
109
        // different result each time map is traversed
110
        raw *bytes.Buffer
111
        // sums is a map of all files and its checksums;
112
        // key is the name of the file and value is the checksum
113
        sums map[string]([]byte)
114
        // A map which contains the same keys as sums, used to mark each file,
115
        // and then check at the end that all files have been visited.
116
        marked map[string]bool
117
}
118

119
func NewChecksumStore() *ChecksumStore {
5✔
120
        return &ChecksumStore{
5✔
121
                sums:   make(map[string]([]byte), 1),
5✔
122
                raw:    bytes.NewBuffer(nil),
5✔
123
                marked: make(map[string]bool, 1),
5✔
124
        }
5✔
125
}
5✔
126

127
func (c *ChecksumStore) Add(file string, sum []byte) error {
11✔
128
        if _, ok := c.sums[file]; ok {
15✔
129
                return os.ErrExist
4✔
130
        }
4✔
131

132
        c.sums[file] = sum
7✔
133
        c.marked[file] = false
7✔
134
        _, err := c.raw.WriteString(fmt.Sprintf("%s  %s\n", sum, file))
7✔
135
        return err
7✔
136
}
137

138
func (c *ChecksumStore) Get(file string) ([]byte, error) {
8✔
139
        sum, ok := c.sums[file]
8✔
140
        if !ok {
10✔
141
                return nil, errors.Errorf("checksum: checksum missing for file: '%s'", file)
2✔
142
        }
2✔
143
        return sum, nil
6✔
144
}
145

146
// Same as Get(), but also marks the file as visited.
147
func (c *ChecksumStore) GetAndMark(file string) ([]byte, error) {
2✔
148
        sum, err := c.Get(file)
2✔
149
        if err == nil {
4✔
150
                c.marked[file] = true
2✔
151
        }
2✔
152
        return sum, err
2✔
153
}
154

155
func (c *ChecksumStore) FilesNotMarked() []string {
2✔
156
        var list []string
2✔
157
        for file, marked := range c.marked {
4✔
158
                if !marked {
2✔
UNCOV
159
                        list = append(list, file)
×
UNCOV
160
                }
×
161
        }
162
        return list
2✔
163
}
164

165
func (c *ChecksumStore) GetRaw() []byte {
11✔
166
        return c.raw.Bytes()
11✔
167
}
11✔
168

169
func (c *ChecksumStore) ReadRaw(data []byte) error {
8✔
170
        raw := bytes.NewBuffer(data)
8✔
171
        for {
18✔
172
                line, err := raw.ReadString('\n')
10✔
173
                if err == io.EOF {
14✔
174
                        break
4✔
175
                } else if err != nil {
8✔
176
                        return errors.Wrap(err, "checksum: can not read raw")
×
177
                }
×
178
                if err = c.readChecksums(line); err != nil {
12✔
179
                        return err
4✔
180
                }
4✔
181
        }
182
        return nil
4✔
183
}
184

185
func (c *ChecksumStore) readChecksums(line string) error {
8✔
186
        trimmed := strings.TrimSpace(line)
8✔
187
        if len(trimmed) == 0 {
8✔
UNCOV
188
                return nil
×
UNCOV
189
        }
×
190
        chunks := strings.Split(trimmed, "  ")
8✔
191
        if len(chunks) != 2 {
10✔
192
                return errors.Errorf("checksum: malformed checksum line: '%s'", line)
2✔
193
        }
2✔
194
        // add element to map
195
        return c.Add(chunks[1], []byte(chunks[0]))
6✔
196
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc