Commit d3eec061 by rfkelly0

upgrade bundled fuse ctypes bindings

parent 0f20660a
#
# [rfk,05/06/09] I've patched this to add support for the init() and
# destroy() callbacks and will submit the patch upstream
# sometime soon...
#
# Copyright (c) 2008 Giorgos Verigakis <verigak@gmail.com> # Copyright (c) 2008 Giorgos Verigakis <verigak@gmail.com>
# #
# Permission to use, copy, modify, and distribute this software for any # Permission to use, copy, modify, and distribute this software for any
...@@ -21,9 +16,10 @@ from __future__ import division ...@@ -21,9 +16,10 @@ from __future__ import division
from ctypes import * from ctypes import *
from ctypes.util import find_library from ctypes.util import find_library
from errno import EFAULT from errno import *
from functools import partial from functools import partial
from platform import machine, system from platform import machine, system
from stat import S_IFDIR
from traceback import print_exc from traceback import print_exc
...@@ -37,7 +33,7 @@ class c_stat(Structure): ...@@ -37,7 +33,7 @@ class c_stat(Structure):
pass # Platform dependent pass # Platform dependent
_system = system() _system = system()
if _system == 'Darwin': if _system in ('Darwin', 'FreeBSD'):
_libiconv = CDLL(find_library("iconv"), RTLD_GLOBAL) # libfuse dependency _libiconv = CDLL(find_library("iconv"), RTLD_GLOBAL) # libfuse dependency
ENOTSUP = 45 ENOTSUP = 45
c_dev_t = c_int32 c_dev_t = c_int32
...@@ -80,11 +76,26 @@ elif _system == 'Linux': ...@@ -80,11 +76,26 @@ elif _system == 'Linux':
getxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte), c_size_t) getxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte), c_size_t)
_machine = machine() _machine = machine()
if _machine == 'i686': if _machine == 'x86_64':
c_stat._fields_ = [ c_stat._fields_ = [
('st_dev', c_dev_t), ('st_dev', c_dev_t),
('__pad1', c_ushort), ('st_ino', c_ulong),
('__st_ino', c_ulong), ('st_nlink', c_ulong),
('st_mode', c_mode_t),
('st_uid', c_uid_t),
('st_gid', c_gid_t),
('__pad0', c_int),
('st_rdev', c_dev_t),
('st_size', c_off_t),
('st_blksize', c_long),
('st_blocks', c_long),
('st_atimespec', c_timespec),
('st_mtimespec', c_timespec),
('st_ctimespec', c_timespec)]
elif _machine == 'ppc':
c_stat._fields_ = [
('st_dev', c_dev_t),
('st_ino', c_ulonglong),
('st_mode', c_mode_t), ('st_mode', c_mode_t),
('st_nlink', c_uint), ('st_nlink', c_uint),
('st_uid', c_uid_t), ('st_uid', c_uid_t),
...@@ -96,26 +107,26 @@ elif _system == 'Linux': ...@@ -96,26 +107,26 @@ elif _system == 'Linux':
('st_blocks', c_longlong), ('st_blocks', c_longlong),
('st_atimespec', c_timespec), ('st_atimespec', c_timespec),
('st_mtimespec', c_timespec), ('st_mtimespec', c_timespec),
('st_ctimespec', c_timespec), ('st_ctimespec', c_timespec)]
('st_ino', c_ulonglong)] else:
elif machine() == 'x86_64': # i686, use as fallback for everything else
c_stat._fields_ = [ c_stat._fields_ = [
('st_dev', c_dev_t), ('st_dev', c_dev_t),
('st_ino', c_ulong), ('__pad1', c_ushort),
('st_nlink', c_ulong), ('__st_ino', c_ulong),
('st_mode', c_mode_t), ('st_mode', c_mode_t),
('st_nlink', c_uint),
('st_uid', c_uid_t), ('st_uid', c_uid_t),
('st_gid', c_gid_t), ('st_gid', c_gid_t),
('__pad0', c_int),
('st_rdev', c_dev_t), ('st_rdev', c_dev_t),
('__pad2', c_ushort),
('st_size', c_off_t), ('st_size', c_off_t),
('st_blksize', c_long), ('st_blksize', c_long),
('st_blocks', c_long), ('st_blocks', c_longlong),
('st_atimespec', c_timespec), ('st_atimespec', c_timespec),
('st_mtimespec', c_timespec), ('st_mtimespec', c_timespec),
('st_ctimespec', c_timespec)] ('st_ctimespec', c_timespec),
else: ('st_ino', c_ulonglong)]
raise NotImplementedError('Linux %s is not supported.' % _machine)
else: else:
raise NotImplementedError('%s is not supported.' % _system) raise NotImplementedError('%s is not supported.' % _system)
...@@ -131,6 +142,23 @@ class c_statvfs(Structure): ...@@ -131,6 +142,23 @@ class c_statvfs(Structure):
('f_ffree', c_fsfilcnt_t), ('f_ffree', c_fsfilcnt_t),
('f_favail', c_fsfilcnt_t)] ('f_favail', c_fsfilcnt_t)]
if _system == 'FreeBSD':
c_fsblkcnt_t = c_uint64
c_fsfilcnt_t = c_uint64
setxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte), c_size_t, c_int)
getxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte), c_size_t)
class c_statvfs(Structure):
_fields_ = [
('f_bavail', c_fsblkcnt_t),
('f_bfree', c_fsblkcnt_t),
('f_blocks', c_fsblkcnt_t),
('f_favail', c_fsfilcnt_t),
('f_ffree', c_fsfilcnt_t),
('f_files', c_fsfilcnt_t),
('f_bsize', c_ulong),
('f_flag', c_ulong),
('f_frsize', c_ulong)]
class fuse_file_info(Structure): class fuse_file_info(Structure):
_fields_ = [ _fields_ = [
('flags', c_int), ('flags', c_int),
...@@ -151,16 +179,6 @@ class fuse_context(Structure): ...@@ -151,16 +179,6 @@ class fuse_context(Structure):
('pid', c_pid_t), ('pid', c_pid_t),
('private_data', c_voidp)] ('private_data', c_voidp)]
class fuse_conn_info(Structure):
_fields_ = [
('proto_major', c_uint),
('proto_minor', c_uint),
('async_read', c_uint),
('max_write', c_uint),
('max_readahead', c_uint),
('capable', c_uint),
('want', c_uint),
('reserved', c_uint*25)]
class fuse_operations(Structure): class fuse_operations(Structure):
_fields_ = [ _fields_ = [
...@@ -196,8 +214,8 @@ class fuse_operations(Structure): ...@@ -196,8 +214,8 @@ class fuse_operations(Structure):
c_char_p, POINTER(c_stat), c_off_t), c_off_t, POINTER(fuse_file_info))), c_char_p, POINTER(c_stat), c_off_t), c_off_t, POINTER(fuse_file_info))),
('releasedir', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info))), ('releasedir', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info))),
('fsyncdir', CFUNCTYPE(c_int, c_char_p, c_int, POINTER(fuse_file_info))), ('fsyncdir', CFUNCTYPE(c_int, c_char_p, c_int, POINTER(fuse_file_info))),
('init', CFUNCTYPE(c_voidp, POINTER(fuse_conn_info))), ('init', CFUNCTYPE(c_voidp, c_voidp)),
('destroy', CFUNCTYPE(None, c_voidp)), ('destroy', CFUNCTYPE(c_voidp, c_voidp)),
('access', CFUNCTYPE(c_int, c_char_p, c_int)), ('access', CFUNCTYPE(c_int, c_char_p, c_int)),
('create', CFUNCTYPE(c_int, c_char_p, c_mode_t, POINTER(fuse_file_info))), ('create', CFUNCTYPE(c_int, c_char_p, c_mode_t, POINTER(fuse_file_info))),
('ftruncate', CFUNCTYPE(c_int, c_char_p, c_off_t, POINTER(fuse_file_info))), ('ftruncate', CFUNCTYPE(c_int, c_char_p, c_off_t, POINTER(fuse_file_info))),
...@@ -209,7 +227,7 @@ class fuse_operations(Structure): ...@@ -209,7 +227,7 @@ class fuse_operations(Structure):
def time_of_timespec(ts): def time_of_timespec(ts):
return ts.tv_sec + 1.0 * ts.tv_nsec / 10 ** 9 return ts.tv_sec + ts.tv_nsec / 10 ** 9
def set_st_attrs(st, attrs): def set_st_attrs(st, attrs):
for key, val in attrs.items(): for key, val in attrs.items():
...@@ -220,13 +238,18 @@ def set_st_attrs(st, attrs): ...@@ -220,13 +238,18 @@ def set_st_attrs(st, attrs):
elif hasattr(st, key): elif hasattr(st, key):
setattr(st, key, val) setattr(st, key, val)
_libfuse = CDLL(find_library("fuse"))
_libfuse_path = find_library('fuse')
if not _libfuse_path:
raise EnvironmentError('Unable to find libfuse')
_libfuse = CDLL(_libfuse_path)
_libfuse.fuse_get_context.restype = POINTER(fuse_context)
def fuse_get_context(): def fuse_get_context():
"""Returns a (uid, gid, pid) tuple""" """Returns a (uid, gid, pid) tuple"""
p = _libfuse.fuse_get_context() ctxp = _libfuse.fuse_get_context()
ctx = cast(p, POINTER(fuse_context)).contents ctx = ctxp.contents
return ctx.uid, ctx.gid, ctx.pid return ctx.uid, ctx.gid, ctx.pid
...@@ -264,7 +287,7 @@ class FUSE(object): ...@@ -264,7 +287,7 @@ class FUSE(object):
_libfuse.fuse_main_real(len(args), argv, pointer(fuse_ops), _libfuse.fuse_main_real(len(args), argv, pointer(fuse_ops),
sizeof(fuse_ops), None) sizeof(fuse_ops), None)
del self.operations # Invoke the destructor del self.operations # Invoke the destructor
def _wrapper_(self, func, *args, **kwargs): def _wrapper_(self, func, *args, **kwargs):
"""Decorator for the methods that follow""" """Decorator for the methods that follow"""
try: try:
...@@ -274,20 +297,14 @@ class FUSE(object): ...@@ -274,20 +297,14 @@ class FUSE(object):
except: except:
print_exc() print_exc()
return -EFAULT return -EFAULT
def init(self,conn):
return self.operations("init",conn)
def destroy(self,data):
return self.operations("destroy",data)
def getattr(self, path, buf): def getattr(self, path, buf):
return self.fgetattr(path, buf, None) return self.fgetattr(path, buf, None)
def readlink(self, path, buf, bufsize): def readlink(self, path, buf, bufsize):
ret = self.operations('readlink', path) ret = self.operations('readlink', path)
strbuf = create_string_buffer(ret[:bufsize - 1]) data = create_string_buffer(ret[:bufsize - 1])
memmove(buf, strbuf, len(strbuf)) memmove(buf, data, len(data))
return 0 return 0
def mknod(self, path, mode, dev): def mknod(self, path, mode, dev):
...@@ -362,24 +379,31 @@ class FUSE(object): ...@@ -362,24 +379,31 @@ class FUSE(object):
return self.operations('fsync', path, datasync, fh) return self.operations('fsync', path, datasync, fh)
def setxattr(self, path, name, value, size, options, *args): def setxattr(self, path, name, value, size, options, *args):
s = string_at(value, size) data = string_at(value, size)
return self.operations('setxattr', path, name, s, options, *args) return self.operations('setxattr', path, name, data, options, *args)
def getxattr(self, path, name, value, size, *args): def getxattr(self, path, name, value, size, *args):
ret = self.operations('getxattr', path, name, *args) ret = self.operations('getxattr', path, name, *args)
buf = create_string_buffer(ret) retsize = len(ret)
buf = create_string_buffer(ret, retsize) # Does not add trailing 0
if bool(value): if bool(value):
memmove(value, buf, len(buf)) if retsize > size:
return len(ret) return -ERANGE
memmove(value, buf, retsize)
return retsize
def listxattr(self, path, namebuf, size): def listxattr(self, path, namebuf, size):
ret = self.operations('listxattr', path) ret = self.operations('listxattr', path)
if not ret: if ret:
return 0 buf = create_string_buffer('\x00'.join(ret))
buf = create_string_buffer('\x00'.join(ret)) else:
buf = ''
bufsize = len(buf)
if bool(namebuf): if bool(namebuf):
memmove(namebuf, buf, len(buf)) if bufsize > size:
return len(buf) return -ERANGE
memmove(namebuf, buf, bufsize)
return bufsize
def removexattr(self, path, name): def removexattr(self, path, name):
return self.operations('removexattr', path, name) return self.operations('removexattr', path, name)
...@@ -412,7 +436,13 @@ class FUSE(object): ...@@ -412,7 +436,13 @@ class FUSE(object):
def fsyncdir(self, path, datasync, fip): def fsyncdir(self, path, datasync, fip):
# Ignore raw_fi # Ignore raw_fi
return self.operations('fsyncdir', path, datasync, fip.contents.fh) return self.operations('fsyncdir', path, datasync, fip.contents.fh)
def init(self, conn):
return self.operations('init', '/')
def destroy(self, private_data):
return self.operations('destroy', '/')
def access(self, path, amode): def access(self, path, amode):
return self.operations('access', path, amode) return self.operations('access', path, amode)
...@@ -453,10 +483,7 @@ class FUSE(object): ...@@ -453,10 +483,7 @@ class FUSE(object):
return self.operations('bmap', path, blocksize, idx) return self.operations('bmap', path, blocksize, idx)
from errno import EACCES, ENOENT class Operations(object):
from stat import S_IFDIR
class Operations:
"""This class should be subclassed and passed as an argument to FUSE on """This class should be subclassed and passed as an argument to FUSE on
initialization. All operations should raise an OSError exception on initialization. All operations should raise an OSError exception on
error. error.
...@@ -468,12 +495,6 @@ class Operations: ...@@ -468,12 +495,6 @@ class Operations:
if not hasattr(self, op): if not hasattr(self, op):
raise OSError(EFAULT, '') raise OSError(EFAULT, '')
return getattr(self, op)(*args) return getattr(self, op)(*args)
def on_init(self,conn):
pass
def on_destroy(self,data):
pass
def access(self, path, amode): def access(self, path, amode):
return 0 return 0
...@@ -481,18 +502,22 @@ class Operations: ...@@ -481,18 +502,22 @@ class Operations:
bmap = None bmap = None
def chmod(self, path, mode): def chmod(self, path, mode):
raise OSError(EACCES, '') raise OSError(EROFS, '')
def chown(self, path, uid, gid): def chown(self, path, uid, gid):
raise OSError(EACCES, '') raise OSError(EROFS, '')
def create(self, path, mode, fi=None): def create(self, path, mode, fi=None):
"""When raw_fi is False (default case), fi is None and create should """When raw_fi is False (default case), fi is None and create should
return a numerical file handle. return a numerical file handle.
When raw_fi is True the file handle should be set directly by create When raw_fi is True the file handle should be set directly by create
and return 0.""" and return 0."""
raise OSError(EACCES, '') raise OSError(EROFS, '')
def destroy(self, path):
"""Called on filesystem destruction. Path is always /"""
pass
def flush(self, path, fh): def flush(self, path, fh):
return 0 return 0
...@@ -505,7 +530,11 @@ class Operations: ...@@ -505,7 +530,11 @@ class Operations:
def getattr(self, path, fh=None): def getattr(self, path, fh=None):
"""Returns a dictionary with keys identical to the stat C structure """Returns a dictionary with keys identical to the stat C structure
of stat(2). of stat(2).
st_atime, st_mtime and st_ctime should be floats.""" st_atime, st_mtime and st_ctime should be floats.
NOTE: There is an incombatibility between Linux and Mac OS X concerning
st_nlink of directories. Mac OS X counts all files inside the directory,
while Linux counts only the subdirectories."""
if path != '/': if path != '/':
raise OSError(ENOENT, '') raise OSError(ENOENT, '')
return dict(st_mode=(S_IFDIR | 0755), st_nlink=2) return dict(st_mode=(S_IFDIR | 0755), st_nlink=2)
...@@ -513,8 +542,13 @@ class Operations: ...@@ -513,8 +542,13 @@ class Operations:
def getxattr(self, path, name, position=0): def getxattr(self, path, name, position=0):
raise OSError(ENOTSUP, '') raise OSError(ENOTSUP, '')
def init(self, path):
"""Called on filesystem initialization. Path is always /
Use it instead of __init__ if you start threads on initialization."""
pass
def link(self, target, source): def link(self, target, source):
raise OSError(EACCES, '') raise OSError(EROFS, '')
def listxattr(self, path): def listxattr(self, path):
return [] return []
...@@ -522,10 +556,10 @@ class Operations: ...@@ -522,10 +556,10 @@ class Operations:
lock = None lock = None
def mkdir(self, path, mode): def mkdir(self, path, mode):
raise OSError(EACCES, '') raise OSError(EROFS, '')
def mknod(self, path, mode, dev): def mknod(self, path, mode, dev):
raise OSError(EACCES, '') raise OSError(EROFS, '')
def open(self, path, flags): def open(self, path, flags):
"""When raw_fi is False (default case), open should return a numerical """When raw_fi is False (default case), open should return a numerical
...@@ -541,7 +575,7 @@ class Operations: ...@@ -541,7 +575,7 @@ class Operations:
def read(self, path, size, offset, fh): def read(self, path, size, offset, fh):
"""Returns a string containing the data requested.""" """Returns a string containing the data requested."""
raise OSError(EACCES, '') raise OSError(ENOENT, '')
def readdir(self, path, fh): def readdir(self, path, fh):
"""Can return either a list of names, or a list of (name, attrs, offset) """Can return either a list of names, or a list of (name, attrs, offset)
...@@ -549,7 +583,7 @@ class Operations: ...@@ -549,7 +583,7 @@ class Operations:
return ['.', '..'] return ['.', '..']
def readlink(self, path): def readlink(self, path):
raise OSError(EACCES, '') raise OSError(ENOENT, '')
def release(self, path, fh): def release(self, path, fh):
return 0 return 0
...@@ -561,35 +595,35 @@ class Operations: ...@@ -561,35 +595,35 @@ class Operations:
raise OSError(ENOTSUP, '') raise OSError(ENOTSUP, '')
def rename(self, old, new): def rename(self, old, new):
raise OSError(EACCES, '') raise OSError(EROFS, '')
def rmdir(self, path): def rmdir(self, path):
raise OSError(EACCES, '') raise OSError(EROFS, '')
def setxattr(self, path, name, value, options, position=0): def setxattr(self, path, name, value, options, position=0):
raise OSError(ENOTSUP, '') raise OSError(ENOTSUP, '')
def statfs(self, path): def statfs(self, path):
"""Returns a dictionary with keys identical to the statvfs C structure """Returns a dictionary with keys identical to the statvfs C structure
of statvfs(3). The f_frsize, f_favail, f_fsid and f_flag fields are of statvfs(3).
ignored by FUSE though.""" On Mac OS X f_bsize and f_frsize must be a power of 2 (minimum 512)."""
return {} return {}
def symlink(self, target, source): def symlink(self, target, source):
raise OSError(EACCES, '') raise OSError(EROFS, '')
def truncate(self, path, length, fh=None): def truncate(self, path, length, fh=None):
raise OSError(EACCES, '') raise OSError(EROFS, '')
def unlink(self, path): def unlink(self, path):
raise OSError(EACCES, '') raise OSError(EROFS, '')
def utimens(self, path, times=None): def utimens(self, path, times=None):
"""Times is a (atime, mtime) tuple. If None use current time.""" """Times is a (atime, mtime) tuple. If None use current time."""
return 0 return 0
def write(self, path, data, offset, fh): def write(self, path, data, offset, fh):
raise OSError(EACCES, '') raise OSError(EROFS, '')
class LoggingMixIn: class LoggingMixIn:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment