Panda3D
Loading...
Searching...
No Matches
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 */
17INLINE const Filename &Multifile::
18get_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 */
27INLINE void Multifile::
28set_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 */
36INLINE bool Multifile::
37is_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 */
45INLINE bool Multifile::
46is_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 */
54INLINE bool Multifile::
55needs_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 */
65INLINE time_t Multifile::
66get_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 */
75INLINE void Multifile::
76set_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 */
93INLINE void Multifile::
94set_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 */
103INLINE bool Multifile::
104get_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 */
112INLINE size_t Multifile::
113get_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 */
126INLINE void Multifile::
127set_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 */
142INLINE bool Multifile::
143get_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 */
156INLINE void Multifile::
157set_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 */
170INLINE const std::string &Multifile::
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 */
189INLINE void Multifile::
190set_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 */
203INLINE const std::string &Multifile::
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 */
221INLINE void Multifile::
222set_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 */
235INLINE int Multifile::
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 */
255INLINE void Multifile::
256set_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 */
266INLINE int Multifile::
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 */
281INLINE bool Multifile::
282remove_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 */
295INLINE vector_uchar Multifile::
296read_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 */
306INLINE std::string Multifile::
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 */
315INLINE const std::string &Multifile::
316get_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 */
324INLINE std::streampos Multifile::
325word_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 */
333INLINE size_t Multifile::
334streampos_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 */
342INLINE std::streampos Multifile::
343normalize_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 */
350INLINE char Multifile::
351tohex(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 */
362INLINE Multifile::Subfile::
363Subfile() {
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 */
379INLINE bool Multifile::Subfile::
380operator < (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 */
395INLINE bool Multifile::Subfile::
396is_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 */
404INLINE bool Multifile::Subfile::
405is_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 */
413INLINE bool Multifile::Subfile::
414is_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 */
422INLINE bool Multifile::Subfile::
423is_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 */
432INLINE std::streampos Multifile::Subfile::
433get_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}
The name of a file, such as a texture file or an Egg file.
Definition filename.h:44
bool get_encryption_flag() const
Returns the flag indicating whether subsequently-added subfiles should be encrypted before writing th...
Definition multifile.I:143
const Filename & get_multifile_name() const
Returns the filename of the Multifile, if it is available.
Definition multifile.I:18
size_t get_scale_factor() const
Returns the internal scale factor for this Multifile.
Definition multifile.I:113
int get_encryption_iteration_count() const
Returns the value that was specified by set_encryption_iteration_count().
Definition multifile.I:267
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
bool flush()
Writes all contents of the Multifile to disk.
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...
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
bool get_record_timestamp() const
Returns the flag indicating whether timestamps should be recorded within the Multifile or not.
Definition multifile.I:104
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
void set_timestamp(time_t timestamp)
Changes the overall mudification timestamp of the multifile.
Definition multifile.I:76
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
void set_encryption_flag(bool flag)
Sets the flag indicating whether subsequently-added subfiles should be encrypted before writing them ...
Definition multifile.I:127
time_t get_timestamp() const
Returns the modification timestamp of the overall Multifile.
Definition multifile.I:66
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
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
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
const std::string & get_header_prefix() const
Returns the string that preceded the Multifile header on the file, if any.
Definition multifile.I:316
bool needs_repack() const
Returns true if the Multifile index is suboptimal and should be repacked.
Definition multifile.I:55
const std::string & get_encryption_algorithm() const
Returns the encryption algorithm that was specified by set_encryption_algorithm().
Definition multifile.I:204
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
void set_multifile_name(const Filename &multifile_name)
Replaces the filename of the Multifile.
Definition multifile.I:28
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
void remove_subfile(int index)
Removes the nth subfile from the Multifile.
vector_uchar read_subfile(int index)
Returns a vector_uchar that contains the entire contents of the indicated subfile.
Definition multifile.I:296
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