Exemplo n.º 1
0
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
}
Exemplo n.º 2
0
func (f *fakeSnappyBackend) RemoveSnapCommonData(info *snap.Info) error {
	f.ops = append(f.ops, fakeOp{
		op:   "remove-snap-common-data",
		name: info.MountDir(),
	})
	return nil
}
Exemplo n.º 3
0
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"))
}
Exemplo n.º 4
0
// 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
}
Exemplo n.º 5
0
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
}
Exemplo n.º 6
0
// 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()
}
Exemplo n.º 7
0
// 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]
}
Exemplo n.º 8
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,
	})
}
Exemplo n.º 9
0
// 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"),
	}
}
Exemplo n.º 10
0
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
}
Exemplo n.º 11
0
// 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)
}
Exemplo n.º 12
0
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)
}
Exemplo n.º 13
0
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)
}
Exemplo n.º 14
0
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
}
Exemplo n.º 15
0
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
}