File: spec.go

package info (click to toggle)
snapd 2.72-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 80,412 kB
  • sloc: sh: 16,506; ansic: 16,211; python: 11,213; makefile: 1,919; exp: 190; awk: 58; xml: 22
file content (139 lines) | stat: -rw-r--r-- 4,576 bytes parent folder | download | duplicates (2)
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
// -*- Mode: Go; indent-tabs-mode: t -*-

/*
 * Copyright (C) 2021 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 polkit

import (
	"bytes"
	"fmt"

	"github.com/snapcore/snapd/interfaces"
	"github.com/snapcore/snapd/polkit/validate"
	"github.com/snapcore/snapd/snap"
)

type Policy []byte
type Rule []byte

// Specification keeps all the polkit policies.
type Specification struct {
	policyFiles map[string]Policy
	ruleFiles   map[string]Rule
}

// AddPolicy adds a polkit policy file to install.
func (spec *Specification) AddPolicy(nameSuffix string, content Policy) error {
	if old, ok := spec.policyFiles[nameSuffix]; ok && !bytes.Equal(old, content) {
		return fmt.Errorf("internal error: polkit policy content for %q re-defined with different content", nameSuffix)
	}
	if spec.policyFiles == nil {
		spec.policyFiles = make(map[string]Policy)
	}
	spec.policyFiles[nameSuffix] = content
	return nil
}

// Policies returns a map of polkit policies added to the Specification.
func (spec *Specification) Policies() map[string]Policy {
	if spec.policyFiles == nil {
		return nil
	}
	result := make(map[string]Policy, len(spec.policyFiles))
	for k, v := range spec.policyFiles {
		result[k] = make(Policy, len(v))
		copy(result[k], v)
	}
	return result
}

// AddRule adds a polkit rule file to install.
func (spec *Specification) AddRule(nameSuffix string, content Rule) error {
	if err := validate.ValidateRuleNameSuffix(nameSuffix); err != nil {
		return err
	}
	if old, ok := spec.ruleFiles[nameSuffix]; ok && !bytes.Equal(old, content) {
		return fmt.Errorf("internal error: polkit rule content for %q re-defined with different content", nameSuffix)
	}
	if spec.ruleFiles == nil {
		spec.ruleFiles = make(map[string]Rule)
	}
	spec.ruleFiles[nameSuffix] = content
	return nil
}

// Rules returns a map of polkit rules added to the Specification.
// This maps from rule name suffixes (without the ".rules" suffix)
// to the content required to be installed.
func (spec *Specification) Rules() map[string]Rule {
	if spec.ruleFiles == nil {
		return nil
	}
	result := make(map[string]Rule, len(spec.ruleFiles))
	for k, v := range spec.ruleFiles {
		result[k] = make(Rule, len(v))
		copy(result[k], v)
	}
	return result
}

// Implementation of methods required by interfaces.Specification

// AddConnectedPlug records polkit-specific side-effects of having a connected plug.
func (spec *Specification) AddConnectedPlug(iface interfaces.Interface, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
	type definer interface {
		PolkitConnectedPlug(spec *Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
	}
	if iface, ok := iface.(definer); ok {
		return iface.PolkitConnectedPlug(spec, plug, slot)
	}
	return nil
}

// AddConnectedSlot records polkit-specific side-effects of having a connected slot.
func (spec *Specification) AddConnectedSlot(iface interfaces.Interface, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
	type definer interface {
		PolkitConnectedSlot(spec *Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
	}
	if iface, ok := iface.(definer); ok {
		return iface.PolkitConnectedSlot(spec, plug, slot)
	}
	return nil
}

// AddPermanentPlug records polkit-specific side-effects of having a plug.
func (spec *Specification) AddPermanentPlug(iface interfaces.Interface, plug *snap.PlugInfo) error {
	type definer interface {
		PolkitPermanentPlug(spec *Specification, plug *snap.PlugInfo) error
	}
	if iface, ok := iface.(definer); ok {
		return iface.PolkitPermanentPlug(spec, plug)
	}
	return nil
}

// AddPermanentSlot records polkit-specific side-effects of having a slot.
func (spec *Specification) AddPermanentSlot(iface interfaces.Interface, slot *snap.SlotInfo) error {
	type definer interface {
		PolkitPermanentSlot(spec *Specification, slot *snap.SlotInfo) error
	}
	if iface, ok := iface.(definer); ok {
		return iface.PolkitPermanentSlot(spec, slot)
	}
	return nil
}