@Sam R It's not too difficult to create your own. A real simple solution would be something like.
bis.writeUint16 len( filename )
bis.writeUint64 len( data )
~ repeat for next file.
Do the reverse when reading the file.
That's the easy part (along with actually encrypting the data, which a VirtualVolume seems to do).
@Sam R The biggest complication comes from replacing the data with larger content.
That's somehow what I meant with my statement “just removing one file is going to rewrite all the master file”. Perhaps the VirtualVolume class has that requirement too (rewriting the whole file when one subfile changes, even if there are less data than previously). For small files, that's probably unnoticeable; if there's just one “large” file and even if you just replace a one byte file with another byte, it would take time (the user may not understand why writing one byte takes 15 minutes…).
However, your reply made me remembering I have already made my own archive format, which I use for updating my apps (among other things); I could adapt it to more needs…