Lion compat for -lfuse_ino64 hack.
[perl-fuse.git] / Fuse.xs
diff --git a/Fuse.xs b/Fuse.xs
index 639adf8..11cfadf 100755 (executable)
--- a/Fuse.xs
+++ b/Fuse.xs
 # 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
+
+/* Implement a macro to handle multiple formats (integer, float, and array
+ * containing seconds and nanoseconds). */
+#define PULL_TIME(st, st_xtim, svp)                                    \
+{                                                                      \
+       SV *sv = svp;                                                   \
+       if (SvROK(sv)) {                                                \
+               AV *av = (AV *)SvRV(sv);                                \
+               if (SvTYPE((SV *)av) != SVt_PVAV) {                     \
+                       Perl_croak_nocontext("Reference was not array ref"); \
+               }                                                       \
+               if (av_len(av) != 1) {                                  \
+                       Perl_croak_nocontext("Array of incorrect dimension"); \
+               }                                                       \
+               (st)->st_xtim##e = SvIV(*(av_fetch(av, 0, FALSE)));     \
+               STAT_NSEC(st, st_xtim) = SvIV(*(av_fetch(av, 1, FALSE))); \
+       }                                                               \
+       else if (SvNOK(sv) || SvIOK(sv)) {                              \
+               double tm = SvNV(sv);                                   \
+               (st)->st_xtim##e = (int)tm;                             \
+               STAT_NSEC(st, st_xtim) = (tm - (int)tm) * 1000000000;   \
+       }                                                               \
+       else {                                                          \
+               Perl_croak_nocontext("Invalid data type passed");       \
+       }                                                               \
+}
+
 /* Determine if threads support should be included */
 #ifdef USE_ITHREADS
 # ifdef I_PTHREAD
@@ -162,9 +194,9 @@ int _PLfuse_getattr(const char *file, struct stat *result) {
        } else {
                result->st_blocks = POPi;
                result->st_blksize = POPi;
-               result->st_ctime = POPi;
-               result->st_mtime = POPi;
-               result->st_atime = POPi;
+               PULL_TIME(result, st_ctim, POPs);
+               PULL_TIME(result, st_mtim, POPs);
+               PULL_TIME(result, st_atim, POPs);
                result->st_size = POPn; // we pop double here to support files larger than 4Gb (long limit)
                result->st_rdev = POPi;
                result->st_gid = POPi;
@@ -997,9 +1029,9 @@ 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)));
+                                               PULL_TIME(&st, st_atim, *(av_fetch(av2,  8, FALSE)));
+                                               PULL_TIME(&st, st_mtim, *(av_fetch(av2,  9, FALSE)));
+                                               PULL_TIME(&st, st_ctim, *(av_fetch(av2, 10, FALSE)));
                                                st.st_blksize = SvIV(*(av_fetch(av2, 11, FALSE)));
                                                st.st_blocks  = SvIV(*(av_fetch(av2, 12, FALSE)));
                                                st_filled = 1;
@@ -1265,9 +1297,9 @@ int _PLfuse_fgetattr(const char *file, struct stat *result,
        } else {
                result->st_blocks = POPi;
                result->st_blksize = POPi;
-               result->st_ctime = POPi;
-               result->st_mtime = POPi;
-               result->st_atime = POPi;
+               PULL_TIME(result, st_ctim, POPs);
+               PULL_TIME(result, st_mtim, POPs);
+               PULL_TIME(result, st_atim, POPs);
                result->st_size = POPn; // we pop double here to support files larger than 4Gb (long limit)
                result->st_rdev = POPi;
                result->st_gid = POPi;