// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package impl

// The device invoker is responsible for managing the state of the device
// manager itself.  The implementation expects that the device manager
// installations are all organized in the following directory structure:
//
// <config.Root>/
//   device-manager/
//     info                    - metadata for the device manager (such as object
//                               name and process id)
//     logs/                   - device manager logs
//       STDERR-<timestamp>    - one for each execution of device manager
//       STDOUT-<timestamp>    - one for each execution of device manager
//     <version 1 timestamp>/  - timestamp of when the version was downloaded
//       deviced               - the device manager binary
//       deviced.sh            - a shell script to start the binary
//     <version 2 timestamp>
//     ...
//     device-data/
//       acls/
//         data
//         signature
//     associated.accounts
//       persistent-args       - list of persistent arguments for the device
//                               manager (json encoded)
//
// The device manager is always expected to be started through the symbolic link
// passed in as config.CurrentLink, which is monitored by an init daemon. This
// provides for simple and robust updates.
//
// To update the device manager to a newer version, a new workspace is created
// and the symlink is updated to the new deviced.sh script. Similarly, to revert
// the device manager to a previous version, all that is required is to update
// the symlink to point to the previous deviced.sh script.

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"reflect"
	"strings"
	"sync"
	"time"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/naming"
	"v.io/v23/rpc"
	"v.io/v23/security"
	"v.io/v23/security/access"
	"v.io/v23/services/application"
	"v.io/v23/services/binary"
	"v.io/v23/services/device"
	"v.io/v23/verror"
	"v.io/x/ref"
	vexec "v.io/x/ref/lib/exec"
	"v.io/x/ref/lib/mgmt"
	vsecurity "v.io/x/ref/lib/security"
	"v.io/x/ref/services/agent/agentlib"
	"v.io/x/ref/services/device/internal/config"
	"v.io/x/ref/services/device/internal/errors"
	"v.io/x/ref/services/profile"
)

type updatingState struct {
	// updating is a flag that records whether this instance of device
	// manager is being updated.
	updating bool
	// updatingMutex is a lock for coordinating concurrent access to
	// <updating>.
	updatingMutex sync.Mutex
}

func newUpdatingState() *updatingState {
	return new(updatingState)
}

func (u *updatingState) testAndSetUpdating() bool {
	u.updatingMutex.Lock()
	defer u.updatingMutex.Unlock()
	if u.updating {
		return true
	}
	u.updating = true
	return false
}

func (u *updatingState) unsetUpdating() {
	u.updatingMutex.Lock()
	u.updating = false
	u.updatingMutex.Unlock()
}

// deviceService implements the Device manager's Device interface.
type deviceService struct {
	updating       *updatingState
	restartHandler func()
	callback       *callbackState
	config         *config.State
	disp           *dispatcher
	uat            BlessingSystemAssociationStore
	securityAgent  *securityAgentState
	tidying        chan<- tidyRequests
}

// ManagerInfo holds state about a running device manager or a running agentd
type ManagerInfo struct {
	Pid int
}

func SaveManagerInfo(dir string, info *ManagerInfo) error {
	jsonInfo, err := json.Marshal(info)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("Marshal(%v) failed: %v", info, err))
	}
	if err := os.MkdirAll(dir, os.FileMode(0700)); err != nil {
		return verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("MkdirAll(%v) failed: %v", dir, err))
	}
	infoPath := filepath.Join(dir, "info")
	if err := ioutil.WriteFile(infoPath, jsonInfo, 0600); err != nil {
		return verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("WriteFile(%v) failed: %v", infoPath, err))
	}
	return nil
}

func LoadManagerInfo(dir string) (*ManagerInfo, error) {
	infoPath := filepath.Join(dir, "info")
	info := new(ManagerInfo)
	if infoBytes, err := ioutil.ReadFile(infoPath); err != nil {
		return nil, verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("ReadFile(%v) failed: %v", infoPath, err))
	} else if err := json.Unmarshal(infoBytes, info); err != nil {
		return nil, verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("Unmarshal(%v) failed: %v", infoBytes, err))
	}
	return info, nil
}

