LaunchAPPL --make-executable: add a #!/.../LaunchCFMApp to a mac app

This commit is contained in:
Wolfgang Thaller 2017-10-04 02:03:26 +02:00
parent bd38a209ba
commit 507ba9debf
5 changed files with 97 additions and 3 deletions

View File

@ -20,6 +20,7 @@ add_definitions(-DRETRO68_PREFIX="${CMAKE_INSTALL_PREFIX}")
add_executable(LaunchAPPL
LaunchAPPL.cc
MakeExecutable.cc
LaunchMethod.h LaunchMethod.cc
Launcher.h Launcher.cc

View File

@ -93,7 +93,7 @@ static void usage()
}
}
void MakeExecutable(string filepath);
int main(int argc, char *argv[])
{
@ -102,6 +102,7 @@ int main(int argc, char *argv[])
desc.add_options()
("help,h", "show this help message")
("make-executable,x", po::value<std::string>(), "make a MacBinary file executable")
;
po::options_description configdesc;
configdesc.add_options()
@ -158,12 +159,28 @@ int main(int argc, char *argv[])
po::notify(options);
if(options.count("help") || !options.count("application") || !options.count("emulator"))
if(options.count("help") || (!options.count("application") && !options.count("make-executable")))
{
usage();
return 0;
}
if(options.count("make-executable"))
{
string fn = options["make-executable"].as<std::string>();
MakeExecutable(fn);
if(!options.count("application"))
return 0;
}
if(!options.count("emulator"))
{
std::cerr << "ERROR: emulator/environment not specified.\n";
usage();
return 1;
}
LaunchMethod *method = NULL;
for(LaunchMethod *lm : launchMethods)
{
@ -181,7 +198,7 @@ int main(int argc, char *argv[])
if(!method->CheckOptions(options))
{
std::cerr << "Missing configuration.\n";
std::cerr << "Need more configuration.\n";
usage();
return 1;
}

View File

@ -0,0 +1,52 @@
#include <string>
#include <iostream>
#include <boost/filesystem.hpp>
#include <stdlib.h>
#include "ResourceFile.h"
using std::string;
namespace fs = boost::filesystem;
void MakeExecutable(string fn)
{
ResourceFile rsrcFile(fn);
if(!rsrcFile.read())
{
std::cerr << "Cannot read application file: " << fn << std::endl;
exit(1);
}
if(!rsrcFile.hasPlainDataFork())
{
std::cerr << "--make-executable can not be used with this data format.\n";
exit(1);
}
string headerString = "#!" RETRO68_PREFIX "/bin/LaunchAPPL\n";
bool hadShebang = false;
if(rsrcFile.data.size())
{
if(headerString.substr(2) == "#!")
{
string::size_type eol = headerString.find('\n');
if(eol != string::npos && eol >= 13 && eol < 4096)
{
if(headerString.substr(eol-11,11) == "/LaunchAPPL")
hadShebang = true;
}
}
if(!hadShebang)
{
std::cerr << "Unfortunately, the application already has a data fork.\n";
std::cerr << "LaunchAPPL --make-executable does not currently work for PowerPC apps.\n";
// TODO: if it's a PEF container, move it back a little and update cfrg
exit(1);
}
}
std::fstream(fn, std::ios::in | std::ios::out | std::ios::binary) << headerString;
fs::permissions(fs::path(fn), fs::owner_exe | fs::group_exe | fs::others_exe | fs::add_perms);
}

View File

@ -523,3 +523,24 @@ bool ResourceFile::write()
return true;
}
bool ResourceFile::hasPlainDataFork(ResourceFile::Format f)
{
switch(f)
{
#ifdef __APPLE__
case Format::real:
#endif
case Format::basilisk:
case Format::underscore_appledouble:
case Format::percent_appledouble:
return true;
default:
return false;
}
}
bool ResourceFile::hasPlainDataFork()
{
return hasPlainDataFork(format);
}

View File

@ -31,6 +31,9 @@ public:
bool read();
bool write();
static bool hasPlainDataFork(Format f);
bool hasPlainDataFork();
std::string pathstring;
Format format;
ResType type;