github.com/Lephar/snapd@v0.0.0-20210825215435-c7fba9cef4d2/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 DaemonScope: SystemDaemon, 69 } 70 } 71 // guess the user services next 72 matches, _ = filepath.Glob(filepath.Join(dirs.SnapUserServicesDir, fmt.Sprintf("snap.%s.*.service", name))) 73 for _, m := range matches { 74 appname := strings.Split(m, ".")[2] 75 out[appname] = &AppInfo{ 76 Snap: info, 77 Name: appname, 78 Daemon: "simple", 79 DaemonScope: UserDaemon, 80 } 81 } 82 83 return out 84 } 85 86 // renameClashingCorePlugs renames plugs that clash with slot names on core snap. 87 // 88 // Some released core snaps had explicitly defined plugs "network-bind" and 89 // "core-support" that clashed with implicit slots with the same names but this 90 // was not validated before. To avoid a flag day and any potential issues, 91 // transparently rename the two clashing plugs by appending the "-plug" suffix. 92 func (info *Info) renameClashingCorePlugs() { 93 if info.InstanceName() == "core" && info.Type() == TypeOS { 94 for _, plugName := range []string{"network-bind", "core-support"} { 95 info.forceRenamePlug(plugName, plugName+"-plug") 96 } 97 } 98 } 99 100 // forceRenamePlug renames the plug from oldName to newName, if present. 101 func (info *Info) forceRenamePlug(oldName, newName string) { 102 if plugInfo, ok := info.Plugs[oldName]; ok { 103 delete(info.Plugs, oldName) 104 info.Plugs[newName] = plugInfo 105 plugInfo.Name = newName 106 for _, appInfo := range info.Apps { 107 if _, ok := appInfo.Plugs[oldName]; ok { 108 delete(appInfo.Plugs, oldName) 109 appInfo.Plugs[newName] = plugInfo 110 } 111 } 112 for _, hookInfo := range info.Hooks { 113 if _, ok := hookInfo.Plugs[oldName]; ok { 114 delete(hookInfo.Plugs, oldName) 115 hookInfo.Plugs[newName] = plugInfo 116 } 117 } 118 } 119 }