fix other 2 cases of conflicting destdir files
authorJoey Hess <joey@kitenet.net>
Sun, 18 Jul 2010 21:30:46 +0000 (17:30 -0400)
committerJoey Hess <joey@kitenet.net>
Sun, 18 Jul 2010 21:38:35 +0000 (17:38 -0400)
Cleanly fixed case where destdir file failed to be written because there
was a directory with the same name. This can be detected with no extra
system calls, and dealt with by finding all pages that wrote files
inside the directory, and removing them and the directory.

The other, inverse case would be expensive to detect in will_render,
since it would need to check each parent directory of the file to see
if the directory is really a conflicting file. But prep_writefile
already does a similar scan for symlinks in the path, so I added code
there to remove the conflicting file. This fix assumes that the file
is written using writefile, and not some other means (but using other means
would be a security hole too, so hopefully nothing does).

IkiWiki.pm
debian/changelog
doc/bugs/conflicts.mdwn

index 85b5424863e5836af0b9d1e0dba2ef0fb73abb87..fa49b2c340fe9b40f46db39a42c0d084b1fcd4f1 100644 (file)
@@ -823,6 +823,17 @@ sub prep_writefile ($$) {
                if (-l "$destdir/$test") {
                        error("cannot write to a symlink ($test)");
                }
+               if (-f _ && $test ne $file) {
+                       # Remove conflicting file.
+                       foreach my $p (keys %renderedfiles, keys %oldrenderedfiles) {
+                               foreach my $f (@{$renderedfiles{$p}}, @{$oldrenderedfiles{$p}}) {
+                                       if ($f eq $test) {
+                                               unlink("$destdir/$test");
+                                               last;
+                                       }
+                               }
+                       }
+               }
                $test=dirname($test);
        }
 
@@ -876,11 +887,12 @@ sub will_render ($$;$) {
        my $dest=shift;
        my $clear=shift;
 
-       # Important security check.
+       # Important security check for independently created files.
        if (-e "$config{destdir}/$dest" && ! $config{rebuild} &&
            ! grep { $_ eq $dest } (@{$renderedfiles{$page}}, @{$oldrenderedfiles{$page}}, @{$wikistate{editpage}{previews}})) {
                my $from_other_page=0;
-               foreach my $p (keys %renderedfiles) {
+               # Expensive, but rarely runs.
+               foreach my $p (keys %renderedfiles, keys %oldrenderedfiles) {
                        if (grep {
                                $_ eq $dest ||
                                dirname($_) eq $dest
@@ -894,6 +906,19 @@ sub will_render ($$;$) {
                        unless $from_other_page;
        }
 
+       # If $dest exists as a directory, remove conflicting files in it
+       # rendered from other pages.
+       if (-d _) {
+               foreach my $p (keys %renderedfiles, keys %oldrenderedfiles) {
+                       foreach my $f (@{$renderedfiles{$p}}, @{$oldrenderedfiles{$p}}) {
+                               if ($f eq dirname($dest) || dirname($f) eq $dest) {
+                                       unlink("$config{destdir}/$f");
+                                       rmdir(dirname("$config{destdir}/$f"));
+                               }
+                       }
+               }
+       }
+
        if (! $clear || $cleared{$page}) {
                $renderedfiles{$page}=[$dest, grep { $_ ne $dest } @{$renderedfiles{$page}}];
        }
index bb9a43692d459dac45b98fe8bfa2a207c6319399..21b5d01fa6277a97a6eb24bd8852427ade3e1272 100644 (file)
@@ -18,6 +18,8 @@ ikiwiki (3.20100705) UNRELEASED; urgency=low
   * po: needstranslation() pagespec can have a percent specified.
   * Drop Cache-Control must-revalidate (Firefox 3.5.10 does not seem to have
     the caching problem that was added to work around). Closes: #588623
+  * Made much more robust in cases where multiple source files produce
+    conflicting files/directories in the destdir.
 
  -- Joey Hess <joeyh@debian.org>  Mon, 05 Jul 2010 13:59:42 -0400
 
index a67450290f270f54ade7c04cc1ecf2ef2fde7d86..bef0f54cd4f5e6a2af361d6585eb00d3c157a326 100644 (file)
@@ -28,3 +28,5 @@ destination file is rendered by multiple pages. Or when one page renders
 a file that is a parent directory of the rendered file of another page.
 It could warn, rather than erroring. The last page rendered would "win";
 generating the destdir file.
+
+[[done]]