Initial commit
This commit is contained in:
28
ffs/dreamfile.go
Normal file
28
ffs/dreamfile.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package ffs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"fusetest/furcadia"
|
||||
|
||||
"bazil.org/fuse"
|
||||
)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TYPE: DreamFile ////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type DreamFile struct {
|
||||
Dream *furcadia.PounceDream
|
||||
_attr fuse.Attr
|
||||
}
|
||||
|
||||
func (f *DreamFile) GetName() string {
|
||||
return f.Dream.ShortURL
|
||||
}
|
||||
|
||||
func (f *DreamFile) Attr(ctx context.Context, a *fuse.Attr) error {
|
||||
fmt.Printf("[D] DreamFile('%v').Attr()\n", f.GetName())
|
||||
*a = f._attr
|
||||
return nil
|
||||
}
|
||||
115
ffs/dreamsdir.go
Normal file
115
ffs/dreamsdir.go
Normal file
@@ -0,0 +1,115 @@
|
||||
package ffs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"bazil.org/fuse"
|
||||
"bazil.org/fuse/fs"
|
||||
)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CONSTANTS //////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const (
|
||||
DREAMS_DIR_INODE_BASE = 0x2000
|
||||
DREAMS_DIR_MAX_INODES = 0x1000
|
||||
)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TYPE: DreamsDir ////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type DreamsDir struct {
|
||||
_attr fuse.Attr
|
||||
_entries []fuse.Dirent
|
||||
}
|
||||
|
||||
func NewDreamsDir(inodeBase uint64, rootUID, rootGID uint32) *DreamsDir {
|
||||
now := time.Now()
|
||||
dir := &DreamsDir{
|
||||
_attr: fuse.Attr{
|
||||
Inode: inodeBase,
|
||||
Nlink: 1,
|
||||
Mode: os.ModeDir | 0500,
|
||||
Uid: rootUID,
|
||||
Gid: rootGID,
|
||||
Atime: now,
|
||||
Ctime: now,
|
||||
Mtime: now,
|
||||
},
|
||||
}
|
||||
|
||||
// add basic entries
|
||||
dir._entries = append(
|
||||
dir._entries,
|
||||
fuse.Dirent{Inode: dir._attr.Inode, Name: ".", Type: fuse.DT_Dir},
|
||||
fuse.Dirent{Inode: ROOT_INODE, Name: "..", Type: fuse.DT_Dir},
|
||||
)
|
||||
|
||||
return dir
|
||||
}
|
||||
|
||||
func (d *DreamsDir) GetAttr() *fuse.Attr {
|
||||
return &d._attr
|
||||
}
|
||||
|
||||
func (d *DreamsDir) Attr(ctx context.Context, a *fuse.Attr) error {
|
||||
*a = d._attr
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DreamsDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
|
||||
pounce := G_FS._pounce
|
||||
dreams := pounce.Dreams
|
||||
items := make([]fuse.Dirent, len(dreams)+2)
|
||||
|
||||
items[0] = fuse.Dirent{Inode: d._attr.Inode, Name: ".", Type: fuse.DT_Dir}
|
||||
items[1] = fuse.Dirent{Inode: ROOT_INODE, Name: "..", Type: fuse.DT_Dir}
|
||||
|
||||
i := 2
|
||||
for shortURL := range dreams {
|
||||
items[i] = fuse.Dirent{
|
||||
Inode: uint64(2000 + i),
|
||||
Name: shortURL,
|
||||
Type: fuse.DT_File,
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func (d *DreamsDir) Lookup(ctx context.Context, name string) (fs.Node, error) {
|
||||
if name == "." {
|
||||
return d, nil
|
||||
}
|
||||
|
||||
dreams := G_FS._pounce.Dreams
|
||||
dream, exists := dreams[name]
|
||||
if !exists {
|
||||
fmt.Printf("[D] DreamsDir().Lookup('%v'): ENOENT\n", name)
|
||||
return nil, syscall.ENOENT
|
||||
}
|
||||
|
||||
fmt.Printf("[D] DreamsDir().Lookup('%v'): OK\n", name)
|
||||
now := time.Now()
|
||||
return &DreamFile{
|
||||
Dream: dream,
|
||||
_attr: fuse.Attr{
|
||||
Inode: 0,
|
||||
Nlink: 1,
|
||||
Mode: 0400,
|
||||
Size: 0,
|
||||
Ctime: now,
|
||||
Atime: now,
|
||||
Mtime: now,
|
||||
Uid: d._attr.Uid,
|
||||
Gid: d._attr.Gid,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
67
ffs/fs.go
Normal file
67
ffs/fs.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package ffs
|
||||
|
||||
import (
|
||||
"fusetest/furcadia"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"bazil.org/fuse"
|
||||
"bazil.org/fuse/fs"
|
||||
)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// VAR ////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var (
|
||||
// Filesystem context (there should only be one)
|
||||
G_FS *FurcFS = nil
|
||||
)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TYPE: FS ///////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type FurcFS struct {
|
||||
RootDir *RootDir
|
||||
_pounce *furcadia.PounceList
|
||||
}
|
||||
|
||||
func InitFS(rootUID, rootGID uint32) *FurcFS {
|
||||
if G_FS != nil {
|
||||
panic("G_FS already initialized - wtf?")
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
fs := &FurcFS{
|
||||
RootDir: &RootDir{
|
||||
_nodes: make(map[string]TopLevelDir),
|
||||
_attr: fuse.Attr{
|
||||
Inode: ROOT_INODE,
|
||||
Nlink: 1,
|
||||
Mode: os.ModeDir | 0500,
|
||||
Uid: rootUID,
|
||||
Gid: rootGID,
|
||||
Atime: now,
|
||||
Ctime: now,
|
||||
Mtime: now,
|
||||
},
|
||||
},
|
||||
_pounce: furcadia.NewPounceList(),
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// register root-level items
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
fs.RootDir._nodes["furres"] = NewFurresDir(FURRES_DIR_INODE_BASE, rootUID, rootGID)
|
||||
fs.RootDir._nodes["dreams"] = NewDreamsDir(DREAMS_DIR_INODE_BASE, rootUID, rootGID)
|
||||
|
||||
// FS context is now ready
|
||||
G_FS = fs
|
||||
return fs
|
||||
}
|
||||
|
||||
func (fs *FurcFS) Root() (fs.Node, error) {
|
||||
return fs.RootDir, nil
|
||||
}
|
||||
28
ffs/furrefile.go
Normal file
28
ffs/furrefile.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package ffs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"fusetest/furcadia"
|
||||
|
||||
"bazil.org/fuse"
|
||||
)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TYPE: DreamFile ////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type FurreFile struct {
|
||||
Furre *furcadia.PounceFurre
|
||||
_attr fuse.Attr
|
||||
}
|
||||
|
||||
func (f *FurreFile) GetName() string {
|
||||
return f.Furre.DisplayName
|
||||
}
|
||||
|
||||
func (f *FurreFile) Attr(ctx context.Context, a *fuse.Attr) error {
|
||||
fmt.Printf("[D] FurreFile('%v').Attr()\n", f.GetName())
|
||||
*a = f._attr
|
||||
return nil
|
||||
}
|
||||
133
ffs/furresdir.go
Normal file
133
ffs/furresdir.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package ffs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"fusetest/furcadia"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"bazil.org/fuse"
|
||||
"bazil.org/fuse/fs"
|
||||
)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CONSTANTS //////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const (
|
||||
FURRES_DIR_INODE_BASE = 0x1000
|
||||
FURRES_DIR_MAX_INODES = 0x1000
|
||||
)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TYPE: DreamsDir ////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type FurresDir struct {
|
||||
_attr fuse.Attr
|
||||
_entries []fuse.Dirent
|
||||
_index map[string]int
|
||||
}
|
||||
|
||||
func NewFurresDir(inodeBase uint64, rootUID, rootGID uint32) *FurresDir {
|
||||
now := time.Now()
|
||||
dir := &FurresDir{
|
||||
_attr: fuse.Attr{
|
||||
Inode: inodeBase,
|
||||
Nlink: 1,
|
||||
Mode: os.ModeDir | 0500,
|
||||
Uid: rootUID,
|
||||
Gid: rootGID,
|
||||
Atime: now,
|
||||
Ctime: now,
|
||||
Mtime: now,
|
||||
},
|
||||
_index: make(map[string]int),
|
||||
}
|
||||
|
||||
// add basic entries
|
||||
dir._entries = append(
|
||||
dir._entries,
|
||||
fuse.Dirent{Inode: dir._attr.Inode, Name: ".", Type: fuse.DT_Dir},
|
||||
fuse.Dirent{Inode: ROOT_INODE, Name: "..", Type: fuse.DT_Dir},
|
||||
)
|
||||
|
||||
// add basic entries to the index
|
||||
for i := range dir._entries {
|
||||
dirent := &dir._entries[i]
|
||||
dir._index[dirent.Name] = i
|
||||
}
|
||||
|
||||
return dir
|
||||
}
|
||||
|
||||
func (d *FurresDir) GetAttr() *fuse.Attr {
|
||||
return &d._attr
|
||||
}
|
||||
|
||||
func (d *FurresDir) Attr(ctx context.Context, a *fuse.Attr) error {
|
||||
*a = d._attr
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *FurresDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
|
||||
return d._entries, nil
|
||||
// pounce := G_FS._pounce
|
||||
// furres := pounce.Furres
|
||||
// items := make([]fuse.Dirent, len(furres)+2)
|
||||
|
||||
// items[0] = fuse.Dirent{Inode: d._attr.Inode, Name: ".", Type: fuse.DT_Dir}
|
||||
// items[1] = fuse.Dirent{Inode: ROOT_INODE, Name: "..", Type: fuse.DT_Dir}
|
||||
|
||||
// var i uint64 = 2
|
||||
// for _, furre := range furres {
|
||||
// items[i] = fuse.Dirent{
|
||||
// Inode: d._attr.Inode + i - 1,
|
||||
// Name: furre.DisplayName,
|
||||
// Type: fuse.DT_File,
|
||||
// }
|
||||
// i++
|
||||
// }
|
||||
|
||||
// return items, nil
|
||||
}
|
||||
|
||||
func (d *FurresDir) Lookup(ctx context.Context, name string) (fs.Node, error) {
|
||||
if name == "." {
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// find dirent for the given name
|
||||
|
||||
direntIndex, exists = d._index[name]
|
||||
if !exists {
|
||||
return nil, syscall.ENOENT
|
||||
}
|
||||
|
||||
furres := G_FS._pounce.Furres
|
||||
shortname := furcadia.GetShortName(name)
|
||||
furre, exists := furres[shortname]
|
||||
if !exists {
|
||||
fmt.Printf("[F] FurresDir().Lookup('%v' -> %v): ENOENT\n", name, shortname)
|
||||
return nil, syscall.ENOENT
|
||||
}
|
||||
|
||||
fmt.Printf("[F] FurresDir().Lookup('%v'): OK\n", name)
|
||||
now := time.Now()
|
||||
return &FurreFile{
|
||||
Furre: furre,
|
||||
_attr: fuse.Attr{
|
||||
Inode: 0,
|
||||
Nlink: 1,
|
||||
Mode: 0400,
|
||||
Size: 0,
|
||||
Ctime: now,
|
||||
Atime: now,
|
||||
Mtime: now,
|
||||
Uid: d._attr.Uid,
|
||||
Gid: d._attr.Gid,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
61
ffs/rootdir.go
Normal file
61
ffs/rootdir.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package ffs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"syscall"
|
||||
|
||||
"bazil.org/fuse"
|
||||
"bazil.org/fuse/fs"
|
||||
)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CONSTANTS //////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const ROOT_INODE = 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TYPE: RootDir //////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type RootDir struct {
|
||||
_attr fuse.Attr
|
||||
_nodes map[string]TopLevelDir
|
||||
}
|
||||
|
||||
func (d *RootDir) Attr(ctx context.Context, a *fuse.Attr) error {
|
||||
*a = d._attr
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *RootDir) Lookup(ctx context.Context, name string) (fs.Node, error) {
|
||||
if name == "." {
|
||||
return d, nil
|
||||
}
|
||||
|
||||
node, exists := d._nodes[name]
|
||||
if exists {
|
||||
fmt.Printf("[D] RootDir.Lookup('%v'): OK\n", name)
|
||||
return node, nil
|
||||
}
|
||||
|
||||
fmt.Printf("[D] RootDir.Lookup('%v'): ENOENT\n", name)
|
||||
return nil, syscall.ENOENT
|
||||
}
|
||||
|
||||
func (d *RootDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
|
||||
fmt.Printf("[D] RootDir.ReadDirAll()\n")
|
||||
items := make([]fuse.Dirent, len(d._nodes))
|
||||
i := 0
|
||||
for name, node := range d._nodes {
|
||||
items[i] = fuse.Dirent{
|
||||
Inode: node.GetAttr().Inode,
|
||||
Name: name,
|
||||
Type: fuse.DT_Dir,
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
return items, nil
|
||||
}
|
||||
30
ffs/util.go
Normal file
30
ffs/util.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package ffs
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"bazil.org/fuse"
|
||||
"bazil.org/fuse/fs"
|
||||
)
|
||||
|
||||
type TopLevelDir interface {
|
||||
fs.Node
|
||||
GetAttr() *fuse.Attr
|
||||
}
|
||||
|
||||
func IsValidName(name string) bool {
|
||||
l := len(name)
|
||||
if l == 0 || l > 255 {
|
||||
return false
|
||||
}
|
||||
|
||||
if name == "." || name == ".." {
|
||||
return false
|
||||
}
|
||||
|
||||
if strings.ContainsRune(name, '/') {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user