diff options
Diffstat (limited to 'src/3rdparty/python/lib/python3.9/site-packages/mac_alias/osx.py')
-rw-r--r-- | src/3rdparty/python/lib/python3.9/site-packages/mac_alias/osx.py | 1074 |
1 files changed, 1074 insertions, 0 deletions
diff --git a/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/osx.py b/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/osx.py new file mode 100644 index 000000000..1b2feabaa --- /dev/null +++ b/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/osx.py @@ -0,0 +1,1074 @@ +import datetime +import os +import uuid +from ctypes import ( + POINTER, + Structure, + Union, + byref, + c_byte, + c_char, + c_char_p, + c_int, + c_long, + c_longlong, + c_short, + c_uint, + c_ulong, + c_ulonglong, + c_ushort, + c_void_p, + cdll, + create_string_buffer, + sizeof, +) + +from .utils import unix_epoch + +libc = cdll.LoadLibrary("/usr/lib/libc.dylib") + +# Constants +FSOPT_NOFOLLOW = 0x00000001 +FSOPT_NOINMEMUPDATE = 0x00000002 +FSOPT_REPORT_FULLSIZE = 0x00000004 +FSOPT_PACK_INVAL_ATTRS = 0x00000008 +FSOPT_ATTR_CMN_EXTENDED = 0x00000020 +FSOPT_RETURN_REALDEV = 0x00000200 + +VOL_CAPABILITIES_FORMAT = 0 +VOL_CAPABILITIES_INTERFACES = 1 + +VOL_CAP_FMT_PERSISTENTOBJECTIDS = 0x00000001 +VOL_CAP_FMT_SYMBOLICLINKS = 0x00000002 +VOL_CAP_FMT_HARDLINKS = 0x00000004 +VOL_CAP_FMT_JOURNAL = 0x00000008 +VOL_CAP_FMT_JOURNAL_ACTIVE = 0x00000010 +VOL_CAP_FMT_NO_ROOT_TIMES = 0x00000020 +VOL_CAP_FMT_SPARSE_FILES = 0x00000040 +VOL_CAP_FMT_ZERO_RUNS = 0x00000080 +VOL_CAP_FMT_CASE_SENSITIVE = 0x00000100 +VOL_CAP_FMT_CASE_PRESERVING = 0x00000200 +VOL_CAP_FMT_FAST_STATFS = 0x00000400 +VOL_CAP_FMT_2TB_FILESIZE = 0x00000800 +VOL_CAP_FMT_OPENDENYMODES = 0x00001000 +VOL_CAP_FMT_HIDDEN_FILES = 0x00002000 +VOL_CAP_FMT_PATH_FROM_ID = 0x00004000 +VOL_CAP_FMT_NO_VOLUME_SIZES = 0x00008000 +VOL_CAP_FMT_DECMPFS_COMPRESSION = 0x00010000 +VOL_CAP_FMT_64BIT_OBJECT_IDS = 0x00020000 + +VOL_CAP_INT_SEARCHFS = 0x00000001 +VOL_CAP_INT_ATTRLIST = 0x00000002 +VOL_CAP_INT_NFSEXPORT = 0x00000004 +VOL_CAP_INT_READDIRATTR = 0x00000008 +VOL_CAP_INT_EXCHANGEDATA = 0x00000010 +VOL_CAP_INT_COPYFILE = 0x00000020 +VOL_CAP_INT_ALLOCATE = 0x00000040 +VOL_CAP_INT_VOL_RENAME = 0x00000080 +VOL_CAP_INT_ADVLOCK = 0x00000100 +VOL_CAP_INT_FLOCK = 0x00000200 +VOL_CAP_INT_EXTENDED_SECURITY = 0x00000400 +VOL_CAP_INT_USERACCESS = 0x00000800 +VOL_CAP_INT_MANLOCK = 0x00001000 +VOL_CAP_INT_NAMEDSTREAMS = 0x00002000 +VOL_CAP_INT_EXTENDED_ATTR = 0x00004000 +VOL_CAP_INT_CLONE = 0x00010000 +VOL_CAP_INT_SNAPSHOT = 0x00020000 +VOL_CAP_INT_RENAME_SWAP = 0x00040000 +VOL_CAP_INT_RENAME_EXCL = 0x00080000 +VOL_CAP_INT_RENAME_OPENFAIL = 0x00100000 + +ATTR_CMN_NAME = 0x00000001 +ATTR_CMN_DEVID = 0x00000002 +ATTR_CMN_FSID = 0x00000004 +ATTR_CMN_OBJTYPE = 0x00000008 +ATTR_CMN_OBJTAG = 0x00000010 +ATTR_CMN_OBJID = 0x00000020 +ATTR_CMN_OBJPERMANENTID = 0x00000040 +ATTR_CMN_PAROBJID = 0x00000080 +ATTR_CMN_SCRIPT = 0x00000100 +ATTR_CMN_CRTIME = 0x00000200 +ATTR_CMN_MODTIME = 0x00000400 +ATTR_CMN_CHGTIME = 0x00000800 +ATTR_CMN_ACCTIME = 0x00001000 +ATTR_CMN_BKUPTIME = 0x00002000 +ATTR_CMN_FNDRINFO = 0x00004000 +ATTR_CMN_OWNERID = 0x00008000 +ATTR_CMN_GRPID = 0x00010000 +ATTR_CMN_ACCESSMASK = 0x00020000 +ATTR_CMN_FLAGS = 0x00040000 +ATTR_CMN_GEN_COUNT = 0x00080000 +ATTR_CMN_DOCUMENT_ID = 0x00100000 +ATTR_CMN_USERACCESS = 0x00200000 +ATTR_CMN_EXTENDED_SECURITY = 0x00400000 +ATTR_CMN_UUID = 0x00800000 +ATTR_CMN_GRPUUID = 0x01000000 +ATTR_CMN_FILEID = 0x02000000 +ATTR_CMN_PARENTID = 0x04000000 +ATTR_CMN_FULLPATH = 0x08000000 +ATTR_CMN_ADDEDTIME = 0x10000000 +ATTR_CMN_ERROR = 0x20000000 +ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000 +ATTR_CMN_RETURNED_ATTRS = 0x80000000 +ATTR_CMN_ALL_ATTRS = 0xFFFFFFFF + +ATTR_CMN_VALIDMASK = 0xFFFFFFFF +ATTR_CMN_SETMASK = 0x51C7FF00 +ATTR_CMN_VOLSETMASK = 0x00006700 + +ATTR_VOL_FSTYPE = 0x00000001 +ATTR_VOL_SIGNATURE = 0x00000002 +ATTR_VOL_SIZE = 0x00000004 +ATTR_VOL_SPACEFREE = 0x00000008 +ATTR_VOL_SPACEAVAIL = 0x00000010 +ATTR_VOL_MINALLOCATION = 0x00000020 +ATTR_VOL_ALLOCATIONCLUMP = 0x00000040 +ATTR_VOL_IOBLOCKSIZE = 0x00000080 +ATTR_VOL_OBJCOUNT = 0x00000100 +ATTR_VOL_FILECOUNT = 0x00000200 +ATTR_VOL_DIRCOUNT = 0x00000400 +ATTR_VOL_MAXOBJCOUNT = 0x00000800 +ATTR_VOL_MOUNTPOINT = 0x00001000 +ATTR_VOL_NAME = 0x00002000 +ATTR_VOL_MOUNTFLAGS = 0x00004000 +ATTR_VOL_MOUNTEDDEVICE = 0x00008000 +ATTR_VOL_ENCODINGSUSED = 0x00010000 +ATTR_VOL_CAPABILITIES = 0x00020000 +ATTR_VOL_UUID = 0x00040000 +ATTR_VOL_QUOTA_SIZE = 0x10000000 +ATTR_VOL_RESERVED_SIZE = 0x20000000 +ATTR_VOL_ATTRIBUTES = 0x40000000 +ATTR_VOL_INFO = 0x80000000 +ATTR_VOL_ALL_ATTRS = 0xF007FFFF + +ATTR_DIR_LINKCOUNT = 0x00000001 +ATTR_DIR_ENTRYCOUNT = 0x00000002 +ATTR_DIR_MOUNTSTATUS = 0x00000004 +DIR_MNTSTATUS_MNTPOINT = 0x00000001 +DIR_MNTSTATUS_TRIGGER = 0x00000002 +ATTR_DIR_ALLOCSIZE = 0x00000008 +ATTR_DIR_IOBLOCKSIZE = 0x00000010 +ATTR_DIR_DATALENGTH = 0x00000020 +ATTR_DIR_ALL_ATTRS = 0x0000003F + +ATTR_DIR_VALIDMASK = 0x0000003F +ATTR_DIR_SETMASK = 0x00000000 + +ATTR_FILE_LINKCOUNT = 0x00000001 +ATTR_FILE_TOTALSIZE = 0x00000002 +ATTR_FILE_ALLOCSIZE = 0x00000004 +ATTR_FILE_IOBLOCKSIZE = 0x00000008 +ATTR_FILE_DEVTYPE = 0x00000020 +ATTR_FILE_FORKCOUNT = 0x00000080 +ATTR_FILE_FORKLIST = 0x00000100 +ATTR_FILE_DATALENGTH = 0x00000200 +ATTR_FILE_DATAALLOCSIZE = 0x00000400 +ATTR_FILE_RSRCLENGTH = 0x00001000 +ATTR_FILE_RSRCALLOCSIZE = 0x00002000 +ATTR_FILE_ALL_ATTRS = 0x000037FF + +ATTR_FILE_VALIDMASK = 0x000037FF +ATTR_FILE_SETMASK = 0x00000020 + +# These are deprecated +ATTR_FORK_TOTALSIZE = 0x00000001 +ATTR_FORK_ALLOCSIZE = 0x00000002 +ATTR_FORK_ALL_ATTRS = 0x00000003 + +# These go in the fork attribute field +ATTR_CMNEXT_RELPATH = 0x00000004 +ATTR_CMNEXT_PRIVATESIZE = 0x00000008 +ATTR_CMNEXT_LINKID = 0x0000010 +ATTR_CMNEXT_NOFIRMLINKPATH = 0x00000020 +ATTR_CMNEXT_REALDEVID = 0x00000040 +ATTR_CMNEXT_REALFSID = 0x00000080 +ATTR_CMNEXT_CLONEID = 0x00000100 +ATTR_CMNEXT_EXT_FLAGS = 0x00000200 +ATTR_CMNEXT_RECURSIVE_GENCOUNT = 0x00000400 +ATTR_CMNEXT_ALL_ATTRS = 0x000007FC + +ATTR_CMNEXT_VALIDMASK = 0x000007FC +ATTR_CMNEXT_SETMASK = 0x00000000 + +ATTR_FORK_VALIDMASK = 0x00000003 +ATTR_FORK_SETMASK = 0x00000000 + +# These can't be used +ATTR_CMN_NAMEDATTRCOUNT = 0x00080000 +ATTR_CMN_NAMEDATTRLIST = 0x00100000 +ATTR_FILE_CLUMPSIZE = 0x00000010 +ATTR_FILE_FILETYPE = 0x00000040 +ATTR_FILE_DATAEXTENTS = 0x00000800 +ATTR_FILE_RSRCEXTENTS = 0x00004000 + + +class attrlist(Structure): + _fields_ = [ + ("bitmapcount", c_ushort), + ("reserved", c_ushort), + ("commonattr", c_uint), + ("volattr", c_uint), + ("dirattr", c_uint), + ("fileattr", c_uint), + ("forkattr", c_uint), + ] + + +class attribute_set_t(Structure): + _fields_ = [ + ("commonattr", c_uint), + ("volattr", c_uint), + ("dirattr", c_uint), + ("fileattr", c_uint), + ("forkattr", c_uint), + ] + + +class fsobj_id_t(Structure): + _fields_ = [ + ("fid_objno", c_uint), + ("fid_generation", c_uint), + ] + + +class timespec(Structure): + _fields_ = [ + ("tv_sec", c_long), + ("tv_nsec", c_long), + ] + + +class attrreference_t(Structure): + _fields_ = [ + ("attr_dataoffset", c_int), + ("attr_length", c_uint), + ] + + +class fsid_t(Structure): + _fields_ = [ + ("val", c_uint * 2), + ] + + +class guid_t(Structure): + _fields_ = [ + ("g_guid", c_byte * 16), + ] + + +class kauth_ace(Structure): + _fields_ = [ + ("ace_applicable", guid_t), + ("ace_flags", c_uint), + ] + + +class kauth_acl(Structure): + _fields_ = [ + ("acl_entrycount", c_uint), + ("acl_flags", c_uint), + ("acl_ace", kauth_ace * 128), + ] + + +class kauth_filesec(Structure): + _fields_ = [ + ("fsec_magic", c_uint), + ("fsec_owner", guid_t), + ("fsec_group", guid_t), + ("fsec_acl", kauth_acl), + ] + + +class diskextent(Structure): + _fields_ = [ + ("startblock", c_uint), + ("blockcount", c_uint), + ] + + +OSType = c_uint +UInt16 = c_ushort +SInt16 = c_short +SInt32 = c_int + + +class Point(Structure): + _fields_ = [ + ("x", SInt16), + ("y", SInt16), + ] + + +class Rect(Structure): + _fields_ = [ + ("x", SInt16), + ("y", SInt16), + ("w", SInt16), + ("h", SInt16), + ] + + +class FileInfo(Structure): + _fields_ = [ + ("fileType", OSType), + ("fileCreator", OSType), + ("finderFlags", UInt16), + ("location", Point), + ("reservedField", UInt16), + ("reserved1", SInt16 * 4), + ("extendedFinderFlags", UInt16), + ("reserved2", SInt16), + ("putAwayFolderID", SInt32), + ] + + +class FolderInfo(Structure): + _fields_ = [ + ("windowBounds", Rect), + ("finderFlags", UInt16), + ("location", Point), + ("reservedField", UInt16), + ("scrollPosition", Point), + ("reserved1", SInt32), + ("extendedFinderFlags", UInt16), + ("reserved2", SInt16), + ("putAwayFolderID", SInt32), + ] + + +class FinderInfo(Union): + _fields_ = [ + ("fileInfo", FileInfo), + ("folderInfo", FolderInfo), + ] + + +extentrecord = diskextent * 8 +vol_capabilities_set_t = c_uint * 4 + + +class vol_capabilities_attr_t(Structure): + _fields_ = [ + ("capabilities", vol_capabilities_set_t), + ("valid", vol_capabilities_set_t), + ] + + +class vol_attributes_attr_t(Structure): + _fields_ = [ + ("validattr", attribute_set_t), + ("nativeattr", attribute_set_t), + ] + + +dev_t = c_uint + +fsobj_type_t = c_uint + +VNON = 0 +VREG = 1 +VDIR = 2 +VBLK = 3 +VCHR = 4 +VLNK = 5 +VSOCK = 6 +VFIFO = 7 +VBAD = 8 +VSTR = 9 +VCPLX = 10 + +fsobj_tag_t = c_uint + +VT_NON = 0 +VT_UFS = 1 +VT_NFS = 2 +VT_MFS = 3 +VT_MSDOSFS = 4 +VT_LFS = 5 +VT_LOFS = 6 +VT_FDESC = 7 +VT_PORTAL = 8 +VT_NULL = 9 +VT_UMAP = 10 +VT_KERNFS = 11 +VT_PROCFS = 12 +VT_AFS = 13 +VT_ISOFS = 14 +VT_UNION = 15 +VT_HFS = 16 +VT_ZFS = 17 +VT_DEVFS = 18 +VT_WEBDAV = 19 +VT_UDF = 20 +VT_AFP = 21 +VT_CDDA = 22 +VT_CIFS = 23 +VT_OTHER = 24 + +fsfile_type_t = c_uint +fsvolid_t = c_uint +text_encoding_t = c_uint +uid_t = c_uint +gid_t = c_uint +int32_t = c_int +uint32_t = c_uint +int64_t = c_longlong +uint64_t = c_ulonglong +off_t = c_long +size_t = c_ulong +uuid_t = c_byte * 16 + +NAME_MAX = 255 +PATH_MAX = 1024 +FSTYPE_MAX = 16 + + +class struct_statfs(Structure): + _fields_ = [ + ("f_bsize", uint32_t), + ("f_iosize", int32_t), + ("f_blocks", uint64_t), + ("f_bfree", uint64_t), + ("f_bavail", uint64_t), + ("f_files", uint64_t), + ("f_ffree", uint64_t), + ("f_fsid", fsid_t), + ("f_owner", uid_t), + ("f_type", uint32_t), + ("f_flags", uint32_t), + ("f_fssubtype", uint32_t), + ("f_fstypename", c_char * FSTYPE_MAX), + ("f_mntonname", c_char * PATH_MAX), + ("f_mntfromname", c_char * PATH_MAX), + ("f_flags_ext", uint32_t), + ("f_reserved", uint32_t * 7), + ] + + +# Calculate the maximum number of bytes required for the attribute buffer +_attr_info = ( + # Common attributes + (0, ATTR_CMN_RETURNED_ATTRS, sizeof(attribute_set_t)), + (0, ATTR_CMN_NAME, sizeof(attrreference_t) + NAME_MAX * 3 + 1), + (0, ATTR_CMN_DEVID, sizeof(dev_t)), + (0, ATTR_CMN_FSID, sizeof(fsid_t)), + (0, ATTR_CMN_OBJTYPE, sizeof(fsobj_type_t)), + (0, ATTR_CMN_OBJTAG, sizeof(fsobj_tag_t)), + (0, ATTR_CMN_OBJID, sizeof(fsobj_id_t)), + (0, ATTR_CMN_OBJPERMANENTID, sizeof(fsobj_id_t)), + (0, ATTR_CMN_PAROBJID, sizeof(fsobj_id_t)), + (0, ATTR_CMN_SCRIPT, sizeof(text_encoding_t)), + (0, ATTR_CMN_CRTIME, sizeof(timespec)), + (0, ATTR_CMN_MODTIME, sizeof(timespec)), + (0, ATTR_CMN_CHGTIME, sizeof(timespec)), + (0, ATTR_CMN_ACCTIME, sizeof(timespec)), + (0, ATTR_CMN_BKUPTIME, sizeof(timespec)), + (0, ATTR_CMN_FNDRINFO, sizeof(FinderInfo)), + (0, ATTR_CMN_OWNERID, sizeof(uid_t)), + (0, ATTR_CMN_GRPID, sizeof(gid_t)), + (0, ATTR_CMN_ACCESSMASK, sizeof(uint32_t)), + (0, ATTR_CMN_NAMEDATTRCOUNT, None), + (0, ATTR_CMN_NAMEDATTRLIST, None), + (0, ATTR_CMN_FLAGS, sizeof(uint32_t)), + (0, ATTR_CMN_GEN_COUNT, sizeof(uint32_t)), + (0, ATTR_CMN_DOCUMENT_ID, sizeof(uint32_t)), + (0, ATTR_CMN_USERACCESS, sizeof(uint32_t)), + (0, ATTR_CMN_EXTENDED_SECURITY, sizeof(attrreference_t) + sizeof(kauth_filesec)), + (0, ATTR_CMN_UUID, sizeof(guid_t)), + (0, ATTR_CMN_GRPUUID, sizeof(guid_t)), + (0, ATTR_CMN_FILEID, sizeof(uint64_t)), + (0, ATTR_CMN_PARENTID, sizeof(uint64_t)), + (0, ATTR_CMN_FULLPATH, sizeof(attrreference_t) + PATH_MAX), + (0, ATTR_CMN_ADDEDTIME, sizeof(timespec)), + (0, ATTR_CMN_DATA_PROTECT_FLAGS, sizeof(uint32_t)), + # Volume attributes + (1, ATTR_VOL_FSTYPE, sizeof(uint32_t)), + (1, ATTR_VOL_SIGNATURE, sizeof(uint32_t)), + (1, ATTR_VOL_SIZE, sizeof(off_t)), + (1, ATTR_VOL_SPACEFREE, sizeof(off_t)), + (1, ATTR_VOL_SPACEAVAIL, sizeof(off_t)), + (1, ATTR_VOL_MINALLOCATION, sizeof(off_t)), + (1, ATTR_VOL_ALLOCATIONCLUMP, sizeof(off_t)), + (1, ATTR_VOL_IOBLOCKSIZE, sizeof(uint32_t)), + (1, ATTR_VOL_OBJCOUNT, sizeof(uint32_t)), + (1, ATTR_VOL_FILECOUNT, sizeof(uint32_t)), + (1, ATTR_VOL_DIRCOUNT, sizeof(uint32_t)), + (1, ATTR_VOL_MAXOBJCOUNT, sizeof(uint32_t)), + (1, ATTR_VOL_MOUNTPOINT, sizeof(attrreference_t) + PATH_MAX), + (1, ATTR_VOL_NAME, sizeof(attrreference_t) + NAME_MAX + 1), + (1, ATTR_VOL_MOUNTFLAGS, sizeof(uint32_t)), + (1, ATTR_VOL_MOUNTEDDEVICE, sizeof(attrreference_t) + PATH_MAX), + (1, ATTR_VOL_ENCODINGSUSED, sizeof(c_ulonglong)), + (1, ATTR_VOL_CAPABILITIES, sizeof(vol_capabilities_attr_t)), + (1, ATTR_VOL_UUID, sizeof(uuid_t)), + (1, ATTR_VOL_QUOTA_SIZE, sizeof(off_t)), + (1, ATTR_VOL_RESERVED_SIZE, sizeof(off_t)), + (1, ATTR_VOL_ATTRIBUTES, sizeof(vol_attributes_attr_t)), + # Directory attributes + (2, ATTR_DIR_LINKCOUNT, sizeof(uint32_t)), + (2, ATTR_DIR_ENTRYCOUNT, sizeof(uint32_t)), + (2, ATTR_DIR_MOUNTSTATUS, sizeof(uint32_t)), + (2, ATTR_DIR_ALLOCSIZE, sizeof(off_t)), + (2, ATTR_DIR_IOBLOCKSIZE, sizeof(uint32_t)), + (2, ATTR_DIR_DATALENGTH, sizeof(off_t)), + # File attributes + (3, ATTR_FILE_LINKCOUNT, sizeof(uint32_t)), + (3, ATTR_FILE_TOTALSIZE, sizeof(off_t)), + (3, ATTR_FILE_ALLOCSIZE, sizeof(off_t)), + (3, ATTR_FILE_IOBLOCKSIZE, sizeof(uint32_t)), + (3, ATTR_FILE_CLUMPSIZE, sizeof(uint32_t)), + (3, ATTR_FILE_DEVTYPE, sizeof(uint32_t)), + (3, ATTR_FILE_FILETYPE, sizeof(uint32_t)), + (3, ATTR_FILE_FORKCOUNT, sizeof(uint32_t)), + (3, ATTR_FILE_FORKLIST, None), + (3, ATTR_FILE_DATALENGTH, sizeof(off_t)), + (3, ATTR_FILE_DATAALLOCSIZE, sizeof(off_t)), + (3, ATTR_FILE_DATAEXTENTS, sizeof(extentrecord)), + (3, ATTR_FILE_RSRCLENGTH, sizeof(off_t)), + (3, ATTR_FILE_RSRCALLOCSIZE, sizeof(off_t)), + (3, ATTR_FILE_RSRCEXTENTS, sizeof(extentrecord)), + # Fork attributes + (4, ATTR_FORK_TOTALSIZE, sizeof(off_t)), + (4, ATTR_FORK_ALLOCSIZE, sizeof(off_t)), + # Extended common attributes + (4, ATTR_CMNEXT_RELPATH, sizeof(attrreference_t) + PATH_MAX), + (4, ATTR_CMNEXT_PRIVATESIZE, sizeof(off_t)), + (4, ATTR_CMNEXT_LINKID, sizeof(uint64_t)), + (4, ATTR_CMNEXT_NOFIRMLINKPATH, sizeof(attrreference_t) + PATH_MAX), + (4, ATTR_CMNEXT_REALDEVID, sizeof(dev_t)), + (4, ATTR_CMNEXT_REALFSID, sizeof(fsid_t)), + (4, ATTR_CMNEXT_CLONEID, sizeof(uint64_t)), + (4, ATTR_CMNEXT_EXT_FLAGS, sizeof(uint64_t)), +) + + +def _attrbuf_size(attrs): + size = 4 + for entry in _attr_info: + if attrs[entry[0]] & entry[1]: + if entry[2] is None: + raise ValueError( + "Unsupported attribute (%u, %x)" % (entry[0], entry[1]) + ) + size += entry[2] + return size + + +_getattrlist = libc.getattrlist +_getattrlist.argtypes = [c_char_p, POINTER(attrlist), c_void_p, c_ulong, c_ulong] +_getattrlist.restype = c_int + +_fgetattrlist = libc.fgetattrlist +_fgetattrlist.argtypes = [c_int, POINTER(attrlist), c_void_p, c_ulong, c_ulong] +_fgetattrlist.restype = c_int + +try: + _statfs = libc["statfs$INODE64"] +except (KeyError, AttributeError): + _statfs = libc["statfs"] + +_statfs.argtypes = [ + c_char_p, + POINTER(struct_statfs), +] +_statfs.restype = c_int + +try: + _fstatfs = libc["fstatfs$INODE64"] +except (KeyError, AttributeError): + _fstatfs = libc["fstatfs"] + +_fstatfs.argtypes = [ + c_int, + POINTER(struct_statfs), +] +_fstatfs.restype = c_int + + +def _datetime_from_timespec(ts): + td = datetime.timedelta(seconds=ts.tv_sec + 1.0e-9 * ts.tv_nsec) + return unix_epoch + td + + +def _decode_utf8_nul(sz): + nul = sz.find(b"\0") + if nul > -1: + sz = sz[:nul] + return sz.decode("utf-8") + + +def _decode_attrlist_result(buf, attrs, options): + result = [] + + assert len(buf) >= 4 + total_size = uint32_t.from_buffer(buf, 0).value + assert total_size <= len(buf) + + offset = 4 + + # Common attributes + if attrs[0] & ATTR_CMN_RETURNED_ATTRS: + a = attribute_set_t.from_buffer(buf, offset) + result.append(a) + offset += sizeof(attribute_set_t) + if not (options & FSOPT_PACK_INVAL_ATTRS): + attrs = [a.commonattr, a.volattr, a.dirattr, a.fileattr, a.forkattr] + if attrs[0] & ATTR_CMN_NAME: + a = attrreference_t.from_buffer(buf, offset) + ofs = offset + a.attr_dataoffset + name = _decode_utf8_nul(buf[ofs : ofs + a.attr_length]) + offset += sizeof(attrreference_t) + result.append(name) + if attrs[0] & ATTR_CMN_DEVID: + a = dev_t.from_buffer(buf, offset) + offset += sizeof(dev_t) + result.append(a.value) + if attrs[0] & ATTR_CMN_FSID: + a = fsid_t.from_buffer(buf, offset) + offset += sizeof(fsid_t) + result.append(a) + if attrs[0] & ATTR_CMN_OBJTYPE: + a = fsobj_type_t.from_buffer(buf, offset) + offset += sizeof(fsobj_type_t) + result.append(a.value) + if attrs[0] & ATTR_CMN_OBJTAG: + a = fsobj_tag_t.from_buffer(buf, offset) + offset += sizeof(fsobj_tag_t) + result.append(a.value) + if attrs[0] & ATTR_CMN_OBJID: + a = fsobj_id_t.from_buffer(buf, offset) + offset += sizeof(fsobj_id_t) + result.append(a) + if attrs[0] & ATTR_CMN_OBJPERMANENTID: + a = fsobj_id_t.from_buffer(buf, offset) + offset += sizeof(fsobj_id_t) + result.append(a) + if attrs[0] & ATTR_CMN_PAROBJID: + a = fsobj_id_t.from_buffer(buf, offset) + offset += sizeof(fsobj_id_t) + result.append(a) + if attrs[0] & ATTR_CMN_SCRIPT: + a = text_encoding_t.from_buffer(buf, offset) + offset += sizeof(text_encoding_t) + result.append(a.value) + if attrs[0] & ATTR_CMN_CRTIME: + a = timespec.from_buffer(buf, offset) + offset += sizeof(timespec) + result.append(_datetime_from_timespec(a)) + if attrs[0] & ATTR_CMN_MODTIME: + a = timespec.from_buffer(buf, offset) + offset += sizeof(timespec) + result.append(_datetime_from_timespec(a)) + if attrs[0] & ATTR_CMN_CHGTIME: + a = timespec.from_buffer(buf, offset) + offset += sizeof(timespec) + result.append(_datetime_from_timespec(a)) + if attrs[0] & ATTR_CMN_ACCTIME: + a = timespec.from_buffer(buf, offset) + offset += sizeof(timespec) + result.append(_datetime_from_timespec(a)) + if attrs[0] & ATTR_CMN_BKUPTIME: + a = timespec.from_buffer(buf, offset) + offset += sizeof(timespec) + result.append(_datetime_from_timespec(a)) + if attrs[0] & ATTR_CMN_FNDRINFO: + a = FinderInfo.from_buffer(buf, offset) + offset += sizeof(FinderInfo) + result.append(a) + if attrs[0] & ATTR_CMN_OWNERID: + a = uid_t.from_buffer(buf, offset) + offset += sizeof(uid_t) + result.append(a.value) + if attrs[0] & ATTR_CMN_GRPID: + a = gid_t.from_buffer(buf, offset) + offset += sizeof(gid_t) + result.append(a.value) + if attrs[0] & ATTR_CMN_ACCESSMASK: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[0] & ATTR_CMN_FLAGS: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[0] & ATTR_CMN_GEN_COUNT: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[0] & ATTR_CMN_DOCUMENT_ID: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[0] & ATTR_CMN_USERACCESS: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[0] & ATTR_CMN_EXTENDED_SECURITY: + a = attrreference_t.from_buffer(buf, offset) + ofs = offset + a.attr_dataoffset + offset += sizeof(attrreference_t) + ec = uint32_t.from_buffer(buf, ofs + 36).value + + class kauth_acl(Structure): + _fields_ = [ + ("acl_entrycount", c_uint), + ("acl_flags", c_uint), + ("acl_ace", kauth_ace * ec), + ] + + class kauth_filesec(Structure): + _fields_ = [ + ("fsec_magic", c_uint), + ("fsec_owner", guid_t), + ("fsec_group", guid_t), + ("fsec_acl", kauth_acl), + ] + + a = kauth_filesec.from_buffer(buf, ofs) + result.append(a) + if attrs[0] & ATTR_CMN_UUID: + result.append(uuid.UUID(bytes=buf[offset : offset + 16])) + offset += sizeof(guid_t) + if attrs[0] & ATTR_CMN_GRPUUID: + result.append(uuid.UUID(bytes=buf[offset : offset + 16])) + offset += sizeof(guid_t) + if attrs[0] & ATTR_CMN_FILEID: + a = uint64_t.from_buffer(buf, offset) + offset += sizeof(uint64_t) + result.append(a.value) + if attrs[0] & ATTR_CMN_PARENTID: + a = uint64_t.from_buffer(buf, offset) + offset += sizeof(uint64_t) + result.append(a.value) + if attrs[0] & ATTR_CMN_FULLPATH: + a = attrreference_t.from_buffer(buf, offset) + ofs = offset + a.attr_dataoffset + path = _decode_utf8_nul(buf[ofs : ofs + a.attr_length]) + offset += sizeof(attrreference_t) + result.append(path) + if attrs[0] & ATTR_CMN_ADDEDTIME: + a = timespec.from_buffer(buf, offset) + offset += sizeof(timespec) + result.append(_datetime_from_timespec(a)) + if attrs[0] & ATTR_CMN_DATA_PROTECT_FLAGS: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + + # Volume attributes + if attrs[1] & ATTR_VOL_FSTYPE: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[1] & ATTR_VOL_SIGNATURE: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[1] & ATTR_VOL_SIZE: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + if attrs[1] & ATTR_VOL_SPACEFREE: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + if attrs[1] & ATTR_VOL_SPACEAVAIL: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + if attrs[1] & ATTR_VOL_MINALLOCATION: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + if attrs[1] & ATTR_VOL_ALLOCATIONCLUMP: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + if attrs[1] & ATTR_VOL_IOBLOCKSIZE: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[1] & ATTR_VOL_OBJCOUNT: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[1] & ATTR_VOL_FILECOUNT: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[1] & ATTR_VOL_DIRCOUNT: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[1] & ATTR_VOL_MAXOBJCOUNT: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[1] & ATTR_VOL_MOUNTPOINT: + a = attrreference_t.from_buffer(buf, offset) + ofs = offset + a.attr_dataoffset + path = _decode_utf8_nul(buf[ofs : ofs + a.attr_length]) + offset += sizeof(attrreference_t) + result.append(path) + if attrs[1] & ATTR_VOL_NAME: + a = attrreference_t.from_buffer(buf, offset) + ofs = offset + a.attr_dataoffset + name = _decode_utf8_nul(buf[ofs : ofs + a.attr_length]) + offset += sizeof(attrreference_t) + result.append(name) + if attrs[1] & ATTR_VOL_MOUNTFLAGS: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[1] & ATTR_VOL_MOUNTEDDEVICE: + a = attrreference_t.from_buffer(buf, offset) + ofs = offset + a.attr_dataoffset + path = _decode_utf8_nul(buf[ofs : ofs + a.attr_length]) + offset += sizeof(attrreference_t) + result.append(path) + if attrs[1] & ATTR_VOL_ENCODINGSUSED: + a = c_ulonglong.from_buffer(buf, offset) + offset += sizeof(c_ulonglong) + result.append(a.value) + if attrs[1] & ATTR_VOL_CAPABILITIES: + a = vol_capabilities_attr_t.from_buffer(buf, offset) + offset += sizeof(vol_capabilities_attr_t) + result.append(a) + if attrs[1] & ATTR_VOL_UUID: + result.append(uuid.UUID(bytes=buf[offset : offset + 16])) + offset += sizeof(uuid_t) + if attrs[1] & ATTR_VOL_QUOTA_SIZE: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + if attrs[1] & ATTR_VOL_RESERVED_SIZE: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + if attrs[1] & ATTR_VOL_ATTRIBUTES: + a = vol_attributes_attr_t.from_buffer(buf, offset) + offset += sizeof(vol_attributes_attr_t) + result.append(a) + + # Directory attributes + if attrs[2] & ATTR_DIR_LINKCOUNT: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[2] & ATTR_DIR_ENTRYCOUNT: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[2] & ATTR_DIR_MOUNTSTATUS: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[2] & ATTR_DIR_ALLOCSIZE: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + if attrs[2] & ATTR_DIR_IOBLOCKSIZE: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[2] & ATTR_DIR_DATALENGTH: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + + # File attributes + if attrs[3] & ATTR_FILE_LINKCOUNT: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[3] & ATTR_FILE_TOTALSIZE: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + if attrs[3] & ATTR_FILE_ALLOCSIZE: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + if attrs[3] & ATTR_FILE_IOBLOCKSIZE: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[3] & ATTR_FILE_CLUMPSIZE: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[3] & ATTR_FILE_DEVTYPE: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[3] & ATTR_FILE_FILETYPE: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[3] & ATTR_FILE_FORKCOUNT: + a = uint32_t.from_buffer(buf, offset) + offset += sizeof(uint32_t) + result.append(a.value) + if attrs[3] & ATTR_FILE_DATALENGTH: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + if attrs[3] & ATTR_FILE_DATAALLOCSIZE: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + if attrs[3] & ATTR_FILE_DATAEXTENTS: + a = extentrecord.from_buffer(buf, offset) + offset += sizeof(extentrecord) + result.append(a.value) + if attrs[3] & ATTR_FILE_RSRCLENGTH: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + if attrs[3] & ATTR_FILE_RSRCALLOCSIZE: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + if attrs[3] & ATTR_FILE_RSRCEXTENTS: + a = extentrecord.from_buffer(buf, offset) + offset += sizeof(extentrecord) + result.append(a.value) + + # Fork attributes + if attrs[4] & ATTR_FORK_TOTALSIZE: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + if attrs[4] & ATTR_FORK_ALLOCSIZE: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + + # Extended common attributes + if attrs[4] & ATTR_CMNEXT_RELPATH: + a = attrreference_t.from_buffer(buf, offset) + ofs = offset + a.attr_dataoffset + path = _decode_utf8_nul(buf[ofs : ofs + a.attr_length]) + offset += sizeof(attrreference_t) + result.append(path) + if attrs[4] & ATTR_CMNEXT_PRIVATESIZE: + a = off_t.from_buffer(buf, offset) + offset += sizeof(off_t) + result.append(a.value) + if attrs[4] & ATTR_CMNEXT_LINKID: + a = uint64_t.from_buffer(buf, offset) + offset += sizeof(uint64_t) + result.append(a.value) + if attrs[4] & ATTR_CMNEXT_NOFIRMLINKPATH: + a = attrreference_t.from_buffer(buf, offset) + ofs = offset + a.attr_dataoffset + path = _decode_utf8_nul(buf[ofs : ofs + a.attr_length]) + offset += sizeof(attrreference_t) + result.append(path) + if attrs[4] & ATTR_CMNEXT_REALDEVID: + a = dev_t.from_buffer(buf, offset) + offset += sizeof(dev_t) + result.append(a.value) + if attrs[4] & ATTR_CMNEXT_REALFSID: + a = fsid_t.from_buffer(buf, offset) + offset += sizeof(fsid_t) + result.append(a.value) + if attrs[4] & ATTR_CMNEXT_CLONEID: + a = uint64_t.from_buffer(buf, offset) + offset += sizeof(uint64_t) + result.append(a.value) + if attrs[4] & ATTR_CMNEXT_EXT_FLAGS: + a = uint64_t.from_buffer(buf, offset) + offset += sizeof(uint64_t) + result.append(a.value) + + return result + + +# Sadly, ctypes.get_errno() seems not to work +__error = libc.__error +__error.restype = POINTER(c_int) + + +def _get_errno(): + return __error().contents.value + + +def getattrlist(path, attrs, options): + if not isinstance(path, bytes): + path = path.encode("utf-8") + attrs = list(attrs) + if attrs[1]: + attrs[1] |= ATTR_VOL_INFO + alist = attrlist( + bitmapcount=5, + commonattr=attrs[0], + volattr=attrs[1], + dirattr=attrs[2], + fileattr=attrs[3], + forkattr=attrs[4], + ) + + bufsize = _attrbuf_size(attrs) + buf = create_string_buffer(bufsize) + + ret = _getattrlist( + path, byref(alist), buf, bufsize, options | FSOPT_REPORT_FULLSIZE + ) + + if ret < 0: + err = _get_errno() + raise OSError(err, os.strerror(err), path) + + return _decode_attrlist_result(buf, attrs, options) + + +def fgetattrlist(fd, attrs, options): + if hasattr(fd, "fileno"): + fd = fd.fileno() + attrs = list(attrs) + if attrs[1]: + attrs[1] |= ATTR_VOL_INFO + alist = attrlist( + bitmapcount=5, + commonattr=attrs[0], + volattr=attrs[1], + dirattr=attrs[2], + fileattr=attrs[3], + forkattr=attrs[4], + ) + + bufsize = _attrbuf_size(attrs) + buf = create_string_buffer(bufsize) + + ret = _fgetattrlist(fd, byref(alist), buf, bufsize, options | FSOPT_REPORT_FULLSIZE) + + if ret < 0: + err = _get_errno() + raise OSError(err, os.strerror(err)) + + return _decode_attrlist_result(buf, attrs, options) + + +def statfs(path): + if not isinstance(path, bytes): + path = path.encode("utf-8") + result = struct_statfs() + ret = _statfs(path, byref(result)) + if ret < 0: + err = _get_errno() + raise OSError(err, os.strerror(err), path) + return result + + +def fstatfs(fd): + if hasattr(fd, "fileno"): + fd = fd.fileno() + result = struct_statfs() + ret = _fstatfs(fd, byref(result)) + if ret < 0: + err = _get_errno() + raise OSError(err, os.strerror(err)) + return result |