opcode.go 14.5 KB
Newer Older
1 2 3
package fuse

import (
4
	"bytes"
5
	"fmt"
6
	"log"
7 8 9
	"unsafe"
)

10
var _ = log.Printf
11
var _ = fmt.Printf
12

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
type opcode int

const (
	_OP_LOOKUP      = opcode(1)
	_OP_FORGET      = opcode(2)
	_OP_GETATTR     = opcode(3)
	_OP_SETATTR     = opcode(4)
	_OP_READLINK    = opcode(5)
	_OP_SYMLINK     = opcode(6)
	_OP_MKNOD       = opcode(8)
	_OP_MKDIR       = opcode(9)
	_OP_UNLINK      = opcode(10)
	_OP_RMDIR       = opcode(11)
	_OP_RENAME      = opcode(12)
	_OP_LINK        = opcode(13)
	_OP_OPEN        = opcode(14)
	_OP_READ        = opcode(15)
	_OP_WRITE       = opcode(16)
	_OP_STATFS      = opcode(17)
	_OP_RELEASE     = opcode(18)
	_OP_FSYNC       = opcode(20)
	_OP_SETXATTR    = opcode(21)
	_OP_GETXATTR    = opcode(22)
	_OP_LISTXATTR   = opcode(23)
	_OP_REMOVEXATTR = opcode(24)
	_OP_FLUSH       = opcode(25)
	_OP_INIT        = opcode(26)
	_OP_OPENDIR     = opcode(27)
	_OP_READDIR     = opcode(28)
	_OP_RELEASEDIR  = opcode(29)
	_OP_FSYNCDIR    = opcode(30)
	_OP_GETLK       = opcode(31)
	_OP_SETLK       = opcode(32)
	_OP_SETLKW      = opcode(33)
	_OP_ACCESS      = opcode(34)
	_OP_CREATE      = opcode(35)
	_OP_INTERRUPT   = opcode(36)
	_OP_BMAP        = opcode(37)
	_OP_DESTROY     = opcode(38)
	_OP_IOCTL       = opcode(39)
	_OP_POLL        = opcode(40)

55
	_OPCODE_COUNT = opcode(41)
56 57
)

58

59 60
////////////////////////////////////////////////////////////////

61
func doInit(state *MountState, req *request) {
Han-Wen Nienhuys's avatar
Polish.  
Han-Wen Nienhuys committed
62
	const (
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
63
		FUSE_KERNEL_VERSION       = 7
Han-Wen Nienhuys's avatar
Polish.  
Han-Wen Nienhuys committed
64 65
		FUSE_KERNEL_MINOR_VERSION = 13
	)
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
66

67 68
	input := (*InitIn)(req.inData)
	if input.Major != FUSE_KERNEL_VERSION {
69
		log.Printf("Major versions does not match. Given %d, want %d\n", input.Major, FUSE_KERNEL_VERSION)
70 71 72 73
		req.status = EIO
		return
	}
	if input.Minor < FUSE_KERNEL_MINOR_VERSION {
74
		log.Printf("Minor version is less than we support. Given %d, want at least %d\n", input.Minor, FUSE_KERNEL_MINOR_VERSION)
75 76 77 78
		req.status = EIO
		return
	}

79
	state.kernelSettings = *input
80
	state.kernelSettings.Flags = input.Flags & (CAP_ASYNC_READ | CAP_BIG_WRITES | CAP_FILE_OPS)
81
	out := &InitOut{
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
82 83 84
		Major:               FUSE_KERNEL_VERSION,
		Minor:               FUSE_KERNEL_MINOR_VERSION,
		MaxReadAhead:        input.MaxReadAhead,
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
85
		Flags:               state.kernelSettings.Flags,
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
86
		MaxWrite:            maxRead,
87 88
		CongestionThreshold: uint16(state.opts.MaxBackground * 3 / 4),
		MaxBackground:       uint16(state.opts.MaxBackground),
89 90 91 92 93 94
	}

	req.outData = unsafe.Pointer(out)
	req.status = OK
}

