Пример #1
0
    def listApfsVolumes(cls):
        LogDebug("Listing APFS volumes")
        if cls.hostVersionTuple()[1] < 13:
            return {}
        p = subprocess.Popen(["/usr/sbin/diskutil", "apfs", "list", "-plist"],
                             bufsize=1,
                             stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
        out, err = p.communicate()
        if p.returncode != 0:
            LogError("diskutil apfs list failed with return code %d" %
                     p.returncode)
            return None
        outData = NSData.dataWithBytes_length_(out, len(out))
        plist, format, error = \
            NSPropertyListSerialization.propertyListWithData_options_format_error_(outData,
                                                                                   NSPropertyListImmutable,
                                                                                   None,
                                                                                   None)
        if "Containers" not in plist:
            LogError("diskutil apfs list does not have any Containers")
            return None

        volumes = {}
        for container in plist["Containers"]:
            for volume in container.get("Volumes", []):
                volumes[volume["DeviceIdentifier"]] = volume
        return volumes
Пример #2
0
    def taskFinalize(self):
        LogNotice(u"Finalize task running")

        self.delegate.buildSetProgressMessage_(
            u"Scanning disk image for restore")
        # The script is wrapped with progresswatcher.py which parses script
        # output and sends it back as notifications to IEDSocketListener.
        args = [
            NSBundle.mainBundle().pathForResource_ofType_(
                u"progresswatcher", u"py"),
            u"--socket",
            self.listenerPath,
            u"imagescan",
            self.outputPath(),
        ]
        LogInfo(u"Launching finalize with arguments:")
        for arg in args:
            LogInfo(u"    '%@'", arg)
        try:
            p = subprocess.Popen(args,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.STDOUT)
            out = p.communicate()[0].decode(u"utf-8")
            LogDebug(u"Finalize exited with status %d and output '%@'",
                     p.returncode, out)
            if p.returncode != 0:
                errMsg = u"Finalize task failed with status %d" % p.returncode
                LogError(u"%@: %@", errMsg, out)
                self.fail_details_(errMsg, out)
        except BaseException as e:
            LogError(u"Failed to launch finalize task: %@", unicode(e))
            self.fail_details_(u"Failed to launch finalize task", unicode(e))
Пример #3
0
 def getFlatPkgInfo_(cls, pkgPath):
     tempdir = tempfile.mkdtemp()
     try:
         # Extract to tempdir, excluding all except Distribution and
         # PackageInfo.
         subprocess.check_output([
             "/usr/bin/xar", "-x", "--exclude", "^[^DP]", "--exclude",
             "Payload", "-C", tempdir, "-f", pkgPath
         ])
         distPath = os.path.join(tempdir, "Distribution")
         pkgInfoPath = os.path.join(tempdir, "PackageInfo")
         if os.path.exists(distPath):
             return cls.getSizeFromDistribution_(distPath)
         elif os.path.exists(pkgInfoPath):
             return cls.getSizeFromPackageInfo_(pkgInfoPath)
         else:
             LogError("No Distribution or PackageInfo found in '%@'",
                      pkgPath)
             return None
     except subprocess.CalledProcessError as e:
         LogError("xar failed with return code %d", e.returncode)
         return None
     finally:
         try:
             shutil.rmtree(tempdir)
         except Exception as e:
             LogWarning("Unable to remove tempdir: %@", str(e))
Пример #4
0
    def listenInBackground_(self, ignored):
        try:
            sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF,
                            (IEDSL_MAX_MSG_SIZE + 16) * IEDSL_MAX_MSG_COUNT)
            sock.bind(self.socketPath)
        except socket.error as e:
            LogError("Error creating datagram socket at %@: %@",
                     self.socketPath, str(e))
            return

        LogDebug("Listening to socket in background thread")
        while True:
            msg = sock.recv(IEDSL_MAX_MSG_SIZE, socket.MSG_WAITALL)
            if not msg:
                continue
            msgData = NSData.dataWithBytes_length_(msg, len(msg))
            plist, format, error = NSPropertyListSerialization.propertyListWithData_options_format_error_(
                msgData, NSPropertyListImmutable, None, None)
            if not plist:
                LogError("Error decoding plist: %@", error)
                continue
            if self.delegate.respondsToSelector_("socketReceivedMessage:"):
                self.delegate.performSelectorOnMainThread_withObject_waitUntilDone_(
                    "socketReceivedMessage:", plist, False)
