From 794b05eb76c5fa0ae149bf69a35b8ead99b8fd30 Mon Sep 17 00:00:00 2001 From: Damir Dzeko Date: Wed, 8 Mar 2006 05:41:08 +0000 Subject: [PATCH] r97: Fixed problem of "failed write" when the output is empty by design. --- changelog.CARNet | 8 ++++++++ cp-update | 48 +++++++++++++++++++++++++++++++----------------- test/Makefile | 11 +++++++++-- test/test9.start | 3 +++ 4 files changed, 51 insertions(+), 19 deletions(-) create mode 100644 test/test9.ok create mode 100644 test/test9.start diff --git a/changelog.CARNet b/changelog.CARNet index 1b83c38..f783254 100644 --- a/changelog.CARNet +++ b/changelog.CARNet @@ -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 Tue, 07 Mar 2006 22:35:37 +0100 + carnet-tools-cn (2.5.1) sarge; urgency=low * Ignoriranje visestrukih default route. diff --git a/cp-update b/cp-update index f4d66be..00ad0d9 100755 --- 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) diff --git a/test/Makefile b/test/Makefile index e0117a8..339768e 100644 --- a/test/Makefile +++ b/test/Makefile @@ -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 index 0000000..e69de29 diff --git a/test/test9.start b/test/test9.start new file mode 100644 index 0000000..41f49af --- /dev/null +++ b/test/test9.start @@ -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! -- 1.7.10.4