Skip to content

Instantly share code, notes, and snippets.

@leveryd
Created October 1, 2021 16:20
Show Gist options
  • Select an option

  • Save leveryd/9cd91c93fd6361b163291c1e5e4481da to your computer and use it in GitHub Desktop.

Select an option

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

leveryd commented Oct 1, 2021

Copy link
Copy Markdown
Author

image

image

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