From af2d274f0e95657279b3e44dcef14f4d48bcb7ea Mon Sep 17 00:00:00 2001 From: Michael Karcher Date: Sun, 17 Aug 2008 19:03:44 +0200 Subject: [PATCH] ntdll: Add sub-second resolution to NtQueryInformationFile. --- configure | 303 ++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 4 +- dlls/ntdll/file.c | 20 +++ include/config.h.in | 9 ++ 4 files changed, 334 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 422f585507a..683c22b99f6 100755 --- a/configure +++ b/configure @@ -21235,6 +21235,309 @@ cat >>confdefs.h <<_ACEOF _ACEOF +fi +{ echo "$as_me:$LINENO: checking for struct stat.st_mtim" >&5 +echo $ECHO_N "checking for struct stat.st_mtim... $ECHO_C" >&6; } +if test "${ac_cv_member_struct_stat_st_mtim+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static struct stat ac_aggr; +if (ac_aggr.st_mtim) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_struct_stat_st_mtim=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static struct stat ac_aggr; +if (sizeof ac_aggr.st_mtim) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_struct_stat_st_mtim=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_member_struct_stat_st_mtim=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_mtim" >&5 +echo "${ECHO_T}$ac_cv_member_struct_stat_st_mtim" >&6; } +if test $ac_cv_member_struct_stat_st_mtim = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_MTIM 1 +_ACEOF + + +fi +{ echo "$as_me:$LINENO: checking for struct stat.st_ctim" >&5 +echo $ECHO_N "checking for struct stat.st_ctim... $ECHO_C" >&6; } +if test "${ac_cv_member_struct_stat_st_ctim+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static struct stat ac_aggr; +if (ac_aggr.st_ctim) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_struct_stat_st_ctim=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static struct stat ac_aggr; +if (sizeof ac_aggr.st_ctim) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_struct_stat_st_ctim=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_member_struct_stat_st_ctim=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_ctim" >&5 +echo "${ECHO_T}$ac_cv_member_struct_stat_st_ctim" >&6; } +if test $ac_cv_member_struct_stat_st_ctim = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_CTIM 1 +_ACEOF + + +fi +{ echo "$as_me:$LINENO: checking for struct stat.st_atim" >&5 +echo $ECHO_N "checking for struct stat.st_atim... $ECHO_C" >&6; } +if test "${ac_cv_member_struct_stat_st_atim+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static struct stat ac_aggr; +if (ac_aggr.st_atim) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_struct_stat_st_atim=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static struct stat ac_aggr; +if (sizeof ac_aggr.st_atim) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_struct_stat_st_atim=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_member_struct_stat_st_atim=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_atim" >&5 +echo "${ECHO_T}$ac_cv_member_struct_stat_st_atim" >&6; } +if test $ac_cv_member_struct_stat_st_atim = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_ATIM 1 +_ACEOF + + fi diff --git a/configure.ac b/configure.ac index fb8de889d35..290e802e897 100644 --- a/configure.ac +++ b/configure.ac @@ -1595,8 +1595,8 @@ AC_CHECK_MEMBERS([struct option.name],,, #include #endif]) -dnl Check for stat.st_blocks -AC_CHECK_MEMBERS([struct stat.st_blocks]) +dnl Check for stat.st_blocks and ns-resolved times +AC_CHECK_MEMBERS([struct stat.st_blocks,struct stat.st_mtim,struct stat.st_ctim,struct stat.st_atim]) dnl Check for sin6_scope_id AC_CHECK_MEMBERS([struct sockaddr_in6.sin6_scope_id],,, diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 972d600d6c5..d7f5b938efd 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -1565,6 +1565,16 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io, RtlSecondsSince1970ToTime( st.st_mtime, &info->LastWriteTime); RtlSecondsSince1970ToTime( st.st_ctime, &info->ChangeTime); RtlSecondsSince1970ToTime( st.st_atime, &info->LastAccessTime); +#ifdef HAVE_STRUCT_STAT_ST_MTIM + info->CreationTime.QuadPart += st.st_mtim.tv_nsec / 100; + info->LastWriteTime.QuadPart += st.st_mtim.tv_nsec / 100; +#endif +#ifdef HAVE_STRUCT_STAT_ST_CTIM + info->ChangeTime.QuadPart += st.st_ctim.tv_nsec / 100; +#endif +#ifdef HAVE_STRUCT_STAT_ST_ATIM + info->LastAccessTime.QuadPart += st.st_atim.tv_nsec / 100; +#endif } } break; @@ -1653,6 +1663,16 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io, RtlSecondsSince1970ToTime( st.st_mtime, &info->BasicInformation.LastWriteTime); RtlSecondsSince1970ToTime( st.st_ctime, &info->BasicInformation.ChangeTime); RtlSecondsSince1970ToTime( st.st_atime, &info->BasicInformation.LastAccessTime); +#ifdef HAVE_STRUCT_STAT_ST_MTIM + info->BasicInformation.CreationTime.QuadPart += st.st_mtim.tv_nsec / 100; + info->BasicInformation.LastWriteTime.QuadPart += st.st_mtim.tv_nsec / 100; +#endif +#ifdef HAVE_STRUCT_STAT_ST_CTIM + info->BasicInformation.ChangeTime.QuadPart += st.st_ctim.tv_nsec / 100; +#endif +#ifdef HAVE_STRUCT_STAT_ST_ATIM + info->BasicInformation.LastAccessTime.QuadPart += st.st_atim.tv_nsec / 100; +#endif info->InternalInformation.IndexNumber.QuadPart = st.st_ino; info->EaInformation.EaSize = 0; info->AccessInformation.AccessFlags = 0; /* FIXME */ diff --git a/include/config.h.in b/include/config.h.in index 1245197b54b..6ce0751831b 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -741,9 +741,18 @@ /* Define to 1 if `f_blocks' is member of `struct statvfs'. */ #undef HAVE_STRUCT_STATVFS_F_BLOCKS +/* Define to 1 if `st_atim' is member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_ATIM + /* Define to 1 if `st_blocks' is member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_BLOCKS +/* Define to 1 if `st_ctim' is member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_CTIM + +/* Define to 1 if `st_mtim' is member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_MTIM + /* Define to 1 if you have the header file. */ #undef HAVE_SYSCALL_H