summaryrefslogtreecommitdiff
path: root/zlib/contrib/untgz/untgz.c
diff options
context:
space:
mode:
Diffstat (limited to 'zlib/contrib/untgz/untgz.c')
-rw-r--r--zlib/contrib/untgz/untgz.c615
1 files changed, 331 insertions, 284 deletions
diff --git a/zlib/contrib/untgz/untgz.c b/zlib/contrib/untgz/untgz.c
index 4a431ff3163..d748b6905bb 100644
--- a/zlib/contrib/untgz/untgz.c
+++ b/zlib/contrib/untgz/untgz.c
@@ -1,8 +1,9 @@
/*
- * untgz.c -- Display contents and/or extract file from
- * a gzip'd TAR file
+ * untgz.c -- Display contents and extract files from a gzip'd TAR file
+ *
* written by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
* adaptation to Unix by Jean-loup Gailly <jloup@gzip.org>
+ * various fixes by Cosmin Truta <cosmint@cs.ubbcluj.ro>
*/
#include <stdio.h>
@@ -10,7 +11,9 @@
#include <string.h>
#include <time.h>
#include <errno.h>
-#include <fcntl.h>
+
+#include "zlib.h"
+
#ifdef unix
# include <unistd.h>
#else
@@ -18,58 +21,54 @@
# include <io.h>
#endif
-#include "zlib.h"
-
#ifdef WIN32
+#include <windows.h>
# ifndef F_OK
-# define F_OK (0)
+# define F_OK 0
# endif
+# define mkdir(dirname,mode) _mkdir(dirname)
# ifdef _MSC_VER
-# define mkdir(dirname,mode) _mkdir(dirname)
# define strdup(str) _strdup(str)
-# define unlink(fn) _unlink(fn)
# define access(path,mode) _access(path,mode)
-# else
-# define mkdir(dirname,mode) _mkdir(dirname)
# endif
#else
# include <utime.h>
#endif
-/* Values used in typeflag field. */
+/* values used in typeflag field */
-#define REGTYPE '0' /* regular file */
-#define AREGTYPE '\0' /* regular file */
-#define LNKTYPE '1' /* link */
-#define SYMTYPE '2' /* reserved */
-#define CHRTYPE '3' /* character special */
-#define BLKTYPE '4' /* block special */
-#define DIRTYPE '5' /* directory */
-#define FIFOTYPE '6' /* FIFO special */
-#define CONTTYPE '7' /* reserved */
+#define REGTYPE '0' /* regular file */
+#define AREGTYPE '\0' /* regular file */
+#define LNKTYPE '1' /* link */
+#define SYMTYPE '2' /* reserved */
+#define CHRTYPE '3' /* character special */
+#define BLKTYPE '4' /* block special */
+#define DIRTYPE '5' /* directory */
+#define FIFOTYPE '6' /* FIFO special */
+#define CONTTYPE '7' /* reserved */
#define BLOCKSIZE 512
struct tar_header
-{ /* byte offset */
- char name[100]; /* 0 */
- char mode[8]; /* 100 */
- char uid[8]; /* 108 */
- char gid[8]; /* 116 */
- char size[12]; /* 124 */
- char mtime[12]; /* 136 */
- char chksum[8]; /* 148 */
- char typeflag; /* 156 */
- char linkname[100]; /* 157 */
- char magic[6]; /* 257 */
- char version[2]; /* 263 */
- char uname[32]; /* 265 */
- char gname[32]; /* 297 */
- char devmajor[8]; /* 329 */
- char devminor[8]; /* 337 */
- char prefix[155]; /* 345 */
- /* 500 */
+{ /* byte offset */
+ char name[100]; /* 0 */
+ char mode[8]; /* 100 */
+ char uid[8]; /* 108 */
+ char gid[8]; /* 116 */
+ char size[12]; /* 124 */
+ char mtime[12]; /* 136 */
+ char chksum[8]; /* 148 */
+ char typeflag; /* 156 */
+ char linkname[100]; /* 157 */
+ char magic[6]; /* 257 */
+ char version[2]; /* 263 */
+ char uname[32]; /* 265 */
+ char gname[32]; /* 297 */
+ char devmajor[8]; /* 329 */
+ char devminor[8]; /* 337 */
+ char prefix[155]; /* 345 */
+ /* 500 */
};
union tar_buffer {
@@ -77,94 +76,148 @@ union tar_buffer {
struct tar_header header;
};
-enum { TGZ_EXTRACT = 0, TGZ_LIST };
+enum { TGZ_EXTRACT, TGZ_LIST, TGZ_INVALID };
-static char *TGZfname OF((const char *));
-void TGZnotfound OF((const char *));
+char *TGZfname OF((const char *));
+void TGZnotfound OF((const char *));
-int getoct OF((char *, int));
-char *strtime OF((time_t *));
-int ExprMatch OF((char *,char *));
+int getoct OF((char *, int));
+char *strtime OF((time_t *));
+int setfiletime OF((char *, time_t));
+int ExprMatch OF((char *, char *));
-int makedir OF((char *));
-int matchname OF((int,int,char **,char *));
+int makedir OF((char *));
+int matchname OF((int, int, char **, char *));
-void error OF((const char *));
-int tar OF((gzFile, int, int, int, char **));
+void error OF((const char *));
+int tar OF((gzFile, int, int, int, char **));
-void help OF((int));
-int main OF((int, char **));
+void help OF((int));
+int main OF((int, char **));
char *prog;
-/* This will give a benign warning */
+const char *TGZsuffix[] = { "\0", ".tar", ".tar.gz", ".taz", ".tgz", NULL };
-static char *TGZprefix[] = { "\0", ".tgz", ".tar.gz", ".tar", NULL };
+/* return the file name of the TGZ archive */
+/* or NULL if it does not exist */
-/* Return the real name of the TGZ archive */
-/* or NULL if it does not exist. */
-
-static char *TGZfname OF((const char *fname))
+char *TGZfname (const char *arcname)
{
static char buffer[1024];
int origlen,i;
-
- strcpy(buffer,fname);
+
+ strcpy(buffer,arcname);
origlen = strlen(buffer);
- for (i=0; TGZprefix[i]; i++)
+ for (i=0; TGZsuffix[i]; i++)
{
- strcpy(buffer+origlen,TGZprefix[i]);
+ strcpy(buffer+origlen,TGZsuffix[i]);
if (access(buffer,F_OK) == 0)
return buffer;
}
return NULL;
}
+
/* error message for the filename */
-void TGZnotfound OF((const char *fname))
+void TGZnotfound (const char *arcname)
{
int i;
- fprintf(stderr,"%s : couldn't find ",prog);
- for (i=0;TGZprefix[i];i++)
- fprintf(stderr,(TGZprefix[i+1]) ? "%s%s, " : "or %s%s\n",
- fname,
- TGZprefix[i]);
+ fprintf(stderr,"%s: Couldn't find ",prog);
+ for (i=0;TGZsuffix[i];i++)
+ fprintf(stderr,(TGZsuffix[i+1]) ? "%s%s, " : "or %s%s\n",
+ arcname,
+ TGZsuffix[i]);
exit(1);
}
-/* help functions */
+/* convert octal digits to int */
+/* on error return -1 */
-int getoct(char *p,int width)
+int getoct (char *p,int width)
{
int result = 0;
char c;
-
- while (width --)
+
+ while (width--)
{
c = *p++;
- if (c == ' ')
- continue;
if (c == 0)
- break;
+ break;
+ if (c == ' ')
+ continue;
+ if (c < '0' || c > '7')
+ return -1;
result = result * 8 + (c - '0');
}
return result;
}
+
+/* convert time_t to string */
+/* use the "YYYY/MM/DD hh:mm:ss" format */
+
char *strtime (time_t *t)
{
struct tm *local;
static char result[32];
local = localtime(t);
- sprintf(result,"%2d/%02d/%4d %02d:%02d:%02d",
- local->tm_mday, local->tm_mon+1, local->tm_year+1900,
- local->tm_hour, local->tm_min, local->tm_sec);
+ sprintf(result,"%4d/%02d/%02d %02d:%02d:%02d",
+ local->tm_year+1900, local->tm_mon+1, local->tm_mday,
+ local->tm_hour, local->tm_min, local->tm_sec);
+ return result;
+}
+
+
+/* set file time */
+
+int setfiletime (char *fname,time_t ftime)
+{
+#ifdef WIN32
+ static int isWinNT = -1;
+ SYSTEMTIME st;
+ FILETIME locft, modft;
+ struct tm *loctm;
+ HANDLE hFile;
+ int result;
+
+ loctm = localtime(&ftime);
+ if (loctm == NULL)
+ return -1;
+
+ st.wYear = (WORD)loctm->tm_year + 1900;
+ st.wMonth = (WORD)loctm->tm_mon + 1;
+ st.wDayOfWeek = (WORD)loctm->tm_wday;
+ st.wDay = (WORD)loctm->tm_mday;
+ st.wHour = (WORD)loctm->tm_hour;
+ st.wMinute = (WORD)loctm->tm_min;
+ st.wSecond = (WORD)loctm->tm_sec;
+ st.wMilliseconds = 0;
+ if (!SystemTimeToFileTime(&st, &locft) ||
+ !LocalFileTimeToFileTime(&locft, &modft))
+ return -1;
+
+ if (isWinNT < 0)
+ isWinNT = (GetVersion() < 0x80000000) ? 1 : 0;
+ hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
+ (isWinNT ? FILE_FLAG_BACKUP_SEMANTICS : 0),
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return -1;
+ result = SetFileTime(hFile, NULL, NULL, &modft) ? 0 : -1;
+ CloseHandle(hFile);
return result;
+#else
+ struct utimbuf settime;
+
+ settime.actime = settime.modtime = ftime;
+ return utime(fname,&settime);
+#endif
}
@@ -172,42 +225,41 @@ char *strtime (time_t *t)
#define ISSPECIAL(c) (((c) == '*') || ((c) == '/'))
-int ExprMatch(char *string,char *expr)
+int ExprMatch (char *string,char *expr)
{
while (1)
{
if (ISSPECIAL(*expr))
- {
- if (*expr == '/')
- {
- if (*string != '\\' && *string != '/')
- return 0;
- string ++; expr++;
- }
- else if (*expr == '*')
- {
- if (*expr ++ == 0)
- return 1;
- while (*++string != *expr)
- if (*string == 0)
- return 0;
- }
- }
+ {
+ if (*expr == '/')
+ {
+ if (*string != '\\' && *string != '/')
+ return 0;
+ string ++; expr++;
+ }
+ else if (*expr == '*')
+ {
+ if (*expr ++ == 0)
+ return 1;
+ while (*++string != *expr)
+ if (*string == 0)
+ return 0;
+ }
+ }
else
- {
- if (*string != *expr)
- return 0;
- if (*expr++ == 0)
- return 1;
- string++;
- }
+ {
+ if (*string != *expr)
+ return 0;
+ if (*expr++ == 0)
+ return 1;
+ string++;
+ }
}
}
-/* recursive make directory */
-/* abort if you get an ENOENT errno somewhere in the middle */
-/* e.g. ignore error "mkdir on existing directory" */
-/* */
+
+/* recursive mkdir */
+/* abort on ENOENT; ignore other errors like "directory already exists" */
/* return 1 if OK */
/* 0 on error */
@@ -216,7 +268,7 @@ int makedir (char *newdir)
char *buffer = strdup(newdir);
char *p;
int len = strlen(buffer);
-
+
if (len <= 0) {
free(buffer);
return 0;
@@ -224,7 +276,7 @@ int makedir (char *newdir)
if (buffer[len-1] == '/') {
buffer[len-1] = '\0';
}
- if (mkdir(buffer, 0775) == 0)
+ if (mkdir(buffer, 0755) == 0)
{
free(buffer);
return 1;
@@ -234,28 +286,29 @@ int makedir (char *newdir)
while (1)
{
char hold;
-
+
while(*p && *p != '\\' && *p != '/')
- p++;
+ p++;
hold = *p;
*p = 0;
- if ((mkdir(buffer, 0775) == -1) && (errno == ENOENT))
- {
- fprintf(stderr,"%s: couldn't create directory %s\n",prog,buffer);
- free(buffer);
- return 0;
- }
+ if ((mkdir(buffer, 0755) == -1) && (errno == ENOENT))
+ {
+ fprintf(stderr,"%s: Couldn't create directory %s\n",prog,buffer);
+ free(buffer);
+ return 0;
+ }
if (hold == 0)
- break;
+ break;
*p++ = hold;
}
free(buffer);
return 1;
}
+
int matchname (int arg,int argc,char **argv,char *fname)
{
- if (arg == argc) /* no arguments given (untgz tgzarchive) */
+ if (arg == argc) /* no arguments given (untgz tgzarchive) */
return 1;
while (arg < argc)
@@ -266,7 +319,7 @@ int matchname (int arg,int argc,char **argv,char *fname)
}
-/* Tar file list or extract */
+/* tar file list or extract */
int tar (gzFile in,int action,int arg,int argc,char **argv)
{
@@ -277,145 +330,140 @@ int tar (gzFile in,int action,int arg,int argc,char **argv)
int remaining = 0;
FILE *outfile = NULL;
char fname[BLOCKSIZE];
+ int tarmode;
time_t tartime;
-
+
if (action == TGZ_LIST)
- printf(" day time size file\n"
- " ---------- -------- --------- -------------------------------------\n");
+ printf(" date time size file\n"
+ " ---------- -------- --------- -------------------------------------\n");
while (1)
{
len = gzread(in, &buffer, BLOCKSIZE);
if (len < 0)
- error (gzerror(in, &err));
+ error(gzerror(in, &err));
/*
* Always expect complete blocks to process
* the tar information.
*/
if (len != BLOCKSIZE)
- error("gzread: incomplete block read");
-
+ {
+ action = TGZ_INVALID; /* force error exit */
+ remaining = 0; /* force I/O cleanup */
+ }
+
/*
* If we have to get a tar header
*/
if (getheader == 1)
- {
- /*
- * if we met the end of the tar
- * or the end-of-tar block,
- * we are done
- */
- if ((len == 0) || (buffer.header.name[0]== 0)) break;
-
- tartime = (time_t)getoct(buffer.header.mtime,12);
- strcpy(fname,buffer.header.name);
-
- switch (buffer.header.typeflag)
- {
- case DIRTYPE:
- if (action == TGZ_LIST)
- printf(" %s <dir> %s\n",strtime(&tartime),fname);
- if (action == TGZ_EXTRACT)
- makedir(fname);
- break;
- case REGTYPE:
- case AREGTYPE:
- remaining = getoct(buffer.header.size,12);
- if (action == TGZ_LIST)
- printf(" %s %9d %s\n",strtime(&tartime),remaining,fname);
- if (action == TGZ_EXTRACT)
- {
- if ((remaining) && (matchname(arg,argc,argv,fname)))
- {
- outfile = fopen(fname,"wb");
- if (outfile == NULL) {
- /* try creating directory */
- char *p = strrchr(fname, '/');
- if (p != NULL) {
- *p = '\0';
- makedir(fname);
- *p = '/';
- outfile = fopen(fname,"wb");
- }
- }
- fprintf(stderr,
- "%s %s\n",
- (outfile) ? "Extracting" : "Couldn't create",
- fname);
- }
- else
- outfile = NULL;
- }
- /*
- * could have no contents
- */
- getheader = (remaining) ? 0 : 1;
- break;
- default:
- if (action == TGZ_LIST)
- printf(" %s <---> %s\n",strtime(&tartime),fname);
- break;
- }
- }
+ {
+ /*
+ * if we met the end of the tar
+ * or the end-of-tar block,
+ * we are done
+ */
+ if ((len == 0) || (buffer.header.name[0] == 0)) break;
+
+ tarmode = getoct(buffer.header.mode,8);
+ tartime = (time_t)getoct(buffer.header.mtime,12);
+ if (tarmode == -1 || tartime == (time_t)-1)
+ {
+ buffer.header.name[0] = 0;
+ action = TGZ_INVALID;
+ }
+
+ strcpy(fname,buffer.header.name);
+
+ switch (buffer.header.typeflag)
+ {
+ case DIRTYPE:
+ if (action == TGZ_LIST)
+ printf(" %s <dir> %s\n",strtime(&tartime),fname);
+ if (action == TGZ_EXTRACT)
+ {
+ makedir(fname);
+ setfiletime(fname,tartime);
+ }
+ break;
+ case REGTYPE:
+ case AREGTYPE:
+ remaining = getoct(buffer.header.size,12);
+ if (remaining == -1)
+ {
+ action = TGZ_INVALID;
+ break;
+ }
+ if (action == TGZ_LIST)
+ printf(" %s %9d %s\n",strtime(&tartime),remaining,fname);
+ else if (action == TGZ_EXTRACT)
+ {
+ if (matchname(arg,argc,argv,fname))
+ {
+ outfile = fopen(fname,"wb");
+ if (outfile == NULL) {
+ /* try creating directory */
+ char *p = strrchr(fname, '/');
+ if (p != NULL) {
+ *p = '\0';
+ makedir(fname);
+ *p = '/';
+ outfile = fopen(fname,"wb");
+ }
+ }
+ if (outfile != NULL)
+ printf("Extracting %s\n",fname);
+ else
+ fprintf(stderr, "%s: Couldn't create %s",prog,fname);
+ }
+ else
+ outfile = NULL;
+ }
+ getheader = 0;
+ break;
+ default:
+ if (action == TGZ_LIST)
+ printf(" %s <---> %s\n",strtime(&tartime),fname);
+ break;
+ }
+ }
else
- {
- unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining;
-
- if ((action == TGZ_EXTRACT) && (outfile != NULL))
- {
- if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes)
- {
- fprintf(stderr,"%s : error writing %s skipping...\n",prog,fname);
- fclose(outfile);
- unlink(fname);
- }
- }
- remaining -= bytes;
- if (remaining == 0)
- {
- getheader = 1;
- if ((action == TGZ_EXTRACT) && (outfile != NULL))
- {
-#ifdef WIN32
- HANDLE hFile;
- FILETIME ftm,ftLocal;
- SYSTEMTIME st;
- struct tm localt;
-
- fclose(outfile);
-
- localt = *localtime(&tartime);
-
- hFile = CreateFile(fname, GENERIC_READ | GENERIC_WRITE,
- 0, NULL, OPEN_EXISTING, 0, NULL);
-
- st.wYear = (WORD)localt.tm_year+1900;
- st.wMonth = (WORD)localt.tm_mon;
- st.wDayOfWeek = (WORD)localt.tm_wday;
- st.wDay = (WORD)localt.tm_mday;
- st.wHour = (WORD)localt.tm_hour;
- st.wMinute = (WORD)localt.tm_min;
- st.wSecond = (WORD)localt.tm_sec;
- st.wMilliseconds = 0;
- SystemTimeToFileTime(&st,&ftLocal);
- LocalFileTimeToFileTime(&ftLocal,&ftm);
- SetFileTime(hFile,&ftm,NULL,&ftm);
- CloseHandle(hFile);
-
- outfile = NULL;
-#else
- struct utimbuf settime;
-
- settime.actime = settime.modtime = tartime;
+ {
+ unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining;
+
+ if (outfile != NULL)
+ {
+ if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes)
+ {
+ fprintf(stderr,"%s: Error writing %s -- skipping\n",prog,fname);
+ fclose(outfile);
+ outfile = NULL;
+ remove(fname);
+ }
+ }
+ remaining -= bytes;
+ }
+
+ if (remaining == 0)
+ {
+ getheader = 1;
+ if (outfile != NULL)
+ {
+ fclose(outfile);
+ outfile = NULL;
+ if (action != TGZ_INVALID)
+ setfiletime(fname,tartime);
+ }
+ }
- fclose(outfile);
- outfile = NULL;
- utime(fname,&settime);
-#endif
- }
- }
- }
+ /*
+ * Abandon if errors are found
+ */
+ if (action == TGZ_INVALID)
+ {
+ error("broken archive");
+ break;
+ }
}
-
+
if (gzclose(in) != Z_OK)
error("failed gzclose");
@@ -423,73 +471,74 @@ int tar (gzFile in,int action,int arg,int argc,char **argv)
}
-/* =========================================================== */
+/* ============================================================ */
void help(int exitval)
{
- fprintf(stderr,
- "untgz v 0.1\n"
- " an sample application of zlib 1.0.4\n\n"
- "Usage : untgz TGZfile to extract all files\n"
- " untgz TGZfile fname ... to extract selected files\n"
- " untgz -l TGZfile to list archive contents\n"
- " untgz -h to display this help\n\n");
+ printf("untgz version 0.2\n"
+ " using zlib version %s\n\n",
+ zlibVersion());
+ printf("Usage: untgz file.tgz extract all files\n"
+ " untgz file.tgz fname ... extract selected files\n"
+ " untgz -l file.tgz list archive contents\n"
+ " untgz -h display this help\n");
exit(exitval);
}
void error(const char *msg)
{
- fprintf(stderr, "%s: %s\n", prog, msg);
- exit(1);
+ fprintf(stderr, "%s: %s\n", prog, msg);
+ exit(1);
}
-/* ====================================================================== */
+/* ============================================================ */
-int _CRT_glob = 0; /* disable globbing of the arguments */
+#if defined(WIN32) && defined(__GNUC__)
+int _CRT_glob = 0; /* disable argument globbing in MinGW */
+#endif
int main(int argc,char **argv)
{
- int action = TGZ_EXTRACT;
- int arg = 1;
- char *TGZfile;
- gzFile *f;
-
+ int action = TGZ_EXTRACT;
+ int arg = 1;
+ char *TGZfile;
+ gzFile *f;
prog = strrchr(argv[0],'\\');
if (prog == NULL)
{
- prog = strrchr(argv[0],'/');
- if (prog == NULL)
- {
- prog = strrchr(argv[0],':');
- if (prog == NULL)
- prog = argv[0];
- else
- prog++;
- }
- else
- prog++;
+ prog = strrchr(argv[0],'/');
+ if (prog == NULL)
+ {
+ prog = strrchr(argv[0],':');
+ if (prog == NULL)
+ prog = argv[0];
+ else
+ prog++;
+ }
+ else
+ prog++;
}
else
prog++;
-
+
if (argc == 1)
help(0);
if (strcmp(argv[arg],"-l") == 0)
{
- action = TGZ_LIST;
- if (argc == ++arg)
- help(0);
+ action = TGZ_LIST;
+ if (argc == ++arg)
+ help(0);
}
else if (strcmp(argv[arg],"-h") == 0)
{
- help(0);
+ help(0);
}
if ((TGZfile = TGZfname(argv[arg])) == NULL)
- TGZnotfound(argv[arg]);
+ TGZnotfound(argv[arg]);
++arg;
if ((action == TGZ_LIST) && (arg != argc))
@@ -502,20 +551,18 @@ int main(int argc,char **argv)
{
case TGZ_LIST:
case TGZ_EXTRACT:
- f = gzopen(TGZfile,"rb");
- if (f == NULL)
- {
- fprintf(stderr,"%s: Couldn't gzopen %s\n",
- prog,
- TGZfile);
- return 1;
- }
- exit(tar(f, action, arg, argc, argv));
+ f = gzopen(TGZfile,"rb");
+ if (f == NULL)
+ {
+ fprintf(stderr,"%s: Couldn't gzopen %s\n",prog,TGZfile);
+ return 1;
+ }
+ exit(tar(f, action, arg, argc, argv));
break;
-
+
default:
- error("Unknown option!");
- exit(1);
+ error("Unknown option");
+ exit(1);
}
return 0;