vendor/github.com/spf13/afero/mem/file.go
changeset 256 6d9efbef00a9
parent 242 2a9ec03fe5a1
child 260 445e01aede7e
equal deleted inserted replaced
255:4f153a23adab 256:6d9efbef00a9
    20 	"io"
    20 	"io"
    21 	"os"
    21 	"os"
    22 	"path/filepath"
    22 	"path/filepath"
    23 	"sync"
    23 	"sync"
    24 	"sync/atomic"
    24 	"sync/atomic"
       
    25 	"time"
    25 )
    26 )
    26 
       
    27 import "time"
       
    28 
    27 
    29 const FilePathSeparator = string(filepath.Separator)
    28 const FilePathSeparator = string(filepath.Separator)
    30 
    29 
    31 type File struct {
    30 type File struct {
    32 	// atomic requires 64-bit alignment for struct field access
    31 	// atomic requires 64-bit alignment for struct field access
    55 	data    []byte
    54 	data    []byte
    56 	memDir  Dir
    55 	memDir  Dir
    57 	dir     bool
    56 	dir     bool
    58 	mode    os.FileMode
    57 	mode    os.FileMode
    59 	modtime time.Time
    58 	modtime time.Time
       
    59 	uid     int
       
    60 	gid     int
    60 }
    61 }
    61 
    62 
    62 func (d *FileData) Name() string {
    63 func (d *FileData) Name() string {
    63 	d.Lock()
    64 	d.Lock()
    64 	defer d.Unlock()
    65 	defer d.Unlock()
    91 	f.Unlock()
    92 	f.Unlock()
    92 }
    93 }
    93 
    94 
    94 func setModTime(f *FileData, mtime time.Time) {
    95 func setModTime(f *FileData, mtime time.Time) {
    95 	f.modtime = mtime
    96 	f.modtime = mtime
       
    97 }
       
    98 
       
    99 func SetUID(f *FileData, uid int) {
       
   100 	f.Lock()
       
   101 	f.uid = uid
       
   102 	f.Unlock()
       
   103 }
       
   104 
       
   105 func SetGID(f *FileData, gid int) {
       
   106 	f.Lock()
       
   107 	f.gid = gid
       
   108 	f.Unlock()
    96 }
   109 }
    97 
   110 
    98 func GetFileInfo(f *FileData) *FileInfo {
   111 func GetFileInfo(f *FileData) *FileInfo {
    99 	return &FileInfo{f}
   112 	return &FileInfo{f}
   100 }
   113 }
   191 	atomic.AddInt64(&f.at, int64(n))
   204 	atomic.AddInt64(&f.at, int64(n))
   192 	return
   205 	return
   193 }
   206 }
   194 
   207 
   195 func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
   208 func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
       
   209 	prev := atomic.LoadInt64(&f.at)
   196 	atomic.StoreInt64(&f.at, off)
   210 	atomic.StoreInt64(&f.at, off)
   197 	return f.Read(b)
   211 	n, err = f.Read(b)
       
   212 	atomic.StoreInt64(&f.at, prev)
       
   213 	return
   198 }
   214 }
   199 
   215 
   200 func (f *File) Truncate(size int64) error {
   216 func (f *File) Truncate(size int64) error {
   201 	if f.closed == true {
   217 	if f.closed == true {
   202 		return ErrFileClosed
   218 		return ErrFileClosed
   205 		return &os.PathError{Op: "truncate", Path: f.fileData.name, Err: errors.New("file handle is read only")}
   221 		return &os.PathError{Op: "truncate", Path: f.fileData.name, Err: errors.New("file handle is read only")}
   206 	}
   222 	}
   207 	if size < 0 {
   223 	if size < 0 {
   208 		return ErrOutOfRange
   224 		return ErrOutOfRange
   209 	}
   225 	}
       
   226 	f.fileData.Lock()
       
   227 	defer f.fileData.Unlock()
   210 	if size > int64(len(f.fileData.data)) {
   228 	if size > int64(len(f.fileData.data)) {
   211 		diff := size - int64(len(f.fileData.data))
   229 		diff := size - int64(len(f.fileData.data))
   212 		f.fileData.data = append(f.fileData.data, bytes.Repeat([]byte{00}, int(diff))...)
   230 		f.fileData.data = append(f.fileData.data, bytes.Repeat([]byte{00}, int(diff))...)
   213 	} else {
   231 	} else {
   214 		f.fileData.data = f.fileData.data[0:size]
   232 		f.fileData.data = f.fileData.data[0:size]
   220 func (f *File) Seek(offset int64, whence int) (int64, error) {
   238 func (f *File) Seek(offset int64, whence int) (int64, error) {
   221 	if f.closed == true {
   239 	if f.closed == true {
   222 		return 0, ErrFileClosed
   240 		return 0, ErrFileClosed
   223 	}
   241 	}
   224 	switch whence {
   242 	switch whence {
   225 	case 0:
   243 	case io.SeekStart:
   226 		atomic.StoreInt64(&f.at, offset)
   244 		atomic.StoreInt64(&f.at, offset)
   227 	case 1:
   245 	case io.SeekCurrent:
   228 		atomic.AddInt64(&f.at, int64(offset))
   246 		atomic.AddInt64(&f.at, offset)
   229 	case 2:
   247 	case io.SeekEnd:
   230 		atomic.StoreInt64(&f.at, int64(len(f.fileData.data))+offset)
   248 		atomic.StoreInt64(&f.at, int64(len(f.fileData.data))+offset)
   231 	}
   249 	}
   232 	return f.at, nil
   250 	return f.at, nil
   233 }
   251 }
   234 
   252 
   235 func (f *File) Write(b []byte) (n int, err error) {
   253 func (f *File) Write(b []byte) (n int, err error) {
       
   254 	if f.closed == true {
       
   255 		return 0, ErrFileClosed
       
   256 	}
   236 	if f.readOnly {
   257 	if f.readOnly {
   237 		return 0, &os.PathError{Op: "write", Path: f.fileData.name, Err: errors.New("file handle is read only")}
   258 		return 0, &os.PathError{Op: "write", Path: f.fileData.name, Err: errors.New("file handle is read only")}
   238 	}
   259 	}
   239 	n = len(b)
   260 	n = len(b)
   240 	cur := atomic.LoadInt64(&f.at)
   261 	cur := atomic.LoadInt64(&f.at)
   244 	var tail []byte
   265 	var tail []byte
   245 	if n+int(cur) < len(f.fileData.data) {
   266 	if n+int(cur) < len(f.fileData.data) {
   246 		tail = f.fileData.data[n+int(cur):]
   267 		tail = f.fileData.data[n+int(cur):]
   247 	}
   268 	}
   248 	if diff > 0 {
   269 	if diff > 0 {
   249 		f.fileData.data = append(bytes.Repeat([]byte{00}, int(diff)), b...)
   270 		f.fileData.data = append(f.fileData.data, append(bytes.Repeat([]byte{00}, int(diff)), b...)...)
   250 		f.fileData.data = append(f.fileData.data, tail...)
   271 		f.fileData.data = append(f.fileData.data, tail...)
   251 	} else {
   272 	} else {
   252 		f.fileData.data = append(f.fileData.data[:cur], b...)
   273 		f.fileData.data = append(f.fileData.data[:cur], b...)
   253 		f.fileData.data = append(f.fileData.data, tail...)
   274 		f.fileData.data = append(f.fileData.data, tail...)
   254 	}
   275 	}
   255 	setModTime(f.fileData, time.Now())
   276 	setModTime(f.fileData, time.Now())
   256 
   277 
   257 	atomic.StoreInt64(&f.at, int64(len(f.fileData.data)))
   278 	atomic.AddInt64(&f.at, int64(n))
   258 	return
   279 	return
   259 }
   280 }
   260 
   281 
   261 func (f *File) WriteAt(b []byte, off int64) (n int, err error) {
   282 func (f *File) WriteAt(b []byte, off int64) (n int, err error) {
   262 	atomic.StoreInt64(&f.at, off)
   283 	atomic.StoreInt64(&f.at, off)