@@ -742,9 +742,61 @@ class c_flock_t(ctypes.Structure): # type: ignore
742742# - 3.14.1 -> 3.16.2: no change
743743_fuse_int32 = ctypes .c_int32 if (fuse_version_major , fuse_version_minor ) >= (3 , 17 ) else ctypes .c_int
744744_fuse_uint32 = ctypes .c_uint32 if (fuse_version_major , fuse_version_minor ) >= (3 , 17 ) else ctypes .c_uint
745- if fuse_version_major == 2 :
745+ _fuse_file_info_fields_ : list [FieldsEntry ] = []
746+ if _system == 'NetBSD' :
747+ # NetBSD has its own FUSE library reimplementation with mismatching struct layouts!
748+ # writepage is a bitfield (as in libFUSE 3.x), but the fh_old member still exists and the reported version is 2.9!
749+ # https://www.netbsd.org/docs/puffs/
750+ # https://github.com/NetBSD/src/blob/netbsd-11/lib/librefuse/fuse.h#L100-L129
751+ # https://github.com/NetBSD/src/blob/netbsd-10/lib/librefuse/fuse.h#L100-L129
752+ # - fuse_file_info is unchanged between 10 and 11
753+ # - FUSE_USE_VERSION is not set, but is set to _REFUSE_VERSION_ (3.10) with a warning if not set!
754+ # - However, the CI prints FUSE version 2.9?!
755+ # - Seems there is no sane way to get the correct compiled version! This is again an absolute shit show!
756+ # https://github.com/NetBSD/src/blob/netbsd-9/lib/librefuse/fuse.h#L51-L61
757+ # - fuse_file_info looks quite different and version is specified as 2.6!
758+ # - #define FUSE_USE_VERSION 26
759+ fuse_version = (fuse_version_major , fuse_version_minor )
760+ _fuse_file_info_fields_ = [
761+ ('flags' , ctypes .c_int32 ),
762+ ('fh_old' , ctypes .c_uint32 ),
763+ ]
764+
765+ _fuse_file_info_fields_bitfield : list [FieldsEntry ] = []
766+
767+ if fuse_version >= (2 , 9 ):
768+ _fuse_file_info_fields_bitfield += [('writepage' , ctypes .c_int32 , 1 )]
769+ else :
770+ _fuse_file_info_fields_ += [('writepage' , ctypes .c_int32 )]
771+
772+ _fuse_file_info_fields_bitfield += [
773+ ('direct_io' , ctypes .c_uint32 , 1 ), # Introduced in FUSE 2.4
774+ ('keep_cache' , ctypes .c_uint32 , 1 ), # Introduced in FUSE 2.4
775+ ('flush' , ctypes .c_uint32 , 1 ), # Introduced in FUSE 2.6
776+ ]
777+ if fuse_version >= (2 , 9 ):
778+ _fuse_file_info_fields_bitfield += [
779+ ('nonseekable' , ctypes .c_uint , 1 ), # Introduced in FUSE 2.8
780+ ('flock_release' , ctypes .c_uint , 1 ), # Introduced in FUSE 2.9
781+ ('cache_readdir' , ctypes .c_uint , 1 ), # Introduced in FUSE 3.5
782+ ]
783+
784+ _fuse_file_info_flag_count = sum (x [2 ] for x in _fuse_file_info_fields_bitfield )
785+ assert _fuse_file_info_flag_count < ctypes .sizeof (_fuse_uint32 ) * 8
786+
787+ _fuse_file_info_fields_ += _fuse_file_info_fields_bitfield
788+ _fuse_file_info_fields_ += [
789+ ('padding' , _fuse_uint32 , ctypes .sizeof (_fuse_uint32 ) * 8 - _fuse_file_info_flag_count ),
790+ ('fh' , ctypes .c_uint64 ),
791+ ('lock_owner' , ctypes .c_uint64 ),
792+ ]
793+
794+ if fuse_version >= (2 , 9 ):
795+ _fuse_file_info_fields_ += [('poll_events' , ctypes .c_uint32 )]
796+
797+ elif fuse_version_major == 2 :
746798 _fh_old_type = ctypes .c_uint if _system == 'OpenBSD' else ctypes .c_ulong
747- _fuse_file_info_fields_ : list [ FieldsEntry ] = [
799+ _fuse_file_info_fields_ = [
748800 ('flags' , ctypes .c_int ),
749801 ('fh_old' , _fh_old_type ),
750802 ('writepage' , ctypes .c_int ),
@@ -972,7 +1024,8 @@ class fuse_conn_info(ctypes.Structure): # Added in 2.6 (ABI break of "init" fro
9721024 # Another ABI break as discussed here: https://lists.debian.org/debian-devel/2024/03/msg00278.html
9731025 # The break was in 3.14.1 NOT in 3.14.0, but I cannot query the bugfix version.
9741026 # I'd hope that all 3.14.0 installations have been replaced by updates to 3.14.1.
975- if fuse_version_minor >= 14 and fuse_version_minor < 17 :
1027+ # ... they have not. My own system, Ubuntu 24.04 uses fuse 3.14.0. Check for >= 3.15.
1028+ if fuse_version_minor >= 15 and fuse_version_minor < 17 :
9761029 _fuse_config_fields_ += [('parallel_direct_writes' , ctypes .c_int )]
9771030
9781031 _fuse_config_fields_ += [
0 commit comments