This is plipo.c in view mode; [Download] [Up]
/*
* Simple portable 'lipo' for NeXTstep fat files.
* 0.9 Sun Mar 13 20:22:03 1994 Chris Schneider
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int getopt(int, char **, char *);
#define FAT_MAGIC 0xcafebabe
#define NON_FAT_BIG_ENDIAN 0xfeedface
#define NON_FAT_LITTLE_ENDIAN 0xcefaedfe
struct fat_header
{
char magic[4]; /* FAT_MAGIC */
char nfat_arch[4]; /* number of structs that follow */
};
struct fat_arch
{
char cputype[4]; /* cpu specifier (int) */
char cpusubtype[4]; /* machine specifier (int) */
char offset[4]; /* file offset to this object file */
char size[4]; /* size of this object file */
char align[4]; /* alignment as a power of 2 */
};
struct non_fat_header
{
char magic[4]; /* FAT_MAGIC */
char cputype[4]; /* cpu specifier (int) */
};
#define GET32(x) ((unsigned long)((((unsigned char *)(x))[0] << 24) | \
(((unsigned char *)(x))[1] << 16) | \
(((unsigned char *)(x))[2] << 8) | \
(((unsigned char *)(x))[3])))
#define GET32L(x) ((unsigned long)((((unsigned char *)(x))[3] << 24) | \
(((unsigned char *)(x))[2] << 16) | \
(((unsigned char *)(x))[1] << 8) | \
(((unsigned char *)(x))[0])))
#define SET32(a, x) ((((unsigned char *)(a))[0] = (unsigned char )(x >> 24)), \
(((unsigned char *)(a))[1] = (unsigned char )(x >> 16)), \
(((unsigned char *)(a))[2] = (unsigned char )(x >> 8)), \
(((unsigned char *)(a))[3]) = (unsigned char )x)
#define COPY32(d, s) (((char *)(d))[0] = ((char *)(s))[0]), \
(((char *)(d))[1] = ((char *)(s))[1]), \
(((char *)(d))[2] = ((char *)(s))[2]), \
(((char *)(d))[3] = ((char *)(s))[3]);
#define CPU_TYPE_ANY (-1)
char *cpus[] =
{
"any",
"unknown",
"vax",
"romp",
"unknown",
"ns32032",
"ns32332",
"m68k",
"i386",
"mips",
"ns32532",
"unknown",
"hppa",
"arm",
"m88k",
"sparc",
"i860",
"i860little",
"rs6000",
"m98k",
NULL
};
static struct fat_arch *fatgetarch(char *mem, int cpu)
{
struct fat_header *fh = (struct fat_header *)mem;
struct fat_arch *fa;
if (fh && (GET32(fh->magic) == FAT_MAGIC))
{
unsigned long num;
fa = (struct fat_arch *)(fh + 1);
for (num = GET32(fh->nfat_arch); num > 0; num--, fa++)
{
if ((cpu == CPU_TYPE_ANY) || (GET32(fa->cputype) == cpu))
return fa;
}
}
return (struct fat_arch *)0;
}
static unsigned long fatgetoffset(char *mem, int cpu)
{
struct fat_arch *fa, *fa0;
if ((fa0 = fatgetarch(mem, CPU_TYPE_ANY)) && (fa = fatgetarch(mem, cpu)))
return GET32(fa->offset);
else
return 0;
}
static unsigned long fatgetsize(char *mem, int cpu)
{
struct fat_arch *fa;
if ((fa = fatgetarch(mem, cpu)))
return GET32(fa->size);
else
return 0;
}
static void fatsave(char *file, char *mem, int cpu)
{
FILE *out;
struct fat_arch *fa, *fa0;
if (file && ((out = fopen(file, "w")) != NULL))
{
if ((fa0 = fatgetarch(mem, CPU_TYPE_ANY)) && (fa = fatgetarch(mem, cpu)))
{
char num[4], msg[] = "\nExtracted with plipo\n";
unsigned long t;
fwrite(mem, 4, 1, out);
SET32(num, 1);
fwrite(num, sizeof(num), 1, out);
t = GET32(fa->offset);
COPY32(fa->offset, fa0->offset);
fwrite(fa, sizeof(struct fat_arch), (size_t)1, out);
SET32(fa->offset, t);
fwrite(msg, sizeof(msg), 1, out);
fwrite(mem, (size_t)(GET32(fa0->offset) - sizeof(msg) -
sizeof(struct fat_arch) - 4 - 4), 1, out);
fwrite(mem + fatgetoffset(mem, cpu),
(size_t)fatgetsize(mem, cpu), 1, out);
}
fclose(out);
}
}
static char *fatload(char *filename)
{
FILE *file = stdin;
char *mem = NULL;
long old, size = 16384;
if (filename && (!strcmp(filename, "-") || (file = fopen(filename, "r"))))
{
for (mem = (char *)malloc((size_t)size), old = 0;
mem = (char *)realloc(mem, (size_t)size);
old += (size - old), size *= 2)
{
if (fread(mem + old, 1, (size_t)(size - old), file) < (size - old))
{
if (ferror(file))
{
free(mem);
mem = NULL;
}
break;
}
}
fclose(file);
}
return mem;
}
static void fatanalyse(char *mem)
{
struct fat_header *fh = (struct fat_header *)mem;
struct non_fat_header *nfh = (struct non_fat_header *)mem;
int ct = -1;
if (fh)
{
if (GET32(fh->magic) == FAT_MAGIC)
{
long num = GET32(fh->nfat_arch);
struct fat_arch *fa = (struct fat_arch *)(fh + 1);
printf("%d architectures:", num);
for ( ; num > 0; fa++, num--)
{
int ct = (int)GET32(fa->cputype);
printf(" %d", ct);
if ((ct < -1) || (ct >= (sizeof(cpus) / sizeof(char *))))
ct = 1;
printf("=%s", cpus[ct + 1]);
}
printf("\n");
}
else
{
if (GET32(nfh->magic) == NON_FAT_BIG_ENDIAN)
ct = (int)GET32(nfh->cputype);
if (GET32(nfh->magic) == NON_FAT_LITTLE_ENDIAN)
ct = (int)GET32L(nfh->cputype);
if (ct >= 0)
{
printf("non-fat file for architecture: %d", ct);
if ((ct < -1) || (ct >= (sizeof(cpus) / sizeof(char *))))
ct = 1;
printf("=%s\n", cpus[ct + 1]);
}
else
printf("unknown file type (magic: %08x)\n", GET32(fh->magic));
}
}
}
int main(int argc, char **argv)
{
int i, c, xcpu = -1;
char *mem, *opts = "x:hiv", errflg = 0;
extern int optind;
extern char *optarg;
while ((c = getopt(argc, argv, opts)) != EOF)
{
switch(c)
{
case 'v':
printf("plipo - portable lipo v1.00 written by Christian Schneider\n");
printf(" (yeah buddha, *that* had to be! ;-))) )\n");
exit(1);
case 'x':
if (xcpu <= 0)
{
if ((xcpu = atoi(optarg)))
break;
for (xcpu = 0; cpus[xcpu]; xcpu++)
{
if (!strcmp(cpus[xcpu], optarg))
break;
}
if (xcpu && cpus[xcpu] && strcmp(cpus[xcpu], "unknown"))
xcpu--;
else
{
printf("invalid cpu '%s' given.\n", optarg);
xcpu = -1;
}
}
else
{
printf("Can only extract one cpu at a time in this version\n");
errflg++;
}
break;
default:
errflg++;
}
}
if (errflg)
{
printf("Usage: %s [-%s] [filename ...]\n", argv[0], opts);
printf(" -h : this help page\n");
printf(" -v : version\n");
printf(" -x <cpu> : extract content for specified cpu (e.g. m68k, i386)\n");
return 1;
}
if (xcpu > 0)
printf("Extracting cpu type '%s'\n", cpus[xcpu + 1]);
if (optind == argc)
{
if ((mem = fatload("-")))
{
char buf[1024];
printf("File <stdin>: ");
fatanalyse(mem);
if (xcpu > 0)
{
sprintf(buf, "fatfile.%s", cpus[xcpu + 1]);
fatsave(buf, mem, xcpu);
}
free(mem);
}
}
for (i = optind; i < argc; i++)
{
if ((mem = fatload(argv[i])))
{
char buf[1024];
printf("File '%s': ", argv[i]);
fatanalyse(mem);
if (xcpu > 0)
{
if (fatgetarch(mem, xcpu))
{
sprintf(buf, "%s.%s", argv[i], cpus[xcpu + 1]);
fatsave(buf, mem, xcpu);
}
else
printf("specified architecture not found.\n");
}
free(mem);
}
}
return 0;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.