Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5.  
  6. #include "physfs.h"
  7.  
  8.  
  9. static int failure = 0;
  10.  
  11. static void modTimeToStr(PHYSFS_sint64 modtime, char *modstr, size_t strsize)
  12. {
  13.     const char *str = "unknown modtime";
  14.     if (modtime != -1)
  15.     {
  16.         time_t t = (time_t) modtime;
  17.         str = ctime(&t);
  18.     } /* if */
  19.  
  20.     strncpy(modstr, str, strsize);
  21.     modstr[strsize-1] = '\0';
  22.     strsize = strlen(modstr);
  23.     while ((modstr[strsize-1] == '\n') || (modstr[strsize-1] == '\r'))
  24.         modstr[--strsize] = '\0';
  25. } /* modTimeToStr */
  26.  
  27.  
  28. static void fail(const char *what, const char *why)
  29. {
  30.     if (why == NULL)
  31.         why = PHYSFS_getLastError();
  32.     fprintf(stderr, "%s failed: %s\n", what, why);
  33.     failure = 1;
  34. } /* fail */
  35.  
  36.  
  37. static void dumpFile(const char *fname)
  38. {
  39.     const int origfailure = failure;
  40.     PHYSFS_File *out = NULL;
  41.     PHYSFS_File *in = NULL;
  42.  
  43.     failure = 0;
  44.  
  45.     if ((in = PHYSFS_openRead(fname)) == NULL)
  46.         fail("\nPHYSFS_openRead", NULL);
  47.     else if ((out = PHYSFS_openWrite(fname)) == NULL)
  48.         fail("\nPHYSFS_openWrite", NULL);
  49.     else
  50.     {
  51.         char modstr[64];
  52.         PHYSFS_sint64 size = PHYSFS_fileLength(in);
  53.  
  54.         printf("(");
  55.         if (size == -1)
  56.             printf("?");
  57.         else
  58.             printf("%lld", (long long) size);
  59.         printf(" bytes");
  60.  
  61.         modTimeToStr(PHYSFS_getLastModTime(fname), modstr, sizeof (modstr));
  62.         printf(", %s)\n", modstr);
  63.  
  64.         while ( (!failure) && (!PHYSFS_eof(in)) )
  65.         {
  66.             static char buf[64 * 1024];
  67.             PHYSFS_sint64 br = PHYSFS_read(in, buf, 1, sizeof (buf));
  68.             if (br == -1)
  69.                 fail("PHYSFS_read", NULL);
  70.             else
  71.             {
  72.                 PHYSFS_sint64 bw = PHYSFS_write(out, buf, 1, br);
  73.                 if (bw != br)
  74.                     fail("PHYSFS_write", NULL);
  75.                 else
  76.                     size -= bw;
  77.             } /* else */
  78.         } /* while */
  79.  
  80.         if ((!failure) && (size != 0))
  81.             fail("PHYSFS_eof", "BUG! eof != PHYSFS_fileLength bytes!");
  82.     } /* else */
  83.  
  84.     if (in != NULL)
  85.         PHYSFS_close(in);
  86.  
  87.     if (out != NULL)
  88.     {
  89.         if (!PHYSFS_close(out))
  90.             fail("PHYSFS_close", NULL);
  91.     } /* if */
  92.  
  93.     if (failure)
  94.         PHYSFS_delete(fname);
  95.     else
  96.         failure = origfailure;
  97. } /* dumpFile */
  98.  
  99.  
  100. static void unpackCallback(void *_depth, const char *origdir, const char *str)
  101. {
  102.     int depth = *((int *) _depth);
  103.     const int len = strlen(origdir) + strlen(str) + 2;
  104.     char *fname = (char *) malloc(len);
  105.     if (fname == NULL)
  106.         fail("malloc", "Out of memory!");
  107.     else
  108.     {
  109.         if (strcmp(origdir, "/") == 0)
  110.             origdir = "";
  111.  
  112.         snprintf(fname, len, "%s/%s", origdir, str);
  113.  
  114.         printf("%s ", fname);
  115.         if (PHYSFS_isDirectory(fname))
  116.         {
  117.             depth++;
  118.             printf("(directory)\n");
  119.             if (!PHYSFS_mkdir(fname))
  120.                 fail("PHYSFS_mkdir", NULL);
  121.             else
  122.                 PHYSFS_enumerateFilesCallback(fname, unpackCallback, &depth);
  123.         } /* if */
  124.  
  125.         else if (PHYSFS_isSymbolicLink(fname))
  126.         {
  127.             printf("(symlink)\n");
  128.             /* !!! FIXME: ?  if (!symlink(fname, */
  129.         } /* else if */
  130.  
  131.         else  /* ...file. */
  132.         {
  133.             dumpFile(fname);
  134.         } /* else */
  135.  
  136.         free(fname);
  137.     } /* else */
  138. } /* unpackCallback */
  139.  
  140.  
  141. int main(int argc, char **argv)
  142. {
  143.     int zero = 0;
  144.  
  145.     if (argc != 3)
  146.     {
  147.         fprintf(stderr, "USAGE: %s <archive> <unpackDirectory>\n", argv[0]);
  148.         return 1;
  149.     } /* if */
  150.  
  151.     if (!PHYSFS_init(argv[0]))
  152.     {
  153.         fprintf(stderr, "PHYSFS_init() failed: %s\n", PHYSFS_getLastError());
  154.         return 2;
  155.     } /* if */
  156.  
  157.     if (!PHYSFS_setWriteDir(argv[2]))
  158.     {
  159.         fprintf(stderr, "PHYSFS_setWriteDir('%s') failed: %s\n",
  160.                 argv[2], PHYSFS_getLastError());
  161.         return 3;
  162.     } /* if */
  163.  
  164.     if (!PHYSFS_mount(argv[1], NULL, 1))
  165.     {
  166.         fprintf(stderr, "PHYSFS_mount('%s') failed: %s\n",
  167.                 argv[1], PHYSFS_getLastError());
  168.         return 4;
  169.     } /* if */
  170.  
  171.     PHYSFS_permitSymbolicLinks(1);
  172.     PHYSFS_enumerateFilesCallback("/", unpackCallback, &zero);
  173.     PHYSFS_deinit();
  174.     if (failure)
  175.         return 5;
  176.  
  177.     return 0;
  178. } /* main */
  179.  
  180. /* end of physfsunpack.c ... */
  181.  
  182.