http://www.perlmonks.org?node_id=367806


in reply to Re: A DWIM too far?
in thread A DWIM too far?

I'm not sure which I find the most bizarre

  1. That the silently destructive behaviour was ever adopted in the first place.
  2. That such a (IMO) flawed behaviour should have been perpectuated.
  3. Or the outpouring of support for it.

As is, the behaviour makes it impossible to safely rename a file.

You can test existance before issuing the rename, but in any multi-tasking environment there is always the possibility that the target file will be created between the test for existance and the rename. This renders the the often hard won (and IMO, sacrosanct) atomicity of the OS rename API useless.

This rates up there with non-exlusive-opens-by-default and cooperative locking as remnant bahaviours of a bygone era that should have been superceded long ago.


Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
"Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon

Replies are listed 'Best First'.
Re: A DWIM too far?
by Abigail-II (Bishop) on Jun 19, 2004 at 05:07 UTC
    As is, the behaviour makes it impossible to safely rename a file.

    That depends on your definition of "safely". The other possible default (not renaming if the target file exists), also prevents "safely" renaming a file. Because that will prevent the to-be-renamed file to be renamed. So that's also "unsafe".

    You should also consider what should happen in the following situation:

    $ touch file $ ln -s target link $ rename file link
    Rename or not?

    Note that if you want to do a "safe" rename, you can do so, although it involves a copy:

    my ($f1, $f2); if (sysopen $f1, "new", O_WRONLY | O_CREAT | O_EXCL) { open $f2 => "old" or die; print $f1 <$fh2>; close $f1 or die; unlink "old" or die; }
    You can test existance before issuing the rename, but in any multi-tasking environment there is always the possibility that the target file will be created between the test for existance and the rename.
    Frankly, I don't get your point. What are you trying to say here? That the rename is making you lose data? That I disagree with. Suppose you are multi-tasking, one threads wants to create a file "new", and another thread wants to move "old" to "new", but you want to end up with both the data that is in "old", and with the data that would be placed in "new" by the other thread. Suppose you would have a 'rename' that doesn't rename if there is already a "new" file. Does that win you anything? Not if the renaming process thread goes first. Then "old" will be renamed to "new", and then wiped out by the other thread that's creating "new". Rename is not to blame in this scenario - the programmer is to blame by not syncronizing two threads that modify the same resource.
    This rates up there with non-exlusive-opens-by-default and cooperative locking as remnant bahaviours of a bygone era that should have been superceded long ago.
    Well, you can always change your system calls. Oh, wait, you can't.

    Abigail

      Note that if you want to do a "safe" rename, you can do so, although it involves a copy

      I may have missed something, but I think it can be done much more easily like this:

      sub rename_i { my($src, $dest) = @_; link($src, $dest) or die "Can't link $src to $dest: $!"; unlink($src) or die "Can't unlink $src: $!"; }

      Hugo

        Well, yes, of course. And I should have know, because that's classical idiom. I'm just going to blame YAPC. 12 hours of sleep in 3 nights.

        Abigail (Conferences and Perlmonks don't mix)

        That may not work for directories.

        But I think that idiom justifies Unix's choice of rename behavior. If rename failed when a new file already exists, there isn't good way to code a rename-that-overwrites.

      Well, you can always change your system calls. Oh, wait, you can't.

      Of course I could--but I don't need to :)


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
Re^3: A DWIM too far?
by QM (Parson) on Jun 18, 2004 at 01:24 UTC
    As is, the behaviour makes it impossible to safely rename a file.
    It makes it harder, at least:
    sub myrename { my $rename = ( $^O eq 'MSWin32' ) ? 'move -y' : 'mv -i'; `$rename @_[0,1]`; return $!; } myrename('abc','def') or die $!;
    I can't recall how to do this to the CORE, perhaps someone will remind me?

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of

      It seems you answered the wrong question. The problem is that you can't be sure to not overwrite a file by renaming it. Your rename subroutine does quite the opposite. Or have I completely misunderstood your reply?
        I think you misunderstood (at least, I hope I've understood :)

        Rewriting rename to include the -i option (or -y option for Windoze) will not clobber an existing file (unless the underlying OS function has the same problem with the -i option, in which case we're all screwed.)

        I tried my example out, and it seemed to work as I intended. I'm sure someone has come up with a more robust and useful version. I was just trying to show that it was possible.

        -QM
        --
        Quantum Mechanics: The dreams stuff is made of

      *GLOBAL::CORE::rename = \&myrename;

      Update: The above is wrong! It should be

      *CORE::GLOBAL::rename = \&myrename;

      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
        Great! Is it possible to say
        sub *GLOBAL::CORE::rename {...}
        directly? Or is it a two step process?

        -QM
        --
        Quantum Mechanics: The dreams stuff is made of

Re^3: A DWIM too far?
by revdiablo (Prior) on Jun 18, 2004 at 02:48 UTC

    Here's something else you might find bizarre. There's a programming language many people greatly enjoy using that has very little stricture by default, lots of similar but slightly different ways to do the same thing, an object system that lets you use whatever type of datastructure you damn well please, and generally encourages a culture of "stay out of my living room because I ask, not because I have a shotgun." Perhaps you find it bizarre, but I find it downright refreshing.

    I feel the same way about cooperative locking, non-exclusive opens, and -- to a far lesser extent -- the overwriting rename(). Do I wish there was a reasonable way to rename without clobbering-by-default? Yes, I do. That doesn't make me like the current behavior any less. Personally, I like a platform that lets me do what I want, even if what I want might be shooting myself in the foot. If this mentality is so strange to you, I wonder how exactly you've managed to stick with Perl as long as you have.

      There is a difference.

      Most of those permissive behaviours that you describe,and which I mostly relish, are controlled entirely within the auspices of my program!

      The destructive behaviour of rename means that I may well be destroying someone else's data, or someone else accidentally or deliberatly destroying mine.

      I consider that a fundemental distinction.


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon

        It doesn't seem like such a fundamental difference to me. Modifying the wrong hash element in an inhereted object can cause data loss. Changing a global sub (such as you do here) can cause serious problems if not done with care. All the behaviors "within the auspices of [your] program" are not necessarily as limited as you seem to imply. And besides, all the behaviors of an operating system are controlled entirely within the auspices of one computer.

        The difference I see is not fundamental, it is one of likelihood. The chances of problems caused by permissive behavior are less at the application level than the operating system level, but they are still there. As I said before, I like a platform that is as permissive as possible, and that goes for programming langauges as well as operating systems. After all, what is an operating system but another programming platform?