gitee.com/mysnapcore/mysnapd@v0.1.0/image/helpers.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2014-2022 Canonical Ltd 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 <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package image 21 22 // TODO: put these in appropriate package(s) once they are clarified a bit more 23 24 import ( 25 "fmt" 26 "os" 27 "path/filepath" 28 29 "gitee.com/mysnapcore/mysnapd/asserts" 30 "gitee.com/mysnapcore/mysnapd/asserts/snapasserts" 31 "gitee.com/mysnapcore/mysnapd/gadget" 32 "gitee.com/mysnapcore/mysnapd/release" 33 "gitee.com/mysnapcore/mysnapd/snap" 34 ) 35 36 // FetchAndCheckSnapAssertions fetches and cross checks the snap assertions 37 // matching the given snap file using the provided asserts.Fetcher and 38 // assertion database. 39 // The optional model assertion must be passed for full cross checks. 40 func FetchAndCheckSnapAssertions(snapPath string, info *snap.Info, model *asserts.Model, f asserts.Fetcher, db asserts.RODatabase) (*asserts.SnapDeclaration, error) { 41 sha3_384, size, err := asserts.SnapFileSHA3_384(snapPath) 42 if err != nil { 43 return nil, err 44 } 45 46 expectedProv := info.Provenance() 47 // this assumes series "16" 48 if err := snapasserts.FetchSnapAssertions(f, sha3_384, expectedProv); err != nil { 49 return nil, fmt.Errorf("cannot fetch snap signatures/assertions: %v", err) 50 } 51 52 // cross checks 53 verifiedRev, err := snapasserts.CrossCheck(info.InstanceName(), sha3_384, expectedProv, size, &info.SideInfo, model, db) 54 if err != nil { 55 return nil, err 56 } 57 if err := snapasserts.CheckProvenanceWithVerifiedRevision(snapPath, verifiedRev); err != nil { 58 return nil, err 59 } 60 61 a, err := db.Find(asserts.SnapDeclarationType, map[string]string{ 62 "series": release.Series, 63 "snap-id": info.SnapID, 64 }) 65 if err != nil { 66 return nil, fmt.Errorf("internal error: lost snap declaration for %q: %v", info.InstanceName(), err) 67 } 68 return a.(*asserts.SnapDeclaration), nil 69 } 70 71 // var so that it can be mocked for tests 72 var writeResolvedContent = writeResolvedContentImpl 73 74 // writeResolvedContent takes gadget.Info and the unpacked 75 // gadget/kernel snaps and outputs the resolved content from the 76 // {gadget,kernel}.yaml into a filesystem tree with the structure: 77 // <prepareImageDir>/resolved-content/<volume-name>/part<structure-nr>/... 78 // 79 // E.g. 80 // /tmp/prep-img/resolved-content/pi/part0/{config.txt,bootcode.bin,...} 81 func writeResolvedContentImpl(prepareDir string, info *gadget.Info, gadgetUnpackDir, kernelUnpackDir string) error { 82 fullPrepareDir, err := filepath.Abs(prepareDir) 83 if err != nil { 84 return err 85 } 86 targetDir := filepath.Join(fullPrepareDir, "resolved-content") 87 88 opts := &gadget.LayoutOptions{ 89 GadgetRootDir: gadgetUnpackDir, 90 KernelRootDir: kernelUnpackDir, 91 } 92 for volName, vol := range info.Volumes { 93 pvol, err := gadget.LayoutVolume(vol, gadget.DefaultConstraints, opts) 94 if err != nil { 95 return err 96 } 97 for i, ps := range pvol.LaidOutStructure { 98 if !ps.HasFilesystem() { 99 continue 100 } 101 mw, err := gadget.NewMountedFilesystemWriter(&ps, nil) 102 if err != nil { 103 return err 104 } 105 // ubuntu-image uses the "part{}" nomenclature 106 dst := filepath.Join(targetDir, volName, fmt.Sprintf("part%d", i)) 107 // on UC20, ensure system-seed links back to the 108 // <PrepareDir>/system-seed 109 if ps.Role == gadget.SystemSeed { 110 uc20systemSeedDir := filepath.Join(fullPrepareDir, "system-seed") 111 if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { 112 return err 113 } 114 if err := os.Symlink(uc20systemSeedDir, dst); err != nil { 115 return err 116 } 117 } 118 if err := mw.Write(dst, nil); err != nil { 119 return err 120 } 121 } 122 } 123 124 return nil 125 }