David Rose 16 tahun lalu
induk
melakukan
d807610d32

+ 27 - 4
panda/src/downloadertools/multify.cxx

@@ -31,9 +31,9 @@ bool append = false;           // -r
 bool update = false;           // -u
 bool update = false;           // -u
 bool tlist = false;            // -t
 bool tlist = false;            // -t
 bool extract = false;          // -x
 bool extract = false;          // -x
-bool kill_cmd = false;             // -k
+bool kill_cmd = false;         // -k
 bool verbose = false;          // -v
 bool verbose = false;          // -v
-bool compress_flag = false;         // -z
+bool compress_flag = false;    // -z
 int default_compression_level = 6;
 int default_compression_level = 6;
 Filename multifile_name;       // -f
 Filename multifile_name;       // -f
 bool got_multifile_name = false;
 bool got_multifile_name = false;
@@ -41,13 +41,15 @@ bool to_stdout = false;        // -O
 bool encryption_flag = false;  // -e
 bool encryption_flag = false;  // -e
 string password;               // -p
 string password;               // -p
 bool got_password = false;
 bool got_password = false;
+string header_prefix;          // -P
+bool got_header_prefix = false;
 Filename chdir_to;             // -C
 Filename chdir_to;             // -C
 bool got_chdir_to = false;
 bool got_chdir_to = false;
 size_t scale_factor = 0;       // -F
 size_t scale_factor = 0;       // -F
 pset<string> dont_compress;    // -Z
 pset<string> dont_compress;    // -Z
 
 
 // Default extensions not to compress.  May be overridden with -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 got_record_timestamp_flag = false;
 bool record_timestamp_flag = true;
 bool record_timestamp_flag = true;
@@ -178,6 +180,15 @@ help() {
     "      specified, and passwords are required, the user will be prompted from\n"
     "      specified, and passwords are required, the user will be prompted from\n"
     "      standard input.\n\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 <scale_factor>\n"
     "  -F <scale_factor>\n"
     "      Specify a Multifile scale factor.  This is only necessary to support\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"
     "      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());
     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()) {
   if (scale_factor != 0 && scale_factor != multifile->get_scale_factor()) {
     cerr << "Setting scale factor to " << scale_factor << "\n";
     cerr << "Setting scale factor to " << scale_factor << "\n";
     multifile->set_scale_factor(scale_factor);
     multifile->set_scale_factor(scale_factor);
@@ -451,6 +466,10 @@ kill_files(int argc, char *argv[]) {
     return false;
     return false;
   }
   }
 
 
+  if (got_header_prefix) {
+    multifile->set_header_prefix(header_prefix);
+  }
+
   int i = 0;
   int i = 0;
   while (i < multifile->get_num_subfiles()) {
   while (i < multifile->get_num_subfiles()) {
     string subfile_name = multifile->get_subfile_name(i);
     string subfile_name = multifile->get_subfile_name(i);
@@ -628,7 +647,7 @@ main(int argc, char *argv[]) {
 
 
   extern char *optarg;
   extern char *optarg;
   extern int optind;
   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);
   int flag = getopt(argc, argv, optflags);
   Filename rel_path;
   Filename rel_path;
   while (flag != EOF) {
   while (flag != EOF) {
@@ -727,6 +746,10 @@ main(int argc, char *argv[]) {
       password = optarg;
       password = optarg;
       got_password = true;
       got_password = true;
       break;
       break;
+    case 'P':
+      header_prefix = optarg;
+      got_header_prefix = true;
+      break;
     case 'F':
     case 'F':
       {
       {
         char *endptr;
         char *endptr;

+ 0 - 19
panda/src/express/multifile.I

@@ -377,25 +377,6 @@ get_magic_number() {
   return string(_header, _header_size);
   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
 //     Function: Multifile::get_header_prefix
 //       Access: Published
 //       Access: Published

+ 68 - 22
panda/src/express/multifile.cxx

@@ -691,7 +691,7 @@ flush() {
   // Also update the overall timestamp.
   // Also update the overall timestamp.
   if (_timestamp_dirty) {
   if (_timestamp_dirty) {
     nassertr(!_write->fail(), false);
     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);
     _write->seekp(timestamp_pos);
     nassertr(!_write->fail(), false);
     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
 //     Function: Multifile::read_subfile
 //       Access: Public
 //       Access: Public
@@ -1535,28 +1585,17 @@ read_index() {
 
 
   char this_header[_header_size];
   char this_header[_header_size];
   read->seekg(0);
   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
   // 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();
   _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 == '#') {
     while (ch != EOF && ch == '#') {
       // Skip to the end of the line.
       // Skip to the end of the line.
       while (ch != EOF && ch != '\n') {
       while (ch != EOF && ch != '\n') {
@@ -1569,10 +1608,17 @@ read_index() {
         ch = read->get();
         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) {
   if (memcmp(this_header, _header, _header_size) != 0) {

+ 1 - 1
panda/src/express/multifile.h

@@ -114,7 +114,7 @@ PUBLISHED:
 
 
   static INLINE string get_magic_number();
   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;
   INLINE const string &get_header_prefix() const;
 
 
 public:
 public: