github.com/rigado/snapd@v2.42.5-go-mod+incompatible/snap/broken.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2014-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 snap 21 22 import ( 23 "fmt" 24 "path/filepath" 25 "strings" 26 27 "github.com/snapcore/snapd/dirs" 28 ) 29 30 // GuessAppsForBroken guesses what apps and services a broken snap has 31 // on the system by searching for matches based on the snap name in 32 // the snap binaries and service file directories. It returns a 33 // mapping from app names to partial AppInfo. 34 func GuessAppsForBroken(info *Info) map[string]*AppInfo { 35 out := make(map[string]*AppInfo) 36 37 // guess binaries first 38 name := info.InstanceName() 39 for _, p := range []string{name, fmt.Sprintf("%s.*", name)} { 40 matches, _ := filepath.Glob(filepath.Join(dirs.SnapBinariesDir, p)) 41 for _, m := range matches { 42 l := strings.SplitN(filepath.Base(m), ".", 2) 43 var appname string 44 if len(l) == 1 { 45 // when app is named the same as snap, it will 46 // be available under '<snap>' name, if the snap 47 // was installed with instance key, the app will 48 // be named `<snap>_<instance>' 49 appname = InstanceSnap(l[0]) 50 } else { 51 appname = l[1] 52 } 53 out[appname] = &AppInfo{ 54 Snap: info, 55 Name: appname, 56 } 57 } 58 } 59 60 // guess the services next 61 matches, _ := filepath.Glob(filepath.Join(dirs.SnapServicesDir, fmt.Sprintf("snap.%s.*.service", name))) 62 for _, m := range matches { 63 appname := strings.Split(m, ".")[2] 64 out[appname] = &AppInfo{ 65 Snap: info, 66 Name: appname, 67 Daemon: "simple", 68 } 69 } 70 71 return out 72 } 73 74 // renameClashingCorePlugs renames plugs that clash with slot names on core snap. 75 // 76 // Some released core snaps had explicitly defined plugs "network-bind" and 77 // "core-support" that clashed with implicit slots with the same names but this 78 // was not validated before. To avoid a flag day and any potential issues, 79 // transparently rename the two clashing plugs by appending the "-plug" suffix. 80 func (info *Info) renameClashingCorePlugs() { 81 if info.InstanceName() == "core" && info.GetType() == TypeOS { 82 for _, plugName := range []string{"network-bind", "core-support"} { 83 info.forceRenamePlug(plugName, plugName+"-plug") 84 } 85 } 86 } 87 88 // forceRenamePlug renames the plug from oldName to newName, if present. 89 func (info *Info) forceRenamePlug(oldName, newName string) { 90 if plugInfo, ok := info.Plugs[oldName]; ok { 91 delete(info.Plugs, oldName) 92 info.Plugs[newName] = plugInfo 93 plugInfo.Name = newName 94 for _, appInfo := range info.Apps { 95 if _, ok := appInfo.Plugs[oldName]; ok { 96 delete(appInfo.Plugs, oldName) 97 appInfo.Plugs[newName] = plugInfo 98 } 99 } 100 for _, hookInfo := range info.Hooks { 101 if _, ok := hookInfo.Plugs[oldName]; ok { 102 delete(hookInfo.Plugs, oldName) 103 hookInfo.Plugs[newName] = plugInfo 104 } 105 } 106 } 107 }