XEmacs 21.2.9
[chise/xemacs-chise.git.1] / nt / minitar.c
diff --git a/nt/minitar.c b/nt/minitar.c
new file mode 100644 (file)
index 0000000..4d89875
--- /dev/null
@@ -0,0 +1,211 @@
+
+/* 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;
+    }
+  }
+}      
+
+
+
+