Skip to content
This repository has been archived by the owner on Jun 26, 2023. It is now read-only.

initial support for setting/updating file modes and modification times #93

Closed
wants to merge 9 commits into from
85 changes: 73 additions & 12 deletions dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import (
"context"
"errors"
"fmt"
dag "github.com/ipfs/go-merkledag"
ft "github.com/ipfs/go-unixfs"
uio "github.com/ipfs/go-unixfs/io"
"os"
"path"
"sync"
"time"

dag "github.com/ipfs/go-merkledag"
ft "github.com/ipfs/go-unixfs"
uio "github.com/ipfs/go-unixfs/io"

cid "github.com/ipfs/go-cid"
ipld "github.com/ipfs/go-ipld-format"
)
Expand All @@ -39,8 +38,6 @@ type Directory struct {
// UnixFS directory implementation used for creating,
// reading and editing directories.
unixfsDir uio.Directory

modTime time.Time
}

// NewDirectory constructs a new MFS directory.
Expand All @@ -62,7 +59,6 @@ func NewDirectory(ctx context.Context, name string, node ipld.Node, parent paren
ctx: ctx,
unixfsDir: db,
entriesCache: make(map[string]FSNode),
modTime: time.Now(),
}, nil
}

Expand Down Expand Up @@ -132,9 +128,6 @@ func (d *Directory) updateChild(c child) error {
if err != nil {
return err
}

d.modTime = time.Now()

return nil
}

Expand Down Expand Up @@ -290,6 +283,10 @@ func (d *Directory) ForEachEntry(ctx context.Context, f func(NodeListing) error)
}

func (d *Directory) Mkdir(name string) (*Directory, error) {
return d.MkdirWithOpts(name, MkdirOpts{})
}

func (d *Directory) MkdirWithOpts(name string, opts MkdirOpts) (*Directory, error) {
d.lock.Lock()
defer d.lock.Unlock()

Expand All @@ -305,7 +302,7 @@ func (d *Directory) Mkdir(name string) (*Directory, error) {
}
}

ndir := ft.EmptyDirNode()
ndir := ft.EmptyDirNodeWithStat(opts.Mode, opts.ModTime)
ndir.SetCidBuilder(d.GetCidBuilder())

err = d.dagService.Add(d.ctx, ndir)
Expand Down Expand Up @@ -365,7 +362,6 @@ func (d *Directory) AddChild(name string, nd ipld.Node) error {
return err
}

d.modTime = time.Now()
return nil
}

Expand Down Expand Up @@ -425,3 +421,68 @@ func (d *Directory) GetNode() (ipld.Node, error) {

return nd.Copy(), err
}

func (d *Directory) SetMode(mode os.FileMode) error {
nd, err := d.GetNode()
if err != nil {
return err
}

fsn, err := ft.ExtractFSNode(nd)
if err != nil {
return err
}

fsn.SetMode(mode)
data, err := fsn.GetBytes()
if err != nil {
return err
}

return d.setNodeData(data, nd.Links())
}

func (d *Directory) SetModTime(ts time.Time) error {
nd, err := d.GetNode()
if err != nil {
return err
}

fsn, err := ft.ExtractFSNode(nd)
if err != nil {
return err
}

fsn.SetModTime(ts)
data, err := fsn.GetBytes()
if err != nil {
return err
}

return d.setNodeData(data, nd.Links())
}

func (d *Directory) setNodeData(data []byte, links []*ipld.Link) error {
nd := dag.NodeWithData(data)
nd.SetLinks(links)

err := d.dagService.Add(d.ctx, nd)
if err != nil {
return err
}

err = d.parent.updateChildEntry(child{d.name, nd})
if err != nil {
return err
}

d.lock.Lock()
defer d.lock.Unlock()
db, err := uio.NewDirectoryFromNode(d.dagService, nd)
if err != nil {
return err
}
d.unixfsDir = db

return nil
}
90 changes: 90 additions & 0 deletions file.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package mfs
import (
"context"
"fmt"
"os"
"sync"
"time"

dag "github.com/ipfs/go-merkledag"
ft "github.com/ipfs/go-unixfs"
Expand Down Expand Up @@ -177,3 +179,91 @@ func (fi *File) Sync() error {
func (fi *File) Type() NodeType {
return TFile
}

func (fi *File) Mode() (os.FileMode, error) {
fi.nodeLock.RLock()
defer fi.nodeLock.RUnlock()

nd, err := fi.GetNode()
if err == nil {
fsn, err := ft.ExtractFSNode(nd)
if err == nil {
return fsn.Mode() & 0xFFF, nil
}
}

return 0, err
}

func (fi *File) SetMode(mode os.FileMode) error {
nd, err := fi.GetNode()
if err != nil {
return err
}

fsn, err := ft.ExtractFSNode(nd)
if err != nil {
return err
}

fsn.SetMode(mode)
data, err := fsn.GetBytes()
if err != nil {
return err
}

return fi.setNodeData(data)
}

// ModTime returns the files' last modification time
func (fi *File) ModTime() (time.Time, error) {
fi.nodeLock.RLock()
defer fi.nodeLock.RUnlock()

nd, err := fi.GetNode()
if err == nil {
fsn, err := ft.ExtractFSNode(nd)
if err == nil {
return fsn.ModTime(), nil
}
}

return time.Time{}, err
}

// SetModTime sets the files' last modification time
func (fi *File) SetModTime(ts time.Time) error {
nd, err := fi.GetNode()
if err != nil {
return err
}

fsn, err := ft.ExtractFSNode(nd)
if err != nil {
return err
}

fsn.SetModTime(ts)
data, err := fsn.GetBytes()
if err != nil {
return err
}

return fi.setNodeData(data)
}

func (fi *File) setNodeData(data []byte) error {
nd := dag.NodeWithData(data)
err := fi.inode.dagService.Add(context.TODO(), nd)
if err != nil {
return err
}

fi.nodeLock.Lock()
defer fi.nodeLock.Unlock()
fi.node = nd
parent := fi.inode.parent
name := fi.inode.name

return parent.updateChildEntry(child{name, fi.node})
}
Loading