Provide API in xpcom macutils for determining universal binary type.
b=572125 r=benwa
--- a/xpcom/base/nsIMacUtils.idl
+++ b/xpcom/base/nsIMacUtils.idl
@@ -36,22 +36,29 @@
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
/**
* nsIMacUtils: Generic globally-available Mac-specific utilities.
*/
-[scriptable, uuid(F6FC107C-5CBA-4C5C-A35E-B69D580D1DB6)]
+[scriptable, uuid(5E9072D7-FF95-455E-9466-8AF9841A72EC)]
interface nsIMacUtils : nsISupports
{
/**
* True when the main executable is a fat file supporting at least
* ppc and x86 (universal binary).
*/
readonly attribute boolean isUniversalBinary;
/**
+ * Returns a string containing a list of architectures delimited
+ * by "-". Architecture sets are always in the same order:
+ * ppc > i386 > ppc64 > x86_64 > (future additions)
+ */
+ readonly attribute AString architecturesInBinary;
+
+ /**
* True when running under binary translation (Rosetta).
*/
readonly attribute boolean isTranslated;
};
--- a/xpcom/base/nsMacUtilsImpl.cpp
+++ b/xpcom/base/nsMacUtilsImpl.cpp
@@ -33,103 +33,120 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsMacUtilsImpl.h"
#include <CoreFoundation/CoreFoundation.h>
-#include <fcntl.h>
-#include <unistd.h>
#include <sys/sysctl.h>
-#include <mach-o/fat.h>
NS_IMPL_ISUPPORTS1(nsMacUtilsImpl, nsIMacUtils)
-/* readonly attribute boolean isUniversalBinary; */
-// True when the main executable is a fat file supporting at least
-// ppc and x86 (universal binary).
-NS_IMETHODIMP nsMacUtilsImpl::GetIsUniversalBinary(PRBool *aIsUniversalBinary)
+nsresult nsMacUtilsImpl::GetArchString(nsAString& archString)
{
- static PRBool sInitialized = PR_FALSE,
- sIsUniversalBinary = PR_FALSE;
-
- if (sInitialized) {
- *aIsUniversalBinary = sIsUniversalBinary;
+ if (!mBinaryArchs.IsEmpty()) {
+ archString.Assign(mBinaryArchs);
return NS_OK;
}
- PRBool foundPPC = PR_FALSE,
- foundX86 = PR_FALSE;
- CFURLRef executableURL = nsnull;
- int fd = -1;
+ archString.Truncate();
- CFBundleRef mainBundle;
- if (!(mainBundle = ::CFBundleGetMainBundle()))
- goto done;
-
- if (!(executableURL = ::CFBundleCopyExecutableURL(mainBundle)))
- goto done;
+ PRBool foundPPC = PR_FALSE,
+ foundX86 = PR_FALSE,
+ foundPPC64 = PR_FALSE,
+ foundX86_64 = PR_FALSE;
- char executablePath[PATH_MAX];
- if (!::CFURLGetFileSystemRepresentation(executableURL, PR_TRUE,
- (UInt8*) executablePath,
- sizeof(executablePath)))
- goto done;
+ CFBundleRef mainBundle = ::CFBundleGetMainBundle();
+ if (!mainBundle) {
+ return NS_ERROR_FAILURE;
+ }
- if ((fd = open(executablePath, O_RDONLY)) == -1)
- goto done;
+ CFArrayRef archList = ::CFBundleCopyExecutableArchitectures(mainBundle);
+ if (!archList) {
+ return NS_ERROR_FAILURE;
+ }
- struct fat_header fatHeader;
- if (read(fd, &fatHeader, sizeof(fatHeader)) != sizeof(fatHeader))
- goto done;
+ CFIndex archCount = ::CFArrayGetCount(archList);
+ for (CFIndex i = 0; i < archCount; i++) {
+ CFNumberRef arch = static_cast<CFNumberRef>(::CFArrayGetValueAtIndex(archList, i));
- // The fat header is always stored on disk as big-endian.
- fatHeader.magic = CFSwapInt32BigToHost(fatHeader.magic);
- fatHeader.nfat_arch = CFSwapInt32BigToHost(fatHeader.nfat_arch);
-
- // Main executable is thin.
- if (fatHeader.magic != FAT_MAGIC)
- goto done;
+ int archInt = 0;
+ if (!::CFNumberGetValue(arch, kCFNumberIntType, &archInt)) {
+ ::CFRelease(archList);
+ return NS_ERROR_FAILURE;
+ }
- // Loop over each architecture in the file. We're presently only
- // interested in 32-bit PPC and x86.
- for (PRUint32 i = 0 ; i < fatHeader.nfat_arch ; i++) {
- struct fat_arch fatArch;
- if (read(fd, &fatArch, sizeof(fatArch)) != sizeof(fatArch))
- goto done;
+ if (archInt == kCFBundleExecutableArchitecturePPC)
+ foundPPC = PR_TRUE;
+ else if (archInt == kCFBundleExecutableArchitectureI386)
+ foundX86 = PR_TRUE;
+ else if (archInt == kCFBundleExecutableArchitecturePPC64)
+ foundPPC64 = PR_TRUE;
+ else if (archInt == kCFBundleExecutableArchitectureX86_64)
+ foundX86_64 = PR_TRUE;
+ }
- // This is still part of the fat header, so byte-swap as needed.
- fatArch.cputype = CFSwapInt32BigToHost(fatArch.cputype);
+ ::CFRelease(archList);
- // Don't mask out the ABI bits. This allows identification of ppc64
- // as distinct from ppc. CPU_TYPE_X86 is preferred to CPU_TYPE_I386
- // but does not exist prior to the 10.4 headers.
- if (fatArch.cputype == CPU_TYPE_POWERPC)
- foundPPC = PR_TRUE;
- else if (fatArch.cputype == CPU_TYPE_I386)
- foundX86 = PR_TRUE;
+ // The order in the string must always be the same so
+ // don't do this in the loop.
+ if (foundPPC) {
+ mBinaryArchs.Append(NS_LITERAL_STRING("ppc"));
}
- if (foundPPC && foundX86)
- sIsUniversalBinary = PR_TRUE;
+ if (foundX86) {
+ if (!mBinaryArchs.IsEmpty()) {
+ mBinaryArchs.Append(NS_LITERAL_STRING("-"));
+ }
+ mBinaryArchs.Append(NS_LITERAL_STRING("i386"));
+ }
+
+ if (foundPPC64) {
+ if (!mBinaryArchs.IsEmpty()) {
+ mBinaryArchs.Append(NS_LITERAL_STRING("-"));
+ }
+ mBinaryArchs.Append(NS_LITERAL_STRING("ppc64"));
+ }
-done:
- if (fd != -1)
- close(fd);
- if (executableURL)
- ::CFRelease(executableURL);
+ if (foundX86_64) {
+ if (!mBinaryArchs.IsEmpty()) {
+ mBinaryArchs.Append(NS_LITERAL_STRING("-"));
+ }
+ mBinaryArchs.Append(NS_LITERAL_STRING("x86_64"));
+ }
+
+ archString.Assign(mBinaryArchs);
+
+ return (archString.IsEmpty() ? NS_ERROR_FAILURE : NS_OK);
+}
- *aIsUniversalBinary = sIsUniversalBinary;
- sInitialized = PR_TRUE;
+NS_IMETHODIMP nsMacUtilsImpl::GetIsUniversalBinary(PRBool *aIsUniversalBinary)
+{
+ NS_ENSURE_ARG_POINTER(aIsUniversalBinary);
+ *aIsUniversalBinary = PR_FALSE;
+
+ nsAutoString archString;
+ nsresult rv = GetArchString(archString);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // The delimiter char in the arch string is '-', so if that character
+ // is in the string we know we have multiple architectures.
+ *aIsUniversalBinary = (archString.Find("-") > -1);
return NS_OK;
}
+NS_IMETHODIMP nsMacUtilsImpl::GetArchitecturesInBinary(nsAString& archString)
+{
+ return GetArchString(archString);
+}
+
/* readonly attribute boolean isTranslated; */
// True when running under binary translation (Rosetta).
NS_IMETHODIMP nsMacUtilsImpl::GetIsTranslated(PRBool *aIsTranslated)
{
#ifdef __ppc__
static PRBool sInitialized = PR_FALSE;
// Initialize sIsNative to 1. If the sysctl fails because it doesn't
--- a/xpcom/base/nsMacUtilsImpl.h
+++ b/xpcom/base/nsMacUtilsImpl.h
@@ -34,27 +34,34 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsMacUtilsImpl_h___
#define nsMacUtilsImpl_h___
#include "nsIMacUtils.h"
+#include "nsString.h"
class nsMacUtilsImpl : public nsIMacUtils
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMACUTILS
nsMacUtilsImpl() {}
private:
~nsMacUtilsImpl() {}
+
+ nsresult GetArchString(nsAString& archString);
+
+ // A string containing a "-" delimited list of architectures
+ // in our binary.
+ nsString mBinaryArchs;
};
// Global singleton service
// 697BD3FD-43E5-41CE-AD5E-C339175C0818
#define NS_MACUTILSIMPL_CLASSNAME "Mac OS X Utilities"
#define NS_MACUTILSIMPL_CID \
{0x697BD3FD, 0x43E5, 0x41CE, {0xAD, 0x5E, 0xC3, 0x39, 0x17, 0x5C, 0x08, 0x18}}
#define NS_MACUTILSIMPL_CONTRACTID "@mozilla.org/xpcom/mac-utils;1"