func (f *fakeSnappyBackend) StopSnapServices(info *snap.Info, meter progress.Meter) error { f.ops = append(f.ops, fakeOp{ op: "stop-snap-services", name: info.MountDir(), }) return nil }
func (f *fakeSnappyBackend) RemoveSnapCommonData(info *snap.Info) error { f.ops = append(f.ops, fakeOp{ op: "remove-snap-common-data", name: info.MountDir(), }) return nil }
func sanitizeDesktopFile(s *snap.Info, desktopFile string, rawcontent []byte) []byte { newContent := []string{} scanner := bufio.NewScanner(bytes.NewReader(rawcontent)) for scanner.Scan() { line := scanner.Text() // whitespace/comments are just copied if strings.TrimSpace(line) == "" || strings.HasPrefix(strings.TrimSpace(line), "#") { newContent = append(newContent, line) continue } // ignore everything we have not whitelisted if !isValidDesktopFilePrefix(line) && !isValidLocalizedDesktopFilePrefix(line) { continue } // rewrite exec lines to an absolute path for the binary if strings.HasPrefix(line, "Exec=") { var err error line, err = rewriteExecLine(s, desktopFile, line) if err != nil { // something went wrong, ignore the line continue } } // do variable substitution line = strings.Replace(line, "${SNAP}", s.MountDir(), -1) newContent = append(newContent, line) } return []byte(strings.Join(newContent, "\n")) }
// AddSnapDesktopFiles puts in place the desktop files for the applications from the snap. func AddSnapDesktopFiles(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 } installedDesktopFileName := filepath.Join(dirs.SnapDesktopFilesDir, fmt.Sprintf("%s_%s", s.Name(), filepath.Base(df))) content = sanitizeDesktopFile(s, installedDesktopFileName, content) if err := osutil.AtomicWriteFile(installedDesktopFileName, []byte(content), 0755, 0); err != nil { return err } } // updates mime info etc if err := updateDesktopDatabase(desktopFiles); err != nil { return err } return nil }
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 }
// 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() }
// 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 info.IconURL } return found[0] }
func (f *fakeSnappyBackend) CurrentInfo(curInfo *snap.Info) { old := "<no-current>" if curInfo != nil { old = curInfo.MountDir() } f.ops = append(f.ops, fakeOp{ op: "current", old: old, }) }
// basicEnv returns the app-level environment variables for a snap. // Despite this being a bit snap-specific, this is in helpers.go because it's // used by so many other modules, we run into circular dependencies if it's // somewhere more reasonable like the snappy module. func basicEnv(info *snap.Info) map[string]string { return map[string]string{ "SNAP": info.MountDir(), "SNAP_COMMON": info.CommonDataDir(), "SNAP_DATA": info.DataDir(), "SNAP_NAME": info.Name(), "SNAP_VERSION": info.Version, "SNAP_REVISION": info.Revision.String(), "SNAP_ARCH": arch.UbuntuArchitecture(), "SNAP_LIBRARY_PATH": "/var/lib/snapd/lib/gl:", "SNAP_REEXEC": os.Getenv("SNAP_REEXEC"), } }
func (f *fakeSnappyBackend) UndoCopySnapData(newInfo *snap.Info, oldInfo *snap.Info, p progress.Meter) error { p.Notify("undo-copy-data") old := "<no-old>" if oldInfo != nil { old = oldInfo.MountDir() } f.ops = append(f.ops, fakeOp{ op: "undo-copy-snap-data", name: newInfo.MountDir(), old: old, }) return nil }
// resolveSpecialVariable resolves one of the three $SNAP* variables at the // beginning of a given path. The variables are $SNAP, $SNAP_DATA and // $SNAP_COMMON. If there are no variables then $SNAP is implicitly assumed // (this is the behavior that was used before the variables were supporter). func resolveSpecialVariable(path string, snapInfo *snap.Info) string { if strings.HasPrefix(path, "$SNAP/") || path == "$SNAP" { return strings.Replace(path, "$SNAP", snapInfo.MountDir(), 1) } if strings.HasPrefix(path, "$SNAP_DATA/") || path == "$SNAP_DATA" { return strings.Replace(path, "$SNAP_DATA", snapInfo.DataDir(), 1) } if strings.HasPrefix(path, "$SNAP_COMMON/") || path == "$SNAP_COMMON" { return strings.Replace(path, "$SNAP_COMMON", snapInfo.CommonDataDir(), 1) } // NOTE: assume $SNAP by default if nothing else is provided, for compatibility return filepath.Join(snapInfo.MountDir(), path) }
func addMountUnit(s *snap.Info, meter progress.Meter) error { squashfsPath := dirs.StripRootDir(s.MountFile()) whereDir := dirs.StripRootDir(s.MountDir()) sysd := systemd.New(dirs.GlobalRootDir, meter) mountUnitName, err := sysd.WriteMountUnitFile(s.Name(), squashfsPath, whereDir, "squashfs") if err != nil { return err } // we need to do a daemon-reload here to ensure that systemd really // knows about this new mount unit file if err := sysd.DaemonReload(); err != nil { return err } if err := sysd.Enable(mountUnitName); err != nil { return err } return sysd.Start(mountUnitName) }
func updateCurrentSymlinks(info *snap.Info) error { mountDir := info.MountDir() currentActiveSymlink := filepath.Join(mountDir, "..", "current") if err := os.Remove(currentActiveSymlink); err != nil && !os.IsNotExist(err) { logger.Noticef("Cannot remove %q: %v", currentActiveSymlink, err) } dataDir := info.DataDir() currentDataSymlink := filepath.Join(dataDir, "..", "current") if err := os.Remove(currentDataSymlink); err != nil && !os.IsNotExist(err) { logger.Noticef("Cannot remove %q: %v", currentDataSymlink, err) } if err := os.MkdirAll(info.DataDir(), 0755); err != nil { return err } if err := os.Symlink(filepath.Base(dataDir), currentDataSymlink); err != nil { return err } return os.Symlink(filepath.Base(mountDir), currentActiveSymlink) }
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 (f *fakeSnappyBackend) CopySnapData(newInfo, oldInfo *snap.Info, p progress.Meter) error { p.Notify("copy-data") old := "<no-old>" if oldInfo != nil { old = oldInfo.MountDir() } if newInfo.MountDir() == f.copySnapDataFailTrigger { f.ops = append(f.ops, fakeOp{ op: "copy-data.failed", name: newInfo.MountDir(), old: old, }) return errors.New("fail") } f.ops = append(f.ops, fakeOp{ op: "copy-data", name: newInfo.MountDir(), old: old, }) return nil }