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 }
bool open_write(std::ofstream &stream, bool truncate=true) const
Opens the indicated ifstream for writing the file, if possible.
Definition: filename.cxx:1899
void set_binary()
Indicates that the filename represents a binary file.
Definition: filename.I:414
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool open_read(std::ifstream &stream) const
Opens the indicated ifstream for reading the file, if possible.
Definition: filename.cxx:1863
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
std::string get_fullpath() const
Returns the entire filename: directory, basename, extension.
Definition: filename.I:338
bool unlink() const
Permanently deletes the file associated with the filename, if possible.
Definition: filename.cxx:2319
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::string get_extension() const
Returns the file extension.
Definition: filename.I:400
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.
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