github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/interfaces/dbus/spec.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2017 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 dbus
    21  
    22  import (
    23  	"bytes"
    24  	"sort"
    25  
    26  	"github.com/snapcore/snapd/interfaces"
    27  	"github.com/snapcore/snapd/snap"
    28  )
    29  
    30  // Specification keeps all the dbus snippets.
    31  type Specification struct {
    32  	// Snippets are indexed by security tag.
    33  	snippets     map[string][]string
    34  	securityTags []string
    35  }
    36  
    37  // AddSnippet adds a new dbus snippet.
    38  func (spec *Specification) AddSnippet(snippet string) {
    39  	if len(spec.securityTags) == 0 {
    40  		return
    41  	}
    42  	if spec.snippets == nil {
    43  		spec.snippets = make(map[string][]string)
    44  	}
    45  	for _, tag := range spec.securityTags {
    46  		spec.snippets[tag] = append(spec.snippets[tag], snippet)
    47  	}
    48  }
    49  
    50  // Snippets returns a deep copy of all the added snippets.
    51  func (spec *Specification) Snippets() map[string][]string {
    52  	result := make(map[string][]string, len(spec.snippets))
    53  	for k, v := range spec.snippets {
    54  		result[k] = append([]string(nil), v...)
    55  	}
    56  	return result
    57  }
    58  
    59  // SnippetForTag returns a combined snippet for given security tag with individual snippets
    60  // joined with newline character. Empty string is returned for non-existing security tag.
    61  func (spec *Specification) SnippetForTag(tag string) string {
    62  	var buffer bytes.Buffer
    63  	for _, snippet := range spec.snippets[tag] {
    64  		buffer.WriteString(snippet)
    65  		buffer.WriteRune('\n')
    66  	}
    67  	return buffer.String()
    68  }
    69  
    70  // SecurityTags returns a list of security tags which have a snippet.
    71  func (spec *Specification) SecurityTags() []string {
    72  	var tags []string
    73  	for t := range spec.snippets {
    74  		tags = append(tags, t)
    75  	}
    76  	sort.Strings(tags)
    77  	return tags
    78  }
    79  
    80  // Implementation of methods required by interfaces.Specification
    81  
    82  // AddConnectedPlug records dbus-specific side-effects of having a connected plug.
    83  func (spec *Specification) AddConnectedPlug(iface interfaces.Interface, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
    84  	type definer interface {
    85  		DBusConnectedPlug(spec *Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    86  	}
    87  	if iface, ok := iface.(definer); ok {
    88  		spec.securityTags = plug.SecurityTags()
    89  		defer func() { spec.securityTags = nil }()
    90  		return iface.DBusConnectedPlug(spec, plug, slot)
    91  	}
    92  	return nil
    93  }
    94  
    95  // AddConnectedSlot records dbus-specific side-effects of having a connected slot.
    96  func (spec *Specification) AddConnectedSlot(iface interfaces.Interface, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
    97  	type definer interface {
    98  		DBusConnectedSlot(spec *Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    99  	}
   100  	if iface, ok := iface.(definer); ok {
   101  		spec.securityTags = slot.SecurityTags()
   102  		defer func() { spec.securityTags = nil }()
   103  		return iface.DBusConnectedSlot(spec, plug, slot)
   104  	}
   105  	return nil
   106  }
   107  
   108  // AddPermanentPlug records dbus-specific side-effects of having a plug.
   109  func (spec *Specification) AddPermanentPlug(iface interfaces.Interface, plug *snap.PlugInfo) error {
   110  	type definer interface {
   111  		DBusPermanentPlug(spec *Specification, plug *snap.PlugInfo) error
   112  	}
   113  	if iface, ok := iface.(definer); ok {
   114  		spec.securityTags = plug.SecurityTags()
   115  		defer func() { spec.securityTags = nil }()
   116  		return iface.DBusPermanentPlug(spec, plug)
   117  	}
   118  	return nil
   119  }
   120  
   121  // AddPermanentSlot records dbus-specific side-effects of having a slot.
   122  func (spec *Specification) AddPermanentSlot(iface interfaces.Interface, slot *snap.SlotInfo) error {
   123  	type definer interface {
   124  		DBusPermanentSlot(spec *Specification, slot *snap.SlotInfo) error
   125  	}
   126  	if iface, ok := iface.(definer); ok {
   127  		spec.securityTags = slot.SecurityTags()
   128  		defer func() { spec.securityTags = nil }()
   129  		return iface.DBusPermanentSlot(spec, slot)
   130  	}
   131  	return nil
   132  }