• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
Build has been set to done!

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

60.27
/handlers/rootfs_image.go
1
// Copyright 2022 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 handlers
16

17
import (
18
        "bytes"
19
        "encoding/json"
20
        "fmt"
21
        "io"
22
        "path/filepath"
23

24
        "github.com/pkg/errors"
25

26
        "github.com/mendersoftware/mender-artifact/artifact"
27
)
28

29
// Rootfs handles updates of type 'rootfs-image'.
30
type Rootfs struct {
31
        version           int
32
        update            *DataFile
33
        regularHeaderRead bool
34

35
        typeInfoV3 *artifact.TypeInfoV3
36
        metaData   map[string]interface{}
37

38
        // If this is augmented instance: The original instance.
39
        original ArtifactUpdate
40

41
        installerBase
42
}
43

44
func NewRootfsV2(updFile string) *Rootfs {
10✔
45
        uf := &DataFile{
10✔
46
                Name: updFile,
10✔
47
        }
10✔
48
        return &Rootfs{
10✔
49
                update:  uf,
10✔
50
                version: 2,
10✔
51
        }
10✔
52
}
10✔
53

54
func NewRootfsV3(updFile string) *Rootfs {
32✔
55
        var uf *DataFile
32✔
56
        if updFile != "" {
38✔
57
                uf = &DataFile{
6✔
58
                        Name: updFile,
6✔
59
                }
6✔
60
        } else {
32✔
61
                uf = nil
26✔
62
        }
26✔
63
        return &Rootfs{
32✔
64
                update:  uf,
32✔
65
                version: 3,
32✔
66
        }
32✔
67
}
68

69
func NewAugmentedRootfs(orig ArtifactUpdate, updFile string) *Rootfs {
10✔
70
        rootfs := NewRootfsV3(updFile)
10✔
71
        rootfs.original = orig
10✔
72
        return rootfs
10✔
73
}
10✔
74

75
// NewRootfsInstaller is used by the artifact reader to read and install
76
// rootfs-image update type.
77
func NewRootfsInstaller() *Rootfs {
4✔
78
        return &Rootfs{}
4✔
79
}
4✔
80

81
// Copy creates a new instance of Rootfs handler from the existing one.
82
func (rp *Rootfs) NewInstance() Installer {
4✔
83
        return &Rootfs{
4✔
84
                version:           rp.version,
4✔
85
                installerBase:     rp.installerBase,
4✔
86
                regularHeaderRead: rp.regularHeaderRead,
4✔
87
        }
4✔
88
}
4✔
89

90
func (rp *Rootfs) NewAugmentedInstance(orig ArtifactUpdate) (Installer, error) {
6✔
91
        if orig.GetVersion() < 3 {
8✔
92
                return nil, errors.New(
2✔
93
                        "Rootfs Payload type version < 3 does not support augmented sections.",
2✔
94
                )
2✔
95
        }
2✔
96
        if *orig.GetUpdateType() != "rootfs-image" {
6✔
97
                return nil, fmt.Errorf("rootfs-image type cannot be an augmented instance of %s type.",
2✔
98
                        *orig.GetUpdateType())
2✔
99
        }
2✔
100

101
        newRootfs := rp.NewInstance().(*Rootfs)
2✔
102
        newRootfs.original = orig
2✔
103
        return newRootfs, nil
2✔
104
}
105

106
func (rp *Rootfs) GetVersion() int {
4✔
107
        return rp.version
4✔
108
}
4✔
109