Пример #5
0
 def connectionDidFinishLoading_(self, connection):
     LogInfo(u"%@ finished downloading to %@", self.package.name(),
             self.cacheTmpPath_(self.package.sha1()))
     self.fileHandle.closeFile()
     self.delegate.downloadStopped_(self.package)
     if self.checksum.hexdigest() == self.package.sha1():
         try:
             os.rename(self.cacheTmpPath_(self.package.sha1()),
                       self.cachePath_(self.package.sha1()))
         except OSError as e:
             error = u"Failed when moving download to %s: %s" % (
                 self.cachePath_(self.package.sha1()), unicode(e))
             LogError(error)
             self.delegate.downloadFailed_withError_(self.package, error)
             return
         linkPath = self.updatePath_(self.package.sha1())
         try:
             os.symlink(self.package.sha1(), linkPath)
         except OSError as e:
             error = u"Failed when creating link from %s to %s: %s" % (
                 self.package.sha1(), linkPath, unicode(e))
             LogError(error)
             self.delegate.downloadFailed_withError_(self.package, error)
             return
         LogNotice(u"%@ added to cache with sha1 %@", self.package.name(),
                   self.package.sha1())
         self.delegate.downloadSucceeded_(self.package)
         self.downloadNextUpdate()
     else:
         error = u"Expected sha1 checksum %s but got %s" % (
             sha1.lower(), m.hexdigest().lower())
         LogError(error)
         self.delegate.downloadFailed_withError_(self.package, error)
Пример #6
0
 def getInstalledPkgSize_(cls, pkgPath):
     # For apps just return the size on disk.
     name, ext = os.path.splitext(pkgPath)
     if ext == u".app":
         return cls.getPackageSize_(pkgPath)
     # For packages try to get the size requirements with installer.
     pkgFileName = os.path.os.path.basename(pkgPath)
     tempdir = tempfile.mkdtemp()
     try:
         symlinkPath = os.path.join(tempdir, pkgFileName)
         os.symlink(pkgPath, symlinkPath)
         p = subprocess.Popen([u"/usr/sbin/installer",
                               u"-pkginfo",
                               u"-verbose",
                               u"-plist",
                               u"-pkg",
                               symlinkPath],
                              stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE)
         out, err = p.communicate()
     finally:
         try:
             shutil.rmtree(tempdir)
         except BaseException as e:
             LogWarning(u"Unable to remove tempdir: %@", unicode(e))
     # Try to handle some common scenarios when installer fails.
     if p.returncode == -11:
         LogWarning(u"Estimating package size since installer -pkginfo "
                    u"'%@' crashed", pkgPath)
         return cls.getPackageSize_(pkgPath) * 2
     elif p.returncode != 0:
         mountPoints = IEDMountInfo.getMountPoints()
         fsInfo = mountPoints[cls.findMountPoint_(pkgPath)]
         if not fsInfo[u"islocal"]:
             LogWarning(u"Estimating package size since installer -pkginfo "
                        u"failed and '%@' is on a remote (%@) filesystem",
                        pkgPath, fsInfo[u"fstypename"])
             return cls.getPackageSize_(pkgPath) * 2
         else:
             LogError(u"installer -pkginfo -pkg '%@' failed with exit code %d", pkgPath, p.returncode)
             return None
     outData = NSData.dataWithBytes_length_(out, len(out))
     plist, format, error = NSPropertyListSerialization.propertyListWithData_options_format_error_(outData,
                                                                                                   NSPropertyListImmutable,
                                                                                                   None,
                                                                                                   None)
     if not plist:
         LogError(u"Error decoding plist: %@", error)
         return None
     LogDebug(u"%@ requires %@", pkgPath, cls.formatBytes_(int(plist[u"Size"]) * 1024))
     return int(plist[u"Size"]) * 1024
Пример #7
0
 def getSizeFromPkgInfoPlist_(cls, infoPlistPath):
     try:
         infoDict = NSDictionary.dictionaryWithContentsOfFile_(infoPlistPath)
         return infoDict[u"IFPkgFlagInstalledSize"] * 1024
     except Exception as e:
         LogError(u"Failed parsing '%@': %@", infoPlistPath, unicode(e))
         return None
Пример #8
0
 def logFailure_(self, message):
     LogError("Version check failed: %@", message)
     if not self.checkSilently:
         alert = NSAlert.alloc().init()
         alert.setMessageText_("Version check failed")
         alert.setInformativeText_(message)
         alert.runModal()
Пример #9
0
    def getInstalledPkgSize_(cls, pkgPath):
        # For apps just return the size on disk.
        ext = os.path.splitext(pkgPath)[1].lower()
        if ext == ".app":
            return cls.getPackageSize_(pkgPath)
        elif ext in (".pkg", ".mpkg"):
            # For packages first try to get the size requirements with
            # installer.
            size = cls.getInstalledPkgSizeFromInstaller_(pkgPath)
            if size is None:
                # If this fails, manually extract the size requirements from
                # the package.
                return cls.calculateInstalledPkgSize_(pkgPath)
            else:
                return size
        elif os.path.basename(pkgPath) == "InstallInfo.plist":
            iedPath = os.path.join(os.path.dirname(pkgPath), "InstallESD.dmg")
            try:
                iedSize = os.stat(iedPath).st_size
                estimatedSize = int(iedSize * 2.72127696157)
                LogDebug(
                    "Estimating size requirements of InstallInfo.plist to %@",
                    cls.formatByteSize_(estimatedSize))
                return estimatedSize
            except OSError:
                pass

        LogError("Don't know how to calculate installed size for '%@'",
                 pkgPath)
        return None
Пример #10
0
 def getInstalledPkgSizeFromInstaller_(cls, pkgPath):
     pkgFileName = os.path.os.path.basename(pkgPath)
     tempdir = tempfile.mkdtemp()
     try:
         symlinkPath = os.path.join(tempdir, pkgFileName)
         os.symlink(pkgPath, symlinkPath)
         p = subprocess.Popen([
             "/usr/sbin/installer", "-pkginfo", "-verbose", "-plist",
             "-pkg", symlinkPath
         ],
                              stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE)
         out, err = p.communicate()
     finally:
         try:
             shutil.rmtree(tempdir)
         except BaseException as e:
             LogWarning("Unable to remove tempdir: %@", str(e))
     if p.returncode != 0:
         LogDebug(
             "/usr/sbin/installer failed to determine size requirements")
         return None
     outData = NSData.dataWithBytes_length_(out, len(out))
     plist, format, error = NSPropertyListSerialization.propertyListWithData_options_format_error_(
         outData, NSPropertyListImmutable, None, None)
     if not plist:
         LogError("Error decoding plist: %@", error)
         return None
     LogDebug("Installer says %@ requires %@", pkgPath,
              cls.formatByteSize_(int(plist["Size"]) * 1024))
     return int(plist["Size"]) * 1024
Пример #11
0
 def connection_didFailWithError_(self, connection, error):
     LogError(u"%@ failed: %@", self.package.name(), error)
     self.delegate.downloadStopped_(self.package)
     self.fileHandle.closeFile()
     self.delegate.downloadFailed_withError_(self.package,
                                             error.localizedDescription())
     self.delegate.downloadAllDone()
