That doesn't look like a great way to choose a backup filename - the rename will succeed even for candidate backup filenames that exist (permissions permitting), so the backup has potentially just clobbered another file! (Or have I misunderstood you?)

Anyway, as I said, the backup filename is supplied by the caller of this code if a backup file is required. My real concern is what the best way to achieve the in-place edit via a temporary file is, possibly taking advantage of the given backup filename if one is given.

I like the idea of writing the processed data to a temporary file and then moving that back (either (1) by a rename or (2) by copying the contents), rather than my original idea of moving/copying the file to be edited and then writing the processed data back to it, so that the process can be easily re-run if it failed the first time.

However, both options (1) and (2) above have problems:

Option (1) goes something like this (return values obviously need checking, and there are some chmod games that can be played too, but this is the bare bones of it):

use File::Temp qw(tempfile); my $file = 'test.txt'; my($tmpfh, $tmpfile) = tempfile(); open my $fh, '<', $file; binmode $fh; while (<$fh>) { # Process $_ here print $tmpfh $_; } close $fh; close $tmpfh; rename $tmpfile, $file;

I can see two problems with that. Firstly, tempfile() was not called in scalar context so the temporary file will not be cleaned up if the program is interrupted or killed. (A $SIG{INT} handler could arrange for them to be cleaned up if interrupted, but not if the program is killed.) Secondly, while the rename itself is (normally) atomic, there is a race condition between the close and the rename - somebody else could potentially modify the file inbetween.

Option (2) looks like this (with the same caveats as before):

use Fcntl qw(:seek); use File::Temp qw(tempfile); my $file = 'test.txt'; my $tmpfh = tempfile(); open my $fh, '<', $file; binmode $fh; while (<$fh>) { # Process $_ here print $tmpfh $_; } close $fh; seek $tmpfh, 0, SEEK_SET; open my $fh2, '>', $file; binmode $fh2; print $fh2 $_ while <$tmpfh>; close $fh2; close $tmpfh;

This time, the temporary file's contents are written back to the original file without the temporary file having been closed, so there is no close/rename race condition. Also, tempfile() was called in scalar context so the temporary file will be cleaned up even if the program is killed (on Win32, at least, via the O_TEMPORARY flag that is used when opening the file). However, the process of copying the temporary file's contents back to the original file is no longer atomic, so if the program is interrupted during the final while loop then the original file will be left partially written.

So neither option is perfect. Which is approach is the lesser of the two evils? Is there another approach with none of these pitfalls?


In reply to Re^4: Copying a file to a temporary file by shay
in thread Copying a file to a temporary file by shay

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.