home *** CD-ROM | disk | FTP | other *** search
- /* Copyright 1988, Gail Zacharias. All rights reserved.
- * Permission is hereby granted to copy, reproduce, redistribute or
- * otherwise use this software provided there is no monetary profit
- * gained specifically from its use or reproduction, it is not sold,
- * rented, traded or otherwise marketed, and this copyright notice
- * and the software version number is included prominently in any copy
- * made.
- * This is mtar version 1.0.
- *
- * Send comments, suggestions, bug reports (not bloody likely), feature
- * requests, etc. to gz@entity.com.
- *
- * Modified by Sak W (sw@network-analysis-ltd.co.uk) to compile with
- * MPW 3.2 (mtar version 1.0.1).
- */
-
- char *Program, *Version = "1.0.1";
-
- #include <stdio.h>
- #include <files.h>
- #include <errors.h>
- #include <errno.h>
- #include <ioctl.h>
-
- StringPtr c2pstr();
- char *strchr(), *strcpy(), *strncpy(), *p2cstr();
-
- /* Sak W mod */
- #define TEXT 'TEXT'
-
- /* The do {} while(0) is for syntactic reasons. MPW C will optimize it out. */
- #define mcopy(dest, src, len) \
- do { char *_dp = (char *)(dest), *_sp = (char *)(src); \
- int _i = (len); \
- while (--_i>=0) *_dp++ = *_sp++; \
- } while(0)
-
- #define fillmem(dest, ch, len) \
- do { char *_dp = (char *)(dest); \
- int _i = (len); \
- while (--_i>=0) *_dp++ = (ch); \
- } while (0)
-
- struct {
- char name[100];
- char mode[8];
- char uid[8];
- char gid[8];
- char size[12];
- char mtime[12];
- char chksum[8];
- char linkflag;
- char linkname[100];
- char magic[8];
- char uname[32];
- char gname[32];
- char devmajor[8];
- char devminor[8];
- char fill[167];
- } tarh;
-
- #define tarsz(n) (((n)+511L) & -512L)
-
- struct {
- unsigned char nlen;
- char name[63];
- FInfo finfo;
- char protected;
- char zero;
- long dflen;
- long rflen;
- long cdate;
- long mdate;
- /* char unused[29]; */
- } macbinh;
-
- #define macbinsz(n) (((n)+127L) & -128L)
-
- static HFileInfo statb;
-
- int binary = 0,
- dataonly = 0,
- verbose = 0;
-
- int dirmode = 0777,
- filemode = 0666;
-
- char *uname = "root",
- *gname = "group";
-
- FILE *tarf = (FILE *) NULL;
-
- #define writeblock(p,len) fwrite((p), 1, (len), tarf)
-
- /* Unfortunately, the Mac keeps only local time, so this will be off by
- the time zone... */
- #define UNIXTIME 2082844800L /* Jan 1, 1970 00:00:00 */
-
-
- main (argc, argv)
- char **argv;
- {
- char *defalt[2];
- Program = argv[0];
- while (--argc > 0 && **++argv == '-') {
- char *argp = &argv[0][1];
- do switch (*argp++) {
- case 'b': dataonly = 1; binary = 1; break;
- case 'u': dataonly = 1; binary = 0; break;
- case 'v': verbose = 1; break;
- case 'o': if (*argp == '\0') {
- if (--argc == 0) goto badarg;
- argp = *++argv;
- }
- uname = argp;
- argp = "";
- break;
- case 'g': if (*argp == '\0') {
- if (--argc == 0) goto badarg;
- argp = *++argv;
- }
- gname = argp;
- argp = "";
- break;
- case 'f': if (tarf) goto badarg;
- if (*argp == '\0') {
- if (--argc == 0) goto badarg;
- argp = *++argv;
- }
- if (!strcmp(argp, "-")) tarf = stdout;
- else if (!(tarf = fopen(argp, "w")))
- fatal("Cannot open %s for writing.", argp);
- argp = "";
- break;
- default: goto badarg;
- } while (*argp);
- }
- if (argc <= 0) {
- defalt[0] = ":";
- defalt[1] = (char *) NULL;
- argv = defalt;
- }
- if (!tarf) tarf = stdout;
- tarfiles(argv);
- fflush(tarf);
- if (ferror(tarf)) {
- if (errno == ENOSPC) fatal("Out of disk space");
- else fatal("Write error");
- }
- if (tarf != stdout) fclose(tarf);
- return 0;
-
- badarg:
- fprintf(stderr, "mtar Version %s, by gz@entity.com. Usage: \n", Version);
- fprintf(stderr, "%s [-vbu] [-o uname] [-g gname] [-f tarfile] files and dirs...\n", Program);
- fprintf(stderr, "Creates a tar archive of the named files.\n\
- -v = verbose: list names of files as store them.\n\
- -b = store only data forks of files.\n\
- -u = like -b, but convert CR to LF in TEXT files.\n\
- -o = set unix owner of files to uname (default 'root').\n");
- fprintf(stderr, " -g = set unix group of files to gname (default 'group').\n\
- -f tarfile = write output to tarfile (instead of standard output).\n\
- -H = show this help message.\n\
- If neither -u nor -b flags are given, stores both forks of each file (as well\n\
- as the mac name, type, creator and dates) using macbinary format.\n\
- If no files are specified, tars the current default directory.\n\n\
- This is freeware. If you paid money for this program, you got ripped off.\n");
- return 2;
- }
-
- tarfiles (files)
- char **files;
- {
- while (*files) {
- if (strlen(*files) >= 100) nametoolong(*files);
- statf(*files);
- if (statb.ioFlAttrib & ioDirMask) {
- statb.ioVRefNum = getvrefnum(*files);
- tardir(*files);
- }
- else {
- char *cp = *files+strlen(*files);
- while (cp != *files && cp[-1] != ':') --cp;
- if ((macbinh.nlen = strlen(cp)) >= 64) nametoolong(*files);
- strcpy(macbinh.name, cp);
- tarfile(*files);
- }
- ++files;
- }
- fillmem(&tarh, 0, 512);
- writeblock(&tarh, 512);
- }
-
- tardir (dname)
- char *dname;
- {
- char name[256];
- long dirid = statb.ioDirID;
- int index = 0;
- int dlen = strlen(dname);
- tarheader(dname, 0);
- if (strchr(dname, ':')) strcpy(name, dname);
- else {
- name[0] = ':';
- strcpy(&name[1], dname);
- dlen++;
- }
- if (name[dlen-1] != ':') name[dlen++] = ':';
- while (1) {
- statb.ioFDirIndex = ++index;
- statb.ioDirID = dirid;
- statb.ioNamePtr = &macbinh.nlen;
- if (PBGetCatInfo((CInfoPBPtr)&statb, 0) || statb.ioResult) {
- if (statb.ioResult != fnfErr) pbsyserr(&statb);
- break;
- }
- strncpy(&name[dlen], macbinh.name, macbinh.nlen);
- name[dlen+macbinh.nlen] = '\0';
- if (macbinh.nlen >= 64 || (dlen + macbinh.nlen) >= 100) nametoolong(name);
- if (statb.ioFlAttrib & ioDirMask) tardir(name);
- else tarfile(name);
- }
- }
-
- tarfile (fname)
- char *fname;
- {
- if (statb.ioFRefNum) {
- long refnum;
- if (ioctl(fileno(tarf), FIOREFNUM, &refnum) >= 0 && refnum == (long) statb.ioFRefNum)
- return 0;
- fprintf(stderr, "%s: Warning: Somebody has \"%s\" open. You may lose.\n", Program, fname);
- }
- if (dataonly) tardata(fname);
- else tarmacbin(fname);
- }
-
- tardata (fname)
- char *fname;
- {
- IOParam pb;
- tarheader(fname, statb.ioFlLgLen);
- if (verbose) fprintf(stderr, "X %s (%ld bytes)\n", tarh.name, statb.ioFlLgLen);
- pb.ioVRefNum = 0;
- pb.ioVersNum = 0;
- pb.ioPermssn = fsRdPerm;
- pb.ioMisc = 0;
- pb.ioNamePtr = c2pstr(fname);
- if (PBOpen((ParmBlkPtr)&pb, 0)) pbsyserr(&pb);
- writefork(&pb, statb.ioFlLgLen, 0);
- p2cstr(fname);
- }
-
- tarmacbin(fname)
- char *fname;
- {
- IOParam pb;
- long fsize = macbinsz(statb.ioFlLgLen)+macbinsz(statb.ioFlRLgLen)+128L;
- tarheader(fname, fsize);
- if (verbose)
- fprintf(stderr, "Macbin %s (%ld+%ld bytes)\n",
- tarh.name, statb.ioFlLgLen, statb.ioFlRLgLen);
- macbinheader();
- pb.ioVRefNum = 0;
- pb.ioVersNum = 0;
- pb.ioPermssn = fsRdPerm;
- pb.ioMisc = 0;
- pb.ioNamePtr = c2pstr(fname);
- if (PBOpen((ParmBlkPtr)&pb, 0)) pbsyserr(&pb);
- writefork(&pb, statb.ioFlLgLen, 1);
- pb.ioVRefNum = 0;
- pb.ioVersNum = 0;
- pb.ioPermssn = fsRdPerm;
- pb.ioMisc = 0;
- if (PBOpenRF((ParmBlkPtr)&pb, 0)) pbsyserr(&pb);
- writefork(&pb, statb.ioFlRLgLen, 1);
- if (fsize & 511L) writeblock(&tarh, 512 - (fsize & 511L));
- p2cstr(fname);
- }
-
- macbinheader()
- {
- fillmem(&macbinh.name[macbinh.nlen], 0, 63-macbinh.nlen);
- mcopy(&macbinh.finfo, &statb.ioFlFndrInfo, sizeof(FInfo));
- macbinh.protected = 0;
- macbinh.zero = 0;
- macbinh.dflen = statb.ioFlLgLen;
- macbinh.rflen = statb.ioFlRLgLen;
- macbinh.cdate = statb.ioFlCrDat;
- macbinh.mdate = statb.ioFlMdDat;
- fillmem(&tarh, 0, 128);
- mcopy(&tarh.name[1], &macbinh, sizeof(macbinh));
- writeblock(&tarh, 128);
- }
-
- writefork (pb, fsize, macbinp)
- IOParam *pb;
- long fsize;
- {
- int blocksz = (macbinp ? 128 : 512);
- pb->ioPosMode = fsAtMark;
- pb->ioBuffer = (Ptr)&tarh;
- pb->ioReqCount = blocksz;
- while (fsize) {
- if (fsize < pb->ioReqCount) pb->ioReqCount = fsize;
- fsize -= pb->ioReqCount;
- if (PBRead((ParmBlkPtr)pb, 0) || pb->ioActCount != pb->ioReqCount) {
- int err = pb->ioResult;
- (void) PBClose((ParmBlkPtr)pb, 0);
- pb->ioResult = err;
- pbsyserr(pb);
- }
- if (!macbinp && !binary && statb.ioFlFndrInfo.fdType == TEXT) {
- char *cp = pb->ioBuffer;
- int i = pb->ioActCount;
- while (i) {
- if (*cp == ('M'-'@')) *cp = ('J'-'@');
- --i, ++cp;
- }
- }
- writeblock(pb->ioBuffer, blocksz);
- }
- if (PBClose((ParmBlkPtr)pb, 0)) pbsyserr(pb);
- }
-
- tarheader (fname, fsize)
- char *fname;
- long fsize;
- {
- int chksum = 0, i;
- fillmem(&tarh, 0, 512);
- mac2unix(tarh.name, fname);
- if (statb.ioFlAttrib & ioDirMask)
- if (tarh.name[strlen(tarh.name)-1] != '/')
- tarh.name[strlen(tarh.name)] = '/';
- numstr(tarh.mode, ((statb.ioFlAttrib & ioDirMask) ? dirmode : filemode), 8);
- numstr(tarh.uid, 0, 8);
- numstr(tarh.gid, 0, 8);
- numstr(tarh.size, fsize, 12);
- numstr(tarh.mtime, statb.ioFlMdDat - UNIXTIME, 12);
- fillmem(tarh.chksum, ' ', 8);
- tarh.linkflag = ((statb.ioFlAttrib & ioDirMask) ? '5' : '0');
- strcpy(tarh.magic, "ustar ");
- strcpy(tarh.uname, uname);
- strcpy(tarh.gname, gname);
- for(i=0; i<512; ++i) chksum += (unsigned char)tarh.name[i];
- numstr(tarh.chksum, chksum, 8);
- writeblock(&tarh, 512);
- }
-
- /* Don't allow absolute names. "HD:foo:bar" becomes "./foo/bar" */
- mac2unix(uname, mname)
- char *uname, *mname;
- {
- char *dp = uname, *cp;
- if (cp = strchr(mname, ':')) *dp++ = '.', *dp++ = '/', ++cp;
- else cp = mname;
- while (1) {
- while (*cp == ':') *dp++ = '.', *dp++ = '.', *dp++ = '/', ++cp;
- while (*cp && *cp != ':') if ((*dp++ = *cp++) == '/') dp[-1] = ':';
- if (!*cp++) break;
- *dp++ = '/';
- }
- for (dp = uname; *dp; ++dp) if (*dp == ' ') *dp = '_';
- if (strlen(uname) >= 100) nametoolong(mname);
- }
-
- numstr (p, num, count)
- char *p;
- {
- p[--count] = '\0';
- if (count != 11) p[--count] = ' ';
- if (num < 0) {
- *p++ = '-';
- --count;
- num = -num;
- }
- while (count) {
- p[--count] = '0' + (num & 7);
- num >>= 3;
- }
- }
-
- statf (fname)
- char *fname;
- {
- char name[256];
- statb.ioNamePtr = c2pstr(strcpy(name, fname));
- statb.ioFVersNum = 0;
- statb.ioVRefNum = 0;
- statb.ioFDirIndex = 0;
- statb.ioDirID = 0;
- if (PBGetCatInfo((CInfoPBPtr)&statb, 0) || statb.ioResult) pbsyserr(&statb);
- statb.ioNamePtr = NULL;
- }
-
- getvrefnum (fname)
- char *fname;
- {
- HVolumeParam pb;
- char name[256];
- pb.ioNamePtr = c2pstr(strcpy(name, fname));
- pb.ioVRefNum = 0;
- pb.ioVolIndex = 0;
- if (PBHGetVInfo((HParmBlkPtr)&pb, 0) || pb.ioResult) pbsyserr(&pb);
- return pb.ioVRefNum;
- }
-
- nametoolong (name)
- char *name;
- {
- fatal("\"%s\" - name too long", name);
- }
-
- pbsyserr (pb)
- IOParam *pb;
- {
- int err = pb->ioResult;
- char *name = pb->ioNamePtr;
- p2cstr(name);
- if (err == fnfErr) fatal("%s - File not found", name);
- else if (err == nsvErr) fatal("%s - No such volume", name);
- else if (err == tmfoErr) fatal("%s - Too many files open", name);
- else if (err == permErr) fatal("%s - Permissions error", name);
- else if (err == dupFNErr) fatal("%s - Duplicate filename", name);
- else if (err == eofErr) fatal("%s - Premature end of file", name);
- else fatal("%s - Error #%d", name, err);
- }
-
- fatal(fmt, arg1, arg2, arg3, arg4, arg5, arg6)
- char *fmt, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
- {
- if (tarf && tarf != stdout) fclose(tarf);
- fprintf(stderr, "%s: ", Program);
- fprintf(stderr, fmt, arg1, arg2, arg3, arg4, arg5, arg6);
- fprintf(stderr, "\n");
- exit(2);
- }
-
-