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.