in reply to Re: Self Deletion
in thread Self Deletion

I recall being surprised when I found out that vi was writing a new file with the same name rather than overwriting the existing contents of the file. But testing today shows vi overwriting existing contents. I think this may have changed when truncate became a standard function (or my memory may just be confused, especially since I did a lot of VMS before that).

I'd be very surprised if any of these were false:

But this all got me curious.

I checked Bleach.pm and find that it does overwrite the existing script contents (which is what I expected). Perl having the script file open doesn't prevent this from happening.

Win32 is one of the few places where just having the script open would prevent you from deleting it. This makes it convenient for testing this. For example, this script: unlink($0) or warn $!,$/,$^E,$/; successfully deletes itself under Win32 while these two:

unlink($0) or warn $!,$/,$^E,$/; __END__
and BEGIN { unlink($0) or warn $!,$/,$^E,$/ } both fail with
Permission denied The process cannot access the file because it is being used by another + process
So note that your own process can qualify as "another process" as far as this error is concerned. It really should say "via another file handle".

So Perl has the script open while it is parsing it but closes it after that unless you have a __DATA__ or __END__ token. So updating the script while it is running would only cause a problem if you did it while the script was still being parsed or if the script had __DATA__/__END__.

So the script should also be able to delete itself (unless if has __END__/__DATA__ and you haven't closed DATA yet) even under Win32. However, the script probably won't be able to delete the directory that it is in under Win32. If any process is currently chdired to a directory, then you aren't allowed to delete that directory under Win32. (Under Unix, you should be able to delete the script and the directory no matter who has them open.) So you might have to chdir("..") under Win32 and even that might not be enough.

Then again, under Win32 you can also use Win32API::File to request that files/directories that are currently in use be deleted during the next reboot.

Finally, the reason that you can't delete the Perl script while Perl still has it open is because the C run-time library under Win32 defaults to specifying sharing of "rw" and not "rwd". I wish they had opted for "rwd", but my time machine is still broken.

When you open a file in Win32, you specify what type of sharing you would like. Many Win32 programs that don't use the C run-time library's I/O layer specify 0 for the sharing (probably as much because they didn't bother to think about what type of sharing they should be allowing as for any logical reason) so that you can't even look at the file contents while the programming is running. This sucks.

But that is plenty of rambling for now...

        - tye (but my friends call me "Tye")

Replies are listed 'Best First'.
Re: (tye)Re: Self Deletion
by John M. Dlugosz (Monsignor) on Jul 08, 2001 at 09:55 UTC
    I checked Bleach.pm and find that it does overwrite the existing script contents (which is what I expected). Perl having the script file open doesn't prevent this from happening.
    You mean opening $0 for writing will overwrite the existing file's contents, and although Perl may still have it open, the way it was opened doesn't prevent it from being opened for writing (at least by the same process or same security context). I suppose that the normal ">" mode of Perl truncates the file to zero length.

    But, in Win32, the deleting of a file is prohibited if it's open at all, regardless of what sharing modes are specified.

    In my experience of saving changes to a PM while it was still running, when the editor saves by writing to a temp file first, then if successful deleting the old and renaming the new, would fail if __DATA__ was being used. The fact that it may close or leave open, depending, explains differing observations on the subject. I thank you for sheding light on this.

    So you might have to chdir("..") under Win32 and even that might not be enough.
    It should be enough, unless spawned tasks are still using it. It's enough for that script.

    Then again, under Win32 you can also use Win32API::File to request that files/directories that are currently in use be deleted during the next reboot.
    The mechanism is totally different for NT/2000 than it is for Win 3.1/95/98/ME. The function in Win32API::File is only present on the former.
    Finally, the reason that you can't delete the Perl script while Perl still has it open is because the C run-time library under Win32 defaults to specifying sharing of "rw" and not "rwd". I wish they had opted for "rwd", but my time machine is still broken.
    Are you sure that's possible on Win32? If it's just a matter of the defaults passed to the underlying functions, you could change the Perl source.

    —John

      You mean opening $0 for writing will overwrite the existing file's contents, and although Perl may still have it open, the way it was opened doesn't prevent it from being opened for writing (at least by the same process or same security context).

      Yes. And, no, some other process in a different security context could do exactly the same thing unless you went out of your way to prevent it.

      But, in Win32, the deleting of a file is prohibited if it's open at all, regardless of what sharing modes are specified.

      No, the C RTL opens files in such a way that no one (not even you) is allowed to delete them until you close them. You can easily open files such that they can be deleted but you have to not use C's fopen() if you want that.

      It should be enough, unless spawned tasks are still using it. It's enough for that script.

      Actually, I was thinking that if one managed to launch the script then in most cases one would have either a shell or Explorer with that directory open. But if the script (or the automated process that launched the script) was also what created the directory, then you have better odds.

      The mechanism is totally different for NT/2000 than it is for Win 3.1/95/98/ME. The function in Win32API::File is only present on the former.

      True. Thanks, I'd forgotten that.

      Are you sure [deleting an open file(?) is] possible on Win32? If it's just a matter of the defaults passed to the underlying functions, you could change the Perl source.

      Yes, I'm sure. See Win32API::File for more on how. You have to modify Win32 Perl to not use the C RTL's fopen(). Win32 Perl already replaces several bits of the C RTL with its own (because of bugs in common C RTLs) so it could roll its own fopen() as well in order to "fix" this. Hmm...

      I just noticed that Win32 Perl's implementation of utime() won't work on a file if anyone has it open for writing (perhaps there would be no point?). It looks like Win32 Perl's stat won't work reliably on files that are currently opened by anyone. I blame these problems on Microsoft making you type FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE in order to be sharing but only 0 in order to be stingy.

              - tye (but my friends call me "Tye")
Re: (tye)Re: Self Deletion
by John M. Dlugosz (Monsignor) on Jul 22, 2001 at 07:49 UTC
    According to perldata,
    For compatibility with older scripts written before __DATA__ was introduced, __END__ behaves like __DATA__ in the toplevel script (but not in files loaded with require or do) and leaves the remaining contents of the file accessible via main::DATA.
    So, I wonder if an __END__ in a .pm file will not have the unwanted side effect of holding that file open, like it does in the main file. This is good news for those who want to continue putting the pod at the end.

    —John