95 96 97 98 99 100 101 102 103 104 105 106
func doOpen(state *MountState, req *request) {
	flags, handle, status := state.fileSystem.Open(req.inHeader, (*OpenIn)(req.inData))
	req.status = status
	if status != OK {
		return
	}

	out := &OpenOut{
		Fh:        handle,
		OpenFlags: flags,
	}

107
	req.outData = unsafe.Pointer(out)
108 109 110
}

func doCreate(state *MountState, req *request) {
111
	flags, handle, entry, status := state.fileSystem.Create(req.inHeader, (*CreateIn)(req.inData), req.filenames[0])
112
	req.status = status
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
113
	if status.Ok() {
114
		req.outData = unsafe.Pointer(&CreateOut{
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
			EntryOut: *entry,
			OpenOut: OpenOut{
				Fh:        handle,
				OpenFlags: flags,
			},
		})
	}
}


func doReadDir(state *MountState, req *request) {
	entries, code := state.fileSystem.ReadDir(req.inHeader, (*ReadIn)(req.inData))
	if entries != nil {
		req.flatData = entries.Bytes()
	}
	req.status = code
}


func doOpenDir(state *MountState, req *request) {
	flags, handle, status := state.fileSystem.OpenDir(req.inHeader, (*OpenIn)(req.inData))
	req.status = status
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
137
	if status.Ok() {
138
		req.outData = unsafe.Pointer(&OpenOut{
139 140 141 142 143 144 145 146
			Fh:        handle,
			OpenFlags: flags,
		})
	}
}

func doSetattr(state *MountState, req *request) {
	o, s := state.fileSystem.SetAttr(req.inHeader, (*SetAttrIn)(req.inData))
147
	req.outData = unsafe.Pointer(o)
148 149 150 151 152 153 154 155
	req.status = s
}

func doWrite(state *MountState, req *request) {
	n, status := state.fileSystem.Write((*WriteIn)(req.inData), req.arg)
	o := &WriteOut{
		Size: n,
	}
156
	req.outData = unsafe.Pointer(o)
157 158 159 160 161 162 163
	req.status = status
}


func doGetXAttr(state *MountState, req *request) {
	input := (*GetXAttrIn)(req.inData)
	var data []byte
164
	if req.inHeader.opcode == _OP_GETXATTR {
165
		data, req.status = state.fileSystem.GetXAttr(req.inHeader, req.filenames[0])
166 167 168 169 170 171 172 173 174 175 176 177 178
	} else {
		data, req.status = state.fileSystem.ListXAttr(req.inHeader)
	}

	if req.status != OK {
		return
	}

	size := uint32(len(data))
	if input.Size == 0 {
		out := &GetXAttrOut{
			Size: size,
		}
179
		req.outData = unsafe.Pointer(out)
180 181 182 183 184 185 186 187 188 189 190 191
	}

	if size > input.Size {
		req.status = ERANGE
	}

	req.flatData = data
}

func doGetAttr(state *MountState, req *request) {
	attrOut, s := state.fileSystem.GetAttr(req.inHeader, (*GetAttrIn)(req.inData))
	req.status = s
192
	req.outData = unsafe.Pointer(attrOut)
193 194 195 196 197 198 199 200 201
}

func doForget(state *MountState, req *request) {
	state.fileSystem.Forget(req.inHeader, (*ForgetIn)(req.inData))
}

func doReadlink(state *MountState, req *request) {
	req.flatData, req.status = state.fileSystem.Readlink(req.inHeader)
}
202

203 204 205 206 207
func doDestroy(state *MountState, req *request) {
	state.fileSystem.Destroy(req.inHeader, (*InitIn)(req.inData))
}