func SavePersistentArgs(root string, args []string) error {
	dir := filepath.Join(root, "device-manager", "device-data")
	if err := os.MkdirAll(dir, 0700); err != nil {
		return fmt.Errorf("MkdirAll(%q) failed: %v", dir, err)
	}
	data, err := json.Marshal(args)
	if err != nil {
		return fmt.Errorf("Marshal(%v) failed: %v", args, err)
	}
	fileName := filepath.Join(dir, "persistent-args")
	return ioutil.WriteFile(fileName, data, 0600)
}

func loadPersistentArgs(root string) ([]string, error) {
	fileName := filepath.Join(root, "device-manager", "device-data", "persistent-args")
	bytes, err := ioutil.ReadFile(fileName)
	if err != nil {
		return nil, err
	}
	args := []string{}
	if err := json.Unmarshal(bytes, &args); err != nil {
		return nil, fmt.Errorf("json.Unmarshal(%v) failed: %v", bytes, err)
	}
	return args, nil
}

func (*deviceService) Describe(*context.T, rpc.ServerCall) (device.Description, error) {
	return Describe()
}

func (*deviceService) IsRunnable(_ *context.T, _ rpc.ServerCall, description binary.Description) (bool, error) {
	deviceProfile, err := ComputeDeviceProfile()
	if err != nil {
		return false, err
	}
	binaryProfiles := make([]*profile.Specification, 0)
	for name, _ := range description.Profiles {
		profile, err := getProfile(name)
		if err != nil {
			return false, err
		}
		binaryProfiles = append(binaryProfiles, profile)
	}
	result := matchProfiles(deviceProfile, binaryProfiles)
	return len(result.Profiles) > 0, nil
}

func (*deviceService) Reset(_ *context.T, _ rpc.ServerCall, deadline time.Duration) error {
	// TODO(jsimsa): Implement.
	return nil
}

// getCurrentFileInfo returns the os.FileInfo for both the symbolic link
// CurrentLink, and the device script in the workspace that this link points to.
func (s *deviceService) getCurrentFileInfo() (os.FileInfo, string, error) {
	path := s.config.CurrentLink
	link, err := os.Lstat(path)
	if err != nil {
		return nil, "", verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("Lstat(%v) failed: %v", path, err))
	}
	scriptPath, err := filepath.EvalSymlinks(path)
	if err != nil {
		return nil, "", verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("EvalSymlinks(%v) failed: %v", path, err))
	}
	return link, scriptPath, nil
}

func (s *deviceService) revertDeviceManager(ctx *context.T) error {
	if err := UpdateLink(s.config.Previous, s.config.CurrentLink); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("UpdateLink failed: %v", err))
	}
	if s.restartHandler != nil {
		s.restartHandler()
	}
	v23.GetAppCycle(ctx).Stop(ctx)
	return nil
}

func (s *deviceService) newLogfile(prefix string) (*os.File, error) {
	d := filepath.Join(s.config.Root, "device_test_logs")
	if _, err := os.Stat(d); err != nil {
		if err := os.MkdirAll(d, 0700); err != nil {
			return nil, err
		}
	}
	f, err := ioutil.TempFile(d, "__device_impl_test__"+prefix)
	if err != nil {
		return nil, err
	}
	return f, nil
}

