libreplace: always provide utime() and utimes()
authorStefan Metzmacher <metze@samba.org>
Wed, 7 May 2008 11:10:31 +0000 (13:10 +0200)
committerStefan Metzmacher <metze@samba.org>
Wed, 7 May 2008 11:25:22 +0000 (13:25 +0200)
I'd like to also provide futimes(), but it seems
that some systems doesn't support a it at kernel level.

If someone knows how to write a portable replacement
for futimes() please tell me...

metze

source/lib/replace/README
source/lib/replace/replace.c
source/lib/replace/replace.h
source/lib/replace/system/config.m4
source/lib/replace/system/time.h
source/lib/replace/test/testsuite.c

index 43f7b08572ff1412f52e3aab0f15fd27212d9ef1..4d94317c4b024f4d0f4f4abb9f99dff38d8d279a 100644 (file)
@@ -62,6 +62,8 @@ getnameinfo
 gai_strerror
 getifaddrs
 freeifaddrs
+utime
+utimes
 
 Types:
 bool
index 443da2ab24e1894c376cbe1181fbbe7567b554be..2c3f14c2dfb8694a0cda2581dffe465a4eb2eac9 100644 (file)
@@ -584,3 +584,30 @@ int rep_unsetenv(const char *name)
        return 0;
 }
 #endif
+
+#ifndef HAVE_UTIME
+int rep_utime(const char *filename, const struct utimbuf *buf)
+{
+       errno = ENOSYS;
+       return -1;
+}
+#endif
+
+#ifndef HAVE_UTIMES
+int rep_utimes(const char *filename, const struct timeval tv[2])
+{
+       struct utimbuf u;
+
+       u.actime = tv[0].tv_sec;
+       if (tv[0].tv_usec > 500000) {
+               u.actime += 1;
+       }
+
+       u.modtime = tv[1].tv_sec;
+       if (tv[1].tv_usec > 500000) {
+               u.modtime += 1;
+       }
+
+       return utime(filename, &u);
+}
+#endif
index bf95169352ecb9cebde68b3abcdc31a9da36efec..c69ea6cdac4d8ae873db163b4ceb6c1cbf73f792 100644 (file)
@@ -101,6 +101,16 @@ void *rep_memmove(void *dest,const void *src,int size);
 /* prototype is in "system/time.h" */
 #endif
 
+#ifndef HAVE_UTIME
+#define utime rep_utime
+/* prototype is in "system/time.h" */
+#endif
+
+#ifndef HAVE_UTIMES
+#define utimes rep_utimes
+/* prototype is in "system/time.h" */
+#endif
+
 #ifndef HAVE_STRLCPY
 #define strlcpy rep_strlcpy
 size_t rep_strlcpy(char *d, const char *s, size_t bufsize);
index ae26bb55905a12e13014213de7847b141b99c2fc..5c9b53d5c59086ae22229e1e1d098aa330fef877 100644 (file)
@@ -9,7 +9,7 @@ AC_CHECK_HEADERS(sys/select.h)
 # time
 AC_CHECK_HEADERS(sys/time.h utime.h)
 AC_HEADER_TIME
-AC_CHECK_FUNCS(utime utimes futimes)
+AC_CHECK_FUNCS(utime utimes)
 
 # wait
 AC_HEADER_SYS_WAIT
index 036812ab8facfd841eded041d73526dc58294717..4abf295d1af819af2992e50f65355a690f122d84 100644 (file)
 
 #ifdef HAVE_UTIME_H
 #include <utime.h>
+#else
+struct utimbuf {
+       time_t actime;       /* access time */
+       time_t modtime;      /* modification time */
+};
 #endif
 
 #ifndef HAVE_MKTIME
@@ -51,4 +56,14 @@ time_t rep_mktime(struct tm *t);
 time_t rep_timegm(struct tm *tm);
 #endif
 
+#ifndef HAVE_UTIME
+/* define is in "replace.h" */
+int rep_utime(const char *filename, const struct utimbuf *buf);
+#endif
+
+#ifndef HAVE_UTIMES
+/* define is in "replace.h" */
+int rep_utimes(const char *filename, const struct timeval tv[2]);
+#endif
+
 #endif
index b53836036562b1df0ab99928184226108ff271e3..1e8290906e18b039505582769b3e59b4495649a3 100644 (file)
@@ -872,6 +872,149 @@ static int test_getifaddrs(void)
        return true;
 }
 
