0 Replies Latest reply on Jun 30, 2008 4:14 PM by mstruk

    VFS - corrupt ZipFile entries() enumeration on Linux

    mstruk

      I'm gonna describe here the root cause of JBVFS-38.

      The problem is Linux (maybe unix?) specific, and can be reproduced without VFS - the recipe is as follows:

      1) Open an existing zip file using JDK's ZipFile object, iterate over entries but don't close the ZipFile.

      ZipFile zf = new ZipFile(archive);
      Enumeration enum = zf.entries();
      while (enum.hasMoreElements()) {
      ...
      }



      2) Then, overwrite this zip file with new content using _any_ method (i.e. JarOutputStream, or copy over an existing archive ...) , and properly close it.

      writeNewJar(archive);


      3) Now, open a new ZipFile around this file and iterate over entries.

      zf = new ZipFile(archive);
      enum = zf.entries();
      while (enum.hasMoreElements()) {
      ...
      }

      Enumeration of entries is corrupt at this point - it returns a non existent entry with a garbled name,
      real entries are missing.

      The key to the problem is step 2) - overwriting the _still open_ ZipFile with new content.

      Interestingly enough, if after step 2) I do a Thread.sleep(30000) and copy the file over with another one through shell,
      the iteration returns proper content. But no matter how I try to do that as part of the same java process - copying streams,
      or going so far as to use Runtime.exec("sh -c 'cp file1 file2'") ... no matter what I do, it doesn't help.

      If ZipFile is closed first, then overwritten, everything is fine.

      If it's deleted and then recreated, everything is fine as well.


      I added delete() method to VirtualFile. It delegates the delete all the way to ZipEntryHandler layer - which takes care of releasing locks if necessary - so we can now reliably delete a file, and then reconstruct it, in order to avoid writing over an open file.


      - marko