aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/CMakeLists.txt2
-rw-r--r--share/share.qbs2
-rw-r--r--src/3rdparty/python/lib/python2.7/site-packages/biplist/LICENSE25
-rw-r--r--src/3rdparty/python/lib/python2.7/site-packages/biplist/__init__.py977
-rw-r--r--src/3rdparty/python/lib/python2.7/site-packages/biplist/qt_attribution.json13
-rw-r--r--src/3rdparty/python/lib/python2.7/site-packages/ds_store/__init__.py3
-rw-r--r--src/3rdparty/python/lib/python2.7/site-packages/mac_alias/__init__.py27
-rw-r--r--src/3rdparty/python/lib/python2.7/site-packages/mac_alias/bookmark.py665
-rw-r--r--src/3rdparty/python/lib/python2.7/site-packages/mac_alias/utils.py18
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/LICENSE (renamed from src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/LICENSE)0
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/__init__.py (renamed from src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/__init__.py)0
-rwxr-xr-xsrc/3rdparty/python/lib/python3.9/site-packages/dmgbuild/__main__.py (renamed from src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/__main__.py)0
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/badge.py (renamed from src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/badge.py)0
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/colors.py (renamed from src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/colors.py)0
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/core.py (renamed from src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/core.py)0
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/licensing.py (renamed from src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/licensing.py)0
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/qt_attribution.json (renamed from src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/qt_attribution.json)0
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/resources.py (renamed from src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/resources.py)0
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/ds_store/LICENSE (renamed from src/3rdparty/python/lib/python2.7/site-packages/ds_store/LICENSE)0
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/ds_store/__init__.py5
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/ds_store/__main__.py102
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/ds_store/buddy.py (renamed from src/3rdparty/python/lib/python2.7/site-packages/ds_store/buddy.py)276
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/ds_store/qt_attribution.json (renamed from src/3rdparty/python/lib/python2.7/site-packages/ds_store/qt_attribution.json)0
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/ds_store/store.py (renamed from src/3rdparty/python/lib/python2.7/site-packages/ds_store/store.py)657
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/mac_alias/LICENSE (renamed from src/3rdparty/python/lib/python2.7/site-packages/mac_alias/LICENSE)0
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/mac_alias/__init__.py47
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/mac_alias/alias.py (renamed from src/3rdparty/python/lib/python2.7/site-packages/mac_alias/alias.py)593
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/mac_alias/bookmark.py677
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/mac_alias/osx.py (renamed from src/3rdparty/python/lib/python2.7/site-packages/mac_alias/osx.py)785
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/mac_alias/qt_attribution.json (renamed from src/3rdparty/python/lib/python2.7/site-packages/mac_alias/qt_attribution.json)0
-rw-r--r--src/3rdparty/python/lib/python3.9/site-packages/mac_alias/utils.py20
31 files changed, 2224 insertions, 2670 deletions
diff --git a/share/CMakeLists.txt b/share/CMakeLists.txt
index fbdcc991d..e47bd74f0 100644
--- a/share/CMakeLists.txt
+++ b/share/CMakeLists.txt
@@ -9,7 +9,7 @@ endif()
# emulating the same layout we will have after the installation
# copy & install python packages
-set(_SITE_PACKAGES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../src/3rdparty/python/lib/python2.7/site-packages/)
+set(_SITE_PACKAGES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../src/3rdparty/python/lib/python3.9/site-packages/)
file(GLOB_RECURSE _SITE_PACKAGES_RELATIVE RELATIVE "${_SITE_PACKAGES_DIR}" "${_SITE_PACKAGES_DIR}/*.py")
set(_SITE_PACKAGES_SRC ${_SITE_PACKAGES_RELATIVE})
diff --git a/share/share.qbs b/share/share.qbs
index 8f2347a67..75e1e83ba 100644
--- a/share/share.qbs
+++ b/share/share.qbs
@@ -24,7 +24,7 @@ Product {
fileTags: ["qbs resources"]
qbs.install: true
qbs.installDir: qbsbuildconfig.resourcesInstallDir + "/share/qbs/python"
- qbs.installSourceBase: "../src/3rdparty/python/lib/python2.7/site-packages"
+ qbs.installSourceBase: "../src/3rdparty/python/lib/python3.9/site-packages"
}
Group {
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/biplist/LICENSE b/src/3rdparty/python/lib/python2.7/site-packages/biplist/LICENSE
deleted file mode 100644
index 1c7ba6cc1..000000000
--- a/src/3rdparty/python/lib/python2.7/site-packages/biplist/LICENSE
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2010, Andrew Wooster
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- * Neither the name of biplist nor the names of its contributors may be
- used to endorse or promote products derived from this software without
- specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/biplist/__init__.py b/src/3rdparty/python/lib/python2.7/site-packages/biplist/__init__.py
deleted file mode 100644
index f9d5836dd..000000000
--- a/src/3rdparty/python/lib/python2.7/site-packages/biplist/__init__.py
+++ /dev/null
@@ -1,977 +0,0 @@
-"""biplist -- a library for reading and writing binary property list files.
-
-Binary Property List (plist) files provide a faster and smaller serialization
-format for property lists on OS X. This is a library for generating binary
-plists which can be read by OS X, iOS, or other clients.
-
-The API models the plistlib API, and will call through to plistlib when
-XML serialization or deserialization is required.
-
-To generate plists with UID values, wrap the values with the Uid object. The
-value must be an int.
-
-To generate plists with NSData/CFData values, wrap the values with the
-Data object. The value must be a string.
-
-Date values can only be datetime.datetime objects.
-
-The exceptions InvalidPlistException and NotBinaryPlistException may be
-thrown to indicate that the data cannot be serialized or deserialized as
-a binary plist.
-
-Plist generation example:
-
- from biplist import *
- from datetime import datetime
- plist = {'aKey':'aValue',
- '0':1.322,
- 'now':datetime.now(),
- 'list':[1,2,3],
- 'tuple':('a','b','c')
- }
- try:
- writePlist(plist, "example.plist")
- except (InvalidPlistException, NotBinaryPlistException), e:
- print "Something bad happened:", e
-
-Plist parsing example:
-
- from biplist import *
- try:
- plist = readPlist("example.plist")
- print plist
- except (InvalidPlistException, NotBinaryPlistException), e:
- print "Not a plist:", e
-"""
-
-from collections import namedtuple
-import datetime
-import io
-import math
-import plistlib
-from struct import pack, unpack, unpack_from
-from struct import error as struct_error
-import sys
-import time
-
-try:
- unicode
- unicodeEmpty = r''
-except NameError:
- unicode = str
- unicodeEmpty = ''
-try:
- long
-except NameError:
- long = int
-try:
- {}.iteritems
- iteritems = lambda x: x.iteritems()
-except AttributeError:
- iteritems = lambda x: x.items()
-
-__all__ = [
- 'Uid', 'Data', 'readPlist', 'writePlist', 'readPlistFromString',
- 'writePlistToString', 'InvalidPlistException', 'NotBinaryPlistException'
-]
-
-# Apple uses Jan 1, 2001 as a base for all plist date/times.
-apple_reference_date = datetime.datetime.utcfromtimestamp(978307200)
-
-class Uid(object):
- """Wrapper around integers for representing UID values. This
- is used in keyed archiving."""
- integer = 0
- def __init__(self, integer):
- self.integer = integer
-
- def __repr__(self):
- return "Uid(%d)" % self.integer
-
- def __eq__(self, other):
- if isinstance(self, Uid) and isinstance(other, Uid):
- return self.integer == other.integer
- return False
-
- def __cmp__(self, other):
- return self.integer - other.integer
-
- def __lt__(self, other):
- return self.integer < other.integer
-
- def __hash__(self):
- return self.integer
-
- def __int__(self):
- return int(self.integer)
-
-class Data(bytes):
- """Wrapper around bytes to distinguish Data values."""
-
-class InvalidPlistException(Exception):
- """Raised when the plist is incorrectly formatted."""
-
-class NotBinaryPlistException(Exception):
- """Raised when a binary plist was expected but not encountered."""
-
-def readPlist(pathOrFile):
- """Raises NotBinaryPlistException, InvalidPlistException"""
- didOpen = False
- result = None
- if isinstance(pathOrFile, (bytes, unicode)):
- pathOrFile = open(pathOrFile, 'rb')
- didOpen = True
- try:
- reader = PlistReader(pathOrFile)
- result = reader.parse()
- except NotBinaryPlistException as e:
- try:
- pathOrFile.seek(0)
- result = None
- if hasattr(plistlib, 'loads'):
- contents = None
- if isinstance(pathOrFile, (bytes, unicode)):
- with open(pathOrFile, 'rb') as f:
- contents = f.read()
- else:
- contents = pathOrFile.read()
- result = plistlib.loads(contents)
- else:
- result = plistlib.readPlist(pathOrFile)
- result = wrapDataObject(result, for_binary=True)
- except Exception as e:
- raise InvalidPlistException(e)
- finally:
- if didOpen:
- pathOrFile.close()
- return result
-
-def wrapDataObject(o, for_binary=False):
- if isinstance(o, Data) and not for_binary:
- v = sys.version_info
- if not (v[0] >= 3 and v[1] >= 4):
- o = plistlib.Data(o)
- elif isinstance(o, (bytes, plistlib.Data)) and for_binary:
- if hasattr(o, 'data'):
- o = Data(o.data)
- elif isinstance(o, tuple):
- o = wrapDataObject(list(o), for_binary)
- o = tuple(o)
- elif isinstance(o, list):
- for i in range(len(o)):
- o[i] = wrapDataObject(o[i], for_binary)
- elif isinstance(o, dict):
- for k in o:
- o[k] = wrapDataObject(o[k], for_binary)
- return o
-
-def writePlist(rootObject, pathOrFile, binary=True):
- if not binary:
- rootObject = wrapDataObject(rootObject, binary)
- if hasattr(plistlib, "dump"):
- if isinstance(pathOrFile, (bytes, unicode)):
- with open(pathOrFile, 'wb') as f:
- return plistlib.dump(rootObject, f)
- else:
- return plistlib.dump(rootObject, pathOrFile)
- else:
- return plistlib.writePlist(rootObject, pathOrFile)
- else:
- didOpen = False
- if isinstance(pathOrFile, (bytes, unicode)):
- pathOrFile = open(pathOrFile, 'wb')
- didOpen = True
- writer = PlistWriter(pathOrFile)
- result = writer.writeRoot(rootObject)
- if didOpen:
- pathOrFile.close()
- return result
-
-def readPlistFromString(data):
- return readPlist(io.BytesIO(data))
-
-def writePlistToString(rootObject, binary=True):
- if not binary:
- rootObject = wrapDataObject(rootObject, binary)
- if hasattr(plistlib, "dumps"):
- return plistlib.dumps(rootObject)
- elif hasattr(plistlib, "writePlistToBytes"):
- return plistlib.writePlistToBytes(rootObject)
- else:
- return plistlib.writePlistToString(rootObject)
- else:
- ioObject = io.BytesIO()
- writer = PlistWriter(ioObject)
- writer.writeRoot(rootObject)
- return ioObject.getvalue()
-
-def is_stream_binary_plist(stream):
- stream.seek(0)
- header = stream.read(7)
- if header == b'bplist0':
- return True
- else:
- return False
-
-PlistTrailer = namedtuple('PlistTrailer', 'offsetSize, objectRefSize, offsetCount, topLevelObjectNumber, offsetTableOffset')
-PlistByteCounts = namedtuple('PlistByteCounts', 'nullBytes, boolBytes, intBytes, realBytes, dateBytes, dataBytes, stringBytes, uidBytes, arrayBytes, setBytes, dictBytes')
-
-class PlistReader(object):
- file = None
- contents = ''
- offsets = None
- trailer = None
- currentOffset = 0
- # Used to detect recursive object references.
- offsetsStack = []
-
- def __init__(self, fileOrStream):
- """Raises NotBinaryPlistException."""
- self.reset()
- self.file = fileOrStream
-
- def parse(self):
- return self.readRoot()
-
- def reset(self):
- self.trailer = None
- self.contents = ''
- self.offsets = []
- self.currentOffset = 0
- self.offsetsStack = []
-
- def readRoot(self):
- result = None
- self.reset()
- # Get the header, make sure it's a valid file.
- if not is_stream_binary_plist(self.file):
- raise NotBinaryPlistException()
- self.file.seek(0)
- self.contents = self.file.read()
- if len(self.contents) < 32:
- raise InvalidPlistException("File is too short.")
- trailerContents = self.contents[-32:]
- try:
- self.trailer = PlistTrailer._make(unpack("!xxxxxxBBQQQ", trailerContents))
-
- if pow(2, self.trailer.offsetSize*8) < self.trailer.offsetTableOffset:
- raise InvalidPlistException("Offset size insufficient to reference all objects.")
-
- if pow(2, self.trailer.objectRefSize*8) < self.trailer.offsetCount:
- raise InvalidPlistException("Too many offsets to represent in size of object reference representation.")
-
- offset_size = self.trailer.offsetSize * self.trailer.offsetCount
- offset = self.trailer.offsetTableOffset
-
- if offset + offset_size > pow(2, 64):
- raise InvalidPlistException("Offset table is excessively long.")
-
- if self.trailer.offsetSize > 16:
- raise InvalidPlistException("Offset size is greater than maximum integer size.")
-
- if self.trailer.objectRefSize == 0:
- raise InvalidPlistException("Object reference size is zero.")
-
- if offset >= len(self.contents) - 32:
- raise InvalidPlistException("Offset table offset is too large.")
-
- if offset < len("bplist00x"):
- raise InvalidPlistException("Offset table offset is too small.")
-
- if self.trailer.topLevelObjectNumber >= self.trailer.offsetCount:
- raise InvalidPlistException("Top level object number is larger than the number of objects.")
-
- offset_contents = self.contents[offset:offset+offset_size]
- offset_i = 0
- offset_table_length = len(offset_contents)
-
- while offset_i < self.trailer.offsetCount:
- begin = self.trailer.offsetSize*offset_i
- end = begin+self.trailer.offsetSize
- if end > offset_table_length:
- raise InvalidPlistException("End of object is at invalid offset %d in offset table of length %d" % (end, offset_table_length))
- tmp_contents = offset_contents[begin:end]
- tmp_sized = self.getSizedInteger(tmp_contents, self.trailer.offsetSize)
- self.offsets.append(tmp_sized)
- offset_i += 1
- self.setCurrentOffsetToObjectNumber(self.trailer.topLevelObjectNumber)
- result = self.readObject()
- except TypeError as e:
- raise InvalidPlistException(e)
- return result
-
- def setCurrentOffsetToObjectNumber(self, objectNumber):
- if objectNumber > len(self.offsets) - 1:
- raise InvalidPlistException("Invalid offset number: %d" % objectNumber)
- self.currentOffset = self.offsets[objectNumber]
- if self.currentOffset in self.offsetsStack:
- raise InvalidPlistException("Recursive data structure detected in object: %d" % objectNumber)
-
- def beginOffsetProtection(self):
- self.offsetsStack.append(self.currentOffset)
- return self.currentOffset
-
- def endOffsetProtection(self, offset):
- try:
- index = self.offsetsStack.index(offset)
- self.offsetsStack = self.offsetsStack[:index]
- except ValueError as e:
- pass
-
- def readObject(self):
- protection = self.beginOffsetProtection()
- result = None
- tmp_byte = self.contents[self.currentOffset:self.currentOffset+1]
- if len(tmp_byte) != 1:
- raise InvalidPlistException("No object found at offset: %d" % self.currentOffset)
- marker_byte = unpack("!B", tmp_byte)[0]
- format = (marker_byte >> 4) & 0x0f
- extra = marker_byte & 0x0f
- self.currentOffset += 1
-
- def proc_extra(extra):
- if extra == 0b1111:
- extra = self.readObject()
- return extra
-
- # bool, null, or fill byte
- if format == 0b0000:
- if extra == 0b0000:
- result = None
- elif extra == 0b1000:
- result = False
- elif extra == 0b1001:
- result = True
- elif extra == 0b1111:
- pass # fill byte
- else:
- raise InvalidPlistException("Invalid object found at offset: %d" % (self.currentOffset - 1))
- # int
- elif format == 0b0001:
- result = self.readInteger(pow(2, extra))
- # real
- elif format == 0b0010:
- result = self.readReal(extra)
- # date
- elif format == 0b0011 and extra == 0b0011:
- result = self.readDate()
- # data
- elif format == 0b0100:
- extra = proc_extra(extra)
- result = self.readData(extra)
- # ascii string
- elif format == 0b0101:
- extra = proc_extra(extra)
- result = self.readAsciiString(extra)
- # Unicode string
- elif format == 0b0110:
- extra = proc_extra(extra)
- result = self.readUnicode(extra)
- # uid
- elif format == 0b1000:
- result = self.readUid(extra)
- # array
- elif format == 0b1010:
- extra = proc_extra(extra)
- result = self.readArray(extra)
- # set
- elif format == 0b1100:
- extra = proc_extra(extra)
- result = set(self.readArray(extra))
- # dict
- elif format == 0b1101:
- extra = proc_extra(extra)
- result = self.readDict(extra)
- else:
- raise InvalidPlistException("Invalid object found: {format: %s, extra: %s}" % (bin(format), bin(extra)))
- self.endOffsetProtection(protection)
- return result
-
- def readContents(self, length, description="Object contents"):
- end = self.currentOffset + length
- if end >= len(self.contents) - 32:
- raise InvalidPlistException("%s extends into trailer" % description)
- elif length < 0:
- raise InvalidPlistException("%s length is less than zero" % length)
- data = self.contents[self.currentOffset:end]
- return data
-
- def readInteger(self, byteSize):
- data = self.readContents(byteSize, "Integer")
- self.currentOffset = self.currentOffset + byteSize
- return self.getSizedInteger(data, byteSize, as_number=True)
-
- def readReal(self, length):
- to_read = pow(2, length)
- data = self.readContents(to_read, "Real")
- if length == 2: # 4 bytes
- result = unpack('>f', data)[0]
- elif length == 3: # 8 bytes
- result = unpack('>d', data)[0]
- else:
- raise InvalidPlistException("Unknown Real of length %d bytes" % to_read)
- return result
-
- def readRefs(self, count):
- refs = []
- i = 0
- while i < count:
- fragment = self.readContents(self.trailer.objectRefSize, "Object reference")
- ref = self.getSizedInteger(fragment, len(fragment))
- refs.append(ref)
- self.currentOffset += self.trailer.objectRefSize
- i += 1
- return refs
-
- def readArray(self, count):
- if not isinstance(count, (int, long)):
- raise InvalidPlistException("Count of entries in dict isn't of integer type.")
- result = []
- values = self.readRefs(count)
- i = 0
- while i < len(values):
- self.setCurrentOffsetToObjectNumber(values[i])
- value = self.readObject()
- result.append(value)
- i += 1
- return result
-
- def readDict(self, count):
- if not isinstance(count, (int, long)):
- raise InvalidPlistException("Count of keys/values in dict isn't of integer type.")
- result = {}
- keys = self.readRefs(count)
- values = self.readRefs(count)
- i = 0
- while i < len(keys):
- self.setCurrentOffsetToObjectNumber(keys[i])
- key = self.readObject()
- self.setCurrentOffsetToObjectNumber(values[i])
- value = self.readObject()
- result[key] = value
- i += 1
- return result
-
- def readAsciiString(self, length):
- if not isinstance(length, (int, long)):
- raise InvalidPlistException("Length of ASCII string isn't of integer type.")
- data = self.readContents(length, "ASCII string")
- result = unpack("!%ds" % length, data)[0]
- self.currentOffset += length
- return str(result.decode('ascii'))
-
- def readUnicode(self, length):
- if not isinstance(length, (int, long)):
- raise InvalidPlistException("Length of Unicode string isn't of integer type.")
- actual_length = length*2
- data = self.readContents(actual_length, "Unicode string")
- self.currentOffset += actual_length
- return data.decode('utf_16_be')
-
- def readDate(self):
- data = self.readContents(8, "Date")
- x = unpack(">d", data)[0]
- if math.isnan(x):
- raise InvalidPlistException("Date is NaN")
- # Use timedelta to workaround time_t size limitation on 32-bit python.
- try:
- result = datetime.timedelta(seconds=x) + apple_reference_date
- except OverflowError:
- if x > 0:
- result = datetime.datetime.max
- else:
- result = datetime.datetime.min
- self.currentOffset += 8
- return result
-
- def readData(self, length):
- if not isinstance(length, (int, long)):
- raise InvalidPlistException("Length of data isn't of integer type.")
- result = self.readContents(length, "Data")
- self.currentOffset += length
- return Data(result)
-
- def readUid(self, length):
- if not isinstance(length, (int, long)):
- raise InvalidPlistException("Uid length isn't of integer type.")
- return Uid(self.readInteger(length+1))
-
- def getSizedInteger(self, data, byteSize, as_number=False):
- """Numbers of 8 bytes are signed integers when they refer to numbers, but unsigned otherwise."""
- result = 0
- if byteSize == 0:
- raise InvalidPlistException("Encountered integer with byte size of 0.")
- # 1, 2, and 4 byte integers are unsigned
- elif byteSize == 1:
- result = unpack('>B', data)[0]
- elif byteSize == 2:
- result = unpack('>H', data)[0]
- elif byteSize == 4:
- result = unpack('>L', data)[0]
- elif byteSize == 8:
- if as_number:
- result = unpack('>q', data)[0]
- else:
- result = unpack('>Q', data)[0]
- elif byteSize <= 16:
- # Handle odd-sized or integers larger than 8 bytes
- # Don't naively go over 16 bytes, in order to prevent infinite loops.
- result = 0
- if hasattr(int, 'from_bytes'):
- result = int.from_bytes(data, 'big')
- else:
- for byte in data:
- if not isinstance(byte, int): # Python3.0-3.1.x return ints, 2.x return str
- byte = unpack_from('>B', byte)[0]
- result = (result << 8) | byte
- else:
- raise InvalidPlistException("Encountered integer longer than 16 bytes.")
- return result
-
-class HashableWrapper(object):
- def __init__(self, value):
- self.value = value
- def __repr__(self):
- return "<HashableWrapper: %s>" % [self.value]
-
-class BoolWrapper(object):
- def __init__(self, value):
- self.value = value
- def __repr__(self):
- return "<BoolWrapper: %s>" % self.value
-
-class FloatWrapper(object):
- _instances = {}
- def __new__(klass, value):
- # Ensure FloatWrapper(x) for a given float x is always the same object
- wrapper = klass._instances.get(value)
- if wrapper is None:
- wrapper = object.__new__(klass)
- wrapper.value = value
- klass._instances[value] = wrapper
- return wrapper
- def __repr__(self):
- return "<FloatWrapper: %s>" % self.value
-
-class StringWrapper(object):
- __instances = {}
-
- encodedValue = None
- encoding = None
-
- def __new__(cls, value):
- '''Ensure we only have a only one instance for any string,
- and that we encode ascii as 1-byte-per character when possible'''
-
- encodedValue = None
-
- for encoding in ('ascii', 'utf_16_be'):
- try:
- encodedValue = value.encode(encoding)
- except: pass
- if encodedValue is not None:
- if encodedValue not in cls.__instances:
- cls.__instances[encodedValue] = super(StringWrapper, cls).__new__(cls)
- cls.__instances[encodedValue].encodedValue = encodedValue
- cls.__instances[encodedValue].encoding = encoding
- return cls.__instances[encodedValue]
-
- raise ValueError('Unable to get ascii or utf_16_be encoding for %s' % repr(value))
-
- def __len__(self):
- '''Return roughly the number of characters in this string (half the byte length)'''
- if self.encoding == 'ascii':
- return len(self.encodedValue)
- else:
- return len(self.encodedValue)//2
-
- def __lt__(self, other):
- return self.encodedValue < other.encodedValue
-
- @property
- def encodingMarker(self):
- if self.encoding == 'ascii':
- return 0b0101
- else:
- return 0b0110
-
- def __repr__(self):
- return '<StringWrapper (%s): %s>' % (self.encoding, self.encodedValue)
-
-class PlistWriter(object):
- header = b'bplist00bybiplist1.0'
- file = None
- byteCounts = None
- trailer = None
- computedUniques = None
- writtenReferences = None
- referencePositions = None
- wrappedTrue = None
- wrappedFalse = None
- # Used to detect recursive object references.
- objectsStack = []
-
- def __init__(self, file):
- self.reset()
- self.file = file
- self.wrappedTrue = BoolWrapper(True)
- self.wrappedFalse = BoolWrapper(False)
-
- def reset(self):
- self.byteCounts = PlistByteCounts(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
- self.trailer = PlistTrailer(0, 0, 0, 0, 0)
-
- # A set of all the uniques which have been computed.
- self.computedUniques = set()
- # A list of all the uniques which have been written.
- self.writtenReferences = {}
- # A dict of the positions of the written uniques.
- self.referencePositions = {}
-
- self.objectsStack = []
-
- def positionOfObjectReference(self, obj):
- """If the given object has been written already, return its
- position in the offset table. Otherwise, return None."""
- return self.writtenReferences.get(obj)
-
- def writeRoot(self, root):
- """
- Strategy is:
- - write header
- - wrap root object so everything is hashable
- - compute size of objects which will be written
- - need to do this in order to know how large the object refs
- will be in the list/dict/set reference lists
- - write objects
- - keep objects in writtenReferences
- - keep positions of object references in referencePositions
- - write object references with the length computed previously
- - computer object reference length
- - write object reference positions
- - write trailer
- """
- output = self.header
- wrapped_root = self.wrapRoot(root)
- self.computeOffsets(wrapped_root, asReference=True, isRoot=True)
- self.trailer = self.trailer._replace(**{'objectRefSize':self.intSize(len(self.computedUniques))})
- self.writeObjectReference(wrapped_root, output)
- output = self.writeObject(wrapped_root, output, setReferencePosition=True)
-
- # output size at this point is an upper bound on how big the
- # object reference offsets need to be.
- self.trailer = self.trailer._replace(**{
- 'offsetSize':self.intSize(len(output)),
- 'offsetCount':len(self.computedUniques),
- 'offsetTableOffset':len(output),
- 'topLevelObjectNumber':0
- })
-
- output = self.writeOffsetTable(output)
- output += pack('!xxxxxxBBQQQ', *self.trailer)
- self.file.write(output)
-
- def beginRecursionProtection(self, obj):
- if not isinstance(obj, (set, dict, list, tuple)):
- return
- if id(obj) in self.objectsStack:
- raise InvalidPlistException("Recursive containers are not allowed in plists.")
- self.objectsStack.append(id(obj))
-
- def endRecursionProtection(self, obj):
- if not isinstance(obj, (set, dict, list, tuple)):
- return
- try:
- index = self.objectsStack.index(id(obj))
- self.objectsStack = self.objectsStack[:index]
- except ValueError as e:
- pass
-
- def wrapRoot(self, root):
- result = None
- self.beginRecursionProtection(root)
-
- if isinstance(root, bool):
- if root is True:
- result = self.wrappedTrue
- else:
- result = self.wrappedFalse
- elif isinstance(root, float):
- result = FloatWrapper(root)
- elif isinstance(root, set):
- n = set()
- for value in root:
- n.add(self.wrapRoot(value))
- result = HashableWrapper(n)
- elif isinstance(root, dict):
- n = {}
- for key, value in iteritems(root):
- n[self.wrapRoot(key)] = self.wrapRoot(value)
- result = HashableWrapper(n)
- elif isinstance(root, list):
- n = []
- for value in root:
- n.append(self.wrapRoot(value))
- result = HashableWrapper(n)
- elif isinstance(root, tuple):
- n = tuple([self.wrapRoot(value) for value in root])
- result = HashableWrapper(n)
- elif isinstance(root, (str, unicode)) and not isinstance(root, Data):
- result = StringWrapper(root)
- elif isinstance(root, bytes):
- result = Data(root)
- else:
- result = root
-
- self.endRecursionProtection(root)
- return result
-
- def incrementByteCount(self, field, incr=1):
- self.byteCounts = self.byteCounts._replace(**{field:self.byteCounts.__getattribute__(field) + incr})
-
- def computeOffsets(self, obj, asReference=False, isRoot=False):
- def check_key(key):
- if key is None:
- raise InvalidPlistException('Dictionary keys cannot be null in plists.')
- elif isinstance(key, Data):
- raise InvalidPlistException('Data cannot be dictionary keys in plists.')
- elif not isinstance(key, StringWrapper):
- raise InvalidPlistException('Keys must be strings.')
-
- def proc_size(size):
- if size > 0b1110:
- size += self.intSize(size)
- return size
- # If this should be a reference, then we keep a record of it in the
- # uniques table.
- if asReference:
- if obj in self.computedUniques:
- return
- else:
- self.computedUniques.add(obj)
-
- if obj is None:
- self.incrementByteCount('nullBytes')
- elif isinstance(obj, BoolWrapper):
- self.incrementByteCount('boolBytes')
- elif isinstance(obj, Uid):
- size = self.intSize(obj.integer)
- self.incrementByteCount('uidBytes', incr=1+size)
- elif isinstance(obj, (int, long)):
- size = self.intSize(obj)
- self.incrementByteCount('intBytes', incr=1+size)
- elif isinstance(obj, FloatWrapper):
- size = self.realSize(obj)
- self.incrementByteCount('realBytes', incr=1+size)
- elif isinstance(obj, datetime.datetime):
- self.incrementByteCount('dateBytes', incr=2)
- elif isinstance(obj, Data):
- size = proc_size(len(obj))
- self.incrementByteCount('dataBytes', incr=1+size)
- elif isinstance(obj, StringWrapper):
- size = proc_size(len(obj))
- self.incrementByteCount('stringBytes', incr=1+size)
- elif isinstance(obj, HashableWrapper):
- obj = obj.value
- if isinstance(obj, set):
- size = proc_size(len(obj))
- self.incrementByteCount('setBytes', incr=1+size)
- for value in obj:
- self.computeOffsets(value, asReference=True)
- elif isinstance(obj, (list, tuple)):
- size = proc_size(len(obj))
- self.incrementByteCount('arrayBytes', incr=1+size)
- for value in obj:
- asRef = True
- self.computeOffsets(value, asReference=True)
- elif isinstance(obj, dict):
- size = proc_size(len(obj))
- self.incrementByteCount('dictBytes', incr=1+size)
- for key, value in iteritems(obj):
- check_key(key)
- self.computeOffsets(key, asReference=True)
- self.computeOffsets(value, asReference=True)
- else:
- raise InvalidPlistException("Unknown object type: %s (%s)" % (type(obj).__name__, repr(obj)))
-
- def writeObjectReference(self, obj, output):
- """Tries to write an object reference, adding it to the references
- table. Does not write the actual object bytes or set the reference
- position. Returns a tuple of whether the object was a new reference
- (True if it was, False if it already was in the reference table)
- and the new output.
- """
- position = self.positionOfObjectReference(obj)
- if position is None:
- self.writtenReferences[obj] = len(self.writtenReferences)
- output += self.binaryInt(len(self.writtenReferences) - 1, byteSize=self.trailer.objectRefSize)
- return (True, output)
- else:
- output += self.binaryInt(position, byteSize=self.trailer.objectRefSize)
- return (False, output)
-
- def writeObject(self, obj, output, setReferencePosition=False):
- """Serializes the given object to the output. Returns output.
- If setReferencePosition is True, will set the position the
- object was written.
- """
- def proc_variable_length(format, length):
- result = b''
- if length > 0b1110:
- result += pack('!B', (format << 4) | 0b1111)
- result = self.writeObject(length, result)
- else:
- result += pack('!B', (format << 4) | length)
- return result
-
- def timedelta_total_seconds(td):
- # Shim for Python 2.6 compatibility, which doesn't have total_seconds.
- # Make one argument a float to ensure the right calculation.
- return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10.0**6) / 10.0**6
-
- if setReferencePosition:
- self.referencePositions[obj] = len(output)
-
- if obj is None:
- output += pack('!B', 0b00000000)
- elif isinstance(obj, BoolWrapper):
- if obj.value is False:
- output += pack('!B', 0b00001000)
- else:
- output += pack('!B', 0b00001001)
- elif isinstance(obj, Uid):
- size = self.intSize(obj.integer)
- output += pack('!B', (0b1000 << 4) | size - 1)
- output += self.binaryInt(obj.integer)
- elif isinstance(obj, (int, long)):
- byteSize = self.intSize(obj)
- root = math.log(byteSize, 2)
- output += pack('!B', (0b0001 << 4) | int(root))
- output += self.binaryInt(obj, as_number=True)
- elif isinstance(obj, FloatWrapper):
- # just use doubles
- output += pack('!B', (0b0010 << 4) | 3)
- output += self.binaryReal(obj)
- elif isinstance(obj, datetime.datetime):
- try:
- timestamp = (obj - apple_reference_date).total_seconds()
- except AttributeError:
- timestamp = timedelta_total_seconds(obj - apple_reference_date)
- output += pack('!B', 0b00110011)
- output += pack('!d', float(timestamp))
- elif isinstance(obj, Data):
- output += proc_variable_length(0b0100, len(obj))
- output += obj
- elif isinstance(obj, StringWrapper):
- output += proc_variable_length(obj.encodingMarker, len(obj))
- output += obj.encodedValue
- elif isinstance(obj, bytes):
- output += proc_variable_length(0b0101, len(obj))
- output += obj
- elif isinstance(obj, HashableWrapper):
- obj = obj.value
- if isinstance(obj, (set, list, tuple)):
- if isinstance(obj, set):
- output += proc_variable_length(0b1100, len(obj))
- else:
- output += proc_variable_length(0b1010, len(obj))
-
- objectsToWrite = []
- for objRef in sorted(obj) if isinstance(obj, set) else obj:
- (isNew, output) = self.writeObjectReference(objRef, output)
- if isNew:
- objectsToWrite.append(objRef)
- for objRef in objectsToWrite:
- output = self.writeObject(objRef, output, setReferencePosition=True)
- elif isinstance(obj, dict):
- output += proc_variable_length(0b1101, len(obj))
- keys = []
- values = []
- objectsToWrite = []
- for key, value in sorted(iteritems(obj)):
- keys.append(key)
- values.append(value)
- for key in keys:
- (isNew, output) = self.writeObjectReference(key, output)
- if isNew:
- objectsToWrite.append(key)
- for value in values:
- (isNew, output) = self.writeObjectReference(value, output)
- if isNew:
- objectsToWrite.append(value)
- for objRef in objectsToWrite:
- output = self.writeObject(objRef, output, setReferencePosition=True)
- return output
-
- def writeOffsetTable(self, output):
- """Writes all of the object reference offsets."""
- all_positions = []
- writtenReferences = list(self.writtenReferences.items())
- writtenReferences.sort(key=lambda x: x[1])
- for obj,order in writtenReferences:
- # Porting note: Elsewhere we deliberately replace empty unicdoe strings
- # with empty binary strings, but the empty unicode string
- # goes into writtenReferences. This isn't an issue in Py2
- # because u'' and b'' have the same hash; but it is in
- # Py3, where they don't.
- if bytes != str and obj == unicodeEmpty:
- obj = b''
- position = self.referencePositions.get(obj)
- if position is None:
- raise InvalidPlistException("Error while writing offsets table. Object not found. %s" % obj)
- output += self.binaryInt(position, self.trailer.offsetSize)
- all_positions.append(position)
- return output
-
- def binaryReal(self, obj):
- # just use doubles
- result = pack('>d', obj.value)
- return result
-
- def binaryInt(self, obj, byteSize=None, as_number=False):
- result = b''
- if byteSize is None:
- byteSize = self.intSize(obj)
- if byteSize == 1:
- result += pack('>B', obj)
- elif byteSize == 2:
- result += pack('>H', obj)
- elif byteSize == 4:
- result += pack('>L', obj)
- elif byteSize == 8:
- if as_number:
- result += pack('>q', obj)
- else:
- result += pack('>Q', obj)
- elif byteSize <= 16:
- try:
- result = pack('>Q', 0) + pack('>Q', obj)
- except struct_error as e:
- raise InvalidPlistException("Unable to pack integer %d: %s" % (obj, e))
- else:
- raise InvalidPlistException("Core Foundation can't handle integers with size greater than 16 bytes.")
- return result
-
- def intSize(self, obj):
- """Returns the number of bytes necessary to store the given integer."""
- # SIGNED
- if obj < 0: # Signed integer, always 8 bytes
- return 8
- # UNSIGNED
- elif obj <= 0xFF: # 1 byte
- return 1
- elif obj <= 0xFFFF: # 2 bytes
- return 2
- elif obj <= 0xFFFFFFFF: # 4 bytes
- return 4
- # SIGNED
- # 0x7FFFFFFFFFFFFFFF is the max.
- elif obj <= 0x7FFFFFFFFFFFFFFF: # 8 bytes signed
- return 8
- elif obj <= 0xffffffffffffffff: # 8 bytes unsigned
- return 16
- else:
- raise InvalidPlistException("Core Foundation can't handle integers with size greater than 8 bytes.")
-
- def realSize(self, obj):
- return 8
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/biplist/qt_attribution.json b/src/3rdparty/python/lib/python2.7/site-packages/biplist/qt_attribution.json
deleted file mode 100644
index 266e9dd89..000000000
--- a/src/3rdparty/python/lib/python2.7/site-packages/biplist/qt_attribution.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "Id": "biplist",
- "Name": "biplist",
- "QDocModule": "qbs",
- "QtUsage": "Used in the qbs dmg module for building Apple disk images.",
- "Description": "biplist is a library for reading/writing binary plists.",
- "Homepage": "https://bitbucket.org/wooster/biplist",
- "Version": "1.0.2",
- "License": "BSD 3-clause \"New\" or \"Revised\" License",
- "LicenseId": "BSD-3-Clause",
- "LicenseFile": "LICENSE",
- "Copyright": "Copyright (c) 2010, Andrew Wooster"
-}
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/ds_store/__init__.py b/src/3rdparty/python/lib/python2.7/site-packages/ds_store/__init__.py
deleted file mode 100644
index a6b812104..000000000
--- a/src/3rdparty/python/lib/python2.7/site-packages/ds_store/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from .store import DSStore, DSStoreEntry
-
-__all__ = ['DSStore', 'DSStoreEntry']
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/__init__.py b/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/__init__.py
deleted file mode 100644
index 7eb314107..000000000
--- a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from .alias import *
-from .bookmark import *
-
-__all__ = [ 'ALIAS_KIND_FILE', 'ALIAS_KIND_FOLDER',
- 'ALIAS_HFS_VOLUME_SIGNATURE',
- 'ALIAS_FIXED_DISK', 'ALIAS_NETWORK_DISK', 'ALIAS_400KB_FLOPPY_DISK',
- 'ALIAS_800KB_FLOPPY_DISK', 'ALIAS_1_44MB_FLOPPY_DISK',
- 'ALIAS_EJECTABLE_DISK',
- 'ALIAS_NO_CNID',
- 'kBookmarkPath', 'kBookmarkCNIDPath', 'kBookmarkFileProperties',
- 'kBookmarkFileName', 'kBookmarkFileID', 'kBookmarkFileCreationDate',
- 'kBookmarkTOCPath', 'kBookmarkVolumePath',
- 'kBookmarkVolumeURL', 'kBookmarkVolumeName', 'kBookmarkVolumeUUID',
- 'kBookmarkVolumeSize', 'kBookmarkVolumeCreationDate',
- 'kBookmarkVolumeProperties', 'kBookmarkContainingFolder',
- 'kBookmarkUserName', 'kBookmarkUID', 'kBookmarkWasFileReference',
- 'kBookmarkCreationOptions', 'kBookmarkURLLengths',
- 'kBookmarkSecurityExtension',
- 'AppleShareInfo',
- 'VolumeInfo',
- 'TargetInfo',
- 'Alias',
- 'Bookmark',
- 'Data',
- 'URL' ]
-
-
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/bookmark.py b/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/bookmark.py
deleted file mode 100644
index 0de6b9404..000000000
--- a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/bookmark.py
+++ /dev/null
@@ -1,665 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# This file implements the Apple "bookmark" format, which is the replacement
-# for the old-fashioned alias format. The details of this format were
-# reverse engineered; some things are still not entirely clear.
-#
-from __future__ import unicode_literals, print_function
-
-import struct
-import uuid
-import datetime
-import os
-import sys
-import pprint
-
-try:
- from urlparse import urljoin
-except ImportError:
- from urllib.parse import urljoin
-
-if sys.platform == 'darwin':
- from . import osx
-
-def iteritems(x):
- return x.iteritems()
-
-try:
- unicode
-except NameError:
- unicode = str
- long = int
- xrange = range
- def iteritems(x):
- return x.items()
-
-from .utils import *
-
-BMK_DATA_TYPE_MASK = 0xffffff00
-BMK_DATA_SUBTYPE_MASK = 0x000000ff
-
-BMK_STRING = 0x0100
-BMK_DATA = 0x0200
-BMK_NUMBER = 0x0300
-BMK_DATE = 0x0400
-BMK_BOOLEAN = 0x0500
-BMK_ARRAY = 0x0600
-BMK_DICT = 0x0700
-BMK_UUID = 0x0800
-BMK_URL = 0x0900
-BMK_NULL = 0x0a00
-
-BMK_ST_ZERO = 0x0000
-BMK_ST_ONE = 0x0001
-
-BMK_BOOLEAN_ST_FALSE = 0x0000
-BMK_BOOLEAN_ST_TRUE = 0x0001
-
-# Subtypes for BMK_NUMBER are really CFNumberType values
-kCFNumberSInt8Type = 1
-kCFNumberSInt16Type = 2
-kCFNumberSInt32Type = 3
-kCFNumberSInt64Type = 4
-kCFNumberFloat32Type = 5
-kCFNumberFloat64Type = 6
-kCFNumberCharType = 7
-kCFNumberShortType = 8
-kCFNumberIntType = 9
-kCFNumberLongType = 10
-kCFNumberLongLongType = 11
-kCFNumberFloatType = 12
-kCFNumberDoubleType = 13
-kCFNumberCFIndexType = 14
-kCFNumberNSIntegerType = 15
-kCFNumberCGFloatType = 16
-
-# Resource property flags (from CFURLPriv.h)
-kCFURLResourceIsRegularFile = 0x00000001
-kCFURLResourceIsDirectory = 0x00000002
-kCFURLResourceIsSymbolicLink = 0x00000004
-kCFURLResourceIsVolume = 0x00000008
-kCFURLResourceIsPackage = 0x00000010
-kCFURLResourceIsSystemImmutable = 0x00000020
-kCFURLResourceIsUserImmutable = 0x00000040
-kCFURLResourceIsHidden = 0x00000080
-kCFURLResourceHasHiddenExtension = 0x00000100
-kCFURLResourceIsApplication = 0x00000200
-kCFURLResourceIsCompressed = 0x00000400
-kCFURLResourceIsSystemCompressed = 0x00000400
-kCFURLCanSetHiddenExtension = 0x00000800
-kCFURLResourceIsReadable = 0x00001000
-kCFURLResourceIsWriteable = 0x00002000
-kCFURLResourceIsExecutable = 0x00004000
-kCFURLIsAliasFile = 0x00008000
-kCFURLIsMountTrigger = 0x00010000
-
-# Volume property flags (from CFURLPriv.h)
-kCFURLVolumeIsLocal = 0x1 #
-kCFURLVolumeIsAutomount = 0x2 #
-kCFURLVolumeDontBrowse = 0x4 #
-kCFURLVolumeIsReadOnly = 0x8 #
-kCFURLVolumeIsQuarantined = 0x10
-kCFURLVolumeIsEjectable = 0x20 #
-kCFURLVolumeIsRemovable = 0x40 #
-kCFURLVolumeIsInternal = 0x80 #
-kCFURLVolumeIsExternal = 0x100 #
-kCFURLVolumeIsDiskImage = 0x200 #
-kCFURLVolumeIsFileVault = 0x400
-kCFURLVolumeIsLocaliDiskMirror = 0x800
-kCFURLVolumeIsiPod = 0x1000 #
-kCFURLVolumeIsiDisk = 0x2000
-kCFURLVolumeIsCD = 0x4000
-kCFURLVolumeIsDVD = 0x8000
-kCFURLVolumeIsDeviceFileSystem = 0x10000
-kCFURLVolumeSupportsPersistentIDs = 0x100000000
-kCFURLVolumeSupportsSearchFS = 0x200000000
-kCFURLVolumeSupportsExchange = 0x400000000
-# reserved 0x800000000
-kCFURLVolumeSupportsSymbolicLinks = 0x1000000000
-kCFURLVolumeSupportsDenyModes = 0x2000000000
-kCFURLVolumeSupportsCopyFile = 0x4000000000
-kCFURLVolumeSupportsReadDirAttr = 0x8000000000
-kCFURLVolumeSupportsJournaling = 0x10000000000
-kCFURLVolumeSupportsRename = 0x20000000000
-kCFURLVolumeSupportsFastStatFS = 0x40000000000
-kCFURLVolumeSupportsCaseSensitiveNames = 0x80000000000
-kCFURLVolumeSupportsCasePreservedNames = 0x100000000000
-kCFURLVolumeSupportsFLock = 0x200000000000
-kCFURLVolumeHasNoRootDirectoryTimes = 0x400000000000
-kCFURLVolumeSupportsExtendedSecurity = 0x800000000000
-kCFURLVolumeSupports2TBFileSize = 0x1000000000000
-kCFURLVolumeSupportsHardLinks = 0x2000000000000
-kCFURLVolumeSupportsMandatoryByteRangeLocks = 0x4000000000000
-kCFURLVolumeSupportsPathFromID = 0x8000000000000
-# reserved 0x10000000000000
-kCFURLVolumeIsJournaling = 0x20000000000000
-kCFURLVolumeSupportsSparseFiles = 0x40000000000000
-kCFURLVolumeSupportsZeroRuns = 0x80000000000000
-kCFURLVolumeSupportsVolumeSizes = 0x100000000000000
-kCFURLVolumeSupportsRemoteEvents = 0x200000000000000
-kCFURLVolumeSupportsHiddenFiles = 0x400000000000000
-kCFURLVolumeSupportsDecmpFSCompression = 0x800000000000000
-kCFURLVolumeHas64BitObjectIDs = 0x1000000000000000
-kCFURLVolumePropertyFlagsAll = 0xffffffffffffffff
-
-BMK_URL_ST_ABSOLUTE = 0x0001
-BMK_URL_ST_RELATIVE = 0x0002
-
-# Bookmark keys
-# = 0x1003
-kBookmarkPath = 0x1004 # Array of path components
-kBookmarkCNIDPath = 0x1005 # Array of CNIDs
-kBookmarkFileProperties = 0x1010 # (CFURL rp flags,
- # CFURL rp flags asked for,
- # 8 bytes NULL)
-kBookmarkFileName = 0x1020
-kBookmarkFileID = 0x1030
-kBookmarkFileCreationDate = 0x1040
-# = 0x1054 # ?
-# = 0x1055 # ?
-# = 0x1056 # ?
-# = 0x1101 # ?
-# = 0x1102 # ?
-kBookmarkTOCPath = 0x2000 # A list of (TOC id, ?) pairs
-kBookmarkVolumePath = 0x2002
-kBookmarkVolumeURL = 0x2005
-kBookmarkVolumeName = 0x2010
-kBookmarkVolumeUUID = 0x2011 # Stored (perversely) as a string
-kBookmarkVolumeSize = 0x2012
-kBookmarkVolumeCreationDate = 0x2013
-kBookmarkVolumeProperties = 0x2020 # (CFURL vp flags,
- # CFURL vp flags asked for,
- # 8 bytes NULL)
-kBookmarkVolumeIsRoot = 0x2030 # True if volume is FS root
-kBookmarkVolumeBookmark = 0x2040 # Embedded bookmark for disk image (TOC id)
-kBookmarkVolumeMountPoint = 0x2050 # A URL
-# = 0x2070
-kBookmarkContainingFolder = 0xc001 # Index of containing folder in path
-kBookmarkUserName = 0xc011 # User that created bookmark
-kBookmarkUID = 0xc012 # UID that created bookmark
-kBookmarkWasFileReference = 0xd001 # True if the URL was a file reference
-kBookmarkCreationOptions = 0xd010
-kBookmarkURLLengths = 0xe003 # See below
-# = 0xf017 # Localized name?
-# = 0xf022
-kBookmarkSecurityExtension = 0xf080
-# = 0xf081
-
-# kBookmarkURLLengths is an array that is set if the URL encoded by the
-# bookmark had a base URL; in that case, each entry is the length of the
-# base URL in question. Thus a URL
-#
-# file:///foo/bar/baz blam/blat.html
-#
-# will result in [3, 2], while the URL
-#
-# file:///foo bar/baz blam blat.html
-#
-# would result in [1, 2, 1, 1]
-
-
-class Data (object):
- def __init__(self, bytedata=None):
- #: The bytes, stored as a byte string
- self.bytes = bytes(bytedata)
-
- def __repr__(self):
- return 'Data(%r)' % self.bytes
-
-class URL (object):
- def __init__(self, base, rel=None):
- if rel is not None:
- #: The base URL, if any (a :class:`URL`)
- self.base = base
- #: The rest of the URL (a string)
- self.relative = rel
- else:
- self.base = None
- self.relative = base
-
- @property
- def absolute(self):
- """Return an absolute URL."""
- if self.base is None:
- return self.relative
- else:
- base_abs = self.base.absolute
- return urljoin(self.base.absolute, self.relative)
-
- def __repr__(self):
- return 'URL(%r)' % self.absolute
-
-class Bookmark (object):
- def __init__(self, tocs=None):
- if tocs is None:
- #: The TOCs for this Bookmark
- self.tocs = []
- else:
- self.tocs = tocs
-
- @classmethod
- def _get_item(cls, data, hdrsize, offset):
- offset += hdrsize
- if offset > len(data) - 8:
- raise ValueError('Offset out of range')
-
- length,typecode = struct.unpack(b'<II', data[offset:offset+8])
-
- if len(data) - offset < 8 + length:
- raise ValueError('Data item truncated')
-
- databytes = data[offset+8:offset+8+length]
-
- dsubtype = typecode & BMK_DATA_SUBTYPE_MASK
- dtype = typecode & BMK_DATA_TYPE_MASK
-
- if dtype == BMK_STRING:
- return databytes.decode('utf-8')
- elif dtype == BMK_DATA:
- return Data(databytes)
- elif dtype == BMK_NUMBER:
- if dsubtype == kCFNumberSInt8Type:
- return ord(databytes[0])
- elif dsubtype == kCFNumberSInt16Type:
- return struct.unpack(b'<h', databytes)[0]
- elif dsubtype == kCFNumberSInt32Type:
- return struct.unpack(b'<i', databytes)[0]
- elif dsubtype == kCFNumberSInt64Type:
- return struct.unpack(b'<q', databytes)[0]
- elif dsubtype == kCFNumberFloat32Type:
- return struct.unpack(b'<f', databytes)[0]
- elif dsubtype == kCFNumberFloat64Type:
- return struct.unpack(b'<d', databytes)[0]
- elif dtype == BMK_DATE:
- # Yes, dates really are stored as *BIG-endian* doubles; everything
- # else is little-endian
- secs = datetime.timedelta(seconds=struct.unpack(b'>d', databytes)[0])
- return osx_epoch + secs
- elif dtype == BMK_BOOLEAN:
- if dsubtype == BMK_BOOLEAN_ST_TRUE:
- return True
- elif dsubtype == BMK_BOOLEAN_ST_FALSE:
- return False
- elif dtype == BMK_UUID:
- return uuid.UUID(bytes=databytes)
- elif dtype == BMK_URL:
- if dsubtype == BMK_URL_ST_ABSOLUTE:
- return URL(databytes.decode('utf-8'))
- elif dsubtype == BMK_URL_ST_RELATIVE:
- baseoff,reloff = struct.unpack(b'<II', databytes)
- base = cls._get_item(data, hdrsize, baseoff)
- rel = cls._get_item(data, hdrsize, reloff)
- return URL(base, rel)
- elif dtype == BMK_ARRAY:
- result = []
- for aoff in xrange(offset+8,offset+8+length,4):
- eltoff, = struct.unpack(b'<I', data[aoff:aoff+4])
- result.append(cls._get_item(data, hdrsize, eltoff))
- return result
- elif dtype == BMK_DICT:
- result = {}
- for eoff in xrange(offset+8,offset+8+length,8):
- keyoff,valoff = struct.unpack(b'<II', data[eoff:eoff+8])
- key = cls._get_item(data, hdrsize, keyoff)
- val = cls._get_item(data, hdrsize, valoff)
- result[key] = val
- return result
- elif dtype == BMK_NULL:
- return None
-
- print('Unknown data type %08x' % typecode)
- return (typecode, databytes)
-
- @classmethod
- def from_bytes(cls, data):
- """Create a :class:`Bookmark` given byte data."""
-
- if len(data) < 16:
- raise ValueError('Not a bookmark file (too short)')
-
- if isinstance(data, bytearray):
- data = bytes(data)
-
- magic,size,dummy,hdrsize = struct.unpack(b'<4sIII', data[0:16])
-
- if magic != b'book':
- raise ValueError('Not a bookmark file (bad magic) %r' % magic)
-
- if hdrsize < 16:
- raise ValueError('Not a bookmark file (header size too short)')
-
- if hdrsize > size:
- raise ValueError('Not a bookmark file (header size too large)')
-
- if size != len(data):
- raise ValueError('Not a bookmark file (truncated)')
-
- tocoffset, = struct.unpack(b'<I', data[hdrsize:hdrsize+4])
-
- tocs = []
-
- while tocoffset != 0:
- tocbase = hdrsize + tocoffset
- if tocoffset > size - hdrsize \
- or size - tocbase < 20:
- raise ValueError('TOC offset out of range')
-
- tocsize,tocmagic,tocid,nexttoc,toccount \
- = struct.unpack(b'<IIIII',
- data[tocbase:tocbase+20])
-
- if tocmagic != 0xfffffffe:
- break
-
- tocsize += 8
-
- if size - tocbase < tocsize:
- raise ValueError('TOC truncated')
-
- if tocsize < 12 * toccount:
- raise ValueError('TOC entries overrun TOC size')
-
- toc = {}
- for n in xrange(0,toccount):
- ebase = tocbase + 20 + 12 * n
- eid,eoffset,edummy = struct.unpack(b'<III',
- data[ebase:ebase+12])
-
- if eid & 0x80000000:
- eid = cls._get_item(data, hdrsize, eid & 0x7fffffff)
-
- toc[eid] = cls._get_item(data, hdrsize, eoffset)
-
- tocs.append((tocid, toc))
-
- tocoffset = nexttoc
-
- return cls(tocs)
-
- def __getitem__(self, key):
- for tid,toc in self.tocs:
- if key in toc:
- return toc[key]
- raise KeyError('Key not found')
-
- def __setitem__(self, key, value):
- if len(self.tocs) == 0:
- self.tocs = [(1, {})]
- self.tocs[0][1][key] = value
-
- def get(self, key, default=None):
- """Lookup the value for a given key, returning a default if not
- present."""
- for tid,toc in self.tocs:
- if key in toc:
- return toc[key]
- return default
-
- @classmethod
- def _encode_item(cls, item, offset):
- if item is True:
- result = struct.pack(b'<II', 0, BMK_BOOLEAN | BMK_BOOLEAN_ST_TRUE)
- elif item is False:
- result = struct.pack(b'<II', 0, BMK_BOOLEAN | BMK_BOOLEAN_ST_FALSE)
- elif isinstance(item, unicode):
- encoded = item.encode('utf-8')
- result = (struct.pack(b'<II', len(encoded), BMK_STRING | BMK_ST_ONE)
- + encoded)
- elif isinstance(item, bytes):
- result = (struct.pack(b'<II', len(item), BMK_STRING | BMK_ST_ONE)
- + item)
- elif isinstance(item, Data):
- result = (struct.pack(b'<II', len(item.bytes),
- BMK_DATA | BMK_ST_ONE)
- + bytes(item.bytes))
- elif isinstance(item, bytearray):
- result = (struct.pack(b'<II', len(item),
- BMK_DATA | BMK_ST_ONE)
- + bytes(item))
- elif isinstance(item, int) or isinstance(item, long):
- if item > -0x80000000 and item < 0x7fffffff:
- result = struct.pack(b'<IIi', 4,
- BMK_NUMBER | kCFNumberSInt32Type, item)
- else:
- result = struct.pack(b'<IIq', 8,
- BMK_NUMBER | kCFNumberSInt64Type, item)
- elif isinstance(item, float):
- result = struct.pack(b'<IId', 8,
- BMK_NUMBER | kCFNumberFloat64Type, item)
- elif isinstance(item, datetime.datetime):
- secs = item - osx_epoch
- result = struct.pack(b'<II', 8, BMK_DATE | BMK_ST_ZERO) \
- + struct.pack(b'>d', float(secs.total_seconds()))
- elif isinstance(item, uuid.UUID):
- result = struct.pack(b'<II', 16, BMK_UUID | BMK_ST_ONE) \
- + item.bytes
- elif isinstance(item, URL):
- if item.base:
- baseoff = offset + 16
- reloff, baseenc = cls._encode_item(item.base, baseoff)
- xoffset, relenc = cls._encode_item(item.relative, reloff)
- result = b''.join([
- struct.pack(b'<IIII', 8, BMK_URL | BMK_URL_ST_RELATIVE,
- baseoff, reloff),
- baseenc,
- relenc])
- else:
- encoded = item.relative.encode('utf-8')
- result = struct.pack(b'<II', len(encoded),
- BMK_URL | BMK_URL_ST_ABSOLUTE) + encoded
- elif isinstance(item, list):
- ioffset = offset + 8 + len(item) * 4
- result = [struct.pack(b'<II', len(item) * 4, BMK_ARRAY | BMK_ST_ONE)]
- enc = []
- for elt in item:
- result.append(struct.pack(b'<I', ioffset))
- ioffset, ienc = cls._encode_item(elt, ioffset)
- enc.append(ienc)
- result = b''.join(result + enc)
- elif isinstance(item, dict):
- ioffset = offset + 8 + len(item) * 8
- result = [struct.pack(b'<II', len(item) * 8, BMK_DICT | BMK_ST_ONE)]
- enc = []
- for k,v in iteritems(item):
- result.append(struct.pack(b'<I', ioffset))
- ioffset, ienc = cls._encode_item(k, ioffset)
- enc.append(ienc)
- result.append(struct.pack(b'<I', ioffset))
- ioffset, ienc = cls._encode_item(v, ioffset)
- enc.append(ienc)
- result = b''.join(result + enc)
- elif item is None:
- result = struct.pack(b'<II', 0, BMK_NULL | BMK_ST_ONE)
- else:
- raise ValueError('Unknown item type when encoding: %s' % item)
-
- offset += len(result)
-
- # Pad to a multiple of 4 bytes
- if offset & 3:
- extra = 4 - (offset & 3)
- result += b'\0' * extra
- offset += extra
-
- return (offset, result)
-
- def to_bytes(self):
- """Convert this :class:`Bookmark` to a byte representation."""
-
- result = []
- tocs = []
- offset = 4 # For the offset to the first TOC
-
- # Generate the data and build the TOCs
- for tid,toc in self.tocs:
- entries = []
-
- for k,v in iteritems(toc):
- if isinstance(k, (str, unicode)):
- noffset = offset
- voffset, enc = self._encode_item(k, offset)
- result.append(enc)
- offset, enc = self._encode_item(v, voffset)
- result.append(enc)
- entries.append((noffset | 0x80000000, voffset))
- else:
- entries.append((k, offset))
- offset, enc = self._encode_item(v, offset)
- result.append(enc)
-
- # TOC entries must be sorted - CoreServicesInternal does a
- # binary search to find data
- entries.sort()
-
- tocs.append((tid, b''.join([struct.pack(b'<III',k,o,0)
- for k,o in entries])))
-
- first_toc_offset = offset
-
- # Now generate the TOC headers
- for ndx,toc in enumerate(tocs):
- tid, data = toc
- if ndx == len(tocs) - 1:
- next_offset = 0
- else:
- next_offset = offset + 20 + len(data)
-
- result.append(struct.pack(b'<IIIII', len(data) - 8,
- 0xfffffffe,
- tid,
- next_offset,
- len(data) // 12))
- result.append(data)
-
- offset += 20 + len(data)
-
- # Finally, add the header (and the first TOC offset, which isn't part
- # of the header, but goes just after it)
- header = struct.pack(b'<4sIIIQQQQI', b'book',
- offset + 48,
- 0x10040000,
- 48,
- 0, 0, 0, 0, first_toc_offset)
-
- result.insert(0, header)
-
- return b''.join(result)
-
- @classmethod
- def for_file(cls, path):
- """Construct a :class:`Bookmark` for a given file."""
-
- # Find the filesystem
- st = osx.statfs(path)
- vol_path = st.f_mntonname.decode('utf-8')
-
- # Grab its attributes
- attrs = [osx.ATTR_CMN_CRTIME,
- osx.ATTR_VOL_SIZE
- | osx.ATTR_VOL_NAME
- | osx.ATTR_VOL_UUID,
- 0, 0, 0]
- volinfo = osx.getattrlist(vol_path, attrs, 0)
-
- vol_crtime = volinfo[0]
- vol_size = volinfo[1]
- vol_name = volinfo[2]
- vol_uuid = volinfo[3]
-
- # Also grab various attributes of the file
- attrs = [(osx.ATTR_CMN_OBJTYPE
- | osx.ATTR_CMN_CRTIME
- | osx.ATTR_CMN_FILEID), 0, 0, 0, 0]
- info = osx.getattrlist(path, attrs, osx.FSOPT_NOFOLLOW)
-
- cnid = info[2]
- crtime = info[1]
-
- if info[0] == osx.VREG:
- flags = kCFURLResourceIsRegularFile
- elif info[0] == osx.VDIR:
- flags = kCFURLResourceIsDirectory
- elif info[0] == osx.VLNK:
- flags = kCFURLResourceIsSymbolicLink
- else:
- flags = kCFURLResourceIsRegularFile
-
- dirname, filename = os.path.split(path)
-
- relcount = 0
- if not os.path.isabs(dirname):
- curdir = os.getcwd()
- head, tail = os.path.split(curdir)
- relcount = 0
- while head and tail:
- relcount += 1
- head, tail = os.path.split(head)
- dirname = os.path.join(curdir, dirname)
-
- foldername = os.path.basename(dirname)
-
- rel_path = os.path.relpath(path, vol_path)
-
- # Build the path arrays
- name_path = []
- cnid_path = []
- head, tail = os.path.split(rel_path)
- if not tail:
- head, tail = os.path.split(head)
- while head or tail:
- if head:
- attrs = [osx.ATTR_CMN_FILEID, 0, 0, 0, 0]
- info = osx.getattrlist(os.path.join(vol_path, head), attrs, 0)
- cnid_path.insert(0, info[0])
- head, tail = os.path.split(head)
- name_path.insert(0, tail)
- else:
- head, tail = os.path.split(head)
- name_path.append(filename)
- cnid_path.append(cnid)
-
- url_lengths = [relcount, len(name_path) - relcount]
-
- fileprops = Data(struct.pack(b'<QQQ', flags, 0x0f, 0))
- volprops = Data(struct.pack(b'<QQQ', 0x81 | kCFURLVolumeSupportsPersistentIDs,
- 0x13ef | kCFURLVolumeSupportsPersistentIDs, 0))
-
- toc = {
- kBookmarkPath: name_path,
- kBookmarkCNIDPath: cnid_path,
- kBookmarkFileCreationDate: crtime,
- kBookmarkFileProperties: fileprops,
- kBookmarkContainingFolder: len(name_path) - 2,
- kBookmarkVolumePath: vol_path,
- kBookmarkVolumeIsRoot: vol_path == '/',
- kBookmarkVolumeURL: URL('file://' + vol_path),
- kBookmarkVolumeName: vol_name,
- kBookmarkVolumeSize: vol_size,
- kBookmarkVolumeCreationDate: vol_crtime,
- kBookmarkVolumeUUID: str(vol_uuid).upper(),
- kBookmarkVolumeProperties: volprops,
- kBookmarkCreationOptions: 512,
- kBookmarkWasFileReference: True,
- kBookmarkUserName: 'unknown',
- kBookmarkUID: 99,
- }
-
- if relcount:
- toc[kBookmarkURLLengths] = url_lengths
-
- return Bookmark([(1, toc)])
-
- def __repr__(self):
- result = ['Bookmark([']
- for tid,toc in self.tocs:
- result.append('(0x%x, {\n' % tid)
- for k,v in iteritems(toc):
- if isinstance(k, (str, unicode)):
- kf = repr(k)
- else:
- kf = '0x%04x' % k
- result.append(' %s: %r\n' % (kf, v))
- result.append('}),\n')
- result.append('])')
-
- return ''.join(result)
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/utils.py b/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/utils.py
deleted file mode 100644
index 6a7d0a121..000000000
--- a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/utils.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-import datetime
-
-ZERO = datetime.timedelta(0)
-class UTC (datetime.tzinfo):
- def utcoffset(self, dt):
- return ZERO
- def dst(self, dt):
- return ZERO
- def tzname(self, dt):
- return 'UTC'
-
-utc = UTC()
-mac_epoch = datetime.datetime(1904,1,1,0,0,0,0,utc)
-unix_epoch = datetime.datetime(1970,1,1,0,0,0,0,utc)
-osx_epoch = datetime.datetime(2001,1,1,0,0,0,0,utc)
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/LICENSE b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/LICENSE
index e91f4eb38..e91f4eb38 100644
--- a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/LICENSE
+++ b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/LICENSE
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/__init__.py b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/__init__.py
index 5fba876a7..5fba876a7 100644
--- a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/__init__.py
+++ b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/__init__.py
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/__main__.py b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/__main__.py
index 908d959f1..908d959f1 100755
--- a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/__main__.py
+++ b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/__main__.py
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/badge.py b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/badge.py
index 3408c30b9..3408c30b9 100644
--- a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/badge.py
+++ b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/badge.py
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/colors.py b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/colors.py
index 70b295c2a..70b295c2a 100644
--- a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/colors.py
+++ b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/colors.py
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/core.py b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/core.py
index b514f77e9..b514f77e9 100644
--- a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/core.py
+++ b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/core.py
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/licensing.py b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/licensing.py
index 1bd00b653..1bd00b653 100644
--- a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/licensing.py
+++ b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/licensing.py
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/qt_attribution.json b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/qt_attribution.json
index d9f97ae2c..d9f97ae2c 100644
--- a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/qt_attribution.json
+++ b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/qt_attribution.json
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/resources.py b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/resources.py
index 03e2a43f3..03e2a43f3 100644
--- a/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/resources.py
+++ b/src/3rdparty/python/lib/python3.9/site-packages/dmgbuild/resources.py
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/ds_store/LICENSE b/src/3rdparty/python/lib/python3.9/site-packages/ds_store/LICENSE
index e91f4eb38..e91f4eb38 100644
--- a/src/3rdparty/python/lib/python2.7/site-packages/ds_store/LICENSE
+++ b/src/3rdparty/python/lib/python3.9/site-packages/ds_store/LICENSE
diff --git a/src/3rdparty/python/lib/python3.9/site-packages/ds_store/__init__.py b/src/3rdparty/python/lib/python3.9/site-packages/ds_store/__init__.py
new file mode 100644
index 000000000..bc8702fab
--- /dev/null
+++ b/src/3rdparty/python/lib/python3.9/site-packages/ds_store/__init__.py
@@ -0,0 +1,5 @@
+from .store import DSStore, DSStoreEntry
+
+__version__ = "1.3.1"
+
+__all__ = ["__version__", "DSStore", "DSStoreEntry"]
diff --git a/src/3rdparty/python/lib/python3.9/site-packages/ds_store/__main__.py b/src/3rdparty/python/lib/python3.9/site-packages/ds_store/__main__.py
new file mode 100644
index 000000000..cf17ab5f6
--- /dev/null
+++ b/src/3rdparty/python/lib/python3.9/site-packages/ds_store/__main__.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+#
+# ds_store: Examine .DS_Store files.
+#
+
+import argparse
+import os
+import os.path
+import pprint
+import re
+import sys
+
+from ds_store import DSStore
+from ds_store.buddy import BuddyError
+
+_not_printable_re = re.compile(rb"[\x00-\x1f\x7f-\x9f]")
+
+
+def usage():
+ print(main.__doc__)
+ sys.exit(0)
+
+
+def chunks(iterable, length):
+ for i in range(0, len(iterable), length):
+ yield i, iterable[i : i + length]
+
+
+def pretty(value):
+ if isinstance(value, dict):
+ return f"{{\n {pprint.pformat(value, indent=4)[1:-1]}\n}}"
+ elif isinstance(value, bytearray):
+ lines = ["["]
+ for offset, chunk in chunks(value, 16):
+ printable_chunk = _not_printable_re.sub(b".", chunk).decode("latin-1")
+ hex_line = " ".join([f"{b:02x}" for b in chunk])
+ line = f" {offset:08x} {hex_line:<47s} {printable_chunk}"
+ lines.append(line)
+ lines.append("]")
+ return "\n".join(lines)
+ elif isinstance(value, bytes):
+ return value.decode("latin-1")
+ else:
+ return value
+
+
+def main(argv):
+ """Display the contents of the .DS_Store file at the specified path.
+
+ If you specify just a directory, ds_store will inspect the .DS_Store
+ file in that directory. If no paths are specified, ds_store will
+ display the contents of the .DS_Store file in the current directory.
+ """
+
+ parser = argparse.ArgumentParser(description=main.__doc__)
+ parser.add_argument("paths", nargs="*")
+ args = parser.parse_args(argv)
+
+ if len(args.paths) == 0:
+ args.paths = ["."]
+
+ failed = False
+ for path in args.paths:
+ if os.path.isdir(path):
+ path = os.path.join(path, ".DS_Store")
+
+ if not os.path.exists(path) or not os.path.isfile(path):
+ print(f"ds_store: {path} not found", file=sys.stderr)
+ failed = True
+ continue
+
+ try:
+ with DSStore.open(path, "r") as d:
+ print(path)
+ print("")
+
+ max_name_len = 0
+ for entry in d:
+ name_len = len(entry.filename)
+ if name_len > max_name_len:
+ max_name_len = name_len
+
+ for entry in d:
+ print(
+ "{:<{width}} {} {}".format(
+ entry.filename,
+ entry.code.decode("latin-1"),
+ pretty(entry.value),
+ width=max_name_len,
+ )
+ )
+ print("")
+ except BuddyError as e:
+ print(f"ds_store: {path}: {e}")
+ failed = True
+
+ if failed:
+ sys.exit(1)
+
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/ds_store/buddy.py b/src/3rdparty/python/lib/python3.9/site-packages/ds_store/buddy.py
index 320768cd3..27b11b3f7 100644
--- a/src/3rdparty/python/lib/python2.7/site-packages/ds_store/buddy.py
+++ b/src/3rdparty/python/lib/python3.9/site-packages/ds_store/buddy.py
@@ -1,23 +1,14 @@
-# -*- coding: utf-8 -*-
-import os
+import binascii
import bisect
+import os
import struct
-import binascii
-try:
- {}.iterkeys
- iterkeys = lambda x: x.iterkeys()
-except AttributeError:
- iterkeys = lambda x: x.keys()
-try:
- unicode
-except NameError:
- unicode = str
class BuddyError(Exception):
pass
-class Block(object):
+
+class Block:
def __init__(self, allocator, offset, size):
self._allocator = allocator
self._offset = offset
@@ -25,7 +16,7 @@ class Block(object):
self._value = bytearray(allocator.read(offset, size))
self._pos = 0
self._dirty = False
-
+
def __len__(self):
return self._size
@@ -34,7 +25,7 @@ class Block(object):
def __exit__(self, exc_type, exc_value, traceback):
self.close()
-
+
def close(self):
if self._dirty:
self.flush()
@@ -46,13 +37,13 @@ class Block(object):
def invalidate(self):
self._dirty = False
-
+
def zero_fill(self):
len = self._size - self._pos
- zeroes = b'\0' * len
- self._value[self._pos:self._size] = zeroes
+ zeroes = b"\0" * len
+ self._value[self._pos : self._size] = zeroes
self._dirty = True
-
+
def tell(self):
return self._pos
@@ -63,12 +54,12 @@ class Block(object):
pos = self._size - pos
if pos < 0 or pos > self._size:
- raise ValueError('Seek out of range in Block instance')
+ raise ValueError("Seek out of range in Block instance")
self._pos = pos
def read(self, size_or_format):
- if isinstance(size_or_format, (str, unicode, bytes)):
+ if isinstance(size_or_format, (str, bytes)):
size = struct.calcsize(size_or_format)
fmt = size_or_format
else:
@@ -76,11 +67,11 @@ class Block(object):
fmt = None
if self._size - self._pos < size:
- raise BuddyError('Unable to read %lu bytes in block' % size)
+ raise BuddyError("Unable to read %lu bytes in block" % size)
- data = self._value[self._pos:self._pos + size]
+ data = self._value[self._pos : self._pos + size]
self._pos += size
-
+
if fmt is not None:
if isinstance(data, bytearray):
return struct.unpack_from(fmt, bytes(data))
@@ -96,11 +87,11 @@ class Block(object):
data = data_or_format
if self._pos + len(data) > self._size:
- raise ValueError('Attempt to write past end of Block')
+ raise ValueError("Attempt to write past end of Block")
- self._value[self._pos:self._pos + len(data)] = data
+ self._value[self._pos : self._pos + len(data)] = data
self._pos += len(data)
-
+
self._dirty = True
def insert(self, data_or_format, *args):
@@ -109,78 +100,80 @@ class Block(object):
else:
data = data_or_format
- del self._value[-len(data):]
- self._value[self._pos:self._pos] = data
+ del self._value[-len(data) :]
+ self._value[self._pos : self._pos] = data
self._pos += len(data)
self._dirty = True
def delete(self, size):
if self._pos + size > self._size:
- raise ValueError('Attempt to delete past end of Block')
- del self._value[self._pos:self._pos + size]
- self._value += b'\0' * size
+ raise ValueError("Attempt to delete past end of Block")
+ del self._value[self._pos : self._pos + size]
+ self._value += b"\0" * size
self._dirty = True
-
+
def __str__(self):
return binascii.b2a_hex(self._value)
-
-class Allocator(object):
+
+
+class Allocator:
def __init__(self, the_file):
self._file = the_file
self._dirty = False
self._file.seek(0)
-
+
# Read the header
- magic1, magic2, offset, size, offset2, self._unknown1 \
- = self.read(-4, '>I4sIII16s')
+ (magic1, magic2, offset, size, offset2, self._unknown1) = self.read(
+ -4, ">I4sIII16s"
+ )
- if magic2 != b'Bud1' or magic1 != 1:
- raise BuddyError('Not a buddy file')
+ if magic2 != b"Bud1" or magic1 != 1:
+ raise BuddyError("Not a buddy file")
if offset != offset2:
- raise BuddyError('Root addresses differ')
+ raise BuddyError("Root addresses differ")
self._root = Block(self, offset, size)
# Read the block offsets
- count, self._unknown2 = self._root.read('>II')
+ count, self._unknown2 = self._root.read(">II")
self._offsets = []
c = (count + 255) & ~255
while c:
- self._offsets += self._root.read('>256I')
+ self._offsets += self._root.read(">256I")
c -= 256
self._offsets = self._offsets[:count]
-
+
# Read the TOC
self._toc = {}
- count = self._root.read('>I')[0]
+ count = self._root.read(">I")[0]
for n in range(count):
- nlen = self._root.read('B')[0]
+ nlen = self._root.read("B")[0]
name = bytes(self._root.read(nlen))
- value = self._root.read('>I')[0]
+ value = self._root.read(">I")[0]
self._toc[name] = value
# Read the free lists
self._free = []
for n in range(32):
- count = self._root.read('>I')
- self._free.append(list(self._root.read('>%uI' % count)))
-
+ count = self._root.read(">I")
+ self._free.append(list(self._root.read(">%uI" % count)))
+
@classmethod
- def open(cls, file_or_name, mode='r+'):
- if isinstance(file_or_name, (str, unicode)):
- if not 'b' in mode:
- mode = mode[:1] + 'b' + mode[1:]
+ def open(cls, file_or_name, mode="r+"):
+ if isinstance(file_or_name, str):
+ if "b" not in mode:
+ mode = mode[:1] + "b" + mode[1:]
f = open(file_or_name, mode)
else:
f = file_or_name
- if 'w' in mode:
+ if "w" in mode:
# Create an empty file in this case
f.truncate()
-
+
# An empty root block needs 1264 bytes:
#
# 0 4 offset count
@@ -190,7 +183,7 @@ class Allocator(object):
# 1032 4 toc count (0)
# 1036 228 free list
# total 1264
-
+
# The free list will contain the following:
#
# 0 5 * 4 no blocks of width less than 5
@@ -208,28 +201,38 @@ class Allocator(object):
# located at offset 2**n where n is its width.)
# Write the header
- header = struct.pack(b'>I4sIII16s',
- 1, b'Bud1',
- 2048, 1264, 2048,
- b'\x00\x00\x10\x0c'
- b'\x00\x00\x00\x87'
- b'\x00\x00\x20\x0b'
- b'\x00\x00\x00\x00')
+ header = struct.pack(
+ b">I4sIII16s",
+ 1,
+ b"Bud1",
+ 2048,
+ 1264,
+ 2048,
+ b"\x00\x00\x10\x0c"
+ b"\x00\x00\x00\x87"
+ b"\x00\x00\x20\x0b"
+ b"\x00\x00\x00\x00",
+ )
f.write(header)
- f.write(b'\0' * 2016)
-
+ f.write(b"\0" * 2016)
+
# Write the root block
- free_list = [struct.pack(b'>5I', 0, 0, 0, 0, 0)]
+ free_list = [struct.pack(b">5I", 0, 0, 0, 0, 0)]
for n in range(5, 11):
- free_list.append(struct.pack(b'>II', 1, 2**n))
- free_list.append(struct.pack(b'>I', 0))
+ free_list.append(struct.pack(b">II", 1, 2**n))
+ free_list.append(struct.pack(b">I", 0))
for n in range(12, 31):
- free_list.append(struct.pack(b'>II', 1, 2**n))
- free_list.append(struct.pack(b'>I', 0))
-
- root = b''.join([struct.pack(b'>III', 1, 0, 2048 | 5),
- struct.pack(b'>I', 0) * 255,
- struct.pack(b'>I', 0)] + free_list)
+ free_list.append(struct.pack(b">II", 1, 2**n))
+ free_list.append(struct.pack(b">I", 0))
+
+ root = b"".join(
+ [
+ struct.pack(b">III", 1, 0, 2048 | 5),
+ struct.pack(b">I", 0) * 255,
+ struct.pack(b">I", 0),
+ ]
+ + free_list
+ )
f.write(root)
return Allocator(f)
@@ -239,7 +242,7 @@ class Allocator(object):
def __exit__(self, exc_type, exc_value, traceback):
self.close()
-
+
def close(self):
self.flush()
self._file.close()
@@ -252,51 +255,57 @@ class Allocator(object):
self._write_root_block_into(rblk)
addr = self._offsets[0]
- offset = addr & ~0x1f
- size = 1 << (addr & 0x1f)
+ offset = addr & ~0x1F
+ size = 1 << (addr & 0x1F)
self._file.seek(0, os.SEEK_SET)
- self._file.write(struct.pack(b'>I4sIII16s',
- 1, b'Bud1',
- offset, size, offset,
- self._unknown1))
+ self._file.write(
+ struct.pack(
+ b">I4sIII16s", 1, b"Bud1", offset, size, offset, self._unknown1
+ )
+ )
self._dirty = False
-
+
self._file.flush()
-
+
def read(self, offset, size_or_format):
- """Read data at `offset', or raise an exception. `size_or_format'
- may either be a byte count, in which case we return raw data,
- or a format string for `struct.unpack', in which case we
- work out the size and unpack the data before returning it."""
+ """Read data at `offset', or raise an exception.
+
+ `size_or_format' may either be a byte count, in which case we
+ return raw data, or a format string for `struct.unpack', in
+ which case we work out the size and unpack the data before
+ returning it.
+ """
# N.B. There is a fixed offset of four bytes(!)
self._file.seek(offset + 4, os.SEEK_SET)
- if isinstance(size_or_format, (str, unicode)):
+ if isinstance(size_or_format, str):
size = struct.calcsize(size_or_format)
fmt = size_or_format
else:
size = size_or_format
fmt = None
-
+
ret = self._file.read(size)
if len(ret) < size:
- ret += b'\0' * (size - len(ret))
+ ret += b"\0" * (size - len(ret))
if fmt is not None:
if isinstance(ret, bytearray):
ret = struct.unpack_from(fmt, bytes(ret))
else:
ret = struct.unpack(fmt, ret)
-
+
return ret
def write(self, offset, data_or_format, *args):
- """Write data at `offset', or raise an exception. `data_or_format'
- may either be the data to write, or a format string for `struct.pack',
- in which case we pack the additional arguments and write the
- resulting data."""
+ """Write data at `offset', or raise an exception.
+
+ `data_or_format' may either be the data to write, or a format
+ string for `struct.pack', in which case we pack the additional
+ arguments and write the resulting data.
+ """
# N.B. There is a fixed offset of four bytes(!)
self._file.seek(offset + 4, os.SEEK_SET)
@@ -313,11 +322,11 @@ class Allocator(object):
except IndexError:
return None
- offset = addr & ~0x1f
- size = 1 << (addr & 0x1f)
+ offset = addr & ~0x1F
+ size = 1 << (addr & 0x1F)
return Block(self, offset, size)
-
+
def _root_block_size(self):
"""Return the number of bytes required by the root block."""
# Offsets
@@ -330,62 +339,62 @@ class Allocator(object):
# Free list
size += sum([4 + 4 * len(fl) for fl in self._free])
-
+
return size
def _write_root_block_into(self, block):
# Offsets
- block.write('>II', len(self._offsets), self._unknown2)
- block.write('>%uI' % len(self._offsets), *self._offsets)
+ block.write(">II", len(self._offsets), self._unknown2)
+ block.write(">%uI" % len(self._offsets), *self._offsets)
extra = len(self._offsets) & 255
if extra:
- block.write(b'\0\0\0\0' * (256 - extra))
+ block.write(b"\0\0\0\0" * (256 - extra))
# TOC
keys = list(self._toc.keys())
keys.sort()
- block.write('>I', len(keys))
+ block.write(">I", len(keys))
for k in keys:
- block.write('B', len(k))
+ block.write("B", len(k))
block.write(k)
- block.write('>I', self._toc[k])
+ block.write(">I", self._toc[k])
# Free list
for w, f in enumerate(self._free):
- block.write('>I', len(f))
+ block.write(">I", len(f))
if len(f):
- block.write('>%uI' % len(f), *f)
+ block.write(">%uI" % len(f), *f)
def _buddy(self, offset, width):
f = self._free[width]
b = offset ^ (1 << width)
-
+
try:
ndx = f.index(b)
except ValueError:
ndx = None
-
+
return (f, b, ndx)
def _release(self, offset, width):
# Coalesce
while True:
- f,b,ndx = self._buddy(offset, width)
+ f, b, ndx = self._buddy(offset, width)
if ndx is None:
break
-
+
offset &= b
width += 1
del f[ndx]
-
+
# Add to the list
bisect.insort(f, offset)
# Mark as dirty
self._dirty = True
-
+
def _alloc(self, width):
w = width
while not self._free[w]:
@@ -407,15 +416,15 @@ class Allocator(object):
except ValueError:
block = len(self._offsets)
self._offsets.append(0)
-
+
# Compute block width
width = max(bytes.bit_length(), 5)
addr = self._offsets[block]
- offset = addr & ~0x1f
-
+ offset = addr & ~0x1F
+
if addr:
- blkwidth = addr & 0x1f
+ blkwidth = addr & 0x1F
if blkwidth == width:
return block
self._release(offset, width)
@@ -424,13 +433,13 @@ class Allocator(object):
offset = self._alloc(width)
self._offsets[block] = offset | width
return block
-
+
def release(self, block):
addr = self._offsets[block]
if addr:
- width = addr & 0x1f
- offset = addr & ~0x1f
+ width = addr & 0x1F
+ offset = addr & ~0x1F
self._release(offset, width)
if block == len(self._offsets):
@@ -442,37 +451,36 @@ class Allocator(object):
return len(self._toc)
def __getitem__(self, key):
- if not isinstance(key, (str, unicode)):
- raise TypeError('Keys must be of string type')
+ if not isinstance(key, str):
+ raise TypeError("Keys must be of string type")
if not isinstance(key, bytes):
- key = key.encode('latin_1')
+ key = key.encode("latin_1")
return self._toc[key]
def __setitem__(self, key, value):
- if not isinstance(key, (str, unicode)):
- raise TypeError('Keys must be of string type')
+ if not isinstance(key, str):
+ raise TypeError("Keys must be of string type")
if not isinstance(key, bytes):
- key = key.encode('latin_1')
+ key = key.encode("latin_1")
self._toc[key] = value
self._dirty = True
def __delitem__(self, key):
- if not isinstance(key, (str, unicode)):
- raise TypeError('Keys must be of string type')
+ if not isinstance(key, str):
+ raise TypeError("Keys must be of string type")
if not isinstance(key, bytes):
- key = key.encode('latin_1')
+ key = key.encode("latin_1")
del self._toc[key]
self._dirty = True
def iterkeys(self):
- return iterkeys(self._toc)
+ return self._toc.keys()
def keys(self):
- return iterkeys(self._toc)
+ return self._toc.keys()
def __iter__(self):
- return iterkeys(self._toc)
+ return self._toc.keys()
def __contains__(self, key):
return key in self._toc
-
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/ds_store/qt_attribution.json b/src/3rdparty/python/lib/python3.9/site-packages/ds_store/qt_attribution.json
index a4854d1ed..a4854d1ed 100644
--- a/src/3rdparty/python/lib/python2.7/site-packages/ds_store/qt_attribution.json
+++ b/src/3rdparty/python/lib/python3.9/site-packages/ds_store/qt_attribution.json
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/ds_store/store.py b/src/3rdparty/python/lib/python3.9/site-packages/ds_store/store.py
index b6f805b24..58e9e1bce 100644
--- a/src/3rdparty/python/lib/python2.7/site-packages/ds_store/store.py
+++ b/src/3rdparty/python/lib/python3.9/site-packages/ds_store/store.py
@@ -1,48 +1,36 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-from __future__ import print_function
-from __future__ import division
-
-import binascii
+import plistlib
import struct
-import biplist
-import mac_alias
-try:
- next
-except NameError:
- next = lambda x: x.next()
-try:
- unicode
-except NameError:
- unicode = str
+import mac_alias
from . import buddy
-class ILocCodec(object):
+
+class ILocCodec:
@staticmethod
def encode(point):
- return struct.pack(b'>IIII', point[0], point[1],
- 0xffffffff, 0xffff0000)
+ return struct.pack(b">IIII", point[0], point[1], 0xFFFFFFFF, 0xFFFF0000)
@staticmethod
def decode(bytesData):
if isinstance(bytesData, bytearray):
- x, y = struct.unpack_from(b'>II', bytes(bytesData[:8]))
+ x, y = struct.unpack_from(b">II", bytes(bytesData[:8]))
else:
- x, y = struct.unpack(b'>II', bytesData[:8])
+ x, y = struct.unpack(b">II", bytesData[:8])
return (x, y)
-class PlistCodec(object):
+
+class PlistCodec:
@staticmethod
def encode(plist):
- return biplist.writePlistToString(plist)
+ return plistlib.dumps(plist, fmt=plistlib.FMT_BINARY)
@staticmethod
def decode(bytes):
- return biplist.readPlistFromString(bytes)
+ return plistlib.loads(bytes)
-class BookmarkCodec(object):
+
+class BookmarkCodec:
@staticmethod
def encode(bmk):
return bmk.to_bytes()
@@ -51,70 +39,73 @@ class BookmarkCodec(object):
def decode(bytes):
return mac_alias.Bookmark.from_bytes(bytes)
+
# This list tells the code how to decode particular kinds of entry in the
# .DS_Store file. This is really a convenience, and we currently only
# support a tiny subset of the possible entry types.
codecs = {
- b'Iloc': ILocCodec,
- b'bwsp': PlistCodec,
- b'lsvp': PlistCodec,
- b'lsvP': PlistCodec,
- b'icvp': PlistCodec,
- b'pBBk': BookmarkCodec
- }
-
-class DSStoreEntry(object):
+ b"Iloc": ILocCodec,
+ b"bwsp": PlistCodec,
+ b"lsvp": PlistCodec,
+ b"lsvP": PlistCodec,
+ b"icvp": PlistCodec,
+ b"pBBk": BookmarkCodec,
+}
+
+
+class DSStoreEntry:
"""Holds the data from an entry in a ``.DS_Store`` file. Note that this is
- not meant to represent the entry itself---i.e. if you change the type
- or value, your changes will *not* be reflected in the underlying file.
+ not meant to represent the entry itself---i.e. if you change the type or
+ value, your changes will *not* be reflected in the underlying file.
- If you want to make a change, you should either use the :class:`DSStore`
- object's :meth:`DSStore.insert` method (which will replace a key if it
- already exists), or the mapping access mode for :class:`DSStore` (often
- simpler anyway).
+ If you want to make a change, you should either use the
+ :class:`DSStore` object's :meth:`DSStore.insert` method (which will
+ replace a key if it already exists), or the mapping access mode for
+ :class:`DSStore` (often simpler anyway).
"""
+
def __init__(self, filename, code, typecode, value=None):
if str != bytes and type(filename) == bytes:
- filename = filename.decode('utf-8')
+ filename = filename.decode("utf-8")
if not isinstance(code, bytes):
- code = code.encode('latin_1')
+ code = code.encode("latin_1")
self.filename = filename
self.code = code
self.type = typecode
self.value = value
-
+
@classmethod
def read(cls, block):
- """Read a ``.DS_Store`` entry from the containing Block"""
+ """Read a ``.DS_Store`` entry from the containing Block."""
# First read the filename
- nlen = block.read(b'>I')[0]
- filename = block.read(2 * nlen).decode('utf-16be')
+ nlen = block.read(b">I")[0]
+ filename = block.read(2 * nlen).decode("utf-16be")
# Next, read the code and type
- code, typecode = block.read(b'>4s4s')
+ code, typecode = block.read(b">4s4s")
# Finally, read the data
- if typecode == b'bool':
- value = block.read(b'>?')[0]
- elif typecode == b'long' or typecode == b'shor':
- value = block.read(b'>I')[0]
- elif typecode == b'blob':
- vlen = block.read(b'>I')[0]
+ if typecode == b"bool":
+ value = block.read(b">?")[0]
+ elif typecode == b"long" or typecode == b"shor":
+ value = block.read(b">I")[0]
+ elif typecode == b"blob":
+ vlen = block.read(b">I")[0]
value = block.read(vlen)
codec = codecs.get(code, None)
if codec:
value = codec.decode(value)
typecode = codec
- elif typecode == b'ustr':
- vlen = block.read(b'>I')[0]
- value = block.read(2 * vlen).decode('utf-16be')
- elif typecode == b'type':
- value = block.read(b'>4s')[0]
- elif typecode == b'comp' or typecode == b'dutc':
- value = block.read(b'>Q')[0]
+ elif typecode == b"ustr":
+ vlen = block.read(b">I")[0]
+ value = block.read(2 * vlen).decode("utf-16be")
+ elif typecode == b"type":
+ value = block.read(b">4s")[0]
+ elif typecode == b"comp" or typecode == b"dutc":
+ value = block.read(b">Q")[0]
else:
raise ValueError('Unknown type code "%s"' % typecode)
@@ -122,152 +113,138 @@ class DSStoreEntry(object):
def __lt__(self, other):
if not isinstance(other, DSStoreEntry):
- raise TypeError('Can only compare against other DSStoreEntry objects')
+ raise TypeError("Can only compare against other DSStoreEntry objects")
sfl = self.filename.lower()
ofl = other.filename.lower()
- return (sfl < ofl
- or (self.filename == other.filename
- and self.code < other.code))
+ return sfl < ofl or (self.filename == other.filename and self.code < other.code)
def __le__(self, other):
if not isinstance(other, DSStoreEntry):
- raise TypeError('Can only compare against other DSStoreEntry objects')
+ raise TypeError("Can only compare against other DSStoreEntry objects")
sfl = self.filename.lower()
ofl = other.filename.lower()
- return (sfl < ofl
- or (sfl == ofl
- and self.code <= other.code))
+ return sfl < ofl or (sfl == ofl and self.code <= other.code)
def __eq__(self, other):
if not isinstance(other, DSStoreEntry):
- raise TypeError('Can only compare against other DSStoreEntry objects')
+ raise TypeError("Can only compare against other DSStoreEntry objects")
sfl = self.filename.lower()
ofl = other.filename.lower()
- return (sfl == ofl
- and self.code == other.code)
+ return sfl == ofl and self.code == other.code
def __ne__(self, other):
if not isinstance(other, DSStoreEntry):
- raise TypeError('Can only compare against other DSStoreEntry objects')
+ raise TypeError("Can only compare against other DSStoreEntry objects")
sfl = self.filename.lower()
ofl = other.filename.lower()
- return (sfl != ofl
- or self.code != other.code)
+ return sfl != ofl or self.code != other.code
def __gt__(self, other):
if not isinstance(other, DSStoreEntry):
- raise TypeError('Can only compare against other DSStoreEntry objects')
+ raise TypeError("Can only compare against other DSStoreEntry objects")
sfl = self.filename.lower()
ofl = other.filename.lower()
-
+
selfCode = self.code
if str != bytes and type(selfCode) is bytes:
- selfCode = selfCode.decode('utf-8')
+ selfCode = selfCode.decode("utf-8")
otherCode = other.code
if str != bytes and type(otherCode) is bytes:
- otherCode = otherCode.decode('utf-8')
-
- return (sfl > ofl or (sfl == ofl and selfCode > otherCode))
+ otherCode = otherCode.decode("utf-8")
+
+ return sfl > ofl or (sfl == ofl and selfCode > otherCode)
def __ge__(self, other):
if not isinstance(other, DSStoreEntry):
- raise TypeError('Can only compare against other DSStoreEntry objects')
+ raise TypeError("Can only compare against other DSStoreEntry objects")
sfl = self.filename.lower()
ofl = other.filename.lower()
- return (sfl > ofl
- or (sfl == ofl
- and self.code >= other.code))
+ return sfl > ofl or (sfl == ofl and self.code >= other.code)
- def __cmp__(self, other):
- if not isinstance(other, DSStoreEntry):
- raise TypeError('Can only compare against other DSStoreEntry objects')
- r = cmp(self.filename.lower(), other.filename.lower())
- if r:
- return r
- return cmp(self.code, other.code)
-
def byte_length(self):
- """Compute the length of this entry, in bytes"""
- utf16 = self.filename.encode('utf-16be')
- l = 4 + len(utf16) + 8
+ """Compute the length of this entry, in bytes."""
+ utf16 = self.filename.encode("utf-16be")
+ length = 4 + len(utf16) + 8
- if isinstance(self.type, unicode):
- entry_type = self.type.encode('latin_1')
+ if isinstance(self.type, str):
+ entry_type = self.type.encode("latin_1")
value = self.value
elif isinstance(self.type, (bytes, str)):
entry_type = self.type
value = self.value
else:
- entry_type = b'blob'
+ entry_type = b"blob"
value = self.type.encode(self.value)
-
- if entry_type == b'bool':
- l += 1
- elif entry_type == b'long' or entry_type == b'shor':
- l += 4
- elif entry_type == b'blob':
- l += 4 + len(value)
- elif entry_type == b'ustr':
- utf16 = value.encode('utf-16be')
- l += 4 + len(utf16)
- elif entry_type == b'type':
- l += 4
- elif entry_type == b'comp' or entry_type == b'dutc':
- l += 8
+
+ if entry_type == b"bool":
+ length += 1
+ elif entry_type == b"long" or entry_type == b"shor":
+ length += 4
+ elif entry_type == b"blob":
+ length += 4 + len(value)
+ elif entry_type == b"ustr":
+ utf16 = value.encode("utf-16be")
+ length += 4 + len(utf16)
+ elif entry_type == b"type":
+ length += 4
+ elif entry_type == b"comp" or entry_type == b"dutc":
+ length += 8
else:
raise ValueError('Unknown type code "%s"' % entry_type)
- return l
-
+ return length
+
def write(self, block, insert=False):
- """Write this entry to the specified Block"""
+ """Write this entry to the specified Block."""
if insert:
w = block.insert
else:
w = block.write
- if isinstance(self.type, unicode):
- entry_type = self.type.encode('latin_1')
+ if isinstance(self.type, str):
+ entry_type = self.type.encode("latin_1")
value = self.value
elif isinstance(self.type, (bytes, str)):
entry_type = self.type
value = self.value
else:
- entry_type = b'blob'
+ entry_type = b"blob"
value = self.type.encode(self.value)
- utf16 = self.filename.encode('utf-16be')
- w(b'>I', len(utf16) // 2)
+ utf16 = self.filename.encode("utf-16be")
+ w(b">I", len(utf16) // 2)
w(utf16)
- w(b'>4s4s', self.code, entry_type)
-
- if entry_type == b'bool':
- w(b'>?', value)
- elif entry_type == b'long' or entry_type == b'shor':
- w(b'>I', value)
- elif entry_type == b'blob':
- w(b'>I', len(value))
+ w(b">4s4s", self.code, entry_type)
+
+ if entry_type == b"bool":
+ w(b">?", value)
+ elif entry_type == b"long" or entry_type == b"shor":
+ w(b">I", value)
+ elif entry_type == b"blob":
+ w(b">I", len(value))
w(value)
- elif entry_type == b'ustr':
- utf16 = value.encode('utf-16be')
- w(b'>I', len(utf16) // 2)
+ elif entry_type == b"ustr":
+ utf16 = value.encode("utf-16be")
+ w(b">I", len(utf16) // 2)
w(utf16)
- elif entry_type == b'type':
- if isinstance(value, unicode):
- value = value.encode('latin_1')
- w(b'>4s', value)
- elif entry_type == b'comp' or entry_type == b'dutc':
- w(b'>Q', value)
+ elif entry_type == b"type":
+ if isinstance(value, str):
+ value = value.encode("latin_1")
+ w(b">4s", value)
+ elif entry_type == b"comp" or entry_type == b"dutc":
+ w(b">Q", value)
else:
raise ValueError('Unknown type code "%s"' % entry_type)
-
+
def __repr__(self):
- return '<%s %s>' % (self.filename, self.code)
+ return f"<{self.filename} {self.code}>"
+
+
+class DSStore:
+ """Python interface to a ``.DS_Store`` file. Works by manipulating the
+ file on the disk---so this code will work with ``.DS_Store`` files for.
-class DSStore(object):
- """Python interface to a ``.DS_Store`` file. Works by manipulating the file
- on the disk---so this code will work with ``.DS_Store`` files for *very*
- large directories.
+ *very* large directories.
A :class:`DSStore` object can be used as if it was a mapping, e.g.::
@@ -280,7 +257,7 @@ class DSStore(object):
Currently, we know how to decode "Iloc", "bwsp", "lsvp", "lsvP" and "icvp"
blobs. "Iloc" decodes to an (x, y) tuple, while the others are all decoded
- using ``biplist``.
+ using ``biplist`` or ``plistlib`` depending on Python version.
Assignment also works, e.g.::
@@ -292,38 +269,48 @@ class DSStore(object):
This is usually going to be the most convenient interface, though
occasionally (for instance when creating a new ``.DS_Store`` file) you
- may wish to drop down to using :class:`DSStoreEntry` objects directly."""
+ may wish to drop down to using :class:`DSStoreEntry` objects directly.
+ """
+
def __init__(self, store):
self._store = store
- self._superblk = self._store['DSDB']
+ self._superblk = self._store["DSDB"]
with self._get_block(self._superblk) as s:
- self._rootnode, self._levels, self._records, \
- self._nodes, self._page_size = s.read(b'>IIIII')
+ (
+ self._rootnode,
+ self._levels,
+ self._records,
+ self._nodes,
+ self._page_size,
+ ) = s.read(b">IIIII")
self._min_usage = 2 * self._page_size // 3
self._dirty = False
-
+
@classmethod
- def open(cls, file_or_name, mode='r+', initial_entries=None):
+ def open(cls, file_or_name, mode="r+", initial_entries=None):
"""Open a ``.DS_Store`` file; pass either a Python file object, or a
- filename in the ``file_or_name`` argument and a file access mode in
- the ``mode`` argument. If you are creating a new file using the "w"
- or "w+" modes, you may also specify a list of entries with which
- to initialise the file."""
+ filename in the ``file_or_name`` argument and a file access mode in the
+ ``mode`` argument.
+
+ If you are creating a new file using the "w" or "w+" modes, you
+ may also specify a list of entries with which to initialise the
+ file.
+ """
store = buddy.Allocator.open(file_or_name, mode)
-
- if mode == 'w' or mode == 'w+':
+
+ if mode == "w" or mode == "w+":
superblk = store.allocate(20)
- store['DSDB'] = superblk
+ store["DSDB"] = superblk
page_size = 4096
-
+
if not initial_entries:
root = store.allocate(page_size)
-
+
with store.get_block(root) as rootblk:
rootblk.zero_fill()
with store.get_block(superblk) as s:
- s.write(b'>IIIII', root, 0, 0, 1, page_size)
+ s.write(b">IIIII", root, 0, 0, 1, page_size)
else:
# Make sure they're in sorted order
initial_entries = list(initial_entries)
@@ -357,48 +344,54 @@ class DSStore(object):
if len(nodes) == 1:
break
-
+
current_level = next_level
next_level = []
ptr_size = 4
# Allocate nodes
ptrs = [store.allocate(page_size) for n in range(node_count)]
-
+
# Generate nodes
pointers = []
prev_pointers = None
for level in levels:
ppndx = 0
- lptrs = ptrs[-len(level):]
- del ptrs[-len(level):]
+ lptrs = ptrs[-len(level) :]
+ del ptrs[-len(level) :]
for node in level:
ndx = lptrs.pop(0)
if prev_pointers is None:
with store.get_block(ndx) as block:
- block.write(b'>II', 0, len(node))
+ block.write(b">II", 0, len(node))
for e in node:
e.write(block)
else:
next_node = prev_pointers[ppndx + len(node)]
- node_ptrs = prev_pointers[ppndx:ppndx+len(node)]
-
+ node_ptrs = prev_pointers[ppndx : ppndx + len(node)]
+
with store.get_block(ndx) as block:
- block.write(b'>II', next_node, len(node))
+ block.write(b">II", next_node, len(node))
for ptr, e in zip(node_ptrs, node):
- block.write(b'>I', ptr)
+ block.write(b">I", ptr)
e.write(block)
-
+
pointers.append(ndx)
prev_pointers = pointers
pointers = []
-
+
root = prev_pointers[0]
with store.get_block(superblk) as s:
- s.write(b'>IIIII', root, len(levels), len(initial_entries),
- node_count, page_size)
-
+ s.write(
+ b">IIIII",
+ root,
+ len(levels),
+ len(initial_entries),
+ node_count,
+ page_size,
+ )
+
return DSStore(store)
def _get_block(self, number):
@@ -410,25 +403,31 @@ class DSStore(object):
self._dirty = False
with self._get_block(self._superblk) as s:
- s.write(b'>IIIII', self._rootnode, self._levels, self._records,
- self._nodes, self._page_size)
+ s.write(
+ b">IIIII",
+ self._rootnode,
+ self._levels,
+ self._records,
+ self._nodes,
+ self._page_size,
+ )
self._store.flush()
def close(self):
"""Flush dirty data and close the underlying file."""
self.flush()
self._store.close()
-
+
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
self.close()
-
+
# Internal B-Tree nodes look like this:
#
# [ next | count | (ptr0 | rec0) | (ptr1 | rec1) ... (ptrN | recN) ]
-
+
# Leaf nodes look like this:
#
# [ 0 | count | rec0 | rec1 ... recN ]
@@ -438,10 +437,10 @@ class DSStore(object):
if node is None:
node = self._rootnode
with self._get_block(node) as block:
- next_node, count = block.read(b'>II')
+ next_node, count = block.read(b">II")
if next_node:
for n in range(count):
- ptr = block.read(b'>I')[0]
+ ptr = block.read(b">I")[0]
for e in self._traverse(ptr):
yield e
e = DSStoreEntry.read(block)
@@ -456,23 +455,30 @@ class DSStore(object):
# Display the data in `node'
def _dump_node(self, node):
with self._get_block(node) as block:
- next_node, count = block.read(b'>II')
- print('next: %u\ncount: %u\n' % (next_node, count))
+ next_node, count = block.read(b">II")
+ print("next: %u\ncount: %u\n" % (next_node, count))
for n in range(count):
if next_node:
- ptr = block.read(b'>I')[0]
- print('%8u ' % ptr, end=' ')
+ ptr = block.read(b">I")[0]
+ print("%8u " % ptr, end=" ")
else:
- print(' ', end=' ')
+ print(" ", end=" ")
e = DSStoreEntry.read(block)
- print(e, ' (%u)' % e.byte_length())
- print('used: %u' % block.tell())
+ print(e, " (%u)" % e.byte_length())
+ print("used: %u" % block.tell())
# Display the data in the super block
def _dump_super(self):
- print('root: %u\nlevels: %u\nrecords: %u\nnodes: %u\npage-size: %u' \
- % (self._rootnode, self._levels, self._records,
- self._nodes, self._page_size))
+ print(
+ "root: %u\nlevels: %u\nrecords: %u\nnodes: %u\npage-size: %u"
+ % (
+ self._rootnode,
+ self._levels,
+ self._records,
+ self._nodes,
+ self._page_size,
+ )
+ )
# Splits entries across two blocks, returning one pivot
#
@@ -480,9 +486,9 @@ class DSStore(object):
def _split2(self, blocks, entries, pointers, before, internal):
left_block = blocks[0]
right_block = blocks[1]
-
+
count = len(entries)
-
+
# Find the feasible splits
best_split = None
best_diff = None
@@ -492,7 +498,7 @@ class DSStore(object):
# We can use a *single* node for this
best_split = count
else:
- # Split into two nodes
+ # Split into two nodes
for n in range(1, count - 1):
left_size = 8 + before[n]
right_size = 8 + total - before[n + 1]
@@ -501,7 +507,7 @@ class DSStore(object):
break
if right_size > self._page_size:
continue
-
+
diff = abs(left_size - right_size)
if best_split is None or diff < best_diff:
@@ -510,54 +516,53 @@ class DSStore(object):
if best_split is None:
return None
-
+
# Write the nodes
left_block.seek(0)
if internal:
next_node = pointers[best_split]
else:
next_node = 0
- left_block.write(b'>II', next_node, best_split)
+ left_block.write(b">II", next_node, best_split)
for n in range(best_split):
if internal:
- left_block.write(b'>I', pointers[n])
+ left_block.write(b">I", pointers[n])
entries[n].write(left_block)
left_block.zero_fill()
if best_split == count:
return []
-
+
right_block.seek(0)
if internal:
next_node = pointers[count]
else:
next_node = 0
- right_block.write(b'>II', next_node, count - best_split - 1)
+ right_block.write(b">II", next_node, count - best_split - 1)
for n in range(best_split + 1, count):
if internal:
- right_block.write(b'>I', pointers[n])
+ right_block.write(b">I", pointers[n])
entries[n].write(right_block)
right_block.zero_fill()
-
+
pivot = entries[best_split]
return [pivot]
-
+
def _split(self, node, entry, right_ptr=0):
self._nodes += 1
self._dirty = True
new_right = self._store.allocate(self._page_size)
- with self._get_block(node) as block, \
- self._get_block(new_right) as right_block:
+ with self._get_block(node) as block, self._get_block(new_right) as right_block:
# First, measure and extract all the elements
entry_size = entry.byte_length()
- entry_pos = None
- next_node, count = block.read(b'>II')
+ # ?? entry_pos = None
+ next_node, count = block.read(b">II")
if next_node:
entry_size += 4
pointers = []
@@ -567,11 +572,11 @@ class DSStore(object):
for n in range(count):
pos = block.tell()
if next_node:
- ptr = block.read(b'>I')[0]
+ ptr = block.read(b">I")[0]
pointers.append(ptr)
e = DSStoreEntry.read(block)
if e > entry:
- entry_pos = n
+ # ?? entry_pos = n
entries.append(entry)
pointers.append(right_ptr)
before.append(total)
@@ -583,10 +588,10 @@ class DSStore(object):
if next_node:
pointers.append(next_node)
- pivot = self._split2([block, right_block],
- entries, pointers, before,
- bool(next_node))[0]
-
+ pivot = self._split2(
+ [block, right_block], entries, pointers, before, bool(next_node)
+ )[0]
+
self._records += 1
self._nodes += 1
self._dirty = True
@@ -598,7 +603,7 @@ class DSStore(object):
def _new_root(self, left, pivot, right):
new_root = self._store.allocate(self._page_size)
with self._get_block(new_root) as block:
- block.write(b'>III', right, 1, left)
+ block.write(b">III", right, 1, left)
pivot.write(block)
self._rootnode = new_root
self._levels += 1
@@ -610,21 +615,21 @@ class DSStore(object):
# pointer (inserted to the RIGHT of `entry')
def _insert_inner(self, path, node, entry, right_ptr):
with self._get_block(node) as block:
- next_node, count = block.read(b'>II')
+ next_node, count = block.read(b">II")
insert_pos = None
insert_ndx = None
n = 0
while n < count:
pos = block.tell()
- ptr = block.read(b'>I')[0]
+ ptr = block.read(b">I")[0]
e = DSStoreEntry.read(block)
if e == entry:
if n == count - 1:
right_ptr = next_node
next_node = ptr
- block_seek(pos)
+ block.seek(pos)
else:
- right_ptr = block.read(b'>I')[0]
+ right_ptr = block.read(b">I")[0]
block.seek(pos + 4)
insert_pos = pos
insert_ndx = n
@@ -651,32 +656,32 @@ class DSStore(object):
else:
if insert_ndx == count:
block.seek(insert_pos)
- block.write(b'>I', next_node)
+ block.write(b">I", next_node)
entry.write(block)
next_node = right_ptr
else:
block.seek(insert_pos + 4)
entry.write(block, True)
- block.insert('>I', right_ptr)
+ block.insert(">I", right_ptr)
block.seek(0)
count += 1
- block.write(b'>II', next_node, count)
+ block.write(b">II", next_node, count)
self._records += 1
self._dirty = True
# Insert `entry' into the leaf node `node'
def _insert_leaf(self, path, node, entry):
with self._get_block(node) as block:
- next_node, count = block.read(b'>II')
+ next_node, count = block.read(b">II")
insert_pos = None
- insert_ndx = None
+ # ?? insert_ndx = None
n = 0
while n < count:
pos = block.tell()
e = DSStoreEntry.read(block)
if e == entry:
insert_pos = pos
- insert_ndx = n
+ # ?? insert_ndx = n
block.seek(pos)
block.delete(e.byte_length())
count -= 1
@@ -685,11 +690,11 @@ class DSStore(object):
continue
elif insert_pos is None and e > entry:
insert_pos = pos
- insert_ndx = n
+ # ?? insert_ndx = n
n += 1
if insert_pos is None:
insert_pos = block.tell()
- insert_ndx = count
+ # ?? insert_ndx = count
remaining = self._page_size - block.tell()
if remaining < entry.byte_length():
@@ -703,21 +708,21 @@ class DSStore(object):
entry.write(block, True)
block.seek(0)
count += 1
- block.write(b'>II', next_node, count)
+ block.write(b">II", next_node, count)
self._records += 1
self._dirty = True
def insert(self, entry):
- """Insert ``entry`` (which should be a :class:`DSStoreEntry`)
- into the B-Tree."""
+ """Insert ``entry`` (which should be a :class:`DSStoreEntry`) into the
+ B-Tree."""
path = []
node = self._rootnode
while True:
with self._get_block(node) as block:
- next_node, count = block.read(b'>II')
+ next_node, count = block.read(b">II")
if next_node:
for n in range(count):
- ptr = block.read(b'>I')[0]
+ ptr = block.read(b">I")[0]
e = DSStoreEntry.read(block)
if entry < e:
next_node = ptr
@@ -735,12 +740,12 @@ class DSStore(object):
# Return usage information for the specified `node'
def _block_usage(self, node):
with self._get_block(node) as block:
- next_node, count = block.read(b'>II')
+ next_node, count = block.read(b">II")
for n in range(count):
if next_node:
- ptr = block.read(b'>I')[0]
- e = DSStoreEntry.read(block)
+ block.read(b">I")[0]
+ DSStoreEntry.read(block)
used = block.tell()
@@ -773,14 +778,14 @@ class DSStore(object):
continue
diff = abs(left_size - mid_size) * abs(right_size - mid_size)
-
+
if best_split is None or diff < best_diff:
best_split = (n, m, count)
best_diff = diff
if best_split is None:
return None
-
+
# Write the nodes
prev_split = -1
for block, split in zip(blocks, best_split):
@@ -789,15 +794,15 @@ class DSStore(object):
next_node = pointers[split]
else:
next_node = 0
- block.write(b'>II', next_node, split)
+ block.write(b">II", next_node, split)
for n in range(prev_split + 1, split):
if internal:
- block.write(b'>I', pointers[n])
+ block.write(b">I", pointers[n])
entries[n].write(block)
block.zero_fill()
-
+
prev_split = split
return (entries[best_split[0]], entries[best_split[1]])
@@ -811,13 +816,13 @@ class DSStore(object):
before = []
total = 0
ppivots = pivots + [None]
- for b,p in zip(blocks, ppivots):
+ for b, p in zip(blocks, ppivots):
b.seek(0)
- next_node, count = b.read(b'>II')
+ next_node, count = b.read(b">II")
for n in range(count):
pos = b.tell()
if next_node:
- ptr = b.read(b'>I')[0]
+ ptr = b.read(b">I")[0]
pointers.append(ptr)
e = DSStoreEntry.read(b)
entries.append(e)
@@ -842,11 +847,11 @@ class DSStore(object):
return
with self._get_block(node) as block:
- next_node, count = block.read(b'>II')
-
+ next_node, count = block.read(b">II")
+
with self._get_block(path[-1]) as parent:
# Find the left and right siblings and respective pivots
- parent_next, parent_count = parent.read(b'>II')
+ parent_next, parent_count = parent.read(b">II")
left_pos = None
left_node = None
left_pivot = None
@@ -857,7 +862,7 @@ class DSStore(object):
prev_e = prev_ptr = prev_pos = None
for n in range(parent_count):
pos = parent.tell()
- ptr = parent.read(b'>I')[0]
+ ptr = parent.read(b">I")[0]
e = DSStoreEntry.read(parent)
if ptr == node:
@@ -870,7 +875,7 @@ class DSStore(object):
right_node = ptr
right_pos = pos
break
-
+
prev_e = e
prev_ptr = ptr
prev_pos = pos
@@ -884,24 +889,27 @@ class DSStore(object):
right_node = parent_next
right_pos = parent.tell()
- parent_used = parent.tell()
-
+ _ = parent.tell()
+
if left_node and right_node:
- with self._get_block(left_node) as left, \
- self._get_block(right_node) as right:
+ with self._get_block(left_node) as left, self._get_block(
+ right_node
+ ) as right:
blocks = [left, block, right]
pivots = [left_pivot, right_pivot]
-
+
entries, pointers, before = self._extract(blocks, pivots)
# If there's a chance that we could use two pages instead
# of three, go for it
- pivots = self._split2(blocks, entries, pointers,
- before, bool(next_node))
+ pivots = self._split2(
+ blocks, entries, pointers, before, bool(next_node)
+ )
if pivots is None:
ptrs = [left_node, node, right_node]
- pivots = self._split3(blocks, entries, pointers,
- before, bool(next_node))
+ pivots = self._split3(
+ blocks, entries, pointers, before, bool(next_node)
+ )
else:
if pivots:
ptrs = [left_node, node]
@@ -913,7 +921,7 @@ class DSStore(object):
self._store.release(right_node)
self._nodes -= 1
self._dirty = True
-
+
# Remove the pivots from the parent
with self._get_block(path[-1]) as parent:
if right_node == parent_next:
@@ -925,11 +933,11 @@ class DSStore(object):
parent.delete(right_pos - left_pos)
parent.seek(0)
parent_count -= 2
- parent.write(b'>II', parent_next, parent_count)
+ parent.write(b">II", parent_next, parent_count)
self._records -= 2
-
+
# Replace with those in pivots
- for e,rp in zip(pivots, ptrs[1:]):
+ for e, rp in zip(pivots, ptrs[1:]):
self._insert_inner(path[:-1], path[-1], e, rp)
elif left_node:
with self._get_block(left_node) as left:
@@ -938,8 +946,9 @@ class DSStore(object):
entries, pointers, before = self._extract(blocks, pivots)
- pivots = self._split2(blocks, entries, pointers,
- before, bool(next_node))
+ pivots = self._split2(
+ blocks, entries, pointers, before, bool(next_node)
+ )
# Remove the pivot from the parent
with self._get_block(path[-1]) as parent:
@@ -952,7 +961,7 @@ class DSStore(object):
parent.delete(node_pos - left_pos)
parent.seek(0)
parent_count -= 1
- parent.write(b'>II', parent_next, parent_count)
+ parent.write(b">II", parent_next, parent_count)
self._records -= 1
# Replace the pivot
@@ -965,8 +974,9 @@ class DSStore(object):
entries, pointers, before = self._extract(blocks, pivots)
- pivots = self._split2(blocks, entries, pointers,
- before, bool(next_node))
+ pivots = self._split2(
+ blocks, entries, pointers, before, bool(next_node)
+ )
# Remove the pivot from the parent
with self._get_block(path[-1]) as parent:
@@ -979,13 +989,12 @@ class DSStore(object):
parent.delete(right_pos - node_pos)
parent.seek(0)
parent_count -= 1
- parent.write(b'>II', parent_next, parent_count)
+ parent.write(b">II", parent_next, parent_count)
self._records -= 1
# Replace the pivot
if pivots:
- self._insert_inner(path[:-1], path[-1], pivots[0],
- right_node)
+ self._insert_inner(path[:-1], path[-1], pivots[0], right_node)
if not path and not parent_count:
self._store.release(path[-1])
@@ -994,7 +1003,7 @@ class DSStore(object):
self._rootnode = node
else:
count, used = self._block_usage(path[-1])
-
+
if used < self._page_size // 2:
self._rebalance(path[:-1], path[-1])
@@ -1002,31 +1011,32 @@ class DSStore(object):
# lower-cased.
def _delete_leaf(self, node, filename_lc, code):
found = False
-
+
with self._get_block(node) as block:
- next_node, count = block.read(b'>II')
+ next_node, count = block.read(b">II")
for n in range(count):
pos = block.tell()
e = DSStoreEntry.read(block)
- if e.filename.lower() == filename_lc \
- and (code is None or e.code == code):
+ if e.filename.lower() == filename_lc and (
+ code is None or e.code == code
+ ):
block.seek(pos)
block.delete(e.byte_length())
found = True
-
+
# This does not affect the loop; THIS IS NOT A BUG
count -= 1
self._records -= 1
self._dirty = True
-
+
if found:
used = block.tell()
-
+
block.seek(0)
- block.write(b'>II', next_node, count)
-
+ block.write(b">II", next_node, count)
+
return used < self._page_size // 2
else:
return False
@@ -1040,7 +1050,7 @@ class DSStore(object):
rebalance = None
while True:
with self._get_block(node) as block:
- next_node, count = block.read(b'>II')
+ next_node, count = block.read(b">II")
if next_node:
path.append(node)
@@ -1053,7 +1063,7 @@ class DSStore(object):
count -= 1
block.seek(0)
- block.write(b'>II', next_node, count)
+ block.write(b">II", next_node, count)
if pos < self._page_size // 2:
rebalance = (path, node)
@@ -1064,16 +1074,17 @@ class DSStore(object):
# Delete an entry from an inner node, `node'
def _delete_inner(self, path, node, filename_lc, code):
rebalance = False
-
+
with self._get_block(node) as block:
- next_node, count = block.read(b'>II')
+ next_node, count = block.read(b">II")
for n in range(count):
pos = block.tell()
- ptr = block.read(b'>I')[0]
+ ptr = block.read(b">I")[0]
e = DSStoreEntry.read(block)
- if e.filename.lower() == filename_lc \
- and (code is None or e.code == code):
+ if e.filename.lower() == filename_lc and (
+ code is None or e.code == code
+ ):
# Take the largest from the left subtree
rebalance, largest = self._take_largest(path, ptr)
@@ -1083,20 +1094,20 @@ class DSStore(object):
next_node = ptr
block.seek(pos)
else:
- right_ptr = block.read(b'>I')[0]
+ right_ptr = block.read(b">I")[0]
block.seek(pos + 4)
-
+
block.delete(e.byte_length() + 4)
count -= 1
block.seek(0)
- block.write(b'>II', next_node, count)
+ block.write(b">II", next_node, count)
self._records -= 1
self._dirty = True
-
+
break
-
+
# Replace the pivot value
self._insert_inner(path, node, largest, right_ptr)
@@ -1107,16 +1118,16 @@ class DSStore(object):
return False
def delete(self, filename, code):
- """Delete an item, identified by ``filename`` and ``code``
- from the B-Tree."""
+ """Delete an item, identified by ``filename`` and ``code`` from the
+ B-Tree."""
if isinstance(filename, DSStoreEntry):
code = filename.code
filename = filename.filename
# If we're deleting *every* node for "filename", we must recurse
if code is None:
- ###TODO: Fix this so we can do bulk deletes
- raise ValueError('You must delete items individually. Sorry')
+ # TODO: Fix this so we can do bulk deletes
+ raise ValueError("You must delete items individually. Sorry")
# Otherwise, we're deleting *one* specific node
filename_lc = filename.lower()
@@ -1124,14 +1135,15 @@ class DSStore(object):
node = self._rootnode
while True:
with self._get_block(node) as block:
- next_node, count = block.read(b'>II')
+ next_node, count = block.read(b">II")
if next_node:
for n in range(count):
- ptr = block.read(b'>I')[0]
+ ptr = block.read(b">I")[0]
e = DSStoreEntry.read(block)
e_lc = e.filename.lower()
- if filename_lc < e_lc \
- or (filename_lc == e_lc and code < e.code):
+ if filename_lc < e_lc or (
+ filename_lc == e_lc and code < e.code
+ ):
next_node = ptr
break
elif filename_lc == e_lc and code == e.code:
@@ -1146,13 +1158,13 @@ class DSStore(object):
# Find implementation
def _find(self, node, filename_lc, code=None):
- if not isinstance(code, bytes):
- code = code.encode('latin_1')
+ if code is not None and not isinstance(code, bytes):
+ code = code.encode("latin_1")
with self._get_block(node) as block:
- next_node, count = block.read(b'>II')
+ next_node, count = block.read(b">II")
if next_node:
for n in range(count):
- ptr = block.read(b'>I')[0]
+ ptr = block.read(b">I")[0]
e = DSStoreEntry.read(block)
if filename_lc < e.filename.lower():
for e in self._find(ptr, filename_lc, code):
@@ -1176,16 +1188,16 @@ class DSStore(object):
yield e
elif code < e.code:
return
-
+
def find(self, filename, code=None):
- """Returns a generator that will iterate over matching entries in
- the B-Tree."""
+ """Returns a generator that will iterate over matching entries in the
+ B-Tree."""
if isinstance(filename, DSStoreEntry):
code = filename.code
filename = filename.filename
filename_lc = filename.lower()
-
+
return self._find(self._rootnode, filename_lc, code)
def __len__(self):
@@ -1194,36 +1206,36 @@ class DSStore(object):
def __iter__(self):
return self._traverse(self._rootnode)
- class Partial(object):
+ class Partial:
"""This is used to implement indexing."""
+
def __init__(self, store, filename):
self._store = store
self._filename = filename
def __getitem__(self, code):
if code is None:
- raise KeyError('no such key - [%s][None]' % self._filename)
+ raise KeyError("no such key - [%s][None]" % self._filename)
if not isinstance(code, bytes):
- code = code.encode('latin_1')
+ code = code.encode("latin_1")
try:
item = next(self._store.find(self._filename, code))
except StopIteration:
- raise KeyError('no such key - [%s][%s]' % (self._filename,
- code))
+ raise KeyError(f"no such key - [{self._filename}][{code}]")
- if not isinstance(item.type, (bytes, str, unicode)):
+ if not isinstance(item.type, (bytes, str)):
return item.value
-
+
return (item.type, item.value)
-
+
def __setitem__(self, code, value):
if code is None:
- raise KeyError('bad key - [%s][None]' % self._filename)
+ raise KeyError("bad key - [%s][None]" % self._filename)
if not isinstance(code, bytes):
- code = code.encode('latin_1')
+ code = code.encode("latin_1")
codec = codecs.get(code, None)
if codec:
@@ -1232,20 +1244,19 @@ class DSStore(object):
else:
entry_type = value[0]
entry_value = value[1]
-
- self._store.insert(DSStoreEntry(self._filename, code,
- entry_type, entry_value))
+
+ self._store.insert(
+ DSStoreEntry(self._filename, code, entry_type, entry_value)
+ )
def __delitem__(self, code):
if code is None:
- raise KeyError('no such key - [%s][None]' % self._filename)
+ raise KeyError("no such key - [%s][None]" % self._filename)
self._store.delete(self._filename, code)
def __iter__(self):
- for item in self._store.find(self._filename):
- yield item
+ yield from self._store.find(self._filename)
def __getitem__(self, filename):
return self.Partial(self, filename)
-
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/LICENSE b/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/LICENSE
index e91f4eb38..e91f4eb38 100644
--- a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/LICENSE
+++ b/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/LICENSE
diff --git a/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/__init__.py b/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/__init__.py
new file mode 100644
index 000000000..0f925e7d1
--- /dev/null
+++ b/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/__init__.py
@@ -0,0 +1,47 @@
+# flake8: noqa
+from .alias import *
+from .bookmark import *
+
+__version__ = "2.2.2"
+
+__all__ = [
+ "__version__",
+ "ALIAS_KIND_FILE",
+ "ALIAS_KIND_FOLDER",
+ "ALIAS_HFS_VOLUME_SIGNATURE",
+ "ALIAS_FIXED_DISK",
+ "ALIAS_NETWORK_DISK",
+ "ALIAS_400KB_FLOPPY_DISK",
+ "ALIAS_800KB_FLOPPY_DISK",
+ "ALIAS_1_44MB_FLOPPY_DISK",
+ "ALIAS_EJECTABLE_DISK",
+ "ALIAS_NO_CNID",
+ "kBookmarkPath",
+ "kBookmarkCNIDPath",
+ "kBookmarkFileProperties",
+ "kBookmarkFileName",
+ "kBookmarkFileID",
+ "kBookmarkFileCreationDate",
+ "kBookmarkTOCPath",
+ "kBookmarkVolumePath",
+ "kBookmarkVolumeURL",
+ "kBookmarkVolumeName",
+ "kBookmarkVolumeUUID",
+ "kBookmarkVolumeSize",
+ "kBookmarkVolumeCreationDate",
+ "kBookmarkVolumeProperties",
+ "kBookmarkContainingFolder",
+ "kBookmarkUserName",
+ "kBookmarkUID",
+ "kBookmarkWasFileReference",
+ "kBookmarkCreationOptions",
+ "kBookmarkURLLengths",
+ "kBookmarkSecurityExtension",
+ "AppleShareInfo",
+ "VolumeInfo",
+ "TargetInfo",
+ "Alias",
+ "Bookmark",
+ "Data",
+ "URL",
+]
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/alias.py b/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/alias.py
index f74b949ea..bf34fb01b 100644
--- a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/alias.py
+++ b/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/alias.py
@@ -1,30 +1,29 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-from __future__ import division
-
-import struct
import datetime
import io
-import re
import os
import os.path
-import stat
+import struct
import sys
+from unicodedata import normalize
-if sys.platform == 'darwin':
+if sys.platform == "darwin":
from . import osx
-try:
- long
-except NameError:
- long = int
+from .utils import mac_epoch
-from .utils import *
-
ALIAS_KIND_FILE = 0
ALIAS_KIND_FOLDER = 1
-ALIAS_HFS_VOLUME_SIGNATURE = b'H+'
+ALIAS_HFS_VOLUME_SIGNATURE = b"H+"
+
+ALIAS_FILESYSTEM_UDF = "UDF (CD/DVD)"
+ALIAS_FILESYSTEM_FAT32 = "FAT32"
+ALIAS_FILESYSTEM_EXFAT = "exFAT"
+ALIAS_FILESYSTEM_HFSX = "HFSX"
+ALIAS_FILESYSTEM_HFSPLUS = "HFS+"
+ALIAS_FILESYSTEM_FTP = "FTP"
+ALIAS_FILESYSTEM_NTFS = "NTFS"
+ALIAS_FILESYSTEM_UNKNOWN = "unknown"
ALIAS_FIXED_DISK = 0
ALIAS_NETWORK_DISK = 1
@@ -33,19 +32,36 @@ ALIAS_800KB_FLOPPY_DISK = 3
ALIAS_1_44MB_FLOPPY_DISK = 4
ALIAS_EJECTABLE_DISK = 5
-ALIAS_NO_CNID = 0xffffffff
+ALIAS_NO_CNID = 0xFFFFFFFF
+
+ALIAS_FSTYPE_MAP = {
+ # Version 2 aliases
+ b"HX": ALIAS_FILESYSTEM_HFSX,
+ b"H+": ALIAS_FILESYSTEM_HFSPLUS,
+ # Version 3 aliases
+ b"BDcu": ALIAS_FILESYSTEM_UDF,
+ b"BDIS": ALIAS_FILESYSTEM_FAT32,
+ b"BDxF": ALIAS_FILESYSTEM_EXFAT,
+ b"HX\0\0": ALIAS_FILESYSTEM_HFSX,
+ b"H+\0\0": ALIAS_FILESYSTEM_HFSPLUS,
+ b"KG\0\0": ALIAS_FILESYSTEM_FTP,
+ b"NTcu": ALIAS_FILESYSTEM_NTFS,
+}
+
def encode_utf8(s):
if isinstance(s, bytes):
return s
- return s.encode('utf-8')
+ return s.encode("utf-8")
+
def decode_utf8(s):
if isinstance(s, bytes):
- return s.decode('utf-8')
+ return s.decode("utf-8")
return s
-class AppleShareInfo (object):
+
+class AppleShareInfo:
def __init__(self, zone=None, server=None, user=None):
#: The AppleShare zone
self.zone = zone
@@ -55,22 +71,38 @@ class AppleShareInfo (object):
self.user = user
def __repr__(self):
- return 'AppleShareInfo(%r,%r,%r)' % (self.zone, self.server, self.user)
-
-class VolumeInfo (object):
- def __init__(self, name, creation_date, fs_type, disk_type,
- attribute_flags, fs_id, appleshare_info=None,
- driver_name=None, posix_path=None, disk_image_alias=None,
- dialup_info=None, network_mount_info=None):
+ return "AppleShareInfo({!r},{!r},{!r})".format(
+ self.zone, self.server, self.user
+ )
+
+
+class VolumeInfo:
+ def __init__(
+ self,
+ name,
+ creation_date,
+ fs_type,
+ disk_type,
+ attribute_flags,
+ fs_id,
+ appleshare_info=None,
+ driver_name=None,
+ posix_path=None,
+ disk_image_alias=None,
+ dialup_info=None,
+ network_mount_info=None,
+ ):
#: The name of the volume on which the target resides
self.name = name
-
+
#: The creation date of the target's volume
self.creation_date = creation_date
-
- #: The filesystem type (a two character code, e.g. ``b'H+'`` for HFS+)
+
+ #: The filesystem type
+ #: (for v2 aliases, this is a 2-character code; for v3 aliases, a
+ #: 4-character code).
self.fs_type = fs_type
-
+
#: The type of disk; should be one of
#:
#: * ALIAS_FIXED_DISK
@@ -109,30 +141,60 @@ class VolumeInfo (object):
#: Network mount information (for automatic remounting)
self.network_mount_info = network_mount_info
+ @property
+ def filesystem_type(self):
+ return ALIAS_FSTYPE_MAP.get(self.fs_type, ALIAS_FILESYSTEM_UNKNOWN)
+
def __repr__(self):
- args = ['name', 'creation_date', 'fs_type', 'disk_type',
- 'attribute_flags', 'fs_id']
+ args = [
+ "name",
+ "creation_date",
+ "fs_type",
+ "disk_type",
+ "attribute_flags",
+ "fs_id",
+ ]
values = []
for a in args:
v = getattr(self, a)
values.append(repr(v))
-
- kwargs = ['appleshare_info', 'driver_name', 'posix_path',
- 'disk_image_alias', 'dialup_info', 'network_mount_info']
+
+ kwargs = [
+ "appleshare_info",
+ "driver_name",
+ "posix_path",
+ "disk_image_alias",
+ "dialup_info",
+ "network_mount_info",
+ ]
for a in kwargs:
v = getattr(self, a)
if v is not None:
- values.append('%s=%r' % (a, v))
- return 'VolumeInfo(%s)' % ','.join(values)
-
-class TargetInfo (object):
- def __init__(self, kind, filename, folder_cnid, cnid, creation_date,
- creator_code, type_code, levels_from=-1, levels_to=-1,
- folder_name=None, cnid_path=None, carbon_path=None,
- posix_path=None, user_home_prefix_len=None):
+ values.append(f"{a}={v!r}")
+ return "VolumeInfo(%s)" % ",".join(values)
+
+
+class TargetInfo:
+ def __init__(
+ self,
+ kind,
+ filename,
+ folder_cnid,
+ cnid,
+ creation_date,
+ creator_code,
+ type_code,
+ levels_from=-1,
+ levels_to=-1,
+ folder_name=None,
+ cnid_path=None,
+ carbon_path=None,
+ posix_path=None,
+ user_home_prefix_len=None,
+ ):
#: Either ALIAS_KIND_FILE or ALIAS_KIND_FOLDER
self.kind = kind
-
+
#: The filename of the target
self.filename = filename
@@ -178,26 +240,39 @@ class TargetInfo (object):
self.user_home_prefix_len = user_home_prefix_len
def __repr__(self):
- args = ['kind', 'filename', 'folder_cnid', 'cnid', 'creation_date',
- 'creator_code', 'type_code']
+ args = [
+ "kind",
+ "filename",
+ "folder_cnid",
+ "cnid",
+ "creation_date",
+ "creator_code",
+ "type_code",
+ ]
values = []
for a in args:
v = getattr(self, a)
values.append(repr(v))
if self.levels_from != -1:
- values.append('levels_from=%r' % self.levels_from)
+ values.append("levels_from=%r" % self.levels_from)
if self.levels_to != -1:
- values.append('levels_to=%r' % self.levels_to)
-
- kwargs = ['folder_name', 'cnid_path', 'carbon_path',
- 'posix_path', 'user_home_prefix_len']
+ values.append("levels_to=%r" % self.levels_to)
+
+ kwargs = [
+ "folder_name",
+ "cnid_path",
+ "carbon_path",
+ "posix_path",
+ "user_home_prefix_len",
+ ]
for a in kwargs:
v = getattr(self, a)
- values.append('%s=%r' % (a, v))
+ values.append(f"{a}={v!r}")
+
+ return "TargetInfo(%s)" % ",".join(values)
+
- return 'TargetInfo(%s)' % ','.join(values)
-
TAG_CARBON_FOLDER_NAME = 0
TAG_CNID_PATH = 1
TAG_CARBON_PATH = 2
@@ -216,21 +291,28 @@ TAG_POSIX_PATH_TO_MOUNTPOINT = 19
TAG_RECURSIVE_ALIAS_OF_DISK_IMAGE = 20
TAG_USER_HOME_LENGTH_PREFIX = 21
-class Alias (object):
- def __init__(self, appinfo=b'\0\0\0\0', version=2, volume=None,
- target=None, extra=[]):
+
+class Alias:
+ def __init__(
+ self,
+ appinfo=b"\0\0\0\0",
+ version=2,
+ volume=None,
+ target=None,
+ extra=[],
+ ):
"""Construct a new :class:`Alias` object with the specified
contents."""
#: Application specific information (four byte byte-string)
self.appinfo = appinfo
- #: Version (we support only version 2)
+ #: Version (we support versions 2 and 3)
self.version = version
#: A :class:`VolumeInfo` object describing the target's volume
self.volume = volume
-
+
#: A :class:`TargetInfo` object describing the target
self.target = target
@@ -239,47 +321,91 @@ class Alias (object):
@classmethod
def _from_fd(cls, b):
- appinfo, recsize, version = struct.unpack(b'>4shh', b.read(8))
+ appinfo, recsize, version = struct.unpack(b">4shh", b.read(8))
if recsize < 150:
- raise ValueError('Incorrect alias length')
-
- if version != 2:
- raise ValueError('Unsupported alias version %u' % version)
-
- kind, volname, voldate, fstype, disktype, \
- folder_cnid, filename, cnid, crdate, creator_code, type_code, \
- levels_from, levels_to, volattrs, volfsid, reserved = \
- struct.unpack(b'>h28pI2shI64pII4s4shhI2s10s', b.read(142))
+ raise ValueError("Incorrect alias length")
+
+ if version not in (2, 3):
+ raise ValueError("Unsupported alias version %u" % version)
+
+ if version == 2:
+ (
+ kind, # h
+ volname, # 28p
+ voldate, # I
+ fstype, # 2s
+ disktype, # h
+ folder_cnid, # I
+ filename, # 64p
+ cnid, # I
+ crdate, # I
+ creator_code, # 4s
+ type_code, # 4s
+ levels_from, # h
+ levels_to, # h
+ volattrs, # I
+ volfsid, # 2s
+ reserved, # 10s
+ ) = struct.unpack(b">h28pI2shI64pII4s4shhI2s10s", b.read(142))
+ else:
+ (
+ kind, # h
+ voldate_hr, # Q
+ fstype, # 4s
+ disktype, # h
+ folder_cnid, # I
+ cnid, # I
+ crdate_hr, # Q
+ volattrs, # I
+ reserved, # 14s
+ ) = struct.unpack(b">hQ4shIIQI14s", b.read(46))
+
+ volname = b""
+ filename = b""
+ creator_code = None
+ type_code = None
+ voldate = voldate_hr / 65536.0
+ crdate = crdate_hr / 65536.0
voldate = mac_epoch + datetime.timedelta(seconds=voldate)
crdate = mac_epoch + datetime.timedelta(seconds=crdate)
alias = Alias()
alias.appinfo = appinfo
-
- alias.volume = VolumeInfo (volname.decode().replace('/',':'),
- voldate, fstype, disktype,
- volattrs, volfsid)
- alias.target = TargetInfo (kind, filename.decode().replace('/',':'),
- folder_cnid, cnid,
- crdate, creator_code, type_code)
+
+ alias.volume = VolumeInfo(
+ volname.decode().replace("/", ":"),
+ voldate,
+ fstype,
+ disktype,
+ volattrs,
+ volfsid,
+ )
+ alias.target = TargetInfo(
+ kind,
+ filename.decode().replace("/", ":"),
+ folder_cnid,
+ cnid,
+ crdate,
+ creator_code,
+ type_code,
+ )
alias.target.levels_from = levels_from
alias.target.levels_to = levels_to
-
- tag = struct.unpack(b'>h', b.read(2))[0]
+
+ tag = struct.unpack(b">h", b.read(2))[0]
while tag != -1:
- length = struct.unpack(b'>h', b.read(2))[0]
+ length = struct.unpack(b">h", b.read(2))[0]
value = b.read(length)
if length & 1:
b.read(1)
if tag == TAG_CARBON_FOLDER_NAME:
- alias.target.folder_name = value.decode().replace('/',':')
+ alias.target.folder_name = value.decode().replace("/", ":")
elif tag == TAG_CNID_PATH:
- alias.target.cnid_path = struct.unpack('>%uI' % (length // 4),
- value)
+ alias.target.cnid_path = struct.unpack(">%uI" % (length // 4), value)
elif tag == TAG_CARBON_PATH:
alias.target.carbon_path = value
elif tag == TAG_APPLESHARE_ZONE:
@@ -301,17 +427,19 @@ class Alias (object):
elif tag == TAG_DIALUP_INFO:
alias.volume.dialup_info = value
elif tag == TAG_UNICODE_FILENAME:
- alias.target.filename = value[2:].decode('utf-16be')
+ alias.target.filename = value[2:].decode("utf-16be")
elif tag == TAG_UNICODE_VOLUME_NAME:
- alias.volume.name = value[2:].decode('utf-16be')
+ alias.volume.name = value[2:].decode("utf-16be")
elif tag == TAG_HIGH_RES_VOLUME_CREATION_DATE:
- seconds = struct.unpack(b'>Q', value)[0] / 65536.0
- alias.volume.creation_date \
- = mac_epoch + datetime.timedelta(seconds=seconds)
+ seconds = struct.unpack(b">Q", value)[0] / 65536.0
+ alias.volume.creation_date = mac_epoch + datetime.timedelta(
+ seconds=seconds
+ )
elif tag == TAG_HIGH_RES_CREATION_DATE:
- seconds = struct.unpack(b'>Q', value)[0] / 65536.0
- alias.target.creation_date \
- = mac_epoch + datetime.timedelta(seconds=seconds)
+ seconds = struct.unpack(b">Q", value)[0] / 65536.0
+ alias.target.creation_date = mac_epoch + datetime.timedelta(
+ seconds=seconds
+ )
elif tag == TAG_POSIX_PATH:
alias.target.posix_path = value.decode()
elif tag == TAG_POSIX_PATH_TO_MOUNTPOINT:
@@ -319,14 +447,14 @@ class Alias (object):
elif tag == TAG_RECURSIVE_ALIAS_OF_DISK_IMAGE:
alias.volume.disk_image_alias = Alias.from_bytes(value)
elif tag == TAG_USER_HOME_LENGTH_PREFIX:
- alias.target.user_home_prefix_len = struct.unpack(b'>h', value)[0]
+ alias.target.user_home_prefix_len = struct.unpack(b">h", value)[0]
else:
alias.extra.append((tag, value))
- tag = struct.unpack(b'>h', b.read(2))[0]
-
+ tag = struct.unpack(b">h", b.read(2))[0]
+
return alias
-
+
@classmethod
def from_bytes(cls, bytes):
"""Construct an :class:`Alias` object given binary Alias data."""
@@ -336,32 +464,40 @@ class Alias (object):
@classmethod
def for_file(cls, path):
"""Create an :class:`Alias` that points at the specified file."""
- if sys.platform != 'darwin':
- raise Exception('Not implemented (requires special support)')
+ if sys.platform != "darwin":
+ raise Exception("Not implemented (requires special support)")
path = encode_utf8(path)
-
+
a = Alias()
# Find the filesystem
st = osx.statfs(path)
vol_path = st.f_mntonname
-
+
+ # File and folder names in HFS+ are normalized to a form similar to NFD.
+ # Must be normalized (NFD->NFC) before use to avoid unicode string comparison issues.
+ vol_path = normalize("NFC", vol_path.decode("utf-8")).encode("utf-8")
+
# Grab its attributes
- attrs = [osx.ATTR_CMN_CRTIME,
- osx.ATTR_VOL_NAME,
- 0, 0, 0]
+ attrs = [osx.ATTR_CMN_CRTIME, osx.ATTR_VOL_NAME, 0, 0, 0]
volinfo = osx.getattrlist(vol_path, attrs, 0)
vol_crtime = volinfo[0]
vol_name = encode_utf8(volinfo[1])
-
+
# Also grab various attributes of the file
- attrs = [(osx.ATTR_CMN_OBJTYPE
- | osx.ATTR_CMN_CRTIME
- | osx.ATTR_CMN_FNDRINFO
- | osx.ATTR_CMN_FILEID
- | osx.ATTR_CMN_PARENTID), 0, 0, 0, 0]
+ attrs = [
+ osx.ATTR_CMN_OBJTYPE
+ | osx.ATTR_CMN_CRTIME
+ | osx.ATTR_CMN_FNDRINFO
+ | osx.ATTR_CMN_FILEID
+ | osx.ATTR_CMN_PARENTID,
+ 0,
+ 0,
+ 0,
+ 0,
+ ]
info = osx.getattrlist(path, attrs, osx.FSOPT_NOFOLLOW)
if info[0] == osx.VDIR:
@@ -371,27 +507,27 @@ class Alias (object):
cnid = info[3]
folder_cnid = info[4]
-
+
dirname, filename = os.path.split(path)
- if dirname == b'' or dirname == b'.':
+ if dirname == b"" or dirname == b".":
dirname = os.getcwd()
foldername = os.path.basename(dirname)
-
+
creation_date = info[1]
if kind == ALIAS_KIND_FILE:
- creator_code = struct.pack(b'I', info[2].fileInfo.fileCreator)
- type_code = struct.pack(b'I', info[2].fileInfo.fileType)
+ creator_code = struct.pack(b"I", info[2].fileInfo.fileCreator)
+ type_code = struct.pack(b"I", info[2].fileInfo.fileType)
else:
- creator_code = b'\0\0\0\0'
- type_code = b'\0\0\0\0'
+ creator_code = b"\0\0\0\0"
+ type_code = b"\0\0\0\0"
- a.target = TargetInfo(kind, filename, folder_cnid, cnid, creation_date,
- creator_code, type_code)
- a.volume = VolumeInfo(vol_name, vol_crtime, b'H+',
- ALIAS_FIXED_DISK, 0, b'\0\0')
+ a.target = TargetInfo(
+ kind, filename, folder_cnid, cnid, creation_date, creator_code, type_code
+ )
+ a.volume = VolumeInfo(vol_name, vol_crtime, b"H+", ALIAS_FIXED_DISK, 0, b"\0\0")
a.target.folder_name = foldername
a.volume.posix_path = vol_path
@@ -399,10 +535,10 @@ class Alias (object):
rel_path = os.path.relpath(path, vol_path)
# Leave off the initial '/' if vol_path is '/' (no idea why)
- if vol_path == b'/':
+ if vol_path == b"/":
a.target.posix_path = rel_path
else:
- a.target.posix_path = b'/' + rel_path
+ a.target.posix_path = b"/" + rel_path
# Construct the Carbon and CNID paths
carbon_path = []
@@ -415,173 +551,202 @@ class Alias (object):
attrs = [osx.ATTR_CMN_FILEID, 0, 0, 0, 0]
info = osx.getattrlist(os.path.join(vol_path, head), attrs, 0)
cnid_path.append(info[0])
- carbon_tail = tail.replace(b':',b'/')
+ carbon_tail = tail.replace(b":", b"/")
carbon_path.insert(0, carbon_tail)
head, tail = os.path.split(head)
- carbon_path = vol_name + b':' + b':\0'.join(carbon_path)
+ carbon_path = vol_name + b":" + b":\0".join(carbon_path)
a.target.carbon_path = carbon_path
a.target.cnid_path = cnid_path
return a
-
+
def _to_fd(self, b):
# We'll come back and fix the length when we're done
pos = b.tell()
- b.write(struct.pack(b'>4shh', self.appinfo, 0, self.version))
+ b.write(struct.pack(b">4shh", self.appinfo, 0, self.version))
- carbon_volname = encode_utf8(self.volume.name).replace(b':',b'/')
- carbon_filename = encode_utf8(self.target.filename).replace(b':',b'/')
+ carbon_volname = encode_utf8(self.volume.name).replace(b":", b"/")
+ carbon_filename = encode_utf8(self.target.filename).replace(b":", b"/")
voldate = (self.volume.creation_date - mac_epoch).total_seconds()
crdate = (self.target.creation_date - mac_epoch).total_seconds()
- # NOTE: crdate should be in local time, but that's system dependent
- # (so doing so is ridiculous, and nothing could rely on it).
- b.write(struct.pack(b'>h28pI2shI64pII4s4shhI2s10s',
- self.target.kind,
- carbon_volname, int(voldate),
- self.volume.fs_type,
- self.volume.disk_type,
- self.target.folder_cnid,
- carbon_filename,
- self.target.cnid,
- int(crdate),
- self.target.creator_code,
- self.target.type_code,
- self.target.levels_from,
- self.target.levels_to,
- self.volume.attribute_flags,
- self.volume.fs_id,
- b'\0'*10))
+ if self.version == 2:
+ # NOTE: crdate should be in local time, but that's system dependent
+ # (so doing so is ridiculous, and nothing could rely on it).
+ b.write(
+ struct.pack(
+ b">h28pI2shI64pII4s4shhI2s10s",
+ self.target.kind, # h
+ carbon_volname, # 28p
+ int(voldate), # I
+ self.volume.fs_type, # 2s
+ self.volume.disk_type, # h
+ self.target.folder_cnid, # I
+ carbon_filename, # 64p
+ self.target.cnid, # I
+ int(crdate), # I
+ self.target.creator_code, # 4s
+ self.target.type_code, # 4s
+ self.target.levels_from, # h
+ self.target.levels_to, # h
+ self.volume.attribute_flags, # I
+ self.volume.fs_id, # 2s
+ b"\0" * 10, # 10s
+ )
+ )
+ else:
+ b.write(
+ struct.pack(
+ b">hQ4shIIQI14s",
+ self.target.kind, # h
+ int(voldate * 65536), # Q
+ self.volume.fs_type, # 4s
+ self.volume.disk_type, # h
+ self.target.folder_cnid, # I
+ self.target.cnid, # I
+ int(crdate * 65536), # Q
+ self.volume.attribute_flags, # I
+ b"\0" * 14, # 14s
+ )
+ )
# Excuse the odd order; we're copying Finder
if self.target.folder_name:
- carbon_foldername = encode_utf8(self.target.folder_name)\
- .replace(b':',b'/')
- b.write(struct.pack(b'>hh', TAG_CARBON_FOLDER_NAME,
- len(carbon_foldername)))
+ carbon_foldername = encode_utf8(self.target.folder_name).replace(b":", b"/")
+ b.write(struct.pack(b">hh", TAG_CARBON_FOLDER_NAME, len(carbon_foldername)))
b.write(carbon_foldername)
if len(carbon_foldername) & 1:
- b.write(b'\0')
+ b.write(b"\0")
- b.write(struct.pack(b'>hhQhhQ',
+ b.write(
+ struct.pack(
+ b">hhQhhQ",
TAG_HIGH_RES_VOLUME_CREATION_DATE,
- 8, int(voldate * 65536),
+ 8,
+ int(voldate * 65536),
TAG_HIGH_RES_CREATION_DATE,
- 8, int(crdate * 65536)))
+ 8,
+ int(crdate * 65536),
+ )
+ )
if self.target.cnid_path:
- cnid_path = struct.pack('>%uI' % len(self.target.cnid_path),
- *self.target.cnid_path)
- b.write(struct.pack(b'>hh', TAG_CNID_PATH,
- len(cnid_path)))
+ cnid_path = struct.pack(
+ ">%uI" % len(self.target.cnid_path), *self.target.cnid_path
+ )
+ b.write(struct.pack(b">hh", TAG_CNID_PATH, len(cnid_path)))
b.write(cnid_path)
if self.target.carbon_path:
- carbon_path=encode_utf8(self.target.carbon_path)
- b.write(struct.pack(b'>hh', TAG_CARBON_PATH,
- len(carbon_path)))
+ carbon_path = encode_utf8(self.target.carbon_path)
+ b.write(struct.pack(b">hh", TAG_CARBON_PATH, len(carbon_path)))
b.write(carbon_path)
if len(carbon_path) & 1:
- b.write(b'\0')
+ b.write(b"\0")
if self.volume.appleshare_info:
ai = self.volume.appleshare_info
if ai.zone:
- b.write(struct.pack(b'>hh', TAG_APPLESHARE_ZONE,
- len(ai.zone)))
+ b.write(struct.pack(b">hh", TAG_APPLESHARE_ZONE, len(ai.zone)))
b.write(ai.zone)
if len(ai.zone) & 1:
- b.write(b'\0')
+ b.write(b"\0")
if ai.server:
- b.write(struct.pack(b'>hh', TAG_APPLESHARE_SERVER_NAME,
- len(ai.server)))
+ b.write(struct.pack(b">hh", TAG_APPLESHARE_SERVER_NAME, len(ai.server)))
b.write(ai.server)
if len(ai.server) & 1:
- b.write(b'\0')
+ b.write(b"\0")
if ai.username:
- b.write(struct.pack(b'>hh', TAG_APPLESHARE_USERNAME,
- len(ai.username)))
+ b.write(struct.pack(b">hh", TAG_APPLESHARE_USERNAME, len(ai.username)))
b.write(ai.username)
if len(ai.username) & 1:
- b.write(b'\0')
+ b.write(b"\0")
if self.volume.driver_name:
driver_name = encode_utf8(self.volume.driver_name)
- b.write(struct.pack(b'>hh', TAG_DRIVER_NAME,
- len(driver_name)))
+ b.write(struct.pack(b">hh", TAG_DRIVER_NAME, len(driver_name)))
b.write(driver_name)
if len(driver_name) & 1:
- b.write(b'\0')
+ b.write(b"\0")
if self.volume.network_mount_info:
- b.write(struct.pack(b'>hh', TAG_NETWORK_MOUNT_INFO,
- len(self.volume.network_mount_info)))
+ b.write(
+ struct.pack(
+ b">hh", TAG_NETWORK_MOUNT_INFO, len(self.volume.network_mount_info)
+ )
+ )
b.write(self.volume.network_mount_info)
if len(self.volume.network_mount_info) & 1:
- b.write(b'\0')
+ b.write(b"\0")
if self.volume.dialup_info:
- b.write(struct.pack(b'>hh', TAG_DIALUP_INFO,
- len(self.volume.network_mount_info)))
+ b.write(
+ struct.pack(
+ b">hh", TAG_DIALUP_INFO, len(self.volume.network_mount_info)
+ )
+ )
b.write(self.volume.network_mount_info)
if len(self.volume.network_mount_info) & 1:
- b.write(b'\0')
+ b.write(b"\0")
- utf16 = decode_utf8(self.target.filename)\
- .replace(':','/').encode('utf-16-be')
- b.write(struct.pack(b'>hhh', TAG_UNICODE_FILENAME,
- len(utf16) + 2,
- len(utf16) // 2))
+ utf16 = decode_utf8(self.target.filename).replace(":", "/").encode("utf-16-be")
+ b.write(
+ struct.pack(b">hhh", TAG_UNICODE_FILENAME, len(utf16) + 2, len(utf16) // 2)
+ )
b.write(utf16)
- utf16 = decode_utf8(self.volume.name)\
- .replace(':','/').encode('utf-16-be')
- b.write(struct.pack(b'>hhh', TAG_UNICODE_VOLUME_NAME,
- len(utf16) + 2,
- len(utf16) // 2))
+ utf16 = decode_utf8(self.volume.name).replace(":", "/").encode("utf-16-be")
+ b.write(
+ struct.pack(
+ b">hhh", TAG_UNICODE_VOLUME_NAME, len(utf16) + 2, len(utf16) // 2
+ )
+ )
b.write(utf16)
if self.target.posix_path:
posix_path = encode_utf8(self.target.posix_path)
- b.write(struct.pack(b'>hh', TAG_POSIX_PATH,
- len(posix_path)))
+ b.write(struct.pack(b">hh", TAG_POSIX_PATH, len(posix_path)))
b.write(posix_path)
if len(posix_path) & 1:
- b.write(b'\0')
+ b.write(b"\0")
if self.volume.posix_path:
posix_path = encode_utf8(self.volume.posix_path)
- b.write(struct.pack(b'>hh', TAG_POSIX_PATH_TO_MOUNTPOINT,
- len(posix_path)))
+ b.write(struct.pack(b">hh", TAG_POSIX_PATH_TO_MOUNTPOINT, len(posix_path)))
b.write(posix_path)
if len(posix_path) & 1:
- b.write(b'\0')
+ b.write(b"\0")
if self.volume.disk_image_alias:
d = self.volume.disk_image_alias.to_bytes()
- b.write(struct.pack(b'>hh', TAG_RECURSIVE_ALIAS_OF_DISK_IMAGE,
- len(d)))
+ b.write(struct.pack(b">hh", TAG_RECURSIVE_ALIAS_OF_DISK_IMAGE, len(d)))
b.write(d)
if len(d) & 1:
- b.write(b'\0')
+ b.write(b"\0")
if self.target.user_home_prefix_len is not None:
- b.write(struct.pack(b'>hhh', TAG_USER_HOME_LENGTH_PREFIX,
- 2, self.target.user_home_prefix_len))
-
- for t,v in self.extra:
- b.write(struct.pack(b'>hh', t, len(v)))
+ b.write(
+ struct.pack(
+ b">hhh",
+ TAG_USER_HOME_LENGTH_PREFIX,
+ 2,
+ self.target.user_home_prefix_len,
+ )
+ )
+
+ for t, v in self.extra:
+ b.write(struct.pack(b">hh", t, len(v)))
b.write(v)
if len(v) & 1:
- b.write(b'\0')
+ b.write(b"\0")
+
+ b.write(struct.pack(b">hh", -1, 0))
- b.write(struct.pack(b'>hh', -1, 0))
-
blen = b.tell() - pos
b.seek(pos + 4, os.SEEK_SET)
- b.write(struct.pack(b'>h', blen))
+ b.write(struct.pack(b">h", blen))
def to_bytes(self):
"""Returns the binary representation for this :class:`Alias`."""
@@ -590,18 +755,18 @@ class Alias (object):
return b.getvalue()
def __str__(self):
- return '<Alias target=%s>' % self.target.filename
+ return "<Alias target=%s>" % self.target.filename
def __repr__(self):
values = []
- if self.appinfo != b'\0\0\0\0':
- values.append('appinfo=%r' % self.appinfo)
+ if self.appinfo != b"\0\0\0\0":
+ values.append("appinfo=%r" % self.appinfo)
if self.version != 2:
- values.append('version=%r' % self.version)
+ values.append("version=%r" % self.version)
if self.volume is not None:
- values.append('volume=%r' % self.volume)
+ values.append("volume=%r" % self.volume)
if self.target is not None:
- values.append('target=%r' % self.target)
+ values.append("target=%r" % self.target)
if self.extra:
- values.append('extra=%r' % self.extra)
- return 'Alias(%s)' % ','.join(values)
+ values.append("extra=%r" % self.extra)
+ return "Alias(%s)" % ",".join(values)
diff --git a/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/bookmark.py b/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/bookmark.py
new file mode 100644
index 000000000..00e16feb1
--- /dev/null
+++ b/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/bookmark.py
@@ -0,0 +1,677 @@
+# This file implements the Apple "bookmark" format, which is the replacement
+# for the old-fashioned alias format. The details of this format were
+# reverse engineered; some things are still not entirely clear.
+#
+import datetime
+import os
+import struct
+import sys
+import uuid
+from urllib.parse import urljoin
+
+if sys.platform == "darwin":
+ from . import osx
+
+from .utils import osx_epoch
+
+BMK_DATA_TYPE_MASK = 0xFFFFFF00
+BMK_DATA_SUBTYPE_MASK = 0x000000FF
+
+BMK_STRING = 0x0100
+BMK_DATA = 0x0200
+BMK_NUMBER = 0x0300
+BMK_DATE = 0x0400
+BMK_BOOLEAN = 0x0500
+BMK_ARRAY = 0x0600
+BMK_DICT = 0x0700
+BMK_UUID = 0x0800
+BMK_URL = 0x0900
+BMK_NULL = 0x0A00
+
+BMK_ST_ZERO = 0x0000
+BMK_ST_ONE = 0x0001
+
+BMK_BOOLEAN_ST_FALSE = 0x0000
+BMK_BOOLEAN_ST_TRUE = 0x0001
+
+# Subtypes for BMK_NUMBER are really CFNumberType values
+kCFNumberSInt8Type = 1
+kCFNumberSInt16Type = 2
+kCFNumberSInt32Type = 3
+kCFNumberSInt64Type = 4
+kCFNumberFloat32Type = 5
+kCFNumberFloat64Type = 6
+kCFNumberCharType = 7
+kCFNumberShortType = 8
+kCFNumberIntType = 9
+kCFNumberLongType = 10
+kCFNumberLongLongType = 11
+kCFNumberFloatType = 12
+kCFNumberDoubleType = 13
+kCFNumberCFIndexType = 14
+kCFNumberNSIntegerType = 15
+kCFNumberCGFloatType = 16
+
+# Resource property flags (from CFURLPriv.h)
+kCFURLResourceIsRegularFile = 0x00000001
+kCFURLResourceIsDirectory = 0x00000002
+kCFURLResourceIsSymbolicLink = 0x00000004
+kCFURLResourceIsVolume = 0x00000008
+kCFURLResourceIsPackage = 0x00000010
+kCFURLResourceIsSystemImmutable = 0x00000020
+kCFURLResourceIsUserImmutable = 0x00000040
+kCFURLResourceIsHidden = 0x00000080
+kCFURLResourceHasHiddenExtension = 0x00000100
+kCFURLResourceIsApplication = 0x00000200
+kCFURLResourceIsCompressed = 0x00000400
+kCFURLResourceIsSystemCompressed = 0x00000400
+kCFURLCanSetHiddenExtension = 0x00000800
+kCFURLResourceIsReadable = 0x00001000
+kCFURLResourceIsWriteable = 0x00002000
+kCFURLResourceIsExecutable = 0x00004000
+kCFURLIsAliasFile = 0x00008000
+kCFURLIsMountTrigger = 0x00010000
+
+# Volume property flags (from CFURLPriv.h)
+kCFURLVolumeIsLocal = 0x1
+kCFURLVolumeIsAutomount = 0x2
+kCFURLVolumeDontBrowse = 0x4
+kCFURLVolumeIsReadOnly = 0x8
+kCFURLVolumeIsQuarantined = 0x10
+kCFURLVolumeIsEjectable = 0x20
+kCFURLVolumeIsRemovable = 0x40
+kCFURLVolumeIsInternal = 0x80
+kCFURLVolumeIsExternal = 0x100
+kCFURLVolumeIsDiskImage = 0x200
+kCFURLVolumeIsFileVault = 0x400
+kCFURLVolumeIsLocaliDiskMirror = 0x800
+kCFURLVolumeIsiPod = 0x1000
+kCFURLVolumeIsiDisk = 0x2000
+kCFURLVolumeIsCD = 0x4000
+kCFURLVolumeIsDVD = 0x8000
+kCFURLVolumeIsDeviceFileSystem = 0x10000
+kCFURLVolumeSupportsPersistentIDs = 0x100000000
+kCFURLVolumeSupportsSearchFS = 0x200000000
+kCFURLVolumeSupportsExchange = 0x400000000
+# reserved 0x800000000
+kCFURLVolumeSupportsSymbolicLinks = 0x1000000000
+kCFURLVolumeSupportsDenyModes = 0x2000000000
+kCFURLVolumeSupportsCopyFile = 0x4000000000
+kCFURLVolumeSupportsReadDirAttr = 0x8000000000
+kCFURLVolumeSupportsJournaling = 0x10000000000
+kCFURLVolumeSupportsRename = 0x20000000000
+kCFURLVolumeSupportsFastStatFS = 0x40000000000
+kCFURLVolumeSupportsCaseSensitiveNames = 0x80000000000
+kCFURLVolumeSupportsCasePreservedNames = 0x100000000000
+kCFURLVolumeSupportsFLock = 0x200000000000
+kCFURLVolumeHasNoRootDirectoryTimes = 0x400000000000
+kCFURLVolumeSupportsExtendedSecurity = 0x800000000000
+kCFURLVolumeSupports2TBFileSize = 0x1000000000000
+kCFURLVolumeSupportsHardLinks = 0x2000000000000
+kCFURLVolumeSupportsMandatoryByteRangeLocks = 0x4000000000000
+kCFURLVolumeSupportsPathFromID = 0x8000000000000
+# reserved 0x10000000000000
+kCFURLVolumeIsJournaling = 0x20000000000000
+kCFURLVolumeSupportsSparseFiles = 0x40000000000000
+kCFURLVolumeSupportsZeroRuns = 0x80000000000000
+kCFURLVolumeSupportsVolumeSizes = 0x100000000000000
+kCFURLVolumeSupportsRemoteEvents = 0x200000000000000
+kCFURLVolumeSupportsHiddenFiles = 0x400000000000000
+kCFURLVolumeSupportsDecmpFSCompression = 0x800000000000000
+kCFURLVolumeHas64BitObjectIDs = 0x1000000000000000
+kCFURLVolumePropertyFlagsAll = 0xFFFFFFFFFFFFFFFF
+
+BMK_URL_ST_ABSOLUTE = 0x0001
+BMK_URL_ST_RELATIVE = 0x0002
+
+# Bookmark keys
+kBookmarkURL = 0x1003 # A URL
+kBookmarkPath = 0x1004 # Array of path components
+kBookmarkCNIDPath = 0x1005 # Array of CNIDs
+kBookmarkFileProperties = (
+ 0x1010 # (CFURL rp flags, CFURL rp flags asked for, 8 bytes NULL)
+)
+kBookmarkFileName = 0x1020
+kBookmarkFileID = 0x1030
+kBookmarkFileCreationDate = 0x1040
+# = 0x1054 # ?
+# = 0x1055 # ?
+# = 0x1056 # ?
+# = 0x1101 # ?
+# = 0x1102 # ?
+kBookmarkTOCPath = 0x2000 # A list of (TOC id, ?) pairs
+kBookmarkVolumePath = 0x2002
+kBookmarkVolumeURL = 0x2005
+kBookmarkVolumeName = 0x2010
+kBookmarkVolumeUUID = 0x2011 # Stored (perversely) as a string
+kBookmarkVolumeSize = 0x2012
+kBookmarkVolumeCreationDate = 0x2013
+kBookmarkVolumeProperties = (
+ 0x2020 # (CFURL vp flags, CFURL vp flags asked for, 8 bytes NULL)
+)
+kBookmarkVolumeIsRoot = 0x2030 # True if volume is FS root
+kBookmarkVolumeBookmark = 0x2040 # Embedded bookmark for disk image (TOC id)
+kBookmarkVolumeMountPoint = 0x2050 # A URL
+# = 0x2070
+kBookmarkContainingFolder = 0xC001 # Index of containing folder in path
+kBookmarkUserName = 0xC011 # User that created bookmark
+kBookmarkUID = 0xC012 # UID that created bookmark
+kBookmarkWasFileReference = 0xD001 # True if the URL was a file reference
+kBookmarkCreationOptions = 0xD010
+kBookmarkURLLengths = 0xE003 # See below
+kBookmarkDisplayName = 0xF017
+kBookmarkIconData = 0xF020
+kBookmarkIconRef = 0xF021
+kBookmarkTypeBindingData = 0xF022
+kBookmarkCreationTime = 0xF030
+kBookmarkSandboxRwExtension = 0xF080
+kBookmarkSandboxRoExtension = 0xF081
+kBookmarkAliasData = 0xFE00
+
+# Alias for backwards compatibility
+kBookmarkSecurityExtension = kBookmarkSandboxRwExtension
+
+# kBookmarkURLLengths is an array that is set if the URL encoded by the
+# bookmark had a base URL; in that case, each entry is the length of the
+# base URL in question. Thus a URL
+#
+# file:///foo/bar/baz blam/blat.html
+#
+# will result in [3, 2], while the URL
+#
+# file:///foo bar/baz blam blat.html
+#
+# would result in [1, 2, 1, 1]
+
+
+class Data:
+ def __init__(self, bytedata=None):
+ #: The bytes, stored as a byte string
+ self.bytes = bytes(bytedata)
+
+ def __repr__(self):
+ return "Data(%r)" % self.bytes
+
+
+class URL:
+ def __init__(self, base, rel=None):
+ if rel is not None:
+ #: The base URL, if any (a :class:`URL`)
+ self.base = base
+ #: The rest of the URL (a string)
+ self.relative = rel
+ else:
+ self.base = None
+ self.relative = base
+
+ @property
+ def absolute(self):
+ """Return an absolute URL."""
+ if self.base is None:
+ return self.relative
+ else:
+ return urljoin(self.base.absolute, self.relative)
+
+ def __repr__(self):
+ return "URL(%r)" % self.absolute
+
+
+class Bookmark:
+ def __init__(self, tocs=None):
+ if tocs is None:
+ #: The TOCs for this Bookmark
+ self.tocs = []
+ else:
+ self.tocs = tocs
+
+ @classmethod
+ def _get_item(cls, data, hdrsize, offset):
+ offset += hdrsize
+ if offset > len(data) - 8:
+ raise ValueError("Offset out of range")
+
+ length, typecode = struct.unpack(b"<II", data[offset : offset + 8])
+
+ if len(data) - offset < 8 + length:
+ raise ValueError("Data item truncated")
+
+ databytes = data[offset + 8 : offset + 8 + length]
+
+ dsubtype = typecode & BMK_DATA_SUBTYPE_MASK
+ dtype = typecode & BMK_DATA_TYPE_MASK
+
+ if dtype == BMK_STRING:
+ return databytes.decode("utf-8")
+ elif dtype == BMK_DATA:
+ return Data(databytes)
+ elif dtype == BMK_NUMBER:
+ if dsubtype == kCFNumberSInt8Type:
+ return ord(databytes[0])
+ elif dsubtype == kCFNumberSInt16Type:
+ return struct.unpack(b"<h", databytes)[0]
+ elif dsubtype == kCFNumberSInt32Type:
+ return struct.unpack(b"<i", databytes)[0]
+ elif dsubtype == kCFNumberSInt64Type:
+ return struct.unpack(b"<q", databytes)[0]
+ elif dsubtype == kCFNumberFloat32Type:
+ return struct.unpack(b"<f", databytes)[0]
+ elif dsubtype == kCFNumberFloat64Type:
+ return struct.unpack(b"<d", databytes)[0]
+ elif dtype == BMK_DATE:
+ # Yes, dates really are stored as *BIG-endian* doubles; everything
+ # else is little-endian
+ secs = datetime.timedelta(seconds=struct.unpack(b">d", databytes)[0])
+ return osx_epoch + secs
+ elif dtype == BMK_BOOLEAN:
+ if dsubtype == BMK_BOOLEAN_ST_TRUE:
+ return True
+ elif dsubtype == BMK_BOOLEAN_ST_FALSE:
+ return False
+ elif dtype == BMK_UUID:
+ return uuid.UUID(bytes=databytes)
+ elif dtype == BMK_URL:
+ if dsubtype == BMK_URL_ST_ABSOLUTE:
+ return URL(databytes.decode("utf-8"))
+ elif dsubtype == BMK_URL_ST_RELATIVE:
+ baseoff, reloff = struct.unpack(b"<II", databytes)
+ base = cls._get_item(data, hdrsize, baseoff)
+ rel = cls._get_item(data, hdrsize, reloff)
+ return URL(base, rel)
+ elif dtype == BMK_ARRAY:
+ result = []
+ for aoff in range(offset + 8, offset + 8 + length, 4):
+ (eltoff,) = struct.unpack(b"<I", data[aoff : aoff + 4])
+ result.append(cls._get_item(data, hdrsize, eltoff))
+ return result
+ elif dtype == BMK_DICT:
+ result = {}
+ for eoff in range(offset + 8, offset + 8 + length, 8):
+ keyoff, valoff = struct.unpack(b"<II", data[eoff : eoff + 8])
+ key = cls._get_item(data, hdrsize, keyoff)
+ val = cls._get_item(data, hdrsize, valoff)
+ result[key] = val
+ return result
+ elif dtype == BMK_NULL:
+ return None
+
+ print("Unknown data type %08x" % typecode)
+ return (typecode, databytes)
+
+ @classmethod
+ def from_bytes(cls, data):
+ """Create a :class:`Bookmark` given byte data."""
+
+ if len(data) < 16:
+ raise ValueError("Not a bookmark file (too short)")
+
+ if isinstance(data, bytearray):
+ data = bytes(data)
+
+ magic, size, dummy, hdrsize = struct.unpack(b"<4sIII", data[0:16])
+
+ if magic not in (b"book", b"alis"):
+ raise ValueError("Not a bookmark file (bad magic) %r" % magic)
+
+ if hdrsize < 16:
+ raise ValueError("Not a bookmark file (header size too short)")
+
+ if hdrsize > size:
+ raise ValueError("Not a bookmark file (header size too large)")
+
+ if size != len(data):
+ raise ValueError("Not a bookmark file (truncated)")
+
+ (tocoffset,) = struct.unpack(b"<I", data[hdrsize : hdrsize + 4])
+
+ tocs = []
+
+ while tocoffset != 0:
+ tocbase = hdrsize + tocoffset
+ if (tocoffset > size - hdrsize) or (size - tocbase < 20):
+ raise ValueError("TOC offset out of range")
+
+ (tocsize, tocmagic, tocid, nexttoc, toccount) = struct.unpack(
+ b"<IIIII", data[tocbase : tocbase + 20]
+ )
+
+ if tocmagic != 0xFFFFFFFE:
+ break
+
+ tocsize += 8
+
+ if size - tocbase < tocsize:
+ raise ValueError("TOC truncated")
+
+ if tocsize < 12 * toccount:
+ raise ValueError("TOC entries overrun TOC size")
+
+ toc = {}
+ for n in range(0, toccount):
+ ebase = tocbase + 20 + 12 * n
+ eid, eoffset, edummy = struct.unpack(b"<III", data[ebase : ebase + 12])
+
+ if eid & 0x80000000:
+ eid = cls._get_item(data, hdrsize, eid & 0x7FFFFFFF)
+
+ toc[eid] = cls._get_item(data, hdrsize, eoffset)
+
+ tocs.append((tocid, toc))
+
+ tocoffset = nexttoc
+
+ return cls(tocs)
+
+ def __getitem__(self, key):
+ for tid, toc in self.tocs:
+ if key in toc:
+ return toc[key]
+ raise KeyError("Key not found")
+
+ def __setitem__(self, key, value):
+ if len(self.tocs) == 0:
+ self.tocs = [(1, {})]
+ self.tocs[0][1][key] = value
+
+ def get(self, key, default=None):
+ """Lookup the value for a given key, returning a default if not
+ present."""
+ for tid, toc in self.tocs:
+ if key in toc:
+ return toc[key]
+ return default
+
+ @classmethod
+ def _encode_item(cls, item, offset):
+ if item is True:
+ result = struct.pack(b"<II", 0, BMK_BOOLEAN | BMK_BOOLEAN_ST_TRUE)
+ elif item is False:
+ result = struct.pack(b"<II", 0, BMK_BOOLEAN | BMK_BOOLEAN_ST_FALSE)
+ elif isinstance(item, str):
+ encoded = item.encode("utf-8")
+ result = (
+ struct.pack(b"<II", len(encoded), BMK_STRING | BMK_ST_ONE) + encoded
+ )
+ elif isinstance(item, bytes):
+ result = struct.pack(b"<II", len(item), BMK_STRING | BMK_ST_ONE) + item
+ elif isinstance(item, Data):
+ result = struct.pack(
+ b"<II", len(item.bytes), BMK_DATA | BMK_ST_ONE
+ ) + bytes(item.bytes)
+ elif isinstance(item, bytearray):
+ result = struct.pack(b"<II", len(item), BMK_DATA | BMK_ST_ONE) + bytes(item)
+ elif isinstance(item, int):
+ if item > -0x80000000 and item < 0x7FFFFFFF:
+ result = struct.pack(b"<IIi", 4, BMK_NUMBER | kCFNumberSInt32Type, item)
+ else:
+ result = struct.pack(b"<IIq", 8, BMK_NUMBER | kCFNumberSInt64Type, item)
+ elif isinstance(item, float):
+ result = struct.pack(b"<IId", 8, BMK_NUMBER | kCFNumberFloat64Type, item)
+ elif isinstance(item, datetime.datetime):
+ secs = item - osx_epoch
+ result = struct.pack(b"<II", 8, BMK_DATE | BMK_ST_ZERO) + struct.pack(
+ b">d", float(secs.total_seconds())
+ )
+
+ elif isinstance(item, uuid.UUID):
+ result = struct.pack(b"<II", 16, BMK_UUID | BMK_ST_ONE) + item.bytes
+ elif isinstance(item, URL):
+ if item.base:
+ baseoff = offset + 16
+ reloff, baseenc = cls._encode_item(item.base, baseoff)
+ xoffset, relenc = cls._encode_item(item.relative, reloff)
+ result = b"".join(
+ [
+ struct.pack(
+ b"<IIII", 8, BMK_URL | BMK_URL_ST_RELATIVE, baseoff, reloff
+ ),
+ baseenc,
+ relenc,
+ ]
+ )
+ else:
+ encoded = item.relative.encode("utf-8")
+ result = (
+ struct.pack(b"<II", len(encoded), BMK_URL | BMK_URL_ST_ABSOLUTE)
+ + encoded
+ )
+ elif isinstance(item, list):
+ ioffset = offset + 8 + len(item) * 4
+ result = [struct.pack(b"<II", len(item) * 4, BMK_ARRAY | BMK_ST_ONE)]
+ enc = []
+ for elt in item:
+ result.append(struct.pack(b"<I", ioffset))
+ ioffset, ienc = cls._encode_item(elt, ioffset)
+ enc.append(ienc)
+ result = b"".join(result + enc)
+ elif isinstance(item, dict):
+ ioffset = offset + 8 + len(item) * 8
+ result = [struct.pack(b"<II", len(item) * 8, BMK_DICT | BMK_ST_ONE)]
+ enc = []
+ for k, v in item.items():
+ result.append(struct.pack(b"<I", ioffset))
+ ioffset, ienc = cls._encode_item(k, ioffset)
+ enc.append(ienc)
+ result.append(struct.pack(b"<I", ioffset))
+ ioffset, ienc = cls._encode_item(v, ioffset)
+ enc.append(ienc)
+ result = b"".join(result + enc)
+ elif item is None:
+ result = struct.pack(b"<II", 0, BMK_NULL | BMK_ST_ONE)
+ else:
+ raise ValueError("Unknown item type when encoding: %s" % item)
+
+ offset += len(result)
+
+ # Pad to a multiple of 4 bytes
+ if offset & 3:
+ extra = 4 - (offset & 3)
+ result += b"\0" * extra
+ offset += extra
+
+ return (offset, result)
+
+ def to_bytes(self):
+ """Convert this :class:`Bookmark` to a byte representation."""
+
+ result = []
+ tocs = []
+ offset = 4 # For the offset to the first TOC
+
+ # Generate the data and build the TOCs
+ for tid, toc in self.tocs:
+ entries = []
+
+ for k, v in toc.items():
+ if isinstance(k, str):
+ noffset = offset
+ voffset, enc = self._encode_item(k, offset)
+ result.append(enc)
+ offset, enc = self._encode_item(v, voffset)
+ result.append(enc)
+ entries.append((noffset | 0x80000000, voffset))
+ else:
+ entries.append((k, offset))
+ offset, enc = self._encode_item(v, offset)
+ result.append(enc)
+
+ # TOC entries must be sorted - CoreServicesInternal does a
+ # binary search to find data
+ entries.sort()
+
+ tocs.append(
+ (tid, b"".join([struct.pack(b"<III", k, o, 0) for k, o in entries]))
+ )
+
+ first_toc_offset = offset
+
+ # Now generate the TOC headers
+ for ndx, toc in enumerate(tocs):
+ tid, data = toc
+ if ndx == len(tocs) - 1:
+ next_offset = 0
+ else:
+ next_offset = offset + 20 + len(data)
+
+ result.append(
+ struct.pack(
+ b"<IIIII",
+ len(data) - 8,
+ 0xFFFFFFFE,
+ tid,
+ next_offset,
+ len(data) // 12,
+ )
+ )
+ result.append(data)
+
+ offset += 20 + len(data)
+
+ # Finally, add the header (and the first TOC offset, which isn't part
+ # of the header, but goes just after it)
+ header = struct.pack(
+ b"<4sIIIQQQQI",
+ b"book",
+ offset + 48,
+ 0x10040000,
+ 48,
+ 0,
+ 0,
+ 0,
+ 0,
+ first_toc_offset,
+ )
+
+ result.insert(0, header)
+
+ return b"".join(result)
+
+ @classmethod
+ def for_file(cls, path):
+ """Construct a :class:`Bookmark` for a given file."""
+
+ # Find the filesystem
+ st = osx.statfs(path)
+ vol_path = st.f_mntonname.decode("utf-8")
+
+ # Grab its attributes
+ attrs = [
+ osx.ATTR_CMN_CRTIME,
+ osx.ATTR_VOL_SIZE | osx.ATTR_VOL_NAME | osx.ATTR_VOL_UUID,
+ 0,
+ 0,
+ 0,
+ ]
+ volinfo = osx.getattrlist(vol_path, attrs, 0)
+
+ vol_crtime = volinfo[0]
+ vol_size = volinfo[1]
+ vol_name = volinfo[2]
+ vol_uuid = volinfo[3]
+
+ # Also grab various attributes of the file
+ attrs = [
+ (osx.ATTR_CMN_OBJTYPE | osx.ATTR_CMN_CRTIME | osx.ATTR_CMN_FILEID),
+ 0,
+ 0,
+ 0,
+ 0,
+ ]
+ info = osx.getattrlist(path, attrs, osx.FSOPT_NOFOLLOW)
+
+ cnid = info[2]
+ crtime = info[1]
+
+ if info[0] == osx.VREG:
+ flags = kCFURLResourceIsRegularFile
+ elif info[0] == osx.VDIR:
+ flags = kCFURLResourceIsDirectory
+ elif info[0] == osx.VLNK:
+ flags = kCFURLResourceIsSymbolicLink
+ else:
+ flags = kCFURLResourceIsRegularFile
+
+ dirname, filename = os.path.split(path)
+
+ relcount = 0
+ if not os.path.isabs(dirname):
+ curdir = os.getcwd()
+ head, tail = os.path.split(curdir)
+ relcount = 0
+ while head and tail:
+ relcount += 1
+ head, tail = os.path.split(head)
+ dirname = os.path.join(curdir, dirname)
+
+ # ?? foldername = os.path.basename(dirname)
+
+ rel_path = os.path.relpath(path, vol_path)
+
+ # Build the path arrays
+ name_path = []
+ cnid_path = []
+ head, tail = os.path.split(rel_path)
+ if not tail:
+ head, tail = os.path.split(head)
+ while head or tail:
+ if head:
+ attrs = [osx.ATTR_CMN_FILEID, 0, 0, 0, 0]
+ info = osx.getattrlist(os.path.join(vol_path, head), attrs, 0)
+ cnid_path.insert(0, info[0])
+ head, tail = os.path.split(head)
+ name_path.insert(0, tail)
+ else:
+ head, tail = os.path.split(head)
+ name_path.append(filename)
+ cnid_path.append(cnid)
+
+ url_lengths = [relcount, len(name_path) - relcount]
+
+ fileprops = Data(struct.pack(b"<QQQ", flags, 0x0F, 0))
+ volprops = Data(
+ struct.pack(
+ b"<QQQ",
+ 0x81 | kCFURLVolumeSupportsPersistentIDs,
+ 0x13EF | kCFURLVolumeSupportsPersistentIDs,
+ 0,
+ )
+ )
+
+ toc = {
+ kBookmarkPath: name_path,
+ kBookmarkCNIDPath: cnid_path,
+ kBookmarkFileCreationDate: crtime,
+ kBookmarkFileProperties: fileprops,
+ kBookmarkContainingFolder: len(name_path) - 2,
+ kBookmarkVolumePath: vol_path,
+ kBookmarkVolumeIsRoot: vol_path == "/",
+ kBookmarkVolumeURL: URL("file://" + vol_path),
+ kBookmarkVolumeName: vol_name,
+ kBookmarkVolumeSize: vol_size,
+ kBookmarkVolumeCreationDate: vol_crtime,
+ kBookmarkVolumeUUID: str(vol_uuid).upper(),
+ kBookmarkVolumeProperties: volprops,
+ kBookmarkCreationOptions: 512,
+ kBookmarkWasFileReference: True,
+ kBookmarkUserName: "unknown",
+ kBookmarkUID: 99,
+ }
+
+ if relcount:
+ toc[kBookmarkURLLengths] = url_lengths
+
+ return Bookmark([(1, toc)])
+
+ def __repr__(self):
+ result = ["Bookmark(["]
+ for tid, toc in self.tocs:
+ result.append("(0x%x, {\n" % tid)
+ for k, v in toc.items():
+ if isinstance(k, str):
+ kf = repr(k)
+ else:
+ kf = "0x%04x" % k
+ result.append(f" {kf}: {v!r}\n")
+ result.append("}),\n")
+ result.append("])")
+
+ return "".join(result)
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/osx.py b/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/osx.py
index d4af65d75..1b2feabaa 100644
--- a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/osx.py
+++ b/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/osx.py
@@ -1,247 +1,367 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from ctypes import *
-import struct
-import os
import datetime
+import os
import uuid
-
-from .utils import *
-
-libc = cdll.LoadLibrary('/usr/lib/libc.dylib')
+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_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_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
-
-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_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_RETURNED_ATTRS = 0x80000000
-ATTR_CMN_ALL_ATTRS = 0x9fe7ffff
-
-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_ATTRIBUTES = 0x40000000
-ATTR_VOL_INFO = 0x80000000
-ATTR_VOL_ALL_ATTRS = 0xc007ffff
-
-ATTR_DIR_LINKCOUNT = 0x00000001
-ATTR_DIR_ENTRYCOUNT = 0x00000002
-ATTR_DIR_MOUNTSTATUS = 0x00000004
-DIR_MNTSTATUS_MNTPOINT = 0x00000001
-DIR_MNTSTATUS_TRIGGER = 0x00000002
-ATTR_DIR_ALL_ATTRS = 0x00000007
-
-ATTR_FILE_LINKCOUNT = 0x00000001
-ATTR_FILE_TOTALSIZE = 0x00000002
-ATTR_FILE_ALLOCSIZE = 0x00000004
-ATTR_FILE_IOBLOCKSIZE = 0x00000008
-ATTR_FILE_DEVTYPE = 0x00000020
-ATTR_FILE_DATALENGTH = 0x00000200
-ATTR_FILE_DATAALLOCSIZE = 0x00000400
-ATTR_FILE_RSRCLENGTH = 0x00001000
-ATTR_FILE_RSRCALLOCSIZE = 0x00002000
-
-ATTR_FILE_ALL_ATTRS = 0x0000362f
-
-ATTR_FORK_TOTALSIZE = 0x00000001
-ATTR_FORK_ALLOCSIZE = 0x00000002
-ATTR_FORK_ALL_ATTRS = 0x00000003
+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_FILE_FORKCOUNT = 0x00000080
-ATTR_FILE_FORKLIST = 0x00000100
-ATTR_CMN_NAMEDATTRCOUNT = 0x00080000
-ATTR_CMN_NAMEDATTRLIST = 0x00100000
-ATTR_FILE_DATAEXTENTS = 0x00000800
-ATTR_FILE_RSRCEXTENTS = 0x00004000
-ATTR_FILE_CLUMPSIZE = 0x00000010
-ATTR_FILE_FILETYPE = 0x00000040
+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)]
+ _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)]
+ _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)]
+ _fields_ = [
+ ("fid_objno", c_uint),
+ ("fid_generation", c_uint),
+ ]
+
class timespec(Structure):
- _fields_ = [('tv_sec', c_long),
- ('tv_nsec', c_long)]
+ _fields_ = [
+ ("tv_sec", c_long),
+ ("tv_nsec", c_long),
+ ]
+
class attrreference_t(Structure):
- _fields_ = [('attr_dataoffset', c_int),
- ('attr_length', c_uint)]
+ _fields_ = [
+ ("attr_dataoffset", c_int),
+ ("attr_length", c_uint),
+ ]
+
class fsid_t(Structure):
- _fields_ = [('val', c_uint * 2)]
+ _fields_ = [
+ ("val", c_uint * 2),
+ ]
+
class guid_t(Structure):
- _fields_ = [('g_guid', c_byte*16)]
+ _fields_ = [
+ ("g_guid", c_byte * 16),
+ ]
+
class kauth_ace(Structure):
- _fields_ = [('ace_applicable', guid_t),
- ('ace_flags', c_uint)]
+ _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)]
+ _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)]
+ _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)]
+ _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)]
+ _fields_ = [
+ ("x", SInt16),
+ ("y", SInt16),
+ ]
+
+
class Rect(Structure):
- _fields_ = [('x', SInt16),
- ('y', SInt16),
- ('w', SInt16),
- ('h', SInt16)]
+ _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)]
+ _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)]
+ _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)]
+ _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)]
+ _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)]
+ _fields_ = [
+ ("validattr", attribute_set_t),
+ ("nativeattr", attribute_set_t),
+ ]
+
dev_t = c_uint
@@ -298,28 +418,34 @@ int64_t = c_longlong
uint64_t = c_ulonglong
off_t = c_long
size_t = c_ulong
-uuid_t = c_byte*16
+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 * 16),
- ('f_mntonname', c_char * PATH_MAX),
- ('f_mntfromname', c_char * PATH_MAX),
- ('f_reserved', uint32_t * 8)]
+ _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 = (
@@ -330,6 +456,7 @@ _attr_info = (
(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)),
@@ -345,6 +472,8 @@ _attr_info = (
(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)),
@@ -353,7 +482,7 @@ _attr_info = (
(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)),
@@ -374,13 +503,16 @@ _attr_info = (
(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)),
@@ -397,22 +529,33 @@ _attr_info = (
(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))
- )
-
+ (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]))
+ 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
@@ -421,23 +564,40 @@ _fgetattrlist = libc.fgetattrlist
_fgetattrlist.argtypes = [c_int, POINTER(attrlist), c_void_p, c_ulong, c_ulong]
_fgetattrlist.restype = c_int
-_statfs = libc['statfs$INODE64']
-_statfs.argtypes = [c_char_p, POINTER(struct_statfs)]
+try:
+ _statfs = libc["statfs$INODE64"]
+except (KeyError, AttributeError):
+ _statfs = libc["statfs"]
+
+_statfs.argtypes = [
+ c_char_p,
+ POINTER(struct_statfs),
+]
_statfs.restype = c_int
-_fstatfs = libc['fstatfs$INODE64']
-_fstatfs.argtypes = [c_int, POINTER(struct_statfs)]
+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')
+ nul = sz.find(b"\0")
if nul > -1:
sz = sz[:nul]
- return sz.decode('utf-8')
+ return sz.decode("utf-8")
+
def _decode_attrlist_result(buf, attrs, options):
result = []
@@ -452,14 +612,14 @@ def _decode_attrlist_result(buf, attrs, options):
if attrs[0] & ATTR_CMN_RETURNED_ATTRS:
a = attribute_set_t.from_buffer(buf, offset)
result.append(a)
- offset += sizeof (attribute_set_t)
+ 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)
+ 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)
@@ -533,6 +693,14 @@ def _decode_attrlist_result(buf, attrs, options):
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)
@@ -542,22 +710,29 @@ def _decode_attrlist_result(buf, attrs, options):
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)]
+ _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)]
+ _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]))
+ 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]))
+ 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)
@@ -570,13 +745,17 @@ def _decode_attrlist_result(buf, attrs, options):
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)
+ 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:
@@ -630,14 +809,14 @@ def _decode_attrlist_result(buf, attrs, options):
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)
+ 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)
+ 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)
@@ -646,8 +825,8 @@ def _decode_attrlist_result(buf, attrs, options):
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)
+ 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)
@@ -658,8 +837,16 @@ def _decode_attrlist_result(buf, attrs, options):
offset += sizeof(vol_capabilities_attr_t)
result.append(a)
if attrs[1] & ATTR_VOL_UUID:
- result.append(uuid.UUID(bytes=buf[offset:offset+16]))
+ 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)
@@ -678,6 +865,18 @@ def _decode_attrlist_result(buf, attrs, options):
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:
@@ -746,34 +945,78 @@ def _decode_attrlist_result(buf, attrs, options):
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')
+ 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])
+ 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)
+ ret = _getattrlist(
+ path, byref(alist), buf, bufsize, options | FSOPT_REPORT_FULLSIZE
+ )
if ret < 0:
err = _get_errno()
@@ -781,24 +1024,26 @@ def getattrlist(path, attrs, options):
return _decode_attrlist_result(buf, attrs, options)
+
def fgetattrlist(fd, attrs, options):
- if hasattr(fd, 'fileno'):
+ 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])
+ 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)
+ ret = _fgetattrlist(fd, byref(alist), buf, bufsize, options | FSOPT_REPORT_FULLSIZE)
if ret < 0:
err = _get_errno()
@@ -806,9 +1051,10 @@ def fgetattrlist(fd, attrs, options):
return _decode_attrlist_result(buf, attrs, options)
+
def statfs(path):
if not isinstance(path, bytes):
- path = path.encode('utf-8')
+ path = path.encode("utf-8")
result = struct_statfs()
ret = _statfs(path, byref(result))
if ret < 0:
@@ -816,8 +1062,9 @@ def statfs(path):
raise OSError(err, os.strerror(err), path)
return result
+
def fstatfs(fd):
- if hasattr(fd, 'fileno'):
+ if hasattr(fd, "fileno"):
fd = fd.fileno()
result = struct_statfs()
ret = _fstatfs(fd, byref(result))
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/qt_attribution.json b/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/qt_attribution.json
index 968b6318c..968b6318c 100644
--- a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/qt_attribution.json
+++ b/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/qt_attribution.json
diff --git a/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/utils.py b/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/utils.py
new file mode 100644
index 000000000..3bf45155c
--- /dev/null
+++ b/src/3rdparty/python/lib/python3.9/site-packages/mac_alias/utils.py
@@ -0,0 +1,20 @@
+import datetime
+
+ZERO = datetime.timedelta(0)
+
+
+class UTC(datetime.tzinfo):
+ def utcoffset(self, dt):
+ return ZERO
+
+ def dst(self, dt):
+ return ZERO
+
+ def tzname(self, dt):
+ return "UTC"
+
+
+utc = UTC()
+mac_epoch = datetime.datetime(1904, 1, 1, 0, 0, 0, 0, utc)
+unix_epoch = datetime.datetime(1970, 1, 1, 0, 0, 0, 0, utc)
+osx_epoch = datetime.datetime(2001, 1, 1, 0, 0, 0, 0, utc)