From af6c15a730507dcfdf87d902aec6ada9f7fa89ba Mon Sep 17 00:00:00 2001 From: Steve Slaven Date: Tue, 28 Jul 2009 07:55:57 -0700 Subject: Modify ftruncate to allow growing or shrinking to a size other than 0 diff --git a/fusearchive.py b/fusearchive.py index f8cce35..00a156d 100755 --- a/fusearchive.py +++ b/fusearchive.py @@ -380,7 +380,7 @@ class FuseArchive(Fuse): def truncate(self, path, len): # Truncate using the ftruncate on the file dmsg( 2, "Using FuseArchiveFile to truncate " + path + " to " + str(len) ) - f = self.FuseArchiveFile( path, os.O_APPEND, 0 ) + f = self.FuseArchiveFile( path, os.O_WRONLY | os.O_APPEND, 0 ) f.ftruncate(len) f.release( 0 ) @@ -730,6 +730,7 @@ class FuseArchive(Fuse): } ) + return 1 @@ -760,11 +761,69 @@ class FuseArchive(Fuse): stats.overstat( self.size ) return stats - def ftruncate(self, len): - if len > 0: - print "WARNING: ftruncate is broken for non-zero len!!!" + def ftruncate(self, length): + if not self.wr: + return errno.IOError + + curr_chunks = len( self.chunks ) + need_chunks = ( length / self.chunk_size ) + extra_bytes = length % self.chunk_size + dmsg( 3, "Ftruncate - " + str(length) ) + dmsg( 3, " - curr_chunks: " + str( curr_chunks ) ) + dmsg( 3, " - need_chunks: " + str( need_chunks ) ) + dmsg( 3, " - extra_bytes: " + str( extra_bytes ) ) + + if extra_bytes: + dmsg( 3, "Need an extra chunk" ) + need_chunks += 1 + + self._load_chunk( 0 ) + + pdb.set_trace() + if need_chunks == 0: + dmsg( 3, "Creating 0 chunk file" ) + self.chunks = [] + elif need_chunks > curr_chunks: + dmsg( 3, "Need to pad out file" ) + + # Just write out null bytes to the length requested + self.flush() + tmp_size = self.size + while tmp_size < length: + to_write = 4096 + if tmp_size + to_write > length: + to_write = length - tmp_size + + dmsg( 3, "Writing " + str( to_write ) + " bytes to extend file to " + str( length ) ) + self.write( "\0" * to_write, tmp_size + 1 ) + tmp_size += to_write + + else: + dmsg( 3, "Truncating chunks" ) + while True: + dmsg( 3, "Need chunks: " + str( need_chunks ) + " curr: " + str( curr_chunks ) ) + if need_chunks == curr_chunks: + break + + dmsg( 3, "Deleting chunk " + str( self.chunk_index ) ) + self.chunks.pop() + curr_chunks = len( self.chunks ) + + # Now make sure this chunk is the right size, first load the + # last chunk + if len( self.chunks ): + self._load_chunk( len( self.chunks ) - 1 ) + dmsg( 3, "Loaded final chunk, len: " + str( len( self.chunk ) ) ) + + # Now truncate or extend this item + if len( self.chunk ) < extra_bytes: + remaining = extra_bytes - len(self.chunk) + dmsg( 3, "Extending final chunk " + str( remaining ) + " bytes" ) + self.chunk += "\0" * remaining + else: + dmsg( 3, "Truncating final chunk to " + str( extra_bytes ) ) + self.chunk = self.chunk[ :extra_bytes ] - self.chunks = [] self.modified = True self._load_chunk( 0 ) self._fflush() -- cgit v0.10.2