Handle bad plists by ignoring them, with py2 and py3 specific approaches

This commit is contained in:
Shea Craig 2018-11-05 14:29:45 -05:00 committed by rallytime
parent fa4414949b
commit 0e23b6e7f1
No known key found for this signature in database
GPG Key ID: E8F1A4B90D0DEA19

View File

@ -11,6 +11,7 @@ import subprocess
import os
import plistlib
import time
import xml.parsers.expat
# Import Salt Libs
import salt.modules.cmdmod
@ -306,6 +307,12 @@ def launchctl(sub_cmd, *args, **kwargs):
def _available_services(refresh=False):
'''
This is a helper function for getting the available macOS services.
The strategy is to look through the known system locations for
launchd plist files, parse them, and use their information for
populating the list of services. Services can run without a plist
file present, but normally services which have an automated startup
will have a plist file, so this is a minor compromise.
'''
try:
if __context__['available_services'] and not refresh:
@ -339,39 +346,47 @@ def _available_services(refresh=False):
continue
try:
# This assumes most of the plist files
# will be already in XML format
plist = plistlib.readPlist(true_path)
if six.PY2:
# py2 plistlib can't read binary plists, and
# uses a different API than py3.
plist = plistlib.readPlist(true_path)
else:
with salt.utils.files.fopen(true_path, 'rb') as handle:
plist = plistlib.load(handle)
except Exception:
# If plistlib is unable to read the file we'll need to use
# the system provided plutil program to attempt conversion
# from binary.
except plistlib.InvalidFileException:
# Raised in python3 if the file is not XML.
# There's nothing we can do; move on to the next one.
msg = 'Unable to parse "%s" as it is invalid XML: InvalidFileException.'
logging.warning(msg, true_path)
continue
except xml.parsers.expat.ExpatError:
# Raised by py2 for all errors.
# Raised by py3 if the file is XML, but with errors.
if six.PY3:
# There's an error in the XML, so move on.
msg = 'Unable to parse "%s" as it is invalid XML: xml.parsers.expat.ExpatError.'
logging.warning(msg, true_path)
continue
# Use the system provided plutil program to attempt
# conversion from binary.
cmd = '/usr/bin/plutil -convert xml1 -o - -- "{0}"'.format(
true_path)
try:
plist_xml = __salt__['cmd.run'](cmd)
if six.PY2:
plist = plistlib.readPlistFromString(plist_xml)
else:
plist = plistlib.loads(
salt.utils.stringutils.to_bytes(plist_xml))
except Exception:
# If the file is actually just invalid XML, move on to
# the next one.
plist = plistlib.readPlistFromString(plist_xml)
except xml.parsers.expat.ExpatError:
# There's still an error in the XML, so move on.
msg = 'Unable to parse "%s" as it is invalid XML: xml.parsers.expat.ExpatError.'
logging.warning(msg, true_path)
continue
try:
_available_services[plist.Label.lower()] = {
'file_name': file_name,
'file_path': true_path,
'plist': plist}
except AttributeError:
# Handle malformed plist files
_available_services[os.path.basename(file_name).lower()] = {
'file_name': file_name,
'file_path': true_path,
'plist': plist}
_available_services[plist['Label'].lower()] = {
'file_name': file_name,
'file_path': true_path,
'plist': plist}
# put this in __context__ as this is a time consuming function.
# a fix for this issue. https://github.com/saltstack/salt/issues/48414