// TODO(cnicolaou): would this be better implemented using the modules
// framework now that it exists?
func (s *deviceService) testDeviceManager(ctx *context.T, workspace string, envelope *application.Envelope) error {
	path := filepath.Join(workspace, "deviced.sh")
	cmd := exec.Command(path)
	cmd.Env = []string{"DEVICE_MANAGER_DONT_REDIRECT_STDOUT_STDERR=1"}

	for k, v := range map[string]*io.Writer{
		"stdout": &cmd.Stdout,
		"stderr": &cmd.Stderr,
	} {
		// Using a log file makes it less likely that stdout and stderr
		// output will be lost if the child crashes.
		file, err := s.newLogfile(fmt.Sprintf("deviced-test-%s", k))
		if err != nil {
			return err
		}
		fName := file.Name()
		defer os.Remove(fName)
		*v = file

		defer func(k string) {
			if f, err := os.Open(fName); err == nil {
				scanner := bufio.NewScanner(f)
				for scanner.Scan() {
					ctx.Infof("[testDeviceManager %s] %s", k, scanner.Text())
				}
			}
		}(k)
	}

	// Setup up the child process callback.
	callbackState := s.callback
	listener := callbackState.listenFor(mgmt.ChildNameConfigKey)
	defer listener.cleanup()
	cfg := vexec.NewConfig()

	cfg.Set(mgmt.ParentNameConfigKey, listener.name())
	cfg.Set(mgmt.ProtocolConfigKey, "tcp")
	cfg.Set(mgmt.AddressConfigKey, "127.0.0.1:0")

	var p security.Principal
	var agentHandle []byte

	switch sa := s.securityAgent; {
	case sa != nil && sa.keyMgr != nil:
		handle, err := sa.keyMgr.NewPrincipal(true)
		if err != nil {
			return verror.New(errors.ErrOperationFailed, ctx, "NewPrincipal() failed", err)
		}
		sockDir, err := generateAgentSockDir(s.config.Root)
		if err != nil {
			return verror.New(errors.ErrOperationFailed, ctx, "generateAgentSockDir() failed", err)
		}
		// TODO(caprita): Add a check to ensure that len(sockPath) < 108.
		sockPath := filepath.Join(sockDir, "s")
		if err := sa.keyMgr.ServePrincipal(handle, sockPath); err != nil {
			return verror.New(errors.ErrOperationFailed, ctx, "ServePrincipal failed", err)
		}
		cfg.Set(mgmt.SecurityAgentPathConfigKey, sockPath)
		defer func() {
			if err := sa.keyMgr.StopServing(handle); err != nil {
				ctx.Errorf("StopServing failed: %v", err)
			}
			if err := sa.keyMgr.DeletePrincipal(handle); err != nil {
				ctx.Errorf("DeletePrincipal failed: %v", err)
			}
		}()
		if p, err = agentlib.NewAgentPrincipalX(sockPath); err != nil {
			return verror.New(errors.ErrOperationFailed, ctx, "NewAgentPrincipalX failed", err)
		}
	case sa != nil && sa.keyMgrAgent != nil:
		// This code path is deprecated in favor of the socket agent
		// connection.
		handle, conn, err := sa.keyMgrAgent.NewPrincipal(ctx, true)
		if err != nil {
			return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("NewPrincipal() failed %v", err))
		}
		agentHandle = handle
		var cancel func()
		if p, cancel, err = agentPrincipal(ctx, conn); err != nil {
			return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("agentPrincipal failed: %v", err))
		}
		defer cancel()
	default:
		credentialsDir := filepath.Join(workspace, "credentials")
		var err error
		if p, err = vsecurity.CreatePersistentPrincipal(credentialsDir, nil); err != nil {
			return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("CreatePersistentPrincipal(%v, nil) failed: %v", credentialsDir, err))
		}
		cmd.Env = append(cmd.Env, ref.EnvCredentials+"="+credentialsDir)
	}
	dmPrincipal := v23.GetPrincipal(ctx)
	dmBlessings, err := dmPrincipal.Bless(p.PublicKey(), dmPrincipal.BlessingStore().Default(), "testdm", security.UnconstrainedUse())
	if err := p.BlessingStore().SetDefault(dmBlessings); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("BlessingStore.SetDefault() failed: %v", err))
	}
	if _, err := p.BlessingStore().Set(dmBlessings, security.AllPrincipals); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("BlessingStore.Set() failed: %v", err))
	}
	if err := security.AddToRoots(p, dmBlessings); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("AddToRoots() failed: %v", err))
	}

	if s.securityAgent != nil && s.securityAgent.keyMgrAgent != nil {
		// This code path is deprecated in favor of the socket agent
		// connection.
		file, err := s.securityAgent.keyMgrAgent.NewConnection(agentHandle)
		if err != nil {
			return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("NewConnection(%v) failed: %v", agentHandle, err))
		}
		defer file.Close()

		fd := len(cmd.ExtraFiles) + vexec.FileOffset
		cmd.ExtraFiles = append(cmd.ExtraFiles, file)
		// TODO: This should use the same network as the agent we're using,
		// not whatever this process was compiled with.
		ep := agentlib.AgentEndpoint(fd)
		cfg.Set(mgmt.SecurityAgentEndpointConfigKey, ep)
	}

	handle := vexec.NewParentHandle(cmd, vexec.ConfigOpt{Config: cfg})
	// Start the child process.
	if err := handle.Start(); err != nil {
		ctx.Errorf("Start() failed: %v", err)
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Start() failed: %v", err))
	}
	defer func() {
		if err := handle.Clean(); err != nil {
			ctx.Errorf("Clean() failed: %v", err)
		}
	}()

	// Wait for the child process to start.
	if err := handle.WaitForReady(childReadyTimeout); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("WaitForReady(%v) failed: %v", childReadyTimeout, err))
	}

	// Watch for the exit of the child. Failures could cause it to happen at any time
	waitchan := make(chan error, 1)
	go func() {
		// Wait timeout needs to be long enough to give the rest of the operations time to run
		err := handle.Wait(2*childReadyTimeout + childWaitTimeout)
		if err != nil {
			waitchan <- verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("new device manager failed to exit cleanly: %v", err))
		}
		close(waitchan)
		listener.stop()
	}()

	childName, err := listener.waitForValue(childReadyTimeout)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("waitForValue(%v) failed: %v", childReadyTimeout, err))
	}
	// Check that invoking Delete() succeeds.
	childName = naming.Join(childName, "device")
	dmClient := device.DeviceClient(childName)
	if err := dmClient.Delete(ctx); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Delete() failed: %v", err))
	}
	if err := <-waitchan; err != nil {
		return err
	}
	return nil
}

