boxdd: Add custom working directory support
This commit is contained in:
@@ -2,9 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
@@ -29,10 +27,12 @@ func preparePlatformWorkingDirectory() error {
|
||||
if listenAddress != "" {
|
||||
return os.MkdirAll(workingDirectory, 0o700)
|
||||
}
|
||||
if !strings.EqualFold(filepath.Clean(workingDirectory), filepath.Clean(defaultServiceWorkingDirectory)) {
|
||||
return E.New("the Windows service working directory must be ", defaultServiceWorkingDirectory)
|
||||
serviceWorkingDirectory, err := resolveWindowsServiceWorkingDirectory(workingDirectory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ensureWindowsWorkingDirectory(workingDirectory)
|
||||
workingDirectory = serviceWorkingDirectory
|
||||
return ensureWindowsWorkingDirectory(serviceWorkingDirectory)
|
||||
}
|
||||
|
||||
type windowsService struct{}
|
||||
|
||||
@@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -65,19 +64,24 @@ func serviceInstall() error {
|
||||
if err != nil {
|
||||
return E.Cause(err, "get executable path")
|
||||
}
|
||||
if !strings.EqualFold(filepath.Clean(commandServiceFlagWorkingDirectory), filepath.Clean(defaultServiceWorkingDirectory)) {
|
||||
return E.New("the Windows service working directory must be ", defaultServiceWorkingDirectory)
|
||||
serviceWorkingDirectory, err := resolveWindowsServiceWorkingDirectory(commandServiceFlagWorkingDirectory)
|
||||
if err != nil {
|
||||
return E.Cause(err, "validate working directory")
|
||||
}
|
||||
executablePath, err = secureWindowsInstallation(executablePath, commandServiceFlagAllowUnsafeInstallation)
|
||||
if err != nil {
|
||||
return E.Cause(err, "secure installation")
|
||||
}
|
||||
err = ensureWindowsWorkingDirectory(serviceWorkingDirectory)
|
||||
if err != nil {
|
||||
return E.Cause(err, "secure working directory")
|
||||
}
|
||||
manager, err := mgr.Connect()
|
||||
if err != nil {
|
||||
return E.Cause(err, "connect to service manager")
|
||||
}
|
||||
defer manager.Disconnect()
|
||||
arguments := []string{"run", "--working-directory", defaultServiceWorkingDirectory}
|
||||
arguments := []string{"run", "--working-directory", serviceWorkingDirectory}
|
||||
config := mgr.Config{
|
||||
DisplayName: serviceDisplayName,
|
||||
Description: serviceDescriptionText,
|
||||
@@ -132,11 +136,6 @@ func serviceInstall() error {
|
||||
rollback()
|
||||
return E.Cause(err, "secure service")
|
||||
}
|
||||
err = ensureWindowsWorkingDirectory(defaultServiceWorkingDirectory)
|
||||
if err != nil {
|
||||
rollback()
|
||||
return E.Cause(err, "secure working directory")
|
||||
}
|
||||
err = eventlog.InstallAsEventCreate(serviceName, eventlog.Error|eventlog.Warning|eventlog.Info)
|
||||
if err != nil && !strings.Contains(err.Error(), "already exists") {
|
||||
rollback()
|
||||
|
||||
@@ -336,6 +336,40 @@ func validateFixedNTFSVolume(path string) (string, error) {
|
||||
return filepath.Clean(volumePath), nil
|
||||
}
|
||||
|
||||
func resolveWindowsServiceWorkingDirectory(path string) (string, error) {
|
||||
if path == "" {
|
||||
return "", E.New("missing daemon working directory")
|
||||
}
|
||||
absolutePath, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return "", E.Cause(err, "resolve daemon working directory")
|
||||
}
|
||||
cleanPath := filepath.Clean(absolutePath)
|
||||
parentPath := filepath.Dir(cleanPath)
|
||||
parentAttributes, err := windowsFileAttributes(parentPath)
|
||||
if err != nil {
|
||||
return "", E.Cause(err, "query daemon working directory parent")
|
||||
}
|
||||
if parentAttributes&windows.FILE_ATTRIBUTE_DIRECTORY == 0 {
|
||||
return "", E.New("daemon working directory parent is not a directory")
|
||||
}
|
||||
if parentAttributes&windows.FILE_ATTRIBUTE_REPARSE_POINT != 0 {
|
||||
return "", E.New("daemon working directory parent is a reparse point")
|
||||
}
|
||||
volumeRoot, err := validateFixedNTFSVolume(parentPath)
|
||||
if err != nil {
|
||||
return "", E.Cause(err, "validate daemon working directory volume")
|
||||
}
|
||||
if strings.EqualFold(cleanPath, filepath.Clean(volumeRoot)) {
|
||||
return "", E.New("daemon working directory must not be a volume root")
|
||||
}
|
||||
err = validateInstallationAncestors(parentPath, volumeRoot, true)
|
||||
if err != nil {
|
||||
return "", E.Cause(err, "validate daemon working directory ancestors")
|
||||
}
|
||||
return cleanPath, nil
|
||||
}
|
||||
|
||||
func validateInstallationAncestors(path string, volumeRoot string, validatePermissions bool) error {
|
||||
currentPath := filepath.Clean(path)
|
||||
cleanVolumeRoot := filepath.Clean(volumeRoot)
|
||||
|
||||
Reference in New Issue
Block a user