110
func (rp *Rootfs) ReadHeader(r io.Reader, path string, version int, augmented bool) error {
34✔
111
        rp.version = version
34✔
112
        switch {
34✔
113
        case filepath.Base(path) == "files":
10✔
114
                if version >= 3 {
14✔
115
                        return errors.New("\"files\" entry found in version 3 artifact")
4✔
116
                }
4✔
117
                files, err := parseFiles(r)
6✔
118
                if err != nil {
8✔
119
                        return err
2✔
120
                } else if len(files.FileList) != 1 {
8✔
121
                        return errors.New("Rootfs image does not contain exactly one file")
2✔
122
                }
2✔
123
                err = rp.SetUpdateFiles([]*DataFile{{Name: files.FileList[0]}})
2✔
124
                if err != nil {
2✔
125
                        return err
×
126
                }
×
127
        case filepath.Base(path) == "type-info":
6✔
128
                if rp.version < 3 {
8✔
129
                        // This was ignored in pre-v3 versions, so keep ignoring it.
2✔
130
                        break
2✔
131
                }
132
                dec := json.NewDecoder(r)
4✔
133
                err := dec.Decode(&rp.typeInfoV3)
4✔
134
                if err != nil {
4✔
135
                        return errors.Wrap(err, "error reading type-info")
×
136
                }
×
137

138
        case filepath.Base(path) == "meta-data":
2✔
139
                dec := json.NewDecoder(r)
2✔
140
                var data interface{}
2✔
141
                err := dec.Decode(&data)
2✔
142
                if err == io.EOF {
4✔
143
                        break
2✔
UNCOV
144
                } else if err != nil {
×
145
                        return errors.Wrap(err, "error reading meta-data")
×
146
                }
×
UNCOV
147
                jsonObj, ok := data.(map[string]interface{})
×
UNCOV
148
                if !ok {
×
149
                        return errors.New("Top level object in meta-data must be a JSON object")
×
150
                }
×
UNCOV
151
                if augmented {
×
152
                        err = rp.setUpdateAugmentMetaData(jsonObj)
×
UNCOV
153
                } else {
×
UNCOV
154
                        err = rp.setUpdateOriginalMetaData(jsonObj)
×
UNCOV
155
                }
×
UNCOV
156
                if err != nil {
×
157
                        return err
×
158
                }
×
159
        case match(artifact.HeaderDirectory+"/*/signatures/*", path),
160
                match(artifact.HeaderDirectory+"/*/scripts/*/*", path):
8✔
161
                if augmented {
8✔
162
                        return errors.New("signatures and scripts not allowed in augmented header")
×
163
                }
×
164
                // TODO: implement when needed
165
        case match(artifact.HeaderDirectory+"/*/checksums/*", path):
2✔
166
                buf := bytes.NewBuffer(nil)
2✔
167
                if _, err := io.Copy(buf, r); err != nil {
2✔
168
                        return errors.Wrap(err, "update: error reading checksum")
×
169
                }
×
170
                rp.update.Checksum = buf.Bytes()
2✔
171
        default:
6✔
172
                return errors.Errorf("update: unsupported file: %v", path)
6✔
173
        }
174
        return nil
20✔
175
}
176

177
func (rfs *Rootfs) GetUpdateFiles() [](*DataFile) {
50✔
178
        if rfs.original != nil {
70✔
179
                return rfs.original.GetUpdateFiles()
20✔
180
        } else if rfs.update != nil {
58✔
181
                return [](*DataFile){rfs.update}
8✔
182
        } else {
30✔
183
                return [](*DataFile){}
22✔
184
        }
22✔
185
}
186

187
func (rfs *Rootfs) SetUpdateFiles(files [](*DataFile)) error {
8✔
188
        if rfs.original != nil {
10✔
189
                if len(files) > 0 && len(rfs.GetUpdateAugmentFiles()) > 0 {
4✔
190
                        return errors.New("Rootfs: Cannot handle both augmented and non-augmented update file")
2✔
191
                }
2✔
192
                return rfs.original.SetUpdateFiles(files)
×
193
        }
194

195
        if len(files) == 0 {
8✔
196
                rfs.update = nil
2✔
197
                return nil
2✔
198
        } else if len(files) != 1 {
6✔
UNCOV
199
                return errors.New("Rootfs: Must provide exactly one update file")
×
UNCOV
200
        }
×
201

202
        rfs.update = files[0]
4✔
203
        return nil
4✔
204
}
205

206
func (rfs *Rootfs) GetUpdateAugmentFiles() [](*DataFile) {
34✔
207
        if rfs.original != nil && rfs.update != nil {
38✔
208
                return [](*DataFile){rfs.update}
4✔
209
        } else {
34✔
210
                return [](*DataFile){}
30✔
211
        }
30✔
212
}
213

214
func (rfs *Rootfs) SetUpdateAugmentFiles(files [](*DataFile)) error {
14✔
215
        if rfs.original == nil {
18✔
216
                if len(files) > 0 {
6✔
217
                        return errors.New("Rootfs: Cannot set augmented data file on non-augmented instance.")
2✔
218
                } else {
4✔
219
                        return nil
2✔
220
                }
2✔
221
        }
222

223
        if len(files) == 0 {
12✔
224
                rfs.update = nil
2✔
225
                return nil
2✔
226
        } else if len(files) != 1 {
12✔
227
                return errors.New("Rootfs: Must provide exactly one update file")
2✔
228
        }
2✔
229

230
        if len(rfs.GetUpdateFiles()) > 0 {
8✔
231
                return errors.New("Rootfs: Cannot handle both augmented and non-augmented update file")
2✔
232
        }
2✔
233

234
        rfs.update = files[0]
4✔
235
        return nil
4✔
236
}
237

