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  }