Kepler core
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

191 lines
5.5 KiB

package storage
import (
"fmt"
"io"
"os"
"path"
log "github.com/Sirupsen/logrus"
"cygnux.net/kepler/config"
)
type FileSystem struct {
cdn string
root string
prefix string
minFreeSize int64
allowZeroFile bool
autoCreateDirectory bool
removeEmptyDirectory bool
defaultFilePerm os.FileMode
defaultDirPerm os.FileMode
}
func NewFileSystem(cfg config.Config) (Storage, error) {
var fs FileSystem
if root := cfg.GetString("root"); root == "" {
return nil, fmt.Errorf("root can not be empty")
} else if !path.IsAbs(root) {
return nil, fmt.Errorf("root '%s' should be an albsolute path", root)
} else if rootInfo, e := os.Stat(root); nil != e {
return nil, e
} else if !rootInfo.IsDir() {
return nil, fmt.Errorf("root '%s' is not a directory", root)
} else {
fs.root = root
}
fs.cdn = cfg.GetString("cdn")
fs.prefix = cfg.GetString("prefix", "/")
fs.minFreeSize = cfg.GetInt64("min_free_size", 10*GB)
fs.allowZeroFile = cfg.GetBool("allow_zero_file", false)
fs.removeEmptyDirectory = cfg.GetBool("remove_empty_directory", false)
fs.autoCreateDirectory = cfg.GetBool("auto_create_directory", true)
fs.defaultDirPerm = os.FileMode(cfg.GetInt32("default_dir_perm", 0755))
fs.defaultFilePerm = os.FileMode(cfg.GetInt32("default_file_perm", 0644))
return fs, nil
}
func (fs FileSystem) CDN() string {
return fs.cdn
}
func (fs FileSystem) Root() string {
return fs.root
}
func (fs FileSystem) Prefix() string {
return fs.prefix
}
func (fs FileSystem) SaveFile(src interface{}, destination string) (FileObject, error) {
switch st := src.(type) {
case string:
return fs.copyFile(st, destination)
case io.Reader:
return fs.saveIOReader(st, destination)
case []byte:
return fs.saveBytes(st, destination)
default:
return nil, fmt.Errorf("unknow source type")
}
//return nil, fmt.Errorf("unknow source type")
}
func (fs FileSystem) copyFile(src string, destination string) (FileObject, error) {
log.Debugln("FileSystem.copyFile:>", src, destination)
if fp, e := os.Open(src); nil != e {
log.Errorln("FileSystem.copyFile:> open src file failed:", e)
return nil, e
} else if out, e := fs.createFile(destination); nil != e {
log.Errorln("FileSystem.copyFile:> create file failed:", e)
return nil, e
} else if n, e := io.Copy(out, fp); nil != e {
log.Errorln("FileSystem.copyFile:> Copy failed:", e)
return nil, e
} else {
return fsObject{
root: fs.root,
prefix: fs.prefix,
filename: destination,
size: n,
}, nil
}
}
func (fs FileSystem) saveBytes(src []byte, destination string) (FileObject, error) {
log.Debugln("FileSystem.saveBytes:>", len(src), destination)
if len(src) < 1 && !fs.allowZeroFile {
log.Errorln("FileSystem.saveBytes:> not allow to create zero file")
return nil, fmt.Errorf("saving zero bytes file is not allowed")
}
if out, e := fs.createFile(destination); nil != e {
log.Errorln("FileSystem.saveBytes:> create file failed:", e)
return nil, e
} else if n, e := out.Write(src); nil != e {
log.Errorln("FileSystem.saveBytes:> write file failed:", e)
return nil, e
} else {
return fsObject{
root: fs.root,
prefix: fs.prefix,
filename: destination,
size: int64(n),
}, nil
}
}
func (fs FileSystem) saveIOReader(src io.Reader, destination string) (FileObject, error) {
log.Debugln("FileSystem.saveIOReader:> ", src, destination)
if out, e := fs.createFile(destination); nil != e {
log.Errorln("FileSystem.saveIOReader:> create file failed:", e)
return nil, e
} else if n, e := io.Copy(out, src); nil != e {
log.Errorln("FileSystem.saveIOReader:> copy file failed:", e)
return nil, e
} else {
return fsObject{
root: fs.root,
prefix: fs.prefix,
filename: destination,
size: n,
}, nil
}
}
func (fs FileSystem) createFile(destination string) (*os.File, error) {
destination = path.Join(fs.root, destination)
if _, e := os.Stat(destination); nil == e {
log.Errorln("FileSystem.createFile:> target file already exists!", destination)
return nil, fmt.Errorf("target file '%s' already exists", destination)
}
dir := path.Dir(destination)
if dirInfo, e := os.Stat(dir); nil != e {
if fs.autoCreateDirectory {
if e := fs.createDirectory(dir); nil != e {
log.Errorln("FileSystem.createFile:> createDirector failed:", e)
return nil, e
}
} else {
log.Errorln("FileSystem.createFile:> target path is not exists:", dir)
return nil, fmt.Errorf("target path '%s' is not exists", dir)
}
} else if !dirInfo.IsDir() {
log.Errorln("FileSystem.createFile:> target path is not a dir:", dir)
return nil, fmt.Errorf("target path '%s' is already exists and it is not a directory", dir)
}
if fp, e := os.OpenFile(destination, os.O_CREATE|os.O_WRONLY, fs.defaultFilePerm); nil != e {
log.Errorln("FileSystem.createFile:> OpenFile failed:", e)
return nil, e
} else {
return fp, nil
}
}
func (fs FileSystem) createDirectory(path string) error {
if path == "" || path == "." || path == ".." {
return nil
}
return os.MkdirAll(path, fs.defaultDirPerm)
}
func (fs FileSystem) DeleteFile(root, filename string) error {
if e := os.Remove(path.Join(root, filename)); nil != e {
return e
}
return nil
}
func (fs FileSystem) OpenFile(root, filename string) (io.ReadSeeker, error) {
return os.Open(path.Join(root, filename))
}
func (fs FileSystem) Stat(root, filename string) (os.FileInfo, error) {
return os.Stat(path.Join(root, filename))
}
func init() {
Register("fs", NewFileSystem)
Register("filesystem", NewFileSystem)
}