Panda3D

multifile.I
Go to the documentation of this file.
1 /**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file multifile.I
10 * @author mike
11 * @date 1997-01-09
12 */
13
14 /**
15 * Returns the filename of the Multifile, if it is available.
16 */
17 INLINE const Filename &Multifile::
18 get_multifile_name() const {
19 return _multifile_name;
20 }
21
22 /**
23 * Replaces the filename of the Multifile. This is primarily used for
24 * documentation purposes only; changing this name does not open the indicated
25 * file. See open_read() or open_write() for that.
26 */
27 INLINE void Multifile::
28 set_multifile_name(const Filename &multifile_name) {
29 _multifile_name = multifile_name;
30 }
31
32 /**
33 * Returns true if the Multifile has been opened for read mode and there have
34 * been no errors, and individual Subfile contents may be extracted.
35 */
36 INLINE bool Multifile::
37 is_read_valid() const {
38 return (_read != nullptr);
39 }
40
41 /**
42 * Returns true if the Multifile has been opened for write mode and there have
43 * been no errors, and Subfiles may be added or removed from the Multifile.
44 */
45 INLINE bool Multifile::
46 is_write_valid() const {
47 return (_write != nullptr && !_write->fail());
48 }
49
50 /**
51 * Returns true if the Multifile index is suboptimal and should be repacked.
52 * Call repack() to achieve this.
53 */
54 INLINE bool Multifile::
55 needs_repack() const {
56 return _needs_repack || (_scale_factor != _new_scale_factor);
57 }
58
59 /**
60 * Returns the modification timestamp of the overall Multifile. This
61 * indicates the most recent date at which subfiles were added or removed from
62 * the Multifile. Note that it is logically possible for an individual
63 * subfile to have a more recent timestamp than the overall timestamp.
64 */
65 INLINE time_t Multifile::
66 get_timestamp() const {
67 return _timestamp;
68 }
69
70 /**
71 * Changes the overall mudification timestamp of the multifile. Note that this
72 * will be reset to the current time every time you modify a subfile.
73 * Only set this if you know what you are doing!
74 */
75 INLINE void Multifile::
76 set_timestamp(time_t timestamp) {
77 _timestamp = timestamp;
78 _timestamp_dirty = true;
79 }
80
81 /**
82 * Sets the flag indicating whether timestamps should be recorded within the
83 * Multifile or not. The default is true, indicating the Multifile will
84 * record timestamps for the overall file and also for each subfile.
85 *
86 * If this is false, the Multifile will not record timestamps internally. In
87 * this case, the return value from get_timestamp() or get_subfile_timestamp()
88 * will be estimations.
89 *
90 * You may want to set this false to minimize the bitwise difference between
91 * independently-generated Multifiles.
92 */
93 INLINE void Multifile::
94 set_record_timestamp(bool flag) {
95 _record_timestamp = flag;
96 _timestamp_dirty = true;
97 }
98
99 /**
100 * Returns the flag indicating whether timestamps should be recorded within
101 * the Multifile or not. See set_record_timestamp().
102 */
103 INLINE bool Multifile::
104 get_record_timestamp() const {
105 return _record_timestamp;
106 }
107
108 /**
109 * Returns the internal scale factor for this Multifile. See
110 * set_scale_factor().
111 */
112 INLINE size_t Multifile::
113 get_scale_factor() const {
114 return _new_scale_factor;
115 }
116
117 /**
118 * Sets the flag indicating whether subsequently-added subfiles should be
119 * encrypted before writing them to the multifile. If true, subfiles will be
120 * encrypted; if false (the default), they will be written without encryption.
121 *
122 * When true, subfiles will be encrypted with the password specified by
123 * set_encryption_password(). It is possible to apply a different password to
124 * different files, but the resulting file can't be mounted via VFS.
125 */
126 INLINE void Multifile::
127 set_encryption_flag(bool flag) {
128 #ifndef HAVE_OPENSSL
129 if (flag) {
130 express_cat.warning()
131 << "OpenSSL not compiled in; cannot generated encrypted multifiles.\n";
132 flag = false;
133 }
134 #endif // HAVE_OPENSSL
135 _encryption_flag = flag;
136 }
137
138 /**
139 * Returns the flag indicating whether subsequently-added subfiles should be
140 * encrypted before writing them to the multifile. See set_encryption_flag().
141 */
142 INLINE bool Multifile::
143 get_encryption_flag() const {
144 return _encryption_flag;
145 }
146
147 /**
148 * Specifies the password that will be used to encrypt subfiles subsequently
149 * added to the multifile, if the encryption flag is also set true (see
150 * set_encryption_flag()).
151 *
152 * It is possible to apply a different password to different files, but the
153 * resulting file can't be mounted via VFS. Changing this value may cause an
154 * implicit call to flush().
155 */
156 INLINE void Multifile::
157 set_encryption_password(const std::string &encryption_password) {
158 if (_encryption_password != encryption_password) {
159 if (!_new_subfiles.empty()) {
160 flush();
161 }
162 _encryption_password = encryption_password;
163 }
164 }
165
166 /**
167 * Returns the password that will be used to encrypt subfiles subsequently
168 * added to the multifile. See set_encryption_password().
169 */
170 INLINE const std::string &Multifile::
171 get_encryption_password() const {
172 return _encryption_password;
173 }
174
175 /**
176 * Specifies the encryption algorithm that should be used for future calls to
177 * add_subfile(). The default is whatever is specified by the encryption-
178 * algorithm config variable. The complete set of available algorithms is
179 * defined by the current version of OpenSSL.
180 *
181 * If an invalid algorithm is specified, there is no immediate error return
182 * code, but flush() will fail and the file will be invalid.
183 *
184 * It is possible to apply a different encryption algorithm to different
185 * files, and unlike the password, this does not interfere with mounting the
186 * multifile via VFS. Changing this value may cause an implicit call to
187 * flush().
188 */
189 INLINE void Multifile::
190 set_encryption_algorithm(const std::string &encryption_algorithm) {
191 if (_encryption_algorithm != encryption_algorithm) {
192 if (!_new_subfiles.empty()) {
193 flush();
194 }
195 _encryption_algorithm = encryption_algorithm;
196 }
197 }
198
199 /**
200 * Returns the encryption algorithm that was specified by
201 * set_encryption_algorithm().
202 */
203 INLINE const std::string &Multifile::
204 get_encryption_algorithm() const {
205 return _encryption_algorithm;
206 }
207
208 /**
209 * Specifies the length of the key, in bits, that should be used to encrypt
210 * the stream in future calls to add_subfile(). The default is whatever is
211 * specified by the encryption-key-length config variable.
212 *
213 * If an invalid key_length for the chosen algorithm is specified, there is no
214 * immediate error return code, but flush() will fail and the file will be
215 * invalid.
216 *
217 * It is possible to apply a different key length to different files, and
218 * unlike the password, this does not interfere with mounting the multifile
219 * via VFS. Changing this value may cause an implicit call to flush().
220 */
221 INLINE void Multifile::
222 set_encryption_key_length(int encryption_key_length) {
223 if (_encryption_key_length != encryption_key_length) {
224 if (!_new_subfiles.empty()) {
225 flush();
226 }
227 _encryption_key_length = encryption_key_length;
228 }
229 }
230
231 /**
232 * Returns the encryption key length, in bits, that was specified by
233 * set_encryption_key_length().
234 */
235 INLINE int Multifile::
236 get_encryption_key_length() const {
237 return _encryption_key_length;
238 }
239
240 /**
241 * Specifies the number of times to repeatedly hash the key before writing it
242 * to the stream in future calls to add_subfile(). Its purpose is to make it
243 * computationally more expensive for an attacker to search the key space
244 * exhaustively. This should be a multiple of 1,000 and should not exceed
245 * about 65 million; the value 0 indicates just one application of the hashing
246 * algorithm.
247 *
248 * The default is whatever is specified by the multifile-encryption-iteration-
249 * count config variable.
250 *
251 * It is possible to apply a different iteration count to different files, and
252 * unlike the password, this does not interfere with mounting the multifile
253 * via VFS. Changing this value causes an implicit call to flush().
254 */
255 INLINE void Multifile::
256 set_encryption_iteration_count(int encryption_iteration_count) {
257 if (_encryption_iteration_count != encryption_iteration_count) {
258 flush();
259 _encryption_iteration_count = encryption_iteration_count;
260 }
261 }
262
263 /**
264 * Returns the value that was specified by set_encryption_iteration_count().
265 */
266 INLINE int Multifile::
267 get_encryption_iteration_count() const {
268 return _encryption_iteration_count;
269 }
270
271 /**
272 * Removes the named subfile from the Multifile, if it exists; returns true if
273 * successfully removed, or false if it did not exist in the first place. The
274 * file will not actually be removed from the disk until the next call to
275 * flush().
276 *
277 * Note that this does not actually remove the data from the indicated
278 * subfile; it simply removes it from the index. The Multifile will not be
279 * reduced in size after this operation, until the next call to repack().
280 */
281 INLINE bool Multifile::
282 remove_subfile(const std::string &subfile_name) {
283 int index = find_subfile(subfile_name);
284 if (index >= 0) {
285 remove_subfile(index);
286 return true;
287 }
288 return false;
289 }
290
291 /**
292 * Returns a vector_uchar that contains the entire contents of the indicated
293 * subfile.
294 */
295 INLINE vector_uchar Multifile::
296 read_subfile(int index) {
297 vector_uchar result;
298 read_subfile(index, result);
299 return result;
300 }
301
302 /**
303 * Returns a string with the first n bytes written to a Multifile, to identify
304 * it as a Multifile.
305 */
306 INLINE std::string Multifile::
307 get_magic_number() {
308 return std::string(_header, _header_size);
309 }
310
311 /**
312 * Returns the string that preceded the Multifile header on the file, if any.
313 * See set_header_prefix().
314 */
315 INLINE const std::string &Multifile::
316 get_header_prefix() const {
317 return _header_prefix;
318 }
319
320 /**
321 * Converts a size_t address read from the file to a streampos byte address
322 * within the file.
323 */
324 INLINE std::streampos Multifile::
325 word_to_streampos(size_t word) const {
326 return (std::streampos)word * (std::streampos)_scale_factor;
327 }
328
329 /**
330 * Converts a streampos byte address within the file to a size_t value
331 * suitable for writing to the file.
332 */
333 INLINE size_t Multifile::
334 streampos_to_word(std::streampos fpos) const {
335 return (size_t)((fpos + (std::streampos)_scale_factor - (std::streampos)1) / (std::streampos)_scale_factor);
336 }
337
338 /**
339 * Rounds the streampos byte address up to the next multiple of _scale_factor.
340 * Only multiples of _scale_factor may be written to the file.
341 */
342 INLINE std::streampos Multifile::
343 normalize_streampos(std::streampos fpos) const {
344 return word_to_streampos(streampos_to_word(fpos));
345 }
346
347 /**
348 * Converts a single nibble to a hex digit.
349 */
350 INLINE char Multifile::
351 tohex(unsigned int nibble) {
352 nibble &= 0xf;
353 if (nibble < 10) {
354 return nibble + '0';
355 }
356 return nibble - 10 + 'a';
357 }
358
359 /**
360 *
361 */
362 INLINE Multifile::Subfile::
363 Subfile() {
364 _index_start = 0;
365 _data_start = 0;
366 _data_length = 0;
367 _timestamp = 0;
368 _source = nullptr;
369 _flags = 0;
370 _compression_level = 0;
371 #ifdef HAVE_OPENSSL
372 _pkey = nullptr;
373 #endif
374 }
375
376 /**
377 * Compares two Subfiles for proper sorting within the index.
378 */
379 INLINE bool Multifile::Subfile::
380 operator < (const Multifile::Subfile &other) const {
381 // This should only be called on normal subfiles, not on certificate files
382 // or signature files. (We don't attempt to sort these special signature
383 // files.)
384 nassertr(!is_cert_special() && !other.is_cert_special(), false);
385
386 // Normal subfiles are simply sorted in alphabetical order by filename.
387 return _name < other._name;
388 }
389
390 /**
391 * Returns true if the Subfile indicates it has been deleted (removed from the
392 * index), false otherwise. This should never be true of Subfiles that
393 * currently appear in either the _subfiles or _new_subfiles lists.
394 */
395 INLINE bool Multifile::Subfile::
396 is_deleted() const {
397 return (_flags & SF_deleted) != 0;
398 }
399
400 /**
401 * Returns true if there was some problem reading the index record for this
402 * Subfile from the Multifile.
403 */
404 INLINE bool Multifile::Subfile::
405 is_index_invalid() const {
406 return (_flags & SF_index_invalid) != 0;
407 }
408
409 /**
410 * Returns true if there was some problem reading the data contents of this
411 * Subfile, particularly when copying into the Multifile.
412 */
413 INLINE bool Multifile::Subfile::
414 is_data_invalid() const {
415 return (_flags & SF_data_invalid) != 0;
416 }
417
418 /**
419 * Returns true if this Subfile represents a signature record, which is
420 * treated specially; or false if it is an ordinary Subfile.
421 */
422 INLINE bool Multifile::Subfile::
423 is_cert_special() const {
424 return (_flags & SF_signature) != 0;
425 }
426
427 /**
428 * Returns the byte position within the Multifile of the last byte that
429 * contributes to this Subfile, either in the index record or in the subfile
430 * data.
431 */
432 INLINE std::streampos Multifile::Subfile::
433 get_last_byte_pos() const {
434 return std::max(_index_start + (std::streampos)_index_length,
435 _data_start + (std::streampos)_data_length) - (std::streampos)1;
436 }
Filename
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
Multifile::get_encryption_flag
bool get_encryption_flag() const
Returns the flag indicating whether subsequently-added subfiles should be encrypted before writing th...
Definition: multifile.I:143
Multifile::get_multifile_name
const Filename & get_multifile_name() const
Returns the filename of the Multifile, if it is available.
Definition: multifile.I:18
Multifile::get_scale_factor
size_t get_scale_factor() const
Returns the internal scale factor for this Multifile.
Definition: multifile.I:113
Multifile::get_encryption_iteration_count
int get_encryption_iteration_count() const
Returns the value that was specified by set_encryption_iteration_count().
Definition: multifile.I:267
Multifile::set_record_timestamp
void set_record_timestamp(bool record_timestamp)
Sets the flag indicating whether timestamps should be recorded within the Multifile or not.
Definition: multifile.I:94
Multifile::flush
bool flush()
Writes all contents of the Multifile to disk.
Definition: multifile.cxx:1127
Multifile::find_subfile
int find_subfile(const std::string &subfile_name) const
Returns the index of the subfile with the indicated name, or -1 if the named subfile is not within th...
Definition: multifile.cxx:1367
Multifile::set_encryption_key_length
void set_encryption_key_length(int encryption_key_length)
Specifies the length of the key, in bits, that should be used to encrypt the stream in future calls t...
Definition: multifile.I:222
Multifile::get_record_timestamp
bool get_record_timestamp() const
Returns the flag indicating whether timestamps should be recorded within the Multifile or not.
Definition: multifile.I:104
Multifile::is_write_valid
bool is_write_valid() const
Returns true if the Multifile has been opened for write mode and there have been no errors,...
Definition: multifile.I:46
Multifile::set_timestamp
void set_timestamp(time_t timestamp)
Changes the overall mudification timestamp of the multifile.
Definition: multifile.I:76
Multifile::set_encryption_algorithm
void set_encryption_algorithm(const std::string &encryption_algorithm)
Specifies the encryption algorithm that should be used for future calls to add_subfile().
Definition: multifile.I:190
Multifile::set_encryption_flag
void set_encryption_flag(bool flag)
Sets the flag indicating whether subsequently-added subfiles should be encrypted before writing them ...
Definition: multifile.I:127
Multifile::get_timestamp
time_t get_timestamp() const
Returns the modification timestamp of the overall Multifile.
Definition: multifile.I:66
Multifile::set_encryption_iteration_count
void set_encryption_iteration_count(int encryption_iteration_count)
Specifies the number of times to repeatedly hash the key before writing it to the stream in future ca...
Definition: multifile.I:256
Multifile::get_encryption_key_length
int get_encryption_key_length() const
Returns the encryption key length, in bits, that was specified by set_encryption_key_length().
Definition: multifile.I:236
Multifile::set_encryption_password
void set_encryption_password(const std::string &encryption_password)
Specifies the password that will be used to encrypt subfiles subsequently added to the multifile,...
Definition: multifile.I:157
Multifile::get_header_prefix
const std::string & get_header_prefix() const
Returns the string that preceded the Multifile header on the file, if any.
Definition: multifile.I:316
Multifile::needs_repack
bool needs_repack() const
Returns true if the Multifile index is suboptimal and should be repacked.
Definition: multifile.I:55
Multifile::get_encryption_algorithm
const std::string & get_encryption_algorithm() const
Returns the encryption algorithm that was specified by set_encryption_algorithm().
Definition: multifile.I:204
Multifile::get_magic_number
get_magic_number
Returns a string with the first n bytes written to a Multifile, to identify it as a Multifile.
Definition: multifile.h:140
Multifile::set_multifile_name
void set_multifile_name(const Filename &multifile_name)
Replaces the filename of the Multifile.
Definition: multifile.I:28
Multifile::is_read_valid
bool is_read_valid() const
Returns true if the Multifile has been opened for read mode and there have been no errors,...
Definition: multifile.I:37
Multifile::remove_subfile
void remove_subfile(int index)
Removes the nth subfile from the Multifile.
Definition: multifile.cxx:1459
Multifile::read_subfile
vector_uchar read_subfile(int index)
Returns a vector_uchar that contains the entire contents of the indicated subfile.
Definition: multifile.I:296
Multifile::get_encryption_password
const std::string & get_encryption_password() const
Returns the password that will be used to encrypt subfiles subsequently added to the multifile.
Definition: multifile.I:171