github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/libfs/wrapped_read_file.go (about) 1 // Copyright 2019 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 package libfs 6 7 import ( 8 "context" 9 "io" 10 "time" 11 12 "github.com/keybase/client/go/kbfs/libkbfs" 13 "github.com/keybase/client/go/logger" 14 "github.com/pkg/errors" 15 billy "gopkg.in/src-d/go-billy.v4" 16 ) 17 18 const ( 19 // Debug tag ID for an individual FS operation. 20 ctxFSOpID = "FSID" 21 ) 22 23 type ctxFSTagKey int 24 25 const ( 26 ctxFSIDKey ctxFSTagKey = iota 27 ) 28 29 // wrappedReadFile is a read-only file that serves data from a given 30 // `reader` function. 31 type wrappedReadFile struct { 32 name string 33 reader func(context.Context) ([]byte, time.Time, error) 34 log logger.Logger 35 36 // TODO: proper locking for `nextRead` if we ever use it outside 37 // of libkbfs node-wrapping (which always uses `ReadAt`). 38 nextRead int 39 } 40 41 var _ billy.File = (*wrappedReadFile)(nil) 42 43 func (wrf *wrappedReadFile) getDataAndTime() ([]byte, time.Time) { 44 ctx := libkbfs.CtxWithRandomIDReplayable( 45 context.Background(), ctxFSIDKey, ctxFSOpID, nil) 46 data, t, err := wrf.reader(ctx) 47 if err != nil { 48 wrf.log.CDebugf(ctx, "Couldn't read wrapped file: %+v", err) 49 return nil, time.Time{} 50 } 51 return data, t 52 } 53 54 func (wrf *wrappedReadFile) Len() int { 55 data, _ := wrf.getDataAndTime() 56 return len(data) 57 } 58 59 func (wrf *wrappedReadFile) Name() string { 60 return wrf.name 61 } 62 63 func (wrf *wrappedReadFile) Write(_ []byte) (n int, err error) { 64 return 0, errors.New("wrapped read files can't be written") 65 } 66 67 func (wrf *wrappedReadFile) Read(p []byte) (n int, err error) { 68 data, _ := wrf.getDataAndTime() 69 70 if wrf.nextRead >= len(data) { 71 return 0, io.EOF 72 } 73 n = copy(p, data[wrf.nextRead:]) 74 wrf.nextRead += n 75 return n, nil 76 } 77 78 func (wrf *wrappedReadFile) ReadAt(p []byte, off int64) (n int, err error) { 79 data, _ := wrf.getDataAndTime() 80 81 if off >= int64(len(data)) { 82 return 0, io.EOF 83 } 84 85 n = copy(p, data[off:]) 86 return n, nil 87 } 88 89 func (wrf *wrappedReadFile) Seek(offset int64, whence int) (int64, error) { 90 newOffset := offset 91 switch whence { 92 case io.SeekStart: 93 case io.SeekCurrent: 94 newOffset = int64(wrf.nextRead) + offset 95 case io.SeekEnd: 96 data, _ := wrf.getDataAndTime() 97 newOffset = int64(len(data)) + offset 98 } 99 if newOffset < 0 { 100 return 0, errors.Errorf("Cannot seek to offset %d", newOffset) 101 } 102 103 wrf.nextRead = int(newOffset) 104 return newOffset, nil 105 } 106 107 func (wrf *wrappedReadFile) Close() error { 108 return nil 109 } 110 111 func (wrf *wrappedReadFile) Lock() error { 112 return errors.New("wrapped read files can't be locked") 113 } 114 115 func (wrf *wrappedReadFile) Unlock() error { 116 return errors.New("wrapped read files can't be unlocked") 117 } 118 119 func (wrf *wrappedReadFile) Truncate(size int64) error { 120 return errors.New("wrapped read files can't be truncated") 121 } 122 123 func (wrf *wrappedReadFile) GetInfo() *wrappedReadFileInfo { 124 data, t := wrf.getDataAndTime() 125 return &wrappedReadFileInfo{ 126 name: wrf.Name(), 127 size: int64(len(data)), 128 mtime: t, 129 } 130 }