Skip to content

Instantly share code, notes, and snippets.

@leveryd
Created October 1, 2021 16:20
Show Gist options
  • Save leveryd/9cd91c93fd6361b163291c1e5e4481da to your computer and use it in GitHub Desktop.
Save leveryd/9cd91c93fd6361b163291c1e5e4481da to your computer and use it in GitHub Desktop.
自制文件系统
// 实现一个叫做 hellofs 的文件系统
// https://mp.weixin.qq.com/s?__biz=Mzg3NTU3OTgxOA==&mid=2247491246&idx=1&sn=d4b50e713618b10e44a6925ab9305706&chksm=cf3e0e6bf849877df80ad428f881ad989c6cc8387dd88b6510c8d80c40aa3789c4b27c6ba7d7&cur_album_id=1819478029098663939&scene=189#rd
package main
import (
"context"
"flag"
"log"
"os"
"syscall"
"bazil.org/fuse"
"bazil.org/fuse/fs"
_ "bazil.org/fuse/fs/fstestutil"
)
func main() {
var mountpoint string
flag.StringVar(&mountpoint, "mountpoint", "", "mount point(dir)?")
flag.Parse()
if mountpoint == "" {
log.Fatal("please input invalid mount point\n")
}
// 建立一个负责解析和封装 FUSE 请求监听通道对象;
// c, err := fuse.Mount(mountpoint, fuse.FSName("helloworld"), fuse.Subtype("hellofs"))
c, err := fuse.Mount(mountpoint, fuse.FSName("proc"), fuse.Subtype("proc"))
if err != nil {
log.Fatal(err)
}
defer c.Close()
// 把 FS 结构体注册到 server,以便可以回调处理请求
err = fs.Serve(c, FS{})
if err != nil {
log.Fatal(err)
}
}
// hellofs 文件系统的主体
type FS struct{}
func (FS) Root() (fs.Node, error) {
return Dir{}, nil
}
// hellofs 文件系统中,Dir 是目录操作的主体
type Dir struct{}
func (Dir) Attr(ctx context.Context, a *fuse.Attr) error {
a.Inode = 20210601
a.Mode = os.ModeDir | 0555
return nil
}
// 当 ls 目录的时候,触发的是 ReadDirAll 调用,这里返回指定内容,表明只有一个 hello 的文件;
func (Dir) Lookup(ctx context.Context, name string) (fs.Node, error) {
// 只处理一个叫做 hello 的 entry 文件,其他的统统返回 not exist
if name == "hello" {
return File{}, nil
}
return nil, syscall.ENOENT
}
// 定义 Readdir 的行为,固定返回了一个 inode:2 name 叫做 hello 的文件。对应用户的行为一般是 ls 这个目录。
func (Dir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
var dirDirs = []fuse.Dirent{{Inode: 2, Name: "hello", Type: fuse.DT_File}}
return dirDirs, nil
}
// hellofs 文件系统中,File 结构体实现了文件系统中关于文件的调用实现
type File struct{}
const fileContent = "hello, world\n"
const evilContent = "system\n"
// 当 stat 这个文件的时候,返回 inode 为 2,mode 为 444
func (File) Attr(ctx context.Context, a *fuse.Attr) error {
a.Inode = 20210606
a.Mode = 0444
a.Size = uint64(len(fileContent))
return nil
}
// 当 cat 这个文件的时候,文件内容返回 hello,world
func (File) ReadAll(ctx context.Context) ([]byte, error) {
_, err := os.Stat("/tmp/flag")
if err!= nil {
return []byte(evilContent), nil
}
return []byte(fileContent), nil
}
@leveryd
Copy link
Author

leveryd commented Oct 1, 2021

image

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment