home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1628 < prev    next >
Internet Message Format  |  1990-12-28  |  9KB

  1. From: dplatt@coherent.com (Dave Platt)
  2. Newsgroups: alt.sources
  3. Subject: [appletalk] MacBinary-to-CAP file converter
  4. Message-ID: <1990Jul27.035725.1421@math.lsa.umich.edu>
  5. Date: 27 Jul 90 03:57:25 GMT
  6.  
  7. Archive-name: bin2cap/27-Jul-90
  8. Original-posting-by: dplatt@coherent.com (Dave Platt)
  9. Original-subject: MacBinary-to-CAP file converter
  10. Reposted-by: emv@math.lsa.umich.edu (Edward Vielmetti)
  11.  
  12. [Reposted from comp.protocols.appletalk.
  13. Comments on this service to emv@math.lsa.umich.edu (Edward Vielmetti).]
  14.  
  15. Well, I finally decided to get off of my rear end and write a utility
  16. which could convert a MacBinary file into CAP/Aufs format.  By cutting
  17. and splicing portions of "cvt2cap", Aufs code, and the "macbin" program,
  18. I managed to get something which seems to work reasonably well (on my
  19. Sparcstation, at least).  
  20.  
  21. It lacks somewhat in its error checking capability (it doesn't verify
  22. the CRC in the MacBinary II header);  it assumes MacBinary II format
  23. (which is mostly what one finds these days);  and the source-code
  24. contains a fair bit of residue from its origin as part of three
  25. different programs, and could use some cleanup.  Quite frankly, it's a
  26. quick and somewhat ugly hack.
  27.  
  28. Nevertheless, it works.  I'm sure I'm not the only CAP user who has been
  29. wishing for a utility of this sort... so, here it is.  It's small, so
  30. I'm posting it here rather than going through comp.sources.whatever...
  31. may the Net Gods forgive me for my presumption.
  32.  
  33. /*
  34.  *    bin2cap
  35.  *
  36.  *    This program converts MacBinary files to CAP/aufs
  37.  *    format files.
  38.  *
  39.  *        bin2cap [sourcefile]
  40.  *
  41.  *      The specified source file (or the standard input if no source
  42.  *      file is specified) is read, verified to be in MacBinary format,
  43.  *      and used to create an Aufs-compatible file in the current working
  44.  *      directory.  The original file is left unchanged.
  45.  *
  46.  *    COPYRIGHT NOTICE
  47.  *
  48.  *      Copyright 1990 by Dave Platt.  All Rights Reserved.
  49.  *
  50.  *    Permission is granted to any individual or institution to use, copy,
  51.  *    or redistribute this software so long as it is not sold for profit,
  52.  *    provided that this notice and the original copyright notices are
  53.  *    retained.  Dave Platt makes no representations about the
  54.  *    suitability of this software for any purpose.  It is provided "as is"
  55.  *    without express or implied warranty.
  56.  *      
  57.  *      Portions of this code are based on the "cvt2cap" program by Paul
  58.  *      Campbell;  on the Aufs file-server package by Charlie Kim et al;  and
  59.  *      on the "macbin" program (author unknown to me).  Relevant copyrights
  60.  *      are included herein.
  61.  *
  62.  *      For portions derived from Aufs:
  63.  *
  64.  *      Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University
  65.  *      in the City of New York.
  66.  *
  67.  *      For portions derived from cvt2cap:
  68.  *    
  69.  *    Copyright (c) May 1988, Paul Campbell, All Rights Reserved.
  70.  *    
  71.  *    Permission is granted to any individual or institution to use, copy,
  72.  *    or redistribute this software so long as it is not sold for profit,
  73.  *    provided that this notice and the original copyright notices are
  74.  *    retained.  Paul Campbell makes no representations about the
  75.  *    suitability of this software for any purpose.  It is provided "as is"
  76.  *    without express or implied warranty.
  77.  *    
  78.  *  History:
  79.  *    4/23/88 Paul Campbell, submitted to CAP distribution
  80.  *    4/23/88 Charlie C. Kim, clean up and modify to work with
  81.  *            byte swapped machines
  82.  *    7/26/90 Dave Platt, beaten about the head and shoulders with a stick
  83.  *            until it would eat MacBinary files rather than AppleSingle
  84.  *            or AppleDouble.
  85.  *
  86.  */    
  87.  
  88.  
  89. #include <stdio.h>
  90. #include <ctype.h>
  91. #include <sys/types.h>
  92. #include <sys/stat.h>
  93. #include <netinet/in.h>
  94. #include <netat/appletalk.h>
  95. #include <netat/macfile.h>
  96.  
  97. char *prog;
  98.  
  99. struct macbinhdr {
  100. /* 000 */  char zero1;
  101. /* 001 */  char nlen;
  102. /* 002 */  char name[63];
  103. /* 065 */  char type[4];
  104. /* 069 */  char creator[4];
  105. /* 073 */  char flags;    
  106. /* 074 */  char zero2;    
  107. /* 075 */  char vert[2];
  108. /* 077 */  char horiz[2];
  109. /* 079 */  char folderID[2];
  110. /* 081 */  char protected;        
  111. /* 082 */  char zero3;        
  112. /* 083 */  char dflen[4];
  113. /* 087 */  char rflen[4];
  114. /* 091 */  char cdate[4];
  115. /* 095 */  char mdate[4];
  116. /* 099 */  char ilen[2];
  117. /* 101 */  char flags2;
  118. /* 102 */  char zero4[20];
  119. /* 122 */  char mbvers;
  120. /* 123 */  char minvers;
  121. /* 124 */  char crc[2];
  122. /* 126 */  char zero5[2];       
  123. } header;
  124.  
  125.     
  126. char dir[] = "";
  127. char file[1025];
  128. char ename[1024],iname[1024];
  129.  
  130. static char *hexdigits = "0123456789abcdef";
  131.  
  132. FileInfo finfo;
  133. fileFinderInfo *finderInfo;
  134.  
  135. FILE *fiopen();
  136. void EtoIName();
  137. int ENameLen();
  138.  
  139. main(argc, argv)
  140. char **argv;
  141. {
  142.     char *fin, *fout;
  143.     FILE *f, *fd, *fx;
  144.     register int i, j;
  145.     int resource, data;
  146.     u_long temp;
  147.  
  148.     bzero(&finfo, sizeof(finfo)); /* make sure clear first */
  149.  
  150.     prog = argv[0];
  151.  
  152.     if (argc > 2)
  153.       {
  154.         usage();
  155.       }
  156.  
  157.     if (argc == 1)
  158.       {
  159.         f = stdin;
  160.       }
  161.     else
  162.       {
  163.         if ((f = fiopen(dir, NULL, argv[1], "r")) == NULL)
  164.           {
  165.         error("can't open input file %", argv[1]);
  166.           }
  167.       }
  168.  
  169.  
  170.     /*
  171.      *    Read the header 
  172.      */
  173.  
  174.     if (fread(&header, sizeof header, 1, f) < 1)
  175.       {
  176.         error("could not read MacBinary header header");
  177.       }
  178.  
  179.     if (header.zero1 != 0 || header.zero2 != 0 || header.nlen <= 0 ||
  180.         header.nlen > 63)
  181.       {
  182.         error ("not a MacBinary file!");
  183.       }
  184.  
  185.     bzero(ename, sizeof ename);
  186.     strncpy(ename, header.name, header.nlen);
  187.     if (ENameLen(ename) > 31)
  188.       {
  189.         error("encoded name > 31 characters");
  190.       }
  191.     EtoIName(ename, iname);
  192.  
  193.     finderInfo = (fileFinderInfo *) finfo.fi_fndr;
  194.     bcopy(header.type, finderInfo->fdType, 4);
  195.     bcopy(header.creator, finderInfo->fdCreator, 4);
  196.     finderInfo->fdFlags = ((header.flags << 8) | header.flags2) & 0xf8fc;
  197.  
  198.     finfo.fi_magic1 = FI_MAGIC1;
  199.     finfo.fi_version = FI_VERSION;
  200.     finfo.fi_magic = FI_MAGIC;
  201.     finfo.fi_bitmap = FI_BM_MACINTOSHFILENAME;
  202.     finfo.fi_macfilename[0] = header.nlen;
  203.     bcopy(header.name, finfo.fi_macfilename+1, header.nlen);
  204.  
  205.     fx = fiopen(dir, ".finderinfo/", iname, "w");
  206.     if (fx == NULL)
  207.         error("cannot create output finder info file '%s'", iname);
  208.     if (fwrite(&finfo, sizeof(finfo), 1, fx) < 1)
  209.         error("cannot write output finder info file '%s'", iname);
  210.     fclose(fx);
  211.  
  212.     bcopy(header.dflen, &temp, sizeof temp);
  213.     data = ntohl(temp);
  214.  
  215.     bcopy(header.rflen, &temp, sizeof temp);
  216.     resource = ntohl(temp);
  217.  
  218.     fx = fiopen(dir, NULL, iname, "w");
  219.     if (fx == NULL)
  220.       error("cannot create output data file '%s'", iname);
  221.     fcopy(fx, f, data);
  222.     fclose(fx);
  223.  
  224.     if (resource > 0)
  225.       {
  226.         while ((data%128) != 0)
  227.           {
  228.         (void) fgetc(f);
  229.         data++;
  230.           }
  231.  
  232.         fx = fiopen(dir, ".resource/", iname, "w");
  233.         if (fx == NULL)
  234.           error("cannot create output resource file '%s'",
  235.             iname);
  236.         fcopy(fx, f, resource);
  237.         fclose(fx);
  238.       }
  239. }
  240.  
  241. /*
  242.  *    open the file "dir""ext""file" with mode "mode"
  243.  */
  244.  
  245. FILE *
  246. fiopen(dir, ext, file, mode)
  247. char *dir, *ext, *file, *mode;
  248. {
  249.     char name[1025];
  250.  
  251.     strcpy(name, dir);
  252.     if (ext)
  253.         strcat(name, ext);
  254.     strcat(name, file);
  255.     return(fopen(name, mode));
  256. }
  257.  
  258. /*
  259.  *    print a nasty message
  260.  */
  261.  
  262. usage()
  263. {
  264.     fprintf(stderr, "Usage: %s [macbinary-file]\n",
  265.             prog);
  266.     exit(1);
  267. }
  268.  
  269. /*
  270.  *    copy length bytes from fin to fout
  271.  */
  272.  
  273. fcopy(fout, fin, length)
  274. FILE *fin, *fout;
  275. unsigned length;
  276. {
  277.     char buffer[4096];
  278.     register unsigned l;
  279.  
  280.     while (length > 0) {
  281.       l = sizeof buffer;
  282.       if (l > length)
  283.         l = length;
  284.       l = fread(buffer, 1, l, fin);
  285.       if (l > 0) {
  286.         if (fwrite(buffer, 1, l, fout) != l)
  287.           error("error writing output file");
  288.       } else break;
  289.       length -= l;
  290.     }
  291. }
  292.  
  293. /*
  294.  *     print another nasty message and quit 
  295.  */
  296.  
  297. error(s, a, b, c, d, e, f)
  298. char *s;
  299. {
  300.     fprintf(stderr, "%s: ", prog);
  301.     fprintf(stderr, s, a, b, c, d, e, f);
  302.     fprintf(stderr, "\n");
  303.     exit(2);
  304. }
  305.  
  306. void
  307. EtoIName(en,inp)
  308. register byte *en;        /* max is 31 or so */
  309. char *inp;
  310. {
  311.   byte c;            /* unsigned char */
  312.   register char *in = inp;
  313.   register int cnt = 0;
  314.  
  315.   while ((c = *en++) != '\0') {
  316.     if (isascii(c) && !iscntrl(c) && isprint(c) && c != '/') {
  317.       *in++ = c;
  318.       cnt++;
  319.     } else {
  320.       /* must convert to */
  321.       *in++ = ':';            /* : */
  322.       *in++ = hexdigits[(c >> 4) & 0xf];
  323.       *in++ = hexdigits[(c & 0xf)];
  324.       cnt += 3;
  325.     }
  326.   }
  327.   *in++ = '\0';
  328. }
  329.  
  330. /*
  331.  * Given an internal file name, compute the length of the external
  332.  * file name
  333.  */
  334. int
  335. ENameLen(in)
  336. register char *in;
  337. {
  338.   register int len = 0;
  339.   register char c;
  340.   register char c2;
  341.  
  342.   while ((c = *in++) != '\0') {
  343.     if (c != ':')
  344.       len++;
  345.     else {
  346.       /* must convert to external form */
  347.       if ((c = *in++) == '\0' || (c2 = *in++) == '\0') {
  348.     len++;
  349.     if (c != '\0')
  350.       len++;
  351.     break;                /* done with while */
  352.       }
  353.       if (index(hexdigits,c) == NULL || index(hexdigits,c2) == NULL) 
  354.     len += 3;
  355.       else
  356.     len++;
  357.     }
  358.   }    
  359.   return(len);
  360. }    
  361.