r97: Fixed problem of "failed write" when the output is empty by design.
authorDamir Dzeko <Damir.Dzeko@CARNet.hr>
Wed, 8 Mar 2006 05:41:08 +0000 (05:41 +0000)
committerDamir Dzeko <Damir.Dzeko@CARNet.hr>
Wed, 8 Mar 2006 05:41:08 +0000 (05:41 +0000)
changelog.CARNet
cp-update
test/Makefile
test/test9.ok [new file with mode: 0644]
test/test9.start [new file with mode: 0644]

index 1b83c38..f783254 100644 (file)
@@ -1,3 +1,11 @@
+carnet-tools-cn (2.5.2) sarge; urgency=low
+
+  * cp-update: ispravljen propust u sigurnosnoj provjeri prilikom 
+      generiranja prazne datoteke nakon brisanja bloka koji je 
+      predstavljao jedini sadrzaj datoteke
+
+  -- Damir Dzeko <ddzeko@srce.hr>  Tue, 07 Mar 2006 22:35:37 +0100
+
 carnet-tools-cn (2.5.1) sarge; urgency=low
 
   * Ignoriranje visestrukih default route.
index f4d66be..00ad0d9 100755 (executable)
--- a/cp-update
+++ b/cp-update
@@ -109,7 +109,7 @@ $UsageShort .= " or type  $ProgramName --help  to be choked with help.\n";
 my ($MarkBegin, $MarkEnd, $Trailer, $ParamBegin, $ParamEnd, $Placement,
     $Package, $File, $Block, $Multi, $InsertRemove, $Comment, $CommentEnd,
     $MatchLine, $RegexpMatch, $StdinContent, $NewContent, $InPlace,
-    $NoClose, $FileHandle, @Lines);
+    $NoClose, $FileHandle, @Lines, $LinesCount);
 
 # Placement modes
 use constant APPEND_AT_END => 0;
