Skip to content

Commit

Permalink
Made mode and mod time work for items within a directory
Browse files Browse the repository at this point in the history
Previously it only worked for a single object or top-level directory. This was only for rpc, as used by ipget, as it was already working for normal ipfs get.
  • Loading branch information
gammazero committed Aug 16, 2024
1 parent 5d23bcb commit d6c6999
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 54 deletions.
77 changes: 36 additions & 41 deletions client/rpc/apifile.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package rpc

import (
"bytes"
"context"
"encoding/json"
"fmt"
Expand Down Expand Up @@ -39,13 +40,23 @@ func (api *UnixfsAPI) Get(ctx context.Context, p path.Path) (files.Node, error)
return nil, err
}

mode, err := stringToFileMode(stat.Mode)
if err != nil {
return nil, err
}

var modTime time.Time
if stat.Mtime != 0 {
modTime = time.Unix(stat.Mtime, int64(stat.MtimeNsecs)).UTC()
}

switch stat.Type {
case "file":
return api.getFile(ctx, p, stat.Size, stat.Mode, stat.Mtime, stat.MtimeNsecs)
return api.getFile(ctx, p, stat.Size, mode, modTime)
case "directory":
return api.getDir(ctx, p, stat.Size, stat.Mode, stat.Mtime, stat.MtimeNsecs)
return api.getDir(ctx, p, stat.Size, mode, modTime)
case "symlink":
return api.getSymlink(ctx, p, stat.Mtime, stat.MtimeNsecs)
return api.getSymlink(ctx, p, modTime)
default:
return nil, fmt.Errorf("unsupported file type '%s'", stat.Type)
}
Expand Down Expand Up @@ -162,21 +173,14 @@ func stringToFileMode(mode string) (os.FileMode, error) {
return os.FileMode(uint32(mode64)), nil
}

