zipper.cc 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // Copyright (C) 2011 Michael McMaster <michael@codesrc.com>
  2. //
  3. // This file is part of libzipper.
  4. //
  5. // libzipper is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // libzipper is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with libzipper. If not, see <http://www.gnu.org/licenses/>.
  17. #include "zipper.hh"
  18. #include "split.hh"
  19. #include <errno.h>
  20. #include "strerror.hh"
  21. #include <cassert>
  22. #include <cstdlib>
  23. #include <deque>
  24. #include <iostream>
  25. #include <sstream>
  26. #include <string>
  27. #include "config.h"
  28. using namespace zipper;
  29. static std::string argv0;
  30. static void usage()
  31. {
  32. std::cerr <<
  33. "libzipper Copyright (C) 2011 Michael McMaster <michael@codesrc.com>\n"
  34. "This program comes with ABSOLUTELY NO WARRANTY.\n"
  35. "This is free software, and you are welcome to redistribute it\n"
  36. "under certain conditions.\n\n" <<
  37. "Usage: \n" <<
  38. argv0 << " {zip|gzip} archive file [files...]\n" <<
  39. argv0 << " {unzip|gunzip} archive" << std::endl;
  40. }
  41. static WriterPtr
  42. getWriter(const std::string& optionName)
  43. {
  44. std::shared_ptr<FileWriter> writer;
  45. if (optionName == "-")
  46. {
  47. writer.reset(new FileWriter("stdout", 1, false));
  48. }
  49. else
  50. {
  51. writer.reset(new FileWriter(optionName, 0660));
  52. }
  53. return writer;
  54. }
  55. static ReaderPtr
  56. getReader(const std::string& optionName)
  57. {
  58. std::shared_ptr<FileReader> reader;
  59. if (optionName == "-")
  60. {
  61. reader.reset(new FileReader("stdin", 0, false));
  62. }
  63. else
  64. {
  65. reader.reset(new FileReader(optionName));
  66. }
  67. return reader;
  68. }
  69. static void
  70. command_zip(const std::deque<std::string>& options)
  71. {
  72. if (options.size() < 2)
  73. {
  74. usage();
  75. exit(EXIT_FAILURE);
  76. }
  77. WriterPtr writer(getWriter(options[0]));
  78. Compressor comp(Container_zip, writer);
  79. for (size_t i = 1; i < options.size(); ++i)
  80. {
  81. ReaderPtr reader(getReader(options[i]));
  82. comp.addFile(*reader);
  83. }
  84. }
  85. static void
  86. command_gzip(const std::deque<std::string>& options)
  87. {
  88. if (options.size() != 2)
  89. {
  90. usage();
  91. exit(EXIT_FAILURE);
  92. }
  93. WriterPtr writer(getWriter(options[0]));
  94. Compressor comp(Container_gzip, writer);
  95. for (size_t i = 1; i < options.size(); ++i)
  96. {
  97. ReaderPtr reader(getReader(options[i]));
  98. comp.addFile(*reader);
  99. }
  100. }
  101. static void
  102. command_extract(const std::deque<std::string>& options)
  103. {
  104. if (options.size() != 1)
  105. {
  106. usage();
  107. exit(EXIT_FAILURE);
  108. }
  109. ReaderPtr reader(getReader(options[0]));
  110. Decompressor decomp(reader);
  111. std::vector<CompressedFilePtr> entries(decomp.getEntries());
  112. for (size_t f = 0; f < entries.size(); ++f)
  113. {
  114. std::deque<std::string> path;
  115. split(
  116. entries[f]->getPath(),
  117. '/',
  118. std::back_insert_iterator<std::deque<std::string> >(path));
  119. path.pop_back(); // Remove extracted file.
  120. std::stringstream builtPath;
  121. for (std::deque<std::string>::iterator it(path.begin());
  122. it != path.end();
  123. ++it)
  124. {
  125. builtPath << *it;
  126. int result(MKDIR(builtPath.str().c_str(), 0775));
  127. if (result != 0 && errno != EEXIST)
  128. {
  129. std::string errMsg(zipper::strerror(errno));
  130. std::stringstream message;
  131. message << "Could not create directory " <<
  132. "\"" <<builtPath.str() << "\": " << errMsg;
  133. throw IOException(message.str());
  134. }
  135. builtPath << '/';
  136. }
  137. FileWriter writer(
  138. entries[f]->getPath(), 0660, entries[f]->getModificationTime());
  139. entries[f]->decompress(writer);
  140. }
  141. }
  142. int main(int argc, char** argv)
  143. {
  144. argv0 = argv[0];
  145. if (argc < 3)
  146. {
  147. usage();
  148. exit(EXIT_FAILURE);
  149. }
  150. std::deque<std::string> options;
  151. for (int i = 1; i < argc; ++i)
  152. {
  153. options.push_back(argv[i]);
  154. }
  155. std::string command(options[0]);
  156. options.pop_front();
  157. if (command == "zip")
  158. {
  159. command_zip(options);
  160. }
  161. else if (command == "gzip")
  162. {
  163. command_gzip(options);
  164. }
  165. else if (command == "gunzip" || command == "unzip")
  166. {
  167. command_extract(options);
  168. }
  169. else
  170. {
  171. usage();
  172. exit(EXIT_FAILURE);
  173. }
  174. return EXIT_SUCCESS;
  175. }