Files
filepass/internal/services/storage.go
2026-04-06 03:26:02 +09:00

91 lines
2.7 KiB
Go

package services
import (
"fmt"
"os"
"path/filepath"
"strings"
"time"
)
// debugLog appends a timestamped line to /tmp/filepass-debug.log.
// Safe to call from any goroutine; errors are silently ignored.
func debugLog(format string, args ...any) {
f, err := os.OpenFile("/tmp/filepass-debug.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
return
}
defer f.Close()
fmt.Fprintf(f, "[%s] %s\n", time.Now().Format("15:04:05.000"), fmt.Sprintf(format, args...))
}
// StorageService executes file operations against a single server's storage.
type StorageService struct {
server Server
}
func NewStorageService(s Server) *StorageService {
return &StorageService{server: s}
}
// Check returns the list of files currently in the remote storage directory.
func (s *StorageService) Check() ([]string, error) {
cmd := SSHCmd(s.server,
"find "+defaultStoragePath+" -type f -printf '%f\n' 2>/dev/null",
)
out, err := cmd.Output()
if err != nil {
return nil, fmt.Errorf("check failed: %w", err)
}
raw := strings.TrimSpace(string(out))
if raw == "" {
return []string{}, nil
}
return strings.Split(raw, "\n"), nil
}
// Get downloads a single file from remote storage into destDir.
func (s *StorageService) Get(filename, destDir string) error {
src := RemotePath(s.server, filename)
dst := filepath.Join(destDir, filename)
cmd := RsyncCmd(s.server, src, dst)
if out, err := cmd.CombinedOutput(); err != nil {
return fmt.Errorf("get failed: %w\n%s", err, strings.TrimSpace(string(out)))
}
return nil
}
// Delete removes a single file from remote storage.
func (s *StorageService) Delete(filename string) error {
remoteCmd := "rm -f " + defaultStoragePath + "/" + shellQuote(filename)
cmd := SSHCmd(s.server, remoteCmd)
debugLog("Delete | args: %v", cmd.Args)
out, err := cmd.CombinedOutput()
debugLog("Delete | exit_err: %v | output: %q", err, strings.TrimSpace(string(out)))
if err != nil {
return fmt.Errorf("delete failed: %w\n%s", err, strings.TrimSpace(string(out)))
}
return nil
}
// Send transfers one or more local files to the remote storage.
// Multiple files are archived into a temp tarball first.
func (s *StorageService) Send(localPaths []string) error {
// TODO: implement
return fmt.Errorf("send: not yet implemented")
}
// CleanAll removes all files from remote storage.
func (s *StorageService) CleanAll() error {
cmd := SSHCmd(s.server,
"rm -f "+defaultStoragePath+"/*",
)
debugLog("CleanAll | args: %v", cmd.Args)
out, err := cmd.CombinedOutput()
debugLog("CleanAll | exit_err: %v | output: %q", err, strings.TrimSpace(string(out)))
if err != nil {
return fmt.Errorf("clean all failed: %w\n%s", err, strings.TrimSpace(string(out)))
}
return nil
}