zipper.cc 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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. using namespace zipper;
  28. static std::string argv0;
  29. static void usage()
  30. {
  31. std::cerr <<
  32. "libzipper Copyright (C) 2011 Michael McMaster <michael@codesrc.com>\n"
  33. "This program comes with ABSOLUTELY NO WARRANTY.\n"
  34. "This is free software, and you are welcome to redistribute it\n"
  35. "under certain conditions.\n\n" <<
  36. "Usage: \n" <<
  37. argv0 << " {zip|gzip} archive file [files...]\n" <<
  38. argv0 << " {unzip|gunzip} archive" << std::endl;
  39. }
  40. static WriterPtr
  41. getWriter(const std::string& optionName)
  42. {
  43. std::shared_ptr<FileWriter> writer;
  44. if (optionName == "-")
  45. {
  46. writer.reset(new FileWriter("stdout", 1, false));
  47. }
  48. else
  49. {
  50. writer.reset(new FileWriter(optionName, 0660));
  51. }
  52. return writer;
  53. }
  54. static ReaderPtr
  55. getReader(const std::string& optionName)
  56. {
  57. std::shared_ptr<FileReader> reader;
  58. if (optionName == "-")
  59. {
  60. reader.reset(new FileReader("stdin", 0, false));
  61. }
  62. else
  63. {
  64. reader.reset(new FileReader(optionName));
  65. }
  66. return reader;
  67. }
  68. static void
  69. command_zip(const std::deque<std::string>& options)
  70. {
  71. if (options.size() < 2)
  72. {
  73. usage();
  74. exit(EXIT_FAILURE);
  75. }
  76. WriterPtr writer(getWriter(options[0]));
  77. Compressor comp(Container_zip, writer);
  78. for (size_t i = 1; i < options.size(); ++i)
  79. {
  80. ReaderPtr reader(getReader(options[i]));
  81. comp.addFile(*reader);
  82. }
  83. }
  84. static void
  85. command_gzip(const std::deque<std::string>& options)
  86. {
  87. if (options.size() != 2)
  88. {
  89. usage();
  90. exit(EXIT_FAILURE);
  91. }
  92. WriterPtr writer(getWriter(options[0]));
  93. Compressor comp(Container_gzip, writer);
  94. for (size_t i = 1; i < options.size(); ++i)
  95. {
  96. ReaderPtr reader(getReader(options[i]));
  97. comp.addFile(*reader);
  98. }
  99. }
  100. static void
  101. command_extract(const std::deque<std::string>& options)
  102. {
  103. if (options.size() != 1)
  104. {
  105. usage();
  106. exit(EXIT_FAILURE);
  107. }
  108. ReaderPtr reader(getReader(options[0]));
  109. Decompressor decomp(reader);
  110. std::vector<CompressedFilePtr> entries(decomp.getEntries());
  111. for (size_t f = 0; f < entries.size(); ++f)
  112. {
  113. std::deque<std::string> path;
  114. split(
  115. entries[f]->getPath(),
  116. '/',
  117. std::back_insert_iterator<std::deque<std::string> >(path));
  118. path.pop_back(); // Remove extracted file.
  119. std::stringstream builtPath;
  120. for (std::deque<std::string>::iterator it(path.begin());
  121. it != path.end();
  122. ++it)
  123. {
  124. builtPath << *it;
  125. int result(mkdir(builtPath.str().c_str(), 0775));
  126. if (result != 0 && errno != EEXIST)
  127. {
  128. std::string errMsg(zipper::strerror(errno));
  129. std::stringstream message;
  130. message << "Could not create directory " <<
  131. "\"" <<builtPath.str() << "\": " << errMsg;
  132. throw IOException(message.str());
  133. }
  134. builtPath << '/';
  135. }
  136. FileWriter writer(
  137. entries[f]->getPath(), 0660, entries[f]->getModificationTime());
  138. entries[f]->decompress(writer);
  139. }
  140. }
  141. int main(int argc, char** argv)
  142. {
  143. argv0 = argv[0];
  144. if (argc < 3)
  145. {
  146. usage();
  147. exit(EXIT_FAILURE);
  148. }
  149. std::deque<std::string> options;
  150. for (int i = 1; i < argc; ++i)
  151. {
  152. options.push_back(argv[i]);
  153. }
  154. std::string command(options[0]);
  155. options.pop_front();
  156. if (command == "zip")
  157. {
  158. command_zip(options);
  159. }
  160. else if (command == "gzip")
  161. {
  162. command_gzip(options);
  163. }
  164. else if (command == "gunzip" || command == "unzip")
  165. {
  166. command_extract(options);
  167. }
  168. else
  169. {
  170. usage();
  171. exit(EXIT_FAILURE);
  172. }
  173. return EXIT_SUCCESS;
  174. }