Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 51 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,9 @@ jobs:
- os: netbsd
version: '10.1'
display_name: NetBSD

- os: omnios
version: r151056
display_name: OmniOS

steps:
- name: Check out repository
Expand All @@ -225,7 +227,7 @@ jobs:
fetch-tags: true

- name: Test on ${{ matrix.display_name }}
uses: cross-platform-actions/action@v0.29.0
uses: cross-platform-actions/action@v0.32.0
with:
operating_system: ${{ matrix.os }}
version: ${{ matrix.version }}
Expand Down Expand Up @@ -320,4 +322,51 @@ jobs:
sudo -E python3 -m pytest -s -v -rs tests || rc=$?
exit "$rc"
;;
omnios)
# Ensure a proper hostname/FQDN is set (VMs may not have one by default)
pfexec /bin/sh -c 'grep -q "omnios\.local" /etc/hosts || echo "127.0.0.1 omnios.local omnios" >> /etc/hosts'
pfexec hostname omnios.local
hostname

# Packages
pfexec pkg install developer/versioning/git
pfexec pkg install developer/gcc14
pfexec pkg set-mediator -V 14 gcc

# driver + libfuse
pfexec pkg set-publisher -p https://sfe.opencsw.org/localhostomnios localhostomnios
pfexec pkg refresh localhostomnios
pfexec pkg install --accept system/file-system/fusefs
pfexec pkg install --accept system/file-system/libfuse
pkg list system/file-system/fusefs
pkg list system/file-system/libfuse
pkg contents system/file-system/fusefs
pkg contents system/file-system/libfuse

# Fetch custom build from Tom and install it
modinfo | grep fuse | awk '{print $1}' | while read id; do pfexec modunload -i $id; done
modinfo | grep fuse || true
curl -L https://www.wagner-net.com/~tom/fuse-files-sfe-omnios-r151054-f66c95f374.tar.bz2 -o /tmp/fuse-files.tar.bz2
pushd /
pfexec tar xvjf /tmp/fuse-files.tar.bz2
popd
ls -l /usr/gnu/lib/amd64/libfuse.so.2.7.1 /usr/gnu/lib/libfuse.so.2.7.1 /usr/kernel/drv/amd64/fuse

# Install pip Dependencies
python3 -m pip install pytest pytest-order ioctl-opt

# Fix PATH
export PATH="/home/runner/.local/bin:$PATH"
echo $PATH

# Test Installation From Source
python3 -m pip install .

