X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=nt%2Fminitar.c;fp=nt%2Fminitar.c;h=d5e3d40ee31ed85ad16f3116d8b3e8d01f2a07c9;hb=9a9fedfd2473568f4827f6295de7b03259b160e5;hp=0000000000000000000000000000000000000000;hpb=97badae7fa41c4bd3e92511ff7b16389e646e022;p=chise%2Fxemacs-chise.git- diff --git a/nt/minitar.c b/nt/minitar.c new file mode 100644 index 0000000..d5e3d40 --- /dev/null +++ b/nt/minitar.c @@ -0,0 +1,246 @@ + +/* 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 +#include +#include +#include +#include +#ifdef WIN32_NATIVE +# include /* For mkdir */ +#endif + +#include + +static void +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 + +static 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 */ + +static int +makepath (char *path) +{ + char tmp[MAXNAMELEN]; + char *cp; + + 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; +#ifdef WIN32_NATIVE + if (mkdir (tmp)) +#else + if (mkdir (tmp, 0777)) +#endif + { + if (errno == EEXIST) + continue; + else + return -1; + } + } + return 0; +} + + + +int +main (int argc, char **argv) +{ + char fullname[MAXNAMELEN]; + char *basedir = "."; + char *tarfile; + 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"); + exit (-2); + } + + 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); + exit (-2); + 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); + } + if (size==0) /* file of size 0 is done */ + in_block = 0; + } + } + 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); + exit (-2); + } + size -= nbytes; + if (size==0) + in_block = 0; + } + } + return 0; +} + + +