2016-06-07 08:37:42 +02:00
|
|
|
package localfs
|
|
|
|
|
|
|
|
import (
|
2019-01-25 08:33:11 +01:00
|
|
|
"encoding/json"
|
2021-12-24 01:24:50 +01:00
|
|
|
"errors"
|
2016-06-07 08:37:42 +02:00
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
2020-03-19 01:26:43 +01:00
|
|
|
"net/http"
|
2016-06-07 08:37:42 +02:00
|
|
|
"os"
|
|
|
|
"path"
|
2019-01-25 08:33:11 +01:00
|
|
|
"time"
|
2016-06-07 08:37:42 +02:00
|
|
|
|
|
|
|
"github.com/andreimarcu/linx-server/backends"
|
2019-01-25 08:33:11 +01:00
|
|
|
"github.com/andreimarcu/linx-server/helpers"
|
2016-06-07 08:37:42 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type LocalfsBackend struct {
|
2019-01-25 08:33:11 +01:00
|
|
|
metaPath string
|
|
|
|
filesPath string
|
2021-12-23 08:20:44 +01:00
|
|
|
locksPath string
|
2016-06-07 08:37:42 +02:00
|
|
|
}
|
|
|
|
|
2019-01-25 08:33:11 +01:00
|
|
|
type MetadataJSON struct {
|
|
|
|
DeleteKey string `json:"delete_key"`
|
2020-02-17 15:58:56 +01:00
|
|
|
AccessKey string `json:"access_key,omitempty"`
|
2019-01-25 08:33:11 +01:00
|
|
|
Sha256sum string `json:"sha256sum"`
|
|
|
|
Mimetype string `json:"mimetype"`
|
|
|
|
Size int64 `json:"size"`
|
|
|
|
Expiry int64 `json:"expiry"`
|
2021-02-10 04:36:14 +01:00
|
|
|
SrcIp string `json:"srcip,omitempty"`
|
2019-01-25 08:33:11 +01:00
|
|
|
ArchiveFiles []string `json:"archive_files,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b LocalfsBackend) Delete(key string) (err error) {
|
|
|
|
err = os.Remove(path.Join(b.filesPath, key))
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = os.Remove(path.Join(b.metaPath, key))
|
|
|
|
return
|
2016-06-07 08:37:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (b LocalfsBackend) Exists(key string) (bool, error) {
|
2019-01-25 08:33:11 +01:00
|
|
|
_, err := os.Stat(path.Join(b.filesPath, key))
|
2016-06-07 08:37:42 +02:00
|
|
|
return err == nil, err
|
|
|
|
}
|
|
|
|
|
2019-01-25 08:33:11 +01:00
|
|
|
func (b LocalfsBackend) Head(key string) (metadata backends.Metadata, err error) {
|
|
|
|
f, err := os.Open(path.Join(b.metaPath, key))
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
return metadata, backends.NotFoundErr
|
|
|
|
} else if err != nil {
|
|
|
|
return metadata, backends.BadMetadata
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
|
|
|
|
decoder := json.NewDecoder(f)
|
|
|
|
|
|
|
|
mjson := MetadataJSON{}
|
|
|
|
if err := decoder.Decode(&mjson); err != nil {
|
|
|
|
return metadata, backends.BadMetadata
|
|
|
|
}
|
|
|
|
|
|
|
|
metadata.DeleteKey = mjson.DeleteKey
|
2020-02-17 15:58:56 +01:00
|
|
|
metadata.AccessKey = mjson.AccessKey
|
2019-01-25 08:33:11 +01:00
|
|
|
metadata.Mimetype = mjson.Mimetype
|
|
|
|
metadata.ArchiveFiles = mjson.ArchiveFiles
|
|
|
|
metadata.Sha256sum = mjson.Sha256sum
|
|
|
|
metadata.Expiry = time.Unix(mjson.Expiry, 0)
|
|
|
|
metadata.Size = mjson.Size
|
|
|
|
|
|
|
|
return
|
2016-06-07 08:37:42 +02:00
|
|
|
}
|
|
|
|
|
2019-01-25 08:33:11 +01:00
|
|
|
func (b LocalfsBackend) Get(key string) (metadata backends.Metadata, f io.ReadCloser, err error) {
|
|
|
|
metadata, err = b.Head(key)
|
2016-06-07 08:37:42 +02:00
|
|
|
if err != nil {
|
2019-01-25 08:33:11 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
f, err = os.Open(path.Join(b.filesPath, key))
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-03-19 01:26:43 +01:00
|
|
|
func (b LocalfsBackend) ServeFile(key string, w http.ResponseWriter, r *http.Request) (err error) {
|
|
|
|
_, err = b.Head(key)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
filePath := path.Join(b.filesPath, key)
|
|
|
|
http.ServeFile(w, r, filePath)
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-01-25 08:33:11 +01:00
|
|
|
func (b LocalfsBackend) writeMetadata(key string, metadata backends.Metadata) error {
|
|
|
|
metaPath := path.Join(b.metaPath, key)
|
|
|
|
|
|
|
|
mjson := MetadataJSON{
|
2020-02-17 15:58:56 +01:00
|
|
|
DeleteKey: metadata.DeleteKey,
|
|
|
|
AccessKey: metadata.AccessKey,
|
|
|
|
Mimetype: metadata.Mimetype,
|
2019-01-25 08:33:11 +01:00
|
|
|
ArchiveFiles: metadata.ArchiveFiles,
|
2020-02-17 15:58:56 +01:00
|
|
|
Sha256sum: metadata.Sha256sum,
|
|
|
|
Expiry: metadata.Expiry.Unix(),
|
|
|
|
Size: metadata.Size,
|
2021-02-10 04:36:14 +01:00
|
|
|
SrcIp: metadata.SrcIp,
|
|
|
|
|
2019-01-25 08:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
dst, err := os.Create(metaPath)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer dst.Close()
|
|
|
|
|
|
|
|
encoder := json.NewEncoder(dst)
|
|
|
|
err = encoder.Encode(mjson)
|
|
|
|
if err != nil {
|
|
|
|
os.Remove(metaPath)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-12-23 08:20:44 +01:00
|
|
|
func (b LocalfsBackend) Lock(filename string) (err error) {
|
|
|
|
lockPath := path.Join(b.locksPath, filename)
|
|
|
|
|
|
|
|
lock, err := os.Create(lockPath)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
lock.Close()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b LocalfsBackend) Unlock(filename string) (err error) {
|
|
|
|
lockPath := path.Join(b.locksPath, filename)
|
|
|
|
|
|
|
|
err = os.Remove(lockPath)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-12-24 01:24:50 +01:00
|
|
|
func (b LocalfsBackend) CheckLock(filename string) (locked bool, err error) {
|
|
|
|
lockPath := path.Join(b.locksPath, filename)
|
|
|
|
|
|
|
|
if _, err := os.Stat(lockPath); errors.Is(err, os.ErrNotExist) {
|
|
|
|
return false, nil
|
|
|
|
} else {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
2021-02-10 04:36:14 +01:00
|
|
|
func (b LocalfsBackend) Put(key string, r io.Reader, expiry time.Time, deleteKey, accessKey string, srcIp string) (m backends.Metadata, err error) {
|
2019-01-25 08:33:11 +01:00
|
|
|
filePath := path.Join(b.filesPath, key)
|
|
|
|
|
|
|
|
dst, err := os.Create(filePath)
|
|
|
|
if err != nil {
|
|
|
|
return
|
2016-06-07 08:37:42 +02:00
|
|
|
}
|
|
|
|
defer dst.Close()
|
|
|
|
|
|
|
|
bytes, err := io.Copy(dst, r)
|
|
|
|
if bytes == 0 {
|
2019-01-25 08:33:11 +01:00
|
|
|
os.Remove(filePath)
|
|
|
|
return m, backends.FileEmptyError
|
2016-06-07 08:37:42 +02:00
|
|
|
} else if err != nil {
|
2019-01-25 08:33:11 +01:00
|
|
|
os.Remove(filePath)
|
|
|
|
return m, err
|
2016-06-07 08:37:42 +02:00
|
|
|
}
|
|
|
|
|
2020-02-17 15:58:56 +01:00
|
|
|
dst.Seek(0, 0)
|
2019-04-09 22:28:18 +02:00
|
|
|
m, err = helpers.GenerateMetadata(dst)
|
|
|
|
if err != nil {
|
|
|
|
os.Remove(filePath)
|
|
|
|
return
|
|
|
|
}
|
2020-02-17 15:58:56 +01:00
|
|
|
dst.Seek(0, 0)
|
2019-04-09 22:28:18 +02:00
|
|
|
|
2019-01-25 08:33:11 +01:00
|
|
|
m.Expiry = expiry
|
|
|
|
m.DeleteKey = deleteKey
|
2020-02-17 15:58:56 +01:00
|
|
|
m.AccessKey = accessKey
|
2021-02-10 04:36:14 +01:00
|
|
|
m.SrcIp = srcIp
|
2019-01-25 08:33:11 +01:00
|
|
|
m.ArchiveFiles, _ = helpers.ListArchiveFiles(m.Mimetype, m.Size, dst)
|
2016-06-07 08:37:42 +02:00
|
|
|
|
2019-01-25 08:33:11 +01:00
|
|
|
err = b.writeMetadata(key, m)
|
|
|
|
if err != nil {
|
|
|
|
os.Remove(filePath)
|
|
|
|
return
|
|
|
|
}
|
2016-06-07 08:37:42 +02:00
|
|
|
|
2019-01-25 08:33:11 +01:00
|
|
|
return
|
2016-06-07 08:37:42 +02:00
|
|
|
}
|
|
|
|
|
2019-04-09 22:28:18 +02:00
|
|
|
func (b LocalfsBackend) PutMetadata(key string, m backends.Metadata) (err error) {
|
|
|
|
err = b.writeMetadata(key, m)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2016-06-07 08:37:42 +02:00
|
|
|
func (b LocalfsBackend) Size(key string) (int64, error) {
|
2019-01-25 08:33:11 +01:00
|
|
|
fileInfo, err := os.Stat(path.Join(b.filesPath, key))
|
2016-06-07 08:37:42 +02:00
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return fileInfo.Size(), nil
|
|
|
|
}
|
|
|
|
|
2017-05-02 06:25:56 +02:00
|
|
|
func (b LocalfsBackend) List() ([]string, error) {
|
|
|
|
var output []string
|
|
|
|
|
2019-01-25 08:33:11 +01:00
|
|
|
files, err := ioutil.ReadDir(b.filesPath)
|
2017-05-02 06:25:56 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, file := range files {
|
|
|
|
output = append(output, file.Name())
|
|
|
|
}
|
|
|
|
|
|
|
|
return output, nil
|
|
|
|
}
|
|
|
|
|
2021-12-23 08:20:44 +01:00
|
|
|
func NewLocalfsBackend(metaPath string, filesPath string, locksPath string) LocalfsBackend {
|
2019-01-25 08:33:11 +01:00
|
|
|
return LocalfsBackend{
|
|
|
|
metaPath: metaPath,
|
|
|
|
filesPath: filesPath,
|
2021-12-23 08:20:44 +01:00
|
|
|
locksPath: locksPath,
|
2019-01-25 08:33:11 +01:00
|
|
|
}
|
2016-06-07 08:37:42 +02:00
|
|
|
}
|