forked from snapcore/snapd
/
aux_store_info.go
111 lines (96 loc) · 3.3 KB
/
aux_store_info.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
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
* Copyright (C) 2018 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 snapstate
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"github.com/snapcore/snapd/dirs"
"github.com/snapcore/snapd/osutil"
"github.com/snapcore/snapd/snap"
)
// auxStoreInfo is information about a snap (*not* a snap revision), not
// needed in the state, that may be stored to augment the information
// returned for locally-installed snaps
type auxStoreInfo struct {
Media snap.MediaInfos `json:"media,omitempty"`
Website string `json:"website,omitempty"`
StoreURL string `json:"store-url,omitempty"`
}
func auxStoreInfoFilename(snapID string) string {
return filepath.Join(dirs.SnapAuxStoreInfoDir, snapID) + ".json"
}
// retrieveAuxStoreInfo loads the stored per-snap auxiliary store info into the given *snap.Info
func retrieveAuxStoreInfo(info *snap.Info) error {
if info.SnapID == "" {
return nil
}
f, err := os.Open(auxStoreInfoFilename(info.SnapID))
if err != nil {
if os.IsNotExist(err) {
return nil
}
return err
}
defer f.Close()
var aux auxStoreInfo
dec := json.NewDecoder(f)
if err := dec.Decode(&aux); err != nil {
return fmt.Errorf("cannot decode auxiliary store info for snap %q: %v", info.InstanceName(), err)
}
if dec.More() {
return fmt.Errorf("cannot decode auxiliary store info for snap %q: spurious content after document body", info.InstanceName())
}
info.Media = aux.Media
info.Website = aux.Website
info.StoreURL = aux.StoreURL
return nil
}
// keepAuxStoreInfo saves the given auxiliary store info to disk.
func keepAuxStoreInfo(snapID string, aux *auxStoreInfo) error {
if snapID == "" {
return nil
}
if err := os.MkdirAll(dirs.SnapAuxStoreInfoDir, 0755); err != nil {
return fmt.Errorf("cannot create directory for auxiliary store info: %v", err)
}
af, err := osutil.NewAtomicFile(auxStoreInfoFilename(snapID), 0644, 0, osutil.NoChown, osutil.NoChown)
if err != nil {
return fmt.Errorf("cannot create file for auxiliary store info for snap %s: %v", snapID, err)
}
// on success, Cancel becomes a nop
defer af.Cancel()
if err := json.NewEncoder(af).Encode(aux); err != nil {
return fmt.Errorf("cannot encode auxiliary store info for snap %s: %v", snapID, err)
}
if err := af.Commit(); err != nil {
return fmt.Errorf("cannot commit auxiliary store info file for snap %s: %v", snapID, err)
}
return nil
}
// discardAuxStoreInfo removes the auxiliary store info for the given snap from disk.
func discardAuxStoreInfo(snapID string) error {
if snapID == "" {
return nil
}
if err := os.Remove(auxStoreInfoFilename(snapID)); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("cannot remove auxiliary store info file for snap %s: %v", snapID, err)
}
return nil
}