MfP4: Use the set/unset tracking to determine when mtime or atime
is unavailable. Use start_time as a substitute when one is missing; if both are missing, skip the call to {f,l,}utime{s,}() entirely.
This commit is contained in:
parent
9128ec21f3
commit
e20d272f0a
@ -439,15 +439,25 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
|
||||
fe->mode = a->mode;
|
||||
}
|
||||
|
||||
if (a->deferred & TODO_TIMES) {
|
||||
if ((a->deferred & TODO_TIMES)
|
||||
&& (archive_entry_mtime_is_set(entry)
|
||||
|| archive_entry_atime_is_set(entry))) {
|
||||
fe = current_fixup(a, archive_entry_pathname(entry));
|
||||
fe->fixup |= TODO_TIMES;
|
||||
fe->mtime = archive_entry_mtime(entry);
|
||||
fe->mtime_nanos = archive_entry_mtime_nsec(entry);
|
||||
fe->atime = archive_entry_atime(entry);
|
||||
fe->atime_nanos = archive_entry_atime_nsec(entry);
|
||||
if (fe->atime == 0 && fe->atime_nanos == 0)
|
||||
if (archive_entry_mtime_is_set(entry)) {
|
||||
fe->mtime = archive_entry_mtime(entry);
|
||||
fe->mtime_nanos = archive_entry_mtime_nsec(entry);
|
||||
} else {
|
||||
fe->mtime = a->start_time;
|
||||
fe->mtime_nanos = 0;
|
||||
}
|
||||
if (archive_entry_atime_is_set(entry)) {
|
||||
fe->atime = archive_entry_atime(entry);
|
||||
fe->atime_nanos = archive_entry_atime_nsec(entry);
|
||||
} else {
|
||||
fe->atime = a->start_time;
|
||||
fe->atime_nanos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (a->deferred & TODO_FFLAGS) {
|
||||
@ -1623,18 +1633,31 @@ set_time(struct archive_write_disk *a)
|
||||
{
|
||||
struct timeval times[2];
|
||||
|
||||
times[1].tv_sec = archive_entry_mtime(a->entry);
|
||||
times[1].tv_usec = archive_entry_mtime_nsec(a->entry) / 1000;
|
||||
/* If no time was provided, we're done. */
|
||||
if (!archive_entry_atime_is_set(a->entry)
|
||||
&& !archive_entry_mtime_is_set(a->entry))
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
times[0].tv_sec = archive_entry_atime(a->entry);
|
||||
times[0].tv_usec = archive_entry_atime_nsec(a->entry) / 1000;
|
||||
/* We know at least one is set, so... */
|
||||
if (archive_entry_mtime_is_set(a->entry)) {
|
||||
times[1].tv_sec = archive_entry_mtime(a->entry);
|
||||
times[1].tv_usec = archive_entry_mtime_nsec(a->entry) / 1000;
|
||||
} else {
|
||||
times[1].tv_sec = a->start_time;
|
||||
times[1].tv_usec = 0;
|
||||
}
|
||||
|
||||
/* If no atime was specified, use start time instead. */
|
||||
/* In theory, it would be marginally more correct to use
|
||||
* time(NULL) here, but that would cost us an extra syscall
|
||||
* for little gain. */
|
||||
if (times[0].tv_sec == 0 && times[0].tv_usec == 0)
|
||||
if (archive_entry_atime_is_set(a->entry)) {
|
||||
times[0].tv_sec = archive_entry_atime(a->entry);
|
||||
times[0].tv_usec = archive_entry_atime_nsec(a->entry) / 1000;
|
||||
} else {
|
||||
times[0].tv_sec = a->start_time;
|
||||
times[0].tv_usec = 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FUTIMES
|
||||
if (a->fd >= 0 && futimes(a->fd, times) == 0) {
|
||||
@ -1672,10 +1695,24 @@ set_time(struct archive_write_disk *a)
|
||||
{
|
||||
struct utimbuf times;
|
||||
|
||||
times.modtime = archive_entry_mtime(a->entry);
|
||||
times.actime = archive_entry_atime(a->entry);
|
||||
if (times.actime == 0)
|
||||
/* If no time was provided, we're done. */
|
||||
if (!archive_entry_atime_is_set(a->entry)
|
||||
&& !archive_entry_mtime_is_set(a->entry))
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
/* We know at least one is set, so... */
|
||||
/* Set mtime from mtime if set, else start time. */
|
||||
if (archive_entry_mtime_is_set(a->entry))
|
||||
times.modtime = archive_entry_mtime(a->entry);
|
||||
else
|
||||
times.modtime = a->start_time;
|
||||
|
||||
/* Set atime from provided atime, else mtime. */
|
||||
if (archive_entry_atime_is_set(a->entry))
|
||||
times.actime = archive_entry_atime(a->entry);
|
||||
else
|
||||
times.actime = a->start_time;
|
||||
|
||||
if (!S_ISLNK(a->mode) && utime(a->name, ×) != 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Can't update time for %s", a->name);
|
||||
|
Loading…
Reference in New Issue
Block a user