forked from snapcore/snapd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
content.go
143 lines (125 loc) · 4.5 KB
/
content.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
* Copyright (C) 2019-2020 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package install
import (
"fmt"
"os"
"path/filepath"
"strconv"
"github.com/snapcore/snapd/dirs"
"github.com/snapcore/snapd/gadget"
"github.com/snapcore/snapd/gadget/internal"
"github.com/snapcore/snapd/gadget/quantity"
"github.com/snapcore/snapd/logger"
)
var contentMountpoint string
func init() {
contentMountpoint = filepath.Join(dirs.SnapRunDir, "gadget-install")
}
// makeFilesystem creates a filesystem on the on-disk structure, according
// to the filesystem type defined in the gadget. If sectorSize is specified,
// that sector size is used when creating the filesystem, otherwise if it is
// zero, automatic values are used instead.
func makeFilesystem(ds *gadget.OnDiskStructure, sectorSize quantity.Size) error {
if ds.HasFilesystem() {
logger.Debugf("create %s filesystem on %s with label %q", ds.VolumeStructure.Filesystem, ds.Node, ds.VolumeStructure.Label)
if err := internal.Mkfs(ds.VolumeStructure.Filesystem, ds.Node, ds.VolumeStructure.Label, ds.Size, sectorSize); err != nil {
return err
}
if err := udevTrigger(ds.Node); err != nil {
return err
}
}
return nil
}
// writeContent populates the given on-disk structure, according to the contents
// defined in the gadget.
func writeContent(ds *gadget.OnDiskStructure, gadgetRoot string, observer gadget.ContentObserver) error {
switch {
case !ds.IsPartition():
return fmt.Errorf("cannot write non-partitions yet")
case !ds.HasFilesystem():
if err := writeNonFSContent(ds, gadgetRoot); err != nil {
return err
}
case ds.HasFilesystem():
if err := writeFilesystemContent(ds, gadgetRoot, observer); err != nil {
return err
}
}
return nil
}
// mountFilesystem mounts the on-disk structure filesystem under the given base
// directory, using the label defined in the gadget as the mount point name.
func mountFilesystem(ds *gadget.OnDiskStructure, baseMntPoint string) error {
if !ds.HasFilesystem() {
return fmt.Errorf("cannot mount a partition with no filesystem")
}
if ds.Label == "" {
return fmt.Errorf("cannot mount a filesystem with no label")
}
mountpoint := filepath.Join(baseMntPoint, ds.Label)
if err := os.MkdirAll(mountpoint, 0755); err != nil {
return fmt.Errorf("cannot create mountpoint: %v", err)
}
if err := sysMount(ds.Node, mountpoint, ds.Filesystem, 0, ""); err != nil {
return fmt.Errorf("cannot mount filesystem %q at %q: %v", ds.Node, mountpoint, err)
}
return nil
}
func writeFilesystemContent(ds *gadget.OnDiskStructure, gadgetRoot string, observer gadget.ContentObserver) (err error) {
mountpoint := filepath.Join(contentMountpoint, strconv.Itoa(ds.Index))
if err := os.MkdirAll(mountpoint, 0755); err != nil {
return err
}
// temporarily mount the filesystem
if err := sysMount(ds.Node, mountpoint, ds.Filesystem, 0, ""); err != nil {
return fmt.Errorf("cannot mount filesystem %q at %q: %v", ds.Node, mountpoint, err)
}
defer func() {
errUnmount := sysUnmount(mountpoint, 0)
if err == nil {
err = errUnmount
}
}()
fs, err := gadget.NewMountedFilesystemWriter(&ds.LaidOutStructure, observer)
if err != nil {
return fmt.Errorf("cannot create filesystem image writer: %v", err)
}
var noFilesToPreserve []string
if err := fs.Write(mountpoint, noFilesToPreserve); err != nil {
return fmt.Errorf("cannot create filesystem image: %v", err)
}
return nil
}
func writeNonFSContent(ds *gadget.OnDiskStructure, gadgetRoot string) error {
f, err := os.OpenFile(ds.Node, os.O_RDWR, 0644)
if err != nil {
return fmt.Errorf("cannot write bare content for %q: %v", ds.Node, err)
}
defer f.Close()
// Laid out structures start relative to the beginning of the
// volume, shift the structure offsets to 0, so that it starts
// at the beginning of the partition
l := gadget.ShiftStructureTo(ds.LaidOutStructure, 0)
raw, err := gadget.NewRawStructureWriter(gadgetRoot, &l)
if err != nil {
return err
}
return raw.Write(f)
}