diff --git a/internal/pkg/dir.go b/internal/pkg/dir.go new file mode 100644 index 0000000..a9a639d --- /dev/null +++ b/internal/pkg/dir.go @@ -0,0 +1,124 @@ +package pkg + +import ( + "crypto/rand" + "fmt" + "os" + "path/filepath" + "time" +) + +type Dir struct { + Path string + PathCurrentDir string + PathBackupDir string +} + +// NewDir creates a new Dir instance. +func NewDir(dir, nameCurrentDir string) *Dir { + return &Dir{ + Path: dir, + PathCurrentDir: filepath.Join(dir, nameCurrentDir), + PathBackupDir: filepath.Join(dir, nameCurrentDir+".bak"), + } +} + +// CreateRandomTmpDir creates a temporary directory in the specified directory with a random name. +// The directory is created with permissions 0750. +// If the directory already exists, an error is returned. +// @return string - path to the temporary directory +// @return error - an error if the directory could not be created +func (d *Dir) CreateRandomTmpDir() (string, error) { + tmpDir := filepath.Join(d.Path, time.Now().Format(time.RFC3339)+"_"+rand.Text()+".tmp") + if _, err := os.Stat(tmpDir); err == nil { + return "", fmt.Errorf("directory already exists: %s", tmpDir) + } + if err := os.MkdirAll(tmpDir, 0750); err != nil { + return "", err + } + return tmpDir, nil +} + +// ReplaceDirToCurrent replaces the current directory with a new directory. +// If the new directory already exists, it is renamed to a backup directory. +// If the backup directory already exists, it is removed. +// @return error - an error if the directory could not be replaced +func (d *Dir) ReplaceDirToCurrent(newDir string) error { + if err := os.RemoveAll(d.PathBackupDir); err != nil { + return err + } + + if _, err := os.Stat(d.PathCurrentDir); err == nil { + if err := os.Rename(d.PathCurrentDir, d.PathBackupDir); err != nil { + return err + } + } + + if err := os.Rename(newDir, d.PathCurrentDir); err != nil { + if _, statErr := os.Stat(d.PathBackupDir); statErr == nil { + _ = os.Rename(d.PathBackupDir, d.PathCurrentDir) + } + return err + } + + if err := os.RemoveAll(d.PathBackupDir); err != nil { + return err + } + + return nil +} + +// MovingFiles moves all files from dirFrom to dirTo. +// If dirTo does not exist, it is created. +// @param dirFrom - path to the directory containing the files to move +// @param dirTo - path to the directory where the files will be moved +// @return error - an error if the files could not be moved +func MovingFiles(dirFrom, dirTo string) error { + if _, err := os.Stat(dirTo); err != nil { + if err := os.MkdirAll(dirTo, 0750); err != nil { + return err + } + } + + entries, err := os.ReadDir(dirFrom) + if err != nil { + return err + } + + for _, entry := range entries { + if entry.IsDir() { + if err := MovingFiles(filepath.Join(dirFrom, entry.Name()), dirTo); err != nil { + return err + } + continue + } + src := filepath.Join(dirFrom, entry.Name()) + dst := filepath.Join(dirTo, entry.Name()) + if err := os.Rename(src, dst); err != nil { + return err + } + } + + return nil +} + +// FindMMDBFile finds the .mmdb file in the specified directory. +// @param dir - path to the directory to search +// @return string - path to the .mmdb file +// @return error - an error if the .mmdb file could not be found +func FindMMDBFile(dir string) (string, error) { + entries, err := os.ReadDir(dir) + if err != nil { + return "", err + } + for _, entry := range entries { + if entry.IsDir() { + continue + } + if filepath.Ext(entry.Name()) == ".mmdb" { + return filepath.Join(dir, entry.Name()), nil + } + } + + return "", fmt.Errorf("no .mmdb file found in %s", dir) +}