func (api *UnixfsAPI) getFile(ctx context.Context, p path.Path, size int64, mode string, mtime int64, mtimeNsecs int) (files.Node, error) {
fm, err := stringToFileMode(mode)
if err != nil {
return nil, err
}

func (api *UnixfsAPI) getFile(ctx context.Context, p path.Path, size int64, mode os.FileMode, mtime time.Time) (files.Node, error) {
f := &apiFile{
ctx: ctx,
core: api.core(),
size: size,
path: p,
mode: fm,
}
if mtime != 0 {
f.mtime = time.Unix(mtime, int64(mtimeNsecs))
ctx: ctx,
core: api.core(),
size: size,
path: p,
mode: mode,
mtime: mtime,
}

return f, f.reset()
Expand Down Expand Up @@ -234,19 +238,19 @@ func (it *apiIter) Next() bool {

switch it.cur.Type {
case unixfs.THAMTShard, unixfs.TMetadata, unixfs.TDirectory:
it.curFile, err = it.core.getDir(it.ctx, path.FromCid(c), int64(it.cur.Size), it.cur.Mode, it.cur.Mtime, it.cur.MtimeNsecs)
it.curFile, err = it.core.getDir(it.ctx, path.FromCid(c), int64(it.cur.Size), it.cur.Mode, it.cur.ModTime)
if err != nil {
it.err = err
return false
}
case unixfs.TFile:
it.curFile, err = it.core.getFile(it.ctx, path.FromCid(c), int64(it.cur.Size), it.cur.Mode, it.cur.Mtime, it.cur.MtimeNsecs)
it.curFile, err = it.core.getFile(it.ctx, path.FromCid(c), int64(it.cur.Size), it.cur.Mode, it.cur.ModTime)
if err != nil {
it.err = err
return false
}
case unixfs.TSymlink:
it.curFile, err = it.core.getSymlink(it.ctx, path.FromCid(c), it.cur.Mtime, it.cur.MtimeNsecs)
it.curFile, err = it.core.getSymlink(it.ctx, path.FromCid(c), it.cur.ModTime)
if err != nil {
it.err = err
return false
Expand Down Expand Up @@ -298,7 +302,7 @@ func (d *apiDir) Entries() files.DirIterator {
}
}

func (api *UnixfsAPI) getDir(ctx context.Context, p path.Path, size int64, mode string, mtime int64, mtimeNsecs int) (files.Node, error) {
func (api *UnixfsAPI) getDir(ctx context.Context, p path.Path, size int64, mode os.FileMode, modTime time.Time) (files.Node, error) {
resp, err := api.core().Request("ls", p.String()).
Option("resolve-size", true).
Option("stream", true).Send(ctx)
Expand All @@ -309,29 +313,25 @@ func (api *UnixfsAPI) getDir(ctx context.Context, p path.Path, size int64, mode
return nil, resp.Error
}

fm, err := stringToFileMode(mode)
if err != nil {
return nil, err
}
data, _ := io.ReadAll(resp.Output)
rdr := bytes.NewReader(data)

d := &apiDir{
ctx: ctx,
core: api,
size: size,
path: p,
mode: fm,
ctx: ctx,
core: api,
size: size,
path: p,
mode: mode,
mtime: modTime,

dec: json.NewDecoder(resp.Output),
}

if mtime != 0 {
d.mtime = time.Unix(mtime, int64(mtimeNsecs)).UTC()
//dec: json.NewDecoder(resp.Output),
dec: json.NewDecoder(rdr),
}

return d, nil
}

func (api *UnixfsAPI) getSymlink(ctx context.Context, p path.Path, mtime int64, mtimeNsecs int) (files.Node, error) {
func (api *UnixfsAPI) getSymlink(ctx context.Context, p path.Path, modTime time.Time) (files.Node, error) {
resp, err := api.core().Request("cat", p.String()).
Option("resolve-size", true).
Option("stream", true).Send(ctx)
Expand All @@ -347,11 +347,6 @@ func (api *UnixfsAPI) getSymlink(ctx context.Context, p path.Path, mtime int64,
return nil, err
}

var modTime time.Time
if mtime != 0 {
modTime = time.Unix(mtime, int64(mtimeNsecs))
}

return files.NewSymlinkFile(string(target), modTime), nil
}

Expand Down
22 changes: 9 additions & 13 deletions client/rpc/unixfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"io"
"os"
"time"

"github.com/ipfs/boxo/files"
unixfs "github.com/ipfs/boxo/ipld/unixfs"
Expand All @@ -23,10 +24,6 @@ type addEvent struct {
Hash string `json:",omitempty"`
Bytes int64 `json:",omitempty"`
Size string `json:",omitempty"`

Mode os.FileMode `json:",omitempty"`
Mtime int64 `json:",omitempty"`
MtimeNsecs int `json:",omitempty"`
}

type UnixfsAPI HttpApi
Expand Down Expand Up @@ -98,12 +95,9 @@ func (api *UnixfsAPI) Add(ctx context.Context, f files.Node, opts ...caopts.Unix

if options.Events != nil {
ifevt := &iface.AddEvent{
Name: out.Name,
Size: out.Size,
Bytes: out.Bytes,
Mode: out.Mode,
Mtime: out.Mtime,
MtimeNsecs: out.MtimeNsecs,
Name: out.Name,
Size: out.Size,
Bytes: out.Bytes,
}

if out.Hash != "" {
Expand Down Expand Up @@ -137,9 +131,8 @@ type lsLink struct {
Type unixfs_pb.Data_DataType
Target string

Mode string
Mtime int64
MtimeNsecs int
Mode os.FileMode
ModTime time.Time
}

type lsObject struct {
Expand Down Expand Up @@ -233,6 +226,9 @@ func (api *UnixfsAPI) Ls(ctx context.Context, p path.Path, opts ...caopts.Unixfs
Size: l0.Size,
Type: ftype,
Target: l0.Target,

Mode: l0.Mode,
ModTime: l0.ModTime,
}:
case <-ctx.Done():
}
Expand Down
7 changes: 7 additions & 0 deletions core/commands/ls.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os"
"sort"
"text/tabwriter"
"time"

cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
Expand All @@ -23,6 +24,8 @@ type LsLink struct {
Size uint64
Type unixfs_pb.Data_DataType
Target string
Mode os.FileMode
ModTime time.Time
}

// LsObject is an element of LsOutput
Expand Down Expand Up @@ -163,6 +166,9 @@ The JSON output contains type information.
Size: link.Size,
Type: ftype,
Target: link.Target,

Mode: link.Mode,
ModTime: link.ModTime,
}
if err := processLink(paths[i], lsLink); err != nil {
return err
Expand Down Expand Up @@ -256,6 +262,7 @@ func tabularOutput(req *cmds.Request, w io.Writer, out *LsOutput, lastObjectHash
}
}

// TODO: Print link.Mode and link.ModTime?
fmt.Fprintf(tw, s, link.Hash, link.Size, cmdenv.EscNonPrint(link.Name))
}
}
Expand Down
2 changes: 2 additions & 0 deletions core/coreapi/unixfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ func (api *UnixfsAPI) processLink(ctx context.Context, linkres ft.LinkResult, se
if !settings.UseCumulativeSize {
lnk.Size = d.FileSize()
}
lnk.Mode = d.Mode()
lnk.ModTime = d.ModTime()
}
}

Expand Down
4 changes: 4 additions & 0 deletions core/coreiface/unixfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package iface
import (
"context"
"os"
"time"

"github.com/ipfs/boxo/files"
"github.com/ipfs/boxo/path"
Expand Down Expand Up @@ -60,6 +61,9 @@ type DirEntry struct {
Type FileType // The type of the file.
Target string // The symlink target (if a symlink).

Mode os.FileMode
ModTime time.Time

Err error
}

Expand Down

0 comments on commit d6c6999

Please sign in to comment.