github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/interfaces/builtin/all.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016 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 builtin 21 22 import ( 23 "fmt" 24 "sort" 25 26 "github.com/snapcore/snapd/interfaces" 27 "github.com/snapcore/snapd/snap" 28 ) 29 30 func init() { 31 snap.SanitizePlugsSlots = SanitizePlugsSlots 32 } 33 34 var ( 35 allInterfaces map[string]interfaces.Interface 36 ) 37 38 // Interfaces returns all of the built-in interfaces. 39 func Interfaces() []interfaces.Interface { 40 ifaces := make([]interfaces.Interface, 0, len(allInterfaces)) 41 for _, iface := range allInterfaces { 42 ifaces = append(ifaces, iface) 43 } 44 sort.Sort(byIfaceName(ifaces)) 45 return ifaces 46 } 47 48 // registerIface appends the given interface into the list of all known interfaces. 49 func registerIface(iface interfaces.Interface) { 50 if allInterfaces[iface.Name()] != nil { 51 panic(fmt.Errorf("cannot register duplicate interface %q", iface.Name())) 52 } 53 if allInterfaces == nil { 54 allInterfaces = make(map[string]interfaces.Interface) 55 } 56 allInterfaces[iface.Name()] = iface 57 } 58 59 func SanitizePlugsSlots(snapInfo *snap.Info) { 60 var badPlugs []string 61 var badSlots []string 62 63 for plugName, plugInfo := range snapInfo.Plugs { 64 iface, ok := allInterfaces[plugInfo.Interface] 65 if !ok { 66 snapInfo.BadInterfaces[plugName] = fmt.Sprintf("unknown interface %q", plugInfo.Interface) 67 badPlugs = append(badPlugs, plugName) 68 continue 69 } 70 // Reject plug with invalid name 71 if err := snap.ValidatePlugName(plugName); err != nil { 72 snapInfo.BadInterfaces[plugName] = err.Error() 73 badPlugs = append(badPlugs, plugName) 74 continue 75 } 76 if err := interfaces.BeforePreparePlug(iface, plugInfo); err != nil { 77 snapInfo.BadInterfaces[plugName] = err.Error() 78 badPlugs = append(badPlugs, plugName) 79 continue 80 } 81 } 82 83 for slotName, slotInfo := range snapInfo.Slots { 84 iface, ok := allInterfaces[slotInfo.Interface] 85 if !ok { 86 snapInfo.BadInterfaces[slotName] = fmt.Sprintf("unknown interface %q", slotInfo.Interface) 87 badSlots = append(badSlots, slotName) 88 continue 89 } 90 // Reject slot with invalid name 91 if err := snap.ValidateSlotName(slotName); err != nil { 92 snapInfo.BadInterfaces[slotName] = err.Error() 93 badSlots = append(badSlots, slotName) 94 continue 95 } 96 if err := interfaces.BeforePrepareSlot(iface, slotInfo); err != nil { 97 snapInfo.BadInterfaces[slotName] = err.Error() 98 badSlots = append(badSlots, slotName) 99 continue 100 } 101 } 102 103 // remove any bad plugs and slots 104 for _, plugName := range badPlugs { 105 delete(snapInfo.Plugs, plugName) 106 for _, app := range snapInfo.Apps { 107 delete(app.Plugs, plugName) 108 } 109 for _, hook := range snapInfo.Hooks { 110 delete(hook.Plugs, plugName) 111 } 112 } 113 for _, slotName := range badSlots { 114 delete(snapInfo.Slots, slotName) 115 for _, app := range snapInfo.Apps { 116 delete(app.Slots, slotName) 117 118 var activatesOn []*snap.SlotInfo 119 for _, slot := range app.ActivatesOn { 120 if slot.Name != slotName { 121 activatesOn = append(activatesOn, slot) 122 } 123 } 124 app.ActivatesOn = activatesOn 125 } 126 for _, hook := range snapInfo.Hooks { 127 delete(hook.Slots, slotName) 128 } 129 } 130 } 131 132 func MockInterface(iface interfaces.Interface) func() { 133 name := iface.Name() 134 allInterfaces[name] = iface 135 return func() { 136 delete(allInterfaces, name) 137 } 138 } 139 140 type byIfaceName []interfaces.Interface 141 142 func (c byIfaceName) Len() int { return len(c) } 143 func (c byIfaceName) Swap(i, j int) { c[i], c[j] = c[j], c[i] } 144 func (c byIfaceName) Less(i, j int) bool { 145 return c[i].Name() < c[j].Name() 146 }