main.go (4043B)
1 package main 2 3 import ( 4 "bytes" 5 "context" 6 "flag" 7 "fmt" 8 "io" 9 "io/fs" 10 "log" 11 "net" 12 "os" 13 "strings" 14 15 "git.mtkn.jp/lib9p" 16 ) 17 18 type numFS struct { 19 root *numFile 20 } 21 22 func (fsys *numFS) String() string { 23 if fsys.root == nil { 24 return "<empty>" 25 } 26 return fsysString(fsys.root) 27 } 28 29 func fsysString(f *numFile) string { 30 s := fmt.Sprintf("%d\n", f.id) 31 for _, c := range f.children { 32 cs := fsysString(c) 33 ln := strings.Split(cs, "\n") 34 for _, l := range ln { 35 s += "\t" + l + "\n" 36 } 37 } 38 return s 39 } 40 41 func (fsys *numFS) OpenFile(name string, _ int) (lib9p.File, error) { 42 if name == "." || name == "" { 43 return fsys.root, nil 44 } 45 wname := strings.Split(name, "/") 46 cwd := fsys.root 47 L: 48 for _, wn := range wname { 49 for _, c := range cwd.children { 50 if fmt.Sprintf("%d", c.id) == wn { 51 cwd = c 52 continue L 53 } 54 } 55 return nil, fmt.Errorf("not found") 56 } 57 return cwd, nil 58 } 59 60 // This function assumes that group and uid both exist and 61 // the leader of group has the same name as group itself. 62 func (fsys *numFS) IsGroupLeader(group, uid string) bool { 63 return group == uid 64 } 65 66 // This function assumes that group and uid both exists and 67 // only the member of group has the same name as group itself. 68 func (fsys *numFS) IsGroupMember(group, uid string) bool { 69 return group == uid 70 } 71 72 type numFile struct { 73 fs *numFS 74 id int 75 reader *bytes.Reader 76 children []*numFile 77 } 78 79 func (f *numFile) Fsys() lib9p.FS { return f.fs } 80 81 func (f *numFile) Stat() (*lib9p.FileInfo, error) { 82 var stat lib9p.Stat 83 stat.Type = 0 84 stat.Dev = 0 85 if f.id == -1 { 86 stat.Qid = lib9p.Qid{ 87 Type: lib9p.QTDIR, 88 Vers: 0, 89 Path: ^uint64(0), 90 } 91 } else { 92 stat.Qid = lib9p.Qid{ 93 Type: lib9p.QTFILE, 94 Vers: 0, 95 Path: uint64(f.id), 96 } 97 } 98 var mode lib9p.FileMode 99 if f.id == -1 { 100 mode |= fs.ModeDir 101 } 102 mode |= 0444 103 stat.Mode = mode 104 stat.Atime = 0 105 stat.Mtime = 0 106 var length int64 107 if f.id == -1 { 108 length = 0 109 } else { 110 length = f.reader.Size() 111 } 112 stat.Length = length 113 stat.Name = fmt.Sprintf("%d", f.id) 114 stat.Uid = "kenji" 115 stat.Gid = "kenji" 116 stat.Muid = "kenji" 117 return &lib9p.FileInfo{Stat: stat}, nil 118 } 119 120 func (f *numFile) Qid() lib9p.Qid { 121 var qid lib9p.Qid 122 if f.id == -1 { 123 qid = lib9p.Qid{ 124 Type: lib9p.QTDIR, 125 Vers: 0, 126 Path: ^uint64(0), 127 } 128 } else { 129 qid = lib9p.Qid{ 130 Type: lib9p.QTFILE, 131 Vers: 0, 132 Path: uint64(f.id), 133 } 134 } 135 return qid 136 } 137 138 func (f *numFile) Read(p []byte) (int, error) { 139 if f.id == -1 { 140 return 0, fmt.Errorf("is a directory") 141 } 142 return f.reader.Read(p) 143 } 144 145 func (f *numFile) ReadAt(p []byte, off int64) (n int, err error) { 146 if f.id == -1 { 147 return 0, fmt.Errorf("is a directory") 148 } 149 return f.reader.ReadAt(p, off) 150 } 151 152 func (f *numFile) ReadDir(n int) ([]fs.DirEntry, error) { 153 if f.id != -1 { 154 return nil, fmt.Errorf("not a directory") 155 } 156 de := make([]fs.DirEntry, len(f.children)) 157 for i, c := range f.children { 158 s, err := c.Stat() 159 if err != nil { 160 return nil, fmt.Errorf("stat: %v", err) 161 } 162 de[i] = s 163 } 164 return de, nil 165 } 166 167 func (f *numFile) Close() error { 168 if f.reader != nil { 169 f.reader.Seek(0, io.SeekStart) 170 } 171 return nil 172 } 173 174 var dFlag = flag.Bool("D", false, "Prints chatty message to the stderr.") 175 176 func main() { 177 flag.Parse() 178 179 if flag.NArg() != 0 { 180 fmt.Fprintf(os.Stderr, "usage: %s [-D]\n", os.Args[0]) 181 os.Exit(1) 182 } 183 184 fsys := new(numFS) 185 fsys.root = &numFile{ 186 fs: fsys, 187 id: -1, 188 reader: nil, 189 children: []*numFile{ 190 &numFile{fsys, 0, bytes.NewReader([]byte("0\n")), nil}, 191 &numFile{fsys, 1, bytes.NewReader([]byte("1\n")), nil}, 192 &numFile{fsys, 2, bytes.NewReader([]byte("2\n")), nil}, 193 &numFile{fsys, 3, bytes.NewReader([]byte("3\n")), nil}, 194 }, 195 } 196 197 listener, err := net.Listen("tcp", "127.0.0.1:5640") 198 if err != nil { 199 log.Fatalf("listen tcp: %v", err) 200 } 201 s := lib9p.NewServer(fsys) 202 if *dFlag { 203 s.Chatty() 204 } 205 for { 206 conn, err := listener.Accept() 207 if err != nil { 208 log.Printf("accept connection: %v", err) 209 continue 210 } 211 go func() { 212 defer conn.Close() 213 s.Serve(context.TODO(), conn, conn) 214 }() 215 } 216 }