Panda3D
pzip.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file pzip.cxx
10  */
11 
12 #include "filename.h"
13 #include "compress_string.h"
14 #include "pnotify.h"
15 #include "panda_getopt.h"
16 #include "preprocess_argv.h"
17 
18 using std::cerr;
19 using std::cin;
20 using std::cout;
21 using std::endl;
22 
23 void
24 usage() {
25  cerr
26  << "\nUsage:\n"
27  << " pzip file [file2 file3 ...]\n"
28  << " pzip -c <file >dest_file\n"
29  << " pzip -o dest_file file\n\n"
30 
31  << "This program compresses the named file(s) using the Panda native\n"
32  << "compression algorithm (gzip in practice, but with a different file\n"
33  << "header). The compressed versions are written to a file with the\n"
34  << "same name as the original, but the extension .pz added to the\n"
35  << "filename, and the original file is removed (unless the version with\n"
36  << "-o is used, in which case you can compress only one file, you specify\n"
37  << "the destination file name, and the original file is not removed).\n\n"
38 
39  << "In many cases, Panda can read the resulting .pz file directly,\n"
40  << "exactly as if it were still in its uncompressed original form.\n"
41  << "In fact, unless vfs-implicit-pz is set to false in your Config.prc\n"
42  << "file, you can also load the file by referencing it with its original\n"
43  << "filename (without the .pz extension), even though it no longer exists\n"
44  << "under that filename, and Panda will find the .pz file and transparently\n"
45  << "decompress it on the fly, as if the original, uncompressed file still\n"
46  << "existed.\n\n"
47 
48  << "Note that if you are adding files to a Panda multifile (.mf file) with\n"
49  << "the multify command, it is not necessary to compress them separately;\n"
50  << "multify has an inline compression option.\n\n"
51 
52  << "Options:\n\n"
53 
54  << " -1 compress faster\n"
55  << " -6 compress default\n"
56  << " -9 compress better (intermediate compression levels supported also)\n\n";
57 
58 }
59 
60 int
61 main(int argc, char **argv) {
62  extern char *optarg;
63  extern int optind;
64  const char *optstr = "o:c123456789h";
65 
66  Filename dest_filename;
67  bool got_dest_filename = false;
68  bool use_stdout = false;
69  int compression_level = 6;
70 
71  preprocess_argv(argc, argv);
72  int flag = getopt(argc, argv, optstr);
73 
74  while (flag != EOF) {
75  switch (flag) {
76  case 'o':
77  dest_filename = Filename::from_os_specific(optarg);
78  got_dest_filename = true;
79  break;
80 
81  case 'c':
82  use_stdout = true;
83  break;
84 
85  case '1':
86  compression_level = 1;
87  break;
88 
89  case '2':
90  compression_level = 2;
91  break;
92 
93  case '3':
94  compression_level = 3;
95  break;
96 
97  case '4':
98  compression_level = 4;
99  break;
100 
101  case '5':
102  compression_level = 5;
103  break;
104 
105  case '6':
106  compression_level = 6;
107  break;
108 
109  case '7':
110  compression_level = 7;
111  break;
112 
113  case '8':
114  compression_level = 8;
115  break;
116 
117  case '9':
118  compression_level = 9;
119  break;
120 
121  case 'h':
122  case '?':
123  default:
124  usage();
125  return 1;
126  }
127  flag = getopt(argc, argv, optstr);
128  }
129 
130  argc -= (optind-1);
131  argv += (optind-1);
132 
133  if (use_stdout) {
134  if (argc > 1) {
135  cerr << "No filenames allowed in conjunction with -c.\n";
136  return 1;
137  }
138 
139  bool success = compress_stream(cin, cout, compression_level);
140  if (!success) {
141  cerr << "Failure compressing standard input\n";
142  return 1;
143  }
144  return 0;
145  }
146 
147  if (argc < 2) {
148  usage();
149  return 1;
150  }
151 
152  if (got_dest_filename && argc > 2) {
153  cerr << "Only one input file allowed in conjunction with -o.\n";
154  return 1;
155  }
156 
157  bool all_ok = true;
158  for (int i = 1; i < argc; i++) {
159  Filename source_file = Filename::from_os_specific(argv[i]);
160  if (source_file.get_extension() == "pz") {
161  cerr << source_file << " already ends .pz; skipping.\n";
162  } else {
163  Filename dest_file = dest_filename;
164  if (!got_dest_filename) {
165  dest_file = source_file.get_fullpath() + ".pz";
166  }
167 
168  // Open source file
169  pifstream read_stream;
170  source_file.set_binary();
171  if (!source_file.open_read(read_stream)) {
172  cerr << "Couldn't read: " << source_file << endl;
173  all_ok = false;
174 
175  } else {
176  // Open destination file
177  pofstream write_stream;
178  dest_file.set_binary();
179  if (!dest_file.open_write(write_stream, true)) {
180  cerr << "Failed to open: " << dest_file << endl;
181  all_ok = false;
182 
183  } else {
184  cerr << dest_file << "\n";
185  bool success = compress_stream(read_stream, write_stream, compression_level);
186 
187  read_stream.close();
188  write_stream.close();
189 
190  if (!success) {
191  cerr << "Failure writing " << dest_file << "\n";
192  all_ok = false;
193  dest_file.unlink();
194 
195  } else {
196  if (!got_dest_filename) {
197  source_file.unlink();
198  }
199  }
200  }
201  }
202  }
203  }
204 
205  if (all_ok) {
206  return 0;
207  } else {
208  return 1;
209  }
210 }
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
bool open_read(std::ifstream &stream) const
Opens the indicated ifstream for reading the file, if possible.
Definition: filename.cxx:1863
bool unlink() const
Permanently deletes the file associated with the filename, if possible.
Definition: filename.cxx:2319
void set_binary()
Indicates that the filename represents a binary file.
Definition: filename.I:414
std::string get_fullpath() const
Returns the entire filename: directory, basename, extension.
Definition: filename.I:338
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
Definition: filename.cxx:328
bool open_write(std::ofstream &stream, bool truncate=true) const
Opens the indicated ifstream for writing the file, if possible.
Definition: filename.cxx:1899
std::string get_extension() const
Returns the file extension.
Definition: filename.I:400
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void preprocess_argv(int &argc, char **&argv)
Processes the argc, argv pair as needed before passing it to getopt().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.