From 8009bcf6547be4820804c41a7d1a236f9240e23d Mon Sep 17 00:00:00 2001 From: Ben Johnson Date: Sat, 5 Feb 2022 08:11:21 -0700 Subject: [PATCH] Remove Windows support Unfortunately, I don't have the expertise or bandwidth to maintain the Windows support in Litestream. I'm open to re-adding support in the future but right now it is hindering development and is not well-tested or well-used. --- cmd/litestream/main.go | 12 +--- cmd/litestream/main_notwindows.go | 21 ------ cmd/litestream/main_windows.go | 108 ------------------------------ go.mod | 1 - internal/internal.go | 11 ++- internal/internal_unix.go | 21 ------ internal/internal_windows.go | 22 ------ 7 files changed, 13 insertions(+), 183 deletions(-) delete mode 100644 cmd/litestream/main_notwindows.go delete mode 100644 cmd/litestream/main_windows.go delete mode 100644 internal/internal_unix.go delete mode 100644 internal/internal_windows.go diff --git a/cmd/litestream/main.go b/cmd/litestream/main.go index ac9d5a5..3373eca 100644 --- a/cmd/litestream/main.go +++ b/cmd/litestream/main.go @@ -17,6 +17,7 @@ import ( "regexp" "strconv" "strings" + "syscall" "time" "github.com/benbjohnson/litestream" @@ -67,13 +68,6 @@ func NewMain(stdin io.Reader, stdout, stderr io.Writer) *Main { // Run executes the program. func (m *Main) Run(ctx context.Context, args []string) (err error) { - // Execute replication command if running as a Windows service. - if isService, err := isWindowsService(); err != nil { - return err - } else if isService { - return runWindowsService(ctx) - } - // Copy "LITESTEAM" environment credentials. applyLitestreamEnv() @@ -98,7 +92,7 @@ func (m *Main) Run(ctx context.Context, args []string) (err error) { ctx, cancel := context.WithCancel(ctx) defer cancel() signalCh := make(chan os.Signal, 1) - signal.Notify(signalCh, notifySignals...) + signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM) if err := c.Run(ctx); err != nil { return err @@ -685,7 +679,7 @@ func DefaultConfigPath() string { if v := os.Getenv("LITESTREAM_CONFIG"); v != "" { return v } - return defaultConfigPath + return "/etc/litestream.yml" } func registerConfigFlag(fs *flag.FlagSet, configPath *string, noExpandEnv *bool) { diff --git a/cmd/litestream/main_notwindows.go b/cmd/litestream/main_notwindows.go deleted file mode 100644 index 6d4dcef..0000000 --- a/cmd/litestream/main_notwindows.go +++ /dev/null @@ -1,21 +0,0 @@ -// +build !windows - -package main - -import ( - "context" - "os" - "syscall" -) - -const defaultConfigPath = "/etc/litestream.yml" - -func isWindowsService() (bool, error) { - return false, nil -} - -func runWindowsService(ctx context.Context) error { - panic("cannot run windows service as unix process") -} - -var notifySignals = []os.Signal{syscall.SIGINT, syscall.SIGTERM} diff --git a/cmd/litestream/main_windows.go b/cmd/litestream/main_windows.go deleted file mode 100644 index e6276eb..0000000 --- a/cmd/litestream/main_windows.go +++ /dev/null @@ -1,108 +0,0 @@ -//go:build windows -// +build windows - -package main - -import ( - "context" - "io" - "log" - "os" - - "golang.org/x/sys/windows" - "golang.org/x/sys/windows/svc" - "golang.org/x/sys/windows/svc/eventlog" -) - -const defaultConfigPath = `C:\Litestream\litestream.yml` - -// serviceName is the Windows Service name. -const serviceName = "Litestream" - -// isWindowsService returns true if currently executing within a Windows service. -func isWindowsService() (bool, error) { - return svc.IsWindowsService() -} - -func runWindowsService(ctx context.Context) error { - // Attempt to install new log service. This will fail if already installed. - // We don't log the error because we don't have anywhere to log until we open the log. - _ = eventlog.InstallAsEventCreate(serviceName, eventlog.Error|eventlog.Warning|eventlog.Info) - - elog, err := eventlog.Open(serviceName) - if err != nil { - return err - } - defer elog.Close() - - // Set eventlog as log writer while running. - log.SetOutput((*eventlogWriter)(elog)) - defer log.SetOutput(os.Stdout) - - log.Print("Litestream service starting") - - if err := svc.Run(serviceName, &windowsService{ctx: ctx}); err != nil { - return errExit - } - - log.Print("Litestream service stopped") - return nil -} - -// windowsService is an interface adapter for svc.Handler. -type windowsService struct { - ctx context.Context -} - -func (s *windowsService) Execute(args []string, r <-chan svc.ChangeRequest, statusCh chan<- svc.Status) (svcSpecificEC bool, exitCode uint32) { - var err error - - // Notify Windows that the service is starting up. - statusCh <- svc.Status{State: svc.StartPending} - - // Instantiate replication command and load configuration. - c := NewReplicateCommand() - if c.Config, err = ReadConfigFile(DefaultConfigPath(), true); err != nil { - log.Printf("cannot load configuration: %s", err) - return true, 1 - } - - // Execute replication command. - if err := c.Run(s.ctx); err != nil { - log.Printf("cannot replicate: %s", err) - statusCh <- svc.Status{State: svc.StopPending} - return true, 2 - } - - // Notify Windows that the service is now running. - statusCh <- svc.Status{State: svc.Running, Accepts: svc.AcceptStop} - - for { - select { - case req := <-r: - switch req.Cmd { - case svc.Stop: - c.Close() - statusCh <- svc.Status{State: svc.StopPending} - return false, windows.NO_ERROR - case svc.Interrogate: - statusCh <- req.CurrentStatus - default: - log.Printf("Litestream service received unexpected change request cmd: %d", req.Cmd) - } - } - } -} - -// Ensure implementation implements io.Writer interface. -var _ io.Writer = (*eventlogWriter)(nil) - -// eventlogWriter is an adapter for using eventlog.Log as an io.Writer. -type eventlogWriter eventlog.Log - -func (w *eventlogWriter) Write(p []byte) (n int, err error) { - elog := (*eventlog.Log)(w) - return 0, elog.Info(1, string(p)) -} - -var notifySignals = []os.Signal{os.Interrupt} diff --git a/go.mod b/go.mod index d0b69b0..13575b6 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,6 @@ require ( github.com/prometheus/client_golang v1.12.1 golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 google.golang.org/api v0.66.0 gopkg.in/yaml.v2 v2.4.0 ) diff --git a/internal/internal.go b/internal/internal.go index 077841c..b2db3b9 100644 --- a/internal/internal.go +++ b/internal/internal.go @@ -132,7 +132,7 @@ func MkdirAll(path string, mode os.FileMode, uid, gid int) error { if j > 1 { // Create parent. - err = MkdirAll(fixRootDirectory(path[:j-1]), mode, uid, gid) + err = MkdirAll(path[:j-1], mode, uid, gid) if err != nil { return err } @@ -154,6 +154,15 @@ func MkdirAll(path string, mode os.FileMode, uid, gid int) error { return nil } +// Fileinfo returns syscall fields from a FileInfo object. +func Fileinfo(fi os.FileInfo) (uid, gid int) { + if fi == nil { + return -1, -1 + } + stat := fi.Sys().(*syscall.Stat_t) + return int(stat.Uid), int(stat.Gid) +} + // ParseSnapshotPath parses the index from a snapshot filename. Used by path-based replicas. func ParseSnapshotPath(s string) (index int, err error) { a := snapshotPathRegex.FindStringSubmatch(s) diff --git a/internal/internal_unix.go b/internal/internal_unix.go deleted file mode 100644 index cedc947..0000000 --- a/internal/internal_unix.go +++ /dev/null @@ -1,21 +0,0 @@ -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris - -package internal - -import ( - "os" - "syscall" -) - -// Fileinfo returns syscall fields from a FileInfo object. -func Fileinfo(fi os.FileInfo) (uid, gid int) { - if fi == nil { - return -1, -1 - } - stat := fi.Sys().(*syscall.Stat_t) - return int(stat.Uid), int(stat.Gid) -} - -func fixRootDirectory(p string) string { - return p -} diff --git a/internal/internal_windows.go b/internal/internal_windows.go deleted file mode 100644 index 1853164..0000000 --- a/internal/internal_windows.go +++ /dev/null @@ -1,22 +0,0 @@ -// +build windows - -package internal - -import ( - "os" -) - -// Fileinfo returns syscall fields from a FileInfo object. -func Fileinfo(fi os.FileInfo) (uid, gid int) { - return -1, -1 -} - -// fixRootDirectory is copied from the standard library for use with mkdirAll() -func fixRootDirectory(p string) string { - if len(p) == len(`\\?\c:`) { - if os.IsPathSeparator(p[0]) && os.IsPathSeparator(p[1]) && p[2] == '?' && os.IsPathSeparator(p[3]) && p[5] == ':' { - return p + `\` - } - } - return p -}