Skip to content

Commit 6196a5b

Browse files
committed
v2api: File2: implement Release, Read, Write, Fsync, Flush, Allocate
Fortunately, this just means fixing up the function signatures.
1 parent d539a4c commit 6196a5b

File tree

5 files changed

+89
-87
lines changed

5 files changed

+89
-87
lines changed

internal/fusefrontend/file2.go

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/rfjakob/gocryptfs/internal/tlog"
2626
)
2727

28+
// File2 implements the go-fuse v2 API (github.com/hanwen/go-fuse/v2/fs)
2829
type File2 struct {
2930
fd *os.File
3031
// Has Release() already been called on this file? This also means that the
@@ -129,7 +130,7 @@ func (f *File2) createHeader() (fileID []byte, err error) {
129130
//
130131
// Called by Read() for normal reading,
131132
// by Write() and Truncate() via doWrite() for Read-Modify-Write.
132-
func (f *File2) doRead(dst []byte, off uint64, length uint64) ([]byte, fuse.Status) {
133+
func (f *File2) doRead(dst []byte, off uint64, length uint64) ([]byte, syscall.Errno) {
133134
// Get the file ID, either from the open file table, or from disk.
134135
var fileID []byte
135136
f.fileTableEntry.IDLock.Lock()
@@ -144,15 +145,15 @@ func (f *File2) doRead(dst []byte, off uint64, length uint64) ([]byte, fuse.Stat
144145
f.fileTableEntry.IDLock.Unlock()
145146
if err == io.EOF {
146147
// Empty file
147-
return nil, fuse.OK
148+
return nil, 0
148149
}
149150
buf := make([]byte, 100)
150151
n, _ := f.fd.ReadAt(buf, 0)
151152
buf = buf[:n]
152153
hexdump := hex.EncodeToString(buf)
153154
tlog.Warn.Printf("doRead %d: corrupt header: %v\nFile hexdump (%d bytes): %s",
154155
f.qIno.Ino, err, n, hexdump)
155-
return nil, fuse.EIO
156+
return nil, syscall.EIO
156157
}
157158
// Save into the file table
158159
f.fileTableEntry.ID = fileID
@@ -173,12 +174,12 @@ func (f *File2) doRead(dst []byte, off uint64, length uint64) ([]byte, fuse.Stat
173174
n, err := f.fd.ReadAt(ciphertext, int64(alignedOffset))
174175
if err != nil && err != io.EOF {
175176
tlog.Warn.Printf("read: ReadAt: %s", err.Error())
176-
return nil, fuse.ToStatus(err)
177+
return nil, fs.ToErrno(err)
177178
}
178179
// The ReadAt came back empty. We can skip all the decryption and return early.
179180
if n == 0 {
180181
f.rootNode.contentEnc.CReqPool.Put(ciphertext)
181-
return dst, fuse.OK
182+
return dst, 0
182183
}
183184
// Truncate ciphertext buffer down to actually read bytes
184185
ciphertext = ciphertext[0:n]
@@ -198,7 +199,7 @@ func (f *File2) doRead(dst []byte, off uint64, length uint64) ([]byte, fuse.Stat
198199
} else {
199200
curruptBlockNo := firstBlockNo + f.contentEnc.PlainOffToBlockNo(uint64(len(plaintext)))
200201
tlog.Warn.Printf("doRead %d: corrupt block #%d: %v", f.qIno.Ino, curruptBlockNo, err)
201-
return nil, fuse.EIO
202+
return nil, syscall.EIO
202203
}
203204
}
204205

@@ -216,15 +217,15 @@ func (f *File2) doRead(dst []byte, off uint64, length uint64) ([]byte, fuse.Stat
216217
out = append(dst, out...)
217218
f.rootNode.contentEnc.PReqPool.Put(plaintext)
218219

219-
return out, fuse.OK
220+
return out, 0
220221
}
221222

222223
// Read - FUSE call
223-
func (f *File2) Read(buf []byte, off int64) (resultData fuse.ReadResult, code fuse.Status) {
224+
func (f *File2) Read(ctx context.Context, buf []byte, off int64) (resultData fuse.ReadResult, errno syscall.Errno) {
224225
if len(buf) > fuse.MAX_KERNEL_WRITE {
225226
// This would crash us due to our fixed-size buffer pool
226227
tlog.Warn.Printf("Read: rejecting oversized request with EMSGSIZE, len=%d", len(buf))
227-
return nil, fuse.Status(syscall.EMSGSIZE)
228+
return nil, syscall.EMSGSIZE
228229
}
229230
f.fdLock.RLock()
230231
defer f.fdLock.RUnlock()
@@ -236,15 +237,15 @@ func (f *File2) Read(buf []byte, off int64) (resultData fuse.ReadResult, code fu
236237
if f.rootNode.args.SerializeReads {
237238
serialize_reads.Wait(off, len(buf))
238239
}
239-
out, status := f.doRead(buf[:0], uint64(off), uint64(len(buf)))
240+
out, errno := f.doRead(buf[:0], uint64(off), uint64(len(buf)))
240241
if f.rootNode.args.SerializeReads {
241242
serialize_reads.Done()
242243
}
243-
if status != fuse.OK {
244-
return nil, status
244+
if errno != 0 {
245+
return nil, errno
245246
}
246-
tlog.Debug.Printf("ino%d: Read: status %v, returning %d bytes", f.qIno.Ino, status, len(out))
247-
return fuse.ReadResultData(out), status
247+
tlog.Debug.Printf("ino%d: Read: errno=%d, returning %d bytes", f.qIno.Ino, errno, len(out))
248+
return fuse.ReadResultData(out), errno
248249
}
249250

250251
// doWrite - encrypt "data" and write it to plaintext offset "off"
@@ -256,7 +257,7 @@ func (f *File2) Read(buf []byte, off int64) (resultData fuse.ReadResult, code fu
256257
// and by Truncate() to rewrite the last file block.
257258
//
258259
// Empty writes do nothing and are allowed.
259-
func (f *File2) doWrite(data []byte, off int64) (uint32, fuse.Status) {
260+
func (f *File2) doWrite(data []byte, off int64) (uint32, syscall.Errno) {
260261
fileWasEmpty := false
261262
// Get the file ID, create a new one if it does not exist yet.
262263
var fileID []byte
@@ -274,7 +275,7 @@ func (f *File2) doWrite(data []byte, off int64) (uint32, fuse.Status) {
274275
fileWasEmpty = true
275276
}
276277
if err != nil {
277-
return 0, fuse.ToStatus(err)
278+
return 0, fs.ToErrno(err)
278279
}
279280
f.fileTableEntry.ID = fileID
280281
}
@@ -287,10 +288,10 @@ func (f *File2) doWrite(data []byte, off int64) (uint32, fuse.Status) {
287288
// Incomplete block -> Read-Modify-Write
288289
if b.IsPartial() {
289290
// Read
290-
oldData, status := f.doRead(nil, b.BlockPlainOff(), f.contentEnc.PlainBS())
291-
if status != fuse.OK {
292-
tlog.Warn.Printf("ino%d fh%d: RMW read failed: %s", f.qIno.Ino, f.intFd(), status.String())
293-
return 0, status
291+
oldData, errno := f.doRead(nil, b.BlockPlainOff(), f.contentEnc.PlainBS())
292+
if errno != 0 {
293+
tlog.Warn.Printf("ino%d fh%d: RMW read failed: errno=%d", f.qIno.Ino, f.intFd(), errno)
294+
return 0, errno
294295
}
295296
// Modify
296297
blockData = f.contentEnc.MergeBlocks(oldData, blockData, int(b.Skip))
@@ -321,7 +322,7 @@ func (f *File2) doWrite(data []byte, off int64) (uint32, fuse.Status) {
321322
tlog.Warn.Printf("ino%d fh%d: doWrite: rollback failed: %v", f.qIno.Ino, f.intFd(), err2)
322323
}
323324
}
324-
return 0, fuse.ToStatus(err)
325+
return 0, fs.ToErrno(err)
325326
}
326327
}
327328
// Write
@@ -331,9 +332,9 @@ func (f *File2) doWrite(data []byte, off int64) (uint32, fuse.Status) {
331332
if err != nil {
332333
tlog.Warn.Printf("ino%d fh%d: doWrite: WriteAt off=%d len=%d failed: %v",
333334
f.qIno.Ino, f.intFd(), cOff, len(ciphertext), err)
334-
return 0, fuse.ToStatus(err)
335+
return 0, fs.ToErrno(err)
335336
}
336-
return uint32(len(data)), fuse.OK
337+
return uint32(len(data)), 0
337338
}
338339

339340
// isConsecutiveWrite returns true if the current write
@@ -349,18 +350,18 @@ func (f *File2) isConsecutiveWrite(off int64) bool {
349350
// Write - FUSE call
350351
//
351352
// If the write creates a hole, pads the file to the next block boundary.
352-
func (f *File2) Write(data []byte, off int64) (uint32, fuse.Status) {
353+
func (f *File2) Write(ctx context.Context, data []byte, off int64) (uint32, syscall.Errno) {
353354
if len(data) > fuse.MAX_KERNEL_WRITE {
354355
// This would crash us due to our fixed-size buffer pool
355356
tlog.Warn.Printf("Write: rejecting oversized request with EMSGSIZE, len=%d", len(data))
356-
return 0, fuse.Status(syscall.EMSGSIZE)
357+
return 0, syscall.EMSGSIZE
357358
}
358359
f.fdLock.RLock()
359360
defer f.fdLock.RUnlock()
360361
if f.released {
361362
// The file descriptor has been closed concurrently
362363
tlog.Warn.Printf("ino%d fh%d: Write on released file", f.qIno.Ino, f.intFd())
363-
return 0, fuse.EBADF
364+
return 0, syscall.EBADF
364365
}
365366
f.fileTableEntry.ContentLock.Lock()
366367
defer f.fileTableEntry.ContentLock.Unlock()
@@ -369,21 +370,21 @@ func (f *File2) Write(data []byte, off int64) (uint32, fuse.Status) {
369370
// But if the write directly follows an earlier write, it cannot create a
370371
// hole, and we can save one Stat() call.
371372
if !f.isConsecutiveWrite(off) {
372-
status := f.writePadHole(off)
373-
if !status.Ok() {
374-
return 0, status
373+
errno := f.writePadHole(off)
374+
if errno != 0 {
375+
return 0, errno
375376
}
376377
}
377-
n, status := f.doWrite(data, off)
378-
if status.Ok() {
378+
n, errno := f.doWrite(data, off)
379+
if errno != 0 {
379380
f.lastOpCount = openfiletable.WriteOpCount()
380381
f.lastWrittenOffset = off + int64(len(data)) - 1
381382
}
382-
return n, status
383+
return n, errno
383384
}
384385

385386
// Release - FUSE call, close file
386-
func (f *File2) Release() {
387+
func (f *File2) Release(ctx context.Context) syscall.Errno {
387388
f.fdLock.Lock()
388389
if f.released {
389390
log.Panicf("ino%d fh%d: double release", f.qIno.Ino, f.intFd())
@@ -392,10 +393,11 @@ func (f *File2) Release() {
392393
openfiletable.Unregister(f.qIno)
393394
f.fd.Close()
394395
f.fdLock.Unlock()
396+
return 0
395397
}
396398

397399
// Flush - FUSE call
398-
func (f *File2) Flush() fuse.Status {
400+
func (f *File2) Flush(ctx context.Context) syscall.Errno {
399401
f.fdLock.RLock()
400402
defer f.fdLock.RUnlock()
401403

@@ -405,18 +407,18 @@ func (f *File2) Flush() fuse.Status {
405407
newFd, err := syscall.Dup(f.intFd())
406408

407409
if err != nil {
408-
return fuse.ToStatus(err)
410+
return fs.ToErrno(err)
409411
}
410412
err = syscall.Close(newFd)
411-
return fuse.ToStatus(err)
413+
return fs.ToErrno(err)
412414
}
413415

414416
// Fsync FUSE call
415-
func (f *File2) Fsync(flags int) (code fuse.Status) {
417+
func (f *File2) Fsync(ctx context.Context, flags uint32) (errno syscall.Errno) {
416418
f.fdLock.RLock()
417419
defer f.fdLock.RUnlock()
418420

419-
return fuse.ToStatus(syscall.Fsync(f.intFd()))
421+
return fs.ToErrno(syscall.Fsync(f.intFd()))
420422
}
421423

422424
// Getattr FUSE call (like stat)

0 commit comments

Comments
 (0)