stuff
This commit is contained in:
27
buildfiles/node_modules/dmg-builder/vendor/mac_alias/__init__.py
generated
vendored
Normal file
27
buildfiles/node_modules/dmg-builder/vendor/mac_alias/__init__.py
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
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' ]
|
||||
|
||||
|
BIN
buildfiles/node_modules/dmg-builder/vendor/mac_alias/__init__.pyc
generated
vendored
Normal file
BIN
buildfiles/node_modules/dmg-builder/vendor/mac_alias/__init__.pyc
generated
vendored
Normal file
Binary file not shown.
612
buildfiles/node_modules/dmg-builder/vendor/mac_alias/alias.py
generated
vendored
Normal file
612
buildfiles/node_modules/dmg-builder/vendor/mac_alias/alias.py
generated
vendored
Normal file
@ -0,0 +1,612 @@
|
||||
# -*- 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 sys
|
||||
from unicodedata import normalize
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
from . import osx
|
||||
|
||||
try:
|
||||
long
|
||||
except NameError:
|
||||
long = int
|
||||
|
||||
from .utils import *
|
||||
|
||||
ALIAS_KIND_FILE = 0
|
||||
ALIAS_KIND_FOLDER = 1
|
||||
|
||||
ALIAS_HFS_VOLUME_SIGNATURE = b'H+'
|
||||
|
||||
ALIAS_FIXED_DISK = 0
|
||||
ALIAS_NETWORK_DISK = 1
|
||||
ALIAS_400KB_FLOPPY_DISK = 2
|
||||
ALIAS_800KB_FLOPPY_DISK = 3
|
||||
ALIAS_1_44MB_FLOPPY_DISK = 4
|
||||
ALIAS_EJECTABLE_DISK = 5
|
||||
|
||||
ALIAS_NO_CNID = 0xffffffff
|
||||
|
||||
def encode_utf8(s):
|
||||
if isinstance(s, bytes):
|
||||
return s
|
||||
return s.encode('utf-8')
|
||||
|
||||
def decode_utf8(s):
|
||||
if isinstance(s, bytes):
|
||||
return s.decode('utf-8')
|
||||
return s
|
||||
|
||||
class AppleShareInfo (object):
|
||||
def __init__(self, zone=None, server=None, user=None):
|
||||
#: The AppleShare zone
|
||||
self.zone = zone
|
||||
#: The AFP server
|
||||
self.server = server
|
||||
#: The username
|
||||
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):
|
||||
#: 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+)
|
||||
self.fs_type = fs_type
|
||||
|
||||
#: The type of disk; should be one of
|
||||
#:
|
||||
#: * ALIAS_FIXED_DISK
|
||||
#: * ALIAS_NETWORK_DISK
|
||||
#: * ALIAS_400KB_FLOPPY_DISK
|
||||
#: * ALIAS_800KB_FLOPPY_DISK
|
||||
#: * ALIAS_1_44MB_FLOPPY_DISK
|
||||
#: * ALIAS_EJECTABLE_DISK
|
||||
self.disk_type = disk_type
|
||||
|
||||
#: Filesystem attribute flags (from HFS volume header)
|
||||
self.attribute_flags = attribute_flags
|
||||
|
||||
#: Filesystem identifier
|
||||
self.fs_id = fs_id
|
||||
|
||||
#: AppleShare information (for automatic remounting of network shares)
|
||||
#: *(optional)*
|
||||
self.appleshare_info = appleshare_info
|
||||
|
||||
#: Driver name (*probably* contains a disk driver name on older Macs)
|
||||
#: *(optional)*
|
||||
self.driver_name = driver_name
|
||||
|
||||
#: POSIX path of the mount point of the target's volume
|
||||
#: *(optional)*
|
||||
self.posix_path = posix_path
|
||||
|
||||
#: :class:`Alias` object pointing at the disk image on which the
|
||||
#: target's volume resides *(optional)*
|
||||
self.disk_image_alias = disk_image_alias
|
||||
|
||||
#: Dialup information (for automatic establishment of dialup connections)
|
||||
self.dialup_info = dialup_info
|
||||
|
||||
#: Network mount information (for automatic remounting)
|
||||
self.network_mount_info = network_mount_info
|
||||
|
||||
def __repr__(self):
|
||||
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']
|
||||
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):
|
||||
#: Either ALIAS_KIND_FILE or ALIAS_KIND_FOLDER
|
||||
self.kind = kind
|
||||
|
||||
#: The filename of the target
|
||||
self.filename = filename
|
||||
|
||||
#: The CNID (Catalog Node ID) of the target's containing folder;
|
||||
#: CNIDs are similar to but different than traditional UNIX inode
|
||||
#: numbers
|
||||
self.folder_cnid = folder_cnid
|
||||
|
||||
#: The CNID (Catalog Node ID) of the target
|
||||
self.cnid = cnid
|
||||
|
||||
#: The target's *creation* date.
|
||||
self.creation_date = creation_date
|
||||
|
||||
#: The target's Mac creator code (a four-character binary string)
|
||||
self.creator_code = creator_code
|
||||
|
||||
#: The target's Mac type code (a four-character binary string)
|
||||
self.type_code = type_code
|
||||
|
||||
#: The depth of the alias? Always seems to be -1 on OS X.
|
||||
self.levels_from = levels_from
|
||||
|
||||
#: The depth of the target? Always seems to be -1 on OS X.
|
||||
self.levels_to = levels_to
|
||||
|
||||
#: The (POSIX) name of the target's containing folder. *(optional)*
|
||||
self.folder_name = folder_name
|
||||
|
||||
#: The path from the volume root as a sequence of CNIDs. *(optional)*
|
||||
self.cnid_path = cnid_path
|
||||
|
||||
#: The Carbon path of the target *(optional)*
|
||||
self.carbon_path = carbon_path
|
||||
|
||||
#: The POSIX path of the target relative to the volume root. Note
|
||||
#: that this may or may not have a leading '/' character, but it is
|
||||
#: always relative to the containing volume. *(optional)*
|
||||
self.posix_path = posix_path
|
||||
|
||||
#: If the path points into a user's home folder, the number of folders
|
||||
#: deep that we go before we get to that home folder. *(optional)*
|
||||
self.user_home_prefix_len = user_home_prefix_len
|
||||
|
||||
def __repr__(self):
|
||||
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)
|
||||
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']
|
||||
for a in kwargs:
|
||||
v = getattr(self, a)
|
||||
values.append('%s=%r' % (a, v))
|
||||
|
||||
return 'TargetInfo(%s)' % ','.join(values)
|
||||
|
||||
TAG_CARBON_FOLDER_NAME = 0
|
||||
TAG_CNID_PATH = 1
|
||||
TAG_CARBON_PATH = 2
|
||||
TAG_APPLESHARE_ZONE = 3
|
||||
TAG_APPLESHARE_SERVER_NAME = 4
|
||||
TAG_APPLESHARE_USERNAME = 5
|
||||
TAG_DRIVER_NAME = 6
|
||||
TAG_NETWORK_MOUNT_INFO = 9
|
||||
TAG_DIALUP_INFO = 10
|
||||
TAG_UNICODE_FILENAME = 14
|
||||
TAG_UNICODE_VOLUME_NAME = 15
|
||||
TAG_HIGH_RES_VOLUME_CREATION_DATE = 16
|
||||
TAG_HIGH_RES_CREATION_DATE = 17
|
||||
TAG_POSIX_PATH = 18
|
||||
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=[]):
|
||||
"""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)
|
||||
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
|
||||
|
||||
#: A list of extra `(tag, value)` pairs
|
||||
self.extra = list(extra)
|
||||
|
||||
@classmethod
|
||||
def _from_fd(cls, b):
|
||||
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))
|
||||
|
||||
voldate = mac_epoch + datetime.timedelta(seconds=voldate)
|
||||
crdate = mac_epoch + datetime.timedelta(seconds=crdate)
|
||||
|
||||
alias = Alias()
|
||||
alias.appinfo = appinfo
|
||||
|
||||
alias.volume = VolumeInfo (volname.replace('/',':'),
|
||||
voldate, fstype, disktype,
|
||||
volattrs, volfsid)
|
||||
alias.target = TargetInfo (kind, filename.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]
|
||||
|
||||
while tag != -1:
|
||||
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.replace('/',':')
|
||||
elif tag == TAG_CNID_PATH:
|
||||
alias.target.cnid_path = struct.unpack(b'>%uI' % (length // 4),
|
||||
value)
|
||||
elif tag == TAG_CARBON_PATH:
|
||||
alias.target.carbon_path = value
|
||||
elif tag == TAG_APPLESHARE_ZONE:
|
||||
if alias.volume.appleshare_info is None:
|
||||
alias.volume.appleshare_info = AppleShareInfo()
|
||||
alias.volume.appleshare_info.zone = value
|
||||
elif tag == TAG_APPLESHARE_SERVER_NAME:
|
||||
if alias.volume.appleshare_info is None:
|
||||
alias.volume.appleshare_info = AppleShareInfo()
|
||||
alias.volume.appleshare_info.server = value
|
||||
elif tag == TAG_APPLESHARE_USERNAME:
|
||||
if alias.volume.appleshare_info is None:
|
||||
alias.volume.appleshare_info = AppleShareInfo()
|
||||
alias.volume.appleshare_info.user = value
|
||||
elif tag == TAG_DRIVER_NAME:
|
||||
alias.volume.driver_name = value
|
||||
elif tag == TAG_NETWORK_MOUNT_INFO:
|
||||
alias.volume.network_mount_info = value
|
||||
elif tag == TAG_DIALUP_INFO:
|
||||
alias.volume.dialup_info = value
|
||||
elif tag == TAG_UNICODE_FILENAME:
|
||||
alias.target.filename = value[2:].decode('utf-16be')
|
||||
elif tag == TAG_UNICODE_VOLUME_NAME:
|
||||
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)
|
||||
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)
|
||||
elif tag == TAG_POSIX_PATH:
|
||||
alias.target.posix_path = value
|
||||
elif tag == TAG_POSIX_PATH_TO_MOUNTPOINT:
|
||||
alias.volume.posix_path = value
|
||||
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]
|
||||
else:
|
||||
alias.extra.append((tag, value))
|
||||
|
||||
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."""
|
||||
with io.BytesIO(bytes) as b:
|
||||
return cls._from_fd(b)
|
||||
|
||||
@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)')
|
||||
|
||||
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]
|
||||
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]
|
||||
info = osx.getattrlist(path, attrs, osx.FSOPT_NOFOLLOW)
|
||||
|
||||
if info[0] == osx.VDIR:
|
||||
kind = ALIAS_KIND_FOLDER
|
||||
else:
|
||||
kind = ALIAS_KIND_FILE
|
||||
|
||||
cnid = info[3]
|
||||
folder_cnid = info[4]
|
||||
|
||||
dirname, filename = os.path.split(path)
|
||||
|
||||
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)
|
||||
else:
|
||||
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.folder_name = foldername
|
||||
a.volume.posix_path = vol_path
|
||||
|
||||
rel_path = os.path.relpath(path, vol_path)
|
||||
|
||||
# Leave off the initial '/' if vol_path is '/' (no idea why)
|
||||
if vol_path == b'/':
|
||||
a.target.posix_path = rel_path
|
||||
else:
|
||||
a.target.posix_path = b'/' + rel_path
|
||||
|
||||
# Construct the Carbon and CNID paths
|
||||
carbon_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.append(info[0])
|
||||
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)
|
||||
|
||||
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))
|
||||
|
||||
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))
|
||||
|
||||
# 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)))
|
||||
b.write(carbon_foldername)
|
||||
if len(carbon_foldername) & 1:
|
||||
b.write(b'\0')
|
||||
|
||||
b.write(struct.pack(b'>hhQhhQ',
|
||||
TAG_HIGH_RES_VOLUME_CREATION_DATE,
|
||||
8, long(voldate * 65536),
|
||||
TAG_HIGH_RES_CREATION_DATE,
|
||||
8, long(crdate * 65536)))
|
||||
|
||||
if self.target.cnid_path:
|
||||
cnid_path = struct.pack(b'>%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)))
|
||||
b.write(carbon_path)
|
||||
if len(carbon_path) & 1:
|
||||
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(ai.zone)
|
||||
if len(ai.zone) & 1:
|
||||
b.write(b'\0')
|
||||
if 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')
|
||||
if 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')
|
||||
|
||||
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(driver_name)
|
||||
if len(driver_name) & 1:
|
||||
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(self.volume.network_mount_info)
|
||||
if len(self.volume.network_mount_info) & 1:
|
||||
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(self.volume.network_mount_info)
|
||||
if len(self.volume.network_mount_info) & 1:
|
||||
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))
|
||||
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))
|
||||
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(posix_path)
|
||||
if len(posix_path) & 1:
|
||||
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(posix_path)
|
||||
if len(posix_path) & 1:
|
||||
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(d)
|
||||
if len(d) & 1:
|
||||
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(v)
|
||||
if len(v) & 1:
|
||||
b.write(b'\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))
|
||||
|
||||
def to_bytes(self):
|
||||
"""Returns the binary representation for this :class:`Alias`."""
|
||||
with io.BytesIO() as b:
|
||||
self._to_fd(b)
|
||||
return b.getvalue()
|
||||
|
||||
def __str__(self):
|
||||
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.version != 2:
|
||||
values.append('version=%r' % self.version)
|
||||
if self.volume is not None:
|
||||
values.append('volume=%r' % self.volume)
|
||||
if self.target is not None:
|
||||
values.append('target=%r' % self.target)
|
||||
if self.extra:
|
||||
values.append('extra=%r' % self.extra)
|
||||
return 'Alias(%s)' % ','.join(values)
|
BIN
buildfiles/node_modules/dmg-builder/vendor/mac_alias/alias.pyc
generated
vendored
Normal file
BIN
buildfiles/node_modules/dmg-builder/vendor/mac_alias/alias.pyc
generated
vendored
Normal file
Binary file not shown.
665
buildfiles/node_modules/dmg-builder/vendor/mac_alias/bookmark.py
generated
vendored
Normal file
665
buildfiles/node_modules/dmg-builder/vendor/mac_alias/bookmark.py
generated
vendored
Normal file
@ -0,0 +1,665 @@
|
||||
# -*- 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)
|
BIN
buildfiles/node_modules/dmg-builder/vendor/mac_alias/bookmark.pyc
generated
vendored
Normal file
BIN
buildfiles/node_modules/dmg-builder/vendor/mac_alias/bookmark.pyc
generated
vendored
Normal file
Binary file not shown.
827
buildfiles/node_modules/dmg-builder/vendor/mac_alias/osx.py
generated
vendored
Normal file
827
buildfiles/node_modules/dmg-builder/vendor/mac_alias/osx.py
generated
vendored
Normal file
@ -0,0 +1,827 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from ctypes import *
|
||||
import struct
|
||||
import os
|
||||
import datetime
|
||||
import uuid
|
||||
|
||||
from .utils import *
|
||||
|
||||
libc = cdll.LoadLibrary('/usr/lib/libc.dylib')
|
||||
|
||||
# Constants
|
||||
FSOPT_NOFOLLOW = 0x00000001
|
||||
FSOPT_NOINMEMUPDATE = 0x00000002
|
||||
FSOPT_REPORT_FULLSIZE = 0x00000004
|
||||
FSOPT_PACK_INVAL_ATTRS = 0x00000008
|
||||
|
||||
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
|
||||
|
||||
# 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
|
||||
|
||||
class attrlist(Structure):
|
||||
_fields_ = [('bitmapcount', c_ushort),
|
||||
('reserved', c_ushort),
|
||||
('commonattr', c_uint),
|
||||
('volattr', c_uint),
|
||||
('dirattr', c_uint),
|
||||
('fileattr', c_uint),
|
||||
('forkattr', c_uint)]
|
||||
|
||||
class attribute_set_t(Structure):
|
||||
_fields_ = [('commonattr', c_uint),
|
||||
('volattr', c_uint),
|
||||
('dirattr', c_uint),
|
||||
('fileattr', c_uint),
|
||||
('forkattr', c_uint)]
|
||||
|
||||
class fsobj_id_t(Structure):
|
||||
_fields_ = [('fid_objno', c_uint),
|
||||
('fid_generation', c_uint)]
|
||||
|
||||
class timespec(Structure):
|
||||
_fields_ = [('tv_sec', c_long),
|
||||
('tv_nsec', c_long)]
|
||||
|
||||
class attrreference_t(Structure):
|
||||
_fields_ = [('attr_dataoffset', c_int),
|
||||
('attr_length', c_uint)]
|
||||
|
||||
class fsid_t(Structure):
|
||||
_fields_ = [('val', c_uint * 2)]
|
||||
|
||||
class guid_t(Structure):
|
||||
_fields_ = [('g_guid', c_byte*16)]
|
||||
|
||||
class kauth_ace(Structure):
|
||||
_fields_ = [('ace_applicable', guid_t),
|
||||
('ace_flags', c_uint)]
|
||||
|
||||
class kauth_acl(Structure):
|
||||
_fields_ = [('acl_entrycount', c_uint),
|
||||
('acl_flags', c_uint),
|
||||
('acl_ace', kauth_ace * 128)]
|
||||
|
||||
class kauth_filesec(Structure):
|
||||
_fields_ = [('fsec_magic', c_uint),
|
||||
('fsec_owner', guid_t),
|
||||
('fsec_group', guid_t),
|
||||
('fsec_acl', kauth_acl)]
|
||||
|
||||
class diskextent(Structure):
|
||||
_fields_ = [('startblock', c_uint),
|
||||
('blockcount', c_uint)]
|
||||
|
||||
OSType = c_uint
|
||||
UInt16 = c_ushort
|
||||
SInt16 = c_short
|
||||
SInt32 = c_int
|
||||
|
||||
class Point(Structure):
|
||||
_fields_ = [('x', SInt16),
|
||||
('y', SInt16)]
|
||||
class Rect(Structure):
|
||||
_fields_ = [('x', SInt16),
|
||||
('y', SInt16),
|
||||
('w', SInt16),
|
||||
('h', SInt16)]
|
||||
class FileInfo(Structure):
|
||||
_fields_ = [('fileType', OSType),
|
||||
('fileCreator', OSType),
|
||||
('finderFlags', UInt16),
|
||||
('location', Point),
|
||||
('reservedField', UInt16),
|
||||
('reserved1', SInt16 * 4),
|
||||
('extendedFinderFlags', UInt16),
|
||||
('reserved2', SInt16),
|
||||
('putAwayFolderID', SInt32)]
|
||||
class FolderInfo(Structure):
|
||||
_fields_ = [('windowBounds', Rect),
|
||||
('finderFlags', UInt16),
|
||||
('location', Point),
|
||||
('reservedField', UInt16),
|
||||
('scrollPosition', Point),
|
||||
('reserved1', SInt32),
|
||||
('extendedFinderFlags', UInt16),
|
||||
('reserved2', SInt16),
|
||||
('putAwayFolderID', SInt32)]
|
||||
class FinderInfo(Union):
|
||||
_fields_ = [('fileInfo', FileInfo),
|
||||
('folderInfo', FolderInfo)]
|
||||
|
||||
extentrecord = diskextent * 8
|
||||
|
||||
vol_capabilities_set_t = c_uint * 4
|
||||
|
||||
class vol_capabilities_attr_t(Structure):
|
||||
_fields_ = [('capabilities', vol_capabilities_set_t),
|
||||
('valid', vol_capabilities_set_t)]
|
||||
|
||||
class vol_attributes_attr_t(Structure):
|
||||
_fields_ = [('validattr', attribute_set_t),
|
||||
('nativeattr', attribute_set_t)]
|
||||
|
||||
dev_t = c_uint
|
||||
|
||||
fsobj_type_t = c_uint
|
||||
|
||||
VNON = 0
|
||||
VREG = 1
|
||||
VDIR = 2
|
||||
VBLK = 3
|
||||
VCHR = 4
|
||||
VLNK = 5
|
||||
VSOCK = 6
|
||||
VFIFO = 7
|
||||
VBAD = 8
|
||||
VSTR = 9
|
||||
VCPLX = 10
|
||||
|
||||
fsobj_tag_t = c_uint
|
||||
|
||||
VT_NON = 0
|
||||
VT_UFS = 1
|
||||
VT_NFS = 2
|
||||
VT_MFS = 3
|
||||
VT_MSDOSFS = 4
|
||||
VT_LFS = 5
|
||||
VT_LOFS = 6
|
||||
VT_FDESC = 7
|
||||
VT_PORTAL = 8
|
||||
VT_NULL = 9
|
||||
VT_UMAP = 10
|
||||
VT_KERNFS = 11
|
||||
VT_PROCFS = 12
|
||||
VT_AFS = 13
|
||||
VT_ISOFS = 14
|
||||
VT_UNION = 15
|
||||
VT_HFS = 16
|
||||
VT_ZFS = 17
|
||||
VT_DEVFS = 18
|
||||
VT_WEBDAV = 19
|
||||
VT_UDF = 20
|
||||
VT_AFP = 21
|
||||
VT_CDDA = 22
|
||||
VT_CIFS = 23
|
||||
VT_OTHER = 24
|
||||
|
||||
fsfile_type_t = c_uint
|
||||
fsvolid_t = c_uint
|
||||
text_encoding_t = c_uint
|
||||
uid_t = c_uint
|
||||
gid_t = c_uint
|
||||
int32_t = c_int
|
||||
uint32_t = c_uint
|
||||
int64_t = c_longlong
|
||||
uint64_t = c_ulonglong
|
||||
off_t = c_long
|
||||
size_t = c_ulong
|
||||
uuid_t = c_byte*16
|
||||
|
||||
NAME_MAX = 255
|
||||
PATH_MAX = 1024
|
||||
|
||||
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)]
|
||||
|
||||
# Calculate the maximum number of bytes required for the attribute buffer
|
||||
_attr_info = (
|
||||
# Common attributes
|
||||
(0, ATTR_CMN_RETURNED_ATTRS, sizeof(attribute_set_t)),
|
||||
(0, ATTR_CMN_NAME, sizeof(attrreference_t) + NAME_MAX * 3 + 1),
|
||||
(0, ATTR_CMN_DEVID, sizeof(dev_t)),
|
||||
(0, ATTR_CMN_FSID, sizeof(fsid_t)),
|
||||
(0, ATTR_CMN_OBJTYPE, sizeof(fsobj_type_t)),
|
||||
(0, ATTR_CMN_OBJTAG, sizeof(fsobj_tag_t)),
|
||||
(0, ATTR_CMN_OBJPERMANENTID, sizeof(fsobj_id_t)),
|
||||
(0, ATTR_CMN_PAROBJID, sizeof(fsobj_id_t)),
|
||||
(0, ATTR_CMN_SCRIPT, sizeof(text_encoding_t)),
|
||||
(0, ATTR_CMN_CRTIME, sizeof(timespec)),
|
||||
(0, ATTR_CMN_MODTIME, sizeof(timespec)),
|
||||
(0, ATTR_CMN_CHGTIME, sizeof(timespec)),
|
||||
(0, ATTR_CMN_ACCTIME, sizeof(timespec)),
|
||||
(0, ATTR_CMN_BKUPTIME, sizeof(timespec)),
|
||||
(0, ATTR_CMN_FNDRINFO, sizeof(FinderInfo)),
|
||||
(0, ATTR_CMN_OWNERID, sizeof(uid_t)),
|
||||
(0, ATTR_CMN_GRPID, sizeof(gid_t)),
|
||||
(0, ATTR_CMN_ACCESSMASK, sizeof(uint32_t)),
|
||||
(0, ATTR_CMN_NAMEDATTRCOUNT, None),
|
||||
(0, ATTR_CMN_NAMEDATTRLIST, None),
|
||||
(0, ATTR_CMN_FLAGS, sizeof(uint32_t)),
|
||||
(0, ATTR_CMN_USERACCESS, sizeof(uint32_t)),
|
||||
(0, ATTR_CMN_EXTENDED_SECURITY, sizeof(attrreference_t) + sizeof(kauth_filesec)),
|
||||
(0, ATTR_CMN_UUID, sizeof(guid_t)),
|
||||
(0, ATTR_CMN_GRPUUID, sizeof(guid_t)),
|
||||
(0, ATTR_CMN_FILEID, sizeof(uint64_t)),
|
||||
(0, ATTR_CMN_PARENTID, sizeof(uint64_t)),
|
||||
(0, ATTR_CMN_FULLPATH, sizeof(attrreference_t) + PATH_MAX),
|
||||
(0, ATTR_CMN_ADDEDTIME, sizeof(timespec)),
|
||||
|
||||
# Volume attributes
|
||||
(1, ATTR_VOL_FSTYPE, sizeof(uint32_t)),
|
||||
(1, ATTR_VOL_SIGNATURE, sizeof(uint32_t)),
|
||||
(1, ATTR_VOL_SIZE, sizeof(off_t)),
|
||||
(1, ATTR_VOL_SPACEFREE, sizeof(off_t)),
|
||||
(1, ATTR_VOL_SPACEAVAIL, sizeof(off_t)),
|
||||
(1, ATTR_VOL_MINALLOCATION, sizeof(off_t)),
|
||||
(1, ATTR_VOL_ALLOCATIONCLUMP, sizeof(off_t)),
|
||||
(1, ATTR_VOL_IOBLOCKSIZE, sizeof(uint32_t)),
|
||||
(1, ATTR_VOL_OBJCOUNT, sizeof(uint32_t)),
|
||||
(1, ATTR_VOL_FILECOUNT, sizeof(uint32_t)),
|
||||
(1, ATTR_VOL_DIRCOUNT, sizeof(uint32_t)),
|
||||
(1, ATTR_VOL_MAXOBJCOUNT, sizeof(uint32_t)),
|
||||
(1, ATTR_VOL_MOUNTPOINT, sizeof(attrreference_t) + PATH_MAX),
|
||||
(1, ATTR_VOL_NAME, sizeof(attrreference_t) + NAME_MAX + 1),
|
||||
(1, ATTR_VOL_MOUNTFLAGS, sizeof(uint32_t)),
|
||||
(1, ATTR_VOL_MOUNTEDDEVICE, sizeof(attrreference_t) + PATH_MAX),
|
||||
(1, ATTR_VOL_ENCODINGSUSED, sizeof(c_ulonglong)),
|
||||
(1, ATTR_VOL_CAPABILITIES, sizeof(vol_capabilities_attr_t)),
|
||||
(1, ATTR_VOL_UUID, sizeof(uuid_t)),
|
||||
(1, ATTR_VOL_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)),
|
||||
|
||||
# File attributes
|
||||
(3, ATTR_FILE_LINKCOUNT, sizeof(uint32_t)),
|
||||
(3, ATTR_FILE_TOTALSIZE, sizeof(off_t)),
|
||||
(3, ATTR_FILE_ALLOCSIZE, sizeof(off_t)),
|
||||
(3, ATTR_FILE_IOBLOCKSIZE, sizeof(uint32_t)),
|
||||
(3, ATTR_FILE_CLUMPSIZE, sizeof(uint32_t)),
|
||||
(3, ATTR_FILE_DEVTYPE, sizeof(uint32_t)),
|
||||
(3, ATTR_FILE_FILETYPE, sizeof(uint32_t)),
|
||||
(3, ATTR_FILE_FORKCOUNT, sizeof(uint32_t)),
|
||||
(3, ATTR_FILE_FORKLIST, None),
|
||||
(3, ATTR_FILE_DATALENGTH, sizeof(off_t)),
|
||||
(3, ATTR_FILE_DATAALLOCSIZE, sizeof(off_t)),
|
||||
(3, ATTR_FILE_DATAEXTENTS, sizeof(extentrecord)),
|
||||
(3, ATTR_FILE_RSRCLENGTH, sizeof(off_t)),
|
||||
(3, ATTR_FILE_RSRCALLOCSIZE, sizeof(off_t)),
|
||||
(3, ATTR_FILE_RSRCEXTENTS, sizeof(extentrecord)),
|
||||
|
||||
# Fork attributes
|
||||
(4, ATTR_FORK_TOTALSIZE, sizeof(off_t)),
|
||||
(4, ATTR_FORK_ALLOCSIZE, sizeof(off_t))
|
||||
)
|
||||
|
||||
def _attrbuf_size(attrs):
|
||||
size = 4
|
||||
for entry in _attr_info:
|
||||
if attrs[entry[0]] & entry[1]:
|
||||
if entry[2] is None:
|
||||
raise ValueError('Unsupported attribute (%u, %x)'
|
||||
% (entry[0], entry[1]))
|
||||
size += entry[2]
|
||||
return size
|
||||
|
||||
_getattrlist = libc.getattrlist
|
||||
_getattrlist.argtypes = [c_char_p, POINTER(attrlist), c_void_p, c_ulong, c_ulong]
|
||||
_getattrlist.restype = c_int
|
||||
|
||||
_fgetattrlist = libc.fgetattrlist
|
||||
_fgetattrlist.argtypes = [c_int, POINTER(attrlist), c_void_p, c_ulong, c_ulong]
|
||||
_fgetattrlist.restype = c_int
|
||||
|
||||
_statfs = libc['statfs$INODE64']
|
||||
_statfs.argtypes = [c_char_p, POINTER(struct_statfs)]
|
||||
_statfs.restype = c_int
|
||||
|
||||
_fstatfs = libc['fstatfs$INODE64']
|
||||
_fstatfs.argtypes = [c_int, POINTER(struct_statfs)]
|
||||
_fstatfs.restype = c_int
|
||||
|
||||
def _datetime_from_timespec(ts):
|
||||
td = datetime.timedelta(seconds=ts.tv_sec + 1.0e-9 * ts.tv_nsec)
|
||||
return unix_epoch + td
|
||||
|
||||
def _decode_utf8_nul(sz):
|
||||
nul = sz.find(b'\0')
|
||||
if nul > -1:
|
||||
sz = sz[:nul]
|
||||
return sz.decode('utf-8')
|
||||
|
||||
def _decode_attrlist_result(buf, attrs, options):
|
||||
result = []
|
||||
|
||||
assert len(buf) >= 4
|
||||
total_size = uint32_t.from_buffer(buf, 0).value
|
||||
assert total_size <= len(buf)
|
||||
|
||||
offset = 4
|
||||
|
||||
# Common attributes
|
||||
if attrs[0] & ATTR_CMN_RETURNED_ATTRS:
|
||||
a = attribute_set_t.from_buffer(buf, offset)
|
||||
result.append(a)
|
||||
offset += sizeof (attribute_set_t)
|
||||
if not (options & FSOPT_PACK_INVAL_ATTRS):
|
||||
attrs = [a.commonattr, a.volattr, a.dirattr, a.fileattr, a.forkattr]
|
||||
if attrs[0] & ATTR_CMN_NAME:
|
||||
a = attrreference_t.from_buffer(buf, offset)
|
||||
ofs = offset + a.attr_dataoffset
|
||||
name = _decode_utf8_nul(buf[ofs:ofs+a.attr_length])
|
||||
offset += sizeof (attrreference_t)
|
||||
result.append(name)
|
||||
if attrs[0] & ATTR_CMN_DEVID:
|
||||
a = dev_t.from_buffer(buf, offset)
|
||||
offset += sizeof(dev_t)
|
||||
result.append(a.value)
|
||||
if attrs[0] & ATTR_CMN_FSID:
|
||||
a = fsid_t.from_buffer(buf, offset)
|
||||
offset += sizeof(fsid_t)
|
||||
result.append(a)
|
||||
if attrs[0] & ATTR_CMN_OBJTYPE:
|
||||
a = fsobj_type_t.from_buffer(buf, offset)
|
||||
offset += sizeof(fsobj_type_t)
|
||||
result.append(a.value)
|
||||
if attrs[0] & ATTR_CMN_OBJTAG:
|
||||
a = fsobj_tag_t.from_buffer(buf, offset)
|
||||
offset += sizeof(fsobj_tag_t)
|
||||
result.append(a.value)
|
||||
if attrs[0] & ATTR_CMN_OBJID:
|
||||
a = fsobj_id_t.from_buffer(buf, offset)
|
||||
offset += sizeof(fsobj_id_t)
|
||||
result.append(a)
|
||||
if attrs[0] & ATTR_CMN_OBJPERMANENTID:
|
||||
a = fsobj_id_t.from_buffer(buf, offset)
|
||||
offset += sizeof(fsobj_id_t)
|
||||
result.append(a)
|
||||
if attrs[0] & ATTR_CMN_PAROBJID:
|
||||
a = fsobj_id_t.from_buffer(buf, offset)
|
||||
offset += sizeof(fsobj_id_t)
|
||||
result.append(a)
|
||||
if attrs[0] & ATTR_CMN_SCRIPT:
|
||||
a = text_encoding_t.from_buffer(buf, offset)
|
||||
offset += sizeof(text_encoding_t)
|
||||
result.append(a.value)
|
||||
if attrs[0] & ATTR_CMN_CRTIME:
|
||||
a = timespec.from_buffer(buf, offset)
|
||||
offset += sizeof(timespec)
|
||||
result.append(_datetime_from_timespec(a))
|
||||
if attrs[0] & ATTR_CMN_MODTIME:
|
||||
a = timespec.from_buffer(buf, offset)
|
||||
offset += sizeof(timespec)
|
||||
result.append(_datetime_from_timespec(a))
|
||||
if attrs[0] & ATTR_CMN_CHGTIME:
|
||||
a = timespec.from_buffer(buf, offset)
|
||||
offset += sizeof(timespec)
|
||||
result.append(_datetime_from_timespec(a))
|
||||
if attrs[0] & ATTR_CMN_ACCTIME:
|
||||
a = timespec.from_buffer(buf, offset)
|
||||
offset += sizeof(timespec)
|
||||
result.append(_datetime_from_timespec(a))
|
||||
if attrs[0] & ATTR_CMN_BKUPTIME:
|
||||
a = timespec.from_buffer(buf, offset)
|
||||
offset += sizeof(timespec)
|
||||
result.append(_datetime_from_timespec(a))
|
||||
if attrs[0] & ATTR_CMN_FNDRINFO:
|
||||
a = FinderInfo.from_buffer(buf, offset)
|
||||
offset += sizeof(FinderInfo)
|
||||
result.append(a)
|
||||
if attrs[0] & ATTR_CMN_OWNERID:
|
||||
a = uid_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uid_t)
|
||||
result.append(a.value)
|
||||
if attrs[0] & ATTR_CMN_GRPID:
|
||||
a = gid_t.from_buffer(buf, offset)
|
||||
offset += sizeof(gid_t)
|
||||
result.append(a.value)
|
||||
if attrs[0] & ATTR_CMN_ACCESSMASK:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[0] & ATTR_CMN_FLAGS:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[0] & ATTR_CMN_USERACCESS:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[0] & ATTR_CMN_EXTENDED_SECURITY:
|
||||
a = attrreference_t.from_buffer(buf, offset)
|
||||
ofs = offset + a.attr_dataoffset
|
||||
offset += sizeof(attrreference_t)
|
||||
ec = uint32_t.from_buffer(buf, ofs + 36).value
|
||||
class kauth_acl(Structure):
|
||||
_fields_ = [('acl_entrycount', c_uint),
|
||||
('acl_flags', c_uint),
|
||||
('acl_ace', kauth_ace * ec)]
|
||||
class kauth_filesec(Structure):
|
||||
_fields_ = [('fsec_magic', c_uint),
|
||||
('fsec_owner', guid_t),
|
||||
('fsec_group', guid_t),
|
||||
('fsec_acl', kauth_acl)]
|
||||
a = kauth_filesec.from_buffer(buf, ofs)
|
||||
result.append(a)
|
||||
if attrs[0] & ATTR_CMN_UUID:
|
||||
result.append(uuid.UUID(bytes=buf[offset:offset+16]))
|
||||
offset += sizeof(guid_t)
|
||||
if attrs[0] & ATTR_CMN_GRPUUID:
|
||||
result.append(uuid.UUID(bytes=buf[offset:offset+16]))
|
||||
offset += sizeof(guid_t)
|
||||
if attrs[0] & ATTR_CMN_FILEID:
|
||||
a = uint64_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint64_t)
|
||||
result.append(a.value)
|
||||
if attrs[0] & ATTR_CMN_PARENTID:
|
||||
a = uint64_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint64_t)
|
||||
result.append(a.value)
|
||||
if attrs[0] & ATTR_CMN_FULLPATH:
|
||||
a = attrreference_t.from_buffer(buf, offset)
|
||||
ofs = offset + a.attr_dataoffset
|
||||
path = _decode_utf8_nul(buf[ofs:ofs+a.attr_length])
|
||||
offset += sizeof (attrreference_t)
|
||||
result.append(path)
|
||||
if attrs[0] & ATTR_CMN_ADDEDTIME:
|
||||
a = timespec.from_buffer(buf, offset)
|
||||
offset += sizeof(timespec)
|
||||
result.append(_datetime_from_timespec(a))
|
||||
|
||||
# Volume attributes
|
||||
if attrs[1] & ATTR_VOL_FSTYPE:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[1] & ATTR_VOL_SIGNATURE:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[1] & ATTR_VOL_SIZE:
|
||||
a = off_t.from_buffer(buf, offset)
|
||||
offset += sizeof(off_t)
|
||||
result.append(a.value)
|
||||
if attrs[1] & ATTR_VOL_SPACEFREE:
|
||||
a = off_t.from_buffer(buf, offset)
|
||||
offset += sizeof(off_t)
|
||||
result.append(a.value)
|
||||
if attrs[1] & ATTR_VOL_SPACEAVAIL:
|
||||
a = off_t.from_buffer(buf, offset)
|
||||
offset += sizeof(off_t)
|
||||
result.append(a.value)
|
||||
if attrs[1] & ATTR_VOL_MINALLOCATION:
|
||||
a = off_t.from_buffer(buf, offset)
|
||||
offset += sizeof(off_t)
|
||||
result.append(a.value)
|
||||
if attrs[1] & ATTR_VOL_ALLOCATIONCLUMP:
|
||||
a = off_t.from_buffer(buf, offset)
|
||||
offset += sizeof(off_t)
|
||||
result.append(a.value)
|
||||
if attrs[1] & ATTR_VOL_IOBLOCKSIZE:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[1] & ATTR_VOL_OBJCOUNT:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[1] & ATTR_VOL_FILECOUNT:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[1] & ATTR_VOL_DIRCOUNT:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[1] & ATTR_VOL_MAXOBJCOUNT:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[1] & ATTR_VOL_MOUNTPOINT:
|
||||
a = attrreference_t.from_buffer(buf, offset)
|
||||
ofs = offset + a.attr_dataoffset
|
||||
path = _decode_utf8_nul(buf[ofs:ofs+a.attr_length])
|
||||
offset += sizeof (attrreference_t)
|
||||
result.append(path)
|
||||
if attrs[1] & ATTR_VOL_NAME:
|
||||
a = attrreference_t.from_buffer(buf, offset)
|
||||
ofs = offset + a.attr_dataoffset
|
||||
name = _decode_utf8_nul(buf[ofs:ofs+a.attr_length])
|
||||
offset += sizeof (attrreference_t)
|
||||
result.append(name)
|
||||
if attrs[1] & ATTR_VOL_MOUNTFLAGS:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[1] & ATTR_VOL_MOUNTEDDEVICE:
|
||||
a = attrreference_t.from_buffer(buf, offset)
|
||||
ofs = offset + a.attr_dataoffset
|
||||
path = _decode_utf8_nul(buf[ofs:ofs+a.attr_length])
|
||||
offset += sizeof (attrreference_t)
|
||||
result.append(path)
|
||||
if attrs[1] & ATTR_VOL_ENCODINGSUSED:
|
||||
a = c_ulonglong.from_buffer(buf, offset)
|
||||
offset += sizeof(c_ulonglong)
|
||||
result.append(a.value)
|
||||
if attrs[1] & ATTR_VOL_CAPABILITIES:
|
||||
a = vol_capabilities_attr_t.from_buffer(buf, offset)
|
||||
offset += sizeof(vol_capabilities_attr_t)
|
||||
result.append(a)
|
||||
if attrs[1] & ATTR_VOL_UUID:
|
||||
result.append(uuid.UUID(bytes=buf[offset:offset+16]))
|
||||
offset += sizeof(uuid_t)
|
||||
if attrs[1] & ATTR_VOL_ATTRIBUTES:
|
||||
a = vol_attributes_attr_t.from_buffer(buf, offset)
|
||||
offset += sizeof(vol_attributes_attr_t)
|
||||
result.append(a)
|
||||
|
||||
# Directory attributes
|
||||
if attrs[2] & ATTR_DIR_LINKCOUNT:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[2] & ATTR_DIR_ENTRYCOUNT:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[2] & ATTR_DIR_MOUNTSTATUS:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
|
||||
# File attributes
|
||||
if attrs[3] & ATTR_FILE_LINKCOUNT:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[3] & ATTR_FILE_TOTALSIZE:
|
||||
a = off_t.from_buffer(buf, offset)
|
||||
offset += sizeof(off_t)
|
||||
result.append(a.value)
|
||||
if attrs[3] & ATTR_FILE_ALLOCSIZE:
|
||||
a = off_t.from_buffer(buf, offset)
|
||||
offset += sizeof(off_t)
|
||||
result.append(a.value)
|
||||
if attrs[3] & ATTR_FILE_IOBLOCKSIZE:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[3] & ATTR_FILE_CLUMPSIZE:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[3] & ATTR_FILE_DEVTYPE:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[3] & ATTR_FILE_FILETYPE:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[3] & ATTR_FILE_FORKCOUNT:
|
||||
a = uint32_t.from_buffer(buf, offset)
|
||||
offset += sizeof(uint32_t)
|
||||
result.append(a.value)
|
||||
if attrs[3] & ATTR_FILE_DATALENGTH:
|
||||
a = off_t.from_buffer(buf, offset)
|
||||
offset += sizeof(off_t)
|
||||
result.append(a.value)
|
||||
if attrs[3] & ATTR_FILE_DATAALLOCSIZE:
|
||||
a = off_t.from_buffer(buf, offset)
|
||||
offset += sizeof(off_t)
|
||||
result.append(a.value)
|
||||
if attrs[3] & ATTR_FILE_DATAEXTENTS:
|
||||
a = extentrecord.from_buffer(buf, offset)
|
||||
offset += sizeof(extentrecord)
|
||||
result.append(a.value)
|
||||
if attrs[3] & ATTR_FILE_RSRCLENGTH:
|
||||
a = off_t.from_buffer(buf, offset)
|
||||
offset += sizeof(off_t)
|
||||
result.append(a.value)
|
||||
if attrs[3] & ATTR_FILE_RSRCALLOCSIZE:
|
||||
a = off_t.from_buffer(buf, offset)
|
||||
offset += sizeof(off_t)
|
||||
result.append(a.value)
|
||||
if attrs[3] & ATTR_FILE_RSRCEXTENTS:
|
||||
a = extentrecord.from_buffer(buf, offset)
|
||||
offset += sizeof(extentrecord)
|
||||
result.append(a.value)
|
||||
|
||||
# Fork attributes
|
||||
if attrs[4] & ATTR_FORK_TOTALSIZE:
|
||||
a = off_t.from_buffer(buf, offset)
|
||||
offset += sizeof(off_t)
|
||||
result.append(a.value)
|
||||
if attrs[4] & ATTR_FORK_ALLOCSIZE:
|
||||
a = off_t.from_buffer(buf, offset)
|
||||
offset += sizeof(off_t)
|
||||
result.append(a.value)
|
||||
|
||||
return result
|
||||
|
||||
# Sadly, ctypes.get_errno() seems not to work
|
||||
__error = libc.__error
|
||||
__error.restype = POINTER(c_int)
|
||||
|
||||
def _get_errno():
|
||||
return __error().contents.value
|
||||
|
||||
def getattrlist(path, attrs, options):
|
||||
if not isinstance(path, bytes):
|
||||
path = path.encode('utf-8')
|
||||
attrs = list(attrs)
|
||||
if attrs[1]:
|
||||
attrs[1] |= ATTR_VOL_INFO
|
||||
alist = attrlist(bitmapcount=5,
|
||||
commonattr=attrs[0],
|
||||
volattr=attrs[1],
|
||||
dirattr=attrs[2],
|
||||
fileattr=attrs[3],
|
||||
forkattr=attrs[4])
|
||||
|
||||
bufsize = _attrbuf_size(attrs)
|
||||
buf = create_string_buffer(bufsize)
|
||||
|
||||
ret = _getattrlist(path, byref(alist), buf, bufsize,
|
||||
options | FSOPT_REPORT_FULLSIZE)
|
||||
|
||||
if ret < 0:
|
||||
err = _get_errno()
|
||||
raise OSError(err, os.strerror(err), path)
|
||||
|
||||
return _decode_attrlist_result(buf, attrs, options)
|
||||
|
||||
def fgetattrlist(fd, attrs, options):
|
||||
if hasattr(fd, 'fileno'):
|
||||
fd = fd.fileno()
|
||||
attrs = list(attrs)
|
||||
if attrs[1]:
|
||||
attrs[1] |= ATTR_VOL_INFO
|
||||
alist = attrlist(bitmapcount=5,
|
||||
commonattr=attrs[0],
|
||||
volattr=attrs[1],
|
||||
dirattr=attrs[2],
|
||||
fileattr=attrs[3],
|
||||
forkattr=attrs[4])
|
||||
|
||||
bufsize = _attrbuf_size(attrs)
|
||||
buf = create_string_buffer(bufsize)
|
||||
|
||||
ret = _fgetattrlist(fd, byref(alist), buf, bufsize,
|
||||
options | FSOPT_REPORT_FULLSIZE)
|
||||
|
||||
if ret < 0:
|
||||
err = _get_errno()
|
||||
raise OSError(err, os.strerror(err))
|
||||
|
||||
return _decode_attrlist_result(buf, attrs, options)
|
||||
|
||||
def statfs(path):
|
||||
if not isinstance(path, bytes):
|
||||
path = path.encode('utf-8')
|
||||
result = struct_statfs()
|
||||
ret = _statfs(path, byref(result))
|
||||
if ret < 0:
|
||||
err = _get_errno()
|
||||
raise OSError(err, os.strerror(err), path)
|
||||
return result
|
||||
|
||||
def fstatfs(fd):
|
||||
if hasattr(fd, 'fileno'):
|
||||
fd = fd.fileno()
|
||||
result = struct_statfs()
|
||||
ret = _fstatfs(fd, byref(result))
|
||||
if ret < 0:
|
||||
err = _get_errno()
|
||||
raise OSError(err, os.strerror(err))
|
||||
return result
|
BIN
buildfiles/node_modules/dmg-builder/vendor/mac_alias/osx.pyc
generated
vendored
Normal file
BIN
buildfiles/node_modules/dmg-builder/vendor/mac_alias/osx.pyc
generated
vendored
Normal file
Binary file not shown.
18
buildfiles/node_modules/dmg-builder/vendor/mac_alias/utils.py
generated
vendored
Normal file
18
buildfiles/node_modules/dmg-builder/vendor/mac_alias/utils.py
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
# -*- 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)
|
BIN
buildfiles/node_modules/dmg-builder/vendor/mac_alias/utils.pyc
generated
vendored
Normal file
BIN
buildfiles/node_modules/dmg-builder/vendor/mac_alias/utils.pyc
generated
vendored
Normal file
Binary file not shown.
Reference in New Issue
Block a user