r300 - trunk

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Sun May 20 19:24:37 EDT 2007


Author: icculus
Date: 2007-05-20 19:24:36 -0400 (Sun, 20 May 2007)
New Revision: 300

Modified:
   trunk/CMakeLists.txt
   trunk/fileio.c
   trunk/fileio.h
   trunk/mojosetup.c
   trunk/platform.h
   trunk/platform_unix.c
Log:
A shot at a kludge for launching a different binary from inside the Base
 Archive, so you can download/run a 32-bit installer but launch a real 64-bit
 process...this may help with amd64 systems that, say, have GTK+ support in
 the normal system, but not in their 32-bit compatibility layer.


Modified: trunk/CMakeLists.txt
===================================================================
--- trunk/CMakeLists.txt	2007-05-20 11:14:27 UTC (rev 299)
+++ trunk/CMakeLists.txt	2007-05-20 23:24:36 UTC (rev 300)
@@ -213,6 +213,16 @@
 ENDIF(MOJOSETUP_LUA_PARSER)
 
 
+# Kludge for Linux x86/amd64 bins...
+IF(UNIX AND NOT MACOSX)  # Just use Mach-O Universal/"fat" binaries on OS X.
+    OPTION(MOJOSETUP_MULTIARCH "Allow multiarch hack." FALSE)
+    MARK_AS_ADVANCED(MOJOSETUP_MULTIARCH)
+    IF(MOJOSETUP_MULTIARCH)
+        ADD_DEFINITIONS(-DSUPPORT_MULTIARCH=1)
+    ENDIF(MOJOSETUP_MULTIARCH)
+ENDIF(UNIX AND NOT MACOSX)
+
+
 # Optional bits of the Lua runtime library...
 
 # BINARY SIZE += 4.5

Modified: trunk/fileio.c
===================================================================
--- trunk/fileio.c	2007-05-20 11:14:27 UTC (rev 299)
+++ trunk/fileio.c	2007-05-20 23:24:36 UTC (rev 300)
@@ -483,15 +483,36 @@
 
 
 MojoArchive *GBaseArchive = NULL;
+const char *GBaseArchivePath = NULL;
 
 MojoArchive *MojoArchive_initBaseArchive(void)
 {
+    char *basepath = NULL;
+    const char *cmd = NULL;
+    MojoInput *io = NULL;
+
     if (GBaseArchive != NULL)
-        return GBaseArchive;
+        return GBaseArchive;  // already initialized.
+
+    if ((cmd = cmdlinestr("base", "MOJOSETUP_BASE", NULL)) != NULL)
+    {
+        if (MojoPlatform_isdir(cmd))
+            GBaseArchive = MojoArchive_newFromDirectory(cmd);
+        else
+        {
+            io = MojoInput_newFromFile(cmd);
+            if (io != NULL)
+                GBaseArchive = MojoArchive_newFromInput(io, cmd);
+        } // else
+
+        if (GBaseArchive != NULL)
+            basepath = xstrdup(cmd);
+    } // else if
+
     else
     {
-        char *basepath = MojoPlatform_appBinaryPath();
-        MojoInput *io = MojoInput_newFromFile(basepath);
+        basepath = MojoPlatform_appBinaryPath();
+        io = MojoInput_newFromFile(basepath);
 
         if (io != NULL)
             GBaseArchive = MojoArchive_newFromInput(io, basepath);
@@ -499,21 +520,28 @@
         if (GBaseArchive == NULL)
         {
             // Just use the same directory as the binary instead.
-            const char *parentdir = basepath;
             char *ptr = strrchr(basepath, '/');
             if (ptr != NULL)
                 *ptr = '\0';
             else
-                parentdir = ".";  // oh well.
-            GBaseArchive = MojoArchive_newFromDirectory(parentdir);
+            {
+                free(basepath);  // oh well, try cwd.
+                basepath = MojoPlatform_currentWorkingDir();
+            } // else
+            GBaseArchive = MojoArchive_newFromDirectory(basepath);
 
             // !!! FIXME: failing this, maybe default.mojosetup?
-            // !!! FIXME:  maybe a command line?
         } // if
 
-        free(basepath);   // appBinaryPath caller free()s this string.
     } // else
 
+    if (GBaseArchive == NULL)
+    {
+        free(basepath);
+        basepath = NULL;
+    } // if
+    GBaseArchivePath = basepath;
+
     return GBaseArchive;
 } // MojoArchive_initBaseArchive
 
@@ -525,6 +553,9 @@
         GBaseArchive->close(GBaseArchive);
         GBaseArchive = NULL;
     } // if
+
+    free((void *) GBaseArchivePath);
+    GBaseArchivePath = NULL;
 } // MojoArchive_deinitBaseArchive
 
 

Modified: trunk/fileio.h
===================================================================
--- trunk/fileio.h	2007-05-20 11:14:27 UTC (rev 299)
+++ trunk/fileio.h	2007-05-20 23:24:36 UTC (rev 300)
@@ -93,6 +93,7 @@
 MojoInput *MojoInput_newFromArchivePath(MojoArchive *ar, const char *fname);
 
 extern MojoArchive *GBaseArchive;
+extern const char *GBaseArchivePath;
 MojoArchive *MojoArchive_initBaseArchive(void);
 void MojoArchive_deinitBaseArchive(void);
 

Modified: trunk/mojosetup.c
===================================================================
--- trunk/mojosetup.c	2007-05-20 11:14:27 UTC (rev 299)
+++ trunk/mojosetup.c	2007-05-20 23:24:36 UTC (rev 300)
@@ -60,6 +60,56 @@
 } // MojoSetup_crash
 
 
