/
file.go
117 lines (96 loc) · 2.66 KB
/
file.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package mfsng
import (
"context"
"fmt"
"io"
"io/fs"
"os"
"time"
uio "github.com/ipfs/boxo/ipld/unixfs/io"
"github.com/ipfs/go-cid"
ipld "github.com/ipfs/go-ipld-format"
)
var (
_ fs.File = (*File)(nil)
_ io.Seeker = (*File)(nil)
_ io.WriterTo = (*File)(nil)
)
type File struct {
dr uio.DagReader
ctx context.Context // an embedded context for cancellation and deadline propogation
info FileInfo
}
func newFile(ctx context.Context, name string, node ipld.Node, getter ipld.NodeGetter) (*File, error) {
dr, err := uio.NewDagReader(ctx, node, getter)
if err != nil {
return nil, fmt.Errorf("new dag reader: %w", err)
}
return &File{
dr: dr,
ctx: ctx,
info: FileInfo{
name: name,
size: int64(dr.Size()),
filemode: dr.FileMode() & os.ModeType,
modtime: dr.ModTime(),
node: node,
},
}, nil
}
// Stat returns a FileInfo describing the file.
func (f *File) Stat() (fs.FileInfo, error) {
return &f.info, nil
}
func (f *File) Read(buf []byte) (int, error) {
return f.dr.CtxReadFull(f.ctx, buf)
}
func (f *File) Seek(offset int64, whence int) (int64, error) {
return f.dr.Seek(offset, whence)
}
func (f *File) WriteTo(w io.Writer) (int64, error) {
return f.dr.WriteTo(w)
}
func (f *File) Close() error {
return f.dr.Close()
}
func (f *File) Name() string { return f.info.name }
func (f *File) IsDir() bool { return false }
func (f *File) Info() (fs.FileInfo, error) { return f.Stat() }
func (f *File) Type() fs.FileMode { return fs.FileMode(0) }
func (f *File) Cid() cid.Cid { return f.info.node.Cid() }
var _ fs.FileInfo = (*FileInfo)(nil)
type FileInfo struct {
name string
filemode fs.FileMode // just the file type bits
size int64
modtime time.Time
node ipld.Node
}
// Name returns the base name of the file or directory.
func (f *FileInfo) Name() string {
return f.name
}
// Size returns the length in bytes of a file or the size in bytes of the underlying node for a directory.
func (f *FileInfo) Size() int64 {
return f.size
}
// Mode returns the file mode bits of the file or directory.
func (f *FileInfo) Mode() fs.FileMode {
return f.filemode
}
// Mode returns the modification time of the file if known or the zero time otherwise.
func (f *FileInfo) ModTime() time.Time {
return f.modtime
}
// IsDir reports whether the info describes a directory.
func (f *FileInfo) IsDir() bool {
return f.filemode.IsDir()
}
// Sys returns the underlying root node of the file or directory.
func (f *FileInfo) Sys() interface{} {
return f.node
}
// Cid returns the CID of the file or directory's root node.
func (f *FileInfo) Cid() cid.Cid {
return f.node.Cid()
}