Panda3D
 All Classes Functions Variables Enumerations
pzip.cxx
00001 // Filename: pzip.cxx
00002 // Created by:  
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "filename.h"
00016 #include "compress_string.h"
00017 #include "pnotify.h"
00018 #include "panda_getopt.h"
00019 #include "preprocess_argv.h"
00020 
00021 void
00022 usage() {
00023   cerr
00024     << "\nUsage:\n"
00025     << "   pzip file [file2 file3 ...]\n"
00026     << "   pzip -c <file >dest_file\n"
00027     << "   pzip -o dest_file file\n\n"
00028 
00029     << "This program compresses the named file(s) using the Panda native\n"
00030     << "compression algorithm (gzip in practice, but with a different file\n"
00031     << "header).  The compressed versions are written to a file with the\n"
00032     << "same name as the original, but the extension .pz added to the\n"
00033     << "filename, and the original file is removed (unless the version with\n"
00034     << "-o is used, in which case you can compress only one file, you specify\n"
00035     << "the destination file name, and the original file is not removed).\n\n"
00036     
00037     << "In many cases, Panda can read the resulting .pz file directly,\n"
00038     << "exactly as if it were still in its uncompressed original form.\n"
00039     << "In fact, unless vfs-implicit-pz is set to false in your Config.prc\n"
00040     << "file, you can also load the file by referencing it with its original\n"
00041     << "filename (without the .pz extension), even though it no longer exists\n"
00042     << "under that filename, and Panda will find the .pz file and transparently\n"
00043     << "decompress it on the fly, as if the original, uncompressed file still\n"
00044     << "existed.\n\n"
00045 
00046     << "Note that if you are adding files to a Panda multifile (.mf file) with\n"
00047     << "the multify command, it is not necessary to compress them separately;\n"
00048     << "multify has an inline compression option.\n\n"
00049 
00050     << "Options:\n\n"
00051 
00052     << "  -1  compress faster\n"
00053     << "  -6  compress default\n"
00054     << "  -9  compress better (intermediate compression levels supported also)\n\n";
00055     
00056 }
00057 
00058 int
00059 main(int argc, char **argv) {
00060   extern char *optarg;
00061   extern int optind;
00062   const char *optstr = "o:c123456789h";
00063 
00064   Filename dest_filename;
00065   bool got_dest_filename = false;
00066   bool use_stdout = false;
00067   int compression_level = 6;
00068 
00069   preprocess_argv(argc, argv);
00070   int flag = getopt(argc, argv, optstr);
00071 
00072   while (flag != EOF) {
00073     switch (flag) {
00074     case 'o':
00075       dest_filename = Filename::from_os_specific(optarg);
00076       got_dest_filename = true;
00077       break;
00078 
00079     case 'c':
00080       use_stdout = true;
00081       break;
00082 
00083     case '1':
00084       compression_level = 1;
00085       break;
00086 
00087     case '2':
00088       compression_level = 2;
00089       break;
00090 
00091     case '3':
00092       compression_level = 3;
00093       break;
00094 
00095     case '4':
00096       compression_level = 4;
00097       break;
00098 
00099     case '5':
00100       compression_level = 5;
00101       break;
00102 
00103     case '6':
00104       compression_level = 6;
00105       break;
00106 
00107     case '7':
00108       compression_level = 7;
00109       break;
00110 
00111     case '8':
00112       compression_level = 8;
00113       break;
00114 
00115     case '9':
00116       compression_level = 9;
00117       break;
00118 
00119     case 'h':
00120     case '?':
00121     default:
00122       usage();
00123       return 1;
00124     }
00125     flag = getopt(argc, argv, optstr);
00126   }
00127 
00128   argc -= (optind-1);
00129   argv += (optind-1);
00130 
00131   if (use_stdout) {
00132     if (argc > 1) {
00133       cerr << "No filenames allowed in conjunction with -c.\n";
00134       return 1;
00135     }
00136 
00137     bool success = compress_stream(cin, cout, compression_level);
00138     if (!success) {
00139       cerr << "Failure compressing standard input\n";
00140       return 1;
00141     }
00142     return 0;
00143   }
00144 
00145   if (argc < 2) {
00146     usage();
00147     return 1;
00148   }
00149 
00150   if (got_dest_filename && argc > 2) {
00151     cerr << "Only one input file allowed in conjunction with -o.\n";
00152     return 1;
00153   }
00154 
00155   bool all_ok = true;
00156   for (int i = 1; i < argc; i++) {
00157     Filename source_file = Filename::from_os_specific(argv[i]);
00158     if (source_file.get_extension() == "pz") {
00159       cerr << source_file << " already ends .pz; skipping.\n";
00160     } else {
00161       Filename dest_file = dest_filename;
00162       if (!got_dest_filename) {
00163         dest_file = source_file.get_fullpath() + ".pz";
00164       }
00165 
00166       // Open source file
00167       pifstream read_stream;
00168       source_file.set_binary();
00169       if (!source_file.open_read(read_stream)) {
00170         cerr << "Couldn't read: " << source_file << endl;
00171         all_ok = false;
00172 
00173       } else {
00174         // Open destination file
00175         pofstream write_stream;
00176         dest_file.set_binary();
00177         if (!dest_file.open_write(write_stream, true)) {
00178           cerr << "Failed to open: " << dest_file << endl;
00179           all_ok = false;
00180 
00181         } else {
00182           cerr << dest_file << "\n";
00183           bool success = compress_stream(read_stream, write_stream, compression_level);
00184           
00185           read_stream.close();
00186           write_stream.close();
00187           
00188           if (!success) {
00189             cerr << "Failure writing " << dest_file << "\n";
00190             all_ok = false;
00191             dest_file.unlink();
00192             
00193           } else {
00194             if (!got_dest_filename) {
00195               source_file.unlink();
00196             }
00197           }
00198         }
00199       }
00200     }
00201   }
00202 
00203   if (all_ok) {
00204     return 0;
00205   } else {
00206     return 1;
00207   }
00208 }
 All Classes Functions Variables Enumerations