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