238
func (rfs *Rootfs) GetUpdateAllFiles() [](*DataFile) {
10✔
239
        allFiles := make([]*DataFile, 0, len(rfs.GetUpdateAugmentFiles())+len(rfs.GetUpdateFiles()))
10✔
240
        allFiles = append(allFiles, rfs.GetUpdateFiles()...)
10✔
241
        allFiles = append(allFiles, rfs.GetUpdateAugmentFiles()...)
10✔
242
        return allFiles
10✔
243
}
10✔
244

245
func (rfs *Rootfs) GetUpdateType() *string {
4✔
246
        updateType := "rootfs-image"
4✔
247
        return &updateType
4✔
248
}
4✔
249

UNCOV
250
func (rfs *Rootfs) GetUpdateOriginalType() *string {
×
UNCOV
251
        originalType := ""
×
UNCOV
252
        return &originalType
×
UNCOV
253
}
×
254

UNCOV
255
func (rfs *Rootfs) GetUpdateDepends() (artifact.TypeInfoDepends, error) {
×
UNCOV
256
        return rfs.GetUpdateOriginalDepends(), nil
×
UNCOV
257
}
×
258

UNCOV
259
func (rfs *Rootfs) GetUpdateProvides() (artifact.TypeInfoProvides, error) {
×
UNCOV
260
        return rfs.GetUpdateOriginalProvides(), nil
×
UNCOV
261
}
×
262

UNCOV
263
func (rfs *Rootfs) GetUpdateMetaData() (map[string]interface{}, error) {
×
UNCOV
264
        // No metadata for rootfs update type.
×
UNCOV
265
        return rfs.GetUpdateOriginalMetaData(), nil
×
UNCOV
266
}
×
267

UNCOV
268
func (rfs *Rootfs) GetUpdateClearsProvides() []string {
×
UNCOV
269
        if rfs.typeInfoV3 == nil {
×
UNCOV
270
                return nil
×
UNCOV
271
        }
×
UNCOV
272
        if rfs.typeInfoV3.ClearsArtifactProvides == nil && rfs.original != nil {
×
273
                return rfs.original.GetUpdateOriginalClearsProvides()
×
274
        }
×
UNCOV
275
        return rfs.typeInfoV3.ClearsArtifactProvides
×
276
}
277

UNCOV
278
func (rfs *Rootfs) setUpdateOriginalMetaData(jsonObj map[string]interface{}) error {
×
UNCOV
279
        if rfs.original != nil {
×
280
                return errors.New("setUpdateOriginalMetaData() called on non-original instance.")
×
UNCOV
281
        } else {
×
UNCOV
282
                rfs.metaData = jsonObj
×
UNCOV
283
        }
×
UNCOV
284
        return nil
×
285
}
286

287
func (rfs *Rootfs) setUpdateAugmentMetaData(jsonObj map[string]interface{}) error {
×
288
        if rfs.original == nil {
×
289
                return errors.New("Called setUpdateAugmentMetaData() on non-augment instance")
×
290
        }
×
291
        rfs.metaData = jsonObj
×
292
        return nil
×
293
}
294

UNCOV
295
func (rfs *Rootfs) GetUpdateOriginalDepends() artifact.TypeInfoDepends {
×
UNCOV
296
        if rfs.typeInfoV3 == nil {
×
UNCOV
297
                return nil
×
UNCOV
298
        }
×
UNCOV
299
        return rfs.typeInfoV3.ArtifactDepends
×
300
}
301

UNCOV
302
func (rfs *Rootfs) GetUpdateOriginalProvides() artifact.TypeInfoProvides {
×
UNCOV
303
        if rfs.typeInfoV3 == nil {
×
UNCOV
304
                return nil
×
UNCOV
305
        }
×
UNCOV
306
        return rfs.typeInfoV3.ArtifactProvides
×
307
}
308

UNCOV
309
func (rfs *Rootfs) GetUpdateOriginalMetaData() map[string]interface{} {
×
UNCOV
310
        if rfs.original != nil {
×
311
                return rfs.original.GetUpdateOriginalMetaData()
×
UNCOV
312
        } else {
×
UNCOV
313
                return rfs.metaData
×
UNCOV
314
        }
×
315
}
316

