MegaGlest/mk/linux/mojosetup/misc/make_self_extracting.c

216 lines
5.5 KiB
C

/**
* MojoSetup; a portable, flexible installation application.
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Ryan C. Gordon.
*
Copyright (c) 2006-2010 Ryan C. Gordon and others.
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from
the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Ryan C. Gordon <icculus@icculus.org>
*
*/
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <sys/types.h>
#ifdef _MSC_VER
#define off_t __int64
#define ftello _ftelli64
typedef unsigned __int64 uint64;
#else
#include <stdint.h>
typedef uint64_t uint64;
#endif
static int usage(const char *argv0)
{
fprintf(stderr, "\nUSAGE: %s <exe> <archive_to_append>\n\n", argv0);
return 1;
} // usage
static int is_self_extractable(const char *fname)
{
unsigned char magic[4];
FILE *io = fopen(fname, "rb");
if (io == NULL)
{
perror("fopen");
fprintf(stderr, "Failed to open '%s' for reading.\n", fname);
return -1;
} // if
if (fread(magic, 4, 1, io) != 1)
{
perror("fread");
fclose(io);
fprintf(stderr, "Failed to read '%s'.\n", fname);
return -1;
} // if
fclose(io);
if ( (magic[0] == 0x50) && (magic[1] == 0x4B) &&
(magic[2] == 0x03) && (magic[3] == 0x04) )
return 1; // it's a .zip file, they handle self-extracting themselves.
return 0;
} // is_self_extractable
static off_t get_file_size(const char *fname)
{
off_t retval = -1;
#define FAIL(x) do { \
perror(x); \
fprintf(stderr, "couldn't determine size of %s\n", fname); \
if (io) \
fclose(io); \
return -1; \
} while (0)
FILE *io = fopen(fname, "rb");
if (io == NULL)
FAIL("fopen");
else if (fseek(io, 0, SEEK_END) != 0)
FAIL("fseek");
else if ((retval = ftello(io)) == -1)
FAIL("ftello");
else if (fclose(io) == EOF)
FAIL("fclose");
#undef FAIL
return retval;
} // get_file_size
int main(int argc, char **argv)
{
static unsigned char buf[1024 * 1024];
FILE *in = NULL;
FILE *out = NULL;
off_t exesize = -1;
off_t arcsize = -1;
off_t bytes = 0;
int is_self = 0;
assert(sizeof (off_t) == 8);
if (argc != 3)
return usage(argv[0]);
if ((exesize = get_file_size(argv[1])) < 0)
return 1;
else if ((arcsize = get_file_size(argv[2])) < 0)
return 1;
else if ((is_self = is_self_extractable(argv[2])) < 0)
return 1;
if ((out = fopen(argv[1], "ab")) == NULL)
{
perror("fopen");
fprintf(stderr, "Failed to open '%s' for appending.\n", argv[1]);
return 1;
} // if
if ((in = fopen(argv[2], "rb")) == NULL)
{
perror("fopen");
fclose(out);
fprintf(stderr, "Failed to open '%s' for reading.\n", argv[2]);
return 1;
} // if
bytes = arcsize;
while (bytes > 0)
{
size_t rc = (size_t) (bytes > sizeof (buf) ? sizeof (buf) : bytes);
rc = fread(buf, 1, rc, in);
if (ferror(in))
{
perror("fread");
break;
} // if
assert(rc != 0);
if (fwrite(buf, rc, 1, out) != 1)
{
perror("fwrite");
break;
} // if
bytes -= (off_t) rc;
} // while
if (bytes > 0)
{
fclose(in);
fclose(out);
fprintf(stderr, "Failed to write '%s'. File may be corrupted.\n", argv[1]);
return 1;
} // if
fclose(in);
if (!is_self)
{
if (fwrite("MOJOBASE", 8, 1, out) != 1)
{
perror("fwrite");
fclose(out);
fprintf(stderr, "Failed to write '%s'. File may be corrupted.\n", argv[1]);
return 1;
} // if
buf[0] = (unsigned char) ((((uint64) arcsize) >> 0) & 0xFF);
buf[1] = (unsigned char) ((((uint64) arcsize) >> 8) & 0xFF);
buf[2] = (unsigned char) ((((uint64) arcsize) >> 16) & 0xFF);
buf[3] = (unsigned char) ((((uint64) arcsize) >> 24) & 0xFF);
buf[4] = (unsigned char) ((((uint64) arcsize) >> 32) & 0xFF);
buf[5] = (unsigned char) ((((uint64) arcsize) >> 40) & 0xFF);
buf[6] = (unsigned char) ((((uint64) arcsize) >> 48) & 0xFF);
buf[7] = (unsigned char) ((((uint64) arcsize) >> 56) & 0xFF);
if (fwrite(buf, 8, 1, out) != 1)
{
perror("fwrite");
fclose(out);
fprintf(stderr, "Failed to write '%s'. File may be corrupted.\n", argv[1]);
return 1;
} // if
} // if
if (fclose(out) == EOF)
{
perror("fclose");
fprintf(stderr, "Failed to close '%s'. File may be corrupted.\n", argv[1]);
return 1;
} // if
return 0;
} // main
// end of make_self_extracting.c ...