untgz.c
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:11k
源码类别:

Symbian

开发平台:

C/C++

  1. /*
  2.  * untgz.c -- Display contents and/or extract file from
  3.  * a gzip'd TAR file
  4.  * written by "Pedro A. Aranda Gutiirrez" <paag@tid.es>
  5.  * adaptation to Unix by Jean-loup Gailly <jloup@gzip.org>
  6.  */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <time.h>
  11. #include <errno.h>
  12. #include <fcntl.h>
  13. #ifdef unix
  14. # include <unistd.h>
  15. #else
  16. # include <direct.h>
  17. # include <io.h>
  18. #endif
  19. #include "zlib.h"
  20. #ifdef WIN32
  21. #  ifndef F_OK
  22. #    define F_OK (0)
  23. #  endif
  24. #  ifdef _MSC_VER
  25. #    define mkdir(dirname,mode) _mkdir(dirname)
  26. #    define strdup(str)         _strdup(str)
  27. #    define unlink(fn)          _unlink(fn)
  28. #    define access(path,mode)   _access(path,mode)
  29. #  else
  30. #    define mkdir(dirname,mode) _mkdir(dirname)
  31. #  endif
  32. #else
  33. #  include <utime.h>
  34. #endif
  35. /* Values used in typeflag field.  */
  36. #define REGTYPE  '0' /* regular file */
  37. #define AREGTYPE '' /* regular file */
  38. #define LNKTYPE  '1' /* link */
  39. #define SYMTYPE  '2' /* reserved */
  40. #define CHRTYPE  '3' /* character special */
  41. #define BLKTYPE  '4' /* block special */
  42. #define DIRTYPE  '5' /* directory */
  43. #define FIFOTYPE '6' /* FIFO special */
  44. #define CONTTYPE '7' /* reserved */
  45. #define BLOCKSIZE 512
  46. struct tar_header
  47. { /* byte offset */
  48.   char name[100]; /*   0 */
  49.   char mode[8]; /* 100 */
  50.   char uid[8]; /* 108 */
  51.   char gid[8]; /* 116 */
  52.   char size[12]; /* 124 */
  53.   char mtime[12]; /* 136 */
  54.   char chksum[8]; /* 148 */
  55.   char typeflag; /* 156 */
  56.   char linkname[100]; /* 157 */
  57.   char magic[6]; /* 257 */
  58.   char version[2]; /* 263 */
  59.   char uname[32]; /* 265 */
  60.   char gname[32]; /* 297 */
  61.   char devmajor[8]; /* 329 */
  62.   char devminor[8]; /* 337 */
  63.   char prefix[155]; /* 345 */
  64. /* 500 */
  65. };
  66. union tar_buffer {
  67.   char               buffer[BLOCKSIZE];
  68.   struct tar_header  header;
  69. };
  70. enum { TGZ_EXTRACT = 0, TGZ_LIST };
  71. static char *TGZfname OF((const char *));
  72. void TGZnotfound OF((const char *));
  73. int getoct OF((char *, int));
  74. char *strtime OF((time_t *));
  75. int ExprMatch OF((char *,char *));
  76. int makedir OF((char *));
  77. int matchname OF((int,int,char **,char *));
  78. void error OF((const char *));
  79. int  tar OF((gzFile, int, int, int, char **));
  80. void help OF((int));
  81. int main OF((int, char **));
  82. char *prog;
  83. /* This will give a benign warning */
  84. static char *TGZprefix[] = { "", ".tgz", ".tar.gz", ".tar", NULL };
  85. /* Return the real name of the TGZ archive */
  86. /* or NULL if it does not exist. */
  87. static char *TGZfname OF((const char *fname))
  88. {
  89.   static char buffer[1024];
  90.   int origlen,i;
  91.   
  92.   strcpy(buffer,fname);
  93.   origlen = strlen(buffer);
  94.   for (i=0; TGZprefix[i]; i++)
  95.     {
  96.        strcpy(buffer+origlen,TGZprefix[i]);
  97.        if (access(buffer,F_OK) == 0)
  98.          return buffer;
  99.     }
  100.   return NULL;
  101. }
  102. /* error message for the filename */
  103. void TGZnotfound OF((const char *fname))
  104. {
  105.   int i;
  106.   fprintf(stderr,"%s : couldn't find ",prog);
  107.   for (i=0;TGZprefix[i];i++)
  108.     fprintf(stderr,(TGZprefix[i+1]) ? "%s%s, " : "or %s%sn",
  109.             fname,
  110.             TGZprefix[i]);
  111.   exit(1);
  112. }
  113. /* help functions */
  114. int getoct(char *p,int width)
  115. {
  116.   int result = 0;
  117.   char c;
  118.   
  119.   while (width --)
  120.     {
  121.       c = *p++;
  122.       if (c == ' ')
  123. continue;
  124.       if (c == 0)
  125. break;
  126.       result = result * 8 + (c - '0');
  127.     }
  128.   return result;
  129. }
  130. char *strtime (time_t *t)
  131. {
  132.   struct tm   *local;
  133.   static char result[32];
  134.   local = localtime(t);
  135.   sprintf(result,"%2d/%02d/%4d %02d:%02d:%02d",
  136.   local->tm_mday, local->tm_mon+1, local->tm_year+1900,
  137.   local->tm_hour, local->tm_min,   local->tm_sec);
  138.   return result;
  139. }
  140. /* regular expression matching */
  141. #define ISSPECIAL(c) (((c) == '*') || ((c) == '/'))
  142. int ExprMatch(char *string,char *expr)
  143. {
  144.   while (1)
  145.     {
  146.       if (ISSPECIAL(*expr))
  147. {
  148.   if (*expr == '/')
  149.     {
  150.       if (*string != '\' && *string != '/')
  151. return 0;
  152.       string ++; expr++;
  153.     }
  154.   else if (*expr == '*')
  155.     {
  156.       if (*expr ++ == 0)
  157. return 1;
  158.       while (*++string != *expr)
  159. if (*string == 0)
  160.   return 0;
  161.     }
  162. }
  163.       else
  164. {
  165.   if (*string != *expr)
  166.     return 0;
  167.   if (*expr++ == 0)
  168.     return 1;
  169.   string++;
  170. }
  171.     }
  172. }
  173. /* recursive make directory */
  174. /* abort if you get an ENOENT errno somewhere in the middle */
  175. /* e.g. ignore error "mkdir on existing directory" */
  176. /* */
  177. /* return 1 if OK */
  178. /*        0 on error */
  179. int makedir (char *newdir)
  180. {
  181.   char *buffer = strdup(newdir);
  182.   char *p;
  183.   int  len = strlen(buffer);
  184.   
  185.   if (len <= 0) {
  186.     free(buffer);
  187.     return 0;
  188.   }
  189.   if (buffer[len-1] == '/') {
  190.     buffer[len-1] = '';
  191.   }
  192.   if (mkdir(buffer, 0775) == 0)
  193.     {
  194.       free(buffer);
  195.       return 1;
  196.     }
  197.   p = buffer+1;
  198.   while (1)
  199.     {
  200.       char hold;
  201.       
  202.       while(*p && *p != '\' && *p != '/')
  203. p++;
  204.       hold = *p;
  205.       *p = 0;
  206.       if ((mkdir(buffer, 0775) == -1) && (errno == ENOENT))
  207. {
  208.   fprintf(stderr,"%s: couldn't create directory %sn",prog,buffer);
  209.   free(buffer);
  210.   return 0;
  211. }
  212.       if (hold == 0)
  213. break;
  214.       *p++ = hold;
  215.     }
  216.   free(buffer);
  217.   return 1;
  218. }
  219. int matchname (int arg,int argc,char **argv,char *fname)
  220. {
  221.   if (arg == argc) /* no arguments given (untgz tgzarchive) */
  222.     return 1;
  223.   while (arg < argc)
  224.     if (ExprMatch(fname,argv[arg++]))
  225.       return 1;
  226.   return 0; /* ignore this for the moment being */
  227. }
  228. /* Tar file list or extract */
  229. int tar (gzFile in,int action,int arg,int argc,char **argv)
  230. {
  231.   union  tar_buffer buffer;
  232.   int    len;
  233.   int    err;
  234.   int    getheader = 1;
  235.   int    remaining = 0;
  236.   FILE   *outfile = NULL;
  237.   char   fname[BLOCKSIZE];
  238.   time_t tartime;
  239.   
  240.   if (action == TGZ_LIST)
  241.     printf("     day      time     size                       filen"
  242.    " ---------- -------- --------- -------------------------------------n");
  243.   while (1)
  244.     {
  245.       len = gzread(in, &buffer, BLOCKSIZE);
  246.       if (len < 0)
  247. error (gzerror(in, &err));
  248.       /*
  249.        * Always expect complete blocks to process
  250.        * the tar information.
  251.        */
  252.       if (len != BLOCKSIZE)
  253. error("gzread: incomplete block read");
  254.       
  255.       /*
  256.        * If we have to get a tar header
  257.        */
  258.       if (getheader == 1)
  259. {
  260.   /*
  261.    * if we met the end of the tar
  262.    * or the end-of-tar block,
  263.    * we are done
  264.    */
  265.   if ((len == 0)  || (buffer.header.name[0]== 0)) break;
  266.   tartime = (time_t)getoct(buffer.header.mtime,12);
  267.   strcpy(fname,buffer.header.name);
  268.   
  269.   switch (buffer.header.typeflag)
  270.     {
  271.     case DIRTYPE:
  272.       if (action == TGZ_LIST)
  273. printf(" %s     <dir> %sn",strtime(&tartime),fname);
  274.       if (action == TGZ_EXTRACT)
  275. makedir(fname);
  276.       break;
  277.     case REGTYPE:
  278.     case AREGTYPE:
  279.       remaining = getoct(buffer.header.size,12);
  280.       if (action == TGZ_LIST)
  281. printf(" %s %9d %sn",strtime(&tartime),remaining,fname);
  282.       if (action == TGZ_EXTRACT)
  283. {
  284.   if ((remaining) && (matchname(arg,argc,argv,fname)))
  285.     {
  286.       outfile = fopen(fname,"wb");
  287.       if (outfile == NULL) {
  288. /* try creating directory */
  289. char *p = strrchr(fname, '/');
  290. if (p != NULL) {
  291.   *p = '';
  292.   makedir(fname);
  293.   *p = '/';
  294.   outfile = fopen(fname,"wb");
  295. }
  296.       }
  297.       fprintf(stderr,
  298.       "%s %sn",
  299.       (outfile) ? "Extracting" : "Couldn't create",
  300.       fname);
  301.     }
  302.   else
  303.     outfile = NULL;
  304. }
  305.       /*
  306.        * could have no contents
  307.        */
  308.       getheader = (remaining) ? 0 : 1;
  309.       break;
  310.     default:
  311.       if (action == TGZ_LIST)
  312. printf(" %s     <---> %sn",strtime(&tartime),fname);
  313.       break;
  314.     }
  315. }
  316.       else
  317. {
  318.   unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining;
  319.   if ((action == TGZ_EXTRACT) && (outfile != NULL))
  320.     {
  321.       if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes)
  322. {
  323.   fprintf(stderr,"%s : error writing %s skipping...n",prog,fname);
  324.   fclose(outfile);
  325.   unlink(fname);
  326. }
  327.     }
  328.   remaining -= bytes;
  329.   if (remaining == 0)
  330.     {
  331.       getheader = 1;
  332.       if ((action == TGZ_EXTRACT) && (outfile != NULL))
  333. {
  334. #ifdef WIN32
  335.   HANDLE hFile;
  336.   FILETIME ftm,ftLocal;
  337.   SYSTEMTIME st;
  338.   struct tm localt;
  339.  
  340.   fclose(outfile);
  341.   localt = *localtime(&tartime);
  342.   hFile = CreateFile(fname, GENERIC_READ | GENERIC_WRITE,
  343.      0, NULL, OPEN_EXISTING, 0, NULL);
  344.   
  345.   st.wYear = (WORD)localt.tm_year+1900;
  346.   st.wMonth = (WORD)localt.tm_mon;
  347.   st.wDayOfWeek = (WORD)localt.tm_wday;
  348.   st.wDay = (WORD)localt.tm_mday;
  349.   st.wHour = (WORD)localt.tm_hour;
  350.   st.wMinute = (WORD)localt.tm_min;
  351.   st.wSecond = (WORD)localt.tm_sec;
  352.   st.wMilliseconds = 0;
  353.   SystemTimeToFileTime(&st,&ftLocal);
  354.   LocalFileTimeToFileTime(&ftLocal,&ftm);
  355.   SetFileTime(hFile,&ftm,NULL,&ftm);
  356.   CloseHandle(hFile);
  357.   outfile = NULL;
  358. #else
  359.   struct utimbuf settime;
  360.   settime.actime = settime.modtime = tartime;
  361.   fclose(outfile);
  362.   outfile = NULL;
  363.   utime(fname,&settime);
  364. #endif
  365. }
  366.     }
  367. }
  368.     }
  369.   
  370.   if (gzclose(in) != Z_OK)
  371.     error("failed gzclose");
  372.   return 0;
  373. }
  374. /* =========================================================== */
  375. void help(int exitval)
  376. {
  377.   fprintf(stderr,
  378.   "untgz v 0.1n"
  379.   " an sample application of zlib 1.0.4nn"
  380.           "Usage : untgz TGZfile            to extract all filesn"
  381.           "        untgz TGZfile fname ...  to extract selected filesn"
  382.           "        untgz -l TGZfile         to list archive contentsn"
  383.           "        untgz -h                 to display this helpnn");
  384.   exit(exitval);
  385. }
  386. void error(const char *msg)
  387. {
  388.     fprintf(stderr, "%s: %sn", prog, msg);
  389.     exit(1);
  390. }
  391. /* ====================================================================== */
  392. int _CRT_glob = 0; /* disable globbing of the arguments */
  393. int main(int argc,char **argv)
  394. {
  395.     int  action = TGZ_EXTRACT;
  396.     int  arg = 1;
  397.     char *TGZfile;
  398.     gzFile *f;
  399.     
  400.     prog = strrchr(argv[0],'\');
  401.     if (prog == NULL)
  402.       {
  403. prog = strrchr(argv[0],'/');
  404. if (prog == NULL)
  405.   {
  406.     prog = strrchr(argv[0],':');
  407.     if (prog == NULL)
  408.       prog = argv[0];
  409.     else
  410.       prog++;
  411.   }
  412. else
  413.   prog++;
  414.       }
  415.     else
  416.       prog++;
  417.     
  418.     if (argc == 1)
  419.       help(0);
  420.     if (strcmp(argv[arg],"-l") == 0)
  421.       {
  422. action = TGZ_LIST;
  423. if (argc == ++arg)
  424.   help(0);
  425.       }
  426.     else if (strcmp(argv[arg],"-h") == 0)
  427.       {
  428. help(0);
  429.       }
  430.     if ((TGZfile = TGZfname(argv[arg])) == NULL)
  431.       TGZnotfound(argv[arg]);            
  432.     ++arg;
  433.     if ((action == TGZ_LIST) && (arg != argc))
  434.       help(1);
  435. /*
  436.  *  Process the TGZ file
  437.  */
  438.     switch(action)
  439.       {
  440.       case TGZ_LIST:
  441.       case TGZ_EXTRACT:
  442. f = gzopen(TGZfile,"rb");
  443. if (f == NULL)
  444.   {
  445.     fprintf(stderr,"%s: Couldn't gzopen %sn",
  446.     prog,
  447.     TGZfile);
  448.     return 1;
  449.   }
  450. exit(tar(f, action, arg, argc, argv));
  451.       break;
  452.       default:
  453. error("Unknown option!");
  454. exit(1);
  455.       }
  456.     return 0;
  457. }