func doLookup(state *MountState, req *request) {
208
	lookupOut, s := state.fileSystem.Lookup(req.inHeader, req.filenames[0])
209
	req.status = s
210
	req.outData = unsafe.Pointer(lookupOut)
211 212 213
}

func doMknod(state *MountState, req *request) {
214
	entryOut, s := state.fileSystem.Mknod(req.inHeader, (*MknodIn)(req.inData), req.filenames[0])
215
	req.status = s
216
	req.outData = unsafe.Pointer(entryOut)
217 218 219
}

func doMkdir(state *MountState, req *request) {
220
	entryOut, s := state.fileSystem.Mkdir(req.inHeader, (*MkdirIn)(req.inData), req.filenames[0])
221
	req.status = s
222
	req.outData = unsafe.Pointer(entryOut)
223 224 225
}

func doUnlink(state *MountState, req *request) {
226
	req.status = state.fileSystem.Unlink(req.inHeader, req.filenames[0])
227 228 229
}

func doRmdir(state *MountState, req *request) {
230
	req.status = state.fileSystem.Rmdir(req.inHeader, req.filenames[0])
231 232 233
}

func doLink(state *MountState, req *request) {
234
	entryOut, s := state.fileSystem.Link(req.inHeader, (*LinkIn)(req.inData), req.filenames[0])
235
	req.status = s
236
	req.outData = unsafe.Pointer(entryOut)
237
}
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
238

239 240 241
func doRead(state *MountState, req *request) {
	req.flatData, req.status = state.fileSystem.Read((*ReadIn)(req.inData), state.buffers)
}
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
242

243 244 245
func doFlush(state *MountState, req *request) {
	req.status = state.fileSystem.Flush((*FlushIn)(req.inData))
}
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
246

247 248 249
func doRelease(state *MountState, req *request) {
	state.fileSystem.Release(req.inHeader, (*ReleaseIn)(req.inData))
}
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
250

251 252 253
func doFsync(state *MountState, req *request) {
	req.status = state.fileSystem.Fsync((*FsyncIn)(req.inData))
}
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
254

255 256 257
func doReleaseDir(state *MountState, req *request) {
	state.fileSystem.ReleaseDir(req.inHeader, (*ReleaseIn)(req.inData))
}
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
258

259 260 261
func doFsyncDir(state *MountState, req *request) {
	req.status = state.fileSystem.FsyncDir(req.inHeader, (*FsyncIn)(req.inData))
}
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
262

263
func doSetXAttr(state *MountState, req *request) {
264
	splits := bytes.SplitN(req.arg, []byte{0}, 2)
265 266 267 268
	req.status = state.fileSystem.SetXAttr(req.inHeader, (*SetXAttrIn)(req.inData), string(splits[0]), splits[1])
}

func doRemoveXAttr(state *MountState, req *request) {
269
	req.status = state.fileSystem.RemoveXAttr(req.inHeader, req.filenames[0])
270 271 272 273 274 275 276
}

func doAccess(state *MountState, req *request) {
	req.status = state.fileSystem.Access(req.inHeader, (*AccessIn)(req.inData))
}

func doSymlink(state *MountState, req *request) {
277 278 279
	entryOut, s := state.fileSystem.Symlink(req.inHeader, req.filenames[1], req.filenames[0])
	req.status = s
	req.outData = unsafe.Pointer(entryOut)
280 281 282
}

func doRename(state *MountState, req *request) {
283
	req.status = state.fileSystem.Rename(req.inHeader, (*RenameIn)(req.inData), req.filenames[0], req.filenames[1])
284 285
}

Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
286 287 288 289 290 291 292
func doIoctl(state *MountState, req *request) {
	out, data, stat := state.fileSystem.Ioctl(req.inHeader, (*IoctlIn)(req.inData))
	req.outData = unsafe.Pointer(out)
	req.flatData = data
	req.status = stat
}

293 294
////////////////////////////////////////////////////////////////

