Scanyonero/ftpserver/virtual-fs.go
David Vogel 853a1bb58d Rework into FTP scanning server
- Rename to Scanyonero
- Add FTP server that ingests TIFF, PNG, JPEG or PDF files
- Add web interface to check and modify ingested files
- Rework how ocrmypdf is invoked

Basics are working, but the program is not in a usable state.
2025-05-14 12:08:38 +02:00

147 lines
4.3 KiB
Go

package ftpserver
import (
"Scanyonero/document"
"io"
"os"
"time"
"github.com/spf13/afero"
"github.com/spf13/afero/mem"
)
const filePathSeparator = os.PathSeparator
type virtualFile struct {
mem.File
Callback func(file document.File) error
}
// Override close behavior.
// When the file handle is closed, we will forward the file content via callback.
func (v *virtualFile) Close() error {
if v.Callback != nil {
file := document.File{
Name: v.Name(),
}
var err error
if file.Data, err = io.ReadAll(mem.NewReadOnlyFileHandle(v.Data())); err != nil {
v.File.Close()
return err
}
if err := v.Callback(file); err != nil {
v.File.Close()
return err
}
}
return v.File.Close()
}
var _ afero.File = &virtualFile{}
type virtualFS struct {
Callback func(file document.File) error
}
var _ afero.Fs = &virtualFS{}
// Create creates a file in the filesystem, returning the file and an error, if any happens.
func (v *virtualFS) Create(name string) (afero.File, error) {
name = normalizePath(name)
//log.Printf("VirtualFS: Create: %v", name)
file := mem.CreateFile(name)
fileHandle := *mem.NewFileHandle(file)
return &virtualFile{File: fileHandle, Callback: v.Callback}, nil
}
// Mkdir creates a directory in the filesystem, return an error if any happens.
func (v *virtualFS) Mkdir(name string, perm os.FileMode) error {
//name = normalizePath(name)
//log.Printf("VirtualFS: Mkdir: %v, %v", name, perm)
return nil
}
// MkdirAll creates a directory path and all parents that does not exist yet.
func (v *virtualFS) MkdirAll(path string, perm os.FileMode) error {
//path = normalizePath(path)
//log.Printf("VirtualFS: MkdirAll: %v, %v", path, perm)
return nil
}
// Open opens a file, returning it or an error, if any happens.
func (v *virtualFS) Open(name string) (afero.File, error) {
name = normalizePath(name)
//log.Printf("VirtualFS: Open: %v", name)
dir := mem.CreateDir(name)
mem.SetMode(dir, os.ModeDir|0o755)
return mem.NewReadOnlyFileHandle(dir), nil
}
// OpenFile opens a file using the given flags and the given mode.
func (v *virtualFS) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) {
name = normalizePath(name)
//log.Printf("VirtualFS: OpenFile: %v, %v, %v", name, flag, perm)
return v.Create(name)
}
// Remove removes a file identified by name, returning an error, if any happens.
func (v *virtualFS) Remove(name string) error {
name = normalizePath(name)
//log.Printf("VirtualFS: Remove: %v", name)
return &os.PathError{Op: "remove", Path: name, Err: os.ErrNotExist}
}
// RemoveAll removes a directory path and any children it contains. It does not fail if the path does not exist (return nil).
func (v *virtualFS) RemoveAll(path string) error {
//path = normalizePath(path)
//log.Printf("VirtualFS: RemoveAll: %v", path)
return nil
}
// Rename renames a file.
func (v *virtualFS) Rename(oldName, newName string) error {
oldName = normalizePath(oldName)
//newName = normalizePath(newName)
//log.Printf("VirtualFS: Rename: %v -> %v", oldName, newName)
return &os.PathError{Op: "rename", Path: oldName, Err: os.ErrNotExist}
}
// Stat returns a FileInfo describing the named file, or an error, if any happens.
func (v *virtualFS) Stat(name string) (os.FileInfo, error) {
name = normalizePath(name)
//log.Printf("VirtualFS: Stat: %v", name)
dir := mem.CreateDir(name)
mem.SetMode(dir, os.ModeDir|0o755)
return mem.GetFileInfo(dir), nil
}
// The name of this FileSystem.
func (v *virtualFS) Name() string {
return "ScanyoneroVirtualFS"
}
// Chmod changes the mode of the named file to mode.
func (v *virtualFS) Chmod(name string, mode os.FileMode) error {
name = normalizePath(name)
//log.Printf("VirtualFS: Chmod: %v, %v", name, mode)
return &os.PathError{Op: "chmod", Path: name, Err: os.ErrNotExist}
}
// Chown changes the uid and gid of the named file.
func (v *virtualFS) Chown(name string, uid, gid int) error {
name = normalizePath(name)
//log.Printf("VirtualFS: Chown: %v, %v, %v", name, uid, gid)
return &os.PathError{Op: "chown", Path: name, Err: os.ErrNotExist}
}
// Chtimes changes the access and modification times of the named file.
func (v *virtualFS) Chtimes(name string, atime time.Time, mtime time.Time) error {
name = normalizePath(name)
//log.Printf("VirtualFS: Chtimes: %v, %v, %v", name, atime, mtime)
return &os.PathError{Op: "chtimes", Path: name, Err: os.ErrNotExist}
}