// TODO(caprita): Move this to util.go since device_installer is also using it now.

func GenerateScript(workspace string, configSettings []string, envelope *application.Envelope, logs string) error {
	// TODO(caprita): Remove this snippet of code, it doesn't seem to serve
	// any purpose.
	path, err := filepath.EvalSymlinks(os.Args[0])
	if err != nil {
		return verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("EvalSymlinks(%v) failed: %v", os.Args[0], err))
	}

	if err := os.MkdirAll(logs, 0711); err != nil {
		return verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("MkdirAll(%v) failed: %v", logs, err))
	}
	stderrLog, stdoutLog := filepath.Join(logs, "STDERR"), filepath.Join(logs, "STDOUT")

	output := "#!" + ShellPath + "\n"
	output += "if [ -z \"$DEVICE_MANAGER_DONT_REDIRECT_STDOUT_STDERR\" ]; then\n"
	output += fmt.Sprintf("  TIMESTAMP=$(%s)\n", DateCommand)
	output += fmt.Sprintf("  exec > %s-$TIMESTAMP 2> %s-$TIMESTAMP\n", stdoutLog, stderrLog)
	output += "  LOG_TO_STDERR=false\n"
	output += "else\n"
	output += "  LOG_TO_STDERR=true\n"
	output += "fi\n"
	output += strings.Join(config.QuoteEnv(append(envelope.Env, configSettings...)), " ") + " "
	// Escape the path to the binary; %q uses Go-syntax escaping, but it's
	// close enough to Bash that we're using it as an approximation.
	//
	// TODO(caprita/rthellend): expose and use shellEscape (from
	// v.io/x/ref/services/debug/debug/impl.go) instead.
	output += fmt.Sprintf("exec %q", filepath.Join(workspace, "deviced")) + " "
	output += fmt.Sprintf("--log_dir=%q ", logs)
	output += "--logtostderr=${LOG_TO_STDERR} "
	output += strings.Join(envelope.Args, " ")

	path = filepath.Join(workspace, "deviced.sh")
	if err := ioutil.WriteFile(path, []byte(output), 0700); err != nil {
		return verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("WriteFile(%v) failed: %v", path, err))
	}
	return nil
}

