mirror of
https://github.com/fankes/beszel.git
synced 2025-10-19 01:39:34 +08:00
118 lines
2.6 KiB
Go
118 lines
2.6 KiB
Go
package agent
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
)
|
|
|
|
// getDataDir returns the path to the data directory for the agent and an error
|
|
// if the directory is not valid. Attempts to find the optimal data directory if
|
|
// no data directories are provided.
|
|
func getDataDir(dataDirs ...string) (string, error) {
|
|
if len(dataDirs) > 0 {
|
|
return testDataDirs(dataDirs)
|
|
}
|
|
|
|
dataDir, _ := GetEnv("DATA_DIR")
|
|
if dataDir != "" {
|
|
dataDirs = append(dataDirs, dataDir)
|
|
}
|
|
|
|
if runtime.GOOS == "windows" {
|
|
dataDirs = append(dataDirs,
|
|
filepath.Join(os.Getenv("APPDATA"), "beszel-agent"),
|
|
filepath.Join(os.Getenv("LOCALAPPDATA"), "beszel-agent"),
|
|
)
|
|
} else {
|
|
dataDirs = append(dataDirs, "/var/lib/beszel-agent")
|
|
if homeDir, err := os.UserHomeDir(); err == nil {
|
|
dataDirs = append(dataDirs, filepath.Join(homeDir, ".config", "beszel"))
|
|
}
|
|
}
|
|
return testDataDirs(dataDirs)
|
|
}
|
|
|
|
func testDataDirs(paths []string) (string, error) {
|
|
// first check if the directory exists and is writable
|
|
for _, path := range paths {
|
|
if valid, _ := isValidDataDir(path, false); valid {
|
|
return path, nil
|
|
}
|
|
}
|
|
// if the directory doesn't exist, try to create it
|
|
for _, path := range paths {
|
|
exists, _ := directoryExists(path)
|
|
if exists {
|
|
continue
|
|
}
|
|
|
|
if err := os.MkdirAll(path, 0755); err != nil {
|
|
continue
|
|
}
|
|
|
|
// Verify the created directory is actually writable
|
|
writable, _ := directoryIsWritable(path)
|
|
if !writable {
|
|
continue
|
|
}
|
|
|
|
return path, nil
|
|
}
|
|
|
|
return "", errors.New("data directory not found")
|
|
}
|
|
|
|
func isValidDataDir(path string, createIfNotExists bool) (bool, error) {
|
|
exists, err := directoryExists(path)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if !exists {
|
|
if !createIfNotExists {
|
|
return false, nil
|
|
}
|
|
if err = os.MkdirAll(path, 0755); err != nil {
|
|
return false, err
|
|
}
|
|
}
|
|
|
|
// Always check if the directory is writable
|
|
writable, err := directoryIsWritable(path)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return writable, nil
|
|
}
|
|
|
|
// directoryExists checks if a directory exists
|
|
func directoryExists(path string) (bool, error) {
|
|
// Check if directory exists
|
|
stat, err := os.Stat(path)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return false, nil
|
|
}
|
|
return false, err
|
|
}
|
|
if !stat.IsDir() {
|
|
return false, fmt.Errorf("%s is not a directory", path)
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
// directoryIsWritable tests if a directory is writable by creating and removing a temporary file
|
|
func directoryIsWritable(path string) (bool, error) {
|
|
testFile := filepath.Join(path, ".write-test")
|
|
file, err := os.Create(testFile)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
defer file.Close()
|
|
defer os.Remove(testFile)
|
|
return true, nil
|
|
}
|