package ipnsfs import ( "sync" chunk "github.com/ipfs/go-ipfs/importer/chunk" dag "github.com/ipfs/go-ipfs/merkledag" mod "github.com/ipfs/go-ipfs/unixfs/mod" context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" ) type File struct { parent childCloser fs *Filesystem name string hasChanges bool mod *mod.DagModifier lock sync.Mutex } // NewFile returns a NewFile object with the given parameters func NewFile(name string, node *dag.Node, parent childCloser, fs *Filesystem) (*File, error) { dmod, err := mod.NewDagModifier(context.Background(), node, fs.dserv, fs.pins.GetManual(), chunk.DefaultSplitter) if err != nil { return nil, err } return &File{ fs: fs, parent: parent, name: name, mod: dmod, }, nil } // Write writes the given data to the file at its current offset func (fi *File) Write(b []byte) (int, error) { fi.Lock() defer fi.Unlock() fi.hasChanges = true return fi.mod.Write(b) } // Read reads into the given buffer from the current offset func (fi *File) Read(b []byte) (int, error) { fi.Lock() defer fi.Unlock() return fi.mod.Read(b) } // Read reads into the given buffer from the current offset func (fi *File) CtxReadFull(ctx context.Context, b []byte) (int, error) { fi.Lock() defer fi.Unlock() return fi.mod.CtxReadFull(ctx, b) } // Close flushes, then propogates the modified dag node up the directory structure // and signals a republish to occur func (fi *File) Close() error { fi.Lock() defer fi.Unlock() if fi.hasChanges { err := fi.mod.Sync() if err != nil { return err } nd, err := fi.mod.GetNode() if err != nil { return err } fi.Unlock() err = fi.parent.closeChild(fi.name, nd) fi.Lock() if err != nil { return err } fi.hasChanges = false } return nil } // Sync flushes the changes in the file to disk func (fi *File) Sync() error { fi.Lock() defer fi.Unlock() return fi.mod.Sync() } // Seek implements io.Seeker func (fi *File) Seek(offset int64, whence int) (int64, error) { fi.Lock() defer fi.Unlock() return fi.mod.Seek(offset, whence) } // Write At writes the given bytes at the offset 'at' func (fi *File) WriteAt(b []byte, at int64) (int, error) { fi.Lock() defer fi.Unlock() fi.hasChanges = true return fi.mod.WriteAt(b, at) } // Size returns the size of this file func (fi *File) Size() (int64, error) { fi.Lock() defer fi.Unlock() return fi.mod.Size() } // GetNode returns the dag node associated with this file func (fi *File) GetNode() (*dag.Node, error) { fi.Lock() defer fi.Unlock() return fi.mod.GetNode() } // Truncate truncates the file to size func (fi *File) Truncate(size int64) error { fi.Lock() defer fi.Unlock() fi.hasChanges = true return fi.mod.Truncate(size) } // Type returns the type FSNode this is func (fi *File) Type() NodeType { return TFile } // Lock the file func (fi *File) Lock() { fi.lock.Lock() } // Unlock the file func (fi *File) Unlock() { fi.lock.Unlock() }