This is an automated email from the ASF dual-hosted git repository.

rmaucher pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 9a76b7baa04bfefcb53033e30f29bbc23ececd89
Author: opencode <[email protected]>
AuthorDate: Tue Oct 20 13:20:34 2026 +0200

    Restore the original archive when normalising the timestamps fails
    
    The archive was atomically renamed to <name>.old before being rewritten
    and the .old file was only deleted on success. If an IOException
    occurred while rewriting (corrupt entry, disk full, ...) the task
    aborted leaving a truncated archive in place of the original, with the
    original surviving only as a stray .old file that required manual
    recovery. When the operation fails after the rename, move the .old file
    back over the partial output before rethrowing, so the input archive is
    restored byte for byte. Report a failing restore as a suppressed
    exception of the original error.
---
 java/org/apache/tomcat/buildutil/RepeatableArchive.java | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/java/org/apache/tomcat/buildutil/RepeatableArchive.java 
b/java/org/apache/tomcat/buildutil/RepeatableArchive.java
index a67939a285..761976d165 100644
--- a/java/org/apache/tomcat/buildutil/RepeatableArchive.java
+++ b/java/org/apache/tomcat/buildutil/RepeatableArchive.java
@@ -109,9 +109,11 @@ public class RepeatableArchive extends Task {
             for (String file : files) {
                 File archive = new File(basedir, file);
                 File oldArchive = new File(basedir, file + ".old");
+                boolean renamed = false;
 
                 try {
                     Files.move(archive.toPath(), oldArchive.toPath(), 
StandardCopyOption.ATOMIC_MOVE);
+                    renamed = true;
 
                     try (ZipFile oldZipFile = new ZipFile(oldArchive);
                             ZipOutputStream zipOut = new ZipOutputStream(new 
FileOutputStream(archive))) {
@@ -139,6 +141,17 @@ public class RepeatableArchive extends Task {
                     }
                     Files.delete(oldArchive.toPath());
                 } catch (IOException ioe) {
+                    // The task did not run to completion for this archive. If 
the original was
+                    // renamed, restore it rather than leaving the archive in 
its current, possibly
+                    // truncated, state together with a stray ".old".
+                    try {
+                        if (renamed) {
+                            Files.move(oldArchive.toPath(), archive.toPath(), 
StandardCopyOption.REPLACE_EXISTING,
+                                    StandardCopyOption.ATOMIC_MOVE);
+                        }
+                    } catch (IOException restoreException) {
+                        ioe.addSuppressed(restoreException);
+                    }
                     throw new BuildException(ioe);
                 }
             }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to