Skip to content

Commit

Permalink
A shot at a kludge for launching a different binary from inside the Base
Browse files Browse the repository at this point in the history
 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.
  • Loading branch information
icculus committed May 20, 2007
1 parent ce67b05 commit f362b7f
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 12 deletions.
10 changes: 10 additions & 0 deletions CMakeLists.txt
Expand Up @@ -213,6 +213,16 @@ ELSE(MOJOSETUP_LUA_PARSER)
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
Expand Down
47 changes: 39 additions & 8 deletions fileio.c
Expand Up @@ -483,37 +483,65 @@ MojoArchive *MojoArchive_newFromDirectory(const char *dirname)


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);

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

Expand All @@ -525,6 +553,9 @@ void MojoArchive_deinitBaseArchive(void)
GBaseArchive->close(GBaseArchive);
GBaseArchive = NULL;
} // if

free((void *) GBaseArchivePath);
GBaseArchivePath = NULL;
} // MojoArchive_deinitBaseArchive


Expand Down
1 change: 1 addition & 0 deletions fileio.h
Expand Up @@ -93,6 +93,7 @@ MojoArchive *MojoArchive_newFromInput(MojoInput *io, const char *origfname);
MojoInput *MojoInput_newFromArchivePath(MojoArchive *ar, const char *fname);

extern MojoArchive *GBaseArchive;
extern const char *GBaseArchivePath;
MojoArchive *MojoArchive_initBaseArchive(void);
void MojoArchive_deinitBaseArchive(void);

Expand Down
54 changes: 53 additions & 1 deletion mojosetup.c
Expand Up @@ -60,6 +60,56 @@ void MojoSetup_terminated(void)
} // 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();
Expand All @@ -75,7 +125,9 @@ static boolean initEverything(void)
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())
Expand Down
9 changes: 9 additions & 0 deletions platform.h
Expand Up @@ -21,6 +21,9 @@ int MojoSetup_main(int argc, char **argv);
// Caller must free returned string!
char *MojoPlatform_appBinaryPath(void);

// Caller must free returned string!
char *MojoPlatform_currentWorkingDir(void);

// Caller must free returned string!
char *MojoPlatform_homedir(void);

Expand Down Expand Up @@ -97,6 +100,12 @@ void *MojoPlatform_dlopen(const uint8 *img, size_t len);
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.
Expand Down
41 changes: 38 additions & 3 deletions platform_unix.c
Expand Up @@ -56,7 +56,7 @@ void beos_usleep(unsigned long ticks);

static struct timeval startup_time;

static char *getCurrentWorkingDir(void)
char *MojoPlatform_currentWorkingDir(void)
{
char *retval = NULL;
size_t len;
Expand All @@ -79,7 +79,7 @@ static char *getCurrentWorkingDir(void)

free(retval);
return NULL;
} // getCurrentWorkingDir
} // MojoPlatform_currentWorkingDir


static void *guaranteeAllocation(void *ptr, size_t len, size_t *_alloclen)
Expand Down Expand Up @@ -123,7 +123,7 @@ static char *realpathInternal(char *path, const char *cwd, int linkloop)
retval = xstrdup(cwd);
else
{
if ((retval = getCurrentWorkingDir()) == NULL)
if ((retval = MojoPlatform_currentWorkingDir()) == NULL)
return NULL;
} // else
len = strlen(retval);
Expand Down Expand Up @@ -715,6 +715,41 @@ void MojoPlatform_dlclose(void *lib)
} // 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)
{
Expand Down

0 comments on commit f362b7f

Please sign in to comment.