mirror of
https://github.com/GrandpaNutz/fafda.git
synced 2026-03-17 05:36:21 +00:00
208 lines
3.7 KiB
Go
208 lines
3.7 KiB
Go
package filesystem
|
|
|
|
import (
|
|
"io"
|
|
"os"
|
|
|
|
"fafda/internal"
|
|
)
|
|
|
|
type File struct {
|
|
*internal.Node
|
|
|
|
flag int
|
|
|
|
off int64
|
|
dirCount int
|
|
written int64
|
|
writer io.WriteCloser
|
|
reader io.ReadCloser
|
|
|
|
driver internal.StorageDriver
|
|
meta internal.MetaFileSystem
|
|
}
|
|
|
|
func NewFile(
|
|
flag int,
|
|
node *internal.Node,
|
|
metafs internal.MetaFileSystem,
|
|
driver internal.StorageDriver,
|
|
) *File {
|
|
return &File{
|
|
Node: node,
|
|
flag: flag,
|
|
|
|
off: 0,
|
|
dirCount: 0,
|
|
written: 0,
|
|
writer: nil,
|
|
reader: nil,
|
|
|
|
driver: driver,
|
|
meta: metafs,
|
|
}
|
|
}
|
|
|
|
func (f *File) Truncate(_ int64) error { return internal.ErrNotSupported }
|
|
func (f *File) WriteAt(_ []byte, _ int64) (int, error) { return 0, internal.ErrNotSupported }
|
|
func (f *File) Sync() error { return nil }
|
|
|
|
func (f *File) Readdirnames(n int) ([]string, error) {
|
|
if !f.IsDir() {
|
|
return nil, internal.ErrIsNotDir
|
|
}
|
|
fi, err := f.Readdir(n)
|
|
names := make([]string, len(fi))
|
|
for i, f := range fi {
|
|
names[i] = f.Name()
|
|
}
|
|
|
|
return names, err
|
|
}
|
|
|
|
func (f *File) Readdir(n int) ([]os.FileInfo, error) {
|
|
if !f.IsDir() {
|
|
return nil, internal.ErrIsNotDir
|
|
}
|
|
|
|
// If n > 0, return at most n entries
|
|
// If n <= 0, return all remaining entries
|
|
files, err := f.meta.Ls(f.Path(), n, f.dirCount)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
entries := make([]os.FileInfo, len(files))
|
|
for i, file := range files {
|
|
entries[i] = &file
|
|
}
|
|
|
|
f.dirCount += len(entries)
|
|
|
|
if n > 0 && len(entries) == 0 {
|
|
return entries, io.EOF
|
|
}
|
|
|
|
return entries, err
|
|
}
|
|
|
|
func (f *File) Read(p []byte) (n int, err error) {
|
|
if f.IsDir() {
|
|
return 0, internal.ErrIsDir
|
|
}
|
|
if f.reader == nil {
|
|
if err = f.openReadStream(0); err != nil {
|
|
return 0, err
|
|
}
|
|
}
|
|
n, err = f.reader.Read(p)
|
|
// Do not increment n on failed read
|
|
if err != nil && err != io.EOF {
|
|
return n, err
|
|
}
|
|
f.off += int64(n)
|
|
return n, err
|
|
}
|
|
|
|
func (f *File) ReadAt(p []byte, off int64) (n int, err error) {
|
|
if f.IsDir() {
|
|
return 0, internal.ErrIsDir
|
|
}
|
|
if _, err := f.Seek(off, io.SeekCurrent); err != nil {
|
|
return 0, err
|
|
}
|
|
return f.Read(p)
|
|
}
|
|
|
|
func (f *File) WriteString(s string) (ret int, err error) {
|
|
if f.IsDir() {
|
|
return 0, internal.ErrIsDir
|
|
}
|
|
return f.Write([]byte(s))
|
|
}
|
|
|
|
func (f *File) Write(p []byte) (int, error) {
|
|
if f.IsDir() {
|
|
return 0, internal.ErrIsDir
|
|
}
|
|
|
|
if !checkFlags(os.O_WRONLY, f.flag) {
|
|
return 0, internal.ErrNotSupported
|
|
}
|
|
|
|
if f.writer == nil {
|
|
f.written = 0
|
|
if err := f.driver.Truncate(f.Id()); err != nil {
|
|
return 0, err
|
|
}
|
|
if writer, err := f.driver.GetWriter(f.Id()); err != nil {
|
|
return 0, err
|
|
} else {
|
|
f.writer = writer
|
|
}
|
|
}
|
|
n, err := f.writer.Write(p)
|
|
f.written += int64(n)
|
|
|
|
return n, err
|
|
}
|
|
|
|
func (f *File) Seek(offset int64, whence int) (int64, error) {
|
|
if f.IsDir() {
|
|
return 0, internal.ErrIsDir
|
|
}
|
|
|
|
pos := int64(0)
|
|
|
|
switch whence {
|
|
case io.SeekStart:
|
|
pos = offset
|
|
case io.SeekCurrent:
|
|
pos = f.off + offset
|
|
case io.SeekEnd:
|
|
pos = f.Size() - offset
|
|
}
|
|
if pos < 0 {
|
|
return 0, internal.ErrInvalidSeek
|
|
}
|
|
if f.reader != nil {
|
|
if err := f.reader.Close(); err != nil {
|
|
return 0, err
|
|
}
|
|
}
|
|
f.reader = nil
|
|
if err := f.openReadStream(pos); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return pos, nil
|
|
}
|
|
|
|
func (f *File) Close() error {
|
|
if f.writer != nil {
|
|
if err := f.writer.Close(); err != nil {
|
|
return err
|
|
}
|
|
if err := f.meta.Sync(f.Path(), f.written); err != nil {
|
|
return err
|
|
}
|
|
f.writer = nil
|
|
}
|
|
if f.reader != nil {
|
|
if err := f.reader.Close(); err != nil {
|
|
return err
|
|
}
|
|
f.reader = nil
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (f *File) openReadStream(startAt int64) error {
|
|
if reader, err := f.driver.GetReader(f.Id(), startAt); err != nil {
|
|
return err
|
|
} else {
|
|
f.reader = reader
|
|
}
|
|
return nil
|
|
}
|