1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-19 18:20:22 +02:00

nanosecond timestamp support in stat and utime

* libguile/posix.h:
* libguile/posix.c (scm_utime): Add optional nanosecond arguments. This
  is an incompatible change on the C level, but it's unlikely people are
  using this POSIX wrapper function, because they would just use the
  POSIX function directly. Hopefully, anyway.

* module/system/base/compile.scm (call-with-output-file/atomic):
  Propagate source timestamps to targets with nanosecond precision, if
  available. Fixes build on systems with ext4 filesystems.

* libguile/filesys.c (scm_stat2scm):
* module/ice-9/posix.scm (stat:atimensec, stat:mtimensec)
  (stat:ctimensec): Add three new elements to Scheme stat structures,
  for nanosecond-level timestamps.

* configure.ac: Add checks for utimensat, and for nanosecond fields in
  struct stat. We should switch to using Gnulib things for these,
  though.

* doc/ref/posix.texi (File System): Add documentation for utime's
  additional arguments, and nanosecond stat timestamp accessors.
This commit is contained in:
Andy Wingo 2010-01-17 16:56:21 +01:00
parent f826a8864a
commit 06bfe276c8
7 changed files with 120 additions and 23 deletions

View file

@ -405,7 +405,7 @@ SCM_SYMBOL (scm_sym_unknown, "unknown");
static SCM
scm_stat2scm (struct stat_or_stat64 *stat_temp)
{
SCM ans = scm_c_make_vector (15, SCM_UNSPECIFIED);
SCM ans = scm_c_make_vector (18, SCM_UNSPECIFIED);
SCM_SIMPLE_VECTOR_SET(ans, 0, scm_from_ulong (stat_temp->st_dev));
SCM_SIMPLE_VECTOR_SET(ans, 1, scm_from_ino_t_or_ino64_t (stat_temp->st_ino));
@ -490,6 +490,21 @@ scm_stat2scm (struct stat_or_stat64 *stat_temp)
*/
}
#ifdef HAVE_STRUCT_STAT_ST_ATIM
SCM_SIMPLE_VECTOR_SET(ans, 15, scm_from_long (stat_temp->st_atim.tv_nsec));
#else
SCM_SIMPLE_VECTOR_SET(ans, 15, SCM_I_MAKINUM (0));
#endif
#ifdef HAVE_STRUCT_STAT_ST_MTIM
SCM_SIMPLE_VECTOR_SET(ans, 16, scm_from_long (stat_temp->st_mtim.tv_nsec));
#else
SCM_SIMPLE_VECTOR_SET(ans, 16, SCM_I_MAKINUM (0));
#endif
#ifdef HAVE_STRUCT_STAT_ST_CTIM
SCM_SIMPLE_VECTOR_SET(ans, 17, scm_from_ulong (stat_temp->st_ctim.tv_sec));
#else
SCM_SIMPLE_VECTOR_SET(ans, 17, SCM_I_MAKINUM (0));
#endif
return ans;
}

View file

@ -1373,13 +1373,18 @@ SCM_DEFINE (scm_mkstemp, "mkstemp!", 1, 0, 0,
}
#undef FUNC_NAME
SCM_DEFINE (scm_utime, "utime", 1, 2, 0,
(SCM pathname, SCM actime, SCM modtime),
SCM_DEFINE (scm_utime, "utime", 1, 5, 0,
(SCM pathname, SCM actime, SCM modtime, SCM actimens, SCM modtimens,
SCM flags),
"@code{utime} sets the access and modification times for the\n"
"file named by @var{path}. If @var{actime} or @var{modtime} is\n"
"not supplied, then the current time is used. @var{actime} and\n"
"@var{modtime} must be integer time values as returned by the\n"
"@code{current-time} procedure.\n"
"@code{current-time} procedure.\n\n"
"The optional @var{actimens} and @var{modtimens} are nanoseconds\n"
"to add @var{actime} and @var{modtime}. Nanosecond precision is\n"
"only supported on some combinations of filesystems and operating\n"
"systems.\n"
"@lisp\n"
"(utime \"foo\" (- (current-time) 3600))\n"
"@end lisp\n"
@ -1388,20 +1393,75 @@ SCM_DEFINE (scm_utime, "utime", 1, 2, 0,
#define FUNC_NAME s_scm_utime
{
int rv;
struct utimbuf utm_tmp;
time_t atim_sec, mtim_sec;
long atim_nsec, mtim_nsec;
int f;
if (SCM_UNBNDP (actime))
SCM_SYSCALL (time (&utm_tmp.actime));
{
#if HAVE_UTIMENSAT
atim_sec = 0;
atim_nsec = UTIME_NOW;
#else
SCM_SYSCALL (time (&atim_sec));
atim_nsec = 0;
#endif
}
else
utm_tmp.actime = SCM_NUM2ULONG (2, actime);
{
atim_sec = SCM_NUM2ULONG (2, actime);
if (SCM_UNBNDP (actimens))
atim_nsec = 0;
else
atim_nsec = SCM_NUM2LONG (4, actimens);
}
if (SCM_UNBNDP (modtime))
SCM_SYSCALL (time (&utm_tmp.modtime));
{
#if HAVE_UTIMENSAT
mtim_sec = 0;
mtim_nsec = UTIME_NOW;
#else
SCM_SYSCALL (time (&mtim_sec));
mtim_nsec = 0;
#endif
}
else
utm_tmp.modtime = SCM_NUM2ULONG (3, modtime);
{
mtim_sec = SCM_NUM2ULONG (3, modtime);
if (SCM_UNBNDP (modtimens))
mtim_nsec = 0;
else
mtim_nsec = SCM_NUM2LONG (5, modtimens);
}
if (SCM_UNBNDP (flags))
f = 0;
else
f = SCM_NUM2INT (6, flags);
#if HAVE_UTIMENSAT
{
struct timespec times[2];
times[0].tv_sec = atim_sec;
times[0].tv_nsec = atim_nsec;
times[1].tv_sec = mtim_sec;
times[1].tv_nsec = mtim_nsec;
STRING_SYSCALL (pathname, c_pathname,
rv = utimensat (AT_FDCWD, c_pathname, &times, f));
}
#else
{
struct utimbuf utm;
utm.actime = atim_sec;
utm.modtime = mtim_sec;
STRING_SYSCALL (pathname, c_pathname,
rv = utime (c_pathname, &utm));
}
#endif
STRING_SYSCALL (pathname, c_pathname,
rv = utime (c_pathname, &utm_tmp));
if (rv != 0)
SCM_SYSERROR;
return SCM_UNSPECIFIED;

View file

@ -70,7 +70,8 @@ SCM_API SCM scm_tmpnam (void);
SCM_API SCM scm_mkstemp (SCM tmpl);
SCM_API SCM scm_open_pipe (SCM pipestr, SCM modes);
SCM_API SCM scm_close_pipe (SCM port);
SCM_API SCM scm_utime (SCM pathname, SCM actime, SCM modtime);
SCM_API SCM scm_utime (SCM pathname, SCM actime, SCM modtime,
SCM actimens, SCM modtimens, SCM flags);
SCM_API SCM scm_access (SCM path, SCM how);
SCM_API SCM scm_getpid (void);
SCM_API SCM scm_putenv (SCM str);