From d71f50566b9f00d9a325a08dff406f52d3f42195 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Tue, 6 Oct 2009 12:23:32 -0600 Subject: [PATCH] utimens: validate futimens usage Using gl_futimens(fd,NULL,times) as an implementation for futimens won't work unless we reliably detect EBADF for out-of-range fd. Also catches a Linux bug with futimens(AT_FDCWD,NULL) changing ".". mingw has a bug where utime's second argument is not const. * lib/utimens.c (gl_futimens): Require valid fd up front, using fewer syscalls on failure later on. Avoid compiler warning on mingw. * modules/utimens (Depends-on): Add dup2. Signed-off-by: Eric Blake --- ChangeLog | 6 ++++++ lib/utimens.c | 30 ++++++++++++++++-------------- modules/utimens | 1 + 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 16e99df94..ffbfe70ba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2009-10-10 Eric Blake + utimens: validate futimens usage + * lib/utimens.c (gl_futimens): Require valid fd up front, using + fewer syscalls on failure later on. Avoid compiler warning on + mingw. + * modules/utimens (Depends-on): Add dup2. + utimens: add test * modules/utimens-tests: New test. * tests/test-utimens.h: New file. diff --git a/lib/utimens.c b/lib/utimens.c index 10d2c8246..b1ac350c3 100644 --- a/lib/utimens.c +++ b/lib/utimens.c @@ -55,9 +55,22 @@ struct utimbuf Return 0 on success, -1 (setting errno) on failure. */ int -gl_futimens (int fd _UNUSED_PARAMETER_, - char const *file, struct timespec const timespec[2]) +gl_futimens (int fd, char const *file, struct timespec const timespec[2]) { + /* Require that at least one of FD or FILE are valid. Works around + a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather + than failing. */ + if (!file) + { + if (fd < 0) + { + errno = EBADF; + return -1; + } + if (dup2 (fd, fd) != fd) + return -1; + } + /* Some Linux-based NFS clients are buggy, and mishandle time stamps of files in NFS file systems in some cases. We have no configure-time test for this, but please see @@ -163,17 +176,6 @@ gl_futimens (int fd _UNUSED_PARAMETER_, #if ! (HAVE_FUTIMESAT || (HAVE_WORKING_UTIMES && HAVE_FUTIMES)) errno = ENOSYS; #endif - - /* Prefer EBADF to ENOSYS if both error numbers apply. */ - if (errno == ENOSYS) - { - int fd2 = dup (fd); - int dup_errno = errno; - if (0 <= fd2) - close (fd2); - errno = (fd2 < 0 && dup_errno == EBADF ? EBADF : ENOSYS); - } - return -1; } @@ -182,7 +184,7 @@ gl_futimens (int fd _UNUSED_PARAMETER_, #else { struct utimbuf utimbuf; - struct utimbuf const *ut; + struct utimbuf *ut; if (timespec) { utimbuf.actime = timespec[0].tv_sec; diff --git a/modules/utimens b/modules/utimens index 425148521..48fbe8e43 100644 --- a/modules/utimens +++ b/modules/utimens @@ -9,6 +9,7 @@ m4/utimens.m4 m4/utimes.m4 Depends-on: +dup2 errno sys_time time -- 2.11.0