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  }