home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
source
/
macbincp.zoo
/
macbin2cap
Wrap
Text File
|
1990-08-14
|
7KB
|
332 lines
/*
* bin2cap
*
* This program converts MacBinary files to CAP/aufs
* format files.
*
* bin2cap [sourcefile]
*
* The specified source file (or the standard input if no source
* file is specified) is read, verified to be in MacBinary format,
* and used to create an Aufs-compatible file in the current working
* directory. The original file is left unchanged.
*
* COPYRIGHT NOTICE
*
* Copyright 1990 by Dave Platt. All Rights Reserved.
*
* Permission is granted to any individual or institution to use, copy,
* or redistribute this software so long as it is not sold for profit,
* provided that this notice and the original copyright notices are
* retained. Dave Platt makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* Portions of this code are based on the "cvt2cap" program by Paul
* Campbell; on the Aufs file-server package by Charlie Kim et al; and
* on the "macbin" program (author unknown to me). Relevant copyrights
* are included herein.
*
* For portions derived from Aufs:
*
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University
* in the City of New York.
*
* For portions derived from cvt2cap:
*
* Copyright (c) May 1988, Paul Campbell, All Rights Reserved.
*
* Permission is granted to any individual or institution to use, copy,
* or redistribute this software so long as it is not sold for profit,
* provided that this notice and the original copyright notices are
* retained. Paul Campbell makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* History:
* 4/23/88 Paul Campbell, submitted to CAP distribution
* 4/23/88 Charlie C. Kim, clean up and modify to work with
* byte swapped machines
* 7/26/90 Dave Platt, beaten about the head and shoulders with a stick
* until it would eat MacBinary files rather than AppleSingle
* or AppleDouble.
*
*/
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <netat/appletalk.h>
#include <netat/macfile.h>
char *prog;
struct macbinhdr {
/* 000 */ char zero1;
/* 001 */ char nlen;
/* 002 */ char name[63];
/* 065 */ char type[4];
/* 069 */ char creator[4];
/* 073 */ char flags;
/* 074 */ char zero2;
/* 075 */ char vert[2];
/* 077 */ char horiz[2];
/* 079 */ char folderID[2];
/* 081 */ char protected;
/* 082 */ char zero3;
/* 083 */ char dflen[4];
/* 087 */ char rflen[4];
/* 091 */ char cdate[4];
/* 095 */ char mdate[4];
/* 099 */ char ilen[2];
/* 101 */ char flags2;
/* 102 */ char zero4[20];
/* 122 */ char mbvers;
/* 123 */ char minvers;
/* 124 */ char crc[2];
/* 126 */ char zero5[2];
} header;
char dir[] = "";
char file[1025];
char ename[1024],iname[1024];
static char *hexdigits = "0123456789abcdef";
FileInfo finfo;
fileFinderInfo *finderInfo;
FILE *fiopen();
void EtoIName();
int ENameLen();
main(argc, argv)
char **argv;
{
char *fin, *fout;
FILE *f, *fd, *fx;
register int i, j;
int resource, data;
u_long temp;
bzero(&finfo, sizeof(finfo)); /* make sure clear first */
prog = argv[0];
if (argc > 2)
{
usage();
}
if (argc == 1)
{
f = stdin;
}
else
{
if ((f = fiopen(dir, NULL, argv[1], "r")) == NULL)
{
error("can't open input file %", argv[1]);
}
}
/*
* Read the header
*/
if (fread(&header, sizeof header, 1, f) < 1)
{
error("could not read MacBinary header header");
}
if (header.zero1 != 0 || header.zero2 != 0 || header.nlen <= 0 ||
header.nlen > 63)
{
error ("not a MacBinary file!");
}
bzero(ename, sizeof ename);
strncpy(ename, header.name, header.nlen);
if (ENameLen(ename) > 31)
{
error("encoded name > 31 characters");
}
EtoIName(ename, iname);
finderInfo = (fileFinderInfo *) finfo.fi_fndr;
bcopy(header.type, finderInfo->fdType, 4);
bcopy(header.creator, finderInfo->fdCreator, 4);
finderInfo->fdFlags = ((header.flags << 8) | header.flags2) & 0xf8fc;
finfo.fi_magic1 = FI_MAGIC1;
finfo.fi_version = FI_VERSION;
finfo.fi_magic = FI_MAGIC;
finfo.fi_bitmap = FI_BM_MACINTOSHFILENAME;
finfo.fi_macfilename[0] = header.nlen;
bcopy(header.name, finfo.fi_macfilename+1, header.nlen);
fx = fiopen(dir, ".finderinfo/", iname, "w");
if (fx == NULL)
error("cannot create output finder info file '%s'", iname);
if (fwrite(&finfo, sizeof(finfo), 1, fx) < 1)
error("cannot write output finder info file '%s'", iname);
fclose(fx);
bcopy(header.dflen, &temp, sizeof temp);
data = ntohl(temp);
bcopy(header.rflen, &temp, sizeof temp);
resource = ntohl(temp);
fx = fiopen(dir, NULL, iname, "w");
if (fx == NULL)
error("cannot create output data file '%s'", iname);
fcopy(fx, f, data);
fclose(fx);
if (resource > 0)
{
while ((data%128) != 0)
{
(void) fgetc(f);
data++;
}
fx = fiopen(dir, ".resource/", iname, "w");
if (fx == NULL)
error("cannot create output resource file '%s'",
iname);
fcopy(fx, f, resource);
fclose(fx);
}
}
/*
* open the file "dir""ext""file" with mode "mode"
*/
FILE *
fiopen(dir, ext, file, mode)
char *dir, *ext, *file, *mode;
{
char name[1025];
strcpy(name, dir);
if (ext)
strcat(name, ext);
strcat(name, file);
return(fopen(name, mode));
}
/*
* print a nasty message
*/
usage()
{
fprintf(stderr, "Usage: %s [macbinary-file]\n",
prog);
exit(1);
}
/*
* copy length bytes from fin to fout
*/
fcopy(fout, fin, length)
FILE *fin, *fout;
unsigned length;
{
char buffer[4096];
register unsigned l;
while (length > 0) {
l = sizeof buffer;
if (l > length)
l = length;
l = fread(buffer, 1, l, fin);
if (l > 0) {
if (fwrite(buffer, 1, l, fout) != l)
error("error writing output file");
} else break;
length -= l;
}
}
/*
* print another nasty message and quit
*/
error(s, a, b, c, d, e, f)
char *s;
{
fprintf(stderr, "%s: ", prog);
fprintf(stderr, s, a, b, c, d, e, f);
fprintf(stderr, "\n");
exit(2);
}
void
EtoIName(en,inp)
register byte *en; /* max is 31 or so */
char *inp;
{
byte c; /* unsigned char */
register char *in = inp;
register int cnt = 0;
while ((c = *en++) != '\0') {
if (isascii(c) && !iscntrl(c) && isprint(c) && c != '/') {
*in++ = c;
cnt++;
} else {
/* must convert to */
*in++ = ':'; /* : */
*in++ = hexdigits[(c >> 4) & 0xf];
*in++ = hexdigits[(c & 0xf)];
cnt += 3;
}
}
*in++ = '\0';
}
/*
* Given an internal file name, compute the length of the external
* file name
*/
int
ENameLen(in)
register char *in;
{
register int len = 0;
register char c;
register char c2;
while ((c = *in++) != '\0') {
if (c != ':')
len++;
else {
/* must convert to external form */
if ((c = *in++) == '\0' || (c2 = *in++) == '\0') {
len++;
if (c != '\0')
len++;
break; /* done with while */
}
if (index(hexdigits,c) == NULL || index(hexdigits,c2) == NULL)
len += 3;
else
len++;
}
}
return(len);
}