Пример #12
0
    def saveUsersProfiles_(self, plist):
        """Save UpdateProfiles.plist to application support."""

        LogInfo("Saving update profiles with PublicationDate %@",
                plist["PublicationDate"])
        if not plist.writeToFile_atomically_(self.userUpdateProfilesPath,
                                             False):
            LogError("Failed to write %@", self.userUpdateProfilesPath)
Пример #13
0
 def getSizeFromDistribution_(cls, distPath):
     kbytes = 0
     try:
         tree = ElementTree.parse(distPath)
         for pkgref in tree.iterfind("pkg-ref[@installKBytes]"):
             kbytes += int(pkgref.get("installKBytes"))
     except Exception as e:
         LogError("Failed parsing '%@': %@", distPath, str(e))
         return None
     return kbytes * 1024
Пример #14
0
 def getPackageSize_(cls, path):
     p = subprocess.Popen(["/usr/bin/du", "-sk", path],
                          stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE)
     out, err = p.communicate()
     if p.returncode != 0:
         LogError("du failed with exit code %d", p.returncode)
         return 0
     else:
         return int(out.split()[0]) * 1024
Пример #15
0
 def getSizeFromPackageInfo_(cls, pkgInfoPath):
     kbytes = 0
     try:
         tree = ElementTree.parse(pkgInfoPath)
         for payload in tree.iterfind("payload[@installKBytes]"):
             kbytes += int(payload.get("installKBytes"))
     except Exception as e:
         LogError("Failed parsing '%@': %@", pkgInfoPath, str(e))
         return None
     return kbytes * 1024
Пример #16
0
 def getBundlePkgInfo_(cls, pkgPath):
     distPath = os.path.join(pkgPath, u"Contents", u"distribution.dist")
     infoPlistPath = os.path.join(pkgPath, u"Contents", u"Info.plist")
     if os.path.exists(distPath):
         return cls.getSizeFromDistribution_(distPath)
     elif os.path.exists(infoPlistPath):
         return cls.getSizeFromPkgInfoPlist_(infoPlistPath)
     else:
         LogError(u"No distribution.dist or Info.plist found in '%@'", pkgPath)
         return None
Пример #17
0
    def init(self):
        self = super(IEDUpdateController, self).init()
        if self is None:
            LogError("Failed to initialize IEDUpdateController")
            return None

        self.cache = IEDUpdateCache.alloc().initWithDelegate_(self)
        if not self.cache:
            LogError("Failed to initialize IEDUpdateController")
            return None
        self.updates = list()
        self.downloadTotalSize = 0
        self.downloads = list()
        self.delegate = None
        self.version = None
        self.build = None
        self.profileWarning = None
        self.boxTableSizeDelta = 0

        return self
Пример #18
0
 def setAdditionalPackages_(self, packagePaths):
     self.additionalPackageError = None
     for packagePath in packagePaths:
         path = IEDUtil.resolvePath_(
             os.path.abspath(os.path.expanduser(packagePath)))
         if not os.path.exists(path):
             self.additionalPackageError = u"Package '%s' not found" % packagePath
             LogError(u"'%@'", self.additionalPackageError)
             return False
         name, ext = os.path.splitext(path)
         if ext.lower() not in IEDUtil.PACKAGE_EXTENSIONS:
             self.additionalPackageError = u"'%s' is not valid software package" % packagePath
             LogError(u"'%@'", self.additionalPackageError)
             return False
         if path not in self.additionalPackages:
             LogInfo(u"Adding '%@' to additional packages", path)
             self.additionalPackages.append(IEDUtil.resolvePath_(path))
         else:
             LogInfo(u"Skipping duplicate package '%@'", path)
     return True
Пример #19
0
 def setAdditionalPackages_(self, packagePaths):
     for packagePath in packagePaths:
         path = IEDUtil.resolvePath_(os.path.expanduser(packagePath))
         if not path:
             LogError(u"Package '%@' not found", packagePath)
             return False
         if path not in self.additionalPackages:
             LogInfo(u"Adding '%@' to additional packages", path)
             self.additionalPackages.append(IEDUtil.resolvePath_(path))
         else:
             LogInfo(u"Skipping duplicate package '%@'", path)
     return True
