[libgsf] Modtime improvements.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgsf] Modtime improvements.
- Date: Mon, 4 Mar 2013 17:41:38 +0000 (UTC)
commit 590b1eb86adc1fe15f6e2675d0027344b9856571
Author: Morten Welinder <terra gnome org>
Date: Mon Mar 4 12:39:57 2013 -0500
Modtime improvements.
GsfInputStdio: usec precision.
GsfOutputStdio: set timestamp on file.
GsfOutput: implement setting modtime as property.
ChangeLog | 10 ++++++++
configure.ac | 4 ++-
gsf/gsf-input-stdio.c | 15 ++++++++++++
gsf/gsf-output-stdio.c | 59 ++++++++++++++++++++++++++++++++++-------------
gsf/gsf-output.c | 11 +++++++-
tests/test-cp.c | 27 +++++++++++++--------
6 files changed, 96 insertions(+), 30 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 058a221..8a463c0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,11 +1,21 @@
2013-03-04 Morten Welinder <terra gnome org>
+ * configure.ac: Check for utime.h and sys/utime.h. Check for
+ stat.st_mtimensec and stat.st_mtim.tv_nsec.
+
+ * tests/test-cp.c (test): Copy modtime too.
+
* gsf/gsf-input.c (gsf_input_get_property): Add new modtime
property.
* gsf/gsf-output.c (gsf_output_get_property): Ditto.
* gsf/gsf-input-gzip.c (check_header): Set modtime when available.
+ * gsf/gsf-input-stdio.c (gsf_input_stdio_new): Set modtime.
+
+ * gsf/gsf-output-stdio.c (gsf_output_stdio_close): Set modtime of
+ resulting file.
+
* gsf/gsf-input.c (gsf_input_uncompress): Fix potential failure
with bzip'd input.
diff --git a/configure.ac b/configure.ac
index a3c2879..0ada77a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -259,6 +259,8 @@ if test $struct_timeval_works = no ; then
AC_MSG_ERROR([struct timeval is not available])
fi
+AC_CHECK_MEMBERS([struct stat.st_mtimensec, struct stat.st_mtim.tv_nsec])
+
AC_MSG_CHECKING([whether -D_BSD_SOURCE is needed for caddr_t])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <sys/types.h>]], [[caddr_t ca]])],
@@ -279,7 +281,7 @@ if test $need_bsd1 = yes -o $need_bsd2 = yes; then
fi
AC_TYPE_MODE_T
-AC_CHECK_HEADERS(fcntl.h malloc.h unistd.h io.h sys/statfs.h sys/param.h sys/mount.h)
+AC_CHECK_HEADERS(fcntl.h malloc.h unistd.h io.h sys/statfs.h sys/param.h sys/mount.h utime.h sys/utime.h)
AC_FUNC_MMAP
AC_MSG_CHECKING([form of statfs])
diff --git a/gsf/gsf-input-stdio.c b/gsf/gsf-input-stdio.c
index b99c74c..c20be0e 100644
--- a/gsf/gsf-input-stdio.c
+++ b/gsf/gsf-input-stdio.c
@@ -148,6 +148,21 @@ gsf_input_stdio_new (char const *filename, GError **err)
input->keep_open = FALSE;
gsf_input_set_size (GSF_INPUT (input), size);
gsf_input_set_name_from_filename (GSF_INPUT (input), filename);
+ if (st.st_mtime != (time_t)-1) {
+ GTimeVal tv;
+
+ tv.tv_sec = st.st_mtime;
+#if defined (HAVE_STRUCT_STAT_ST_MTIMENSEC)
+ tv.tv_usec = st.st_mtimensec / 1000;
+#elif defined (HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
+ tv.tv_usec = st.st_mtim.tv_nsec / 1000;
+#else
+ tv.tv_usec = 0;
+#endif
+
+ gsf_input_set_modtime (GSF_INPUT (input),
+ g_date_time_new_from_timeval_utc (&tv));
+ }
return GSF_INPUT (input);
}
diff --git a/gsf/gsf-output-stdio.c b/gsf/gsf-output-stdio.c
index bf89aef..3bcb54f 100644
--- a/gsf/gsf-output-stdio.c
+++ b/gsf/gsf-output-stdio.c
@@ -36,6 +36,14 @@
#include <sys/statfs.h>
#endif
+#ifdef HAVE_UTIME_H
+#define UTIME_AVAILABLE
+#include <utime.h>
+#elif defined(HAVE_SYS_UTIME_H)
+#define UTIME_AVAILABLE
+#include <sys/utime.h>
+#endif
+
#ifdef G_OS_WIN32
#include <wchar.h>
#include <direct.h>
@@ -193,6 +201,7 @@ gsf_output_stdio_close (GsfOutput *output)
GsfOutputStdio *stdio = GSF_OUTPUT_STDIO (output);
gboolean res;
char *backup_filename = NULL;
+ GDateTime *modtime;
if (stdio->file == NULL)
return FALSE;
@@ -238,9 +247,9 @@ gsf_output_stdio_close (GsfOutput *output)
"Could not backup the original as %s.",
utf8name);
g_free (utf8name);
- g_free (backup_filename);
g_unlink (stdio->temp_filename);
- return FALSE;
+ res = FALSE;
+ goto out;
}
}
@@ -253,24 +262,40 @@ gsf_output_stdio_close (GsfOutput *output)
res = gsf_output_set_error (output,
saved_errno,
"%s", g_strerror (saved_errno));
- } else {
- /* Restore permissions. There is not much error checking we
- * can do here, I'm afraid. The final data is saved anyways.
- * Note the order: mode, uid+gid, gid, uid, mode.
- */
- g_chmod (stdio->real_filename, stdio->st.st_mode);
-#ifdef HAVE_CHOWN
- if (chown_wrapper (stdio->real_filename,
- stdio->st.st_uid,
- stdio->st.st_gid)) {
- /* We cannot set both. Maybe we can set one. */
- chown_wrapper (stdio->real_filename, -1, stdio->st.st_gid);
- chown_wrapper (stdio->real_filename, stdio->st.st_uid, -1);
- }
- g_chmod (stdio->real_filename, stdio->st.st_mode);
+ goto out;
+ }
+
+ modtime = gsf_output_get_modtime (output);
+ if (modtime) {
+#ifdef UTIME_AVAILABLE
+ struct utimbuf ut;
+
+ ut.actime = time (NULL);
+ ut.modtime = g_date_time_to_unix (modtime);
+ /* Ignore errors */
+ /* utimes() provides better accuracy, but doesn't have
+ gstdio version. gio seems to provide access. */
+ (void)utime (stdio->real_filename, &ut);
#endif
}
+ /* Restore permissions. There is not much error checking we
+ * can do here, I'm afraid. The final data is saved anyways.
+ * Note the order: mode, uid+gid, gid, uid, mode.
+ */
+ g_chmod (stdio->real_filename, stdio->st.st_mode);
+#ifdef HAVE_CHOWN
+ if (chown_wrapper (stdio->real_filename,
+ stdio->st.st_uid,
+ stdio->st.st_gid)) {
+ /* We cannot set both. Maybe we can set one. */
+ chown_wrapper (stdio->real_filename, -1, stdio->st.st_gid);
+ chown_wrapper (stdio->real_filename, stdio->st.st_uid, -1);
+ }
+ g_chmod (stdio->real_filename, stdio->st.st_mode);
+#endif
+
+out:
g_free (backup_filename);
return res;
diff --git a/gsf/gsf-output.c b/gsf/gsf-output.c
index 2439190..a40d7e5 100644
--- a/gsf/gsf-output.c
+++ b/gsf/gsf-output.c
@@ -58,7 +58,16 @@ gsf_output_set_property (GObject *object,
G_GNUC_UNUSED GValue const *value,
GParamSpec *pspec)
{
+ GsfOutput *output = GSF_OUTPUT (object);
+
switch (property_id) {
+ case PROP_MODTIME: {
+ GDateTime *modtime = g_value_get_boxed (value);
+ if (modtime)
+ modtime = g_date_time_add (modtime, 0); // Copy
+ gsf_output_set_modtime (output, modtime);
+ break;
+ }
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -133,8 +142,6 @@ gsf_output_init (GObject *obj)
output->is_closed = FALSE;
output->printf_buf = NULL;
output->printf_buf_size = 0;
-
- gsf_output_set_modtime (output, g_date_time_new_now_utc ());
}
static void
diff --git a/tests/test-cp.c b/tests/test-cp.c
index b1a6881..6c16e2d 100644
--- a/tests/test-cp.c
+++ b/tests/test-cp.c
@@ -29,10 +29,11 @@
static int
test (char *argv[])
{
- GsfInput *input;
- GsfOutput *output;
+ GsfInput *input = NULL;
+ GsfOutput *output = NULL;
GError *err = NULL;
int rval = 0;
+ GDateTime *modtime;
input = gsf_input_stdio_new (argv[1], &err);
if (input == NULL) {
@@ -43,31 +44,37 @@ test (char *argv[])
g_error_free (err);
return 1;
}
+ modtime = gsf_input_get_modtime (input);
- output = gsf_output_stdio_new (argv[2], &err);
+ output = gsf_output_stdio_new_full
+ (argv[2], &err, "modtime", modtime, NULL);
if (output == NULL) {
-
g_return_val_if_fail (err != NULL, 1);
g_warning ("'%s' error: %s\n", argv[2], err->message);
g_error_free (err);
- g_object_unref (G_OBJECT (input));
- return 1;
+ rval = 1;
+ goto out;
}
if (gsf_input_copy (input, output) == FALSE) {
- rval = 1;
err = (GError*) gsf_output_error (output);
if (err != NULL) {
g_warning ("'%s' error: %s\n", argv[2], err->message);
}
+ rval = 1;
+ goto out;
}
- g_object_unref (G_OBJECT (input));
+out:
+ if (input)
+ g_object_unref (input);
- gsf_output_close (output);
- g_object_unref (G_OBJECT (output));
+ if (output) {
+ gsf_output_close (output);
+ g_object_unref (output);
+ }
return rval;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]