295
type operationFunc func(*MountState, *request)
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
296
type castPointerFunc func(unsafe.Pointer) interface{}
297

298
type operationHandler struct {
299 300
	Name       string
	Func       operationFunc
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
301 302
	InputSize  uintptr
	OutputSize uintptr
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
303 304
	DecodeIn   castPointerFunc
	DecodeOut  castPointerFunc
305
	FileNames  int
306
}
307

308
var operationHandlers []*operationHandler
309

Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
310 311
func operationName(op opcode) string {
	h := getHandler(op)
312
	if h == nil {
313 314
		return "unknown"
	}
315
	return h.Name
316 317
}

Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
318
func (op opcode) String() string {
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
319 320 321
	return operationName(op)
}

Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
322
func getHandler(o opcode) *operationHandler {
323
	if o >= _OPCODE_COUNT {
324
		return nil
325
	}
326
	return operationHandlers[o]
327
}
328 329

func init() {
330
	operationHandlers = make([]*operationHandler, _OPCODE_COUNT)
331 332 333
	for i, _ := range operationHandlers {
		operationHandlers[i] = &operationHandler{Name: "UNKNOWN"}
	}
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
334

Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
335
	for op, sz := range map[opcode]uintptr{
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
		_OP_FORGET:     unsafe.Sizeof(ForgetIn{}),
		_OP_GETATTR:    unsafe.Sizeof(GetAttrIn{}),
		_OP_SETATTR:    unsafe.Sizeof(SetAttrIn{}),
		_OP_MKNOD:      unsafe.Sizeof(MknodIn{}),
		_OP_MKDIR:      unsafe.Sizeof(MkdirIn{}),
		_OP_RENAME:     unsafe.Sizeof(RenameIn{}),
		_OP_LINK:       unsafe.Sizeof(LinkIn{}),
		_OP_OPEN:       unsafe.Sizeof(OpenIn{}),
		_OP_READ:       unsafe.Sizeof(ReadIn{}),
		_OP_WRITE:      unsafe.Sizeof(WriteIn{}),
		_OP_RELEASE:    unsafe.Sizeof(ReleaseIn{}),
		_OP_FSYNC:      unsafe.Sizeof(FsyncIn{}),
		_OP_SETXATTR:   unsafe.Sizeof(SetXAttrIn{}),
		_OP_GETXATTR:   unsafe.Sizeof(GetXAttrIn{}),
		_OP_LISTXATTR:  unsafe.Sizeof(GetXAttrIn{}),
		_OP_FLUSH:      unsafe.Sizeof(FlushIn{}),
		_OP_INIT:       unsafe.Sizeof(InitIn{}),
		_OP_OPENDIR:    unsafe.Sizeof(OpenIn{}),
		_OP_READDIR:    unsafe.Sizeof(ReadIn{}),
		_OP_RELEASEDIR: unsafe.Sizeof(ReleaseIn{}),
		_OP_FSYNCDIR:   unsafe.Sizeof(FsyncIn{}),
		_OP_ACCESS:     unsafe.Sizeof(AccessIn{}),
		_OP_CREATE:     unsafe.Sizeof(CreateIn{}),
		_OP_INTERRUPT:  unsafe.Sizeof(InterruptIn{}),
		_OP_BMAP:       unsafe.Sizeof(BmapIn{}),
		_OP_IOCTL:      unsafe.Sizeof(IoctlIn{}),
		_OP_POLL:       unsafe.Sizeof(PollIn{}),
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
363
	} {
364 365
		operationHandlers[op].InputSize = sz
	}
366

Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
367
	for op, sz := range map[opcode]uintptr{
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
		_OP_LOOKUP:    unsafe.Sizeof(EntryOut{}),
		_OP_GETATTR:   unsafe.Sizeof(AttrOut{}),
		_OP_SETATTR:   unsafe.Sizeof(AttrOut{}),
		_OP_SYMLINK:   unsafe.Sizeof(EntryOut{}),
		_OP_MKNOD:     unsafe.Sizeof(EntryOut{}),
		_OP_MKDIR:     unsafe.Sizeof(EntryOut{}),
		_OP_LINK:      unsafe.Sizeof(EntryOut{}),
		_OP_OPEN:      unsafe.Sizeof(OpenOut{}),
		_OP_WRITE:     unsafe.Sizeof(WriteOut{}),
		_OP_STATFS:    unsafe.Sizeof(StatfsOut{}),
		_OP_GETXATTR:  unsafe.Sizeof(GetXAttrOut{}),
		_OP_LISTXATTR: unsafe.Sizeof(GetXAttrOut{}),
		_OP_INIT:      unsafe.Sizeof(InitOut{}),
		_OP_OPENDIR:   unsafe.Sizeof(OpenOut{}),
		_OP_CREATE:    unsafe.Sizeof(CreateOut{}),
		_OP_BMAP:      unsafe.Sizeof(BmapOut{}),
		_OP_IOCTL:     unsafe.Sizeof(IoctlOut{}),
		_OP_POLL:      unsafe.Sizeof(PollOut{}),
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
386
	} {
387 388
		operationHandlers[op].OutputSize = sz
	}
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
389

390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
	for op, v := range map[opcode]string{
		_OP_LOOKUP:      "LOOKUP",
		_OP_FORGET:      "FORGET",
		_OP_GETATTR:     "GETATTR",
		_OP_SETATTR:     "SETATTR",
		_OP_READLINK:    "READLINK",
		_OP_SYMLINK:     "SYMLINK",
		_OP_MKNOD:       "MKNOD",
		_OP_MKDIR:       "MKDIR",
		_OP_UNLINK:      "UNLINK",
		_OP_RMDIR:       "RMDIR",
		_OP_RENAME:      "RENAME",
		_OP_LINK:        "LINK",
		_OP_OPEN:        "OPEN",
		_OP_READ:        "READ",
		_OP_WRITE:       "WRITE",
		_OP_STATFS:      "STATFS",
		_OP_RELEASE:     "RELEASE",
		_OP_FSYNC:       "FSYNC",
		_OP_SETXATTR:    "SETXATTR",
		_OP_GETXATTR:    "GETXATTR",
		_OP_LISTXATTR:   "LISTXATTR",
		_OP_REMOVEXATTR: "REMOVEXATTR",
		_OP_FLUSH:       "FLUSH",
		_OP_INIT:        "INIT",
		_OP_OPENDIR:     "OPENDIR",
		_OP_READDIR:     "READDIR",
		_OP_RELEASEDIR:  "RELEASEDIR",
		_OP_FSYNCDIR:    "FSYNCDIR",
		_OP_GETLK:       "GETLK",
		_OP_SETLK:       "SETLK",
		_OP_SETLKW:      "SETLKW",
		_OP_ACCESS:      "ACCESS",
		_OP_CREATE:      "CREATE",
		_OP_INTERRUPT:   "INTERRUPT",
		_OP_BMAP:        "BMAP",
		_OP_DESTROY:     "DESTROY",
		_OP_IOCTL:       "IOCTL",
		_OP_POLL:        "POLL"} {
429
		operationHandlers[op].Name = v
430 431
	}

Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
432
	for op, v := range map[opcode]operationFunc{
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
		_OP_OPEN:        doOpen,
		_OP_READDIR:     doReadDir,
		_OP_WRITE:       doWrite,
		_OP_OPENDIR:     doOpenDir,
		_OP_CREATE:      doCreate,
		_OP_SETATTR:     doSetattr,
		_OP_GETXATTR:    doGetXAttr,
		_OP_LISTXATTR:   doGetXAttr,
		_OP_GETATTR:     doGetAttr,
		_OP_FORGET:      doForget,
		_OP_READLINK:    doReadlink,
		_OP_INIT:        doInit,
		_OP_DESTROY:     doDestroy,
		_OP_LOOKUP:      doLookup,
		_OP_MKNOD:       doMknod,
		_OP_MKDIR:       doMkdir,
		_OP_UNLINK:      doUnlink,
		_OP_RMDIR:       doRmdir,
		_OP_LINK:        doLink,
		_OP_READ:        doRead,
		_OP_FLUSH:       doFlush,
		_OP_RELEASE:     doRelease,
		_OP_FSYNC:       doFsync,
		_OP_RELEASEDIR:  doReleaseDir,
		_OP_FSYNCDIR:    doFsyncDir,
		_OP_SETXATTR:    doSetXAttr,
		_OP_REMOVEXATTR: doRemoveXAttr,
		_OP_ACCESS:      doAccess,
		_OP_SYMLINK:     doSymlink,
		_OP_RENAME:      doRename,
463
	} {
464
		operationHandlers[op].Func = v
465
	}
466

467
	// Outputs.
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
468
	for op, f := range map[opcode]castPointerFunc{
469
		_OP_LOOKUP:  func(ptr unsafe.Pointer) interface{} { return (*EntryOut)(ptr) },
470
		_OP_OPEN:    func(ptr unsafe.Pointer) interface{} { return (*OpenOut)(ptr) },
471
		_OP_GETATTR: func(ptr unsafe.Pointer) interface{} { return (*AttrOut)(ptr) },
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
472
		_OP_CREATE:  func(ptr unsafe.Pointer) interface{} { return (*CreateOut)(ptr) },
473
		_OP_SETATTR: func(ptr unsafe.Pointer) interface{} { return (*AttrOut)(ptr) },
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
474
		_OP_INIT:    func(ptr unsafe.Pointer) interface{} { return (*InitOut)(ptr) },
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
475
		_OP_MKDIR:   func(ptr unsafe.Pointer) interface{} { return (*EntryOut)(ptr) },
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
476 477
	} {
		operationHandlers[op].DecodeOut = f
478
	}
479 480

	// Inputs.
481 482 483
	for op, f := range map[opcode]castPointerFunc{
		_OP_GETATTR: func(ptr unsafe.Pointer) interface{} { return (*GetAttrIn)(ptr) },
		_OP_SETATTR: func(ptr unsafe.Pointer) interface{} { return (*SetAttrIn)(ptr) },
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
484
		_OP_INIT:    func(ptr unsafe.Pointer) interface{} { return (*InitIn)(ptr) },
485
		_OP_IOCTL:   func(ptr unsafe.Pointer) interface{} { return (*IoctlIn)(ptr) },
486 487
		_OP_OPEN:    func(ptr unsafe.Pointer) interface{} { return (*OpenIn)(ptr) },
		_OP_CREATE:  func(ptr unsafe.Pointer) interface{} { return (*CreateIn)(ptr) },
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
488
		_OP_READ:    func(ptr unsafe.Pointer) interface{} { return (*ReadIn)(ptr) },
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
489
		_OP_ACCESS:  func(ptr unsafe.Pointer) interface{} { return (*AccessIn)(ptr) },
490 491 492
	} {
		operationHandlers[op].DecodeIn = f
	}
493 494

	// File name args.
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
495
	for op, count := range map[opcode]int{
496 497 498
		_OP_CREATE:      1,
		_OP_GETXATTR:    1,
		_OP_LINK:        1,
499
		_OP_LOOKUP:      1,
500 501 502
		_OP_MKDIR:       1,
		_OP_MKNOD:       1,
		_OP_REMOVEXATTR: 1,
503
		_OP_RENAME:      2,
504
		_OP_RMDIR:       1,
505 506
		_OP_SYMLINK:     2,
		_OP_UNLINK:      1,
507 508 509
	} {
		operationHandlers[op].FileNames = count
	}
510
}