func (s *deviceService) updateDeviceManager(ctx *context.T) error {
	if len(s.config.Origin) == 0 {
		return verror.New(errors.ErrUpdateNoOp, ctx)
	}
	envelope, err := fetchEnvelope(ctx, s.config.Origin)
	if err != nil {
		return err
	}
	if envelope.Title != application.DeviceManagerTitle {
		return verror.New(errors.ErrAppTitleMismatch, ctx, fmt.Sprintf("app title mismatch. Got %q, expected %q.", envelope.Title, application.DeviceManagerTitle))
	}
	// Read and merge persistent args, if present.
	if args, err := loadPersistentArgs(s.config.Root); err == nil {
		envelope.Args = append(envelope.Args, args...)
	}
	if s.config.Envelope != nil && reflect.DeepEqual(envelope, s.config.Envelope) {
		return verror.New(errors.ErrUpdateNoOp, ctx)
	}
	// Create new workspace.
	workspace := filepath.Join(s.config.Root, "device-manager", generateVersionDirName())
	perm := os.FileMode(0700)
	if err := os.MkdirAll(workspace, perm); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("MkdirAll(%v, %v) failed: %v", workspace, perm, err))
	}

	deferrer := func() {
		CleanupDir(ctx, workspace, "")
	}
	defer func() {
		if deferrer != nil {
			deferrer()
		}
	}()

	// Populate the new workspace with a device manager binary.
	// TODO(caprita): match identical binaries on binary signature
	// rather than binary object name.
	sameBinary := s.config.Envelope != nil && envelope.Binary.File == s.config.Envelope.Binary.File
	if sameBinary {
		if err := LinkSelf(workspace, "deviced"); err != nil {
			return err
		}
	} else {
		if err := downloadBinary(ctx, envelope.Publisher, &envelope.Binary, workspace, "deviced"); err != nil {
			return err
		}
	}

	// Populate the new workspace with a device manager script.
	configSettings, err := s.config.Save(envelope)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, err)
	}

	logs := filepath.Join(s.config.Root, "device-manager", "logs")
	if err := GenerateScript(workspace, configSettings, envelope, logs); err != nil {
		return err
	}

	if err := s.testDeviceManager(ctx, workspace, envelope); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("testDeviceManager failed: %v", err))
	}

	if err := UpdateLink(filepath.Join(workspace, "deviced.sh"), s.config.CurrentLink); err != nil {
		return err
	}

	if s.restartHandler != nil {
		s.restartHandler()
	}
	v23.GetAppCycle(ctx).Stop(ctx)
	deferrer = nil
	return nil
}

func (*deviceService) Install(ctx *context.T, _ rpc.ServerCall, _ string, _ device.Config, _ application.Packages) (string, error) {
	return "", verror.New(errors.ErrInvalidSuffix, ctx)
}

func (*deviceService) Run(ctx *context.T, _ rpc.ServerCall) error {
	return verror.New(errors.ErrInvalidSuffix, ctx)
}

func (s *deviceService) Revert(ctx *context.T, _ rpc.ServerCall) error {
	if s.config.Previous == "" {
		return verror.New(errors.ErrUpdateNoOp, ctx, fmt.Sprintf("Revert failed: no previous version"))
	}
	updatingState := s.updating
	if updatingState.testAndSetUpdating() {
		return verror.New(errors.ErrOperationInProgress, ctx, fmt.Sprintf("Revert failed: already in progress"))
	}
	err := s.revertDeviceManager(ctx)
	if err != nil {
		updatingState.unsetUpdating()
	}
	return err
}

