🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
4.3 KiB

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