Пример #20
0
    def loadProfilesFromPlist_(self, plist):
        """Load UpdateProfiles from a plist dictionary."""

        LogInfo("Loading update profiles with PublicationDate %@",
                plist["PublicationDate"])

        try:
            # FIXME: Add profile verification.

            self.profiles = dict()
            for name, updates in plist["Profiles"].iteritems():
                profile = list()
                for update in updates:
                    profile.append(plist["Updates"][update])
                self.profiles[name] = profile

            self.publicationDate = plist["PublicationDate"]

            self.updatePaths = dict()
            for name, update in plist["Updates"].iteritems():
                filename, ext = os.path.splitext(
                    os.path.basename(update["url"]))
                self.updatePaths[update["sha1"]] = "%s(%s)%s" % (
                    filename, update["sha1"][:7], ext)

            self.deprecatedInstallerBuilds = dict()
            try:
                for replacement, builds in plist[
                        "DeprecatedInstallers"].iteritems():
                    for build in builds:
                        self.deprecatedInstallerBuilds[build] = replacement
            except KeyError:
                LogWarning("No deprecated installers in profile")

            self.deprecatedOS = False
            try:
                for osVerStr in plist["DeprecatedOSVersions"]:
                    deprecatedVerMajor = IEDUtil.splitVersion(osVerStr)[1]
                    if IEDUtil.hostMajorVersion() <= deprecatedVerMajor:
                        self.deprecatedOS = True
                        LogWarning("%@ is no longer being updated by Apple",
                                   osVerStr)
                        break
            except KeyError:
                LogWarning("No deprecated OS versions in profile")

            if self.delegate:
                self.delegate.profilesUpdated()
        except BaseException as e:
            LogError("Failed to load profile: %@", unicode(e))
Пример #21
0
 def connection_didReceiveData_(self, connection, data):
     try:
         self.fileHandle.writeData_(data)
     except BaseException as e:
         LogError(u"Write error: %@", unicode(e))
         connection.cancel()
         error = u"Writing to %s failed: %s" % (self.cacheTmpPath_(self.package.sha1()), unicode(e))
         self.fileHandle.closeFile()
         self.delegate.downloadFailed_withError_(self.package, error)
         self.delegate.downloadAllDone()
         return
     self.checksum.update(data)
     self.bytesReceived += data.length()
     self.delegate.downloadGotData_bytesRead_(self.package, self.bytesReceived)
Пример #22
0
    def init(self):
        self = super(IEDUpdateCache, self).init()
        if self is None:
            return None

        fm = NSFileManager.defaultManager()
        url, error = fm.URLForDirectory_inDomain_appropriateForURL_create_error_(
            NSApplicationSupportDirectory, NSUserDomainMask, None, True, None)
        if not url:
            if error:
                LogError("Unable to locate Application Support directory: %@",
                         error.localizedDescription())
            else:
                LogError("Unable to locate Application Support directory")
            return None
        self.updateDir = os.path.join(url.path(), "AutoDMG", "Updates")
        if not os.path.exists(self.updateDir):
            try:
                os.makedirs(self.updateDir)
            except OSError as e:
                LogError("Failed to create %@: %@", self.updateDir, str(e))

        return self
Пример #23
0
    def init(self):
        self = super(IEDUpdateCache, self).init()
        if self is None:
            return None

        fm = NSFileManager.defaultManager()
        url, error = fm.URLForDirectory_inDomain_appropriateForURL_create_error_(
            NSApplicationSupportDirectory, NSUserDomainMask, None, True, None)
        self.updateDir = os.path.join(url.path(), u"AutoDMG", u"Updates")
        if not os.path.exists(self.updateDir):
            try:
                os.makedirs(self.updateDir)
            except OSError as e:
                LogError(u"Failed to create %@: %@", self.updateDir,
                         unicode(e))

        return self