+static int test_utime(void)
+{
+       struct utimbuf u;
+       struct stat st1, st2, st3;
+       int fd;
+
+       printf("test: utime\n");
+       unlink(TESTFILE);
+
+       fd = open(TESTFILE, O_RDWR|O_CREAT, 0600);
+       if (fd == -1) {
+               printf("failure: utime [\n"
+                      "creating '%s' failed - %s\n]\n",
+                      TESTFILE, strerror(errno));
+               return false;
+       }
+
+       if (fstat(fd, &st1) != 0) {
+               printf("failure: utime [\n"
+                      "fstat (1) failed - %s\n]\n",
+                      strerror(errno));
+               return false;
+       }
+
+       u.actime = st1.st_atime + 300;
+       u.modtime = st1.st_mtime - 300;
+       if (utime(TESTFILE, &u) != 0) {
+               printf("failure: utime [\n"
+                      "utime(&u) failed - %s\n]\n",
+                      strerror(errno));
+               return false;
+       }
+
+       if (fstat(fd, &st2) != 0) {
+               printf("failure: utime [\n"
+                      "fstat (2) failed - %s\n]\n",
+                      strerror(errno));
+               return false;
+       }
+
+       if (utime(TESTFILE, NULL) != 0) {
+               printf("failure: utime [\n"
+                      "utime(NULL) failed - %s\n]\n",
+                      strerror(errno));
+               return false;
+       }
+
+       if (fstat(fd, &st3) != 0) {
+               printf("failure: utime [\n"
+                      "fstat (3) failed - %s\n]\n",
+                      strerror(errno));
+               return false;
+       }
+
+#define CMP_VAL(a,c,b) do { \
+       if (a c b) { \
+               printf("failure: utime [\n" \
+                      "%s: %s(%d) %s %s(%d)\n]\n", \
+                      __location__, \
+                      #a, (int)a, #c, #b, (int)b); \
+               return false; \
+       } \
+} while(0)
+#define EQUAL_VAL(a,b) CMP_VAL(a,!=,b)
+#define GREATER_VAL(a,b) CMP_VAL(a,<=,b)
+#define LESSER_VAL(a,b) CMP_VAL(a,>=,b)
+
+       EQUAL_VAL(st2.st_atime, st1.st_atime + 300);
+       EQUAL_VAL(st2.st_mtime, st1.st_mtime - 300);
+       LESSER_VAL(st3.st_atime, st2.st_atime);
+       GREATER_VAL(st3.st_mtime, st2.st_mtime);
+
+#undef CMP_VAL
+#undef EQUAL_VAL
+#undef GREATER_VAL
+#undef LESSER_VAL
+
+       unlink(TESTFILE);
+       printf("success: utime\n");
+       return true;
+}
+
+static int test_utimes(void)
+{
+       struct timeval tv[2];
+       struct stat st1, st2;
+       int fd;
+
+       printf("test: utimes\n");
+       unlink(TESTFILE);
+
+       fd = open(TESTFILE, O_RDWR|O_CREAT, 0600);
+       if (fd == -1) {
+               printf("failure: utimes [\n"
+                      "creating '%s' failed - %s\n]\n",
+                      TESTFILE, strerror(errno));
+               return false;
+       }
+
+       if (fstat(fd, &st1) != 0) {
+               printf("failure: utimes [\n"
+                      "fstat (1) failed - %s\n]\n",
+                      strerror(errno));
+               return false;
+       }
+
+       ZERO_STRUCT(tv);
+       tv[0].tv_sec = st1.st_atime + 300;
+       tv[1].tv_sec = st1.st_mtime - 300;
+       if (utimes(TESTFILE, tv) != 0) {
+               printf("failure: utimes [\n"
+                      "utimes(tv) failed - %s\n]\n",
+                      strerror(errno));
+               return false;
+       }
+
+       if (fstat(fd, &st2) != 0) {
+               printf("failure: utimes [\n"
+                      "fstat (2) failed - %s\n]\n",
+                      strerror(errno));
+               return false;
+       }
+
+#define EQUAL_VAL(a,b) do { \
+       if (a != b) { \
+               printf("failure: utimes [\n" \
+                      "%s: %s(%d) != %s(%d)\n]\n", \
+                      __location__, \
+                      #a, (int)a, #b, (int)b); \
+               return false; \
+       } \
+} while(0)
+
+       EQUAL_VAL(st2.st_atime, st1.st_atime + 300);
+       EQUAL_VAL(st2.st_mtime, st1.st_mtime - 300);
+
+#undef EQUAL_VAL
+
+       unlink(TESTFILE);
+       printf("success: utimes\n");
+       return true;
+}
+
 struct torture_context;
 bool torture_local_replace(struct torture_context *ctx)
 {
@@ -920,6 +1063,8 @@ bool torture_local_replace(struct torture_context *ctx)
        ret &= test_socketpair();
        ret &= test_strptime();
        ret &= test_getifaddrs();
+       ret &= test_utime();
+       ret &= test_utimes();
 
        return ret;
 }