passed/storage/dir.go

143 lines
2 KiB
Go
Raw Normal View History

2024-10-30 09:09:18 +00:00
package storage
import (
2024-10-30 11:18:27 +00:00
"encoding/gob"
2024-10-30 09:09:18 +00:00
"log"
"os"
"path"
"time"
)
2024-10-30 10:47:17 +00:00
func NewDirStore(path string) Store {
2024-10-30 09:09:18 +00:00
store := &dir{
2024-10-30 10:47:17 +00:00
path: path,
2024-10-30 09:09:18 +00:00
}
return store
}
type dir struct {
2024-10-30 10:47:17 +00:00
path string
2024-10-30 09:09:18 +00:00
}
type dirEntry struct {
2024-10-30 11:18:27 +00:00
Password []byte
ExpiresAt time.Time
}
2024-10-30 10:17:48 +00:00
func (store *dir) Create(password []byte, expiresAt time.Time) (string, error) {
2024-10-30 09:09:18 +00:00
for range 1000 {
id := generateId(24)
path := store.getPath(id)
file, err := os.OpenFile(
path,
os.O_CREATE|os.O_EXCL|os.O_WRONLY,
os.ModePerm,
)
switch {
case os.IsExist(err):
continue
case err != nil:
return "", err
}
defer file.Close()
entry := dirEntry{
2024-10-30 09:09:18 +00:00
Password: password,
ExpiresAt: expiresAt,
}
2024-10-30 11:18:27 +00:00
err = gob.NewEncoder(file).Encode(&entry)
2024-10-30 09:09:18 +00:00
if err != nil {
log.Printf("%s", err)
return "", err
}
return id, nil
}
return "", ErrFull
}
2024-10-30 10:17:48 +00:00
func (store *dir) Get(id string) ([]byte, error) {
2024-10-30 09:09:18 +00:00
path := store.getPath(id)
file, err := os.OpenFile(
path,
os.O_RDONLY,
0,
)
switch {
case os.IsNotExist(err):
return nil, ErrNotFound
case err != nil:
return nil, err
}
defer file.Close()
var entry dirEntry
2024-10-30 11:18:27 +00:00
err = gob.NewDecoder(file).Decode(&entry)
2024-10-30 09:09:18 +00:00
if err != nil {
return nil, err
}
return entry.Password, nil
}
2024-10-30 10:17:48 +00:00
func (store *dir) Delete(id string) error {
2024-10-30 09:09:18 +00:00
path := store.getPath(id)
2024-10-30 10:17:48 +00:00
err := os.Remove(path)
if err != nil {
return nil
2024-10-30 09:09:18 +00:00
}
2024-10-30 10:17:48 +00:00
return nil
2024-10-30 09:09:18 +00:00
}
2024-10-30 10:47:17 +00:00
func (store *dir) ClearExpired() error {
now := time.Now()
2024-10-30 09:09:18 +00:00
2024-10-30 10:47:17 +00:00
entries, err := os.ReadDir(store.path)
if err != nil {
return err
}
2024-10-30 09:09:18 +00:00
2024-10-30 10:47:17 +00:00
for _, file := range entries {
id := file.Name()
path := store.getPath(id)
file, err := os.OpenFile(
path,
os.O_RDONLY,
0,
)
if err != nil {
return err
}
2024-10-30 09:09:18 +00:00
2024-10-30 10:47:17 +00:00
defer file.Close()
2024-10-30 09:09:18 +00:00
var entry dirEntry
2024-10-30 11:18:27 +00:00
err = gob.NewDecoder(file).Decode(&entry)
2024-10-30 10:47:17 +00:00
if err != nil {
return err
}
if now.After(entry.ExpiresAt) {
// Close file early as we need to delete it
file.Close()
err = store.Delete(id)
if err != nil {
return err
2024-10-30 09:09:18 +00:00
}
}
}
2024-10-30 10:47:17 +00:00
return nil
2024-10-30 09:09:18 +00:00
}
func (store *dir) getPath(id string) string {
return path.Join(store.path, id)
}