From 6fd3b1c8bbfdf8b1ee8e9613b9121f5205660633 Mon Sep 17 00:00:00 2001 From: Derrik Pates Date: Thu, 9 Dec 2010 22:26:18 +0100 Subject: [PATCH] 64-bit support, 2.6 binding I am (somewhat indirectly, now) using the Fuse package, which you maintain, as the basis for a set of Perl modules I've written to mount AFP filesystems via Fuse. I actually have made a few changes to the copy I run, to address the following issues: - On NetBSD, the Fuse package won't build out of the box against NetBSD's ReFUSE implementation; I have a few changes that make it work (all except extended attributes, which apparently PUFFS/ReFUSE doesn't yet handle). - On FreeBSD and NetBSD, the version 2.6 binding profile works better, so I've altered the code slightly to use it; it works on Linux and OS X as well. - On most 32-bit Linux distributions (and NetBSD/FreeBSD), Perl is not built with 64-bit integer support, thus breaking access to large files (> 2 ** 31 - 1 bytes long). I've added a sort-of-hackish workaround for Perl builds without $Config{'use64bitint'} to get large files handled sanely. - Added a few extra option names that aren't included in the @validOpts list by default. If you're interested in my code, check out http://svn.now.ai/listing.php?repname=afp-perl to see the repository, or http://svn.now.ai/svn/afp-perl/ for SVN checkout access. -- Derrik Pates demon@now.ai --- Fuse.xs | 42 ++++++++++++++++++++++++++++++++++++------ Makefile.PL | 6 ++++-- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/Fuse.xs b/Fuse.xs index a5cc6c7..9574fdd 100755 --- a/Fuse.xs +++ b/Fuse.xs @@ -368,13 +368,22 @@ int _PLfuse_chown (const char *file, uid_t uid, gid_t gid) { int _PLfuse_truncate (const char *file, off_t off) { int rv; +#ifndef PERL_HAS_64BITINT + char *temp; +#endif FUSE_CONTEXT_PRE; DEBUGf("truncate begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newSVpv(file,0))); +#ifdef PERL_HAS_64BITINT XPUSHs(sv_2mortal(newSViv(off))); +#else + asprintf(&temp, "%llu", off); + XPUSHs(sv_2mortal(newSVpv(temp, 0))); + free(temp); +#endif PUTBACK; rv = call_sv(_PLfuse_callbacks[12],G_SCALAR); SPAGAIN; @@ -498,6 +507,9 @@ int _PLfuse_open (const char *file, struct fuse_file_info *fi) { int _PLfuse_read (const char *file, char *buf, size_t buflen, off_t off, struct fuse_file_info *fi) { int rv; +#ifndef PERL_HAS_64BITINT + char *temp; +#endif FUSE_CONTEXT_PRE; DEBUGf("read begin\n"); ENTER; @@ -505,7 +517,13 @@ int _PLfuse_read (const char *file, char *buf, size_t buflen, off_t off, struct PUSHMARK(SP); XPUSHs(sv_2mortal(newSVpv(file,0))); XPUSHs(sv_2mortal(newSViv(buflen))); +#ifdef PERL_HAS_64BITINT XPUSHs(sv_2mortal(newSViv(off))); +#else + asprintf(&temp, "%llu", off); + XPUSHs(sv_2mortal(newSVpv(temp, 0))); + free(temp); +#endif XPUSHs(fi->fh==0 ? &PL_sv_undef : (SV *)fi->fh); PUTBACK; rv = call_sv(_PLfuse_callbacks[15],G_SCALAR); @@ -538,6 +556,9 @@ int _PLfuse_read (const char *file, char *buf, size_t buflen, off_t off, struct int _PLfuse_write (const char *file, const char *buf, size_t buflen, off_t off, struct fuse_file_info *fi) { int rv; +#ifndef PERL_HAS_64BITINT + char *temp; +#endif FUSE_CONTEXT_PRE; DEBUGf("write begin\n"); ENTER; @@ -545,7 +566,13 @@ int _PLfuse_write (const char *file, const char *buf, size_t buflen, off_t off, PUSHMARK(SP); XPUSHs(sv_2mortal(newSVpv(file,0))); XPUSHs(sv_2mortal(newSVpvn(buf,buflen))); +#ifdef PERL_HAS_64BITINT XPUSHs(sv_2mortal(newSViv(off))); +#else + asprintf(&temp, "%llu", off); + XPUSHs(sv_2mortal(newSVpv(temp, 0))); + free(temp); +#endif XPUSHs(fi->fh==0 ? &PL_sv_undef : (SV *)fi->fh); PUTBACK; rv = call_sv(_PLfuse_callbacks[16],G_SCALAR); @@ -906,11 +933,12 @@ perl_fuse_main(...) struct fuse_operations fops = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; - int i, fd, debug, threaded; + int i, debug, threaded; char *mountpoint; char *mountopts; struct fuse_args margs = FUSE_ARGS_INIT(0, NULL); struct fuse_args fargs = FUSE_ARGS_INIT(0, NULL); + struct fuse_chan *fc; INIT: if(items != 29) { fprintf(stderr,"Perl<->C inconsistency or internal error\n"); @@ -962,9 +990,9 @@ perl_fuse_main(...) fuse_opt_free_args(&margs); croak("out of memory\n"); } - fd = fuse_mount(mountpoint,&margs); + fc = fuse_mount(mountpoint,&margs); fuse_opt_free_args(&margs); - if(fd < 0) + if (fc == NULL) croak("could not mount fuse filesystem!\n"); if (debug) { if ( fuse_opt_add_arg(&fargs, "") == -1 || @@ -976,9 +1004,11 @@ perl_fuse_main(...) if (fuse_opt_add_arg(&fargs, "") == -1) croak("out of memory\n"); } - +#ifndef __NetBSD__ if(threaded) { - fuse_loop_mt(fuse_new(fd,&fargs,&fops,sizeof(fops))); + fuse_loop_mt(fuse_new(fc,&fargs,&fops,sizeof(fops),NULL)); } else - fuse_loop(fuse_new(fd,&fargs,&fops,sizeof(fops))); +#endif + fuse_loop(fuse_new(fc,&fargs,&fops,sizeof(fops),NULL)); + fuse_unmount(mountpoint,fc); fuse_opt_free_args(&fargs); diff --git a/Makefile.PL b/Makefile.PL index 61a8420..1522ff5 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,5 @@ use ExtUtils::MakeMaker; +use Config; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. @@ -27,10 +28,11 @@ if ($ver && $ver + 0 < 2.5) { warn "fuse version found: ", $ver || $ver2 || $ver3, "\n"; } -my $inc = '-DFUSE_USE_VERSION=25 ' . `pkg-config --cflags fuse` || '-I ../include -D_FILE_OFFSET_BITS=64'; -my $obj = `pkg-config --libs fuse` || '-lfuse'; +my $inc = '-DFUSE_USE_VERSION=26 ' . `pkg-config --cflags fuse` || '-I ../include -D_FILE_OFFSET_BITS=64'; +my $obj = `pkg-config --libs fuse` || (($^O eq 'netbsd') ? '-lrefuse' : '-lfuse'); my $def = '-Wall -g -ggdb'; $def .= ' -D__FreeBSD__=10 -D_FILE_OFFSET_BITS=64' if $^O eq 'darwin'; +$def .= ' -DPERL_HAS_64BITINT' if $Config{'use64bitint'}; WriteMakefile( 'NAME' => 'Fuse', -- 2.20.1