# Unit Tests (FUSE 2)
python3 -c 'import mfusepy; assert mfusepy.fuse_version_major == 2'
# preserve pytest exit status, always show logs
rc=0
pfexec python3 -m pytest -v -rs tests || rc=$?
exit "$rc"
;;
esac
88 changes: 83 additions & 5 deletions mfusepy.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,22 @@ def reg32_get_value(rootkey, keyname, valname):
arch = "x64" if sys.maxsize > 0xFFFFFFFF else "x86"
_libfuse_path += f"bin\\winfsp-{arch}.dll"
# pytype: enable=module-attr
elif _system == 'SunOS':
_libfuse_path = find_library('fuse') or find_library('fuse3')
if not _libfuse_path:
for path in [
'/usr/gnu/lib/amd64/libfuse.so',
'/usr/gnu/lib/libfuse.so',
'/usr/lib/amd64/libfuse.so.2',
'/usr/lib/libfuse.so.2',
'/usr/lib/amd64/libfuse.so',
'/usr/lib/libfuse.so',
'/lib/amd64/libfuse.so.2',
'/lib/libfuse.so.2',
]:
if os.path.exists(path):
_libfuse_path = path
break
elif _libfuse_name := os.environ.get('FUSE_LIBRARY_NAME'):
_libfuse_path = find_library(_libfuse_name)
else:
Expand Down Expand Up @@ -588,6 +604,47 @@ def get_fuse_version(libfuse):
('st_gen', ctypes.c_uint32),
('st_spare', ctypes.c_uint32 * 2),
]
elif _system == 'SunOS':
ENOTSUP = 48
c_dev_t = ctypes.c_uint64
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
setxattr_t = ctypes.CFUNCTYPE(
ctypes.c_int,
ctypes.c_char_p,
ctypes.c_char_p,
c_byte_p,
ctypes.c_size_t,
ctypes.c_int,
)
getxattr_t = ctypes.CFUNCTYPE(
ctypes.c_int,
ctypes.c_char_p,
ctypes.c_char_p,
c_byte_p,
ctypes.c_size_t,
)
c_fsblkcnt_t = ctypes.c_uint64
c_fsfilcnt_t = ctypes.c_uint64
_c_stat__fields_ = [
('st_dev', c_dev_t),
('st_ino', ctypes.c_uint64),
('st_mode', c_mode_t),
('st_nlink', ctypes.c_uint32),
('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_int32),
('st_blocks', ctypes.c_int64),
('st_fstype', ctypes.c_char * 16),
]
else:
raise NotImplementedError(_system + ' is not supported.')

Expand Down Expand Up @@ -677,6 +734,23 @@ class c_statvfs(ctypes.Structure):
('f_mntfromname', ctypes.c_char * 1024),
('f_mntfromlabel', ctypes.c_char * 1024),
]
elif _system == 'SunOS':
# Source: /usr/include/sys/statvfs.h
_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),
('f_basetype', ctypes.c_char * 16),
('f_flag', ctypes.c_ulong),
('f_namemax', ctypes.c_ulong),
('f_fstr', ctypes.c_char * 32),
]
else:
# https://sourceware.org/git?p=glibc.git;a=blob;f=bits/statvfs.h;h=ea89d9004d834c81874de00b5e3f5617d3096ccc;hb=HEAD#l33
_fields_ = [
Expand Down Expand Up @@ -880,12 +954,16 @@ class fuse_context(ctypes.Structure):
('gid', c_gid_t),
('pid', c_pid_t),
('private_data', ctypes.c_void_p),
# Added in 2.8. Note that this is an ABI break because programs compiled against 2.7
# will allocate a smaller struct leading to out-of-bound accesses when used for a 2.8
# shared library! It shouldn't hurt the other way around to have a larger struct than
# the shared library expects. The newer members will simply be ignored.
('umask', c_mode_t),
]
# OpenBSD announces 2.6, but still has the umask struct member.
if fuse_version_major == 3 or (fuse_version_major == 2 and fuse_version_minor >= 8) or _system == 'OpenBSD':
_fields_ += [
# Added in 2.8. Note that this is an ABI break because programs compiled against 2.7
# will allocate a smaller struct leading to out-of-bound accesses when used for a 2.8
# shared library! It shouldn't hurt the other way around to have a larger struct than
# the shared library expects. The newer members will simply be ignored.
('umask', c_mode_t),
]


_libfuse.fuse_get_context.restype = ctypes.POINTER(fuse_context)
Expand Down
26 changes: 26 additions & 0 deletions tests/test_struct_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,31 @@
if platform.system() != 'NetBSD':
STRUCT_NAMES['fuse_file_info'] = ['flags', 'fh', 'lock_owner']

if platform.system() == 'SunOS':
STRUCT_NAMES['statvfs'] = [
'f_bavail',
'f_bfree',
'f_blocks',
'f_bsize',
'f_favail',
'f_ffree',
'f_files',
'f_flag',
'f_frsize',
'f_fsid',
'f_namemax',
'f_basetype', # SunOS only
'f_fstr', # SunOS only
]
STRUCT_NAMES['fuse_context'] = ['fuse', 'uid', 'gid', 'pid'] # no 'umask' on SunOS
STRUCT_NAMES['fuse_conn_info'] = [
'proto_major',
'proto_minor',
'max_write',
'max_readahead',
# 4 attrs not present on SunOS
]

if mfusepy.fuse_version_major == 3:
STRUCT_NAMES['fuse_config'] = [
'set_gid',
Expand Down Expand Up @@ -178,6 +203,7 @@ def c_run(name: str, source: str) -> str:
'/usr/local/include/osxfuse/fuse',
'/usr/local/include/macfuse/fuse',
'/usr/include/libfuse',
'/usr/gnu/include/fuse',
]
if mfusepy.fuse_version_major == 3:
include_paths += ['/usr/local/include/fuse3', '/usr/include/fuse3']
Expand Down