146 lines
2.9 KiB
Go
146 lines
2.9 KiB
Go
package main
|
|
|
|
import (
|
|
// External
|
|
"github.com/jmoiron/sqlx"
|
|
|
|
// Standard
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
"time"
|
|
)
|
|
|
|
type File struct {
|
|
ID int
|
|
UUID string
|
|
UserID int `db:"user_id"`
|
|
Name string `db:"name"`
|
|
Size int
|
|
Type string `db:"type"`
|
|
Modified time.Time
|
|
UploadComplete bool `db:"upload_complete"`
|
|
}
|
|
|
|
var (
|
|
fileUUIDCache map[string]int
|
|
)
|
|
|
|
func init() {
|
|
fileUUIDCache = make(map[string]int)
|
|
}
|
|
|
|
func AddFileToDb(userID int, file *File) (err error) { // {{{
|
|
file.UserID = userID
|
|
|
|
var rows *sqlx.Rows
|
|
rows, err = db.Queryx(`
|
|
INSERT INTO public.file(user_id, uuid, name, size, type, modified, upload_complete)
|
|
VALUES($1, $2, $3, $4, $5, $6, false)
|
|
ON CONFLICT (user_id, uuid) DO UPDATE set name = public.file.name
|
|
RETURNING id
|
|
`,
|
|
file.UserID,
|
|
file.UUID,
|
|
file.Name,
|
|
file.Size,
|
|
file.Type,
|
|
file.Modified,
|
|
)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
|
|
rows.Next()
|
|
err = rows.Scan(&file.ID)
|
|
return
|
|
} // }}}
|
|
func Files(userID int, nodeUUID string, fileID int) (files []File, err error) { // {{{
|
|
var rows *sqlx.Rows
|
|
rows, err = db.Queryx(
|
|
`SELECT *
|
|
FROM file
|
|
WHERE
|
|
user_id = $1 AND
|
|
node_uuid = $2 AND
|
|
CASE $3::int
|
|
WHEN 0 THEN true
|
|
ELSE id = $3
|
|
END`,
|
|
userID,
|
|
nodeUUID,
|
|
fileID,
|
|
)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
|
|
files = []File{}
|
|
for rows.Next() {
|
|
file := File{}
|
|
if err = rows.StructScan(&file); err != nil {
|
|
return
|
|
}
|
|
files = append(files, file)
|
|
}
|
|
|
|
return
|
|
} // }}}
|
|
func FileIDToPath(id int) (string, string) { // {{{
|
|
str := fmt.Sprintf("%012d", id)
|
|
dir := path.Join(config.Storage.Files, str[0:4], str[4:8])
|
|
fpath := path.Join(config.Storage.Files, str[0:4], str[4:8], str[8:12])
|
|
return dir, fpath
|
|
} // }}}
|
|
|
|
func FileWriteData(userID int, dbID int, data []byte, create bool) (err error) { // {{{
|
|
dir, fpath := FileIDToPath(dbID)
|
|
err = os.MkdirAll(dir, 0700)
|
|
if err != nil {
|
|
Log.Error("file", "error", err)
|
|
return
|
|
}
|
|
|
|
var f *os.File
|
|
if create {
|
|
f, err = os.OpenFile(fpath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
|
} else {
|
|
f, err = os.OpenFile(fpath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
|
}
|
|
if err != nil {
|
|
Log.Error("file", "error", err)
|
|
return
|
|
}
|
|
defer f.Close()
|
|
|
|
_, err = f.Write(data)
|
|
if err != nil {
|
|
Log.Error("file", "error", err)
|
|
return
|
|
}
|
|
|
|
return
|
|
} // }}}
|
|
|
|
func FileMetadata(userID int, uuid string) (f File, err error) { // {{{
|
|
row := db.QueryRowx(`SELECT * FROM public.file WHERE user_id = $1 AND "uuid" = $2`, userID, uuid)
|
|
err = row.StructScan(&f)
|
|
return
|
|
|
|
} // }}}
|
|
func FileForUser(userID int, uuid string) (f *os.File, md File, err error) { // {{{
|
|
row := db.QueryRowx(`SELECT * FROM public.file WHERE user_id = $1 AND "uuid" = $2`, userID, uuid)
|
|
err = row.StructScan(&md)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
_, fpath := FileIDToPath(md.ID)
|
|
f, err = os.OpenFile(fpath, os.O_RDONLY, 0600)
|
|
return
|
|
|
|
} // }}}
|
|
|
|
// vim: foldmethod=marker
|