Back to index

lightning-sunbird  0.9+nobinonly
nsMacUtilsImpl.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is XPCOM utility functions for Mac OS X
00016  *
00017  * The Initial Developer of the Original Code is Google Inc.
00018  * Portions created by the Initial Developer are Copyright (C) 2006
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *  Mark Mentovai <mark@moxienet.com> (Original Author)
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nsMacUtilsImpl.h"
00039 
00040 #include <CoreFoundation/CoreFoundation.h>
00041 #include <fcntl.h>
00042 #include <unistd.h>
00043 #include <sys/sysctl.h>
00044 #include <mach-o/fat.h>
00045 
00046 NS_IMPL_ISUPPORTS1(nsMacUtilsImpl, nsIMacUtils)
00047 
00048 /* readonly attribute boolean isUniversalBinary; */
00049 // True when the main executable is a fat file supporting at least
00050 // ppc and x86 (universal binary).
00051 NS_IMETHODIMP nsMacUtilsImpl::GetIsUniversalBinary(PRBool *aIsUniversalBinary)
00052 {
00053   static PRBool sInitialized = PR_FALSE,
00054                 sIsUniversalBinary = PR_FALSE;
00055 
00056   if (sInitialized) {
00057     *aIsUniversalBinary = sIsUniversalBinary;
00058     return NS_OK;
00059   }
00060 
00061   PRBool foundPPC = PR_FALSE,
00062          foundX86 = PR_FALSE;
00063   CFURLRef executableURL = nsnull;
00064   int fd = -1;
00065 
00066   CFBundleRef mainBundle;
00067   if (!(mainBundle = ::CFBundleGetMainBundle()))
00068     goto done;
00069 
00070   if (!(executableURL = ::CFBundleCopyExecutableURL(mainBundle)))
00071     goto done;
00072 
00073   char executablePath[PATH_MAX];
00074   if (!::CFURLGetFileSystemRepresentation(executableURL, PR_TRUE,
00075                                           (UInt8*) executablePath,
00076                                           sizeof(executablePath)))
00077     goto done;
00078 
00079   if ((fd = open(executablePath, O_RDONLY)) == -1)
00080     goto done;
00081 
00082   struct fat_header fatHeader;
00083   if (read(fd, &fatHeader, sizeof(fatHeader)) != sizeof(fatHeader))
00084     goto done;
00085 
00086   // The fat header is always stored on disk as big-endian.
00087   fatHeader.magic = CFSwapInt32BigToHost(fatHeader.magic);
00088   fatHeader.nfat_arch = CFSwapInt32BigToHost(fatHeader.nfat_arch);
00089 
00090   // Main executable is thin.
00091   if (fatHeader.magic != FAT_MAGIC)
00092     goto done;
00093 
00094   // Loop over each architecture in the file.  We're presently only
00095   // interested in 32-bit PPC and x86.
00096   for (PRUint32 i = 0 ; i < fatHeader.nfat_arch ; i++) {
00097     struct fat_arch fatArch;
00098     if (read(fd, &fatArch, sizeof(fatArch)) != sizeof(fatArch))
00099       goto done;
00100 
00101     // This is still part of the fat header, so byte-swap as needed.
00102     fatArch.cputype = CFSwapInt32BigToHost(fatArch.cputype);
00103 
00104     // Don't mask out the ABI bits.  This allows identification of ppc64
00105     // as distinct from ppc.  CPU_TYPE_X86 is preferred to CPU_TYPE_I386
00106     // but does not exist prior to the 10.4 headers.
00107     if (fatArch.cputype == CPU_TYPE_POWERPC)
00108       foundPPC = PR_TRUE;
00109     else if (fatArch.cputype == CPU_TYPE_I386)
00110       foundX86 = PR_TRUE;
00111   }
00112 
00113   if (foundPPC && foundX86)
00114     sIsUniversalBinary = PR_TRUE;
00115 
00116 done:
00117   if (fd != -1)
00118     close(fd);
00119   if (executableURL)
00120     ::CFRelease(executableURL);
00121 
00122   *aIsUniversalBinary = sIsUniversalBinary;
00123   sInitialized = PR_TRUE;
00124 
00125   return NS_OK;
00126 }
00127 
00128 /* readonly attribute boolean isTranslated; */
00129 // True when running under binary translation (Rosetta).
00130 NS_IMETHODIMP nsMacUtilsImpl::GetIsTranslated(PRBool *aIsTranslated)
00131 {
00132 #ifdef __ppc__
00133   static PRBool  sInitialized = PR_FALSE;
00134 
00135   // Initialize sIsNative to 1.  If the sysctl fails because it doesn't
00136   // exist, then translation is not possible, so the process must not be
00137   // running translated.
00138   static PRInt32 sIsNative = 1;
00139 
00140   if (!sInitialized) {
00141     size_t sz = sizeof(sIsNative);
00142     sysctlbyname("sysctl.proc_native", &sIsNative, &sz, NULL, 0);
00143     sInitialized = PR_TRUE;
00144   }
00145 
00146   *aIsTranslated = !sIsNative;
00147 #else
00148   // Translation only exists for ppc code.  Other architectures aren't
00149   // translated.
00150   *aIsTranslated = PR_FALSE;
00151 #endif
00152 
00153   return NS_OK;
00154 }