--- /dev/null
+
+/* Minitar: extract .tar.gz files on Win32 platforms.
+ Uses zlib for decompression.
+
+ This is very simple-minded, it ignores checksums, and any type of file
+ that is not a plain file or a directory. Nonetheless it is useful.
+
+ Author: Charles G. Waldman (cgw@pgt.com), Aug 4 1998
+
+ This file is placed in the public domain; you can
+ do whatever you like with it. There is NO WARRANTY.
+ If it breaks, you get to keep both pieces */
+
+
+#include <stdio.h>
+#include <Errno.h>
+
+#include <zlib.h>
+
+Usage(char *name)
+{
+ fprintf(stderr,"Usage: %s file.tar.gz [base-dir]\n",name);
+ fprintf(stderr,"\tExtracts the contents compressed tar file to base-dir\n");
+ exit(-1);
+}
+
+
+#define BLOCKSIZE 512
+#define MAXNAMELEN 1024
+
+int octal(char *str)
+{
+ int ret = -1;
+ sscanf(str,"%o",&ret);
+ return ret;
+}
+
+/* this is like mkdir -p, except if there is no trailing slash,
+ the final component is assumed to be a file, rather than a
+ path component, so it is not created as a directory */
+
+int makepath(char *path)
+{
+ char tmp[MAXNAMELEN];
+ char *cp;
+ extern int errno;
+
+ for (cp=path; cp; cp = (char*)strchr(cp+1,'/')){
+ if (!*cp)
+ break;
+ if (*cp != '/')
+ continue;
+ strncpy(tmp, path, cp-path);
+ tmp[cp-path] = '\0';
+ if (strlen(tmp) == 0)
+ continue;
+ if (mkdir(tmp,0777)){
+ if (errno == EEXIST)
+ continue;
+ else
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+
+
+main(int argc, char **argv)
+{
+ char fullname[MAXNAMELEN];
+ char *basedir = ".";
+ char *tarfile;
+ char *cp;
+ int size;
+ char osize[13];
+ char name[101];
+ char magic[7];
+ char type;
+
+ gzFile *infile = (gzFile*)0;
+ FILE *outfile = (FILE*)0;
+
+ char block[BLOCKSIZE];
+ int nbytes, nread, nwritten;
+
+ int in_block = 0;
+ int directory = 0;
+
+ if (argc < 2 || argc > 3)
+ Usage(argv[0]);
+
+ tarfile = argv[1];
+ if (argc==3)
+ basedir = argv[2];
+
+ if (! (infile = gzopen(tarfile,"rb"))){
+ fprintf(stderr,"Cannot open %s\n", tarfile);
+ exit(-2);
+ }
+
+ while (1){
+
+
+ nread = gzread(infile,block,512);
+
+ if (!in_block && nread == 0)
+ break;
+
+ if (nread != BLOCKSIZE){
+ fprintf(stderr,"Error: incomplete block read. Exiting.\n");
+ exit(-2);
+ }
+
+ if (!in_block){
+ if (block[0]=='\0') /* We're done */
+ break;
+
+ strncpy(magic,block+257,6);
+ magic[6] = '\0';
+ if (strcmp(magic,"ustar ")){
+ fprintf(stderr,
+ "Error: incorrect magic number in tar header. Exiting\n");
+ }
+
+ strncpy(name,block,100);
+ name[100] = '\0';
+ sprintf(fullname,"%s/%s",basedir,name);
+ printf("%s\n",fullname);
+ type = block[156];
+
+ switch(type){
+ case '0':
+ case '\0':
+ directory = 0;
+ break;
+ case '5':
+ directory = 1;
+ break;
+ default:
+ fprintf(stderr,"Error: unknown type flag %c. Exiting.\n",type);
+ break;
+ }
+
+ if (directory){
+ in_block = 0;
+
+ /* makepath will ignore the final path component, so make sure
+ dirnames have a trailing slash */
+
+ if (fullname[strlen(fullname)-1] != '/')
+ strcat(fullname,"/");
+ if (makepath(fullname)){
+ fprintf(stderr, "Error: cannot create directory %s. Exiting.\n",
+ fullname);
+ exit(-2);
+ }
+ continue;
+ } else { /*file */
+ in_block = 1;
+ if (outfile){
+ if (fclose(outfile)){
+ fprintf(stderr,"Error: cannot close file %s. Exiting.\n",
+ fullname);
+ exit(-2);
+ }
+ outfile = (FILE*)0;
+ }
+
+ if ( !(outfile = fopen(fullname,"wb"))){
+ /*try creating the directory, maybe it's not there */
+ if (makepath(fullname)){
+ fprintf(stderr,"Error: cannot create file %s. Exiting.\n",
+ fullname);
+ exit(-2);
+ }
+ /* now try again to open the file */
+ if (!(outfile = fopen(fullname,"wb"))){
+ fprintf(stderr,"Error: cannot create file %s. Exiting.\n",
+ fullname);
+ exit(-2);
+ }
+ }
+
+ strncpy(osize,block+124,12);
+ osize[12] = '\0';
+ size = octal(osize);
+ if (size<0){
+ fprintf(stderr,"Error: invalid size in tar header. Exiting.\n");
+ exit(-2);
+ }
+ }
+ } else { /* write or continue writing file contents */
+ nbytes = size>512? 512:size;
+
+ nwritten = fwrite(block, 1, nbytes, outfile);
+ if (nwritten != nbytes){
+ fprintf(stderr, "Error: only wrote %d bytes to file %s. Exiting.\n",
+ nwritten, fullname);
+ }
+ size -= nbytes;
+ if (size==0)
+ in_block = 0;
+ }
+ }
+}
+
+
+
+