ref: a2bc51f7f3479008175e41367105e7ab2516318e
dir: /main.go/
package main
import (
"fmt"
"os"
"io"
"sync"
"time"
"golang.org/x/sys/plan9"
"github.com/knusbaum/go9p/fs"
"github.com/knusbaum/go9p"
"github.com/knusbaum/go9p/proto"
)
type snarfile struct {
fs.BaseFile
real *os.File
realwrite *os.File
snarfStream fs.Stream
mu sync.Mutex
}
func (f *snarfile) Write(fid uint64, offset uint64, data []byte) (uint32, error) {
f.mu.Lock()
defer f.mu.Unlock()
realwrite, err := os.OpenFile("/mnt/snarflogger/rsnarf", os.O_WRONLY, 0644)
if err != nil {
fmt.Printf("Coudn't open snarf for writing: %s\n", err)
return 0, err
}
defer realwrite.Close()
realwrite.Write(data)
_, err = f.snarfStream.Write(data)
if err != nil {
fmt.Printf("Error writing to snarfStream: %v\n", err)
return 0, err
}
return uint32(len(data)), nil
}
func (f *snarfile) Read(fid uint64, offset uint64, count uint64) ([]byte, error) {
real, _ := os.Open("/mnt/snarflogger/rsnarf")
defer real.Close()
var reader io.Reader = real
content, err := io.ReadAll(reader)
return content, err
}
func newSnarf(fsys *fs.FS, name, uid, gid string, perm uint32, real *os.File, realwrite *os.File, stream fs.Stream) *snarfile {
stat := fsys.NewStat(name, uid, gid, perm)
return &snarfile{
BaseFile: *fs.NewBaseFile(stat),
real: real,
realwrite: realwrite,
snarfStream: stream,
}
}
func mountmnt() {
fid, dir := fs.NewFS("penny", "penny", proto.DMDIR|0644)
stat := fid.NewStat("rsnarf", "penny", "penny", 0644)
mntfile := fs.NewBaseFile(stat)
dir.AddChild(mntfile)
var fds [2]int
var err error
err = plan9.Pipe(fds[:])
if err != nil {
fmt.Printf("Failed to create pipe for /mnt/snarflogger: %s\n", err)
os.Exit(1)
}
rw := os.NewFile(uintptr(fds[0]), "")
go func() {
if err := go9p.ServeReadWriter(rw, rw, fid.Server()); err != nil {
fmt.Printf("failed to serve /mnt/snarflogger: %v\n", err)
os.Exit(1)
}
}()
plan9.Mount(fds[1], -1, "/mnt/snarflogger", plan9.MREPL, "")
err = plan9.Bind("/dev/snarf", "/mnt/snarflogger/rsnarf", plan9.MREPL)
}
func main() {
mountmnt()
fid, dir := fs.NewFS("penny", "penny", proto.DMDIR|0644)
snarfStream := fs.NewSkippingStream(1024)
snarfLogStat := fid.NewStat("snarflog", "penny", "penny", 0644)
snarfLogFile := fs.NewStreamFile(snarfLogStat, snarfStream)
if err := dir.AddChild(snarfLogFile); err != nil {
fmt.Printf("Err adding snarflog: %s\n", err)
return
}
snarf := newSnarf(fid, "snarf", "penny", "penny", 0644, nil, nil, snarfStream)
if err := dir.AddChild(snarf); err != nil {
fmt.Printf("Err: %s\n", err)
return
}
go func() {
if err := go9p.PostSrv("snarflogger", fid.Server()); err != nil {
fmt.Printf("Failed to post server: %v\n", err)
os.Exit(1)
}
}()
for {
_, err := os.Stat("/srv/snarflogger")
if err == nil {
break
}
time.Sleep(100 * time.Millisecond)
}
srvFd, err := plan9.Open("/srv/snarflogger", plan9.O_RDWR)
if err != nil {
fmt.Printf("Failed to open /srv/snarflogger: %v\n", err)
os.Exit(1)
}
defer plan9.Close(srvFd)
err = plan9.Mount(srvFd, -1, "/dev", plan9.MBEFORE, "")
if err != nil {
fmt.Printf("Failed to mount: %v\n", err)
os.Exit(1)
}
select{}
}