-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathlfs_fuse.pyx
227 lines (162 loc) · 5.55 KB
/
lfs_fuse.pyx
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
import sys
import time
import traceback
from lfs import create_lfs
from llfuse cimport *
from diskimpl cimport Block
from libc.stdlib cimport malloc, calloc, free, abort, realloc
from libc.string cimport memcpy, memset, strlen, strcmp
from posix.fcntl cimport S_IFREG, S_IFDIR, S_IFLNK
from posix.types cimport ino_t
from libc.errno cimport ENOENT, ENOTDIR, EISDIR, EACCES, ENOMEM, ENAMETOOLONG
inode_obj = None
MAX_NAME_LENGTH = 8
#################
cdef int mkstat(fuse_ino_t ino, struct_stat *stbuf):
print 'mkstat ino={}'.format(ino)
stat = inode_obj.get_attr(ino)
if ino == 1:
stbuf.st_mode = 0755 | S_IFDIR
else:
stbuf.st_mode = stat.mode
stbuf.st_ino = ino
stbuf.st_nlink = 1
stbuf.st_size = 0
stbuf.st_mtime = stat.mtime
return 0
cdef void ll_getattr(fuse_req_t req, fuse_ino_t ino, fuse_file_info *fi):
print "getattr ino={}".format(ino)
cdef struct_stat stbuf
memset(&stbuf, 0, sizeof(stbuf))
if mkstat(ino, &stbuf) == -1:
fuse_reply_err(req, ENOENT)
else:
fuse_reply_attr(req, &stbuf, 1.0)
cdef void ll_lookup(fuse_req_t req, fuse_ino_t parent, const char *name):
print "lookup parent={}, name={}".format(parent, name)
cdef size_t namelen = strlen(name)
if namelen > MAX_NAME_LENGTH:
fuse_reply_err(req, ENOENT)
return
cdef fuse_entry_param e
memset(&e, 0, sizeof(e))
cdef uint64_t pname = 0
memcpy(&pname, name, namelen)
t = inode_obj.lookup(parent, pname)
if t < 0:
fuse_reply_err(req, ENOENT)
return
e.ino = t
e.attr_timeout = 1.0
e.entry_timeout = 1.0
mkstat(e.ino, &e.attr)
fuse_reply_entry(req, &e)
cdef struct dirbuf:
char *p;
size_t size
cdef void dirbuf_add(fuse_req_t req, dirbuf *b, const char *name, fuse_ino_t ino):
cdef struct_stat stbuf
cdef size_t oldsize = b.size
b.size += fuse_add_direntry(req, NULL, 0, name, NULL, 0)
cdef char *newp = <char*>realloc(<void*>b.p, b.size)
if newp == NULL:
print "memory error, could not realloc buffer"
abort()
b.p = newp
memset(&stbuf, 0, sizeof(stbuf))
stbuf.st_ino = ino
fuse_add_direntry(req, b.p + oldsize, b.size - oldsize, name, &stbuf, b.size)
cdef int reply_buf_limited(fuse_req_t req, const char *buf, size_t bufsize, off_t off, size_t maxsize):
if off < bufsize:
return fuse_reply_buf(req, buf + off, min(bufsize - off, maxsize))
else:
fuse_reply_buf(req, NULL, 0)
cdef void ll_readdir(fuse_req_t req, fuse_ino_t ino,
size_t size, off_t off, fuse_file_info* fi):
print "readdir ino={} size={} off={}".format(ino, size, off)
cdef dirbuf b
cdef Block block
cdef uint64_t i
cdef uint64_t name = 0
if ino != 1:
fuse_reply_err(req, ENOTDIR)
else:
memset(&b, 0, sizeof(b))
dirbuf_add(req, &b, ".", ino)
dirbuf_add(req, &b, "..", ino)
block = inode_obj.read(ino, 0)
for i in range(32):
fileino = block[4 + i * 2 + 1]
if fileino != 0:
name = block[4 + i * 2]
dirbuf_add(req, &b, <char*>&name, fileino)
if b.size > size + off:
break
reply_buf_limited(req, b.p, b.size, off, size)
free(b.p)
cdef mknod(fuse_ino_t parent, const char *name, mode_t mode, dev_t rdev):
cdef size_t namelen = strlen(name)
if namelen > MAX_NAME_LENGTH:
return -ENAMETOOLONG
cdef uint64_t pname = 0
memcpy(&pname, name, namelen)
return inode_obj.mknod(parent, pname, mode, int(time.time()))
cdef void ll_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
mode_t mode, dev_t rdev):
print 'mknod parent={}, name={}, mode={}, rdev={}'.format(parent, name, mode, rdev)
ino = mknod(parent, name, mode, rdev)
if ino < 0:
fuse_reply_err(req, -1 * ino)
return
cdef fuse_entry_param e
memset(&e, 0, sizeof(e))
e.ino = ino
e.attr_timeout = 1.0
e.entry_timeout = 1.0
mkstat(e.ino, &e.attr)
fuse_reply_entry(req, &e)
def main():
global inode_obj
if '--' in sys.argv:
fargs = sys.argv[sys.argv.index('--') + 1:]
sys.argv = sys.argv[:sys.argv.index('--')]
else:
fargs = []
inode_obj = create_lfs(fargs)
cdef int argc = len(sys.argv)
cdef char** argv = <char**>malloc(argc * sizeof(char**))
if argv == NULL:
print "Malloc: Memory error. Could not allocate"
abort()
for i in range(argc):
argv[i] = sys.argv[i]
cmain(argc, argv)
cdef int cmain(int argc, char **argv):
cdef fuse_args args
args.argc = argc
args.argv = argv
args.allocated = 0
cdef fuse_chan *ch
cdef char* mountpoint = NULL
cdef int err = -1
cdef fuse_session *se
cdef fuse_lowlevel_ops ops
memset(<void*>&ops, 0, sizeof(ops))
ops.getattr = &ll_getattr
ops.lookup = &ll_lookup
ops.readdir = &ll_readdir
ops.mknod = &ll_mknod
if fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) != -1:
ch = fuse_mount(mountpoint, &args)
if ch != NULL:
se = fuse_lowlevel_new(&args, &ops, sizeof(ops), NULL)
if se != NULL:
if fuse_set_signal_handlers(se) != -1:
fuse_session_add_chan(se, ch)
err = fuse_session_loop(se)
fuse_remove_signal_handlers(se)
fuse_session_remove_chan(ch)
fuse_session_destroy(se)
fuse_unmount(mountpoint, ch)
fuse_opt_free_args(&args)
return err