-
Notifications
You must be signed in to change notification settings - Fork 0
/
file.go
138 lines (116 loc) · 2.68 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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package mfs
import (
"context"
"fmt"
"sync"
chunk "github.com/ipfs/go-ipfs/importer/chunk"
dag "github.com/ipfs/go-ipfs/merkledag"
ft "github.com/ipfs/go-ipfs/unixfs"
mod "github.com/ipfs/go-ipfs/unixfs/mod"
node "gx/ipfs/QmUsVJ7AEnGyjX8YWnrwq9vmECVGwBQNAKPpgz5KSg8dcq/go-ipld-node"
)
type File struct {
parent childCloser
name string
desclock sync.RWMutex
dserv dag.DAGService
node node.Node
nodelk sync.Mutex
}
// NewFile returns a NewFile object with the given parameters
func NewFile(name string, node node.Node, parent childCloser, dserv dag.DAGService) (*File, error) {
return &File{
dserv: dserv,
parent: parent,
name: name,
node: node,
}, nil
}
const (
OpenReadOnly = iota
OpenWriteOnly
OpenReadWrite
)
func (fi *File) Open(flags int, sync bool) (FileDescriptor, error) {
fi.nodelk.Lock()
node := fi.node
fi.nodelk.Unlock()
switch node := node.(type) {
case *dag.ProtoNode:
fsn, err := ft.FSNodeFromBytes(node.Data())
if err != nil {
return nil, err
}
switch fsn.Type {
default:
return nil, fmt.Errorf("unsupported fsnode type for 'file'")
case ft.TSymlink:
return nil, fmt.Errorf("symlinks not yet supported")
case ft.TFile, ft.TRaw:
// OK case
}
case *dag.RawNode:
// Ok as well.
}
switch flags {
case OpenReadOnly:
fi.desclock.RLock()
case OpenWriteOnly, OpenReadWrite:
fi.desclock.Lock()
default:
// TODO: support other modes
return nil, fmt.Errorf("mode not supported")
}
dmod, err := mod.NewDagModifier(context.TODO(), node, fi.dserv, chunk.DefaultSplitter)
if err != nil {
return nil, err
}
return &fileDescriptor{
inode: fi,
perms: flags,
sync: sync,
mod: dmod,
}, nil
}
// Size returns the size of this file
func (fi *File) Size() (int64, error) {
fi.nodelk.Lock()
defer fi.nodelk.Unlock()
switch nd := fi.node.(type) {
case *dag.ProtoNode:
pbd, err := ft.FromBytes(nd.Data())
if err != nil {
return 0, err
}
return int64(pbd.GetFilesize()), nil
case *dag.RawNode:
return int64(len(nd.RawData())), nil
default:
return 0, fmt.Errorf("unrecognized node type in mfs/file.Size()")
}
}
// GetNode returns the dag node associated with this file
func (fi *File) GetNode() (node.Node, error) {
fi.nodelk.Lock()
defer fi.nodelk.Unlock()
return fi.node, nil
}
func (fi *File) Flush() error {
// open the file in fullsync mode
fd, err := fi.Open(OpenWriteOnly, true)
if err != nil {
return err
}
defer fd.Close()
return fd.Flush()
}
func (fi *File) Sync() error {
// just being able to take the writelock means the descriptor is synced
fi.desclock.Lock()
fi.desclock.Unlock()
return nil
}
// Type returns the type FSNode this is
func (fi *File) Type() NodeType {
return TFile
}