aboutsummaryrefslogtreecommitdiffstats
path: root/fusearchive.py
diff options
context:
space:
mode:
authorSteve Slaven <bpk@hoopajoo.net>2009-07-28 21:19:04 (GMT)
committerSteve Slaven <bpk@hoopajoo.net>2009-07-28 21:19:04 (GMT)
commitd8eb6cf4482087f473101e32ef02aba5180093ec (patch)
treea07bbe7b820f76160e255a5571351a66691589df /fusearchive.py
parentd950f262888b3cab63a0cf55af10f0ef22b4b2dd (diff)
downloadfusearchive-d8eb6cf4482087f473101e32ef02aba5180093ec.zip
fusearchive-d8eb6cf4482087f473101e32ef02aba5180093ec.tar.gz
fusearchive-d8eb6cf4482087f473101e32ef02aba5180093ec.tar.bz2
This is a workaround for a bug with lseek causing a getattr instead of
fgetattr on an already opened file, so it reports the wrong file size if you use seek_end for whence by reading the on-disk info instead of the open-file info
Diffstat (limited to 'fusearchive.py')
-rwxr-xr-xfusearchive.py35
1 files changed, 30 insertions, 5 deletions
diff --git a/fusearchive.py b/fusearchive.py
index a0cdb18..f3567aa 100755
--- a/fusearchive.py
+++ b/fusearchive.py
@@ -46,6 +46,14 @@ dirty_size = 1024 * 1024 * 1;
# This is the number of actualy blocks in that size
dirty_flush = int( dirty_size / magic_blocksize )
+# This is a cache of open files by inode, to fix the lseek == size problem
+# this causes a failure in fsx-linux becuase to to lseek(fd,0,seek_end) it
+# apparently does a getattr to find the file length then subtracts the
+# offset from that to pass to write or whatever, since the offset is passed
+# to write and we don't maintain one internally. xmp.py also fails this
+# test.
+dirty_cache = {}
+
def flag2mode(flags):
md = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'}
m = md[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)]
@@ -344,11 +352,19 @@ class FuseArchive(Fuse):
treefile = "./tree" + path
if os.path.isfile( treefile ):
- logging.debug( "Delegating getattr to FuserArchiveFile" )
-
- f = self.FuseArchiveFile( path, os.O_RDONLY, 0 )
- stats = f.fgetattr()
- f.release( 0 )
+ logging.debug( "Delegating getattr to FuserArchiveFile for " + path )
+
+ # Check in the dirty cache first (to handle lseek and the
+ # relatively broken implmentation in fuse/python)
+ if path in dirty_cache:
+ logging.info( "WORKAROUND: lseek appears to do a gettattr if whence is SEEK_END, using dirty cache object" )
+ f = dirty_cache[ path ]
+ stats = f.fgetattr()
+ # no release, it's still being used
+ else:
+ f = self.FuseArchiveFile( path, os.O_RDONLY, 0 )
+ stats = f.fgetattr()
+ f.release( 0 )
else:
logging.debug( "Using os.lstat to get stats" )
stats = os.lstat( treefile )
@@ -725,6 +741,10 @@ class FuseArchive(Fuse):
logging.debug( "Chunk size is now: " + str(len(self.chunk)) )
logging.debug( "File size is now: " + str(self.size) )
+
+ # Mark us in the dirty cache
+ dirty_cache[ self.orig_path ] = self
+
return len(buf)
# BUG: If you cp -a a file then quickly ls -l sometimes it doesn't show
@@ -766,6 +786,10 @@ class FuseArchive(Fuse):
'chunk_size': self.chunk_size
} )
+ # Not dirty anymore
+ if self.orig_path in dirty_cache:
+ del dirty_cache[ self.orig_path ]
+
logging.debug( "_fflush exit" )
return 1
@@ -854,6 +878,7 @@ class FuseArchive(Fuse):
self.modified = True
self.size = length
self._load_chunk( 0 )
+ # Don't need to mark dirty cache because we're flushing
self._fflush()
def lock(self, cmd, owner, **kw):