Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add fix for RT #71271.

Seems that my utimens() addition inspired someone to notice the
lack of support in other codepaths for sub-second time resolution.
This fix takes the fractional portion of any mtime/ctime/atime
values and converts it into the appropriate nanosecond value, and
assigns that to the correct location in the "struct stat". Tested
on Linux 3.0 (Ubuntu 11.10), FreeBSD 8.2, NetBSD 5.1 and MacOS X
10.6 (Snow Leopard).
  • Loading branch information...
commit 788f7ce661e7404b75e7f42e623ef638b62a0a42 1 parent 98bd016
@demonfoo demonfoo authored
Showing with 38 additions and 9 deletions.
  1. +38 −9 Fuse.xs
View
47 Fuse.xs
@@ -12,6 +12,12 @@
# include <sys/xattr.h>
#endif
+#if defined(__linux__)
+# define STAT_NSEC(st, st_xtim) ((st)->st_xtim.tv_nsec)
+#else
+# define STAT_NSEC(st, st_xtim) ((st)->st_xtim##espec.tv_nsec)
+#endif
+
/* Determine if threads support should be included */
#ifdef USE_ITHREADS
# ifdef I_PTHREAD
@@ -160,11 +166,19 @@ int _PLfuse_getattr(const char *file, struct stat *result) {
else
rv = -ENOENT;
} else {
+ double tm;
result->st_blocks = POPi;
result->st_blksize = POPi;
- result->st_ctime = POPi;
- result->st_mtime = POPi;
- result->st_atime = POPi;
+ /* Do a little gymnastics to transform the fractional part into nsec */
+ tm = POPn;
+ result->st_ctime = (int)tm;
+ STAT_NSEC(result, st_ctim) = (tm - (int)tm) * 1000000000;
+ tm = POPn;
+ result->st_mtime = (int)tm;
+ STAT_NSEC(result, st_mtim) = (tm - (int)tm) * 1000000000;
+ tm = POPn;
+ result->st_atime = (int)tm;
+ STAT_NSEC(result, st_atim) = (tm - (int)tm) * 1000000000;
result->st_size = POPn; // we pop double here to support files larger than 4Gb (long limit)
result->st_rdev = POPi;
result->st_gid = POPi;
@@ -989,6 +1003,7 @@ int _PLfuse_readdir(const char *file, void *dirh, fuse_fill_dir_t dirfil,
if (SvROK(*svp) &&
SvTYPE(av2 = (AV *)SvRV(*svp)) == SVt_PVAV &&
av_len(av2) == 12) {
+ double tm;
st.st_dev = SvIV(*(av_fetch(av2, 0, FALSE)));
st.st_ino = SvIV(*(av_fetch(av2, 1, FALSE)));
st.st_mode = SvIV(*(av_fetch(av2, 2, FALSE)));
@@ -997,9 +1012,15 @@ int _PLfuse_readdir(const char *file, void *dirh, fuse_fill_dir_t dirfil,
st.st_gid = SvIV(*(av_fetch(av2, 5, FALSE)));
st.st_rdev = SvIV(*(av_fetch(av2, 6, FALSE)));
st.st_size = SvNV(*(av_fetch(av2, 7, FALSE)));
- st.st_atime = SvIV(*(av_fetch(av2, 8, FALSE)));
- st.st_mtime = SvIV(*(av_fetch(av2, 9, FALSE)));
- st.st_ctime = SvIV(*(av_fetch(av2, 10, FALSE)));
+ tm = SvNV(*(av_fetch(av2, 8, FALSE)));
+ st.st_atime = (int)tm;
+ STAT_NSEC(&st, st_atim) = (tm - (int)tm) * 1000000000;
+ tm = SvNV(*(av_fetch(av2, 9, FALSE)));
+ st.st_mtime = (int)tm;
+ STAT_NSEC(&st, st_mtim) = (tm - (int)tm) * 1000000000;
+ tm = SvNV(*(av_fetch(av2, 10, FALSE)));
+ st.st_ctime = (int)tm;
+ STAT_NSEC(&st, st_ctim) = (tm - (int)tm) * 1000000000;
st.st_blksize = SvIV(*(av_fetch(av2, 11, FALSE)));
st.st_blocks = SvIV(*(av_fetch(av2, 12, FALSE)));
st_filled = 1;
@@ -1263,11 +1284,19 @@ int _PLfuse_fgetattr(const char *file, struct stat *result,
else
rv = -ENOENT;
} else {
+ double tm;
result->st_blocks = POPi;
result->st_blksize = POPi;
- result->st_ctime = POPi;
- result->st_mtime = POPi;
- result->st_atime = POPi;
+ /* Do a little gymnastics to transform the fractional part into nsec */
+ tm = POPn;
+ result->st_ctime = (int)tm;
+ STAT_NSEC(result, st_ctim) = (tm - (int)tm) * 1000000000;
+ tm = POPn;
+ result->st_mtime = (int)tm;
+ STAT_NSEC(result, st_mtim) = (tm - (int)tm) * 1000000000;
+ tm = POPn;
+ result->st_atime = (int)tm;
+ STAT_NSEC(result, st_atim) = (tm - (int)tm) * 1000000000;
result->st_size = POPn; // we pop double here to support files larger than 4Gb (long limit)
result->st_rdev = POPi;
result->st_gid = POPi;
Please sign in to comment.
Something went wrong with that request. Please try again.