tar: --atime-preserve fixes for races etc.

This patch fixes a race condition in the --atime-preserve=replace
option, which might cause tar to improperly follow a symbolic link.

It also drops the use of the _FIOSATIME ioctl of Solaris 2.x
and later, which loses resolution on time stamps.  Modern Solaris
systems support full-resolution time stamps in the kernel, and
it's not worth the hassle of testing this call, useful only in
no-longer-supported Solaris variants.

Also, it undoes a change I recently introduced to the --compare
option, which caused it to not follow symbolic links unless the
--dereference option was also used.  Quite possibly this change is
a good idea, but the old behavior was documented and the change
should not have been installed casually.

* configure.ac: Don't check for stropts.h and sys/filio.h.
* gnulib.modules: Add futimens, utimensat.  Remove futimens.
* src/common.h (fd_utimensat): New decl.
* src/compare.c (diff_file, diff_multivol):
Don't use open_read_flags: those are for --create only.
* src/create.c (dump_file0): Adjust to set_file_atime changes.
Pass fstatat_flags to set_file_atime, so that symbolic links are
not followed inadvertantly.
* src/extract.c: Don't include utimens.h.
(set_stat): Use fd_utimensat ant UTIME_NOW rather than fdutimens.
* src/misc.c: Don't include utimens.h, stropts.h, sys/filio.h.
(fd_utimensat): New function.
(set_file_atime): Use it.  New arg atflag, controlling symlink
handling.  All callers changed.
This commit is contained in:
Paul Eggert
2010-09-16 10:16:47 -07:00
parent 59146768ef
commit ecbcb7b6d7
7 changed files with 51 additions and 45 deletions

View File

@@ -24,14 +24,6 @@
#include <save-cwd.h>
#include <xgetcwd.h>
#include <unlinkdir.h>
#include <utimens.h>
#if HAVE_STROPTS_H
# include <stropts.h>
#endif
#if HAVE_SYS_FILIO_H
# include <sys/filio.h>
#endif
#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
@@ -621,24 +613,30 @@ deref_stat (bool deref, char const *name, struct stat *buf)
return deref ? stat (name, buf) : lstat (name, buf);
}
/* Set FD's (i.e., FILE's) access time to TIMESPEC[0]. If that's not
possible to do by itself, set its access and data modification
times to TIMESPEC[0] and TIMESPEC[1], respectively. */
/* Use futimens if possible, utimensat otherwise. */
int
set_file_atime (int fd, char const *file, struct timespec const timespec[2])
fd_utimensat (int fd, int parentfd, char const *file,
struct timespec const ts[2], int atflag)
{
#ifdef _FIOSATIME
if (0 <= fd)
{
struct timeval timeval;
timeval.tv_sec = timespec[0].tv_sec;
timeval.tv_usec = timespec[0].tv_nsec / 1000;
if (ioctl (fd, _FIOSATIME, &timeval) == 0)
return 0;
int result = futimens (fd, ts);
if (! (result < 0 && errno == ENOSYS))
return result;
}
#endif
return gl_futimens (fd, file, timespec);
return utimensat (parentfd, file, ts, atflag);
}
/* Set FD's (i.e., FILE's) access time to ATIME.
ATFLAG controls symbolic-link following, in the style of openat. */
int
set_file_atime (int fd, char const *file, struct timespec atime, int atflag)
{
struct timespec ts[2];
ts[0] = atime;
ts[1].tv_nsec = UTIME_OMIT;
return fd_utimensat (fd, AT_FDCWD, file, ts, atflag);
}
/* A description of a working directory. */