Visualization Library 2.0.0-b5

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
untgz.c
Go to the documentation of this file.
1 /*
2  * untgz.c -- Display contents and extract files from a gzip'd TAR file
3  *
4  * written by Pedro A. Aranda Gutierrez <paag@tid.es>
5  * adaptation to Unix by Jean-loup Gailly <jloup@gzip.org>
6  * various fixes by Cosmin Truta <cosmint@cs.ubbcluj.ro>
7  */
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <time.h>
13 #include <errno.h>
14 
15 #include "zlib.h"
16 
17 #ifdef unix
18 # include <unistd.h>
19 #else
20 # include <direct.h>
21 # include <io.h>
22 #endif
23 
24 #ifdef WIN32
25 #include <windows.h>
26 # ifndef F_OK
27 # define F_OK 0
28 # endif
29 # define mkdir(dirname,mode) _mkdir(dirname)
30 # ifdef _MSC_VER
31 # define access(path,mode) _access(path,mode)
32 # define chmod(path,mode) _chmod(path,mode)
33 # define strdup(str) _strdup(str)
34 # endif
35 #else
36 # include <utime.h>
37 #endif
38 
39 
40 /* values used in typeflag field */
41 
42 #define REGTYPE '0' /* regular file */
43 #define AREGTYPE '\0' /* regular file */
44 #define LNKTYPE '1' /* link */
45 #define SYMTYPE '2' /* reserved */
46 #define CHRTYPE '3' /* character special */
47 #define BLKTYPE '4' /* block special */
48 #define DIRTYPE '5' /* directory */
49 #define FIFOTYPE '6' /* FIFO special */
50 #define CONTTYPE '7' /* reserved */
51 
52 /* GNU tar extensions */
53 
54 #define GNUTYPE_DUMPDIR 'D' /* file names from dumped directory */
55 #define GNUTYPE_LONGLINK 'K' /* long link name */
56 #define GNUTYPE_LONGNAME 'L' /* long file name */
57 #define GNUTYPE_MULTIVOL 'M' /* continuation of file from another volume */
58 #define GNUTYPE_NAMES 'N' /* file name that does not fit into main hdr */
59 #define GNUTYPE_SPARSE 'S' /* sparse file */
60 #define GNUTYPE_VOLHDR 'V' /* tape/volume header */
61 
62 
63 /* tar header */
64 
65 #define BLOCKSIZE 512
66 #define SHORTNAMESIZE 100
67 
68 struct tar_header
69 { /* byte offset */
70  char name[100]; /* 0 */
71  char mode[8]; /* 100 */
72  char uid[8]; /* 108 */
73  char gid[8]; /* 116 */
74  char size[12]; /* 124 */
75  char mtime[12]; /* 136 */
76  char chksum[8]; /* 148 */
77  char typeflag; /* 156 */
78  char linkname[100]; /* 157 */
79  char magic[6]; /* 257 */
80  char version[2]; /* 263 */
81  char uname[32]; /* 265 */
82  char gname[32]; /* 297 */
83  char devmajor[8]; /* 329 */
84  char devminor[8]; /* 337 */
85  char prefix[155]; /* 345 */
86  /* 500 */
87 };
88 
89 union tar_buffer
90 {
91  char buffer[BLOCKSIZE];
92  struct tar_header header;
93 };
94 
95 struct attr_item
96 {
97  struct attr_item *next;
98  char *fname;
99  int mode;
100  time_t time;
101 };
102 
104 
105 char *TGZfname OF((const char *));
106 void TGZnotfound OF((const char *));
107 
108 int getoct OF((char *, int));
109 char *strtime OF((time_t *));
110 int setfiletime OF((char *, time_t));
111 void push_attr OF((struct attr_item **, char *, int, time_t));
112 void restore_attr OF((struct attr_item **));
113 
114 int ExprMatch OF((char *, char *));
115 
116 int makedir OF((char *));
117 int matchname OF((int, int, char **, char *));
118 
119 void error OF((const char *));
120 int tar OF((gzFile, int, int, int, char **));
121 
122 void help OF((int));
123 int main OF((int, char **));
124 
125 char *prog;
126 
127 const char *TGZsuffix[] = { "\0", ".tar", ".tar.gz", ".taz", ".tgz", NULL };
128 
129 /* return the file name of the TGZ archive */
130 /* or NULL if it does not exist */
131 
132 char *TGZfname (const char *arcname)
133 {
134  static char buffer[1024];
135  int origlen,i;
136 
137  strcpy(buffer,arcname);
138  origlen = strlen(buffer);
139 
140  for (i=0; TGZsuffix[i]; i++)
141  {
142  strcpy(buffer+origlen,TGZsuffix[i]);
143  if (access(buffer,F_OK) == 0)
144  return buffer;
145  }
146  return NULL;
147 }
148 
149 
150 /* error message for the filename */
151 
152 void TGZnotfound (const char *arcname)
153 {
154  int i;
155 
156  fprintf(stderr,"%s: Couldn't find ",prog);
157  for (i=0;TGZsuffix[i];i++)
158  fprintf(stderr,(TGZsuffix[i+1]) ? "%s%s, " : "or %s%s\n",
159  arcname,
160  TGZsuffix[i]);
161  exit(1);
162 }
163 
164 
165 /* convert octal digits to int */
166 /* on error return -1 */
167 
168 int getoct (char *p,int width)
169 {
170  int result = 0;
171  char c;
172 
173  while (width--)
174  {
175  c = *p++;
176  if (c == 0)
177  break;
178  if (c == ' ')
179  continue;
180  if (c < '0' || c > '7')
181  return -1;
182  result = result * 8 + (c - '0');
183  }
184  return result;
185 }
186 
187 
188 /* convert time_t to string */
189 /* use the "YYYY/MM/DD hh:mm:ss" format */
190 
191 char *strtime (time_t *t)
192 {
193  struct tm *local;
194  static char result[32];
195 
196  local = localtime(t);
197  sprintf(result,"%4d/%02d/%02d %02d:%02d:%02d",
198  local->tm_year+1900, local->tm_mon+1, local->tm_mday,
199  local->tm_hour, local->tm_min, local->tm_sec);
200  return result;
201 }
202 
203 
204 /* set file time */
205 
206 int setfiletime (char *fname,time_t ftime)
207 {
208 #ifdef WIN32
209  static int isWinNT = -1;
210  SYSTEMTIME st;
211  FILETIME locft, modft;
212  struct tm *loctm;
213  HANDLE hFile;
214  int result;
215 
216  loctm = localtime(&ftime);
217  if (loctm == NULL)
218  return -1;
219 
220  st.wYear = (WORD)loctm->tm_year + 1900;
221  st.wMonth = (WORD)loctm->tm_mon + 1;
222  st.wDayOfWeek = (WORD)loctm->tm_wday;
223  st.wDay = (WORD)loctm->tm_mday;
224  st.wHour = (WORD)loctm->tm_hour;
225  st.wMinute = (WORD)loctm->tm_min;
226  st.wSecond = (WORD)loctm->tm_sec;
227  st.wMilliseconds = 0;
228  if (!SystemTimeToFileTime(&st, &locft) ||
229  !LocalFileTimeToFileTime(&locft, &modft))
230  return -1;
231 
232  if (isWinNT < 0)
233  isWinNT = (GetVersion() < 0x80000000) ? 1 : 0;
234  hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
235  (isWinNT ? FILE_FLAG_BACKUP_SEMANTICS : 0),
236  NULL);
237  if (hFile == INVALID_HANDLE_VALUE)
238  return -1;
239  result = SetFileTime(hFile, NULL, NULL, &modft) ? 0 : -1;
240  CloseHandle(hFile);
241  return result;
242 #else
243  struct utimbuf settime;
244 
245  settime.actime = settime.modtime = ftime;
246  return utime(fname,&settime);
247 #endif
248 }
249 
250 
251 /* push file attributes */
252 
253 void push_attr(struct attr_item **list,char *fname,int mode,time_t time)
254 {
255  struct attr_item *item;
256 
257  item = (struct attr_item *)malloc(sizeof(struct attr_item));
258  if (item == NULL)
259  error("Out of memory");
260  item->fname = strdup(fname);
261  item->mode = mode;
262  item->time = time;
263  item->next = *list;
264  *list = item;
265 }
266 
267 
268 /* restore file attributes */
269 
270 void restore_attr(struct attr_item **list)
271 {
272  struct attr_item *item, *prev;
273 
274  for (item = *list; item != NULL; )
275  {
276  setfiletime(item->fname,item->time);
277  chmod(item->fname,item->mode);
278  prev = item;
279  item = item->next;
280  free(prev);
281  }
282  *list = NULL;
283 }
284 
285 
286 /* match regular expression */
287 
288 #define ISSPECIAL(c) (((c) == '*') || ((c) == '/'))
289 
290 int ExprMatch (char *string,char *expr)
291 {
292  while (1)
293  {
294  if (ISSPECIAL(*expr))
295  {
296  if (*expr == '/')
297  {
298  if (*string != '\\' && *string != '/')
299  return 0;
300  string ++; expr++;
301  }
302  else if (*expr == '*')
303  {
304  if (*expr ++ == 0)
305  return 1;
306  while (*++string != *expr)
307  if (*string == 0)
308  return 0;
309  }
310  }
311  else
312  {
313  if (*string != *expr)
314  return 0;
315  if (*expr++ == 0)
316  return 1;
317  string++;
318  }
319  }
320 }
321 
322 
323 /* recursive mkdir */
324 /* abort on ENOENT; ignore other errors like "directory already exists" */
325 /* return 1 if OK */
326 /* 0 on error */
327 
328 int makedir (char *newdir)
329 {
330  char *buffer = strdup(newdir);
331  char *p;
332  int len = strlen(buffer);
333 
334  if (len <= 0) {
335  free(buffer);
336  return 0;
337  }
338  if (buffer[len-1] == '/') {
339  buffer[len-1] = '\0';
340  }
341  if (mkdir(buffer, 0755) == 0)
342  {
343  free(buffer);
344  return 1;
345  }
346 
347  p = buffer+1;
348  while (1)
349  {
350  char hold;
351 
352  while(*p && *p != '\\' && *p != '/')
353  p++;
354  hold = *p;
355  *p = 0;
356  if ((mkdir(buffer, 0755) == -1) && (errno == ENOENT))
357  {
358  fprintf(stderr,"%s: Couldn't create directory %s\n",prog,buffer);
359  free(buffer);
360  return 0;
361  }
362  if (hold == 0)
363  break;
364  *p++ = hold;
365  }
366  free(buffer);
367  return 1;
368 }
369 
370 
371 int matchname (int arg,int argc,char **argv,char *fname)
372 {
373  if (arg == argc) /* no arguments given (untgz tgzarchive) */
374  return 1;
375 
376  while (arg < argc)
377  if (ExprMatch(fname,argv[arg++]))
378  return 1;
379 
380  return 0; /* ignore this for the moment being */
381 }
382 
383 
384 /* tar file list or extract */
385 
386 int tar (gzFile in,int action,int arg,int argc,char **argv)
387 {
388  union tar_buffer buffer;
389  int len;
390  int err;
391  int getheader = 1;
392  int remaining = 0;
393  FILE *outfile = NULL;
394  char fname[BLOCKSIZE];
395  int tarmode;
396  time_t tartime;
397  struct attr_item *attributes = NULL;
398 
399  if (action == TGZ_LIST)
400  printf(" date time size file\n"
401  " ---------- -------- --------- -------------------------------------\n");
402  while (1)
403  {
404  len = gzread(in, &buffer, BLOCKSIZE);
405  if (len < 0)
406  error(gzerror(in, &err));
407  /*
408  * Always expect complete blocks to process
409  * the tar information.
410  */
411  if (len != BLOCKSIZE)
412  {
413  action = TGZ_INVALID; /* force error exit */
414  remaining = 0; /* force I/O cleanup */
415  }
416 
417  /*
418  * If we have to get a tar header
419  */
420  if (getheader >= 1)
421  {
422  /*
423  * if we met the end of the tar
424  * or the end-of-tar block,
425  * we are done
426  */
427  if (len == 0 || buffer.header.name[0] == 0)
428  break;
429 
430  tarmode = getoct(buffer.header.mode,8);
431  tartime = (time_t)getoct(buffer.header.mtime,12);
432  if (tarmode == -1 || tartime == (time_t)-1)
433  {
434  buffer.header.name[0] = 0;
435  action = TGZ_INVALID;
436  }
437 
438  if (getheader == 1)
439  {
440  strncpy(fname,buffer.header.name,SHORTNAMESIZE);
441  if (fname[SHORTNAMESIZE-1] != 0)
442  fname[SHORTNAMESIZE] = 0;
443  }
444  else
445  {
446  /*
447  * The file name is longer than SHORTNAMESIZE
448  */
449  if (strncmp(fname,buffer.header.name,SHORTNAMESIZE-1) != 0)
450  error("bad long name");
451  getheader = 1;
452  }
453 
454  /*
455  * Act according to the type flag
456  */
457  switch (buffer.header.typeflag)
458  {
459  case DIRTYPE:
460  if (action == TGZ_LIST)
461  printf(" %s <dir> %s\n",strtime(&tartime),fname);
462  if (action == TGZ_EXTRACT)
463  {
464  makedir(fname);
465  push_attr(&attributes,fname,tarmode,tartime);
466  }
467  break;
468  case REGTYPE:
469  case AREGTYPE:
470  remaining = getoct(buffer.header.size,12);
471  if (remaining == -1)
472  {
473  action = TGZ_INVALID;
474  break;
475  }
476  if (action == TGZ_LIST)
477  printf(" %s %9d %s\n",strtime(&tartime),remaining,fname);
478  else if (action == TGZ_EXTRACT)
479  {
480  if (matchname(arg,argc,argv,fname))
481  {
482  outfile = fopen(fname,"wb");
483  if (outfile == NULL) {
484  /* try creating directory */
485  char *p = strrchr(fname, '/');
486  if (p != NULL) {
487  *p = '\0';
488  makedir(fname);
489  *p = '/';
490  outfile = fopen(fname,"wb");
491  }
492  }
493  if (outfile != NULL)
494  printf("Extracting %s\n",fname);
495  else
496  fprintf(stderr, "%s: Couldn't create %s",prog,fname);
497  }
498  else
499  outfile = NULL;
500  }
501  getheader = 0;
502  break;
503  case GNUTYPE_LONGLINK:
504  case GNUTYPE_LONGNAME:
505  remaining = getoct(buffer.header.size,12);
506  if (remaining < 0 || remaining >= BLOCKSIZE)
507  {
508  action = TGZ_INVALID;
509  break;
510  }
511  len = gzread(in, fname, BLOCKSIZE);
512  if (len < 0)
513  error(gzerror(in, &err));
514  if (fname[BLOCKSIZE-1] != 0 || (int)strlen(fname) > remaining)
515  {
516  action = TGZ_INVALID;
517  break;
518  }
519  getheader = 2;
520  break;
521  default:
522  if (action == TGZ_LIST)
523  printf(" %s <---> %s\n",strtime(&tartime),fname);
524  break;
525  }
526  }
527  else
528  {
529  unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining;
530 
531  if (outfile != NULL)
532  {
533  if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes)
534  {
535  fprintf(stderr,
536  "%s: Error writing %s -- skipping\n",prog,fname);
537  fclose(outfile);
538  outfile = NULL;
539  remove(fname);
540  }
541  }
542  remaining -= bytes;
543  }
544 
545  if (remaining == 0)
546  {
547  getheader = 1;
548  if (outfile != NULL)
549  {
550  fclose(outfile);
551  outfile = NULL;
552  if (action != TGZ_INVALID)
553  push_attr(&attributes,fname,tarmode,tartime);
554  }
555  }
556 
557  /*
558  * Abandon if errors are found
559  */
560  if (action == TGZ_INVALID)
561  {
562  error("broken archive");
563  break;
564  }
565  }
566 
567  /*
568  * Restore file modes and time stamps
569  */
570  restore_attr(&attributes);
571 
572  if (gzclose(in) != Z_OK)
573  error("failed gzclose");
574 
575  return 0;
576 }
577 
578 
579 /* ============================================================ */
580 
581 void help(int exitval)
582 {
583  printf("untgz version 0.2.1\n"
584  " using zlib version %s\n\n",
585  zlibVersion());
586  printf("Usage: untgz file.tgz extract all files\n"
587  " untgz file.tgz fname ... extract selected files\n"
588  " untgz -l file.tgz list archive contents\n"
589  " untgz -h display this help\n");
590  exit(exitval);
591 }
592 
593 void error(const char *msg)
594 {
595  fprintf(stderr, "%s: %s\n", prog, msg);
596  exit(1);
597 }
598 
599 
600 /* ============================================================ */
601 
602 #if defined(WIN32) && defined(__GNUC__)
603 int _CRT_glob = 0; /* disable argument globbing in MinGW */
604 #endif
605 
606 int main(int argc,char **argv)
607 {
608  int action = TGZ_EXTRACT;
609  int arg = 1;
610  char *TGZfile;
611  gzFile *f;
612 
613  prog = strrchr(argv[0],'\\');
614  if (prog == NULL)
615  {
616  prog = strrchr(argv[0],'/');
617  if (prog == NULL)
618  {
619  prog = strrchr(argv[0],':');
620  if (prog == NULL)
621  prog = argv[0];
622  else
623  prog++;
624  }
625  else
626  prog++;
627  }
628  else
629  prog++;
630 
631  if (argc == 1)
632  help(0);
633 
634  if (strcmp(argv[arg],"-l") == 0)
635  {
636  action = TGZ_LIST;
637  if (argc == ++arg)
638  help(0);
639  }
640  else if (strcmp(argv[arg],"-h") == 0)
641  {
642  help(0);
643  }
644 
645  if ((TGZfile = TGZfname(argv[arg])) == NULL)
646  TGZnotfound(argv[arg]);
647 
648  ++arg;
649  if ((action == TGZ_LIST) && (arg != argc))
650  help(1);
651 
652 /*
653  * Process the TGZ file
654  */
655  switch(action)
656  {
657  case TGZ_LIST:
658  case TGZ_EXTRACT:
659  f = gzopen(TGZfile,"rb");
660  if (f == NULL)
661  {
662  fprintf(stderr,"%s: Couldn't gzopen %s\n",prog,TGZfile);
663  return 1;
664  }
665  exit(tar(f, action, arg, argc, argv));
666  break;
667 
668  default:
669  error("Unknown option");
670  exit(1);
671  }
672 
673  return 0;
674 }
#define AREGTYPE
Definition: untgz.c:43
int matchname(int arg, int argc, char **argv, char *fname)
Definition: untgz.c:371
GLuint GLint GLboolean GLint GLenum access
char * prog
Definition: untgz.c:125
GLfloat GLfloat p
#define NULL
Definition: ftobjs.h:61
int makedir(char *newdir)
Definition: untgz.c:328
char * malloc()
int ZEXPORT gzclose(gzFile file)
Definition: gzclose.c:11
GLint GLint GLsizei width
void help(int exitval)
Definition: untgz.c:581
png_uint_32 i
Definition: png.h:2640
unsigned short prefix[65536]
Definition: gun.c:163
#define DIRTYPE
Definition: untgz.c:48
#define REGTYPE
Definition: untgz.c:42
#define INVALID_HANDLE_VALUE
Definition: iowin32.c:21
#define Z_OK
Definition: zlib.h:132
char * strtime(time_t *t)
Definition: untgz.c:191
int main(int argc, char **argv)
Definition: untgz.c:606
#define BLOCKSIZE
Definition: untgz.c:65
void push_attr(struct attr_item **list, char *fname, int mode, time_t time)
Definition: untgz.c:253
FILE * outfile
Definition: jpeglib.h:910
void error(const char *msg)
Definition: untgz.c:593
GLenum GLsizei len
GLenum mode
const char * TGZsuffix[]
Definition: untgz.c:127
GLuint buffer
const GLubyte * c
#define GNUTYPE_LONGLINK
Definition: untgz.c:55
int free()
int const char * version
Definition: zlib.h:813
int setfiletime(char *fname, time_t ftime)
Definition: untgz.c:206
const char *ZEXPORT zlibVersion()
Definition: zutil.c:30
GLuint const GLchar * name
#define ISSPECIAL(c)
Definition: untgz.c:288
if(!abbox) return FT_THROW(Invalid_Argument)
#define local
Definition: zutil.h:30
const char *ZEXPORT gzerror(gzFile file, int *errnum)
Definition: gzlib.c:528
#define SHORTNAMESIZE
Definition: untgz.c:66
GLuint64EXT * result
GLuint in
int getoct(char *p, int width)
Definition: untgz.c:168
gzFile ZEXPORT gzopen(char *path, const char *mode) const
Definition: gzlib.c:268
int ExprMatch(char *string, char *expr)
Definition: untgz.c:290
char * arg
Definition: cdjpeg.h:136
void TGZnotfound(const char *arcname)
Definition: untgz.c:152
#define GNUTYPE_LONGNAME
Definition: untgz.c:56
char *TGZfname OF((const char *))
GLdouble GLdouble t
char * TGZfname(const char *arcname)
Definition: untgz.c:132
int ZEXPORT gzread(gzFile file, voidp buf, unsigned len)
Definition: gzread.c:288
GLfloat f
int tar(gzFile in, int action, int arg, int argc, char **argv)
Definition: untgz.c:386
GLsizeiptr size
void restore_attr(struct attr_item **list)
Definition: untgz.c:270
png_const_charp msg
Definition: PngFile.c:23