diff options
author | Javier Jardón <jjardon@gnome.org> | 2018-08-28 17:45:50 +0100 |
---|---|---|
committer | Javier Jardón <jjardon@gnome.org> | 2018-11-05 12:47:01 +0000 |
commit | 2df43fa5b3ce2f9858a83c09e72071d0657e2cb3 (patch) | |
tree | cf8200b3f6c60ec1b246790cebe42b347946ddcb | |
parent | 82e971efa22b3d14d50397d627b7ace6b185a19d (diff) | |
download | buildstream-jjardon/fusepy.tar.gz |
Depend on fusepy package instead internal copyjjardon/fusepy
-rw-r--r-- | .gitlab-ci.yml | 3 | ||||
-rw-r--r-- | buildstream/_fuse/fuse.py | 1006 | ||||
-rw-r--r-- | buildstream/_fuse/hardlinks.py | 2 | ||||
-rw-r--r-- | buildstream/_fuse/mount.py | 2 | ||||
-rw-r--r-- | setup.cfg | 1 | ||||
-rwxr-xr-x | setup.py | 1 |
6 files changed, 6 insertions, 1009 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 02a803de4..9f4320980 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -57,6 +57,7 @@ source_dist: variables: PYTEST_ADDOPTS: "--color=yes" script: + - pip3 install 'fusepy>=3.0.0' # Diagnostics - mount - df -h @@ -118,6 +119,7 @@ tests-unix: # disappear unless we mark it as user-installed. - dnf mark install fuse-libs - dnf erase -y bubblewrap ostree + - pip3 install 'fusepy>=3.0.0' # Unpack and get into dist/buildstream - cd dist && ./unpack.sh && cd buildstream @@ -145,6 +147,7 @@ docs: stage: test script: - export BST_SOURCE_CACHE="$(pwd)/cache/integration-cache/sources" + - pip3 install 'fusepy>=3.0.0' # Currently sphinx_rtd_theme does not support Sphinx >1.8, this breaks search functionality - pip3 install sphinx==1.7.9 - pip3 install sphinx-click diff --git a/buildstream/_fuse/fuse.py b/buildstream/_fuse/fuse.py deleted file mode 100644 index 4ff6b9903..000000000 --- a/buildstream/_fuse/fuse.py +++ /dev/null @@ -1,1006 +0,0 @@ -# This is an embedded copy of fuse.py taken from the following upstream commit: -# -# https://github.com/terencehonles/fusepy/commit/0eafeb557e0e70926ed9450008ef17057d302391 -# -# Our local modifications are recorded in the Git history of this repo. - -# Copyright (c) 2012 Terence Honles <terence@honles.com> (maintainer) -# Copyright (c) 2008 Giorgos Verigakis <verigak@gmail.com> (author) -# -# Permission to use, copy, modify, and distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -# pylint: skip-file - -from __future__ import print_function, absolute_import, division - -from ctypes import * -from ctypes.util import find_library -from errno import * -from os import strerror -from platform import machine, system -from signal import signal, SIGINT, SIG_DFL -from stat import S_IFDIR -from traceback import print_exc - -import logging - -try: - from functools import partial -except ImportError: - # http://docs.python.org/library/functools.html#functools.partial - def partial(func, *args, **keywords): - def newfunc(*fargs, **fkeywords): - newkeywords = keywords.copy() - newkeywords.update(fkeywords) - return func(*(args + fargs), **newkeywords) - - newfunc.func = func - newfunc.args = args - newfunc.keywords = keywords - return newfunc - -try: - basestring -except NameError: - basestring = str - -class c_timespec(Structure): - _fields_ = [('tv_sec', c_long), ('tv_nsec', c_long)] - -class c_utimbuf(Structure): - _fields_ = [('actime', c_timespec), ('modtime', c_timespec)] - -class c_stat(Structure): - pass # Platform dependent - -_system = system() -_machine = machine() - -if _system == 'Darwin': - _libiconv = CDLL(find_library('iconv'), RTLD_GLOBAL) # libfuse dependency - _libfuse_path = (find_library('fuse4x') or find_library('osxfuse') or - find_library('fuse')) -else: - _libfuse_path = find_library('fuse') - -if not _libfuse_path: - raise EnvironmentError('Unable to find libfuse') -else: - _libfuse = CDLL(_libfuse_path) - -if _system == 'Darwin' and hasattr(_libfuse, 'macfuse_version'): - _system = 'Darwin-MacFuse' - - -if _system in ('Darwin', 'Darwin-MacFuse', 'FreeBSD'): - ENOTSUP = 45 - c_dev_t = c_int32 - c_fsblkcnt_t = c_ulong - c_fsfilcnt_t = c_ulong - c_gid_t = c_uint32 - c_mode_t = c_uint16 - c_off_t = c_int64 - c_pid_t = c_int32 - c_uid_t = c_uint32 - setxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte), - c_size_t, c_int, c_uint32) - getxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte), - c_size_t, c_uint32) - if _system == 'Darwin': - c_stat._fields_ = [ - ('st_dev', c_dev_t), - ('st_mode', c_mode_t), - ('st_nlink', c_uint16), - ('st_ino', c_uint64), - ('st_uid', c_uid_t), - ('st_gid', c_gid_t), - ('st_rdev', c_dev_t), - ('st_atimespec', c_timespec), - ('st_mtimespec', c_timespec), - ('st_ctimespec', c_timespec), - ('st_birthtimespec', c_timespec), - ('st_size', c_off_t), - ('st_blocks', c_int64), - ('st_blksize', c_int32), - ('st_flags', c_int32), - ('st_gen', c_int32), - ('st_lspare', c_int32), - ('st_qspare', c_int64)] - else: - c_stat._fields_ = [ - ('st_dev', c_dev_t), - ('st_ino', c_uint32), - ('st_mode', c_mode_t), - ('st_nlink', c_uint16), - ('st_uid', c_uid_t), - ('st_gid', c_gid_t), - ('st_rdev', c_dev_t), - ('st_atimespec', c_timespec), - ('st_mtimespec', c_timespec), - ('st_ctimespec', c_timespec), - ('st_size', c_off_t), - ('st_blocks', c_int64), - ('st_blksize', c_int32)] -elif _system == 'Linux': - ENOTSUP = 95 - c_dev_t = c_ulonglong - c_fsblkcnt_t = c_ulonglong - c_fsfilcnt_t = c_ulonglong - c_gid_t = c_uint - c_mode_t = c_uint - c_off_t = c_longlong - c_pid_t = c_int - c_uid_t = c_uint - 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) - - if _machine == 'x86_64': - c_stat._fields_ = [ - ('st_dev', c_dev_t), - ('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 == 'mips': - c_stat._fields_ = [ - ('st_dev', c_dev_t), - ('__pad1_1', c_ulong), - ('__pad1_2', c_ulong), - ('__pad1_3', c_ulong), - ('st_ino', c_ulong), - ('st_mode', c_mode_t), - ('st_nlink', c_ulong), - ('st_uid', c_uid_t), - ('st_gid', c_gid_t), - ('st_rdev', c_dev_t), - ('__pad2_1', c_ulong), - ('__pad2_2', c_ulong), - ('st_size', c_off_t), - ('__pad3', c_ulong), - ('st_atimespec', c_timespec), - ('__pad4', c_ulong), - ('st_mtimespec', c_timespec), - ('__pad5', c_ulong), - ('st_ctimespec', c_timespec), - ('__pad6', c_ulong), - ('st_blksize', c_long), - ('st_blocks', c_long), - ('__pad7_1', c_ulong), - ('__pad7_2', c_ulong), - ('__pad7_3', c_ulong), - ('__pad7_4', c_ulong), - ('__pad7_5', c_ulong), - ('__pad7_6', c_ulong), - ('__pad7_7', c_ulong), - ('__pad7_8', c_ulong), - ('__pad7_9', c_ulong), - ('__pad7_10', c_ulong), - ('__pad7_11', c_ulong), - ('__pad7_12', c_ulong), - ('__pad7_13', c_ulong), - ('__pad7_14', c_ulong)] - elif _machine == 'ppc': - c_stat._fields_ = [ - ('st_dev', c_dev_t), - ('st_ino', c_ulonglong), - ('st_mode', c_mode_t), - ('st_nlink', c_uint), - ('st_uid', c_uid_t), - ('st_gid', c_gid_t), - ('st_rdev', c_dev_t), - ('__pad2', c_ushort), - ('st_size', c_off_t), - ('st_blksize', c_long), - ('st_blocks', c_longlong), - ('st_atimespec', c_timespec), - ('st_mtimespec', c_timespec), - ('st_ctimespec', c_timespec)] - elif _machine == 'ppc64' or _machine == 'ppc64le': - c_stat._fields_ = [ - ('st_dev', c_dev_t), - ('st_ino', c_ulong), - ('st_nlink', c_ulong), - ('st_mode', c_mode_t), - ('st_uid', c_uid_t), - ('st_gid', c_gid_t), - ('__pad', c_uint), - ('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 == 'aarch64': - c_stat._fields_ = [ - ('st_dev', c_dev_t), - ('st_ino', c_ulong), - ('st_mode', c_mode_t), - ('st_nlink', c_uint), - ('st_uid', c_uid_t), - ('st_gid', c_gid_t), - ('st_rdev', c_dev_t), - ('__pad1', c_ulong), - ('st_size', c_off_t), - ('st_blksize', c_int), - ('__pad2', c_int), - ('st_blocks', c_long), - ('st_atimespec', c_timespec), - ('st_mtimespec', c_timespec), - ('st_ctimespec', c_timespec)] - else: - # i686, use as fallback for everything else - c_stat._fields_ = [ - ('st_dev', c_dev_t), - ('__pad1', c_ushort), - ('__st_ino', c_ulong), - ('st_mode', c_mode_t), - ('st_nlink', c_uint), - ('st_uid', c_uid_t), - ('st_gid', c_gid_t), - ('st_rdev', c_dev_t), - ('__pad2', c_ushort), - ('st_size', c_off_t), - ('st_blksize', c_long), - ('st_blocks', c_longlong), - ('st_atimespec', c_timespec), - ('st_mtimespec', c_timespec), - ('st_ctimespec', c_timespec), - ('st_ino', c_ulonglong)] -else: - raise NotImplementedError('{} is not supported.'.format(_system)) - - -class c_statvfs(Structure): - _fields_ = [ - ('f_bsize', c_ulong), - ('f_frsize', c_ulong), - ('f_blocks', c_fsblkcnt_t), - ('f_bfree', c_fsblkcnt_t), - ('f_bavail', c_fsblkcnt_t), - ('f_files', c_fsfilcnt_t), - ('f_ffree', c_fsfilcnt_t), - ('f_favail', c_fsfilcnt_t), - ('f_fsid', c_ulong), - #('unused', c_int), - ('f_flag', c_ulong), - ('f_namemax', c_ulong)] - -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): - _fields_ = [ - ('flags', c_int), - ('fh_old', c_ulong), - ('writepage', c_int), - ('direct_io', c_uint, 1), - ('keep_cache', c_uint, 1), - ('flush', c_uint, 1), - ('padding', c_uint, 29), - ('fh', c_uint64), - ('lock_owner', c_uint64)] - -class fuse_context(Structure): - _fields_ = [ - ('fuse', c_voidp), - ('uid', c_uid_t), - ('gid', c_gid_t), - ('pid', c_pid_t), - ('private_data', c_voidp)] - -_libfuse.fuse_get_context.restype = POINTER(fuse_context) - - -class fuse_operations(Structure): - _fields_ = [ - ('getattr', CFUNCTYPE(c_int, c_char_p, POINTER(c_stat))), - ('readlink', CFUNCTYPE(c_int, c_char_p, POINTER(c_byte), c_size_t)), - ('getdir', c_voidp), # Deprecated, use readdir - ('mknod', CFUNCTYPE(c_int, c_char_p, c_mode_t, c_dev_t)), - ('mkdir', CFUNCTYPE(c_int, c_char_p, c_mode_t)), - ('unlink', CFUNCTYPE(c_int, c_char_p)), - ('rmdir', CFUNCTYPE(c_int, c_char_p)), - ('symlink', CFUNCTYPE(c_int, c_char_p, c_char_p)), - ('rename', CFUNCTYPE(c_int, c_char_p, c_char_p)), - ('link', CFUNCTYPE(c_int, c_char_p, c_char_p)), - ('chmod', CFUNCTYPE(c_int, c_char_p, c_mode_t)), - ('chown', CFUNCTYPE(c_int, c_char_p, c_uid_t, c_gid_t)), - ('truncate', CFUNCTYPE(c_int, c_char_p, c_off_t)), - ('utime', c_voidp), # Deprecated, use utimens - ('open', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info))), - - ('read', CFUNCTYPE(c_int, c_char_p, POINTER(c_byte), c_size_t, - c_off_t, POINTER(fuse_file_info))), - - ('write', CFUNCTYPE(c_int, c_char_p, POINTER(c_byte), c_size_t, - c_off_t, POINTER(fuse_file_info))), - - ('statfs', CFUNCTYPE(c_int, c_char_p, POINTER(c_statvfs))), - ('flush', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info))), - ('release', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info))), - ('fsync', CFUNCTYPE(c_int, c_char_p, c_int, POINTER(fuse_file_info))), - ('setxattr', setxattr_t), - ('getxattr', getxattr_t), - ('listxattr', CFUNCTYPE(c_int, c_char_p, POINTER(c_byte), c_size_t)), - ('removexattr', CFUNCTYPE(c_int, c_char_p, c_char_p)), - ('opendir', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info))), - - ('readdir', CFUNCTYPE(c_int, c_char_p, c_voidp, - CFUNCTYPE(c_int, c_voidp, 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))), - - ('fsyncdir', CFUNCTYPE(c_int, c_char_p, c_int, - POINTER(fuse_file_info))), - - ('init', CFUNCTYPE(c_voidp, c_voidp)), - ('destroy', CFUNCTYPE(c_voidp, c_voidp)), - ('access', CFUNCTYPE(c_int, c_char_p, c_int)), - - ('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))), - - ('fgetattr', CFUNCTYPE(c_int, c_char_p, POINTER(c_stat), - POINTER(fuse_file_info))), - - ('lock', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info), - c_int, c_voidp)), - - ('utimens', CFUNCTYPE(c_int, c_char_p, POINTER(c_utimbuf))), - ('bmap', CFUNCTYPE(c_int, c_char_p, c_size_t, POINTER(c_ulonglong))), - ('flag_nullpath_ok', c_uint, 1), - ('flag_nopath', c_uint, 1), - ('flag_utime_omit_ok', c_uint, 1), - ('flag_reserved', c_uint, 29), - ] - - -def time_of_timespec(ts): - return ts.tv_sec + ts.tv_nsec / 10 ** 9 - -def set_st_attrs(st, attrs): - for key, val in attrs.items(): - if key in ('st_atime', 'st_mtime', 'st_ctime', 'st_birthtime'): - timespec = getattr(st, key + 'spec', None) - if timespec is None: - continue - timespec.tv_sec = int(val) - timespec.tv_nsec = int((val - timespec.tv_sec) * 10 ** 9) - elif hasattr(st, key): - setattr(st, key, val) - - -def fuse_get_context(): - 'Returns a (uid, gid, pid) tuple' - - ctxp = _libfuse.fuse_get_context() - ctx = ctxp.contents - return ctx.uid, ctx.gid, ctx.pid - - -class FuseOSError(OSError): - def __init__(self, errno): - super(FuseOSError, self).__init__(errno, strerror(errno)) - - -class FUSE(object): - ''' - This class is the lower level interface and should not be subclassed under - normal use. Its methods are called by fuse. - - Assumes API version 2.6 or later. - ''' - - OPTIONS = ( - ('foreground', '-f'), - ('debug', '-d'), - ('nothreads', '-s'), - ) - - def __init__(self, operations, mountpoint, raw_fi=False, encoding='utf-8', - **kwargs): - - ''' - Setting raw_fi to True will cause FUSE to pass the fuse_file_info - class as is to Operations, instead of just the fh field. - - This gives you access to direct_io, keep_cache, etc. - ''' - - self.operations = operations - self.raw_fi = raw_fi - self.encoding = encoding - - args = ['fuse'] - - args.extend(flag for arg, flag in self.OPTIONS - if kwargs.pop(arg, False)) - - kwargs.setdefault('fsname', operations.__class__.__name__) - args.append('-o') - args.append(','.join(self._normalize_fuse_options(**kwargs))) - args.append(mountpoint) - - args = [arg.encode(encoding) for arg in args] - argv = (c_char_p * len(args))(*args) - - fuse_ops = fuse_operations() - for ent in fuse_operations._fields_: - name, prototype = ent[:2] - - val = getattr(operations, name, None) - if val is None: - continue - - # Function pointer members are tested for using the - # getattr(operations, name) above but are dynamically - # invoked using self.operations(name) - if hasattr(prototype, 'argtypes'): - val = prototype(partial(self._wrapper, getattr(self, name))) - - setattr(fuse_ops, name, val) - - try: - old_handler = signal(SIGINT, SIG_DFL) - except ValueError: - old_handler = SIG_DFL - - err = _libfuse.fuse_main_real(len(args), argv, pointer(fuse_ops), - sizeof(fuse_ops), None) - - try: - signal(SIGINT, old_handler) - except ValueError: - pass - - del self.operations # Invoke the destructor - if err: - raise RuntimeError(err) - - @staticmethod - def _normalize_fuse_options(**kargs): - for key, value in kargs.items(): - if isinstance(value, bool): - if value is True: yield key - else: - yield '{}={}'.format(key, value) - - @staticmethod - def _wrapper(func, *args, **kwargs): - 'Decorator for the methods that follow' - - try: - return func(*args, **kwargs) or 0 - except OSError as e: - return -(e.errno or EFAULT) - except: - print_exc() - return -EFAULT - - def _decode_optional_path(self, path): - # NB: this method is intended for fuse operations that - # allow the path argument to be NULL, - # *not* as a generic path decoding method - if path is None: - return None - return path.decode(self.encoding) - - def getattr(self, path, buf): - return self.fgetattr(path, buf, None) - - def readlink(self, path, buf, bufsize): - ret = self.operations('readlink', path.decode(self.encoding)) \ - .encode(self.encoding) - - # copies a string into the given buffer - # (null terminated and truncated if necessary) - data = create_string_buffer(ret[:bufsize - 1]) - memmove(buf, data, len(data)) - return 0 - - def mknod(self, path, mode, dev): - return self.operations('mknod', path.decode(self.encoding), mode, dev) - - def mkdir(self, path, mode): - return self.operations('mkdir', path.decode(self.encoding), mode) - - def unlink(self, path): - return self.operations('unlink', path.decode(self.encoding)) - - def rmdir(self, path): - return self.operations('rmdir', path.decode(self.encoding)) - - def symlink(self, source, target): - 'creates a symlink `target -> source` (e.g. ln -s source target)' - - return self.operations('symlink', target.decode(self.encoding), - source.decode(self.encoding)) - - def rename(self, old, new): - return self.operations('rename', old.decode(self.encoding), - new.decode(self.encoding)) - - def link(self, source, target): - 'creates a hard link `target -> source` (e.g. ln source target)' - - return self.operations('link', target.decode(self.encoding), - source.decode(self.encoding)) - - def chmod(self, path, mode): - return self.operations('chmod', path.decode(self.encoding), mode) - - def chown(self, path, uid, gid): - # Check if any of the arguments is a -1 that has overflowed - if c_uid_t(uid + 1).value == 0: - uid = -1 - if c_gid_t(gid + 1).value == 0: - gid = -1 - - return self.operations('chown', path.decode(self.encoding), uid, gid) - - def truncate(self, path, length): - return self.operations('truncate', path.decode(self.encoding), length) - - def open(self, path, fip): - fi = fip.contents - if self.raw_fi: - return self.operations('open', path.decode(self.encoding), fi) - else: - fi.fh = self.operations('open', path.decode(self.encoding), - fi.flags) - - return 0 - - def read(self, path, buf, size, offset, fip): - if self.raw_fi: - fh = fip.contents - else: - fh = fip.contents.fh - - ret = self.operations('read', self._decode_optional_path(path), size, - offset, fh) - - if not ret: return 0 - - retsize = len(ret) - assert retsize <= size, \ - 'actual amount read {:d} greater than expected {:d}'.format(retsize, size) - - data = create_string_buffer(ret, retsize) - memmove(buf, data, retsize) - return retsize - - def write(self, path, buf, size, offset, fip): - data = string_at(buf, size) - - if self.raw_fi: - fh = fip.contents - else: - fh = fip.contents.fh - - return self.operations('write', self._decode_optional_path(path), data, - offset, fh) - - def statfs(self, path, buf): - stv = buf.contents - attrs = self.operations('statfs', path.decode(self.encoding)) - for key, val in attrs.items(): - if hasattr(stv, key): - setattr(stv, key, val) - - return 0 - - def flush(self, path, fip): - if self.raw_fi: - fh = fip.contents - else: - fh = fip.contents.fh - - return self.operations('flush', self._decode_optional_path(path), fh) - - def release(self, path, fip): - if self.raw_fi: - fh = fip.contents - else: - fh = fip.contents.fh - - return self.operations('release', self._decode_optional_path(path), fh) - - def fsync(self, path, datasync, fip): - if self.raw_fi: - fh = fip.contents - else: - fh = fip.contents.fh - - return self.operations('fsync', self._decode_optional_path(path), datasync, - fh) - - def setxattr(self, path, name, value, size, options, *args): - return self.operations('setxattr', path.decode(self.encoding), - name.decode(self.encoding), - string_at(value, size), options, *args) - - def getxattr(self, path, name, value, size, *args): - ret = self.operations('getxattr', path.decode(self.encoding), - name.decode(self.encoding), *args) - - retsize = len(ret) - # allow size queries - if not value: return retsize - - # do not truncate - if retsize > size: return -ERANGE - - buf = create_string_buffer(ret, retsize) # Does not add trailing 0 - memmove(value, buf, retsize) - - return retsize - - def listxattr(self, path, namebuf, size): - attrs = self.operations('listxattr', path.decode(self.encoding)) or '' - ret = '\x00'.join(attrs).encode(self.encoding) - if len(ret) > 0: - ret += '\x00'.encode(self.encoding) - - retsize = len(ret) - # allow size queries - if not namebuf: return retsize - - # do not truncate - if retsize > size: return -ERANGE - - buf = create_string_buffer(ret, retsize) - memmove(namebuf, buf, retsize) - - return retsize - - def removexattr(self, path, name): - return self.operations('removexattr', path.decode(self.encoding), - name.decode(self.encoding)) - - def opendir(self, path, fip): - # Ignore raw_fi - fip.contents.fh = self.operations('opendir', - path.decode(self.encoding)) - - return 0 - - def readdir(self, path, buf, filler, offset, fip): - # Ignore raw_fi - for item in self.operations('readdir', self._decode_optional_path(path), - fip.contents.fh): - - if isinstance(item, basestring): - name, st, offset = item, None, 0 - else: - name, attrs, offset = item - if attrs: - st = c_stat() - set_st_attrs(st, attrs) - else: - st = None - - if filler(buf, name.encode(self.encoding), st, offset) != 0: - break - - return 0 - - def releasedir(self, path, fip): - # Ignore raw_fi - return self.operations('releasedir', self._decode_optional_path(path), - fip.contents.fh) - - def fsyncdir(self, path, datasync, fip): - # Ignore raw_fi - return self.operations('fsyncdir', self._decode_optional_path(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): - return self.operations('access', path.decode(self.encoding), amode) - - def create(self, path, mode, fip): - fi = fip.contents - path = path.decode(self.encoding) - - if self.raw_fi: - return self.operations('create', path, mode, fi) - else: - # This line is different from upstream to fix issues - # reading file opened with O_CREAT|O_RDWR. - # See issue #143. - fi.fh = self.operations('create', path, mode, fi.flags) - # END OF MODIFICATION - return 0 - - def ftruncate(self, path, length, fip): - if self.raw_fi: - fh = fip.contents - else: - fh = fip.contents.fh - - return self.operations('truncate', self._decode_optional_path(path), - length, fh) - - def fgetattr(self, path, buf, fip): - memset(buf, 0, sizeof(c_stat)) - - st = buf.contents - if not fip: - fh = fip - elif self.raw_fi: - fh = fip.contents - else: - fh = fip.contents.fh - - attrs = self.operations('getattr', self._decode_optional_path(path), fh) - set_st_attrs(st, attrs) - return 0 - - def lock(self, path, fip, cmd, lock): - if self.raw_fi: - fh = fip.contents - else: - fh = fip.contents.fh - - return self.operations('lock', self._decode_optional_path(path), fh, cmd, - lock) - - def utimens(self, path, buf): - if buf: - atime = time_of_timespec(buf.contents.actime) - mtime = time_of_timespec(buf.contents.modtime) - times = (atime, mtime) - else: - times = None - - return self.operations('utimens', path.decode(self.encoding), times) - - def bmap(self, path, blocksize, idx): - return self.operations('bmap', path.decode(self.encoding), blocksize, - idx) - - -class Operations(object): - ''' - This class should be subclassed and passed as an argument to FUSE on - initialization. All operations should raise a FuseOSError exception on - error. - - When in doubt of what an operation should do, check the FUSE header file - or the corresponding system call man page. - ''' - - def __call__(self, op, *args): - if not hasattr(self, op): - raise FuseOSError(EFAULT) - return getattr(self, op)(*args) - - def access(self, path, amode): - return 0 - - bmap = None - - def chmod(self, path, mode): - raise FuseOSError(EROFS) - - def chown(self, path, uid, gid): - raise FuseOSError(EROFS) - - def create(self, path, mode, fi=None): - ''' - When raw_fi is False (default case), fi is None and create should - return a numerical file handle. - - When raw_fi is True the file handle should be set directly by create - and return 0. - ''' - - raise FuseOSError(EROFS) - - def destroy(self, path): - 'Called on filesystem destruction. Path is always /' - - pass - - def flush(self, path, fh): - return 0 - - def fsync(self, path, datasync, fh): - return 0 - - def fsyncdir(self, path, datasync, fh): - return 0 - - def getattr(self, path, fh=None): - ''' - Returns a dictionary with keys identical to the stat C structure of - stat(2). - - 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 != '/': - raise FuseOSError(ENOENT) - return dict(st_mode=(S_IFDIR | 0o755), st_nlink=2) - - def getxattr(self, path, name, position=0): - raise FuseOSError(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): - 'creates a hard link `target -> source` (e.g. ln source target)' - - raise FuseOSError(EROFS) - - def listxattr(self, path): - return [] - - lock = None - - def mkdir(self, path, mode): - raise FuseOSError(EROFS) - - def mknod(self, path, mode, dev): - raise FuseOSError(EROFS) - - def open(self, path, flags): - ''' - When raw_fi is False (default case), open should return a numerical - file handle. - - When raw_fi is True the signature of open becomes: - open(self, path, fi) - - and the file handle should be set directly. - ''' - - return 0 - - def opendir(self, path): - 'Returns a numerical file handle.' - - return 0 - - def read(self, path, size, offset, fh): - 'Returns a string containing the data requested.' - - raise FuseOSError(EIO) - - def readdir(self, path, fh): - ''' - Can return either a list of names, or a list of (name, attrs, offset) - tuples. attrs is a dict as in getattr. - ''' - - return ['.', '..'] - - def readlink(self, path): - raise FuseOSError(ENOENT) - - def release(self, path, fh): - return 0 - - def releasedir(self, path, fh): - return 0 - - def removexattr(self, path, name): - raise FuseOSError(ENOTSUP) - - def rename(self, old, new): - raise FuseOSError(EROFS) - - def rmdir(self, path): - raise FuseOSError(EROFS) - - def setxattr(self, path, name, value, options, position=0): - raise FuseOSError(ENOTSUP) - - def statfs(self, path): - ''' - Returns a dictionary with keys identical to the statvfs C structure of - statvfs(3). - - On Mac OS X f_bsize and f_frsize must be a power of 2 - (minimum 512). - ''' - - return {} - - def symlink(self, target, source): - 'creates a symlink `target -> source` (e.g. ln -s source target)' - - raise FuseOSError(EROFS) - - def truncate(self, path, length, fh=None): - raise FuseOSError(EROFS) - - def unlink(self, path): - raise FuseOSError(EROFS) - - def utimens(self, path, times=None): - 'Times is a (atime, mtime) tuple. If None use current time.' - - return 0 - - def write(self, path, data, offset, fh): - raise FuseOSError(EROFS) - - -class LoggingMixIn: - log = logging.getLogger('fuse.log-mixin') - - def __call__(self, op, path, *args): - self.log.debug('-> %s %s %s', op, path, repr(args)) - ret = '[Unhandled Exception]' - try: - ret = getattr(self, op)(path, *args) - return ret - except OSError as e: - ret = str(e) - raise - finally: - self.log.debug('<- %s %s', op, repr(ret)) diff --git a/buildstream/_fuse/hardlinks.py b/buildstream/_fuse/hardlinks.py index ff2e81eea..8408de428 100644 --- a/buildstream/_fuse/hardlinks.py +++ b/buildstream/_fuse/hardlinks.py @@ -27,7 +27,7 @@ import shutil import stat import tempfile -from .fuse import FuseOSError, Operations +from fuse import FuseOSError, Operations from .mount import Mount diff --git a/buildstream/_fuse/mount.py b/buildstream/_fuse/mount.py index e31684100..c8d6076ba 100644 --- a/buildstream/_fuse/mount.py +++ b/buildstream/_fuse/mount.py @@ -24,7 +24,7 @@ import sys from contextlib import contextmanager from multiprocessing import Process -from .fuse import FUSE +from fuse import FUSE from .._exceptions import ImplError from .. import _signals @@ -22,7 +22,6 @@ pep8ignore = tmp/* ALL */lib/python3* ALL */bin/* ALL - buildstream/_fuse/fuse.py ALL .eggs/* ALL *_pb2.py ALL *_pb2_grpc.py ALL @@ -343,6 +343,7 @@ setup(name='BuildStream', 'jinja2 >= 2.10', 'protobuf >= 3.5', 'grpcio >= 1.10', + 'fusepy >= 3.0.0', ], entry_points=bst_install_entry_points, tests_require=dev_requires, |