add set_record_timestamp()

This commit is contained in:
David Rose 2006-10-04 17:54:31 +00:00
parent 10f8157070
commit af2ef4dca8
4 changed files with 164 additions and 14 deletions

View File

@ -51,6 +51,43 @@ pset<string> dont_compress; // -Z
// Default extensions not to compress. May be overridden with -Z.
string dont_compress_str = "jpg,mp3";
bool got_record_timestamp_flag = false;
bool record_timestamp_flag = true;
////////////////////////////////////////////////////////////////////
// Function: string_to_int
// Description: A string-interface wrapper around the C library
// strtol(). This parses the ASCII representation of an
// integer, and then sets tail to everything that
// follows the first valid integer read. If, on exit,
// str == tail, there was no valid integer in the
// source string; if !tail.empty(), there was garbage
// after the integer.
//
// It is legal if str and tail refer to the same string.
////////////////////////////////////////////////////////////////////
static int
string_to_int(const string &str, string &tail) {
const char *nptr = str.c_str();
char *endptr;
int result = strtol(nptr, &endptr, 10);
tail = endptr;
return result;
}
////////////////////////////////////////////////////////////////////
// Function: string_to_int
// Description: Another flavor of string_to_int(), this one returns
// true if the string is a perfectly valid integer (and
// sets result to that value), or false otherwise.
////////////////////////////////////////////////////////////////////
static bool
string_to_int(const string &str, int &result) {
string tail;
result = string_to_int(str, tail);
return tail.empty();
}
void
usage() {
cerr <<
@ -159,6 +196,14 @@ help() {
" \"" << dont_compress_str << "\". Specify -Z \"\" (be sure to include the space) to allow\n"
" all files to be compressed.\n\n"
" -T <flag>\n"
" Enable or disable the recording of file timestamps within the multifile.\n"
" If <flag> is 1, timestamps will be recorded within the multifile for\n"
" each subfile added; this is the default behavior. If <flag> is 0,\n"
" timestamps will not be recorded, which will make it easier to do a\n"
" bitwise comparison between multifiles to determine whether their\n"
" contents are equivalent.\n\n"
" -1 .. -9\n"
" Specify the compression level when -z is in effect. Larger numbers\n"
" generate slightly smaller files, but compression takes longer. The\n"
@ -273,6 +318,10 @@ add_files(int argc, char *argv[]) {
return false;
}
}
if (got_record_timestamp_flag) {
multifile->set_record_timestamp(record_timestamp_flag);
}
if (encryption_flag) {
multifile->set_encryption_flag(true);
@ -389,10 +438,15 @@ extract_files(int argc, char *argv[]) {
}
const char *
format_timestamp(time_t timestamp) {
format_timestamp(bool record_timestamp, time_t timestamp) {
static const size_t buffer_size = 512;
static char buffer[buffer_size];
if (!record_timestamp) {
// No timestamps.
return "";
}
if (timestamp == 0) {
// A zero timestamp is a special case.
return " (no date) ";
@ -447,26 +501,34 @@ list_files(int argc, char *argv[]) {
printf("%12d worse %c %s %s\n",
multifile->get_subfile_length(i),
encrypted_symbol,
format_timestamp(multifile->get_subfile_timestamp(i)),
format_timestamp(multifile->get_record_timestamp(),
multifile->get_subfile_timestamp(i)),
subfile_name.c_str());
} else {
printf("%12d %3.0f%% %c %s %s\n",
multifile->get_subfile_length(i),
100.0 - ratio * 100.0, encrypted_symbol,
format_timestamp(multifile->get_subfile_timestamp(i)),
format_timestamp(multifile->get_record_timestamp(),
multifile->get_subfile_timestamp(i)),
subfile_name.c_str());
}
} else {
printf("%12d %c %s %s\n",
multifile->get_subfile_length(i),
encrypted_symbol,
format_timestamp(multifile->get_subfile_timestamp(i)),
format_timestamp(multifile->get_record_timestamp(),
multifile->get_subfile_timestamp(i)),
subfile_name.c_str());
}
}
}
cout << "Last modification " << format_timestamp(multifile->get_timestamp()) << "\n";
fflush(stdout);
if (multifile->get_record_timestamp()) {
cout << "Last modification "
<< format_timestamp(true, multifile->get_timestamp()) << "\n";
}
if (multifile->get_scale_factor() != 1) {
cout << "Scale factor is " << multifile->get_scale_factor() << "\n";
}
@ -520,7 +582,7 @@ main(int argc, char *argv[]) {
extern char *optarg;
extern int optind;
static const char *optflags = "crutxvz123456789Z:f:OC:ep:F:h";
static const char *optflags = "crutxvz123456789Z:T:f:OC:ep:F:h";
int flag = getopt(argc, argv, optflags);
Filename rel_path;
while (flag != EOF) {
@ -585,6 +647,19 @@ main(int argc, char *argv[]) {
case 'Z':
dont_compress_str = optarg;
break;
case 'T':
{
int flag;
if (!string_to_int(optarg, flag) ||
(flag != 0 && flag != 1)) {
cerr << "Invalid timestamp flag: " << optarg << "\n";
usage();
return 1;
}
record_timestamp_flag = (flag != 0);
got_record_timestamp_flag = true;
}
break;
case 'f':
multifile_name = Filename::from_os_specific(optarg);
got_multifile_name = true;
@ -655,8 +730,14 @@ main(int argc, char *argv[]) {
if (create || append || update) {
okflag = add_files(argc, argv);
} else if (extract) {
if (got_record_timestamp_flag) {
cerr << "Warning: -T ignored on extract.\n";
}
okflag = extract_files(argc, argv);
} else { // list
if (got_record_timestamp_flag) {
cerr << "Warning: -T ignored on list.\n";
}
okflag = list_files(argc, argv);
}

View File

@ -78,6 +78,41 @@ get_timestamp() const {
return _timestamp;
}
////////////////////////////////////////////////////////////////////
// Function: Multifile::set_record_timestamp
// Access: Published
// Description: Sets the flag indicating whether timestamps should be
// recorded within the Multifile or not. The default is
// true, indicating the Multifile will record timestamps
// for the overall file and also for each subfile.
//
// If this is false, the Multifile will not record
// timestamps internally. In this case, the return
// value from get_timestamp() or get_subfile_timestamp()
// will be estimations.
//
// You may want to set this false to minimize the
// bitwise difference between independently-generated
// Multifiles.
////////////////////////////////////////////////////////////////////
INLINE void Multifile::
set_record_timestamp(bool flag) {
_record_timestamp = flag;
_timestamp_dirty = true;
}
////////////////////////////////////////////////////////////////////
// Function: Multifile::get_record_timestamp
// Access: Published
// Description: Returns the flag indicating whether timestamps
// should be recorded within the Multifile or not. See
// set_record_timestamp().
////////////////////////////////////////////////////////////////////
INLINE bool Multifile::
get_record_timestamp() const {
return _record_timestamp;
}
////////////////////////////////////////////////////////////////////
// Function: Multifile::get_scale_factor
// Access: Published

View File

@ -111,6 +111,7 @@ Multifile() {
_needs_repack = false;
_timestamp = 0;
_timestamp_dirty = false;
_record_timestamp = true;
_scale_factor = 1;
_new_scale_factor = 1;
_encryption_flag = false;
@ -534,7 +535,11 @@ flush() {
nassertr(!_write->fail(), false);
StreamWriter writer(*_write);
writer.add_uint32(_timestamp);
if (_record_timestamp) {
writer.add_uint32(_timestamp);
} else {
writer.add_uint32(0);
}
_timestamp_dirty = false;
}
@ -808,14 +813,19 @@ get_subfile_length(int index) const {
// Access: Published
// Description: Returns the modification time of the nth
// subfile. If this is called on an older .mf file,
// which did not store individual timestamps in the
// file, this will return the modification time of the
// overall multifile.
// which did not store individual timestamps in the file
// (or if get_record_timestamp() is false), this will
// return the modification time of the overall
// multifile.
////////////////////////////////////////////////////////////////////
time_t Multifile::
get_subfile_timestamp(int index) const {
nassertr(index >= 0 && index < (int)_subfiles.size(), 0);
return _subfiles[index]->_timestamp;
if (!get_record_timestamp()) {
return get_timestamp();
} else {
return _subfiles[index]->_timestamp;
}
}
////////////////////////////////////////////////////////////////////
@ -1384,8 +1394,16 @@ read_index() {
return false;
}
_record_timestamp = true;
if (_file_minor_ver >= 1) {
_timestamp = reader.get_uint32();
time_t read_timestamp = reader.get_uint32();
if (read_timestamp == 0) {
// If we read a 0 timestamp from the file, that implies that we
// don't want to record a timestamp in this particular file.
_record_timestamp = false;
} else {
_timestamp = read_timestamp;
}
_timestamp_dirty = false;
}
@ -1456,7 +1474,12 @@ write_header() {
writer.add_int16(_current_minor_ver);
writer.add_uint32(_scale_factor);
writer.add_uint32(_timestamp);
if (_record_timestamp) {
writer.add_uint32(_timestamp);
} else {
writer.add_uint32(0);
_timestamp_dirty = false;
}
_next_index = _write->tellp();
_next_index = pad_to_streampos(_next_index);
@ -1515,6 +1538,9 @@ read_index(istream &read, streampos fpos, Multifile *multifile) {
_timestamp = multifile->get_timestamp();
} else {
_timestamp = reader.get_uint32();
if (_timestamp == 0) {
_timestamp = multifile->get_timestamp();
}
}
size_t name_length = reader.get_uint16();
@ -1758,7 +1784,11 @@ rewrite_index_data_start(ostream &write, Multifile *multifile) {
if ((_flags & (SF_compressed | SF_encrypted)) != 0) {
writer.add_uint32(_uncompressed_length);
}
writer.add_uint32(_timestamp);
if (multifile->_record_timestamp) {
writer.add_uint32(_timestamp);
} else {
writer.add_uint32(0);
}
}
////////////////////////////////////////////////////////////////////

View File

@ -56,6 +56,9 @@ PUBLISHED:
INLINE time_t get_timestamp() const;
INLINE void set_record_timestamp(bool record_timestamp);
INLINE bool get_record_timestamp() const;
void set_scale_factor(size_t scale_factor);
INLINE size_t get_scale_factor() const;
@ -168,6 +171,7 @@ private:
bool _needs_repack;
time_t _timestamp;
bool _timestamp_dirty;
bool _record_timestamp;
size_t _scale_factor;
size_t _new_scale_factor;