From d807610d329393680fe1616cdafd36621f871c47 Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 4 Sep 2009 21:38:43 +0000 Subject: [PATCH] multify -P --- panda/src/downloadertools/multify.cxx | 31 +++++++-- panda/src/express/multifile.I | 19 ------ panda/src/express/multifile.cxx | 90 ++++++++++++++++++++------- panda/src/express/multifile.h | 2 +- 4 files changed, 96 insertions(+), 46 deletions(-) diff --git a/panda/src/downloadertools/multify.cxx b/panda/src/downloadertools/multify.cxx index da33f6cc0d..6e5bce4343 100644 --- a/panda/src/downloadertools/multify.cxx +++ b/panda/src/downloadertools/multify.cxx @@ -31,9 +31,9 @@ bool append = false; // -r bool update = false; // -u bool tlist = false; // -t bool extract = false; // -x -bool kill_cmd = false; // -k +bool kill_cmd = false; // -k bool verbose = false; // -v -bool compress_flag = false; // -z +bool compress_flag = false; // -z int default_compression_level = 6; Filename multifile_name; // -f bool got_multifile_name = false; @@ -41,13 +41,15 @@ bool to_stdout = false; // -O bool encryption_flag = false; // -e string password; // -p bool got_password = false; +string header_prefix; // -P +bool got_header_prefix = false; Filename chdir_to; // -C bool got_chdir_to = false; size_t scale_factor = 0; // -F pset dont_compress; // -Z // Default extensions not to compress. May be overridden with -Z. -string dont_compress_str = "jpg,mp3"; +string dont_compress_str = "jpg,png,mp3,ogg"; bool got_record_timestamp_flag = false; bool record_timestamp_flag = true; @@ -178,6 +180,15 @@ help() { " specified, and passwords are required, the user will be prompted from\n" " standard input.\n\n" + " -P \"prefix\"\n" + " Specifies a header_prefix to write to the beginning of the multifile.\n" + " This is primarily useful for creating a multifile that can be invoked\n" + " directly as a program from the shell on Unix-like environments,\n" + " for instance, p3d files. The header_prefix must begin with a hash\n" + " mark and end with a newline; this will be enforced if it is not\n" + " already so. This only has effect in conjunction with with -c, -u,\n" + " or -k.\n\n" + " -F \n" " Specify a Multifile scale factor. This is only necessary to support\n" " Multifiles that will exceed 4GB in size. The default scale factor is\n" @@ -330,6 +341,10 @@ add_files(int argc, char *argv[]) { multifile->set_encryption_password(get_password()); } + if (got_header_prefix) { + multifile->set_header_prefix(header_prefix); + } + if (scale_factor != 0 && scale_factor != multifile->get_scale_factor()) { cerr << "Setting scale factor to " << scale_factor << "\n"; multifile->set_scale_factor(scale_factor); @@ -451,6 +466,10 @@ kill_files(int argc, char *argv[]) { return false; } + if (got_header_prefix) { + multifile->set_header_prefix(header_prefix); + } + int i = 0; while (i < multifile->get_num_subfiles()) { string subfile_name = multifile->get_subfile_name(i); @@ -628,7 +647,7 @@ main(int argc, char *argv[]) { extern char *optarg; extern int optind; - static const char *optflags = "crutxkvz123456789Z:T:f:OC:ep:F:h"; + static const char *optflags = "crutxkvz123456789Z:T:f:OC:ep:P:F:h"; int flag = getopt(argc, argv, optflags); Filename rel_path; while (flag != EOF) { @@ -727,6 +746,10 @@ main(int argc, char *argv[]) { password = optarg; got_password = true; break; + case 'P': + header_prefix = optarg; + got_header_prefix = true; + break; case 'F': { char *endptr; diff --git a/panda/src/express/multifile.I b/panda/src/express/multifile.I index a5a47cfb01..23c2130be8 100644 --- a/panda/src/express/multifile.I +++ b/panda/src/express/multifile.I @@ -377,25 +377,6 @@ get_magic_number() { return string(_header, _header_size); } -//////////////////////////////////////////////////////////////////// -// Function: Multifile::set_header_prefix -// Access: Published -// Description: Sets the string which is written to the Multifile -// before the Multifile header. This string must begin -// with a hash mark and end with a newline character, -// and include at least 6 characters; and if it includes -// embedded newline characters, each one must be -// followed by a hash mark. -// -// This is primarily useful as a simple hack to allow -// p3d applications to be run directly from the command -// line on Unix-like systems. -//////////////////////////////////////////////////////////////////// -INLINE void Multifile:: -set_header_prefix(const string &header_prefix) { - _header_prefix = header_prefix; -} - //////////////////////////////////////////////////////////////////// // Function: Multifile::get_header_prefix // Access: Published diff --git a/panda/src/express/multifile.cxx b/panda/src/express/multifile.cxx index 4966add1a9..e254942b8e 100644 --- a/panda/src/express/multifile.cxx +++ b/panda/src/express/multifile.cxx @@ -691,7 +691,7 @@ flush() { // Also update the overall timestamp. if (_timestamp_dirty) { nassertr(!_write->fail(), false); - static const size_t timestamp_pos = _header_size + 2 + 2 + 4; + static const size_t timestamp_pos = _header_prefix.size() + _header_size + 2 + 2 + 4; _write->seekp(timestamp_pos); nassertr(!_write->fail(), false); @@ -1336,7 +1336,57 @@ ls(ostream &out) const { } } +//////////////////////////////////////////////////////////////////// +// Function: Multifile::set_header_prefix +// Access: Published +// Description: Sets the string which is written to the Multifile +// before the Multifile header. This string must begin +// with a hash mark and end with a newline character; +// and if it includes embedded newline characters, each +// one must be followed by a hash mark. If these +// conditions are not initially true, the string will be +// modified as necessary to make it so. +// +// This is primarily useful as a simple hack to allow +// p3d applications to be run directly from the command +// line on Unix-like systems. +// +// The return value is true if successful, or false on +// failure (for instance, because the header prefix +// violates the above rules). +//////////////////////////////////////////////////////////////////// +void Multifile:: +set_header_prefix(const string &header_prefix) { + string new_header_prefix = header_prefix; + if (!new_header_prefix.empty()) { + // It must begin with a hash mark. + if (new_header_prefix[0] != '#') { + new_header_prefix = string("#") + new_header_prefix; + } + + // It must end with a newline. + if (new_header_prefix[new_header_prefix.size() - 1] != '\n') { + new_header_prefix += string("\n"); + } + + // Embedded newlines must be followed by a hash mark. + size_t newline = new_header_prefix.find('\n'); + while (newline < new_header_prefix.size() - 1) { + if (new_header_prefix[newline + 1] != '#') { + new_header_prefix = new_header_prefix.substr(0, newline + 1) + string("#") + new_header_prefix.substr(newline + 1); + } + newline = new_header_prefix.find('#', newline); + } + } + + if (_header_prefix != new_header_prefix) { + _header_prefix = new_header_prefix; + _needs_repack = true; + } +} + + //////////////////////////////////////////////////////////////////// // Function: Multifile::read_subfile // Access: Public @@ -1535,28 +1585,17 @@ read_index() { char this_header[_header_size]; read->seekg(0); - read->read(this_header, _header_size); - if (read->fail() || read->gcount() != (unsigned)_header_size) { - express_cat.info() - << "Unable to read Multifile header " << _multifile_name << ".\n"; - _read->release(); - close(); - return false; - } // Here's a special case: if the multifile begins with a hash - // character, then we skip at least 6 characters (the length of the - // original header string we already read), and continue reading and - // discarding lines of ASCII text, until we come across a nonempty - // line that does not begin with a hash character. This allows a - // P3D application (which is a multifile) to be run directly on the - // command line on Unix-based systems. + // character, then we continue reading and discarding lines of ASCII + // text, until we come across a nonempty line that does not begin + // with a hash character. This allows a P3D application (which is a + // multifile) to be run directly on the command line on Unix-based + // systems. _header_prefix = string(); + int ch = read->get(); - if (this_header[0] == '#') { - _header_prefix = string(this_header, _header_size); - int ch = '#'; - + if (ch == '#') { while (ch != EOF && ch == '#') { // Skip to the end of the line. while (ch != EOF && ch != '\n') { @@ -1569,10 +1608,17 @@ read_index() { ch = read->get(); } } + } - // Now fill up the header. - this_header[0] = ch; - read->read(this_header + 1, _header_size - 1); + // Now read the actual Multifile header. + this_header[0] = ch; + read->read(this_header + 1, _header_size - 1); + if (read->fail() || read->gcount() != (unsigned)(_header_size - 1)) { + express_cat.info() + << "Unable to read Multifile header " << _multifile_name << ".\n"; + _read->release(); + close(); + return false; } if (memcmp(this_header, _header, _header_size) != 0) { diff --git a/panda/src/express/multifile.h b/panda/src/express/multifile.h index 21c8cf449e..04d79c30c6 100644 --- a/panda/src/express/multifile.h +++ b/panda/src/express/multifile.h @@ -114,7 +114,7 @@ PUBLISHED: static INLINE string get_magic_number(); - INLINE void set_header_prefix(const string &header_prefix); + void set_header_prefix(const string &header_prefix); INLINE const string &get_header_prefix() const; public: