mirror of
https://github.com/simon-ding/polaris.git
synced 2026-02-06 23:21:00 +08:00
104 lines
2.7 KiB
Go
104 lines
2.7 KiB
Go
package storage
|
|
|
|
import (
|
|
"io"
|
|
"io/fs"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"polaris/log"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type Storage interface {
|
|
Move(src, dest string) error
|
|
Copy(src, dest string) error
|
|
ReadDir(dir string) ([]fs.FileInfo, error)
|
|
ReadFile(string) ([]byte, error)
|
|
WriteFile(string, []byte) error
|
|
}
|
|
|
|
func NewLocalStorage(dir string) (*LocalStorage, error) {
|
|
os.MkdirAll(dir, 0655)
|
|
|
|
return &LocalStorage{dir: dir}, nil
|
|
}
|
|
|
|
type LocalStorage struct {
|
|
dir string
|
|
}
|
|
|
|
func (l *LocalStorage) Copy(src, destDir string) error {
|
|
os.MkdirAll(filepath.Join(l.dir, destDir), os.ModePerm)
|
|
|
|
targetBase := filepath.Join(l.dir, destDir, filepath.Base(src)) //文件的场景,要加上文件名, move filename ./dir/
|
|
info, err := os.Stat(src)
|
|
if err != nil {
|
|
return errors.Wrap(err, "read source dir")
|
|
}
|
|
if info.IsDir() { //如果是路径,则只移动路径里面的文件,不管当前路径, 行为类似 move dirname/* target_dir/
|
|
targetBase = filepath.Join(l.dir, destDir)
|
|
}
|
|
log.Debugf("local storage target base dir is: %v", targetBase)
|
|
|
|
err = filepath.Walk(src, func(path string, info fs.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
rel, err := filepath.Rel(src, path)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "relation between %s and %s", src, path)
|
|
}
|
|
destName := filepath.Join(targetBase, rel)
|
|
|
|
if info.IsDir() {
|
|
os.Mkdir(destName, os.ModePerm)
|
|
} else { //is file
|
|
if err := os.Link(path, destName); err != nil {
|
|
log.Warnf("hard link file error: %v, will try copy file, source: %s, dest: %s", err, path, destName)
|
|
if writer, err := os.OpenFile(destName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.ModePerm); err != nil {
|
|
return errors.Wrapf(err, "create file %s", destName)
|
|
} else {
|
|
defer writer.Close()
|
|
if f, err := os.OpenFile(path, os.O_RDONLY, os.ModePerm); err != nil {
|
|
return errors.Wrapf(err, "read file %v", path)
|
|
} else { //open success
|
|
defer f.Close()
|
|
_, err := io.Copy(writer, f)
|
|
if err != nil {
|
|
return errors.Wrap(err, "transmitting data error")
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
log.Infof("file copy complete: %v", destName)
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return errors.Wrap(err, "move file error")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (l *LocalStorage) Move(src, destDir string) error {
|
|
if err := l.Copy(src, destDir); err != nil {
|
|
return err
|
|
}
|
|
return os.RemoveAll(src)
|
|
}
|
|
|
|
func (l *LocalStorage) ReadDir(dir string) ([]fs.FileInfo, error) {
|
|
return ioutil.ReadDir(filepath.Join(l.dir, dir))
|
|
}
|
|
|
|
func (l *LocalStorage) ReadFile(name string) ([]byte, error) {
|
|
return os.ReadFile(filepath.Join(l.dir, name))
|
|
}
|
|
|
|
func (l *LocalStorage) WriteFile(name string, data []byte) error {
|
|
return os.WriteFile(filepath.Join(l.dir, name), data, os.ModePerm)
|
|
}
|