Panda3D

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