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