@@ -251,7 +251,7 @@ do_it() and exit(0);
 # --------------
 
 sub do_it {
-  slurp();
+  $LinesCount = slurp();
   if (DO_CHANGE == $InsertRemove) {
     $StdinContent = &stdin_content;
     change() or add();
@@ -278,10 +278,11 @@ sub slurp() {
 
   # If FILE does not have a trailing newline, be sure to add it
   # before appending anything else.
-
   if (@Lines and $Lines[$#Lines] !~ m/\n$/s) {
     $Lines[$#Lines] .= "\n";
   }
+  
+  return scalar @Lines;
 }
 
 sub add() {
@@ -321,7 +322,9 @@ sub add() {
       push(@Lines, $StdinContent);
     }
   }
-  return scalar(@Lines); # whatever
+  # add the number of lines in added content to safety counter
+  $LinesCount += ($StdinContent =~ tr/\n//);
+  return $LinesCount; # whatever true
 }
 
 sub del() {
@@ -337,9 +340,12 @@ sub del() {
 
   my (@filtered);
   foreach (@Lines) {
-    push (@filtered, $_)
-      unless (/^$mybegin(?:$mytrailer)?$/o .. /^$myend(?:$mytrailer)?$/o);
-      
+    if (/^$mybegin(?:$mytrailer)?$/o .. /^$myend(?:$mytrailer)?$/o) {
+      # additional safety counter for double-check
+      -- $LinesCount;
+    } else {
+      push (@filtered, $_);
+    }
     # for safety check:
     $bm_found = 1 if (/^$mybegin(?:$mytrailer)?$/o);
     $em_found = 1 if (/^$myend(?:$mytrailer)?$/o);
@@ -352,7 +358,7 @@ sub del() {
     # safety exit    
     die "$ProgramName: no end-mark after begin-mark!\n";
   }
-  return scalar(@Lines); # whatever
+  return $LinesCount; # whatever
 }
 
 sub change() {
@@ -371,6 +377,7 @@ sub change() {
   $skip = 0; # skip original block
   foreach (@Lines) {
     if (! $done and $skip > 0) {
+      -- $LinesCount;
       if (/^$myend(?:$mytrailer)?$/o) {
         ++ $done; # skipped all that was to skip
       } else {
@@ -379,6 +386,7 @@ sub change() {
     }
     elsif (0 == $skip and $_ =~ /^$mybegin(?:$mytrailer)?$/o) {
       push (@filtered, $StdinContent);
+      $LinesCount += ($StdinContent =~ tr/\n//);
       $skip = 1;
     }
     else {
@@ -407,7 +415,7 @@ sub actualize() {
   # put it all thogether
   my $newContent = join('', @Lines);
 
-  unless (length($newContent)) {
+  unless (length($newContent) or 0 == $LinesCount) {
     # safety exit in last second :)
     die "$ProgramName: New content empty -- aborting file alteration!\n";
   }
@@ -430,10 +438,13 @@ sub actualize() {
       sysseek(*$FileHandle, 0, SEEK_SET)
        or die "$ProgramName: Failed to seek to the begining of file ($!)\n";
     }
-    my $wb = syswrite($FileHandle, $newContent);
-    if (! $wb or length($newContent) != $wb) {
-      # FIXME: try restoring backup copy
-      die "$ProgramName: Failed to write the content to '$File' ($!)\n";
+    if (length($newContent)) {
+      my $wb = syswrite($FileHandle, $newContent);
+      if (! $wb or length($newContent) != $wb) {
+        # FIXME: try restoring backup copy
+        my $ncl = length($newContent);
+        die "$ProgramName: Failed to write the content to '$File' (wb=$wb, len=$ncl, err:$!)\n";
+      }
     }
     if ($NoClose) {
       # this could be handy for files that had stuff appended
@@ -450,10 +461,13 @@ sub actualize() {
     # write content in new file in single write op
     sysopen ($FileHandle, $file_new, O_CREAT|O_TRUNC|O_WRONLY)
       or die "$ProgramName: Failed to open file '$File' for writing ($!)\n";
-    my $wb = syswrite($FileHandle, $newContent);
-    if (! $wb or length($newContent) != $wb) {
-      unlink($file_new);
-      die "$ProgramName: Failed to write the content to '$File' ($!)\n";
+    if (length($newContent)) {
+      my $wb = syswrite($FileHandle, $newContent);
+      if (! $wb or length($newContent) != $wb) {
+        unlink($file_new);
+        my ($ncl) = length($newContent);
+        die "$ProgramName: Failed to write the content to '$File' (wb=$wb, len=$ncl, err:$!)\n";
+      }
     }
     close($FileHandle);
     # do the moving (should be atomic)
index e0117a8..339768e 100644 (file)
@@ -6,12 +6,12 @@
 # path to cp-update script
 CPUPDATE=../cp-update
 
-tests: test0 test1 test2 test3 test4 test5 test6 test7 test8
+tests: test0 test1 test2 test3 test4 test5 test6 test7 test8 test9
        @echo "All tests completed successfully"
        @cp test-file.start test-file
        
 clean: test0 test-file.start
-       rm -f test[0-9] test[0-9][a-zA-Z0-9] test-file.[0-9]*
+       rm -f test[0-9] test[0-9][a-zA-Z0-9] test-file.[0-9]* test[0-9].tmp
 
 # prepare everything for test sequence
 test0: test-file.start
@@ -99,6 +99,13 @@ test8: test1 test2 test3 test4 test5 test6
        cp test-file $@
        echo Succeeded $@
 
+# remove single last block to leave the file empty
+test9: test9.start
+       cp test9.start test9.tmp
+       $(CPUPDATE) -r test9 test9.tmp
+       cmp test9.tmp test9.ok
+       echo Succeeded $@
+
 # more tests needed
 # --insert-before
 # --begin/end marks
diff --git a/test/test9.ok b/test/test9.ok
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/test9.start b/test/test9.start
new file mode 100644 (file)
index 0000000..41f49af
--- /dev/null
@@ -0,0 +1,3 @@
+# Begin update by CARNet package test9 -- DO NOT DELETE THIS LINE!
+Block inserted by test9
+# End update by CARNet package test9 -- DO NOT DELETE THIS LINE!