Пример #24
0
 def checkAppleBugWarning_(self, path):
     LogDebug("checkAppleBugWarning:%@", path)
     if (IEDUtil.hostMajorVersion() != 14):
         return True
     LogDebug("We're running on Mojave")
     if not path.endswith(".app"):
         return True
     LogDebug("The source is a .app")
     if IEDUtil.volumePathForPath_(path) != "/":
         return True
     LogError("The source is an installer app on a Mojave system volume")
     text = "A bug in the OS installer (radar 43296160) causes installs to fail " \
         "if the Mojave installer is on the system volume. Copy it to an external " \
         "volume or wrap it in a dmg before dropping it on AutoDMG."
     self.delegate.sourceFailed_text_("Install will fail due to Apple bug",
                                      text)
     return False
Пример #25
0
    def socketReceivedMessage_(self, msg):
        # The message is a dictionary with "action" as the only required key.
        action = msg["action"]

        if action == "update_progress":
            percent = msg["percent"]
            currentProgress = self.progress + self.currentPhase[
                "weight"] * percent / 100.0
            self.delegate.buildSetProgress_(currentProgress)

        elif action == "update_message":
            if self.lastUpdateMessage != msg["message"]:
                # Only log update messages when they change.
                LogInfo("%@", msg["message"])
            self.lastUpdateMessage = msg["message"]
            self.delegate.buildSetProgressMessage_(msg["message"])

        elif action == "select_phase":
            LogNotice("Script phase: %@", msg["phase"])
            self.nextPhase()

        elif action == "log_message":
            LogMessage(msg["log_level"], msg["message"])

        elif action == "notify_failure":
            self.fail_details_("Build failed", msg["message"])

        elif action == "notify_success":
            LogNotice("Build success: %@", msg["message"])

        elif action == "task_done":
            status = msg["termination_status"]
            if status == 0:
                self.nextTask()
            else:
                details = NSString.stringWithFormat_(
                    "Task exited with status %@", msg["termination_status"])
                LogError("%@", details)
                # Status codes 100-199 are from installesdtodmg.sh, and have
                # been preceeded by a "notify_failure" message.
                if (status < 100) or (status > 199):
                    self.fail_details_("Build failed", details)

        else:
            self.fail_details_("Unknown progress notification", "Message: %@",
                               msg)
Пример #26
0
 def getInstalledPkgSize_(cls, pkgPath):
     # For apps just return the size on disk.
     ext = os.path.splitext(pkgPath)[1].lower()
     if ext == ".app":
         return cls.getPackageSize_(pkgPath)
     elif ext in (".pkg", ".mpkg"):
         # For packages first try to get the size requirements with
         # installer.
         size = cls.getInstalledPkgSizeFromInstaller_(pkgPath)
         if size is None:
             # If this fails, manually extract the size requirements from
             # the package.
             return cls.calculateInstalledPkgSize_(pkgPath)
         else:
             return size
     else:
         LogError("Don't know how to calculate installed size for '%@'",
                  pkgPath)
         return None
Пример #27
0
    def init(self):
        self = super(IEDCLIController, self).init()
        if self is None:
            return None

        self.cache = IEDUpdateCache.alloc().initWithDelegate_(self)
        if not self.cache:
            LogError("Failed to initialize IEDUpdateController")
            return None
        self.workflow = IEDWorkflow.alloc().initWithDelegate_(self)
        self.profileController = IEDProfileController.alloc().init()
        self.profileController.awakeFromNib()
        self.profileController.setDelegate_(self)
        self.cache.pruneAndCreateSymlinks(self.profileController.updatePaths)

        self.busy = False

        self.progressMax = 1.0
        self.lastMessage = ""

        self.hasFailed = False

        return self
