home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
source
/
sit_shar
/
sit.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-05-20
|
6KB
|
284 lines
/*
* sit - Stuffit for UNIX
* Puts unix data files into stuffit archive suitable for downloading
* to a Mac. Automatically processes files output from xbin.
*
* Reverse engineered from unsit by Allan G. Weber, which was based on
* macput, which was based on ...
* Just like unsit this uses the host's version of compress to do the work.
*
* Examples:
* 1) take collection of UNIX text files and make them LSC text files
* when uncompressed on the mac:
* sit -u -T TEXT -C KAHL file ...
* 2) Process output from xbin:
* xbin file1 (produces FileOne.{info,rsrc,data})
* sit file1
*
* Tom Bereiter
* ..!{rutgers,ames}!cs.utexas.edu!halley!rolex!twb
*/
#define BSD
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include "sit.h"
#ifdef BSD
#include <sys/time.h>
#include <sys/timeb.h>
#else
#include <time.h>
extern long timezone;
#endif
#ifndef min
#define min(a,b) ((a)<(b)?(a):(b))
#endif
/* Mac time of 00:00:00 GMT, Jan 1, 1970 */
#define TIMEDIFF 0x7c25b080
struct sitHdr sh;
struct fileHdr fh;
char buf[BUFSIZ];
char *defoutfile = "archive.sit";
int ofd;
ushort crc;
int clen;
int rmfiles;
int unixf;
char *Creator, *Type;
usage() { fprintf(stderr,"Usage: sit file\n"); }
extern char *optarg;
extern int optind;
main(argc,argv) char **argv; {
int i,n;
int total, nfiles;
int c;
while ((c=getopt(argc, argv, "ro:uC:T:")) != EOF)
switch (c) {
case 'r':
rmfiles++; /* remove files when done */
break;
case 'o': /* specify output file */
defoutfile = optarg;
break;
case 'u': /* unix file -- change '\n' to '\r' */
unixf++;
break;
case 'C': /* set Mac creator */
Creator = optarg;
break;
case 'T': /* set Mac file type */
Type = optarg;
break;
case '?':
usage();
exit(1);
}
if ((ofd=creat(defoutfile,0644))<0) {
perror(defoutfile);
exit(1);
}
/* empty header, will seek back and fill in later */
write(ofd,&sh,sizeof sh);
for (i=optind; i<argc; i++) {
n = put_file(argv[i]);
if (n) {
total += n;
nfiles++;
}
}
lseek(ofd,0,0);
total += sizeof(sh);
/* header header */
strncpy(sh.sig1,"SIT!",4);
cp2(nfiles,sh.numFiles);
cp4(total,sh.arcLen);
strncpy(sh.sig2,"rLau",4);
sh.version = 1;
write(ofd,&sh,sizeof sh);
}
put_file(name)
char name[];
{
struct stat st;
struct infohdr ih;
int i,n,fd;
long fpos1, fpos2;
char nbuf[256], *p;
int fork=0;
long tdiff;
struct tm *tp;
#ifdef BSD
struct timeb tbuf;
#else
long bs;
#endif
fpos1 = lseek(ofd,0,1); /* remember where we are */
/* write empty header, will seek back and fill in later */
bzero(&fh,sizeof fh);
write(ofd,&fh,sizeof fh);
/* look for resource fork */
strcpy(nbuf,name);
strcat(nbuf,".rsrc");
if (stat(nbuf,&st)>=0 && st.st_size) { /* resource fork exists */
dofork(nbuf);
cp4(st.st_size,fh.rLen);
cp4(clen,fh.cRLen);
cp2(crc,fh.rsrcCRC);
fh.compRMethod = lpzComp;
fork++;
}
if (rmfiles) unlink(nbuf); /* ignore errors */
/* look for data fork */
st.st_size = 0;
strcpy(nbuf,name);
if (stat(nbuf,&st)<0) { /* first try plain name */
strcat(nbuf,".data");
stat(nbuf,&st);
}
if (st.st_size) { /* data fork exists */
dofork(nbuf);
cp4(st.st_size,fh.dLen);
cp4(clen,fh.cDLen);
cp2(crc,fh.dataCRC);
fh.compDMethod = lpzComp;
fork++;
}
if (fork == 0) {
fprintf(stderr,"%s: no data or resource files\n",name);
return 0;
}
if (rmfiles) unlink(nbuf); /* ignore errors */
/* look for .info file */
strcpy(nbuf,name);
strcat(nbuf,".info");
if ((fd=open(nbuf,0))>=0 && read(fd,&ih,sizeof(ih))==sizeof(ih)) {
strncpy(fh.fName, ih.name,64);
strncpy(fh.fType, ih.type, 4);
strncpy(fh.fCreator, ih.creator, 4);
strncpy(fh.FndrFlags, ih.flag, 2);
strncpy(fh.cDate, ih.ctime, 4);
strncpy(fh.mDate, ih.mtime, 4);
}
else { /* no info file so fake it */
strncpy(&fh.fName[1], name,63); fh.fName[0] = min(strlen(name),63);
/* default to LSC text file */
strncpy(fh.fType, Type ? Type : "TEXT", 4);
strncpy(fh.fCreator, Creator ? Creator : "KAHL", 4);
/* convert unix file time to mac time format */
#ifdef BSD
ftime(&tbuf);
tp = localtime(&tbuf.time);
tdiff = TIMEDIFF - tbuf.timezone * 60;
if (tp->tm_isdst)
tdiff += 60 * 60;
#else
/* I hope this is right! -andy */
time(&bs);
tp = localtime(&bs);
tdiff = TIMEDIFF - timezone;
if (tp->tm_isdst)
tdiff += 60 * 60;
#endif
cp4(st.st_ctime + tdiff, fh.cDate);
cp4(st.st_mtime + tdiff, fh.mDate);
}
close(fd);
if (rmfiles) unlink(nbuf); /* ignore errors */
crc = updcrc(0,&fh,(sizeof fh)-2);
cp2(crc, fh.hdrCRC);
fpos2 = lseek(ofd,0,1); /* remember where we are */
lseek(ofd,fpos1,0); /* seek back over file(s) and header */
write(ofd,&fh,sizeof fh); /* write back header */
fpos2=lseek(ofd,fpos2,0); /* seek forward file */
return (fpos2 - fpos1);
}
dofork(name)
char name[];
{
FILE *fs;
int n, fd, ufd;
char *p;
if ((fd=open(name,0))<0) {
perror(name);
return 0;
}
if (unixf) /* build conversion file */
if ((ufd=creat("sit+temp",0644))<0) {
perror("sit+temp");
return 0;
}
/* do crc of file: */
crc = 0;
while ((n=read(fd,buf,BUFSIZ))>0) {
if (unixf) { /* convert '\n' to '\r' */
for (p=buf; p<&buf[n]; p++)
if (*p == '\n') *p = '\r';
write(ufd,buf,n);
}
crc = updcrc(crc,buf,n);
}
close(fd);
/*
* open pipe to compress file
* If a unix file ('\n' -> '\r' conversion) 'sit+temp' will be a new copy
* with the conversion done. Otherwise, 'sit+temp' is just a link to
* the input file.
*/
if (unixf)
close(ufd);
else link(name,"sit+temp");
fs = popen("compress -c -n -b 14 sit+temp","r");
if (fs == NULL) {
perror(name);
return 0;
}
/* write out compressed file */
clen = 0;
while ((n=fread(buf,1,BUFSIZ,fs))>0) {
write(ofd,buf,n);
clen += n;
}
pclose(fs);
unlink("sit+temp");
}
cp2(x,dest)
unsigned short x;
char dest[];
{
dest[0] = x>>8;
dest[1] = x;
}
cp4(x,dest)
unsigned long x;
char dest[];
{
dest[0] = x>>24;
dest[1] = x>>16;
dest[2] = x>>8;
dest[3] = x;
}