// UnlinkSnap deactivates the given active snap. func UnlinkSnap(info *snap.Info, inter interacter) error { mountDir := info.MountDir() currentSymlink := filepath.Join(mountDir, "..", "current") currentActiveDir, err := filepath.EvalSymlinks(currentSymlink) if err != nil { if os.IsNotExist(err) { return ErrSnapNotActive } return err } if mountDir != currentActiveDir { return ErrSnapNotActive } // remove generated services, binaries, security policy err1 := RemoveGeneratedWrappers(info, inter) // removing security setup move here! // and finally remove current symlink err2 := removeCurrentSymlink(info, inter) // FIXME: aggregate errors instead return firstErr(err1, err2) }
func addPackageBinaries(s *snap.Info) error { if err := os.MkdirAll(dirs.SnapBinariesDir, 0755); err != nil { return err } baseDir := s.MountDir() for _, app := range s.Apps { if app.Daemon != "" { continue } // this will remove the global base dir when generating the // service file, this ensures that /snap/foo/1.0/bin/start // is in the service file when the SetRoot() option // is used realBaseDir := stripGlobalRootDir(baseDir) content, err := generateSnapBinaryWrapper(app, realBaseDir) if err != nil { return err } if err := osutil.AtomicWriteFile(app.WrapperPath(), []byte(content), 0755, 0); err != nil { return err } } return nil }
// XXX: would really like not to expose this but used in daemon tests atm func UpdateCurrentSymlink(info *snap.Info, inter interacter) error { mountDir := info.MountDir() currentActiveSymlink := filepath.Join(mountDir, "..", "current") if err := os.Remove(currentActiveSymlink); err != nil && !os.IsNotExist(err) { logger.Noticef("Failed to remove %q: %v", currentActiveSymlink, err) } dataDir := info.DataDir() dbase := filepath.Dir(dataDir) currentDataSymlink := filepath.Join(dbase, "current") if err := os.Remove(currentDataSymlink); err != nil && !os.IsNotExist(err) { logger.Noticef("Failed to remove %q: %v", currentDataSymlink, err) } // symlink is relative to parent dir if err := os.Symlink(filepath.Base(mountDir), currentActiveSymlink); err != nil { return err } if err := os.MkdirAll(info.DataDir(), 0755); err != nil { return err } // FIXME: create {Os,Kernel}Snap type instead of adding special // cases here if err := setNextBoot(info); err != nil { return err } return os.Symlink(filepath.Base(dataDir), currentDataSymlink) }
func addPackageDesktopFiles(s *snap.Info) error { if err := os.MkdirAll(dirs.SnapDesktopFilesDir, 0755); err != nil { return err } baseDir := s.MountDir() desktopFiles, err := filepath.Glob(filepath.Join(baseDir, "meta", "gui", "*.desktop")) if err != nil { return fmt.Errorf("cannot get desktop files for %v: %s", baseDir, err) } for _, df := range desktopFiles { content, err := ioutil.ReadFile(df) if err != nil { return err } realBaseDir := stripGlobalRootDir(baseDir) content = sanitizeDesktopFile(s, realBaseDir, content) installedDesktopFileName := filepath.Join(dirs.SnapDesktopFilesDir, fmt.Sprintf("%s_%s", s.Name(), filepath.Base(df))) if err := osutil.AtomicWriteFile(installedDesktopFileName, []byte(content), 0755, 0); err != nil { return err } } return nil }
func (f *fakeSnappyBackend) RemoveSnapData(info *snap.Info) error { f.ops = append(f.ops, fakeOp{ op: "remove-snap-data", name: info.MountDir(), }) return nil }
func (f *fakeSnappyBackend) UndoCopySnapData(newInfo *snap.Info, flags int) error { f.ops = append(f.ops, fakeOp{ op: "undo-copy-snap-data", name: newInfo.MountDir(), }) return nil }
// snapDate returns the time of the snap mount directory. func snapDate(info *snap.Info) time.Time { st, err := os.Stat(info.MountDir()) if err != nil { return time.Time{} } return st.ModTime() }
func (f *fakeSnappyBackend) UnlinkSnap(info *snap.Info, meter progress.Meter) error { meter.Notify("unlink") f.ops = append(f.ops, fakeOp{ op: "unlink-snap", name: info.MountDir(), }) return nil }
func (f *fakeSnappyBackend) CanRemove(info *snap.Info, active bool) bool { f.ops = append(f.ops, fakeOp{ op: "can-remove", name: info.MountDir(), active: active, }) return true }
// snapIcon tries to find the icon inside the snap func snapIcon(info *snap.Info) string { // XXX: copy of snap.Snap.Icon which will go away found, _ := filepath.Glob(filepath.Join(info.MountDir(), "meta", "gui", "icon.*")) if len(found) == 0 { return "" } return found[0] }
func (f *fakeSnappyBackend) CheckSnap(snapFilePath string, curInfo *snap.Info, flags int) error { cur := "<no-current>" if curInfo != nil { cur = curInfo.MountDir() } f.ops = append(f.ops, fakeOp{ op: "check-snap", name: snapFilePath, old: cur, flags: flags, }) return nil }
func (f *fakeSnappyBackend) CopySnapData(newInfo, oldInfo *snap.Info, flags int) error { old := "<no-old>" if oldInfo != nil { old = oldInfo.MountDir() } f.ops = append(f.ops, fakeOp{ op: "copy-data", name: newInfo.MountDir(), flags: flags, old: old, }) return nil }
func addSquashfsMount(s *snap.Info, inhibitHooks bool, inter interacter) error { squashfsPath := stripGlobalRootDir(s.MountFile()) whereDir := stripGlobalRootDir(s.MountDir()) sysd := systemd.New(dirs.GlobalRootDir, inter) mountUnitName, err := sysd.WriteMountUnitFile(s.Name(), squashfsPath, whereDir) if err != nil { return err } // we always enable the mount unit even in inhibit hooks if err := sysd.Enable(mountUnitName); err != nil { return err } if !inhibitHooks { return sysd.Start(mountUnitName) } return nil }
func (f *fakeSnappyBackend) LinkSnap(info *snap.Info) error { if info.MountDir() == f.linkSnapFailTrigger { f.ops = append(f.ops, fakeOp{ op: "link-snap.failed", name: info.MountDir(), }) return errors.New("fail") } f.ops = append(f.ops, fakeOp{ op: "link-snap", name: info.MountDir(), }) return nil }
func addPackageServices(s *snap.Info, inter interacter) error { baseDir := s.MountDir() for _, app := range s.Apps { if app.Daemon == "" { continue } // this will remove the global base dir when generating the // service file, this ensures that /snap/foo/1.0/bin/start // is in the service file when the SetRoot() option // is used realBaseDir := stripGlobalRootDir(baseDir) // Generate service file content, err := generateSnapServicesFile(app, realBaseDir) if err != nil { return err } svcFilePath := app.ServiceFile() os.MkdirAll(filepath.Dir(svcFilePath), 0755) if err := osutil.AtomicWriteFile(svcFilePath, []byte(content), 0644, 0); err != nil { return err } // Generate systemd socket file if needed if app.Socket { content, err := generateSnapSocketFile(app, realBaseDir) if err != nil { return err } svcSocketFilePath := app.ServiceSocketFile() os.MkdirAll(filepath.Dir(svcSocketFilePath), 0755) if err := osutil.AtomicWriteFile(svcSocketFilePath, []byte(content), 0644, 0); err != nil { return err } } // daemon-reload and enable plus start serviceName := filepath.Base(app.ServiceFile()) sysd := systemd.New(dirs.GlobalRootDir, inter) if err := sysd.DaemonReload(); err != nil { return err } // enable the service if err := sysd.Enable(serviceName); err != nil { return err } if err := sysd.Start(serviceName); err != nil { return err } if app.Socket { socketName := filepath.Base(app.ServiceSocketFile()) // enable the socket if err := sysd.Enable(socketName); err != nil { return err } if err := sysd.Start(socketName); err != nil { return err } } } return nil }