1# -*- coding: utf-8 -*- 2from __future__ import unicode_literals 3 4from ctypes import * 5import struct 6import os 7import datetime 8import uuid 9 10from .utils import * 11 12libc = cdll.LoadLibrary('/usr/lib/libc.dylib') 13 14# Constants 15FSOPT_NOFOLLOW = 0x00000001 16FSOPT_NOINMEMUPDATE = 0x00000002 17FSOPT_REPORT_FULLSIZE = 0x00000004 18FSOPT_PACK_INVAL_ATTRS = 0x00000008 19 20VOL_CAPABILITIES_FORMAT = 0 21VOL_CAPABILITIES_INTERFACES = 1 22 23VOL_CAP_FMT_PERSISTENTOBJECTIDS = 0x00000001 24VOL_CAP_FMT_SYMBOLICLINKS = 0x00000002 25VOL_CAP_FMT_HARDLINKS = 0x00000004 26VOL_CAP_FMT_JOURNAL = 0x00000008 27VOL_CAP_FMT_JOURNAL_ACTIVE = 0x00000010 28VOL_CAP_FMT_NO_ROOT_TIMES = 0x00000020 29VOL_CAP_FMT_SPARSE_FILES = 0x00000040 30VOL_CAP_FMT_ZERO_RUNS = 0x00000080 31VOL_CAP_FMT_CASE_SENSITIVE = 0x00000100 32VOL_CAP_FMT_CASE_PRESERVING = 0x00000200 33VOL_CAP_FMT_FAST_STATFS = 0x00000400 34VOL_CAP_FMT_2TB_FILESIZE = 0x00000800 35VOL_CAP_FMT_OPENDENYMODES = 0x00001000 36VOL_CAP_FMT_HIDDEN_FILES = 0x00002000 37VOL_CAP_FMT_PATH_FROM_ID = 0x00004000 38VOL_CAP_FMT_NO_VOLUME_SIZES = 0x00008000 39VOL_CAP_FMT_DECMPFS_COMPRESSION = 0x00010000 40VOL_CAP_FMT_64BIT_OBJECT_IDS = 0x00020000 41 42VOL_CAP_INT_SEARCHFS = 0x00000001 43VOL_CAP_INT_ATTRLIST = 0x00000002 44VOL_CAP_INT_NFSEXPORT = 0x00000004 45VOL_CAP_INT_READDIRATTR = 0x00000008 46VOL_CAP_INT_EXCHANGEDATA = 0x00000010 47VOL_CAP_INT_COPYFILE = 0x00000020 48VOL_CAP_INT_ALLOCATE = 0x00000040 49VOL_CAP_INT_VOL_RENAME = 0x00000080 50VOL_CAP_INT_ADVLOCK = 0x00000100 51VOL_CAP_INT_FLOCK = 0x00000200 52VOL_CAP_INT_EXTENDED_SECURITY = 0x00000400 53VOL_CAP_INT_USERACCESS = 0x00000800 54VOL_CAP_INT_MANLOCK = 0x00001000 55VOL_CAP_INT_NAMEDSTREAMS = 0x00002000 56VOL_CAP_INT_EXTENDED_ATTR = 0x00004000 57 58ATTR_CMN_NAME = 0x00000001 59ATTR_CMN_DEVID = 0x00000002 60ATTR_CMN_FSID = 0x00000004 61ATTR_CMN_OBJTYPE = 0x00000008 62ATTR_CMN_OBJTAG = 0x00000010 63ATTR_CMN_OBJID = 0x00000020 64ATTR_CMN_OBJPERMANENTID = 0x00000040 65ATTR_CMN_PAROBJID = 0x00000080 66ATTR_CMN_SCRIPT = 0x00000100 67ATTR_CMN_CRTIME = 0x00000200 68ATTR_CMN_MODTIME = 0x00000400 69ATTR_CMN_CHGTIME = 0x00000800 70ATTR_CMN_ACCTIME = 0x00001000 71ATTR_CMN_BKUPTIME = 0x00002000 72ATTR_CMN_FNDRINFO = 0x00004000 73ATTR_CMN_OWNERID = 0x00008000 74ATTR_CMN_GRPID = 0x00010000 75ATTR_CMN_ACCESSMASK = 0x00020000 76ATTR_CMN_FLAGS = 0x00040000 77ATTR_CMN_USERACCESS = 0x00200000 78ATTR_CMN_EXTENDED_SECURITY = 0x00400000 79ATTR_CMN_UUID = 0x00800000 80ATTR_CMN_GRPUUID = 0x01000000 81ATTR_CMN_FILEID = 0x02000000 82ATTR_CMN_PARENTID = 0x04000000 83ATTR_CMN_FULLPATH = 0x08000000 84ATTR_CMN_ADDEDTIME = 0x10000000 85ATTR_CMN_RETURNED_ATTRS = 0x80000000 86ATTR_CMN_ALL_ATTRS = 0x9fe7ffff 87 88ATTR_VOL_FSTYPE = 0x00000001 89ATTR_VOL_SIGNATURE = 0x00000002 90ATTR_VOL_SIZE = 0x00000004 91ATTR_VOL_SPACEFREE = 0x00000008 92ATTR_VOL_SPACEAVAIL = 0x00000010 93ATTR_VOL_MINALLOCATION = 0x00000020 94ATTR_VOL_ALLOCATIONCLUMP = 0x00000040 95ATTR_VOL_IOBLOCKSIZE = 0x00000080 96ATTR_VOL_OBJCOUNT = 0x00000100 97ATTR_VOL_FILECOUNT = 0x00000200 98ATTR_VOL_DIRCOUNT = 0x00000400 99ATTR_VOL_MAXOBJCOUNT = 0x00000800 100ATTR_VOL_MOUNTPOINT = 0x00001000 101ATTR_VOL_NAME = 0x00002000 102ATTR_VOL_MOUNTFLAGS = 0x00004000 103ATTR_VOL_MOUNTEDDEVICE = 0x00008000 104ATTR_VOL_ENCODINGSUSED = 0x00010000 105ATTR_VOL_CAPABILITIES = 0x00020000 106ATTR_VOL_UUID = 0x00040000 107ATTR_VOL_ATTRIBUTES = 0x40000000 108ATTR_VOL_INFO = 0x80000000 109ATTR_VOL_ALL_ATTRS = 0xc007ffff 110 111ATTR_DIR_LINKCOUNT = 0x00000001 112ATTR_DIR_ENTRYCOUNT = 0x00000002 113ATTR_DIR_MOUNTSTATUS = 0x00000004 114DIR_MNTSTATUS_MNTPOINT = 0x00000001 115DIR_MNTSTATUS_TRIGGER = 0x00000002 116ATTR_DIR_ALL_ATTRS = 0x00000007 117 118ATTR_FILE_LINKCOUNT = 0x00000001 119ATTR_FILE_TOTALSIZE = 0x00000002 120ATTR_FILE_ALLOCSIZE = 0x00000004 121ATTR_FILE_IOBLOCKSIZE = 0x00000008 122ATTR_FILE_DEVTYPE = 0x00000020 123ATTR_FILE_DATALENGTH = 0x00000200 124ATTR_FILE_DATAALLOCSIZE = 0x00000400 125ATTR_FILE_RSRCLENGTH = 0x00001000 126ATTR_FILE_RSRCALLOCSIZE = 0x00002000 127 128ATTR_FILE_ALL_ATTRS = 0x0000362f 129 130ATTR_FORK_TOTALSIZE = 0x00000001 131ATTR_FORK_ALLOCSIZE = 0x00000002 132ATTR_FORK_ALL_ATTRS = 0x00000003 133 134# These can't be used 135ATTR_FILE_FORKCOUNT = 0x00000080 136ATTR_FILE_FORKLIST = 0x00000100 137ATTR_CMN_NAMEDATTRCOUNT = 0x00080000 138ATTR_CMN_NAMEDATTRLIST = 0x00100000 139ATTR_FILE_DATAEXTENTS = 0x00000800 140ATTR_FILE_RSRCEXTENTS = 0x00004000 141ATTR_FILE_CLUMPSIZE = 0x00000010 142ATTR_FILE_FILETYPE = 0x00000040 143 144class attrlist(Structure): 145 _fields_ = [('bitmapcount', c_ushort), 146 ('reserved', c_ushort), 147 ('commonattr', c_uint), 148 ('volattr', c_uint), 149 ('dirattr', c_uint), 150 ('fileattr', c_uint), 151 ('forkattr', c_uint)] 152 153class attribute_set_t(Structure): 154 _fields_ = [('commonattr', c_uint), 155 ('volattr', c_uint), 156 ('dirattr', c_uint), 157 ('fileattr', c_uint), 158 ('forkattr', c_uint)] 159 160class fsobj_id_t(Structure): 161 _fields_ = [('fid_objno', c_uint), 162 ('fid_generation', c_uint)] 163 164class timespec(Structure): 165 _fields_ = [('tv_sec', c_long), 166 ('tv_nsec', c_long)] 167 168class attrreference_t(Structure): 169 _fields_ = [('attr_dataoffset', c_int), 170 ('attr_length', c_uint)] 171 172class fsid_t(Structure): 173 _fields_ = [('val', c_uint * 2)] 174 175class guid_t(Structure): 176 _fields_ = [('g_guid', c_byte*16)] 177 178class kauth_ace(Structure): 179 _fields_ = [('ace_applicable', guid_t), 180 ('ace_flags', c_uint)] 181 182class kauth_acl(Structure): 183 _fields_ = [('acl_entrycount', c_uint), 184 ('acl_flags', c_uint), 185 ('acl_ace', kauth_ace * 128)] 186 187class kauth_filesec(Structure): 188 _fields_ = [('fsec_magic', c_uint), 189 ('fsec_owner', guid_t), 190 ('fsec_group', guid_t), 191 ('fsec_acl', kauth_acl)] 192 193class diskextent(Structure): 194 _fields_ = [('startblock', c_uint), 195 ('blockcount', c_uint)] 196 197OSType = c_uint 198UInt16 = c_ushort 199SInt16 = c_short 200SInt32 = c_int 201 202class Point(Structure): 203 _fields_ = [('x', SInt16), 204 ('y', SInt16)] 205class Rect(Structure): 206 _fields_ = [('x', SInt16), 207 ('y', SInt16), 208 ('w', SInt16), 209 ('h', SInt16)] 210class FileInfo(Structure): 211 _fields_ = [('fileType', OSType), 212 ('fileCreator', OSType), 213 ('finderFlags', UInt16), 214 ('location', Point), 215 ('reservedField', UInt16), 216 ('reserved1', SInt16 * 4), 217 ('extendedFinderFlags', UInt16), 218 ('reserved2', SInt16), 219 ('putAwayFolderID', SInt32)] 220class FolderInfo(Structure): 221 _fields_ = [('windowBounds', Rect), 222 ('finderFlags', UInt16), 223 ('location', Point), 224 ('reservedField', UInt16), 225 ('scrollPosition', Point), 226 ('reserved1', SInt32), 227 ('extendedFinderFlags', UInt16), 228 ('reserved2', SInt16), 229 ('putAwayFolderID', SInt32)] 230class FinderInfo(Union): 231 _fields_ = [('fileInfo', FileInfo), 232 ('folderInfo', FolderInfo)] 233 234extentrecord = diskextent * 8 235 236vol_capabilities_set_t = c_uint * 4 237 238class vol_capabilities_attr_t(Structure): 239 _fields_ = [('capabilities', vol_capabilities_set_t), 240 ('valid', vol_capabilities_set_t)] 241 242class vol_attributes_attr_t(Structure): 243 _fields_ = [('validattr', attribute_set_t), 244 ('nativeattr', attribute_set_t)] 245 246dev_t = c_uint 247 248fsobj_type_t = c_uint 249 250VNON = 0 251VREG = 1 252VDIR = 2 253VBLK = 3 254VCHR = 4 255VLNK = 5 256VSOCK = 6 257VFIFO = 7 258VBAD = 8 259VSTR = 9 260VCPLX = 10 261 262fsobj_tag_t = c_uint 263 264VT_NON = 0 265VT_UFS = 1 266VT_NFS = 2 267VT_MFS = 3 268VT_MSDOSFS = 4 269VT_LFS = 5 270VT_LOFS = 6 271VT_FDESC = 7 272VT_PORTAL = 8 273VT_NULL = 9 274VT_UMAP = 10 275VT_KERNFS = 11 276VT_PROCFS = 12 277VT_AFS = 13 278VT_ISOFS = 14 279VT_UNION = 15 280VT_HFS = 16 281VT_ZFS = 17 282VT_DEVFS = 18 283VT_WEBDAV = 19 284VT_UDF = 20 285VT_AFP = 21 286VT_CDDA = 22 287VT_CIFS = 23 288VT_OTHER = 24 289 290fsfile_type_t = c_uint 291fsvolid_t = c_uint 292text_encoding_t = c_uint 293uid_t = c_uint 294gid_t = c_uint 295int32_t = c_int 296uint32_t = c_uint 297int64_t = c_longlong 298uint64_t = c_ulonglong 299off_t = c_long 300size_t = c_ulong 301uuid_t = c_byte*16 302 303NAME_MAX = 255 304PATH_MAX = 1024 305 306class struct_statfs(Structure): 307 _fields_ = [('f_bsize', uint32_t), 308 ('f_iosize', int32_t), 309 ('f_blocks', uint64_t), 310 ('f_bfree', uint64_t), 311 ('f_bavail', uint64_t), 312 ('f_files', uint64_t), 313 ('f_ffree', uint64_t), 314 ('f_fsid', fsid_t), 315 ('f_owner', uid_t), 316 ('f_type', uint32_t), 317 ('f_flags', uint32_t), 318 ('f_fssubtype', uint32_t), 319 ('f_fstypename', c_char * 16), 320 ('f_mntonname', c_char * PATH_MAX), 321 ('f_mntfromname', c_char * PATH_MAX), 322 ('f_reserved', uint32_t * 8)] 323 324# Calculate the maximum number of bytes required for the attribute buffer 325_attr_info = ( 326 # Common attributes 327 (0, ATTR_CMN_RETURNED_ATTRS, sizeof(attribute_set_t)), 328 (0, ATTR_CMN_NAME, sizeof(attrreference_t) + NAME_MAX * 3 + 1), 329 (0, ATTR_CMN_DEVID, sizeof(dev_t)), 330 (0, ATTR_CMN_FSID, sizeof(fsid_t)), 331 (0, ATTR_CMN_OBJTYPE, sizeof(fsobj_type_t)), 332 (0, ATTR_CMN_OBJTAG, sizeof(fsobj_tag_t)), 333 (0, ATTR_CMN_OBJPERMANENTID, sizeof(fsobj_id_t)), 334 (0, ATTR_CMN_PAROBJID, sizeof(fsobj_id_t)), 335 (0, ATTR_CMN_SCRIPT, sizeof(text_encoding_t)), 336 (0, ATTR_CMN_CRTIME, sizeof(timespec)), 337 (0, ATTR_CMN_MODTIME, sizeof(timespec)), 338 (0, ATTR_CMN_CHGTIME, sizeof(timespec)), 339 (0, ATTR_CMN_ACCTIME, sizeof(timespec)), 340 (0, ATTR_CMN_BKUPTIME, sizeof(timespec)), 341 (0, ATTR_CMN_FNDRINFO, sizeof(FinderInfo)), 342 (0, ATTR_CMN_OWNERID, sizeof(uid_t)), 343 (0, ATTR_CMN_GRPID, sizeof(gid_t)), 344 (0, ATTR_CMN_ACCESSMASK, sizeof(uint32_t)), 345 (0, ATTR_CMN_NAMEDATTRCOUNT, None), 346 (0, ATTR_CMN_NAMEDATTRLIST, None), 347 (0, ATTR_CMN_FLAGS, sizeof(uint32_t)), 348 (0, ATTR_CMN_USERACCESS, sizeof(uint32_t)), 349 (0, ATTR_CMN_EXTENDED_SECURITY, sizeof(attrreference_t) + sizeof(kauth_filesec)), 350 (0, ATTR_CMN_UUID, sizeof(guid_t)), 351 (0, ATTR_CMN_GRPUUID, sizeof(guid_t)), 352 (0, ATTR_CMN_FILEID, sizeof(uint64_t)), 353 (0, ATTR_CMN_PARENTID, sizeof(uint64_t)), 354 (0, ATTR_CMN_FULLPATH, sizeof(attrreference_t) + PATH_MAX), 355 (0, ATTR_CMN_ADDEDTIME, sizeof(timespec)), 356 357 # Volume attributes 358 (1, ATTR_VOL_FSTYPE, sizeof(uint32_t)), 359 (1, ATTR_VOL_SIGNATURE, sizeof(uint32_t)), 360 (1, ATTR_VOL_SIZE, sizeof(off_t)), 361 (1, ATTR_VOL_SPACEFREE, sizeof(off_t)), 362 (1, ATTR_VOL_SPACEAVAIL, sizeof(off_t)), 363 (1, ATTR_VOL_MINALLOCATION, sizeof(off_t)), 364 (1, ATTR_VOL_ALLOCATIONCLUMP, sizeof(off_t)), 365 (1, ATTR_VOL_IOBLOCKSIZE, sizeof(uint32_t)), 366 (1, ATTR_VOL_OBJCOUNT, sizeof(uint32_t)), 367 (1, ATTR_VOL_FILECOUNT, sizeof(uint32_t)), 368 (1, ATTR_VOL_DIRCOUNT, sizeof(uint32_t)), 369 (1, ATTR_VOL_MAXOBJCOUNT, sizeof(uint32_t)), 370 (1, ATTR_VOL_MOUNTPOINT, sizeof(attrreference_t) + PATH_MAX), 371 (1, ATTR_VOL_NAME, sizeof(attrreference_t) + NAME_MAX + 1), 372 (1, ATTR_VOL_MOUNTFLAGS, sizeof(uint32_t)), 373 (1, ATTR_VOL_MOUNTEDDEVICE, sizeof(attrreference_t) + PATH_MAX), 374 (1, ATTR_VOL_ENCODINGSUSED, sizeof(c_ulonglong)), 375 (1, ATTR_VOL_CAPABILITIES, sizeof(vol_capabilities_attr_t)), 376 (1, ATTR_VOL_UUID, sizeof(uuid_t)), 377 (1, ATTR_VOL_ATTRIBUTES, sizeof(vol_attributes_attr_t)), 378 379 # Directory attributes 380 (2, ATTR_DIR_LINKCOUNT, sizeof(uint32_t)), 381 (2, ATTR_DIR_ENTRYCOUNT, sizeof(uint32_t)), 382 (2, ATTR_DIR_MOUNTSTATUS, sizeof(uint32_t)), 383 384 # File attributes 385 (3, ATTR_FILE_LINKCOUNT, sizeof(uint32_t)), 386 (3, ATTR_FILE_TOTALSIZE, sizeof(off_t)), 387 (3, ATTR_FILE_ALLOCSIZE, sizeof(off_t)), 388 (3, ATTR_FILE_IOBLOCKSIZE, sizeof(uint32_t)), 389 (3, ATTR_FILE_CLUMPSIZE, sizeof(uint32_t)), 390 (3, ATTR_FILE_DEVTYPE, sizeof(uint32_t)), 391 (3, ATTR_FILE_FILETYPE, sizeof(uint32_t)), 392 (3, ATTR_FILE_FORKCOUNT, sizeof(uint32_t)), 393 (3, ATTR_FILE_FORKLIST, None), 394 (3, ATTR_FILE_DATALENGTH, sizeof(off_t)), 395 (3, ATTR_FILE_DATAALLOCSIZE, sizeof(off_t)), 396 (3, ATTR_FILE_DATAEXTENTS, sizeof(extentrecord)), 397 (3, ATTR_FILE_RSRCLENGTH, sizeof(off_t)), 398 (3, ATTR_FILE_RSRCALLOCSIZE, sizeof(off_t)), 399 (3, ATTR_FILE_RSRCEXTENTS, sizeof(extentrecord)), 400 401 # Fork attributes 402 (4, ATTR_FORK_TOTALSIZE, sizeof(off_t)), 403 (4, ATTR_FORK_ALLOCSIZE, sizeof(off_t)) 404 ) 405 406def _attrbuf_size(attrs): 407 size = 4 408 for entry in _attr_info: 409 if attrs[entry[0]] & entry[1]: 410 if entry[2] is None: 411 raise ValueError('Unsupported attribute (%u, %x)' 412 % (entry[0], entry[1])) 413 size += entry[2] 414 return size 415 416_getattrlist = libc.getattrlist 417_getattrlist.argtypes = [c_char_p, POINTER(attrlist), c_void_p, c_ulong, c_ulong] 418_getattrlist.restype = c_int 419 420_fgetattrlist = libc.fgetattrlist 421_fgetattrlist.argtypes = [c_int, POINTER(attrlist), c_void_p, c_ulong, c_ulong] 422_fgetattrlist.restype = c_int 423 424_statfs = libc['statfs$INODE64'] 425_statfs.argtypes = [c_char_p, POINTER(struct_statfs)] 426_statfs.restype = c_int 427 428_fstatfs = libc['fstatfs$INODE64'] 429_fstatfs.argtypes = [c_int, POINTER(struct_statfs)] 430_fstatfs.restype = c_int 431 432def _datetime_from_timespec(ts): 433 td = datetime.timedelta(seconds=ts.tv_sec + 1.0e-9 * ts.tv_nsec) 434 return unix_epoch + td 435 436def _decode_utf8_nul(sz): 437 nul = sz.find(b'\0') 438 if nul > -1: 439 sz = sz[:nul] 440 return sz.decode('utf-8') 441 442def _decode_attrlist_result(buf, attrs, options): 443 result = [] 444 445 assert len(buf) >= 4 446 total_size = uint32_t.from_buffer(buf, 0).value 447 assert total_size <= len(buf) 448 449 offset = 4 450 451 # Common attributes 452 if attrs[0] & ATTR_CMN_RETURNED_ATTRS: 453 a = attribute_set_t.from_buffer(buf, offset) 454 result.append(a) 455 offset += sizeof (attribute_set_t) 456 if not (options & FSOPT_PACK_INVAL_ATTRS): 457 attrs = [a.commonattr, a.volattr, a.dirattr, a.fileattr, a.forkattr] 458 if attrs[0] & ATTR_CMN_NAME: 459 a = attrreference_t.from_buffer(buf, offset) 460 ofs = offset + a.attr_dataoffset 461 name = _decode_utf8_nul(buf[ofs:ofs+a.attr_length]) 462 offset += sizeof (attrreference_t) 463 result.append(name) 464 if attrs[0] & ATTR_CMN_DEVID: 465 a = dev_t.from_buffer(buf, offset) 466 offset += sizeof(dev_t) 467 result.append(a.value) 468 if attrs[0] & ATTR_CMN_FSID: 469 a = fsid_t.from_buffer(buf, offset) 470 offset += sizeof(fsid_t) 471 result.append(a) 472 if attrs[0] & ATTR_CMN_OBJTYPE: 473 a = fsobj_type_t.from_buffer(buf, offset) 474 offset += sizeof(fsobj_type_t) 475 result.append(a.value) 476 if attrs[0] & ATTR_CMN_OBJTAG: 477 a = fsobj_tag_t.from_buffer(buf, offset) 478 offset += sizeof(fsobj_tag_t) 479 result.append(a.value) 480 if attrs[0] & ATTR_CMN_OBJID: 481 a = fsobj_id_t.from_buffer(buf, offset) 482 offset += sizeof(fsobj_id_t) 483 result.append(a) 484 if attrs[0] & ATTR_CMN_OBJPERMANENTID: 485 a = fsobj_id_t.from_buffer(buf, offset) 486 offset += sizeof(fsobj_id_t) 487 result.append(a) 488 if attrs[0] & ATTR_CMN_PAROBJID: 489 a = fsobj_id_t.from_buffer(buf, offset) 490 offset += sizeof(fsobj_id_t) 491 result.append(a) 492 if attrs[0] & ATTR_CMN_SCRIPT: 493 a = text_encoding_t.from_buffer(buf, offset) 494 offset += sizeof(text_encoding_t) 495 result.append(a.value) 496 if attrs[0] & ATTR_CMN_CRTIME: 497 a = timespec.from_buffer(buf, offset) 498 offset += sizeof(timespec) 499 result.append(_datetime_from_timespec(a)) 500 if attrs[0] & ATTR_CMN_MODTIME: 501 a = timespec.from_buffer(buf, offset) 502 offset += sizeof(timespec) 503 result.append(_datetime_from_timespec(a)) 504 if attrs[0] & ATTR_CMN_CHGTIME: 505 a = timespec.from_buffer(buf, offset) 506 offset += sizeof(timespec) 507 result.append(_datetime_from_timespec(a)) 508 if attrs[0] & ATTR_CMN_ACCTIME: 509 a = timespec.from_buffer(buf, offset) 510 offset += sizeof(timespec) 511 result.append(_datetime_from_timespec(a)) 512 if attrs[0] & ATTR_CMN_BKUPTIME: 513 a = timespec.from_buffer(buf, offset) 514 offset += sizeof(timespec) 515 result.append(_datetime_from_timespec(a)) 516 if attrs[0] & ATTR_CMN_FNDRINFO: 517 a = FinderInfo.from_buffer(buf, offset) 518 offset += sizeof(FinderInfo) 519 result.append(a) 520 if attrs[0] & ATTR_CMN_OWNERID: 521 a = uid_t.from_buffer(buf, offset) 522 offset += sizeof(uid_t) 523 result.append(a.value) 524 if attrs[0] & ATTR_CMN_GRPID: 525 a = gid_t.from_buffer(buf, offset) 526 offset += sizeof(gid_t) 527 result.append(a.value) 528 if attrs[0] & ATTR_CMN_ACCESSMASK: 529 a = uint32_t.from_buffer(buf, offset) 530 offset += sizeof(uint32_t) 531 result.append(a.value) 532 if attrs[0] & ATTR_CMN_FLAGS: 533 a = uint32_t.from_buffer(buf, offset) 534 offset += sizeof(uint32_t) 535 result.append(a.value) 536 if attrs[0] & ATTR_CMN_USERACCESS: 537 a = uint32_t.from_buffer(buf, offset) 538 offset += sizeof(uint32_t) 539 result.append(a.value) 540 if attrs[0] & ATTR_CMN_EXTENDED_SECURITY: 541 a = attrreference_t.from_buffer(buf, offset) 542 ofs = offset + a.attr_dataoffset 543 offset += sizeof(attrreference_t) 544 ec = uint32_t.from_buffer(buf, ofs + 36).value 545 class kauth_acl(Structure): 546 _fields_ = [('acl_entrycount', c_uint), 547 ('acl_flags', c_uint), 548 ('acl_ace', kauth_ace * ec)] 549 class kauth_filesec(Structure): 550 _fields_ = [('fsec_magic', c_uint), 551 ('fsec_owner', guid_t), 552 ('fsec_group', guid_t), 553 ('fsec_acl', kauth_acl)] 554 a = kauth_filesec.from_buffer(buf, ofs) 555 result.append(a) 556 if attrs[0] & ATTR_CMN_UUID: 557 result.append(uuid.UUID(bytes=buf[offset:offset+16])) 558 offset += sizeof(guid_t) 559 if attrs[0] & ATTR_CMN_GRPUUID: 560 result.append(uuid.UUID(bytes=buf[offset:offset+16])) 561 offset += sizeof(guid_t) 562 if attrs[0] & ATTR_CMN_FILEID: 563 a = uint64_t.from_buffer(buf, offset) 564 offset += sizeof(uint64_t) 565 result.append(a.value) 566 if attrs[0] & ATTR_CMN_PARENTID: 567 a = uint64_t.from_buffer(buf, offset) 568 offset += sizeof(uint64_t) 569 result.append(a.value) 570 if attrs[0] & ATTR_CMN_FULLPATH: 571 a = attrreference_t.from_buffer(buf, offset) 572 ofs = offset + a.attr_dataoffset 573 path = _decode_utf8_nul(buf[ofs:ofs+a.attr_length]) 574 offset += sizeof (attrreference_t) 575 result.append(path) 576 if attrs[0] & ATTR_CMN_ADDEDTIME: 577 a = timespec.from_buffer(buf, offset) 578 offset += sizeof(timespec) 579 result.append(_datetime_from_timespec(a)) 580 581 # Volume attributes 582 if attrs[1] & ATTR_VOL_FSTYPE: 583 a = uint32_t.from_buffer(buf, offset) 584 offset += sizeof(uint32_t) 585 result.append(a.value) 586 if attrs[1] & ATTR_VOL_SIGNATURE: 587 a = uint32_t.from_buffer(buf, offset) 588 offset += sizeof(uint32_t) 589 result.append(a.value) 590 if attrs[1] & ATTR_VOL_SIZE: 591 a = off_t.from_buffer(buf, offset) 592 offset += sizeof(off_t) 593 result.append(a.value) 594 if attrs[1] & ATTR_VOL_SPACEFREE: 595 a = off_t.from_buffer(buf, offset) 596 offset += sizeof(off_t) 597 result.append(a.value) 598 if attrs[1] & ATTR_VOL_SPACEAVAIL: 599 a = off_t.from_buffer(buf, offset) 600 offset += sizeof(off_t) 601 result.append(a.value) 602 if attrs[1] & ATTR_VOL_MINALLOCATION: 603 a = off_t.from_buffer(buf, offset) 604 offset += sizeof(off_t) 605 result.append(a.value) 606 if attrs[1] & ATTR_VOL_ALLOCATIONCLUMP: 607 a = off_t.from_buffer(buf, offset) 608 offset += sizeof(off_t) 609 result.append(a.value) 610 if attrs[1] & ATTR_VOL_IOBLOCKSIZE: 611 a = uint32_t.from_buffer(buf, offset) 612 offset += sizeof(uint32_t) 613 result.append(a.value) 614 if attrs[1] & ATTR_VOL_OBJCOUNT: 615 a = uint32_t.from_buffer(buf, offset) 616 offset += sizeof(uint32_t) 617 result.append(a.value) 618 if attrs[1] & ATTR_VOL_FILECOUNT: 619 a = uint32_t.from_buffer(buf, offset) 620 offset += sizeof(uint32_t) 621 result.append(a.value) 622 if attrs[1] & ATTR_VOL_DIRCOUNT: 623 a = uint32_t.from_buffer(buf, offset) 624 offset += sizeof(uint32_t) 625 result.append(a.value) 626 if attrs[1] & ATTR_VOL_MAXOBJCOUNT: 627 a = uint32_t.from_buffer(buf, offset) 628 offset += sizeof(uint32_t) 629 result.append(a.value) 630 if attrs[1] & ATTR_VOL_MOUNTPOINT: 631 a = attrreference_t.from_buffer(buf, offset) 632 ofs = offset + a.attr_dataoffset 633 path = _decode_utf8_nul(buf[ofs:ofs+a.attr_length]) 634 offset += sizeof (attrreference_t) 635 result.append(path) 636 if attrs[1] & ATTR_VOL_NAME: 637 a = attrreference_t.from_buffer(buf, offset) 638 ofs = offset + a.attr_dataoffset 639 name = _decode_utf8_nul(buf[ofs:ofs+a.attr_length]) 640 offset += sizeof (attrreference_t) 641 result.append(name) 642 if attrs[1] & ATTR_VOL_MOUNTFLAGS: 643 a = uint32_t.from_buffer(buf, offset) 644 offset += sizeof(uint32_t) 645 result.append(a.value) 646 if attrs[1] & ATTR_VOL_MOUNTEDDEVICE: 647 a = attrreference_t.from_buffer(buf, offset) 648 ofs = offset + a.attr_dataoffset 649 path = _decode_utf8_nul(buf[ofs:ofs+a.attr_length]) 650 offset += sizeof (attrreference_t) 651 result.append(path) 652 if attrs[1] & ATTR_VOL_ENCODINGSUSED: 653 a = c_ulonglong.from_buffer(buf, offset) 654 offset += sizeof(c_ulonglong) 655 result.append(a.value) 656 if attrs[1] & ATTR_VOL_CAPABILITIES: 657 a = vol_capabilities_attr_t.from_buffer(buf, offset) 658 offset += sizeof(vol_capabilities_attr_t) 659 result.append(a) 660 if attrs[1] & ATTR_VOL_UUID: 661 result.append(uuid.UUID(bytes=buf[offset:offset+16])) 662 offset += sizeof(uuid_t) 663 if attrs[1] & ATTR_VOL_ATTRIBUTES: 664 a = vol_attributes_attr_t.from_buffer(buf, offset) 665 offset += sizeof(vol_attributes_attr_t) 666 result.append(a) 667 668 # Directory attributes 669 if attrs[2] & ATTR_DIR_LINKCOUNT: 670 a = uint32_t.from_buffer(buf, offset) 671 offset += sizeof(uint32_t) 672 result.append(a.value) 673 if attrs[2] & ATTR_DIR_ENTRYCOUNT: 674 a = uint32_t.from_buffer(buf, offset) 675 offset += sizeof(uint32_t) 676 result.append(a.value) 677 if attrs[2] & ATTR_DIR_MOUNTSTATUS: 678 a = uint32_t.from_buffer(buf, offset) 679 offset += sizeof(uint32_t) 680 result.append(a.value) 681 682 # File attributes 683 if attrs[3] & ATTR_FILE_LINKCOUNT: 684 a = uint32_t.from_buffer(buf, offset) 685 offset += sizeof(uint32_t) 686 result.append(a.value) 687 if attrs[3] & ATTR_FILE_TOTALSIZE: 688 a = off_t.from_buffer(buf, offset) 689 offset += sizeof(off_t) 690 result.append(a.value) 691 if attrs[3] & ATTR_FILE_ALLOCSIZE: 692 a = off_t.from_buffer(buf, offset) 693 offset += sizeof(off_t) 694 result.append(a.value) 695 if attrs[3] & ATTR_FILE_IOBLOCKSIZE: 696 a = uint32_t.from_buffer(buf, offset) 697 offset += sizeof(uint32_t) 698 result.append(a.value) 699 if attrs[3] & ATTR_FILE_CLUMPSIZE: 700 a = uint32_t.from_buffer(buf, offset) 701 offset += sizeof(uint32_t) 702 result.append(a.value) 703 if attrs[3] & ATTR_FILE_DEVTYPE: 704 a = uint32_t.from_buffer(buf, offset) 705 offset += sizeof(uint32_t) 706 result.append(a.value) 707 if attrs[3] & ATTR_FILE_FILETYPE: 708 a = uint32_t.from_buffer(buf, offset) 709 offset += sizeof(uint32_t) 710 result.append(a.value) 711 if attrs[3] & ATTR_FILE_FORKCOUNT: 712 a = uint32_t.from_buffer(buf, offset) 713 offset += sizeof(uint32_t) 714 result.append(a.value) 715 if attrs[3] & ATTR_FILE_DATALENGTH: 716 a = off_t.from_buffer(buf, offset) 717 offset += sizeof(off_t) 718 result.append(a.value) 719 if attrs[3] & ATTR_FILE_DATAALLOCSIZE: 720 a = off_t.from_buffer(buf, offset) 721 offset += sizeof(off_t) 722 result.append(a.value) 723 if attrs[3] & ATTR_FILE_DATAEXTENTS: 724 a = extentrecord.from_buffer(buf, offset) 725 offset += sizeof(extentrecord) 726 result.append(a.value) 727 if attrs[3] & ATTR_FILE_RSRCLENGTH: 728 a = off_t.from_buffer(buf, offset) 729 offset += sizeof(off_t) 730 result.append(a.value) 731 if attrs[3] & ATTR_FILE_RSRCALLOCSIZE: 732 a = off_t.from_buffer(buf, offset) 733 offset += sizeof(off_t) 734 result.append(a.value) 735 if attrs[3] & ATTR_FILE_RSRCEXTENTS: 736 a = extentrecord.from_buffer(buf, offset) 737 offset += sizeof(extentrecord) 738 result.append(a.value) 739 740 # Fork attributes 741 if attrs[4] & ATTR_FORK_TOTALSIZE: 742 a = off_t.from_buffer(buf, offset) 743 offset += sizeof(off_t) 744 result.append(a.value) 745 if attrs[4] & ATTR_FORK_ALLOCSIZE: 746 a = off_t.from_buffer(buf, offset) 747 offset += sizeof(off_t) 748 result.append(a.value) 749 750 return result 751 752# Sadly, ctypes.get_errno() seems not to work 753__error = libc.__error 754__error.restype = POINTER(c_int) 755 756def _get_errno(): 757 return __error().contents.value 758 759def getattrlist(path, attrs, options): 760 if not isinstance(path, bytes): 761 path = path.encode('utf-8') 762 attrs = list(attrs) 763 if attrs[1]: 764 attrs[1] |= ATTR_VOL_INFO 765 alist = attrlist(bitmapcount=5, 766 commonattr=attrs[0], 767 volattr=attrs[1], 768 dirattr=attrs[2], 769 fileattr=attrs[3], 770 forkattr=attrs[4]) 771 772 bufsize = _attrbuf_size(attrs) 773 buf = create_string_buffer(bufsize) 774 775 ret = _getattrlist(path, byref(alist), buf, bufsize, 776 options | FSOPT_REPORT_FULLSIZE) 777 778 if ret < 0: 779 err = _get_errno() 780 raise OSError(err, os.strerror(err), path) 781 782 return _decode_attrlist_result(buf, attrs, options) 783 784def fgetattrlist(fd, attrs, options): 785 if hasattr(fd, 'fileno'): 786 fd = fd.fileno() 787 attrs = list(attrs) 788 if attrs[1]: 789 attrs[1] |= ATTR_VOL_INFO 790 alist = attrlist(bitmapcount=5, 791 commonattr=attrs[0], 792 volattr=attrs[1], 793 dirattr=attrs[2], 794 fileattr=attrs[3], 795 forkattr=attrs[4]) 796 797 bufsize = _attrbuf_size(attrs) 798 buf = create_string_buffer(bufsize) 799 800 ret = _fgetattrlist(fd, byref(alist), buf, bufsize, 801 options | FSOPT_REPORT_FULLSIZE) 802 803 if ret < 0: 804 err = _get_errno() 805 raise OSError(err, os.strerror(err)) 806 807 return _decode_attrlist_result(buf, attrs, options) 808 809def statfs(path): 810 if not isinstance(path, bytes): 811 path = path.encode('utf-8') 812 result = struct_statfs() 813 ret = _statfs(path, byref(result)) 814 if ret < 0: 815 err = _get_errno() 816 raise OSError(err, os.strerror(err), path) 817 return result 818 819def fstatfs(fd): 820 if hasattr(fd, 'fileno'): 821 fd = fd.fileno() 822 result = struct_statfs() 823 ret = _fstatfs(fd, byref(result)) 824 if ret < 0: 825 err = _get_errno() 826 raise OSError(err, os.strerror(err)) 827 return result 828