This repository has been archived on 2026-08-16. You can view files and clone it, but cannot push or open issues or pull requests.
ollie-9p/internal/p9/store.go

130 lines
3.6 KiB
Go

package p9
import (
"os"
"path/filepath"
"time"
)
// syntheticFileInfo implements os.FileInfo for entries with no backing file.
type syntheticFileInfo struct {
name string
mode os.FileMode
size int64
isDir bool
}
func (f *syntheticFileInfo) Name() string { return f.name }
func (f *syntheticFileInfo) Size() int64 { return f.size }
func (f *syntheticFileInfo) Mode() os.FileMode { return f.mode }
func (f *syntheticFileInfo) ModTime() time.Time { return time.Time{} }
func (f *syntheticFileInfo) IsDir() bool { return f.isDir }
func (f *syntheticFileInfo) Sys() any { return nil }
// syntheticEntryImpl implements os.DirEntry for entries with no backing file.
type syntheticEntryImpl struct {
name string
mode os.FileMode
isDir bool
}
func (e *syntheticEntryImpl) Name() string { return e.name }
func (e *syntheticEntryImpl) IsDir() bool { return e.isDir }
func (e *syntheticEntryImpl) Type() os.FileMode {
if e.isDir {
return os.ModeDir
}
return 0
}
func (e *syntheticEntryImpl) Info() (os.FileInfo, error) {
return &syntheticFileInfo{name: e.name, mode: e.mode, isDir: e.isDir}, nil
}
// syntheticEntry returns a synthetic file DirEntry.
func syntheticEntry(name string, mode os.FileMode) os.DirEntry {
return &syntheticEntryImpl{name: name, mode: mode}
}
// syntheticDirEntry returns a synthetic directory DirEntry.
func syntheticDirEntry(name string, mode os.FileMode) os.DirEntry {
return &syntheticEntryImpl{name: name, mode: mode, isDir: true}
}
// ReadableStore is a named collection of byte blobs supporting only read operations.
type ReadableStore interface {
Stat(name string) (os.FileInfo, error)
List() ([]os.DirEntry, error)
Get(name string) ([]byte, error)
}
// WritableStore supports writing blobs by name.
type WritableStore interface {
Put(name string, data []byte) error
}
// ReadWriteStore supports reading and writing but not structural mutations.
type ReadWriteStore interface {
ReadableStore
WritableStore
}
// BlobStore extends ReadWriteStore with creation and deletion.
// Suitable for content-addressed or append-only backing stores.
type BlobStore interface {
ReadWriteStore
Delete(name string) error
Create(name string) error
}
// Store is a fully mutable store that also supports renaming entries.
type Store interface {
BlobStore
Rename(oldName, newName string) error
}
// FlatDirStore implements Store backed by a directory on the local filesystem.
type FlatDirStore struct {
dir string
perm os.FileMode
}
// NewFlatDirStore returns a FlatDirStore rooted at dir.
// perm is applied to newly created or written files.
func NewFlatDirStore(dir string, perm os.FileMode) *FlatDirStore {
return &FlatDirStore{dir: dir, perm: perm}
}
func (s *FlatDirStore) Stat(name string) (os.FileInfo, error) {
return os.Stat(filepath.Join(s.dir, name))
}
func (s *FlatDirStore) List() ([]os.DirEntry, error) {
return os.ReadDir(s.dir)
}
func (s *FlatDirStore) Get(name string) ([]byte, error) {
return os.ReadFile(filepath.Join(s.dir, name))
}
func (s *FlatDirStore) Put(name string, data []byte) error {
if err := os.MkdirAll(s.dir, 0755); err != nil {
return err
}
return os.WriteFile(filepath.Join(s.dir, name), data, s.perm)
}
func (s *FlatDirStore) Delete(name string) error {
return os.Remove(filepath.Join(s.dir, name))
}
func (s *FlatDirStore) Create(name string) error {
if err := os.MkdirAll(s.dir, 0755); err != nil {
return err
}
return os.WriteFile(filepath.Join(s.dir, name), nil, s.perm)
}
func (s *FlatDirStore) Rename(oldName, newName string) error {
return os.Rename(filepath.Join(s.dir, oldName), filepath.Join(s.dir, newName))
}