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); }