func (*deviceService) Instantiate(ctx *context.T, _ device.ApplicationInstantiateServerCall) (string, error) {
	return "", verror.New(errors.ErrInvalidSuffix, ctx)
}

func (*deviceService) Delete(ctx *context.T, _ rpc.ServerCall) error {
	v23.GetAppCycle(ctx).Stop(ctx)
	return nil
}

func (s *deviceService) Kill(ctx *context.T, _ rpc.ServerCall, _ time.Duration) error {
	if s.restartHandler != nil {
		s.restartHandler()
	}
	v23.GetAppCycle(ctx).Stop(ctx)
	return nil
}

func (*deviceService) Uninstall(ctx *context.T, _ rpc.ServerCall) error {
	return verror.New(errors.ErrInvalidSuffix, ctx)
}

func (s *deviceService) Update(ctx *context.T, _ rpc.ServerCall) error {
	ctx, cancel := context.WithTimeout(ctx, rpcContextLongTimeout)
	defer cancel()

	updatingState := s.updating
	if updatingState.testAndSetUpdating() {
		return verror.New(errors.ErrOperationInProgress, ctx)
	}

	err := s.updateDeviceManager(ctx)
	if err != nil {
		updatingState.unsetUpdating()
	}
	return err
}

func (*deviceService) UpdateTo(*context.T, rpc.ServerCall, string) error {
	// TODO(jsimsa): Implement.
	return nil
}

func (s *deviceService) SetPermissions(_ *context.T, _ rpc.ServerCall, perms access.Permissions, version string) error {
	d := PermsDir(s.disp.config)
	return s.disp.permsStore.Set(d, perms, version)
}

func (s *deviceService) GetPermissions(*context.T, rpc.ServerCall) (perms access.Permissions, version string, err error) {
	d := PermsDir(s.disp.config)
	return s.disp.permsStore.Get(d)
}

// TODO(rjkroege): Make it possible for users on the same system to also
// associate their accounts with their identities.
func (s *deviceService) AssociateAccount(_ *context.T, _ rpc.ServerCall, identityNames []string, accountName string) error {
	if accountName == "" {
		return s.uat.DisassociateSystemAccountForBlessings(identityNames)
	}
	// TODO(rjkroege): Optionally verify here that the required uname is a valid.
	return s.uat.AssociateSystemAccountForBlessings(identityNames, accountName)
}

func (s *deviceService) ListAssociations(ctx *context.T, call rpc.ServerCall) (associations []device.Association, err error) {
	// Temporary code. Dump this.
	if ctx.V(2) {
		b, r := security.RemoteBlessingNames(ctx, call.Security())
		ctx.Infof("ListAssociations given blessings: %v\n", b)
		if len(r) > 0 {
			ctx.Infof("ListAssociations rejected blessings: %v\n", r)
		}
	}
	return s.uat.AllBlessingSystemAssociations()
}

func (*deviceService) Debug(*context.T, rpc.ServerCall) (string, error) {
	return "Not implemented", nil
}

func (s *deviceService) Status(*context.T, rpc.ServerCall) (device.Status, error) {
	state := device.InstanceStateRunning
	if s.updating.updating {
		state = device.InstanceStateUpdating
	}
	// Extract the version from the current link path.
	//
	// TODO(caprita): make the version available in the device's directory.
	scriptPath, err := filepath.EvalSymlinks(s.config.CurrentLink)
	if err != nil {
		return nil, err
	}
	dir := filepath.Dir(scriptPath)
	versionDir := filepath.Base(dir)
	if versionDir == "." {
		versionDir = "base"
	}
	return device.StatusDevice{Value: device.DeviceStatus{
		State:   state,
		Version: versionDir,
	}}, nil
}

func (s *deviceService) TidyNow(ctx *context.T, _ rpc.ServerCall) error {
	ec := make(chan error)
	s.tidying <- tidyRequests{ctx: ctx, bc: ec}
	return <-ec
}
