my @subs = map {undef} @names;
my $tmp = 0;
my %mapping = map { $_ => $tmp++ } @names;
- my @otherargs = qw(debug threaded mountpoint mountopts nullpath_ok);
+ my @otherargs = qw(debug threaded mountpoint mountopts nullpath_ok utimens_as_array);
my %otherargs = (
- debug => 0,
- threaded => 0,
- mountpoint => "",
- mountopts => "",
- nullpath_ok => 0,
+ debug => 0,
+ threaded => 0,
+ mountpoint => "",
+ mountopts => "",
+ nullpath_ok => 0,
+ utimens_as_array => 0,
);
while(my $name = shift) {
my ($subref) = shift;
file/directory handles from open, opendir and create. Default is 0 (off).
Only effective on Fuse 2.8 and up; with earlier versions, this does nothing.
+=item utimens_as_array => boolean
+
+This flag causes timestamps passed via the utimens() call to be passed
+as arrays containing the time in seconds, and a second value containing
+the number of nanoseconds, instead of a floating point value. This allows
+for more precise times, as the normal floating point type used by Perl
+(double) loses accuracy starting at about tenths of a microsecond.
+
=back
=head3 Fuse::fuse_get_context
Note that if this call is implemented, it overrides utime() ALWAYS.
+Also note that if you want times passed as arrays instead of floating point
+values, for higher precision, you should pass the C<utimens_as_array> option
+to C<Fuse::main>.
+
=head3 bmap
Arguments: Pathname, numeric blocksize, numeric block number
#ifdef USE_ITHREADS
perl_mutex mutex;
#endif
+ int utimens_as_array;
} my_cxt_t;
START_MY_CXT;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpv(file,0)));
- XPUSHs(tv ? sv_2mortal(newSVnv(tv[0].tv_sec + (tv[0].tv_nsec / 1000000000.0))) : &PL_sv_undef);
- XPUSHs(tv ? sv_2mortal(newSVnv(tv[1].tv_sec + (tv[1].tv_nsec / 1000000000.0))) : &PL_sv_undef);
+ if (MY_CXT.utimens_as_array) {
+ /* Pushing timespecs as 2-element arrays (if tv is present). */
+ AV *av;
+ if (tv) {
+ av = newAV();
+ av_push(av, newSViv(tv[0].tv_sec));
+ av_push(av, newSViv(tv[0].tv_nsec));
+ XPUSHs(sv_2mortal(newRV_noinc((SV *)av)));
+ av = newAV();
+ av_push(av, newSViv(tv[1].tv_sec));
+ av_push(av, newSViv(tv[1].tv_nsec));
+ XPUSHs(sv_2mortal(newRV_noinc((SV *)av)));
+ }
+ else {
+ XPUSHs(&PL_sv_undef);
+ XPUSHs(&PL_sv_undef);
+ }
+
+ }
+ else {
+ /* Pushing timespecs as floating point (double) values. */
+ XPUSHs(tv ? sv_2mortal(newSVnv(tv[0].tv_sec + (tv[0].tv_nsec / 1000000000.0))) : &PL_sv_undef);
+ XPUSHs(tv ? sv_2mortal(newSVnv(tv[1].tv_sec + (tv[1].tv_nsec / 1000000000.0))) : &PL_sv_undef);
+ }
PUTBACK;
rv = call_sv(MY_CXT.callback[36],G_SCALAR);
SPAGAIN;
struct fuse_chan *fc;
dMY_CXT;
INIT:
- if(items != N_CALLBACKS + 5) {
+ if(items != N_CALLBACKS + 6) {
fprintf(stderr,"Perl<->C inconsistency or internal error\n");
XSRETURN_UNDEF;
}
#if FUSE_VERSION >= 28
fops.flag_nullpath_ok = SvIV(ST(4));
#endif /* FUSE_VERSION >= 28 */
+ MY_CXT.utimens_as_array = SvIV(ST(5));
for(i=0;i<N_CALLBACKS;i++) {
- SV *var = ST(i+5);
+ SV *var = ST(i+6);
/* allow symbolic references, or real code references. */
if(SvOK(var) && (SvPOK(var) || (SvROK(var) && SvTYPE(SvRV(var)) == SVt_PVCV))) {
void **tmp1 = (void**)&_available_ops, **tmp2 = (void**)&fops;
} else if(SvOK(var)) {
croak("invalid callback (%i) passed to perl_fuse_main "
"(%s is not a string, code ref, or undef).\n",
- i+5,SvPVbyte_nolen(var));
+ i+6,SvPVbyte_nolen(var));
} else {
MY_CXT.callback[i] = NULL;
}