ftp.nice.ch/pub/next/unix/admin/plipo.I.bs.tar.gz#/plipo/plipo.c

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.