Windows support
This commit is contained in:
parent
c621d4a335
commit
ad2921311a
17
FSNode.py
17
FSNode.py
|
@ -84,9 +84,7 @@ class FSNode:
|
|||
st_ctime=time.time(),
|
||||
st_mtime=time.time(),
|
||||
st_atime=time.time(),
|
||||
st_nlink=len(self.children),
|
||||
st_uid=os.getuid(),
|
||||
st_gid=os.getgid()
|
||||
st_nlink=len(self.children)
|
||||
)
|
||||
else:
|
||||
return dict(
|
||||
|
@ -95,9 +93,7 @@ class FSNode:
|
|||
st_mtime=time.time(),
|
||||
st_atime=time.time(),
|
||||
st_nlink=2,
|
||||
st_size=self.size,
|
||||
st_uid=os.getuid(),
|
||||
st_gid=os.getgid()
|
||||
st_size=self.size
|
||||
)
|
||||
|
||||
def find_child_by_name(self, name: str):
|
||||
|
@ -267,7 +263,6 @@ class FSNode:
|
|||
f.children.append(readme)
|
||||
|
||||
return f
|
||||
|
||||
@staticmethod
|
||||
def from_label(mo: Label, parent, m) -> None:
|
||||
f = parent.find_child_by_name(slugify("README.md"))
|
||||
|
@ -283,7 +278,13 @@ class FSNode:
|
|||
|
||||
@staticmethod
|
||||
def from_url(mo: Url, parent, m):
|
||||
f = FSNode(mo.name, parent, False)
|
||||
if os.name == 'nt':
|
||||
f = FSNode(mo.name+".url", parent, False)
|
||||
file_content = "[InternetShortcut]\nURL="+mo.url
|
||||
f.size = len(file_content)
|
||||
f.linkTo = UrlLink(file_content)
|
||||
else:
|
||||
f = FSNode(mo.name+".txt", parent, False)
|
||||
f.size = len(mo.url)
|
||||
f.linkTo = UrlLink(mo.url)
|
||||
return f
|
||||
|
|
|
@ -6,6 +6,10 @@ This is a FUSE filesystem for Moodle. It allows you to mount your Moodle site as
|
|||
It is a concept that has been around for a while, but I have not found any implementations that I could get to work, or that were not abandoned.
|
||||
This is my attempt at creating one.
|
||||
|
||||
## Windows binary
|
||||
|
||||
You can easily grab a windows binary in the _realeases_ section, it behaves as the program, make sure to place the env file alongside it
|
||||
|
||||
## Installation
|
||||
|
||||
First, you need to create a `.env` file with the following variables:
|
||||
|
@ -26,6 +30,9 @@ python moodlefuse.py
|
|||
|
||||
This only works on Linux, as it uses FUSE. I have not tested it on Mac, but it could work there too.
|
||||
|
||||
> Q: Why is _refuse_ in the project root?
|
||||
> It's alpha software with some errors, I managed to make it fit for this project for now
|
||||
|
||||
|
||||
### Requirements
|
||||
|
||||
|
|
4
main.py
4
main.py
|
@ -1,6 +1,6 @@
|
|||
import logging
|
||||
|
||||
from fuse import FUSE
|
||||
import sys
|
||||
from refuse.high import FUSE
|
||||
|
||||
from moodle import Moodle
|
||||
from moodlefs import MoodleFS
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from errno import ENOENT, EACCES
|
||||
|
||||
import fuse
|
||||
from fuse import LoggingMixIn, Operations, FuseOSError
|
||||
from refuse import high as fuse
|
||||
from refuse.high import LoggingMixIn, Operations, FuseOSError
|
||||
|
||||
from FSNode import FSNode
|
||||
|
||||
|
@ -30,10 +30,10 @@ class MoodleFS(LoggingMixIn, Operations):
|
|||
return s.to_stat_struct()
|
||||
|
||||
def getxattr(self, path, name, position=0):
|
||||
pass
|
||||
raise fuse.FuseOSError(EACCES)
|
||||
|
||||
def listxattr(self, path):
|
||||
return []
|
||||
raise fuse.FuseOSError(EACCES)
|
||||
|
||||
def mkdir(self, path, mode):
|
||||
raise fuse.FuseOSError(EACCES)
|
||||
|
|
25
refuse/__init__.py
Normal file
25
refuse/__init__.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
REFUSE
|
||||
Simple cross-plattform ctypes bindings for libfuse / FUSE for macOS / WinFsp
|
||||
https://github.com/pleiszenburg/refuse
|
||||
|
||||
src/refuse/__init__.py: Package root
|
||||
|
||||
Copyright (C) 2008-2020 refuse contributors
|
||||
|
||||
<LICENSE_BLOCK>
|
||||
The contents of this file are subject to the Internet Systems Consortium (ISC)
|
||||
license ("ISC license" or "License"). You may not use this file except in
|
||||
compliance with the License. You may obtain a copy of the License at
|
||||
https://opensource.org/licenses/ISC
|
||||
https://github.com/pleiszenburg/refuse/blob/master/LICENSE
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing rights and limitations under the License.
|
||||
</LICENSE_BLOCK>
|
||||
|
||||
"""
|
482
refuse/_high_header.py
Normal file
482
refuse/_high_header.py
Normal file
|
@ -0,0 +1,482 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
REFUSE
|
||||
Simple cross-plattform ctypes bindings for libfuse / FUSE for macOS / WinFsp
|
||||
https://github.com/pleiszenburg/refuse
|
||||
|
||||
src/refuse/_high_header.py: Temporary helper for code refactoring
|
||||
|
||||
THIS FILE IS TEMPORARY AND WILL BE REMOVED!
|
||||
|
||||
Copyright (C) 2008-2020 refuse contributors
|
||||
|
||||
<LICENSE_BLOCK>
|
||||
The contents of this file are subject to the Internet Systems Consortium (ISC)
|
||||
license ("ISC license" or "License"). You may not use this file except in
|
||||
compliance with the License. You may obtain a copy of the License at
|
||||
https://opensource.org/licenses/ISC
|
||||
https://github.com/pleiszenburg/refuse/blob/master/LICENSE
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing rights and limitations under the License.
|
||||
</LICENSE_BLOCK>
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# IMPORT
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
import ctypes
|
||||
import sys
|
||||
|
||||
from ._inventory import dump_globals, get_arch
|
||||
|
||||
if __name__ == '__main__': # DEBUG
|
||||
_system, _machine = sys.argv[1], sys.argv[2]
|
||||
else: # REGULAR
|
||||
_system, _machine = get_arch()
|
||||
|
||||
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# HEADER: TYPES
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
if _system == 'Windows':
|
||||
# NOTE:
|
||||
#
|
||||
# sizeof(long)==4 on Windows 32-bit and 64-bit
|
||||
# sizeof(long)==4 on Cygwin 32-bit and ==8 on Cygwin 64-bit
|
||||
#
|
||||
# We have to fix up c_long and c_ulong so that it matches the
|
||||
# Cygwin (and UNIX) sizes when run on Windows.
|
||||
import sys
|
||||
if sys.maxsize > 0xffffffff:
|
||||
c_win_long = ctypes.c_int64
|
||||
c_win_ulong = ctypes.c_uint64
|
||||
else:
|
||||
c_win_long = ctypes.c_int32
|
||||
c_win_ulong = ctypes.c_uint32
|
||||
|
||||
if _system == 'Windows' or _system == 'CYGWIN':
|
||||
class c_timespec(ctypes.Structure):
|
||||
_fields_ = [('tv_sec', c_win_long), ('tv_nsec', c_win_long)]
|
||||
elif _system == 'OpenBSD':
|
||||
c_time_t = ctypes.c_int64
|
||||
class c_timespec(ctypes.Structure):
|
||||
_fields_ = [('tv_sec', c_time_t), ('tv_nsec', ctypes.c_long)]
|
||||
else:
|
||||
class c_timespec(ctypes.Structure):
|
||||
_fields_ = [('tv_sec', ctypes.c_long), ('tv_nsec', ctypes.c_long)]
|
||||
|
||||
class c_utimbuf(ctypes.Structure):
|
||||
_fields_ = [('actime', c_timespec), ('modtime', c_timespec)]
|
||||
|
||||
class c_stat(ctypes.Structure):
|
||||
pass # Platform dependent
|
||||
|
||||
if _system in ('Darwin', 'Darwin-MacFuse', 'FreeBSD'):
|
||||
ENOTSUP = 45
|
||||
|
||||
c_dev_t = ctypes.c_int32
|
||||
c_fsblkcnt_t = ctypes.c_ulong
|
||||
c_fsfilcnt_t = ctypes.c_ulong
|
||||
c_gid_t = ctypes.c_uint32
|
||||
c_mode_t = ctypes.c_uint16
|
||||
c_off_t = ctypes.c_int64
|
||||
c_pid_t = ctypes.c_int32
|
||||
c_uid_t = ctypes.c_uint32
|
||||
setxattr_t = ctypes.CFUNCTYPE(
|
||||
ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
|
||||
ctypes.POINTER(ctypes.c_byte), ctypes.c_size_t, ctypes.c_int,
|
||||
ctypes.c_uint32)
|
||||
getxattr_t = ctypes.CFUNCTYPE(
|
||||
ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
|
||||
ctypes.POINTER(ctypes.c_byte),
|
||||
ctypes.c_size_t, ctypes.c_uint32)
|
||||
if _system == 'Darwin':
|
||||
c_stat._fields_ = [
|
||||
('st_dev', c_dev_t),
|
||||
('st_mode', c_mode_t),
|
||||
('st_nlink', ctypes.c_uint16),
|
||||
('st_ino', ctypes.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', ctypes.c_int64),
|
||||
('st_blksize', ctypes.c_int32),
|
||||
('st_flags', ctypes.c_int32),
|
||||
('st_gen', ctypes.c_int32),
|
||||
('st_lspare', ctypes.c_int32),
|
||||
('st_qspare', ctypes.c_int64)]
|
||||
else: # MacFuse, FreeBSD
|
||||
c_stat._fields_ = [
|
||||
('st_dev', c_dev_t),
|
||||
('st_ino', ctypes.c_uint32),
|
||||
('st_mode', c_mode_t),
|
||||
('st_nlink', ctypes.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', ctypes.c_int64),
|
||||
('st_blksize', ctypes.c_int32)]
|
||||
elif _system == 'Linux':
|
||||
ENOTSUP = 95
|
||||
|
||||
c_dev_t = ctypes.c_ulonglong
|
||||
c_fsblkcnt_t = ctypes.c_ulonglong
|
||||
c_fsfilcnt_t = ctypes.c_ulonglong
|
||||
c_gid_t = ctypes.c_uint
|
||||
c_mode_t = ctypes.c_uint
|
||||
c_off_t = ctypes.c_longlong
|
||||
c_pid_t = ctypes.c_int
|
||||
c_uid_t = ctypes.c_uint
|
||||
setxattr_t = ctypes.CFUNCTYPE(
|
||||
ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
|
||||
ctypes.POINTER(ctypes.c_byte), ctypes.c_size_t, ctypes.c_int)
|
||||
|
||||
getxattr_t = ctypes.CFUNCTYPE(
|
||||
ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
|
||||
ctypes.POINTER(ctypes.c_byte), ctypes.c_size_t)
|
||||
|
||||
if _machine == 'x86_64':
|
||||
c_stat._fields_ = [
|
||||
('st_dev', c_dev_t),
|
||||
('st_ino', ctypes.c_ulong),
|
||||
('st_nlink', ctypes.c_ulong),
|
||||
('st_mode', c_mode_t),
|
||||
('st_uid', c_uid_t),
|
||||
('st_gid', c_gid_t),
|
||||
('__pad0', ctypes.c_int),
|
||||
('st_rdev', c_dev_t),
|
||||
('st_size', c_off_t),
|
||||
('st_blksize', ctypes.c_long),
|
||||
('st_blocks', ctypes.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', ctypes.c_ulong),
|
||||
('__pad1_2', ctypes.c_ulong),
|
||||
('__pad1_3', ctypes.c_ulong),
|
||||
('st_ino', ctypes.c_ulong),
|
||||
('st_mode', c_mode_t),
|
||||
('st_nlink', ctypes.c_ulong),
|
||||
('st_uid', c_uid_t),
|
||||
('st_gid', c_gid_t),
|
||||
('st_rdev', c_dev_t),
|
||||
('__pad2_1', ctypes.c_ulong),
|
||||
('__pad2_2', ctypes.c_ulong),
|
||||
('st_size', c_off_t),
|
||||
('__pad3', ctypes.c_ulong),
|
||||
('st_atimespec', c_timespec),
|
||||
('__pad4', ctypes.c_ulong),
|
||||
('st_mtimespec', c_timespec),
|
||||
('__pad5', ctypes.c_ulong),
|
||||
('st_ctimespec', c_timespec),
|
||||
('__pad6', ctypes.c_ulong),
|
||||
('st_blksize', ctypes.c_long),
|
||||
('st_blocks', ctypes.c_long),
|
||||
('__pad7_1', ctypes.c_ulong),
|
||||
('__pad7_2', ctypes.c_ulong),
|
||||
('__pad7_3', ctypes.c_ulong),
|
||||
('__pad7_4', ctypes.c_ulong),
|
||||
('__pad7_5', ctypes.c_ulong),
|
||||
('__pad7_6', ctypes.c_ulong),
|
||||
('__pad7_7', ctypes.c_ulong),
|
||||
('__pad7_8', ctypes.c_ulong),
|
||||
('__pad7_9', ctypes.c_ulong),
|
||||
('__pad7_10', ctypes.c_ulong),
|
||||
('__pad7_11', ctypes.c_ulong),
|
||||
('__pad7_12', ctypes.c_ulong),
|
||||
('__pad7_13', ctypes.c_ulong),
|
||||
('__pad7_14', ctypes.c_ulong)]
|
||||
elif _machine == 'ppc':
|
||||
c_stat._fields_ = [
|
||||
('st_dev', c_dev_t),
|
||||
('st_ino', ctypes.c_ulonglong),
|
||||
('st_mode', c_mode_t),
|
||||
('st_nlink', ctypes.c_uint),
|
||||
('st_uid', c_uid_t),
|
||||
('st_gid', c_gid_t),
|
||||
('st_rdev', c_dev_t),
|
||||
('__pad2', ctypes.c_ushort),
|
||||
('st_size', c_off_t),
|
||||
('st_blksize', ctypes.c_long),
|
||||
('st_blocks', ctypes.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', ctypes.c_ulong),
|
||||
('st_nlink', ctypes.c_ulong),
|
||||
('st_mode', c_mode_t),
|
||||
('st_uid', c_uid_t),
|
||||
('st_gid', c_gid_t),
|
||||
('__pad', ctypes.c_uint),
|
||||
('st_rdev', c_dev_t),
|
||||
('st_size', c_off_t),
|
||||
('st_blksize', ctypes.c_long),
|
||||
('st_blocks', ctypes.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', ctypes.c_ulong),
|
||||
('st_mode', c_mode_t),
|
||||
('st_nlink', ctypes.c_uint),
|
||||
('st_uid', c_uid_t),
|
||||
('st_gid', c_gid_t),
|
||||
('st_rdev', c_dev_t),
|
||||
('__pad1', ctypes.c_ulong),
|
||||
('st_size', c_off_t),
|
||||
('st_blksize', ctypes.c_int),
|
||||
('__pad2', ctypes.c_int),
|
||||
('st_blocks', ctypes.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', ctypes.c_ushort),
|
||||
('__st_ino', ctypes.c_ulong),
|
||||
('st_mode', c_mode_t),
|
||||
('st_nlink', ctypes.c_uint),
|
||||
('st_uid', c_uid_t),
|
||||
('st_gid', c_gid_t),
|
||||
('st_rdev', c_dev_t),
|
||||
('__pad2', ctypes.c_ushort),
|
||||
('st_size', c_off_t),
|
||||
('st_blksize', ctypes.c_long),
|
||||
('st_blocks', ctypes.c_longlong),
|
||||
('st_atimespec', c_timespec),
|
||||
('st_mtimespec', c_timespec),
|
||||
('st_ctimespec', c_timespec),
|
||||
('st_ino', ctypes.c_ulonglong)]
|
||||
elif _system == 'Windows' or _system == 'CYGWIN':
|
||||
ENOTSUP = 129 if _system == 'Windows' else 134
|
||||
c_dev_t = ctypes.c_uint
|
||||
c_fsblkcnt_t = c_win_ulong
|
||||
c_fsfilcnt_t = c_win_ulong
|
||||
c_gid_t = ctypes.c_uint
|
||||
c_mode_t = ctypes.c_uint
|
||||
c_off_t = ctypes.c_longlong
|
||||
c_pid_t = ctypes.c_int
|
||||
c_uid_t = ctypes.c_uint
|
||||
setxattr_t = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
|
||||
ctypes.POINTER(ctypes.c_byte), ctypes.c_size_t, ctypes.c_int)
|
||||
getxattr_t = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
|
||||
ctypes.POINTER(ctypes.c_byte), ctypes.c_size_t)
|
||||
c_stat._fields_ = [
|
||||
('st_dev', c_dev_t),
|
||||
('st_ino', ctypes.c_ulonglong),
|
||||
('st_mode', c_mode_t),
|
||||
('st_nlink', ctypes.c_ushort),
|
||||
('st_uid', c_uid_t),
|
||||
('st_gid', c_gid_t),
|
||||
('st_rdev', c_dev_t),
|
||||
('st_size', c_off_t),
|
||||
('st_atimespec', c_timespec),
|
||||
('st_mtimespec', c_timespec),
|
||||
('st_ctimespec', c_timespec),
|
||||
('st_blksize', ctypes.c_int),
|
||||
('st_blocks', ctypes.c_longlong),
|
||||
('st_birthtimespec', c_timespec)]
|
||||
elif _system == 'OpenBSD':
|
||||
ENOTSUP = 91
|
||||
c_dev_t = ctypes.c_int32
|
||||
c_uid_t = ctypes.c_uint32
|
||||
c_gid_t = ctypes.c_uint32
|
||||
c_mode_t = ctypes.c_uint32
|
||||
c_off_t = ctypes.c_int64
|
||||
c_pid_t = ctypes.c_int32
|
||||
c_ino_t = ctypes.c_uint64
|
||||
c_nlink_t = ctypes.c_uint32
|
||||
c_blkcnt_t = ctypes.c_int64
|
||||
c_blksize_t = ctypes.c_int32
|
||||
setxattr_t = ctypes.CFUNCTYPE(
|
||||
ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
|
||||
ctypes.POINTER(ctypes.c_byte), ctypes.c_size_t, ctypes.c_int)
|
||||
getxattr_t = ctypes.CFUNCTYPE(
|
||||
ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
|
||||
ctypes.POINTER(ctypes.c_byte),
|
||||
ctypes.c_size_t)
|
||||
c_fsblkcnt_t = ctypes.c_uint64
|
||||
c_fsfilcnt_t = ctypes.c_uint64
|
||||
c_stat._fields_ = [
|
||||
('st_mode', c_mode_t),
|
||||
('st_dev', c_dev_t),
|
||||
('st_ino', c_ino_t),
|
||||
('st_nlink', c_nlink_t),
|
||||
('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_blkcnt_t),
|
||||
('st_blksize', c_blksize_t),
|
||||
('st_flags', ctypes.c_uint32),
|
||||
('st_gen', ctypes.c_uint32),
|
||||
('st_birthtimespec', c_timespec),
|
||||
]
|
||||
else:
|
||||
raise NotImplementedError('%s is not supported.' % _system)
|
||||
|
||||
|
||||
if _system == 'FreeBSD':
|
||||
c_fsblkcnt_t = ctypes.c_uint64
|
||||
c_fsfilcnt_t = ctypes.c_uint64
|
||||
setxattr_t = ctypes.CFUNCTYPE(
|
||||
ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
|
||||
ctypes.POINTER(ctypes.c_byte), ctypes.c_size_t, ctypes.c_int)
|
||||
|
||||
getxattr_t = ctypes.CFUNCTYPE(
|
||||
ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
|
||||
ctypes.POINTER(ctypes.c_byte), ctypes.c_size_t)
|
||||
|
||||
class c_statvfs(ctypes.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', ctypes.c_ulong),
|
||||
('f_flag', ctypes.c_ulong),
|
||||
('f_frsize', ctypes.c_ulong)]
|
||||
elif _system == 'Windows' or _system == 'CYGWIN':
|
||||
class c_statvfs(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('f_bsize', c_win_ulong),
|
||||
('f_frsize', c_win_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_win_ulong),
|
||||
('f_flag', c_win_ulong),
|
||||
('f_namemax', c_win_ulong)]
|
||||
else:
|
||||
class c_statvfs(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('f_bsize', ctypes.c_ulong),
|
||||
('f_frsize', ctypes.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', ctypes.c_ulong),
|
||||
# ('unused', ctypes.c_int),
|
||||
('f_flag', ctypes.c_ulong),
|
||||
('f_namemax', ctypes.c_ulong)]
|
||||
|
||||
if _system == 'Windows' or _system == 'CYGWIN':
|
||||
class fuse_file_info(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('flags', ctypes.c_int),
|
||||
('fh_old', ctypes.c_int),
|
||||
('writepage', ctypes.c_int),
|
||||
('direct_io', ctypes.c_uint, 1),
|
||||
('keep_cache', ctypes.c_uint, 1),
|
||||
('flush', ctypes.c_uint, 1),
|
||||
('padding', ctypes.c_uint, 29),
|
||||
('fh', ctypes.c_uint64),
|
||||
('lock_owner', ctypes.c_uint64)]
|
||||
elif _system == "OpenBSD":
|
||||
class fuse_file_info(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('flags', ctypes.c_int32),
|
||||
('fh_old', ctypes.c_uint32),
|
||||
('writepage', ctypes.c_int32),
|
||||
('direct_io', ctypes.c_uint32, 1),
|
||||
('keep_cache', ctypes.c_uint32, 1),
|
||||
('flush', ctypes.c_uint32, 1),
|
||||
('nonseekable', ctypes.c_uint32, 1),
|
||||
('padding', ctypes.c_uint32, 27),
|
||||
('flock_release', ctypes.c_uint32, 1),
|
||||
('fh', ctypes.c_uint64),
|
||||
('lock_owner', ctypes.c_uint64)]
|
||||
else:
|
||||
class fuse_file_info(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('flags', ctypes.c_int),
|
||||
('fh_old', ctypes.c_ulong),
|
||||
('writepage', ctypes.c_int),
|
||||
('direct_io', ctypes.c_uint, 1),
|
||||
('keep_cache', ctypes.c_uint, 1),
|
||||
('flush', ctypes.c_uint, 1),
|
||||
('nonseekable', ctypes.c_uint, 1),
|
||||
('flock_release', ctypes.c_uint, 1),
|
||||
('padding', ctypes.c_uint, 27),
|
||||
('fh', ctypes.c_uint64),
|
||||
('lock_owner', ctypes.c_uint64)]
|
||||
|
||||
if _system == "OpenBSD":
|
||||
class fuse_context(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('fuse', ctypes.c_voidp),
|
||||
('uid', c_uid_t),
|
||||
('gid', c_gid_t),
|
||||
('pid', c_pid_t),
|
||||
('private_data', ctypes.c_voidp),
|
||||
('umask', c_mode_t),
|
||||
]
|
||||
else:
|
||||
class fuse_context(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('fuse', ctypes.c_voidp),
|
||||
('uid', c_uid_t),
|
||||
('gid', c_gid_t),
|
||||
('pid', c_pid_t),
|
||||
('private_data', ctypes.c_voidp)]
|
||||
|
||||
if _system == "OpenBSD":
|
||||
bmap_ret_t = ctypes.c_uint64
|
||||
extra_fields = []
|
||||
else:
|
||||
bmap_ret_t = ctypes.c_ulonglong
|
||||
extra_fields = [
|
||||
('flag_nullpath_ok', ctypes.c_uint, 1),
|
||||
('flag_nopath', ctypes.c_uint, 1),
|
||||
('flag_utime_omit_ok', ctypes.c_uint, 1),
|
||||
('flag_reserved', ctypes.c_uint, 29),
|
||||
('ioctl', ctypes.CFUNCTYPE(
|
||||
ctypes.c_int, ctypes.c_char_p, ctypes.c_uint, ctypes.c_void_p,
|
||||
ctypes.POINTER(fuse_file_info), ctypes.c_uint, ctypes.c_void_p)),
|
||||
]
|
||||
|
||||
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# DEBUG
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
if __name__ == '__main__':
|
||||
dump_globals(globals())
|
147
refuse/_inventory.py
Normal file
147
refuse/_inventory.py
Normal file
|
@ -0,0 +1,147 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
REFUSE
|
||||
Simple cross-plattform ctypes bindings for libfuse / FUSE for macOS / WinFsp
|
||||
https://github.com/pleiszenburg/refuse
|
||||
|
||||
src/refuse/_inventory.py: Temporary helper for code refactoring
|
||||
|
||||
THIS FILE IS TEMPORARY AND WILL BE REMOVED!
|
||||
|
||||
Copyright (C) 2008-2020 refuse contributors
|
||||
|
||||
<LICENSE_BLOCK>
|
||||
The contents of this file are subject to the Internet Systems Consortium (ISC)
|
||||
license ("ISC license" or "License"). You may not use this file except in
|
||||
compliance with the License. You may obtain a copy of the License at
|
||||
https://opensource.org/licenses/ISC
|
||||
https://github.com/pleiszenburg/refuse/blob/master/LICENSE
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing rights and limitations under the License.
|
||||
</LICENSE_BLOCK>
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# IMPORT
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
import _ctypes
|
||||
from pprint import pprint as pp
|
||||
import platform # machine, system
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# LIBRARY HEADER "INVENTORY"
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
def get_arch():
|
||||
"""Get system name and generic, OS-independent machine name
|
||||
"""
|
||||
|
||||
system = platform.system()
|
||||
machine = platform.machine()
|
||||
|
||||
if machine in ('i386', 'i486', 'i586', 'i686'):
|
||||
machine = 'x86'
|
||||
|
||||
# On Windows, machine equals hardware - not os. We want os.
|
||||
if system == 'Windows':
|
||||
machine = 'x86_64' if sys.platform == 'win64' else 'x86'
|
||||
|
||||
return system, machine
|
||||
|
||||
|
||||
def get_archs():
|
||||
|
||||
system_dict = {
|
||||
'Windows': ['x86', 'x86_64'],
|
||||
'CYGWIN': ['x86', 'x86_64'],
|
||||
'OpenBSD': ['x86', 'x86_64', 'mips', 'ppc', 'ppc64', 'ppc64le', 'aarch64'],
|
||||
'FreeBSD': ['x86', 'x86_64'],
|
||||
'Darwin': ['x86', 'x86_64', 'ppc', 'ppc64'],
|
||||
'Darwin-MacFuse': ['x86', 'x86_64', 'ppc', 'ppc64'],
|
||||
'Linux': ['x86', 'x86_64', 'mips', 'ppc', 'ppc64', 'ppc64le', 'aarch64'],
|
||||
}
|
||||
|
||||
arch_list = []
|
||||
for system, machines in system_dict.items():
|
||||
for machine in machines:
|
||||
arch_list.append((system, machine))
|
||||
|
||||
for system, machine in arch_list:
|
||||
yield system, machine
|
||||
|
||||
|
||||
def _analyze_item_(item):
|
||||
|
||||
item_type = type(item)
|
||||
item_type_name = getattr(item_type, '__name__')
|
||||
|
||||
if item_type in (int, float, str, bytes, bool, list, dict, set, tuple): # basic python type
|
||||
return item_type.__name__, item
|
||||
|
||||
if hasattr(item, '_fields_'): # ctypes struct
|
||||
fields = [[field[0], _analyze_item_(field[1])] for field in item._fields_]
|
||||
return ['ctypes struct', fields]
|
||||
|
||||
if item_type_name == 'PyCSimpleType':
|
||||
return getattr(item, '__name__')
|
||||
|
||||
if item_type_name == 'PyCFuncPtrType':
|
||||
try:
|
||||
return [
|
||||
'ctypes func',
|
||||
[_analyze_item_(field) for field in getattr(item, 'argtypes', [])],
|
||||
_analyze_item_(item.restype)
|
||||
]
|
||||
except:
|
||||
return [
|
||||
'ctypes func', '?'
|
||||
]
|
||||
|
||||
return getattr(item, '__name__', '?'), type(item)
|
||||
|
||||
|
||||
def dump_globals(globals_dict):
|
||||
|
||||
header_dict = {
|
||||
name: _analyze_item_(globals_dict[name])
|
||||
for name in globals_dict.keys()
|
||||
if not name.startswith('_') and name not in (
|
||||
'sys', # import
|
||||
'ctypes', # import
|
||||
'get_arch', # infrastructure
|
||||
'dump_globals', # debug
|
||||
'extra_fields' # TMP from OpenBSD port
|
||||
)
|
||||
}
|
||||
pp(header_dict)
|
||||
|
||||
|
||||
def dump_header():
|
||||
|
||||
for system, machine in get_archs():
|
||||
|
||||
sys.stdout.write('+++ %s / %s +++\n' % (system, machine))
|
||||
sys.stdout.flush()
|
||||
proc = subprocess.Popen(
|
||||
['python3', '-m', 'refuse._high_header', system, machine],
|
||||
stdout = subprocess.PIPE, stderr = subprocess.PIPE
|
||||
)
|
||||
data = proc.communicate()
|
||||
sys.stderr.write(data[1].decode('utf-8'))
|
||||
sys.stderr.flush()
|
||||
sys.stdout.write(data[0].decode('utf-8'))
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
dump_header()
|
80
refuse/_refactor.py
Normal file
80
refuse/_refactor.py
Normal file
|
@ -0,0 +1,80 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
REFUSE
|
||||
Simple cross-plattform ctypes bindings for libfuse / FUSE for macOS / WinFsp
|
||||
https://github.com/pleiszenburg/refuse
|
||||
|
||||
src/refuse/_refactor.py: Temporary helper for code refactoring
|
||||
|
||||
THIS FILE IS TEMPORARY AND WILL BE REMOVED!
|
||||
|
||||
Copyright (C) 2008-2020 refuse contributors
|
||||
|
||||
<LICENSE_BLOCK>
|
||||
The contents of this file are subject to the Internet Systems Consortium (ISC)
|
||||
license ("ISC license" or "License"). You may not use this file except in
|
||||
compliance with the License. You may obtain a copy of the License at
|
||||
https://opensource.org/licenses/ISC
|
||||
https://github.com/pleiszenburg/refuse/blob/master/LICENSE
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing rights and limitations under the License.
|
||||
</LICENSE_BLOCK>
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# IMPORT
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
import os
|
||||
import ctypes
|
||||
from ctypes.util import find_library
|
||||
import sys
|
||||
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# FIND LIBRARY
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
def get_libfuse(_system):
|
||||
|
||||
_libfuse_path = os.environ.get('FUSE_LIBRARY_PATH')
|
||||
if not _libfuse_path:
|
||||
if _system == 'Darwin':
|
||||
# libfuse dependency
|
||||
_libiconv = ctypes.CDLL(find_library('iconv'), ctypes.RTLD_GLOBAL)
|
||||
|
||||
_libfuse_path = (find_library('fuse4x') or find_library('osxfuse') or
|
||||
find_library('fuse'))
|
||||
elif _system == 'Windows':
|
||||
try:
|
||||
import _winreg as reg
|
||||
except ImportError:
|
||||
import winreg as reg
|
||||
def Reg32GetValue(rootkey, keyname, valname):
|
||||
key, val = None, None
|
||||
try:
|
||||
key = reg.OpenKey(rootkey, keyname, 0, reg.KEY_READ | reg.KEY_WOW64_32KEY)
|
||||
val = str(reg.QueryValueEx(key, valname)[0])
|
||||
except WindowsError:
|
||||
pass
|
||||
finally:
|
||||
if key is not None:
|
||||
reg.CloseKey(key)
|
||||
return val
|
||||
_libfuse_path = Reg32GetValue(reg.HKEY_LOCAL_MACHINE, r"SOFTWARE\WinFsp", r"InstallDir")
|
||||
if _libfuse_path:
|
||||
_libfuse_path += r"bin\winfsp-%s.dll" % ("x64" if sys.maxsize > 0xffffffff else "x86")
|
||||
else:
|
||||
_libfuse_path = find_library('fuse')
|
||||
|
||||
if not _libfuse_path:
|
||||
raise EnvironmentError('Unable to find libfuse')
|
||||
else:
|
||||
_libfuse = ctypes.CDLL(_libfuse_path)
|
||||
|
||||
return _libfuse
|
1407
refuse/high.py
Normal file
1407
refuse/high.py
Normal file
File diff suppressed because it is too large
Load Diff
976
refuse/low.py
Normal file
976
refuse/low.py
Normal file
|
@ -0,0 +1,976 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
REFUSE
|
||||
Simple cross-plattform ctypes bindings for libfuse / FUSE for macOS / WinFsp
|
||||
https://github.com/pleiszenburg/refuse
|
||||
|
||||
src/refuse/low.py: "Low level" FUSE API
|
||||
|
||||
Copyright (C) 2008-2020 refuse contributors
|
||||
|
||||
<LICENSE_BLOCK>
|
||||
The contents of this file are subject to the Internet Systems Consortium (ISC)
|
||||
license ("ISC license" or "License"). You may not use this file except in
|
||||
compliance with the License. You may obtain a copy of the License at
|
||||
https://opensource.org/licenses/ISC
|
||||
https://github.com/pleiszenburg/refuse/blob/master/LICENSE
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing rights and limitations under the License.
|
||||
</LICENSE_BLOCK>
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# IMPORT
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
import ctypes
|
||||
import errno
|
||||
import os
|
||||
import warnings
|
||||
|
||||
from ctypes.util import find_library
|
||||
from platform import machine, system
|
||||
from signal import signal, SIGINT, SIG_DFL
|
||||
from stat import S_IFDIR
|
||||
|
||||
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# HEADER: TODO organize ...
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
_system = system()
|
||||
_machine = machine()
|
||||
|
||||
_libfuse_path = os.environ.get('FUSE_LIBRARY_PATH')
|
||||
if not _libfuse_path:
|
||||
if _system == 'Darwin':
|
||||
# libfuse dependency
|
||||
_libiconv = ctypes.CDLL(find_library('iconv'), ctypes.RTLD_GLOBAL)
|
||||
|
||||
_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 = ctypes.CDLL(_libfuse_path)
|
||||
|
||||
|
||||
class LibFUSE(ctypes.CDLL):
|
||||
def __init__(self):
|
||||
if _system == 'Darwin':
|
||||
self.libiconv = _libiconv
|
||||
super(LibFUSE, self).__init__(_libfuse_path)
|
||||
|
||||
self.fuse_mount.argtypes = (
|
||||
ctypes.c_char_p, ctypes.POINTER(fuse_args))
|
||||
|
||||
self.fuse_mount.restype = ctypes.c_void_p
|
||||
|
||||
self.fuse_lowlevel_new.argtypes = (
|
||||
ctypes.POINTER(fuse_args), ctypes.POINTER(fuse_lowlevel_ops),
|
||||
ctypes.c_size_t, ctypes.c_void_p)
|
||||
|
||||
self.fuse_lowlevel_new.restype = ctypes.c_void_p
|
||||
self.fuse_set_signal_handlers.argtypes = (ctypes.c_void_p,)
|
||||
self.fuse_session_add_chan.argtypes = (
|
||||
ctypes.c_void_p, ctypes.c_void_p)
|
||||
self.fuse_session_loop.argtypes = (ctypes.c_void_p,)
|
||||
self.fuse_remove_signal_handlers.argtypes = (ctypes.c_void_p,)
|
||||
self.fuse_session_remove_chan.argtypes = (ctypes.c_void_p,)
|
||||
self.fuse_session_destroy.argtypes = (ctypes.c_void_p,)
|
||||
self.fuse_unmount.argtypes = (ctypes.c_char_p, ctypes.c_void_p)
|
||||
|
||||
self.fuse_req_ctx.restype = ctypes.POINTER(fuse_ctx)
|
||||
self.fuse_req_ctx.argtypes = (fuse_req_t,)
|
||||
|
||||
self.fuse_reply_err.argtypes = (fuse_req_t, ctypes.c_int)
|
||||
self.fuse_reply_attr.argtypes = (
|
||||
fuse_req_t, ctypes.c_void_p, ctypes.c_double)
|
||||
self.fuse_reply_entry.argtypes = (fuse_req_t, ctypes.c_void_p)
|
||||
self.fuse_reply_open.argtypes = (fuse_req_t, ctypes.c_void_p)
|
||||
self.fuse_reply_buf.argtypes = (
|
||||
fuse_req_t, ctypes.c_char_p, ctypes.c_size_t)
|
||||
self.fuse_reply_none.argtypes = (fuse_req_t,)
|
||||
self.fuse_reply_write.argtypes = (fuse_req_t, ctypes.c_size_t)
|
||||
self.fuse_reply_readlink.argtypes = (
|
||||
fuse_req_t, ctypes.c_char_p)
|
||||
|
||||
self.fuse_add_direntry.argtypes = (
|
||||
ctypes.c_void_p, ctypes.c_char_p, ctypes.c_size_t,
|
||||
ctypes.c_char_p, c_stat_p, c_off_t)
|
||||
|
||||
class fuse_args(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('argc', ctypes.c_int),
|
||||
('argv', ctypes.POINTER(ctypes.c_char_p)),
|
||||
('allocated', ctypes.c_int),
|
||||
]
|
||||
|
||||
class c_timespec(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('tv_sec', ctypes.c_long),
|
||||
('tv_nsec', ctypes.c_long),
|
||||
]
|
||||
|
||||
class c_stat(ctypes.Structure):
|
||||
pass # Platform dependent
|
||||
|
||||
if _system == 'Darwin':
|
||||
ENOTSUP = 45
|
||||
|
||||
c_dev_t = ctypes.c_int32
|
||||
c_fsblkcnt_t = ctypes.c_ulong
|
||||
c_fsfilcnt_t = ctypes.c_ulong
|
||||
c_gid_t = ctypes.c_uint32
|
||||
c_mode_t = ctypes.c_uint16
|
||||
c_off_t = ctypes.c_int64
|
||||
c_pid_t = ctypes.c_int32
|
||||
c_uid_t = ctypes.c_uint32
|
||||
c_stat._fields_ = [
|
||||
('st_dev', c_dev_t),
|
||||
('st_ino', ctypes.c_uint32),
|
||||
('st_mode', c_mode_t),
|
||||
('st_nlink', ctypes.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', ctypes.c_int64),
|
||||
('st_blksize', ctypes.c_int32)]
|
||||
elif _system == 'Linux':
|
||||
ENOTSUP = 95
|
||||
|
||||
c_dev_t = ctypes.c_ulonglong
|
||||
c_fsblkcnt_t = ctypes.c_ulonglong
|
||||
c_fsfilcnt_t = ctypes.c_ulonglong
|
||||
c_gid_t = ctypes.c_uint
|
||||
c_mode_t = ctypes.c_uint
|
||||
c_off_t = ctypes.c_longlong
|
||||
c_pid_t = ctypes.c_int
|
||||
c_uid_t = ctypes.c_uint
|
||||
|
||||
if _machine == 'x86_64':
|
||||
c_stat._fields_ = [
|
||||
('st_dev', c_dev_t),
|
||||
('st_ino', ctypes.c_ulong),
|
||||
('st_nlink', ctypes.c_ulong),
|
||||
('st_mode', c_mode_t),
|
||||
('st_uid', c_uid_t),
|
||||
('st_gid', c_gid_t),
|
||||
('__pad0', ctypes.c_int),
|
||||
('st_rdev', c_dev_t),
|
||||
('st_size', c_off_t),
|
||||
('st_blksize', ctypes.c_long),
|
||||
('st_blocks', ctypes.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', ctypes.c_ulong),
|
||||
('__pad1_2', ctypes.c_ulong),
|
||||
('__pad1_3', ctypes.c_ulong),
|
||||
('st_ino', ctypes.c_ulong),
|
||||
('st_mode', c_mode_t),
|
||||
('st_nlink', ctypes.c_ulong),
|
||||
('st_uid', c_uid_t),
|
||||
('st_gid', c_gid_t),
|
||||
('st_rdev', c_dev_t),
|
||||
('__pad2_1', ctypes.c_ulong),
|
||||
('__pad2_2', ctypes.c_ulong),
|
||||
('st_size', c_off_t),
|
||||
('__pad3', ctypes.c_ulong),
|
||||
('st_atimespec', c_timespec),
|
||||
('__pad4', ctypes.c_ulong),
|
||||
('st_mtimespec', c_timespec),
|
||||
('__pad5', ctypes.c_ulong),
|
||||
('st_ctimespec', c_timespec),
|
||||
('__pad6', ctypes.c_ulong),
|
||||
('st_blksize', ctypes.c_long),
|
||||
('st_blocks', ctypes.c_long),
|
||||
('__pad7_1', ctypes.c_ulong),
|
||||
('__pad7_2', ctypes.c_ulong),
|
||||
('__pad7_3', ctypes.c_ulong),
|
||||
('__pad7_4', ctypes.c_ulong),
|
||||
('__pad7_5', ctypes.c_ulong),
|
||||
('__pad7_6', ctypes.c_ulong),
|
||||
('__pad7_7', ctypes.c_ulong),
|
||||
('__pad7_8', ctypes.c_ulong),
|
||||
('__pad7_9', ctypes.c_ulong),
|
||||
('__pad7_10', ctypes.c_ulong),
|
||||
('__pad7_11', ctypes.c_ulong),
|
||||
('__pad7_12', ctypes.c_ulong),
|
||||
('__pad7_13', ctypes.c_ulong),
|
||||
('__pad7_14', ctypes.c_ulong)]
|
||||
elif _machine == 'ppc':
|
||||
c_stat._fields_ = [
|
||||
('st_dev', c_dev_t),
|
||||
('st_ino', ctypes.c_ulonglong),
|
||||
('st_mode', c_mode_t),
|
||||
('st_nlink', ctypes.c_uint),
|
||||
('st_uid', c_uid_t),
|
||||
('st_gid', c_gid_t),
|
||||
('st_rdev', c_dev_t),
|
||||
('__pad2', ctypes.c_ushort),
|
||||
('st_size', c_off_t),
|
||||
('st_blksize', ctypes.c_long),
|
||||
('st_blocks', ctypes.c_longlong),
|
||||
('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', ctypes.c_ushort),
|
||||
('__st_ino', ctypes.c_ulong),
|
||||
('st_mode', c_mode_t),
|
||||
('st_nlink', ctypes.c_uint),
|
||||
('st_uid', c_uid_t),
|
||||
('st_gid', c_gid_t),
|
||||
('st_rdev', c_dev_t),
|
||||
('__pad2', ctypes.c_ushort),
|
||||
('st_size', c_off_t),
|
||||
('st_blksize', ctypes.c_long),
|
||||
('st_blocks', ctypes.c_longlong),
|
||||
('st_atimespec', c_timespec),
|
||||
('st_mtimespec', c_timespec),
|
||||
('st_ctimespec', c_timespec),
|
||||
('st_ino', ctypes.c_ulonglong)]
|
||||
else:
|
||||
raise NotImplementedError('%s is not supported.' % _system)
|
||||
|
||||
class c_statvfs(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('f_bsize', ctypes.c_ulong),
|
||||
('f_frsize', ctypes.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)]
|
||||
|
||||
class fuse_file_info(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('flags', ctypes.c_int),
|
||||
('fh_old', ctypes.c_ulong),
|
||||
('writepage', ctypes.c_int),
|
||||
('direct_io', ctypes.c_uint, 1),
|
||||
('keep_cache', ctypes.c_uint, 1),
|
||||
('flush', ctypes.c_uint, 1),
|
||||
('nonseekable', ctypes.c_uint, 1),
|
||||
('flock_release', ctypes.c_uint, 1),
|
||||
('padding', ctypes.c_uint, 27),
|
||||
('fh', ctypes.c_uint64),
|
||||
('lock_owner', ctypes.c_uint64)]
|
||||
|
||||
class fuse_ctx(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('uid', c_uid_t),
|
||||
('gid', c_gid_t),
|
||||
('pid', c_pid_t),
|
||||
]
|
||||
|
||||
class fuse_forget_data(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('ino', ctypes.c_uint64), # fuse_ino_t on libfuse3
|
||||
('nlookup', ctypes.c_uint64),
|
||||
]
|
||||
|
||||
fuse_ino_t = ctypes.c_ulong
|
||||
fuse_req_t = ctypes.c_void_p
|
||||
c_stat_p = ctypes.POINTER(c_stat)
|
||||
c_bytes_p = ctypes.POINTER(ctypes.c_byte)
|
||||
fuse_file_info_p = ctypes.POINTER(fuse_file_info)
|
||||
fuse_forget_data_p = ctypes.POINTER(fuse_forget_data)
|
||||
|
||||
FUSE_SET_ATTR = ('st_mode', 'st_uid', 'st_gid', 'st_size', 'st_atime', 'st_mtime')
|
||||
|
||||
class fuse_entry_param(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('ino', fuse_ino_t),
|
||||
('generation', ctypes.c_ulong),
|
||||
('attr', c_stat),
|
||||
('attr_timeout', ctypes.c_double),
|
||||
('entry_timeout', ctypes.c_double),
|
||||
]
|
||||
|
||||
class fuse_lowlevel_ops(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('init', ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p)),
|
||||
('destroy', ctypes.CFUNCTYPE(None, ctypes.c_void_p)),
|
||||
|
||||
('lookup', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_char_p)),
|
||||
|
||||
('forget', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_ulong)), # nlookup is uint64_t in libfuse3
|
||||
|
||||
('getattr', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, fuse_file_info_p)),
|
||||
|
||||
('setattr', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, c_stat_p, ctypes.c_int,
|
||||
fuse_file_info_p)),
|
||||
|
||||
('readlink', ctypes.CFUNCTYPE(None, fuse_req_t, fuse_ino_t)),
|
||||
|
||||
('mknod', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_char_p, c_mode_t,
|
||||
c_dev_t)),
|
||||
|
||||
('mkdir', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_char_p, c_mode_t)),
|
||||
|
||||
('unlink', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_char_p)),
|
||||
|
||||
('rmdir', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_char_p)),
|
||||
|
||||
('symlink', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, ctypes.c_char_p, fuse_ino_t, ctypes.c_char_p)),
|
||||
|
||||
('rename', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_char_p, fuse_ino_t,
|
||||
ctypes.c_char_p)), # There is an extra argument `unsigned int flags` in libfuse3
|
||||
|
||||
('link', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, fuse_ino_t, ctypes.c_char_p)),
|
||||
|
||||
('open', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, fuse_file_info_p)),
|
||||
|
||||
('read', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_size_t, c_off_t,
|
||||
fuse_file_info_p)),
|
||||
|
||||
('write', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, c_bytes_p, ctypes.c_size_t,
|
||||
c_off_t, fuse_file_info_p)),
|
||||
|
||||
('flush', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, fuse_file_info_p)),
|
||||
|
||||
('release', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, fuse_file_info_p)),
|
||||
|
||||
('fsync', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_int, fuse_file_info_p)),
|
||||
|
||||
('opendir', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, fuse_file_info_p)),
|
||||
|
||||
('readdir', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_size_t, c_off_t,
|
||||
fuse_file_info_p)),
|
||||
|
||||
('releasedir', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, fuse_file_info_p)),
|
||||
|
||||
('fsyncdir', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_int, fuse_file_info_p)),
|
||||
|
||||
('statfs', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t)),
|
||||
|
||||
('setxattr', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_char_p, c_bytes_p, ctypes.c_size_t, ctypes.c_int)),
|
||||
|
||||
('getxattr', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_char_p, ctypes.c_size_t)),
|
||||
|
||||
('listxattr', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_size_t)),
|
||||
|
||||
('removexattr', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_char_p)),
|
||||
|
||||
('access', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_int)),
|
||||
|
||||
('create', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_char_p, c_mode_t, fuse_file_info_p)),
|
||||
|
||||
('getlk', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, fuse_file_info_p, ctypes.c_void_p)),
|
||||
|
||||
('setlk', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, fuse_file_info_p, ctypes.c_void_p, ctypes.c_int)),
|
||||
|
||||
('bmap', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_size_t, ctypes.c_uint64)),
|
||||
|
||||
('ioctl', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_int, ctypes.c_void_p, fuse_file_info_p, ctypes.c_uint, ctypes.c_void_p, ctypes.c_size_t, ctypes.c_size_t)),
|
||||
|
||||
('poll', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, fuse_file_info_p, ctypes.c_void_p)),
|
||||
|
||||
('write_buf', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_void_p, c_off_t, fuse_file_info_p)),
|
||||
|
||||
('retrieve_reply', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, ctypes.c_void_p, fuse_ino_t, c_off_t, ctypes.c_void_p)),
|
||||
|
||||
('forget_multi', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, ctypes.c_size_t, fuse_forget_data_p)),
|
||||
|
||||
('flock', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, fuse_file_info_p, ctypes.c_int)),
|
||||
|
||||
('fallocate', ctypes.CFUNCTYPE(
|
||||
None, fuse_req_t, fuse_ino_t, ctypes.c_int, c_off_t, c_off_t, fuse_file_info_p)),
|
||||
|
||||
# readdirplus only exists in libfuse3
|
||||
#('readdirplus', ctypes.CFUNCTYPE(
|
||||
#None, fuse_req_t, fuse_ino_t, ctypes.c_size_t, c_off_t, fuse_file_info_p)),
|
||||
]
|
||||
|
||||
|
||||
def struct_to_dict(p):
|
||||
try:
|
||||
x = p.contents
|
||||
return dict((key, getattr(x, key)) for key, type in x._fields_)
|
||||
except ValueError:
|
||||
return {}
|
||||
|
||||
def stat_to_dict(p, use_ns=False):
|
||||
try:
|
||||
d = {}
|
||||
x = p.contents
|
||||
for key, type in x._fields_:
|
||||
if key in ('st_atimespec', 'st_mtimespec', 'st_ctimespec'):
|
||||
ts = getattr(x, key)
|
||||
key = key[:-4] # Lose the "spec"
|
||||
|
||||
if use_ns:
|
||||
d[key] = ts.tv_sec * 10 ** 9 + ts.tv_nsec
|
||||
else:
|
||||
d[key] = ts.tv_sec + ts.tv_nsec / 1E9
|
||||
else:
|
||||
d[key] = getattr(x, key)
|
||||
return d
|
||||
except ValueError:
|
||||
return {}
|
||||
|
||||
def dict_to_stat(d, use_ns=False):
|
||||
for key in ('st_atime', 'st_mtime', 'st_ctime'):
|
||||
if key in d:
|
||||
val = d[key]
|
||||
|
||||
if use_ns:
|
||||
sec, ns = divmod(int(val), 10 ** 9)
|
||||
else:
|
||||
sec = int(val)
|
||||
nsec = int((val - sec) * 1E9)
|
||||
|
||||
d[key + 'spec'] = c_timespec(sec, nsec)
|
||||
return c_stat(**d)
|
||||
|
||||
def setattr_mask_to_list(mask):
|
||||
return [FUSE_SET_ATTR[i] for i in range(len(FUSE_SET_ATTR)) if mask & (1 << i)]
|
||||
|
||||
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# CLASS: FUSELL
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
class FUSELL:
|
||||
use_ns = False
|
||||
|
||||
def __init__(self, mountpoint, encoding='utf-8'):
|
||||
if not self.use_ns:
|
||||
warnings.warn(
|
||||
'Time as floating point seconds for utimens is deprecated!\n'
|
||||
'To enable time as nanoseconds set the property "use_ns" to '
|
||||
'True in your FUSELL class or set your fusepy '
|
||||
'requirements to <4.',
|
||||
DeprecationWarning)
|
||||
|
||||
self.libfuse = LibFUSE()
|
||||
self.encoding = encoding
|
||||
|
||||
fuse_ops = fuse_lowlevel_ops()
|
||||
|
||||
for name, prototype in fuse_lowlevel_ops._fields_:
|
||||
method = getattr(self, 'fuse_' + name, None) or getattr(self, name, None)
|
||||
if method:
|
||||
setattr(fuse_ops, name, prototype(method))
|
||||
|
||||
args = ['fuse']
|
||||
argv = fuse_args(len(args), (ctypes.c_char_p * len(args))(*[arg.encode(self.encoding) for arg in args]), 0)
|
||||
|
||||
# TODO: handle initialization errors
|
||||
|
||||
chan = self.libfuse.fuse_mount(mountpoint.encode(encoding), argv)
|
||||
assert chan
|
||||
|
||||
session = self.libfuse.fuse_lowlevel_new(
|
||||
argv, ctypes.byref(fuse_ops), ctypes.sizeof(fuse_ops), None)
|
||||
assert session
|
||||
|
||||
try:
|
||||
old_handler = signal(SIGINT, SIG_DFL)
|
||||
except ValueError:
|
||||
old_handler = SIG_DFL
|
||||
|
||||
err = self.libfuse.fuse_set_signal_handlers(session)
|
||||
assert err == 0
|
||||
|
||||
self.libfuse.fuse_session_add_chan(session, chan)
|
||||
|
||||
err = self.libfuse.fuse_session_loop(session)
|
||||
assert err == 0
|
||||
|
||||
err = self.libfuse.fuse_remove_signal_handlers(session)
|
||||
assert err == 0
|
||||
|
||||
try:
|
||||
signal(SIGINT, old_handler)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
self.libfuse.fuse_session_remove_chan(chan)
|
||||
self.libfuse.fuse_session_destroy(session)
|
||||
self.libfuse.fuse_unmount(mountpoint.encode(encoding), chan)
|
||||
|
||||
def reply_err(self, req, err):
|
||||
return self.libfuse.fuse_reply_err(req, err)
|
||||
|
||||
def reply_none(self, req):
|
||||
self.libfuse.fuse_reply_none(req)
|
||||
|
||||
def reply_entry(self, req, entry):
|
||||
entry['attr'] = c_stat(**entry['attr'])
|
||||
e = fuse_entry_param(**entry)
|
||||
self.libfuse.fuse_reply_entry(req, ctypes.byref(e))
|
||||
|
||||
def reply_create(self, req, *args):
|
||||
pass # XXX
|
||||
|
||||
def reply_attr(self, req, attr, attr_timeout):
|
||||
st = dict_to_stat(attr, use_ns=self.use_ns)
|
||||
return self.libfuse.fuse_reply_attr(
|
||||
req, ctypes.byref(st), ctypes.c_double(attr_timeout))
|
||||
|
||||
def reply_readlink(self, req, link):
|
||||
return self.libfuse.fuse_reply_readlink(
|
||||
req, link.encode(self.encoding))
|
||||
|
||||
def reply_open(self, req, d):
|
||||
fi = fuse_file_info(**d)
|
||||
return self.libfuse.fuse_reply_open(req, ctypes.byref(fi))
|
||||
|
||||
def reply_write(self, req, count):
|
||||
return self.libfuse.fuse_reply_write(req, count)
|
||||
|
||||
def reply_buf(self, req, buf):
|
||||
return self.libfuse.fuse_reply_buf(req, buf, len(buf))
|
||||
|
||||
def reply_readdir(self, req, size, off, entries):
|
||||
bufsize = 0
|
||||
sized_entries = []
|
||||
for name, attr in entries:
|
||||
name = name.encode(self.encoding)
|
||||
entsize = self.libfuse.fuse_add_direntry(req, None, 0, name, None, 0)
|
||||
sized_entries.append((name, attr, entsize))
|
||||
bufsize += entsize
|
||||
|
||||
next = 0
|
||||
buf = ctypes.create_string_buffer(bufsize)
|
||||
for name, attr, entsize in sized_entries:
|
||||
entbuf = ctypes.cast(
|
||||
ctypes.addressof(buf) + next, ctypes.c_char_p)
|
||||
st = c_stat(**attr)
|
||||
next += entsize
|
||||
self.libfuse.fuse_add_direntry(
|
||||
req, entbuf, entsize, name, ctypes.byref(st), next)
|
||||
|
||||
if off < bufsize:
|
||||
buf = ctypes.cast(
|
||||
ctypes.addressof(buf) + off, ctypes.c_char_p) if off else buf
|
||||
return self.libfuse.fuse_reply_buf(req, buf, min(bufsize - off, size))
|
||||
else:
|
||||
return self.libfuse.fuse_reply_buf(req, None, 0)
|
||||
|
||||
|
||||
# If you override the following methods you should reply directly
|
||||
# with the self.libfuse.fuse_reply_* methods.
|
||||
|
||||
def fuse_lookup(self, req, parent, name):
|
||||
self.lookup(req, parent, name.decode(self.encoding))
|
||||
|
||||
def fuse_getattr(self, req, ino, fi):
|
||||
self.getattr(req, ino, struct_to_dict(fi))
|
||||
|
||||
def fuse_setattr(self, req, ino, attr, to_set, fi):
|
||||
attr_dict = stat_to_dict(attr, use_ns=self.use_ns)
|
||||
to_set_list = setattr_mask_to_list(to_set)
|
||||
fi_dict = struct_to_dict(fi)
|
||||
self.setattr(req, ino, attr_dict, to_set_list, fi_dict)
|
||||
|
||||
def fuse_mknod(self, req, parent, name, mode, rdev):
|
||||
self.mknod(req, parent, name.decode(self.encoding), mode, rdev)
|
||||
|
||||
def fuse_mkdir(self, req, parent, name, mode):
|
||||
self.mkdir(req, parent, name.decode(self.encoding), mode)
|
||||
|
||||
def fuse_unlink(self, req, parent, name):
|
||||
self.unlink(req, parent, name.decode(self.encoding))
|
||||
|
||||
def fuse_rmdir(self, req, parent, name):
|
||||
self.rmdir(req, parent, name.decode(self.encoding))
|
||||
|
||||
def fuse_symlink(self, req, link, parent, name):
|
||||
self.symlink(req, link.decode(self.encoding), parent, name.decode(self.encoding))
|
||||
|
||||
def fuse_rename(self, req, parent, name, newparent, newname):
|
||||
self.rename(req, parent, name.decode(self.encoding), newparent, newname.decode(self.encoding))
|
||||
|
||||
def fuse_link(self, req, ino, newparent, newname):
|
||||
self.link(req, ino, newparent, newname.decode(self.encoding))
|
||||
|
||||
def fuse_open(self, req, ino, fi):
|
||||
self.open(req, ino, struct_to_dict(fi))
|
||||
|
||||
def fuse_read(self, req, ino, size, off, fi):
|
||||
self.read(req, ino, size, off, fi)
|
||||
|
||||
def fuse_write(self, req, ino, buf, size, off, fi):
|
||||
buf_str = ctypes.string_at(buf, size)
|
||||
fi_dict = struct_to_dict(fi)
|
||||
self.write(req, ino, buf_str, off, fi_dict)
|
||||
|
||||
def fuse_flush(self, req, ino, fi):
|
||||
self.flush(req, ino, struct_to_dict(fi))
|
||||
|
||||
def fuse_release(self, req, ino, fi):
|
||||
self.release(req, ino, struct_to_dict(fi))
|
||||
|
||||
def fuse_fsync(self, req, ino, datasync, fi):
|
||||
self.fsyncdir(req, ino, datasync, struct_to_dict(fi))
|
||||
|
||||
def fuse_opendir(self, req, ino, fi):
|
||||
self.opendir(req, ino, struct_to_dict(fi))
|
||||
|
||||
def fuse_readdir(self, req, ino, size, off, fi):
|
||||
self.readdir(req, ino, size, off, struct_to_dict(fi))
|
||||
|
||||
def fuse_releasedir(self, req, ino, fi):
|
||||
self.releasedir(req, ino, struct_to_dict(fi))
|
||||
|
||||
def fuse_fsyncdir(self, req, ino, datasync, fi):
|
||||
self.fsyncdir(req, ino, datasync, struct_to_dict(fi))
|
||||
|
||||
def fuse_setxattr(self, req, ino, name, value, size, flags):
|
||||
self.setxattr(req, ino, name.decode(self.encoding), ctypes.string_at(value, size), flags)
|
||||
|
||||
def fuse_getxattr(self, req, ino, name, size):
|
||||
self.getxattr(req, ino, name.decode(self.encoding), size)
|
||||
|
||||
def fuse_removexattr(self, req, ino, name):
|
||||
self.removexattr(req, ino, name.decode(self.encoding))
|
||||
|
||||
def fuse_create(self, req, parent, name, mode, fi):
|
||||
self.create(req, parent, name.decode(self.encoding), mode, struct_to_dict(fi))
|
||||
|
||||
# Utility methods
|
||||
|
||||
def req_ctx(self, req):
|
||||
ctx = self.libfuse.fuse_req_ctx(req)
|
||||
return struct_to_dict(ctx)
|
||||
|
||||
|
||||
# Methods to be overridden in subclasses.
|
||||
# Reply with the self.reply_* methods.
|
||||
|
||||
def init(self, userdata, conn):
|
||||
"""Initialize filesystem
|
||||
|
||||
There's no reply to this method
|
||||
"""
|
||||
pass
|
||||
|
||||
def destroy(self, userdata):
|
||||
"""Clean up filesystem
|
||||
|
||||
There's no reply to this method
|
||||
"""
|
||||
pass
|
||||
|
||||
def lookup(self, req, parent, name):
|
||||
"""Look up a directory entry by name and get its attributes.
|
||||
|
||||
Valid replies:
|
||||
reply_entry
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.ENOENT)
|
||||
|
||||
def forget(self, req, ino, nlookup):
|
||||
"""Forget about an inode
|
||||
|
||||
Valid replies:
|
||||
reply_none
|
||||
"""
|
||||
self.reply_none(req)
|
||||
|
||||
def getattr(self, req, ino, fi):
|
||||
"""Get file attributes
|
||||
|
||||
Valid replies:
|
||||
reply_attr
|
||||
reply_err
|
||||
"""
|
||||
if ino == 1:
|
||||
attr = {'st_ino': 1, 'st_mode': S_IFDIR | 0o755, 'st_nlink': 2}
|
||||
self.reply_attr(req, attr, 1.0)
|
||||
else:
|
||||
self.reply_err(req, errno.ENOENT)
|
||||
|
||||
def setattr(self, req, ino, attr, to_set, fi):
|
||||
"""Set file attributes
|
||||
|
||||
Valid replies:
|
||||
reply_attr
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.EROFS)
|
||||
|
||||
def readlink(self, req, ino):
|
||||
"""Read symbolic link
|
||||
|
||||
Valid replies:
|
||||
reply_readlink
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.ENOENT)
|
||||
|
||||
def mknod(self, req, parent, name, mode, rdev):
|
||||
"""Create file node
|
||||
|
||||
Valid replies:
|
||||
reply_entry
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.EROFS)
|
||||
|
||||
def mkdir(self, req, parent, name, mode):
|
||||
"""Create a directory
|
||||
|
||||
Valid replies:
|
||||
reply_entry
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.EROFS)
|
||||
|
||||
def unlink(self, req, parent, name):
|
||||
"""Remove a file
|
||||
|
||||
Valid replies:
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.EROFS)
|
||||
|
||||
def rmdir(self, req, parent, name):
|
||||
"""Remove a directory
|
||||
|
||||
Valid replies:
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.EROFS)
|
||||
|
||||
def symlink(self, req, link, parent, name):
|
||||
"""Create a symbolic link
|
||||
|
||||
Valid replies:
|
||||
reply_entry
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.EROFS)
|
||||
|
||||
def rename(self, req, parent, name, newparent, newname):
|
||||
"""Rename a file
|
||||
|
||||
Valid replies:
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.EROFS)
|
||||
|
||||
def link(self, req, ino, newparent, newname):
|
||||
"""Create a hard link
|
||||
|
||||
Valid replies:
|
||||
reply_entry
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.EROFS)
|
||||
|
||||
def open(self, req, ino, fi):
|
||||
"""Open a file
|
||||
|
||||
Valid replies:
|
||||
reply_open
|
||||
reply_err
|
||||
"""
|
||||
self.reply_open(req, fi)
|
||||
|
||||
def read(self, req, ino, size, off, fi):
|
||||
"""Read data
|
||||
|
||||
Valid replies:
|
||||
reply_buf
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.EIO)
|
||||
|
||||
def write(self, req, ino, buf, off, fi):
|
||||
"""Write data
|
||||
|
||||
Valid replies:
|
||||
reply_write
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.EROFS)
|
||||
|
||||
def flush(self, req, ino, fi):
|
||||
"""Flush method
|
||||
|
||||
Valid replies:
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, 0)
|
||||
|
||||
def release(self, req, ino, fi):
|
||||
"""Release an open file
|
||||
|
||||
Valid replies:
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, 0)
|
||||
|
||||
def fsync(self, req, ino, datasync, fi):
|
||||
"""Synchronize file contents
|
||||
|
||||
Valid replies:
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, 0)
|
||||
|
||||
def opendir(self, req, ino, fi):
|
||||
"""Open a directory
|
||||
|
||||
Valid replies:
|
||||
reply_open
|
||||
reply_err
|
||||
"""
|
||||
self.reply_open(req, fi)
|
||||
|
||||
def readdir(self, req, ino, size, off, fi):
|
||||
"""Read directory
|
||||
|
||||
Valid replies:
|
||||
reply_readdir
|
||||
reply_err
|
||||
"""
|
||||
if ino == 1:
|
||||
attr = {'st_ino': 1, 'st_mode': S_IFDIR}
|
||||
entries = [('.', attr), ('..', attr)]
|
||||
self.reply_readdir(req, size, off, entries)
|
||||
else:
|
||||
self.reply_err(req, errno.ENOENT)
|
||||
|
||||
def releasedir(self, req, ino, fi):
|
||||
"""Release an open directory
|
||||
|
||||
Valid replies:
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, 0)
|
||||
|
||||
def fsyncdir(self, req, ino, datasync, fi):
|
||||
"""Synchronize directory contents
|
||||
|
||||
Valid replies:
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, 0)
|
||||
|
||||
def statfs(self, req, ino):
|
||||
""" Get file system statistics
|
||||
|
||||
Valid replies:
|
||||
reply_statfs
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.ENOSYS)
|
||||
|
||||
def setxattr(self, req, ino, name, value, flags):
|
||||
""" Set an extended attribute
|
||||
|
||||
Valid replies:
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.ENOSYS)
|
||||
|
||||
def getxattr(self, req, ino, name, size):
|
||||
""" Set an extended attribute
|
||||
|
||||
Valid replies:
|
||||
reply_buf
|
||||
reply_data
|
||||
reply_xattr
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.ENOSYS)
|
||||
|
||||
def listxattr(self, req, ino, size):
|
||||
"""List extended attribute names
|
||||
|
||||
Valid replies:
|
||||
reply_buf
|
||||
reply_data
|
||||
reply_xattr
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.ENOSYS)
|
||||
|
||||
def removexattr(self, req, ino, name):
|
||||
"""Remove an extended attribute
|
||||
|
||||
Valid replies:
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.ENOSYS)
|
||||
|
||||
def access(self, req, ino, mask):
|
||||
"""Check file access permissions
|
||||
|
||||
Valid replies:
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.ENOSYS)
|
||||
|
||||
def create(self, req, parent, name, mode, fi):
|
||||
"""Create and open a file
|
||||
|
||||
Valid replies:
|
||||
reply_create
|
||||
reply_err
|
||||
"""
|
||||
self.reply_err(req, errno.ENOSYS)
|
Loading…
Reference in New Issue
Block a user