UNCOV
317
func (rfs *Rootfs) GetUpdateOriginalClearsProvides() []string {
×
UNCOV
318
        if rfs.original == nil {
×
UNCOV
319
                if rfs.typeInfoV3 == nil {
×
UNCOV
320
                        return nil
×
UNCOV
321
                }
×
UNCOV
322
                return rfs.typeInfoV3.ClearsArtifactProvides
×
323
        } else {
×
324
                return rfs.original.GetUpdateOriginalClearsProvides()
×
325
        }
×
326
}
327

328
func (rfs *Rootfs) GetUpdateAugmentDepends() artifact.TypeInfoDepends {
×
329
        return nil
×
330
}
×
331

332
func (rfs *Rootfs) GetUpdateAugmentProvides() artifact.TypeInfoProvides {
×
333
        return nil
×
334
}
×
335

UNCOV
336
func (rfs *Rootfs) GetUpdateAugmentMetaData() map[string]interface{} {
×
UNCOV
337
        if rfs.original == nil {
×
UNCOV
338
                return nil
×
UNCOV
339
        } else {
×
340
                return rfs.metaData
×
341
        }
×
342
}
343

344
func (rfs *Rootfs) GetUpdateAugmentClearsProvides() []string {
×
345
        if rfs.original == nil {
×
346
                return nil
×
347
        } else {
×
348
                if rfs.typeInfoV3 == nil {
×
349
                        return nil
×
350
                }
×
351
                return rfs.typeInfoV3.ClearsArtifactProvides
×
352
        }
353
}
354

355
func (rfs *Rootfs) ComposeHeader(args *ComposeHeaderArgs) error {
12✔
356

12✔
357
        path := artifact.UpdateHeaderPath(args.No)
12✔
358

12✔
359
        switch rfs.version {
12✔
360
        case 1, 2:
4✔
361
                // first store files
4✔
362
                if err := writeFiles(args.TarWriter, []string{filepath.Base(rfs.update.Name)},
4✔
363
                        path); err != nil {
6✔
364
                        return err
2✔
365
                }
2✔
366

367
                if err := writeTypeInfo(args.TarWriter, "rootfs-image", path); err != nil {
2✔
368
                        return err
×
369
                }
×
370

371
        case 3:
6✔
372
                if args.Augmented {
8✔
373
                        // Remove the typeinfov3.provides, as this should not be written in the
2✔
374
                        // augmented-header.
2✔
375
                        if args.TypeInfoV3 != nil {
4✔
376
                                args.TypeInfoV3.ArtifactProvides = nil
2✔
377
                        }
2✔
378
                }
379

380
                if err := writeTypeInfoV3(&WriteInfoArgs{
6✔
381
                        tarWriter:  args.TarWriter,
6✔
382
                        dir:        path,
6✔
383
                        typeinfov3: args.TypeInfoV3,
6✔
384
                }); err != nil {
8✔
385
                        return errors.Wrap(err, "ComposeHeader")
2✔
386
                }
2✔
387
        default:
2✔
388
                return fmt.Errorf("ComposeHeader: rootfs-version %d not supported", rfs.version)
2✔
389

390
        }
391

392
        // store empty meta-data
393
        // the file needs to be a part of artifact even if this one is empty
394
        if len(args.MetaData) != 0 {
8✔
395
                return errors.New(
2✔
396
                        "MetaData not empty in Rootfs.ComposeHeader. This is a bug in the application.",
2✔
397
                )
2✔
398
        }
2✔
399
        sw := artifact.NewTarWriterStream(args.TarWriter)
4✔
400
        if err := sw.Write(nil, filepath.Join(path, "meta-data")); err != nil {
4✔
401
                return errors.Wrap(err, "Payload: can not store meta-data")
×
402
        }
×
403

404
        return nil
4✔
405
}
406

407
func (rfs *Rootfs) GetUpdateOriginalTypeInfoWriter() io.Writer {
×
408
        // We don't use the type-info information with rootfs payloads.
×
409
        return nil
×
410
}
×
411

412
func (rfs *Rootfs) GetUpdateAugmentTypeInfoWriter() io.Writer {
×
413
        // We don't use the type-info information with rootfs payloads.
×
414
        return nil
×
415
}
×
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