75
76
getxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte), c_size_t)
77
78
_machine = machine()
78
if _machine == 'i686':
82
('__st_ino', c_ulong),
83
('st_mode', c_mode_t),
90
('st_blksize', c_long),
91
('st_blocks', c_longlong),
92
('st_atimespec', c_timespec),
93
('st_mtimespec', c_timespec),
94
('st_ctimespec', c_timespec),
95
('st_ino', c_ulonglong)]
96
elif machine() == 'x86_64':
79
if _machine == 'x86_64':
97
80
c_stat._fields_ = [
98
81
('st_dev', c_dev_t),
99
82
('st_ino', c_ulong),
109
92
('st_atimespec', c_timespec),
110
93
('st_mtimespec', c_timespec),
111
94
('st_ctimespec', c_timespec)]
95
elif _machine == 'ppc':
98
('st_ino', c_ulonglong),
99
('st_mode', c_mode_t),
100
('st_nlink', c_uint),
103
('st_rdev', c_dev_t),
104
('__pad2', c_ushort),
105
('st_size', c_off_t),
106
('st_blksize', c_long),
107
('st_blocks', c_longlong),
108
('st_atimespec', c_timespec),
109
('st_mtimespec', c_timespec),
110
('st_ctimespec', c_timespec)]
113
raise NotImplementedError('Linux %s is not supported.' % _machine)
112
# i686, use as fallback for everything else
115
('__pad1', c_ushort),
116
('__st_ino', c_ulong),
117
('st_mode', c_mode_t),
118
('st_nlink', c_uint),
121
('st_rdev', c_dev_t),
122
('__pad2', c_ushort),
123
('st_size', c_off_t),
124
('st_blksize', c_long),
125
('st_blocks', c_longlong),
126
('st_atimespec', c_timespec),
127
('st_mtimespec', c_timespec),
128
('st_ctimespec', c_timespec),
129
('st_ino', c_ulonglong)]
115
131
raise NotImplementedError('%s is not supported.' % _system)
126
142
('f_ffree', c_fsfilcnt_t),
127
143
('f_favail', c_fsfilcnt_t)]
145
if _system == 'FreeBSD':
146
c_fsblkcnt_t = c_uint64
147
c_fsfilcnt_t = c_uint64
148
setxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte), c_size_t, c_int)
149
getxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte), c_size_t)
150
class c_statvfs(Structure):
152
('f_bavail', c_fsblkcnt_t),
153
('f_bfree', c_fsblkcnt_t),
154
('f_blocks', c_fsblkcnt_t),
155
('f_favail', c_fsfilcnt_t),
156
('f_ffree', c_fsfilcnt_t),
157
('f_files', c_fsfilcnt_t),
158
('f_bsize', c_ulong),
160
('f_frsize', c_ulong)]
129
162
class fuse_file_info(Structure):
131
164
('flags', c_int),
180
213
c_char_p, POINTER(c_stat), c_off_t), c_off_t, POINTER(fuse_file_info))),
181
214
('releasedir', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info))),
182
215
('fsyncdir', CFUNCTYPE(c_int, c_char_p, c_int, POINTER(fuse_file_info))),
183
('init', c_voidp), # Use __init__
184
('destroy', c_voidp), # Use __del__
216
('init', CFUNCTYPE(c_voidp, c_voidp)),
217
('destroy', CFUNCTYPE(c_voidp, c_voidp)),
185
218
('access', CFUNCTYPE(c_int, c_char_p, c_int)),
186
219
('create', CFUNCTYPE(c_int, c_char_p, c_mode_t, POINTER(fuse_file_info))),
187
220
('ftruncate', CFUNCTYPE(c_int, c_char_p, c_off_t, POINTER(fuse_file_info))),
195
228
def time_of_timespec(ts):
196
return ts.tv_sec + 1.0 * ts.tv_nsec / 10 ** 9
229
return ts.tv_sec + ts.tv_nsec / 10 ** 9
198
231
def set_st_attrs(st, attrs):
199
232
for key, val in attrs.items():
204
237
elif hasattr(st, key):
205
238
setattr(st, key, val)
207
_libfuse = CDLL(find_library("fuse"))
241
_libfuse_path = find_library('fuse')
242
if not _libfuse_path:
243
raise EnvironmentError('Unable to find libfuse')
244
_libfuse = CDLL(_libfuse_path)
245
_libfuse.fuse_get_context.restype = POINTER(fuse_context)
210
248
def fuse_get_context():
211
249
"""Returns a (uid, gid, pid) tuple"""
212
p = _libfuse.fuse_get_context()
213
ctx = cast(p, POINTER(fuse_context)).contents
250
ctxp = _libfuse.fuse_get_context()
214
252
return ctx.uid, ctx.gid, ctx.pid
265
303
def readlink(self, path, buf, bufsize):
266
304
ret = self.operations('readlink', path)
267
strbuf = create_string_buffer(ret[:bufsize - 1])
268
memmove(buf, strbuf, len(strbuf))
305
data = create_string_buffer(ret[:bufsize - 1])
306
memmove(buf, data, len(data))
271
309
def mknod(self, path, mode, dev):
309
347
def read(self, path, buf, size, offset, fip):
310
348
fh = fip.contents if self.raw_fi else fip.contents.fh
311
349
ret = self.operations('read', path, size, offset, fh)
313
memmove(buf, create_string_buffer(ret), size)
352
data = create_string_buffer(ret[:size], size)
353
memmove(buf, data, size)
316
356
def write(self, path, buf, size, offset, fip):
317
357
data = string_at(buf, size)
339
379
return self.operations('fsync', path, datasync, fh)
341
381
def setxattr(self, path, name, value, size, options, *args):
342
s = string_at(value, size)
343
return self.operations('setxattr', path, name, s, options, *args)
382
data = string_at(value, size)
383
return self.operations('setxattr', path, name, data, options, *args)
345
385
def getxattr(self, path, name, value, size, *args):
346
386
ret = self.operations('getxattr', path, name, *args)
347
buf = create_string_buffer(ret)
388
buf = create_string_buffer(ret, retsize) # Does not add trailing 0
349
memmove(value, buf, size)
392
memmove(value, buf, retsize)
352
395
def listxattr(self, path, namebuf, size):
353
396
ret = self.operations('listxattr', path)
356
buf = create_string_buffer('\x00'.join(ret))
397
buf = create_string_buffer('\x00'.join(ret)) if ret else ''
357
399
if bool(namebuf):
358
memmove(namebuf, buf, size)
402
memmove(namebuf, buf, bufsize)
361
405
def removexattr(self, path, name):
362
406
return self.operations('removexattr', path, name)
389
433
def fsyncdir(self, path, datasync, fip):
391
435
return self.operations('fsyncdir', path, datasync, fip.contents.fh)
437
def init(self, conn):
438
return self.operations('init', '/')
440
def destroy(self, private_data):
441
return self.operations('destroy', '/')
393
443
def access(self, path, amode):
394
444
return self.operations('access', path, amode)
430
480
return self.operations('bmap', path, blocksize, idx)
433
from errno import EACCES, ENOENT
434
from stat import S_IFDIR
483
class Operations(object):
437
484
"""This class should be subclassed and passed as an argument to FUSE on
438
485
initialization. All operations should raise an OSError exception on
454
501
def chmod(self, path, mode):
455
raise OSError(EACCES, '')
502
raise OSError(EROFS, '')
457
504
def chown(self, path, uid, gid):
458
raise OSError(EACCES, '')
505
raise OSError(EROFS, '')
460
507
def create(self, path, mode, fi=None):
461
508
"""When raw_fi is False (default case), fi is None and create should
462
509
return a numerical file handle.
463
510
When raw_fi is True the file handle should be set directly by create
465
raise OSError(EACCES, '')
512
raise OSError(EROFS, '')
514
def destroy(self, path):
515
"""Called on filesystem destruction. Path is always /"""
467
518
def flush(self, path, fh):
488
539
def getxattr(self, path, name, position=0):
489
540
raise OSError(ENOTSUP, '')
542
def init(self, path):
543
"""Called on filesystem initialization. Path is always /
544
Use it instead of __init__ if you start threads on initialization."""
491
547
def link(self, target, source):
492
raise OSError(EACCES, '')
548
raise OSError(EROFS, '')
494
550
def listxattr(self, path):
499
555
def mkdir(self, path, mode):
500
raise OSError(EACCES, '')
556
raise OSError(EROFS, '')
502
558
def mknod(self, path, mode, dev):
503
raise OSError(EACCES, '')
559
raise OSError(EROFS, '')
505
561
def open(self, path, flags):
506
562
"""When raw_fi is False (default case), open should return a numerical
517
573
def read(self, path, size, offset, fh):
518
574
"""Returns a string containing the data requested."""
519
raise OSError(EACCES, '')
575
raise OSError(ENOENT, '')
521
577
def readdir(self, path, fh):
522
578
"""Can return either a list of names, or a list of (name, attrs, offset)
524
580
return ['.', '..']
526
582
def readlink(self, path):
527
raise OSError(EACCES, '')
583
raise OSError(ENOENT, '')
529
585
def release(self, path, fh):
536
592
raise OSError(ENOTSUP, '')
538
594
def rename(self, old, new):
539
raise OSError(EACCES, '')
595
raise OSError(EROFS, '')
541
597
def rmdir(self, path):
542
raise OSError(EACCES, '')
598
raise OSError(EROFS, '')
544
600
def setxattr(self, path, name, value, options, position=0):
545
601
raise OSError(ENOTSUP, '')
547
603
def statfs(self, path):
548
604
"""Returns a dictionary with keys identical to the statvfs C structure
549
of statvfs(3). The f_frsize, f_favail, f_fsid and f_flag fields are
550
ignored by FUSE though."""
606
On Mac OS X f_bsize and f_frsize must be a power of 2 (minimum 512)."""
553
609
def symlink(self, target, source):
554
raise OSError(EACCES, '')
610
raise OSError(EROFS, '')
556
612
def truncate(self, path, length, fh=None):
557
raise OSError(EACCES, '')
613
raise OSError(EROFS, '')
559
615
def unlink(self, path):
560
raise OSError(EACCES, '')
616
raise OSError(EROFS, '')
562
618
def utimens(self, path, times=None):
563
619
"""Times is a (atime, mtime) tuple. If None use current time."""
566
622
def write(self, path, data, offset, fh):
567
raise OSError(EACCES, '')
623
raise OSError(EROFS, '')
570
626
class LoggingMixIn: