def _pkginfo(self, package_id): """Retrieves package information for a specific Package ID using the macOS 'pkgutil' binary.""" result = None cmd = ['/usr/sbin/pkgutil', '--pkg-info-plist', package_id] process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) p_result, p_error = process.communicate() if process.returncode is 0: _result = plist.readPlistFromString(p_result) LOG.debug(p_result) if _result: result = dict() for key, value in _result.items(): if key == 'install-time': value = datetime.fromtimestamp(value).strftime( '%Y-%m-%d %H:%M:%S') elif key == 'pkg-version': value = LooseVersion(value) result[key.replace('-', '_')] = value else: result = False else: LOG.debug(p_error) result = False LOG.debug('{}: {}'.format(' '.join(cmd), result)) return result
def _get_mountpath(self, output): """Gets the mount path of a sparseimage/dmg file from the output of the 'hdiutil' command.""" # Use the PLIST output to set 'config.DMG_VOLUME_MOUNTPATH' result = None # This method is used to read buffer input and dict input. if isinstance(output, dict): _result = output['system-entities'] for item in _result: result = item.get('mount-point', None) if result: break else: _result = plist.readPlistFromString(output)['system-entities'] for item in _result: _vk = item.get('volume-kind', None) if _vk and _vk == self._volume_kind[self.filesystem]: result = item.get('mount-point', None) break return result
def _get_disk_stats(self): """Gets the amount of free space and returns a byte value.""" result = None cmd = ['/usr/sbin/diskutil', 'info', '-plist', self._disk] process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) p_result, p_error = process.communicate() if process.returncode is 0: result = plist.readPlistFromString(p_result) else: print(p_error) LOG.info(p_error) sys.exit(process.returncode) return result
def _sparse_exists(self): """Gets information about any potential attached sparse images to avoid volume and image entangling.""" result = None cmd = [self._hdiutil, 'info', '-plist'] process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) p_result, p_error = process.communicate() if process.returncode == 0: _result = plist.readPlistFromString(p_result).get('images', None) if _result: for image in _result: _image_path = image.get('image-path', None) _image_type = image.get('image-type', None) _sys_entity = image.get('system-entities') if _image_path and _image_type: if _image_path == self.sparse_image: if _image_type == 'sparse disk image' and _sys_entity: _de = self._get_devicepath(output=image) _mp = self._get_mountpath(output=image) result = dict() result['mount-point'] = _mp result['dev-entry'] = _de break else: LOG.debug('{}: {} - {}'.format(' '.join(cmd), process.returncode, p_error)) print(p_error) sys.exit(process.returncode) # Log success/fail with short message. LOG.debug('{}: {}'.format(' '.join(cmd), process.returncode)) return result
def _get_devicepath(self, output): """Gets the '/dev/disk' device path from the output of the 'hdiutil' command.""" # Use the PLIST output to set 'config.DMG_VOLUME_MOUNTPATH' result = None # This method is used to read buffer input and dict input. if isinstance(output, dict): _result = output['system-entities'] else: _result = plist.readPlistFromString(output)['system-entities'] for item in _result: _ch = item.get('content-hint', None) # This is required for APFS because it seems to not properly eject # the volume, so an eject on the device is required. # if self.filesystem == 'APFS' and _ch == 'GUID_partition_scheme': if _ch == 'GUID_partition_scheme': # config.DMG_DISK_DEV = item.get('dev-entry', None) result = item.get('dev-entry', None) break return result