+#if !SUPPORT_MULTIARCH
+#define trySwitchBinaries()
+#else
+static void trySwitchBinary(MojoArchive *ar)
+{
+    MojoInput *io = ar->openCurrentEntry(ar);
+    if (io != NULL)
+    {
+        const uint32 imglen = (uint32) io->length(io);
+        uint8 *img = (uint8 *) xmalloc(imglen);
+        const uint32 br = io->read(io, img, imglen);
+        io->close(io);
+        if (br == imglen)
+        {
+            logInfo("Switching binary with '%s'...", ar->prevEnum.filename);
+            MojoPlatform_switchBin(img, imglen);  // no return on success.
+            logError("...Switch binary failed.");
+        } // if
+        free(img);
+    } // if
+} // trySwitchBinary
+
+
+static void trySwitchBinaries(void)
+{
+    if (cmdlinestr("nobinswitch", "MOJOSETUP_NOBINSWITCH", NULL) != NULL)
+        return;  // we are already switched or the user is preventing it.
+
+    setenv("MOJOSETUP_NOSWITCHBIN", "1", 1);
+    setenv("MOJOSETUP_BASE", GBaseArchivePath, 1);
+
+    if (GBaseArchive->enumerate(GBaseArchive))
+    {
+        const MojoArchiveEntry *entinfo;
+        while ((entinfo = GBaseArchive->enumNext(GBaseArchive)) != NULL)
+        {
+            if (entinfo->type != MOJOARCHIVE_ENTRY_FILE)
+                continue;
+
+            if (strncmp(entinfo->filename, "arch/", 5) != 0)
+                continue;
+
+            trySwitchBinary(GBaseArchive);
+        } // while
+    } // if
+    
+} // trySwitchBinaries
+#endif
+
+
 static boolean initEverything(void)
 {
     MojoLog_initLogging();
@@ -75,7 +125,9 @@
     if (!MojoArchive_initBaseArchive())
         panic("Initial setup failed. Cannot continue.");
 
-    else if (!MojoGui_initGuiPlugin())
+    trySwitchBinaries();  // may not return.
+
+    if (!MojoGui_initGuiPlugin())
         panic("Initial GUI setup failed. Cannot continue.");
 
     else if (!MojoLua_initLua())

Modified: trunk/platform.h
===================================================================
--- trunk/platform.h	2007-05-20 11:14:27 UTC (rev 299)
+++ trunk/platform.h	2007-05-20 23:24:36 UTC (rev 300)
@@ -22,6 +22,9 @@
 char *MojoPlatform_appBinaryPath(void);
 
 // Caller must free returned string!
+char *MojoPlatform_currentWorkingDir(void);
+
+// Caller must free returned string!
 char *MojoPlatform_homedir(void);
 
 uint32 MojoPlatform_ticks(void);
@@ -97,6 +100,12 @@
 void *MojoPlatform_dlsym(void *lib, const char *sym);
 void MojoPlatform_dlclose(void *lib);
 
+#if !SUPPORT_MULTIARCH
+#define MojoPlatform_switchBin(img, len)
+#else
+void MojoPlatform_switchBin(const uint8 *img, size_t len);
+#endif
+
 // Put the calling process to sleep for at least (ticks) milliseconds.
 //  This is meant to yield the CPU while spinning in a loop that is polling
 //  for input, etc. Pumping the GUI event queue happens elsewhere, not here.

Modified: trunk/platform_unix.c
===================================================================
--- trunk/platform_unix.c	2007-05-20 11:14:27 UTC (rev 299)
+++ trunk/platform_unix.c	2007-05-20 23:24:36 UTC (rev 300)
@@ -56,7 +56,7 @@
 
 static struct timeval startup_time;
 
-static char *getCurrentWorkingDir(void)
+char *MojoPlatform_currentWorkingDir(void)
 {
     char *retval = NULL;
     size_t len;
@@ -79,7 +79,7 @@
 
     free(retval);
     return NULL;
-} // getCurrentWorkingDir
+} // MojoPlatform_currentWorkingDir
 
 
 static void *guaranteeAllocation(void *ptr, size_t len, size_t *_alloclen)
@@ -123,7 +123,7 @@
             retval = xstrdup(cwd);
         else
         {
-            if ((retval = getCurrentWorkingDir()) == NULL)
+            if ((retval = MojoPlatform_currentWorkingDir()) == NULL)
                 return NULL;
         } // else
         len = strlen(retval);
@@ -715,7 +715,42 @@
 } // MojoPlatform_dlclose
 
 
+#if SUPPORT_MULTIARCH
+void MojoPlatform_switchBin(const uint8 *img, size_t len)
+{
+    const char *dirs[] = { "/dev/shm", getenv("TMPDIR"), P_tmpdir, "/tmp" };
+    const char *tmpl = "mojosetup-switch-bin-XXXXXX";
+    char fname[PATH_MAX];
+    int i = 0;
 
+    for (i = 0; i < STATICARRAYLEN(dirs); i++)
+    {
+        if (testTmpDir(dirs[i], fname, len, tmpl))
+        {
+            const int fd = mkstemp(fname);
+            if (fd != -1)
+            {
+                const size_t bw = write(fd, img, len);
+                const int rc = close(fd);
+                if ((bw == len) && (rc != -1))
+                {
+                    const char *tmpstr = GArgv[0];
+                    chmod(fname, 0700);
+                    GArgv[0] = fname;
+                    execv(fname, (char * const *) GArgv);
+                    // only hits this line if process wasn't replaced.
+                    GArgv[0] = tmpstr;
+                } // if
+                unlink(fname);
+            } // if
+        } // if
+    } // for
+
+    // couldn't replace current process.
+} // MojoPlatform_switchBin
+#endif
+
+
 static void signal_catcher(int sig)
 {
     static boolean first_shot = true;




More information about the mojosetup-commits mailing list