github.com/pbberlin/tools@v0.0.0-20160910141205-7aa5421c2169/os/fsi/dsfs/40_file_impl.go (about) 1 package dsfs 2 3 import ( 4 "io" 5 "os" 6 "sync/atomic" 7 "time" 8 9 "github.com/pbberlin/tools/os/fsi" 10 ) 11 12 func (f *DsFile) Close() error { 13 14 atomic.StoreInt64(&f.at, 0) 15 f.Lock() 16 f.closed = true 17 18 err := f.Sync() 19 if err != nil { 20 return err 21 } 22 23 f.Unlock() 24 25 return nil 26 } 27 28 // See fsi.File interface. 29 // Adapt (f *AeDir) Readdir also 30 func (f *DsFile) Readdir(n int) (fis []os.FileInfo, err error) { 31 32 fis, err = f.fSys.ReadDir(f.Dir) 33 34 wantAll := n <= 0 35 36 if wantAll { 37 return fis, nil 38 } 39 40 // Actually we would need memDirFetchPos 41 // holding the latest retrieved file in 42 // a forwardly-linked-list mimic. 43 // Compare https://golang.org/src/os/file_windows.go 44 // Instead: We either or return *all* available files 45 // or empty slice plus io.EOF 46 if f.memDirFetchPos == 0 { 47 f.memDirFetchPos = len(fis) 48 return fis, nil 49 } else { 50 f.memDirFetchPos = 0 51 return []os.FileInfo{}, io.EOF 52 } 53 54 } 55 56 // See fsi.File interface. 57 func (f *DsFile) Readdirnames(n int) (names []string, err error) { 58 fis, err := f.Readdir(n) 59 names = make([]string, 0, len(fis)) 60 for _, lp := range fis { 61 names = append(names, lp.Name()) 62 } 63 return names, err 64 } 65 66 func (f *DsFile) Read(b []byte) (n int, err error) { 67 f.Lock() 68 defer f.Unlock() 69 if f.closed == true { 70 return 0, fsi.ErrFileClosed 71 } 72 if len(b) > 0 && int(f.at) == len(f.Data) { 73 return 0, io.EOF 74 } 75 if len(f.Data)-int(f.at) >= len(b) { 76 n = len(b) 77 } else { 78 n = len(f.Data) - int(f.at) 79 } 80 copy(b, f.Data[f.at:f.at+int64(n)]) 81 atomic.AddInt64(&f.at, int64(n)) 82 return 83 } 84 85 func (f *DsFile) ReadAt(b []byte, off int64) (n int, err error) { 86 atomic.StoreInt64(&f.at, off) 87 return f.Read(b) 88 } 89 90 func (f *DsFile) Seek(offset int64, whence int) (int64, error) { 91 if f.closed == true { 92 return 0, fsi.ErrFileClosed 93 } 94 switch whence { 95 case 0: 96 atomic.StoreInt64(&f.at, offset) 97 case 1: 98 atomic.AddInt64(&f.at, int64(offset)) 99 case 2: 100 atomic.StoreInt64(&f.at, int64(len(f.Data))+offset) 101 } 102 return f.at, nil 103 } 104 105 func (f *DsFile) Stat() (os.FileInfo, error) { 106 return os.FileInfo(*f), nil 107 } 108 109 func (f *DsFile) Sync() error { 110 err := f.fSys.saveFileByPath(f, f.Dir+f.BName) 111 if err != nil { 112 return err 113 } 114 return nil 115 } 116 117 func (f *DsFile) Truncate(size int64) error { 118 if f.closed == true { 119 return fsi.ErrFileClosed 120 } 121 if size < 0 { 122 return fsi.ErrOutOfRange 123 } 124 if size > int64(len(f.Data)) { 125 diff := size - int64(len(f.Data)) 126 // f.Content = append(f.Content, bytes.Repeat([]byte{00}, int(diff))...) 127 sb := make([]byte, int(diff)) 128 f.Data = append(f.Data, sb...) 129 } else { 130 f.Data = f.Data[0:size] 131 } 132 f.MModTime = time.Now() 133 return nil 134 } 135 136 func (f *DsFile) Write(b []byte) (n int, err error) { 137 n = len(b) 138 cur := atomic.LoadInt64(&f.at) 139 f.Lock() 140 defer f.Unlock() 141 diff := cur - int64(len(f.Data)) 142 var tail []byte 143 if n+int(cur) < len(f.Data) { 144 tail = f.Data[n+int(cur):] 145 } 146 if diff > 0 { 147 sb := make([]byte, int(diff)) 148 f.Data = append(sb, b...) 149 // f.Content = append(bytes.Repeat([]byte{00}, int(diff)), b...) 150 f.Data = append(f.Data, tail...) 151 } else { 152 f.Data = append(f.Data[:cur], b...) 153 f.Data = append(f.Data, tail...) 154 } 155 atomic.StoreInt64(&f.at, int64(len(f.Data))) 156 f.MModTime = time.Now() 157 return 158 } 159 160 func (f *DsFile) WriteAt(b []byte, off int64) (n int, err error) { 161 atomic.StoreInt64(&f.at, off) 162 return f.Write(b) 163 } 164 165 func (f *DsFile) WriteString(s string) (ret int, err error) { 166 return f.Write([]byte(s)) 167 }