gitee.com/mysnapcore/mysnapd@v0.1.0/image/preseed/reset.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2020-2022 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 preseed 21 22 import ( 23 "fmt" 24 "io/ioutil" 25 "os" 26 "path/filepath" 27 28 "gitee.com/mysnapcore/mysnapd/cmd/snaplock/runinhibit" 29 "gitee.com/mysnapcore/mysnapd/dirs" 30 "gitee.com/mysnapcore/mysnapd/osutil" 31 apparmor_sandbox "gitee.com/mysnapcore/mysnapd/sandbox/apparmor" 32 ) 33 34 // bash-completion symlinks; note there are symlinks that point at 35 // completer, and symlinks that point at the completer symlinks. 36 // e.g. 37 // lxd.lxc -> /snap/core/current/usr/lib/snapd/complete.sh 38 // lxc -> lxd.lxc 39 func resetCompletionSymlinks(completersPath string) error { 40 files, err := ioutil.ReadDir(completersPath) 41 if err != nil && !os.IsNotExist(err) { 42 return fmt.Errorf("error reading %s: %v", completersPath, err) 43 } 44 completeShSymlinks := make(map[string]string) 45 var otherSymlinks []string 46 47 // pass 1: find all symlinks pointing at complete.sh 48 for _, fileInfo := range files { 49 if fileInfo.Mode()&os.ModeSymlink == 0 { 50 continue 51 } 52 fullPath := filepath.Join(completersPath, fileInfo.Name()) 53 if dirs.IsCompleteShSymlink(fullPath) { 54 if err := os.Remove(fullPath); err != nil { 55 return fmt.Errorf("error removing symlink %s: %v", fullPath, err) 56 } 57 completeShSymlinks[fileInfo.Name()] = fullPath 58 } else { 59 otherSymlinks = append(otherSymlinks, fullPath) 60 } 61 } 62 // pass 2: find all symlinks that point at the symlinks found in pass 1. 63 for _, other := range otherSymlinks { 64 target, err := os.Readlink(other) 65 if err != nil { 66 return fmt.Errorf("error reading symlink target of %s: %v", other, err) 67 } 68 if _, ok := completeShSymlinks[target]; ok { 69 if err := os.Remove(other); err != nil { 70 return fmt.Errorf("error removing symlink %s: %v", other, err) 71 } 72 } 73 } 74 75 return nil 76 } 77 78 // ResetPreseededChroot removes all preseeding artifacts from preseedChroot 79 // (classic Ubuntu only). 80 func ResetPreseededChroot(preseedChroot string) error { 81 var err error 82 preseedChroot, err = filepath.Abs(preseedChroot) 83 if err != nil { 84 return err 85 } 86 87 exists, isDir, err := osutil.DirExists(preseedChroot) 88 if err != nil { 89 return fmt.Errorf("cannot reset %q: %v", preseedChroot, err) 90 } 91 if !exists { 92 return fmt.Errorf("cannot reset non-existing directory %q", preseedChroot) 93 } 94 if !isDir { 95 return fmt.Errorf("cannot reset %q, it is not a directory", preseedChroot) 96 } 97 98 // globs that yield individual files 99 globs := []string{ 100 dirs.SnapStateFile, 101 dirs.SnapSystemKeyFile, 102 filepath.Join(dirs.SnapBlobDir, "*.snap"), 103 filepath.Join(dirs.SnapUdevRulesDir, "*-snap.*.rules"), 104 filepath.Join(dirs.SnapDBusSystemPolicyDir, "snap.*.*.conf"), 105 filepath.Join(dirs.SnapServicesDir, "snap.*.service"), 106 filepath.Join(dirs.SnapServicesDir, "snap.*.timer"), 107 filepath.Join(dirs.SnapServicesDir, "snap.*.socket"), 108 filepath.Join(dirs.SnapServicesDir, "snap-*.mount"), 109 filepath.Join(dirs.SnapServicesDir, "multi-user.target.wants", "snap-*.mount"), 110 filepath.Join(dirs.SnapUserServicesDir, "snap.*.service"), 111 filepath.Join(dirs.SnapUserServicesDir, "snap.*.socket"), 112 filepath.Join(dirs.SnapUserServicesDir, "snap.*.timer"), 113 filepath.Join(dirs.SnapUserServicesDir, "default.target.wants", "snap.*.service"), 114 filepath.Join(dirs.SnapUserServicesDir, "sockets.target.wants", "snap.*.socket"), 115 filepath.Join(dirs.SnapUserServicesDir, "timers.target.wants", "snap.*.timer"), 116 filepath.Join(runinhibit.InhibitDir, "*.lock"), 117 } 118 119 for _, gl := range globs { 120 matches, err := filepath.Glob(filepath.Join(preseedChroot, gl)) 121 if err != nil { 122 // the only possible error from Glob() is ErrBadPattern 123 return err 124 } 125 for _, path := range matches { 126 if err := os.Remove(path); err != nil { 127 return fmt.Errorf("error removing %s: %v", path, err) 128 } 129 } 130 } 131 132 // directories that need to be removed recursively (but 133 // leaving parent directory intact). 134 globs = []string{ 135 filepath.Join(dirs.SnapDataDir, "*"), 136 filepath.Join(dirs.SnapCacheDir, "*"), 137 filepath.Join(apparmor_sandbox.CacheDir, "*"), 138 filepath.Join(dirs.SnapDesktopFilesDir, "*"), 139 filepath.Join(dirs.SnapDBusSessionServicesDir, "*"), 140 filepath.Join(dirs.SnapDBusSystemServicesDir, "*"), 141 } 142 143 for _, gl := range globs { 144 matches, err := filepath.Glob(filepath.Join(preseedChroot, gl)) 145 if err != nil { 146 // the only possible error from Glob() is ErrBadPattern 147 return err 148 } 149 for _, path := range matches { 150 if err := os.RemoveAll(path); err != nil { 151 return fmt.Errorf("error removing %s: %v", path, err) 152 } 153 } 154 } 155 156 // directories removed entirely 157 paths := []string{ 158 dirs.SnapAssertsDBDir, 159 dirs.FeaturesDir, 160 dirs.SnapDesktopIconsDir, 161 dirs.SnapDeviceDir, 162 dirs.SnapCookieDir, 163 dirs.SnapMountPolicyDir, 164 dirs.SnapAppArmorDir, 165 dirs.SnapSeqDir, 166 dirs.SnapMountDir, 167 dirs.SnapSeccompBase, 168 } 169 170 for _, path := range paths { 171 if err := os.RemoveAll(filepath.Join(preseedChroot, path)); err != nil { 172 // report the error and carry on 173 return fmt.Errorf("error removing %s: %v", path, err) 174 } 175 } 176 177 for _, completersPath := range []string{dirs.CompletersDir, dirs.LegacyCompletersDir} { 178 if err := resetCompletionSymlinks(filepath.Join(preseedChroot, completersPath)); err != nil { 179 return err 180 } 181 } 182 183 return nil 184 }