Пример #28
0
def cli_main(argv):
    IEDLog.IEDLogToController = False
    IEDLog.IEDLogToSyslog = True
    IEDLog.IEDLogToStdOut = True
    IEDLog.IEDLogToFile = False

    from IEDCLIController import IEDCLIController
    clicontroller = IEDCLIController.alloc().init()

    try:
        # Initialize user defaults before application starts.
        defaults = NSUserDefaults.standardUserDefaults()
        defaultsPath = NSBundle.mainBundle().pathForResource_ofType_(
            u"Defaults", u"plist")
        defaultsDict = NSDictionary.dictionaryWithContentsOfFile_(defaultsPath)
        defaults.registerDefaults_(defaultsDict)

        p = argparse.ArgumentParser()
        p.add_argument(u"-v",
                       u"--verbose",
                       action=u"store_true",
                       help=u"Verbose output")
        p.add_argument(u"-L",
                       u"--log-level",
                       type=int,
                       choices=range(0, 8),
                       default=6,
                       metavar=u"LEVEL",
                       help=u"Log level (0-7), default 6")
        p.add_argument(u"-l", u"--logfile", help=u"Log to file")
        p.add_argument(u"-r",
                       u"--root",
                       action=u"store_true",
                       help=u"Allow running as root")
        sp = p.add_subparsers(title=u"subcommands", dest=u"subcommand")

        # Populate subparser for each verb.
        for verb in clicontroller.listVerbs():
            verb_method = getattr(clicontroller, u"cmd%s_" % verb.capitalize())
            addargs_method = getattr(clicontroller,
                                     u"addargs%s_" % verb.capitalize())
            parser = sp.add_parser(verb, help=verb_method.__doc__)
            addargs_method(parser)
            parser.set_defaults(func=verb_method)

        args = p.parse_args(argv)

        if args.verbose:
            IEDLog.IEDLogStdOutLogLevel = IEDLog.IEDLogLevelInfo
        else:
            IEDLog.IEDLogStdOutLogLevel = IEDLog.IEDLogLevelNotice

        IEDLog.IEDLogFileLogLevel = args.log_level

        if args.logfile == u"-":
            # Redirect log to stdout instead.
            IEDLog.IEDLogFileHandle = sys.stdout
            IEDLog.IEDLogToFile = True
            IEDLog.IEDLogToStdOut = False
        else:
            try:
                if args.logfile:
                    logFile = args.logfile
                else:
                    logFile = os.path.join(
                        get_log_dir(), u"AutoDMG-%s.log" % get_date_string())
                IEDLog.IEDLogFileHandle = open(logFile, u"a", buffering=1)
            except OSError as e:
                print >> sys.stderr, (u"Couldn't open %s for writing" %
                                      logFile).encode(u"utf-8")
                return os.EX_CANTCREAT
            IEDLog.IEDLogToFile = True

        # Check if we're running with root.
        if os.getuid() == 0:
            if args.root:
                fm = NSFileManager.defaultManager()
                url, error = fm.URLForDirectory_inDomain_appropriateForURL_create_error_(
                    NSApplicationSupportDirectory, NSUserDomainMask, None,
                    False, None)
                LogWarning(u"Running as root, using %@",
                           os.path.join(url.path(), u"AutoDMG"))
            else:
                LogError(
                    u"Running as root isn't recommended (use -r to override)")
                return os.EX_USAGE

        # Log version info on startup.
        version, build = IEDUtil.getAppVersion()
        LogInfo(u"AutoDMG v%@ build %@", version, build)
        name, version, build = IEDUtil.readSystemVersion_(u"/")
        LogInfo(u"%@ %@ %@", name, version, build)
        LogInfo(u"%@ %@ (%@)", platform.python_implementation(),
                platform.python_version(), platform.python_compiler())
        LogInfo(u"PyObjC %@", objc.__version__)

        return args.func(args)
    finally:
        clicontroller.cleanup()
Пример #29
0
 def failWithMessage_(self, message):
     LogError("%@", message)
     self.hasFailed = True
     self.busy = False
Пример #30
0
 def detachFailed_details_(self, dmgPath, details):
     LogError("Failed to detach '%@': %@", dmgPath, details)