mwm@violet.berkeley.edu (Mike Meyer) (01/13/87)
Ok, here's the source to tarsplit.c. It's a straight port of the OS/9
program that does the same thing. Major gotcha: tarsplit doesn't do
name translation, so '.' and '..' don't work. For instance, you can't
do "tar cf - ." on the Unix end and then take it apart on the Amiga,
as "." isn't a recognized file name.
Recomended useage: cd to the parent of the directory you want to
download, and do:
tar cbf 1 download.tar download_dir
This will tar download_dir into download.tar. Setting the blocksize to
1 causes minimal wasted space in the image. I haven't tried
compressing the result; gotta do that soon. After downloading it, cd
to the place you want the directory to appear in, and do "tarsplit
download.tar" (or whever you put it). For small files (*NOT* the mg
sources!), putting things in ram: works fine.
For those who don't want to compile it, or don't trust your compiler,
I put the binary in the pub/amiga directory on ucbvax. Matt should
feel free to delete it, though. I didn't uuencode it, and I didn't
touch Matt's index.
Note: This has not been tested under either Lattice 3.10, or any
version of MANX. It's also the second posting, having been posted
nearly a year ago; right after I did it.
Finally, I've heard rumors of a PD tar. If I can find a copy, I'll
probably try and post it, but not do the port.
<mike
P.S. - since he doesn't mention it in the file, I'll do it here. The
original OS/9 version of this was written by James Jones (the hacker
from Mars :-). James can currently be found as jejones@mcrware.UUCP.
-------------------- cut here, only one file --------------------
/*
* TarSplit -- split up tar files (creating directories as needed)
*
* usage: TarSplit [pathname]
*
* semantics: splits up tar file taken from stdin (or pathname, if
* specified) and creates the files therein under the working data
* directory.
*/
#include <stdio.h>
#ifdef AMIGA
#include <exec/types.h>
typedef int bool ;
bool ChkSumOK() ;
#include <libraries/dosextens.h>
#else
#include <modes.h>
#include <bool.h>
#define DIRMODE (S_IREAD | S_IWRITE | S_IEXEC | S_IOREAD | S_IOEXEC)
#endif
#define TBLOCK 512
#define NAMSIZ 100
union hblock {
char dummy[TBLOCK];
struct header {
char name[NAMSIZ];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char linkflag;
char linkname[NAMSIZ];
} dbuf;
};
#define BLKSIZE (sizeof (union hblock))
#define HARDLINK '1'
#define SYMBLINK '2'
#define NORMAL '\0'
main(argc, argv)
int argc;
char *argv[];
{
FILE *TarFP;
union hblock TarBlock;
#ifndef AMIGA
/* make the compiler happy about formatted I/O for longs... */
pflinit();
#endif
switch(argc) {
#ifndef AMIGA
case 1:
TarFP = stdin;
break;
#endif
case 2:
if ((TarFP = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "TarSplit: can't open %s\n", argv[1]);
exit(1);
}
break;
default:
fprintf(stderr, "usage: TarSplit [pathname]\n");
exit(1);
}
for (;;) {
if (fread(&TarBlock, BLKSIZE, 1, TarFP) == NULL) {
fprintf(stderr, "TarSplit: premature EOF\n");
exit(1);
} else if (IsZero(&TarBlock)) {
while (fread(&TarBlock, BLKSIZE, 1, TarFP) != NULL)
;
break;
} else
DoFile(&TarBlock, TarFP);
}
}
bool
IsZero(block)
union hblock *block;
{
int i;
char *cblock;
cblock = block->dummy;
for (i = 0; i < TBLOCK; i++)
if (*cblock++ != '\0')
return(FALSE);
return (TRUE);
}
DoFile(block, TarFP)
union hblock *block;
FILE *TarFP;
{
long FSize;
char FName[NAMSIZ], *RefName;
int i;
bool IsDir, OpenOK;
FILE *NewFP;
if (!ChkSumOK(block)) {
fprintf(stderr, "TarSplit: bad checksum, name %s?\n",
block->dbuf.name);
exit(1);
}
switch(block->dbuf.linkflag) {
case HARDLINK:
case SYMBLINK:
fprintf(stderr, "TarSplit: can't handle links\n");
exit(1);
case NORMAL:
break;
default:
fprintf(stderr, "TarSplit: unknown linkflag\n");
exit(1);
}
#ifdef AMIGA
if (sscanf(block->dbuf.size, "%12lo", &FSize) != 1) {
#else
if (sscanf(block->dbuf.size, "%12O", &FSize) != 1) {
#endif
fprintf(stderr, "TarSplit: bad size\n");
exit(1);
}
for (i = 0, RefName = block->dbuf.name; *RefName; i++, RefName++)
FName[i] = *RefName;
if (IsDir = (*(RefName - 1) == '/')) {
FName[i - 1] = '\0';
if (strcmp(FName, ".") == 0)
OpenOK = TRUE;
else
#ifdef AMIGA
{
struct FileLock *Lock, *CreateDir() ;
OpenOK = (Lock = CreateDir(FName)) != 0 ;
UnLock(Lock) ;
}
#else
OpenOK = mknod(FName, DIRMODE) == 0;
#endif
} else {
FName[i] = '\0';
OpenOK = (NewFP = fopen(FName, "w")) != NULL;
}
if (!OpenOK) {
fprintf(stderr, "TarSplit: can't create %s\n", FName);
exit(1);
}
for (; FSize > 0; FSize -= TBLOCK) {
if (fread(block, BLKSIZE, 1, TarFP) == NULL) {
fprintf(stderr, "TarSplit: premature EOF\n");
exit(1);
}
if (!IsDir)
fwrite(block->dummy, 1,
(FSize > TBLOCK ? TBLOCK : (int) FSize), NewFP);
}
if (!IsDir)
fclose(NewFP);
}
bool
ChkSumOK(block)
union hblock *block;
{
long Accum, ChkSumVal;
int i;
#ifdef AMIGA
sscanf(block->dbuf.chksum, "%8lo", &ChkSumVal);
#else
sscanf(block->dbuf.chksum, "%8O", &ChkSumVal);
#endif
for (i = 0; i < 8; i++)
block->dbuf.chksum[i] = ' ';
Accum = 0;
for (i = 0; i < TBLOCK; i++)
Accum += 0xff & block->dummy[i];
return(Accum == ChkSumVal);
}