Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Self Deletion

by Anonymous Monk
on Jul 07, 2001 at 08:29 UTC ( [id://94690]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to create a script that will identify its location and remove the entire directory containing it. This would also include its contents and the script that created the deletion process. This would be on a linux box. Any ideas on how i would create a script that can produce a process to delete itself?

Replies are listed 'Best First'.
Re: Self Deletion
by andreychek (Parson) on Jul 07, 2001 at 08:46 UTC
    I have to admit -- I've never tried this particular task before, but I found it most amusing to build. Perhaps it was the danger that if I did it incorrectly I'd end up without my home directory or something like that :-)

    However, I'm happy to announce that this code is tested, it does work, and I'll describe what it does so you know what you're getting yourself into :-)

    #!/usr/bin/perl -w use File::Path; use File::Basename; # This extracts the path of the current directory into # the variable $dirname my $dirname = dirname($0); # The following line (beginning with the word "rmtree") is # commented for safety purposes. It WILL delete the # contents of the directory the script is in, and all it's # subdirs. I did test it, but please do not take my word # for it! Try it in your temp dir before putting this in # with your live data. # Uncommenting this line will cause files to be deleted! # rmtree([$dirname], 1, 1); print "This is a drill. If this were not a drill, the dir '$dirname', + and all of it's contents and subdirectories would be toast right now +.";
    Update: Code has been removed until the original posted states why they want it.. while there are many legitimate reasons for this, there are also plenty of malicious ones.

    Update 2: The original poster has posted a very legitimate reason for requiring this functionality. So without further ado, I have re-posted this code. I appologize for the delay, but unfortunatly not everyone is honest these days. Good luck!
    -Eric
      I believe, although I might be wrong, that this is for the purposes of developing an uninstaller, which has the inevitable consequence of deleting files including itself.

      This wasn't a suspicious request like:
      calculating criticle mass
      im trying calculate the critical mass of u235, does anyone have any sample code? Oh, does anyone know a quick way to compute yield? thanks!
      Just as knives could be used to hurt people, they are most often used for cooking or other peaceful and productive purposes.
        like andreychek said, there is no information as to what the intent is. Virus code was removed recently because it had the potential to become something that nobody wanted to be responsibl for. I don't think that most uninstallers go along deleting every file in a directory blindly, including itself. Why would you want to delete the uninstaller other then to rid the computer of the evidence as to what casued the deletion of the files. It looks a little suspecious to me. I'd like to see some reasoing behind the question, at least then some of the monks may be able to suggest a better way to do it. If it is for a ligit reason, the AM will have no problem following up and posting why they want to do this. It all comes down to the morality of posting potentially dangerous code on PM's.

        Stuffy
        That's my story, and I'm sticking to it, unless I'm wrong in which case I will probably change it ;~)
        may be reproduced under the SDL
      I am sorry I should have been more clean on the onset. I am using the script to put in directories of a very complex and automated classified lisitng system so that the listing will "delete itself" after a secified duration. This way i can have wierd and unique add durations such as 7.39 days or 60.33 minutes and so on.
Re: Self Deletion
by clintp (Curate) on Jul 07, 2001 at 17:50 UTC
    Just so you know, this is a very unportable Unix behavior. Under AIX 3 (poss. 4) and under HPUX you can't delete a file that's being exec'd -- whether it's a loadable object file or a script.

    I wrote a user-space filesystem caching program for Ford Motor, and one of the problems was trying to delete (cache out) a file in use. The support scripts for the caching program often had to be removed and couldn't.

    The error returned by unlink is ETXTBUSY. A workaround is to detect ETXTBUSY on unlink, and move the file up a directory in the tree with link, and then delete the original with unlink. The i-node isn't removed (and this makes the OS happy) but the directory is emptied (and this makes the programmer happy).

      You can rm running executables on AIX 4 (AIX 3 is really old). You just can't cp over them or recompile over them. A common thing to do in AIX Makefiles is to rm them first before recompiling.

      FWIW, unlinking a running executable is usually only a problem when it resides on an NFS server, since in that case the code really does go away immediately (leading to interesting results). So I imagine this is pretty much the same on HPUX since it is really just a way to keep someone from hurting themselves, but not an absolute necessity. Of course I'm probably mistaken...

      bluto

        You can rm running executables on AIX 4 (AIX 3 is really old). You just can't cp over them or recompile over them. A common thing to do in AIX Makefiles is to rm them first before recompiling.

        It's not just AIX, it's most unices. When a program is run, part of the program is mmap'd so copying over the file would corrupt the program's memory (whereas deleting the file would not, due to the way unix handles open files with a 0 link count).
Re: Self Deletion
by cLive ;-) (Prior) on Jul 07, 2001 at 13:41 UTC
    Let's assume you're on *nix, and let's assume you have <HTTP://www.unixtools.org/cgiwrap">cgiwrap installed (so you have the correct permission - if not, the script is chmoded 777 :).

    Then:

    $ENV{'SCRIPT_NAME'} =~ m|(.*)/|; my $dir = "$path_to_web_root/".$1; system('rm','-rf',$dir);
    should do the trick*

    cLive ;-)

    PS -for some reason, I'm assuming it's a CGI script.

    *I am reasonably drunk, so if I'm wrong, take it with a pinch of salt...

Re: Self Deletion
by John M. Dlugosz (Monsignor) on Jul 07, 2001 at 21:33 UTC
    In my experience, the perl script file is not held open once it is executing. I've saved a changed file without error while a script was running. Modules that modify itself, like the pony thing or bleach, rely on being able to rewrite the current file, so I'm sure it's not just an NT implementation thing. Those wierd modules operate inside a use, which means the file must be closed before parsing starts, rather than read and parsed a line at a time.

      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:

      • Perl leaves the file open until it is done parsing
      • Perl leaves the file open for the duration of the run if there is a __END__ or __DATA__ token in it
      • ACME::Bleach works even if your script has an __END__ or __DATA__ token
      • Therefore, ACME::Bleach doesn't rely on Perl having closed the script before it modifies it

      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")
        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

        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

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://94690]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2024-04-24 02:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found