From ebd9d5ba1abc432f3a11b99ac32657b4cea7ecfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Tue, 9 Aug 2005 15:00:59 +0000 Subject: Patch #1180695: Implement nanosecond stat resolution on FreeBSD, add st_gen, st_birthtime. --- Doc/lib/libos.tex | 7 ++ Misc/NEWS | 3 + Modules/posixmodule.c | 47 ++++++++ configure | 289 +++++++++++++++++++++++++++++++++++++++++++++++++- configure.in | 19 ++++ pyconfig.h.in | 9 ++ 6 files changed, 373 insertions(+), 1 deletion(-) diff --git a/Doc/lib/libos.tex b/Doc/lib/libos.tex index 3d9056d..2e6636e 100644 --- a/Doc/lib/libos.tex +++ b/Doc/lib/libos.tex @@ -996,6 +996,12 @@ also be available: \member{st_rdev} (type of device if an inode device). \member{st_flags} (user defined flags for file). +On other Unix systems (such as FreeBSD), the following attributes +may be available (but may be only filled out of root tries to +use them: +\member{st_gen} (file generation number), +\member{st_birthtime} (time of file creation). + On Mac OS systems, the following attributes may also be available: \member{st_rsize}, \member{st_creator}, @@ -1037,6 +1043,7 @@ Availability: Macintosh, \UNIX, Windows. \versionchanged [Added access to values as attributes of the returned object]{2.2} +\versionchanged[Added st_gen, st_birthtime]{2.5} \end{funcdesc} \begin{funcdesc}{stat_float_times}{\optional{newvalue}} diff --git a/Misc/NEWS b/Misc/NEWS index 10e43bc..a1f15ab 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -121,6 +121,9 @@ Core and builtins Extension Modules ----------------- +- Patch #1180695: Add nanosecond stat resolution, and st_gen, + st_birthtime for FreeBSD. + - Patch #1231069: The fcntl.ioctl function now uses the 'I' code for the request code argument, which results in more C-like behaviour for large or negative values. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index e0c2b7f..6e229f6 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -706,6 +706,12 @@ static PyStructSequence_Field stat_result_fields[] = { #ifdef HAVE_STRUCT_STAT_ST_FLAGS {"st_flags", "user defined flags for file"}, #endif +#ifdef HAVE_STRUCT_STAT_ST_GEN + {"st_gen", "generation number"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME + {"st_birthtime", "time of creation"}, +#endif {0} }; @@ -733,6 +739,18 @@ static PyStructSequence_Field stat_result_fields[] = { #define ST_FLAGS_IDX ST_RDEV_IDX #endif +#ifdef HAVE_STRUCT_STAT_ST_GEN +#define ST_GEN_IDX (ST_RDEV_IDX+1) +#else +#define ST_GEN_IDX ST_RDEV_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME +#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1) +#else +#define ST_BIRTHTIME_IDX ST_GEN_IDX +#endif + static PyStructSequence_Desc stat_result_desc = { "stat_result", /* name */ stat_result__doc__, /* doc */ @@ -878,8 +896,14 @@ _pystat_fromstructstat(STRUCT_STAT st) mnsec = st.st_mtim.tv_nsec; cnsec = st.st_ctim.tv_nsec; #else +#ifdef HAVE_STAT_TV_NSEC2 + ansec = st.st_atimespec.tv_nsec; + mnsec = st.st_mtimespec.tv_nsec; + cnsec = st.st_ctimespec.tv_nsec; +#else ansec = mnsec = cnsec = 0; #endif +#endif fill_time(v, 7, st.st_atime, ansec); fill_time(v, 8, st.st_mtime, mnsec); fill_time(v, 9, st.st_ctime, cnsec); @@ -896,6 +920,29 @@ _pystat_fromstructstat(STRUCT_STAT st) PyStructSequence_SET_ITEM(v, ST_RDEV_IDX, PyInt_FromLong((long)st.st_rdev)); #endif +#ifdef HAVE_STRUCT_STAT_ST_GEN + PyStructSequence_SET_ITEM(v, ST_GEN_IDX, + PyInt_FromLong((long)st.st_gen)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME + { + PyObject *val; + unsigned long bsec,bnsec; + bsec = (long)st.st_birthtime; +#ifdef HAVE_STAT_TV_NSEC2 + bnsec = st.st_birthtimespec.tv_nsec; +#else + bnsec = 0; +#endif + if (_stat_float_times) { + val = PyFloat_FromDouble(bsec + 1e-9*bnsec); + } else { + val = PyInt_FromLong((long)bsec); + } + PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX, + val); + } +#endif #ifdef HAVE_STRUCT_STAT_ST_FLAGS PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX, PyInt_FromLong((long)st.st_flags)); diff --git a/configure b/configure index 26403dd..213b50c 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 1.485 . +# From configure.in Revision: 1.486 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59 for python 2.5. # @@ -16526,6 +16526,226 @@ _ACEOF fi +echo "$as_me:$LINENO: checking for struct stat.st_gen" >&5 +echo $ECHO_N "checking for struct stat.st_gen... $ECHO_C" >&6 +if test "${ac_cv_member_struct_stat_st_gen+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_gen) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&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); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_struct_stat_st_gen=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_gen) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&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); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_struct_stat_st_gen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_member_struct_stat_st_gen=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_gen" >&5 +echo "${ECHO_T}$ac_cv_member_struct_stat_st_gen" >&6 +if test $ac_cv_member_struct_stat_st_gen = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_GEN 1 +_ACEOF + + +fi + +echo "$as_me:$LINENO: checking for struct stat.st_birthtime" >&5 +echo $ECHO_N "checking for struct stat.st_birthtime... $ECHO_C" >&6 +if test "${ac_cv_member_struct_stat_st_birthtime+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_birthtime) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&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); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_struct_stat_st_birthtime=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_birthtime) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&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); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_struct_stat_st_birthtime=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_member_struct_stat_st_birthtime=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_birthtime" >&5 +echo "${ECHO_T}$ac_cv_member_struct_stat_st_birthtime" >&6 +if test $ac_cv_member_struct_stat_st_birthtime = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1 +_ACEOF + + +fi + echo "$as_me:$LINENO: checking for struct stat.st_blocks" >&5 echo $ECHO_N "checking for struct stat.st_blocks... $ECHO_C" >&6 if test "${ac_cv_member_struct_stat_st_blocks+set}" = set; then @@ -20266,6 +20486,73 @@ _ACEOF fi +# Look for BSD style subsecond timestamps in struct stat +echo "$as_me:$LINENO: checking for tv_nsec2 in struct stat" >&5 +echo $ECHO_N "checking for tv_nsec2 in struct stat... $ECHO_C" >&6 +if test "${ac_cv_stat_tv_nsec2+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. */ +#include +int +main () +{ + +struct stat st; +st.st_mtimespec.tv_nsec = 1; + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&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); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_stat_tv_nsec2=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_stat_tv_nsec2=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +echo "$as_me:$LINENO: result: $ac_cv_stat_tv_nsec2" >&5 +echo "${ECHO_T}$ac_cv_stat_tv_nsec2" >&6 +if test "$ac_cv_stat_tv_nsec2" = yes +then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STAT_TV_NSEC2 1 +_ACEOF + +fi + # On HP/UX 11.0, mvwdelch is a block with a return statement echo "$as_me:$LINENO: checking whether mvwdelch is an expression" >&5 echo $ECHO_N "checking whether mvwdelch is an expression... $ECHO_C" >&6 diff --git a/configure.in b/configure.in index 7d6fe82..15a2a06 100644 --- a/configure.in +++ b/configure.in @@ -2424,6 +2424,8 @@ AC_STRUCT_TIMEZONE AC_CHECK_MEMBERS([struct stat.st_rdev]) AC_CHECK_MEMBERS([struct stat.st_blksize]) AC_CHECK_MEMBERS([struct stat.st_flags]) +AC_CHECK_MEMBERS([struct stat.st_gen]) +AC_CHECK_MEMBERS([struct stat.st_birthtime]) AC_STRUCT_ST_BLOCKS AC_MSG_CHECKING(for time.h that defines altzone) @@ -3042,6 +3044,23 @@ then [Define if you have struct stat.st_mtim.tv_nsec]) fi +# Look for BSD style subsecond timestamps in struct stat +AC_MSG_CHECKING(for tv_nsec2 in struct stat) +AC_CACHE_VAL(ac_cv_stat_tv_nsec2, +AC_TRY_COMPILE([#include ], [ +struct stat st; +st.st_mtimespec.tv_nsec = 1; +], +ac_cv_stat_tv_nsec2=yes, +ac_cv_stat_tv_nsec2=no, +ac_cv_stat_tv_nsec2=no)) +AC_MSG_RESULT($ac_cv_stat_tv_nsec2) +if test "$ac_cv_stat_tv_nsec2" = yes +then + AC_DEFINE(HAVE_STAT_TV_NSEC2, 1, + [Define if you have struct stat.st_mtimensec]) +fi + # On HP/UX 11.0, mvwdelch is a block with a return statement AC_MSG_CHECKING(whether mvwdelch is an expression) AC_CACHE_VAL(ac_cv_mvwdelch_is_expression, diff --git a/pyconfig.h.in b/pyconfig.h.in index a60e4da..47723de 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -455,6 +455,9 @@ /* Define if you have struct stat.st_mtim.tv_nsec */ #undef HAVE_STAT_TV_NSEC +/* Define if you have struct stat.st_mtimensec */ +#undef HAVE_STAT_TV_NSEC2 + /* Define if your compiler supports variable length function prototypes (e.g. void fprintf(FILE *, char *, ...);) *and* */ #undef HAVE_STDARG_PROTOTYPES @@ -483,6 +486,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STROPTS_H +/* Define to 1 if `st_birthtime' is member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_BIRTHTIME + /* Define to 1 if `st_blksize' is member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_BLKSIZE @@ -492,6 +498,9 @@ /* Define to 1 if `st_flags' is member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_FLAGS +/* Define to 1 if `st_gen' is member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_GEN + /* Define to 1 if `st_rdev' is member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_RDEV -- cgit v0.12