| package utils |
|
|
| import ( |
| "fmt" |
| "io" |
| "mime" |
| "os" |
| "path" |
| "path/filepath" |
| "strings" |
|
|
| "github.com/OpenListTeam/OpenList/v4/internal/errs" |
|
|
| "github.com/OpenListTeam/OpenList/v4/internal/conf" |
| log "github.com/sirupsen/logrus" |
| ) |
|
|
| |
| func CopyFile(src, dst string) error { |
| var err error |
| var srcfd *os.File |
| var dstfd *os.File |
| var srcinfo os.FileInfo |
|
|
| if srcfd, err = os.Open(src); err != nil { |
| return err |
| } |
| defer srcfd.Close() |
|
|
| if dstfd, err = CreateNestedFile(dst); err != nil { |
| return err |
| } |
| defer dstfd.Close() |
|
|
| if _, err = CopyWithBuffer(dstfd, srcfd); err != nil { |
| return err |
| } |
| if srcinfo, err = os.Stat(src); err != nil { |
| return err |
| } |
| return os.Chmod(dst, srcinfo.Mode()) |
| } |
|
|
| |
| func CopyDir(src, dst string) error { |
| var err error |
| var fds []os.DirEntry |
| var srcinfo os.FileInfo |
|
|
| if srcinfo, err = os.Stat(src); err != nil { |
| return err |
| } |
| if err = os.MkdirAll(dst, srcinfo.Mode()); err != nil { |
| return err |
| } |
| if fds, err = os.ReadDir(src); err != nil { |
| return err |
| } |
| for _, fd := range fds { |
| srcfp := path.Join(src, fd.Name()) |
| dstfp := path.Join(dst, fd.Name()) |
|
|
| if fd.IsDir() { |
| if err = CopyDir(srcfp, dstfp); err != nil { |
| fmt.Println(err) |
| } |
| } else { |
| if err = CopyFile(srcfp, dstfp); err != nil { |
| fmt.Println(err) |
| } |
| } |
| } |
| return nil |
| } |
|
|
| |
| func SymlinkOrCopyFile(src, dst string) error { |
| if err := CreateNestedDirectory(filepath.Dir(dst)); err != nil { |
| return err |
| } |
| if err := os.Symlink(src, dst); err != nil { |
| return CopyFile(src, dst) |
| } |
| return nil |
| } |
|
|
| |
| func Exists(name string) bool { |
| if _, err := os.Stat(name); err != nil { |
| if os.IsNotExist(err) { |
| return false |
| } |
| } |
| return true |
| } |
|
|
| |
| func CreateNestedDirectory(path string) error { |
| err := os.MkdirAll(path, 0700) |
| if err != nil { |
| log.Errorf("can't create folder, %s", err) |
| } |
| return err |
| } |
|
|
| |
| func CreateNestedFile(path string) (*os.File, error) { |
| basePath := filepath.Dir(path) |
| if err := CreateNestedDirectory(basePath); err != nil { |
| return nil, err |
| } |
| return os.Create(path) |
| } |
|
|
| |
| func CreateTempFile(r io.Reader, size int64) (*os.File, error) { |
| if f, ok := r.(*os.File); ok { |
| return f, nil |
| } |
| f, err := os.CreateTemp(conf.Conf.TempDir, "file-*") |
| if err != nil { |
| return nil, err |
| } |
| readBytes, err := CopyWithBuffer(f, r) |
| if err != nil { |
| _ = os.Remove(f.Name()) |
| return nil, errs.NewErr(err, "CreateTempFile failed") |
| } |
| if size > 0 && readBytes != size { |
| _ = os.Remove(f.Name()) |
| return nil, errs.NewErr(err, "CreateTempFile failed, incoming stream actual size= %d, expect = %d ", readBytes, size) |
| } |
| _, err = f.Seek(0, io.SeekStart) |
| if err != nil { |
| _ = os.Remove(f.Name()) |
| return nil, errs.NewErr(err, "CreateTempFile failed, can't seek to 0 ") |
| } |
| return f, nil |
| } |
|
|
| |
| func GetFileType(filename string) int { |
| ext := strings.ToLower(Ext(filename)) |
| if SliceContains(conf.SlicesMap[conf.AudioTypes], ext) { |
| return conf.AUDIO |
| } |
| if SliceContains(conf.SlicesMap[conf.VideoTypes], ext) { |
| return conf.VIDEO |
| } |
| if SliceContains(conf.SlicesMap[conf.ImageTypes], ext) { |
| return conf.IMAGE |
| } |
| if SliceContains(conf.SlicesMap[conf.TextTypes], ext) { |
| return conf.TEXT |
| } |
| return conf.UNKNOWN |
| } |
|
|
| func GetObjType(filename string, isDir bool) int { |
| if isDir { |
| return conf.FOLDER |
| } |
| return GetFileType(filename) |
| } |
|
|
| var extraMimeTypes = map[string]string{ |
| ".apk": "application/vnd.android.package-archive", |
| } |
|
|
| func GetMimeType(name string) string { |
| ext := path.Ext(name) |
| if m, ok := extraMimeTypes[ext]; ok { |
| return m |
| } |
| m := mime.TypeByExtension(ext) |
| if m != "" { |
| return m |
| } |
| return "application/octet-stream" |
| } |
|
|
| const ( |
| KB = 1 << (10 * (iota + 1)) |
| MB |
| GB |
| TB |
| ) |
|
|
| |
| |
| func IsSystemFile(filename string) bool { |
| |
| switch filename { |
| case ".DS_Store", "desktop.ini", "Thumbs.db", "@eaDir": |
| return true |
| } |
|
|
| |
| if strings.HasPrefix(filename, "._") { |
| return true |
| } |
|
|
| return false |
| } |
|
|