xref: /openbsd-src/gnu/usr.bin/perl/cpan/ExtUtils-Install/lib/ExtUtils/Install.pm (revision 2e109fb9e8c0dc273648ddbc62f0a74abf9e098d)
1package ExtUtils::Install;
2use strict;
3
4use vars qw(@ISA @EXPORT $VERSION $MUST_REBOOT %Config);
5
6use AutoSplit;
7use Carp ();
8use Config qw(%Config);
9use Cwd qw(cwd);
10use Exporter;
11use ExtUtils::Packlist;
12use File::Basename qw(dirname);
13use File::Compare qw(compare);
14use File::Copy;
15use File::Find qw(find);
16use File::Path;
17use File::Spec;
18
19
20@ISA = ('Exporter');
21@EXPORT = ('install','uninstall','pm_to_blib', 'install_default');
22
23=pod
24
25=head1 NAME
26
27ExtUtils::Install - install files from here to there
28
29=head1 SYNOPSIS
30
31  use ExtUtils::Install;
32
33  install({ 'blib/lib' => 'some/install/dir' } );
34
35  uninstall($packlist);
36
37  pm_to_blib({ 'lib/Foo/Bar.pm' => 'blib/lib/Foo/Bar.pm' });
38
39=head1 VERSION
40
412.04
42
43=cut
44
45$VERSION = '2.04';  # <-- do not forget to update the POD section just above this line!
46$VERSION = eval $VERSION;
47
48=pod
49
50=head1 DESCRIPTION
51
52Handles the installing and uninstalling of perl modules, scripts, man
53pages, etc...
54
55Both install() and uninstall() are specific to the way
56ExtUtils::MakeMaker handles the installation and deinstallation of
57perl modules. They are not designed as general purpose tools.
58
59On some operating systems such as Win32 installation may not be possible
60until after a reboot has occurred. This can have varying consequences:
61removing an old DLL does not impact programs using the new one, but if
62a new DLL cannot be installed properly until reboot then anything
63depending on it must wait. The package variable
64
65  $ExtUtils::Install::MUST_REBOOT
66
67is used to store this status.
68
69If this variable is true then such an operation has occurred and
70anything depending on this module cannot proceed until a reboot
71has occurred.
72
73If this value is defined but false then such an operation has
74ocurred, but should not impact later operations.
75
76=over
77
78=begin _private
79
80=item _chmod($$;$)
81
82Wrapper to chmod() for debugging and error trapping.
83
84=item _warnonce(@)
85
86Warns about something only once.
87
88=item _choke(@)
89
90Dies with a special message.
91
92=back
93
94=end _private
95
96=cut
97
98my $Is_VMS     = $^O eq 'VMS';
99my $Is_MacPerl = $^O eq 'MacOS';
100my $Is_Win32   = $^O eq 'MSWin32';
101my $Is_cygwin  = $^O eq 'cygwin';
102my $CanMoveAtBoot = ($Is_Win32 || $Is_cygwin);
103my $Perm_Dir = $ENV{PERL_CORE} ? 0770 : 0755;
104
105# *note* CanMoveAtBoot is only incidentally the same condition as below
106# this needs not hold true in the future.
107my $Has_Win32API_File = ($Is_Win32 || $Is_cygwin)
108    ? (eval {require Win32API::File; 1} || 0)
109    : 0;
110
111
112my $Inc_uninstall_warn_handler;
113
114# install relative to here
115
116my $INSTALL_ROOT = $ENV{PERL_INSTALL_ROOT};
117my $INSTALL_QUIET = $ENV{PERL_INSTALL_QUIET};
118
119my $Curdir = File::Spec->curdir;
120my $Updir  = File::Spec->updir;
121
122sub _estr(@) {
123    return join "\n",'!' x 72,@_,'!' x 72,'';
124}
125
126{my %warned;
127sub _warnonce(@) {
128    my $first=shift;
129    my $msg=_estr "WARNING: $first",@_;
130    warn $msg unless $warned{$msg}++;
131}}
132
133sub _choke(@) {
134    my $first=shift;
135    my $msg=_estr "ERROR: $first",@_;
136    Carp::croak($msg);
137}
138
139
140sub _chmod($$;$) {
141    my ( $mode, $item, $verbose )=@_;
142    $verbose ||= 0;
143    if (chmod $mode, $item) {
144        printf "chmod(0%o, %s)\n",$mode, $item if $verbose > 1;
145    } else {
146        my $err="$!";
147        _warnonce sprintf "WARNING: Failed chmod(0%o, %s): %s\n",
148                  $mode, $item, $err
149            if -e $item;
150    }
151}
152
153=begin _private
154
155=over
156
157=item _move_file_at_boot( $file, $target, $moan  )
158
159OS-Specific, Win32/Cygwin
160
161Schedules a file to be moved/renamed/deleted at next boot.
162$file should be a filespec of an existing file
163$target should be a ref to an array if the file is to be deleted
164otherwise it should be a filespec for a rename. If the file is existing
165it will be replaced.
166
167Sets $MUST_REBOOT to 0 to indicate a deletion operation has occurred
168and sets it to 1 to indicate that a move operation has been requested.
169
170returns 1 on success, on failure if $moan is false errors are fatal.
171If $moan is true then returns 0 on error and warns instead of dies.
172
173=end _private
174
175=cut
176
177
178
179sub _move_file_at_boot { #XXX OS-SPECIFIC
180    my ( $file, $target, $moan  )= @_;
181    Carp::confess("Panic: Can't _move_file_at_boot on this platform!")
182         unless $CanMoveAtBoot;
183
184    my $descr= ref $target
185                ? "'$file' for deletion"
186                : "'$file' for installation as '$target'";
187
188    if ( ! $Has_Win32API_File ) {
189
190        my @msg=(
191            "Cannot schedule $descr at reboot.",
192            "Try installing Win32API::File to allow operations on locked files",
193            "to be scheduled during reboot. Or try to perform the operation by",
194            "hand yourself. (You may need to close other perl processes first)"
195        );
196        if ( $moan ) { _warnonce(@msg) } else { _choke(@msg) }
197        return 0;
198    }
199    my $opts= Win32API::File::MOVEFILE_DELAY_UNTIL_REBOOT();
200    $opts= $opts | Win32API::File::MOVEFILE_REPLACE_EXISTING()
201        unless ref $target;
202
203    _chmod( 0666, $file );
204    _chmod( 0666, $target ) unless ref $target;
205
206    if (Win32API::File::MoveFileEx( $file, $target, $opts )) {
207        $MUST_REBOOT ||= ref $target ? 0 : 1;
208        return 1;
209    } else {
210        my @msg=(
211            "MoveFileEx $descr at reboot failed: $^E",
212            "You may try to perform the operation by hand yourself. ",
213            "(You may need to close other perl processes first).",
214        );
215        if ( $moan ) { _warnonce(@msg) } else { _choke(@msg) }
216    }
217    return 0;
218}
219
220
221=begin _private
222
223
224=item _unlink_or_rename( $file, $tryhard, $installing )
225
226OS-Specific, Win32/Cygwin
227
228Tries to get a file out of the way by unlinking it or renaming it. On
229some OS'es (Win32 based) DLL files can end up locked such that they can
230be renamed but not deleted. Likewise sometimes a file can be locked such
231that it cant even be renamed or changed except at reboot. To handle
232these cases this routine finds a tempfile name that it can either rename
233the file out of the way or use as a proxy for the install so that the
234rename can happen later (at reboot).
235
236  $file : the file to remove.
237  $tryhard : should advanced tricks be used for deletion
238  $installing : we are not merely deleting but we want to overwrite
239
240When $tryhard is not true if the unlink fails its fatal. When $tryhard
241is true then the file is attempted to be renamed. The renamed file is
242then scheduled for deletion. If the rename fails then $installing
243governs what happens. If it is false the failure is fatal. If it is true
244then an attempt is made to schedule installation at boot using a
245temporary file to hold the new file. If this fails then a fatal error is
246thrown, if it succeeds it returns the temporary file name (which will be
247a derivative of the original in the same directory) so that the caller can
248use it to install under. In all other cases of success returns $file.
249On failure throws a fatal error.
250
251=end _private
252
253=cut
254
255
256
257sub _unlink_or_rename { #XXX OS-SPECIFIC
258    my ( $file, $tryhard, $installing )= @_;
259
260    # this chmod was originally unconditional. However, its not needed on
261    # POSIXy systems since permission to unlink a file is specified by the
262    # directory rather than the file; and in fact it screwed up hard- and
263    # symlinked files. Keep it for other platforms in case its still
264    # needed there.
265    if ($^O =~ /^(dos|os2|MSWin32|VMS)$/) {
266        _chmod( 0666, $file );
267    }
268    my $unlink_count = 0;
269    while (unlink $file) { $unlink_count++; }
270    return $file if $unlink_count > 0;
271    my $error="$!";
272
273    _choke("Cannot unlink '$file': $!")
274          unless $CanMoveAtBoot && $tryhard;
275
276    my $tmp= "AAA";
277    ++$tmp while -e "$file.$tmp";
278    $tmp= "$file.$tmp";
279
280    warn "WARNING: Unable to unlink '$file': $error\n",
281         "Going to try to rename it to '$tmp'.\n";
282
283    if ( rename $file, $tmp ) {
284        warn "Rename successful. Scheduling '$tmp'\nfor deletion at reboot.\n";
285        # when $installing we can set $moan to true.
286        # IOW, if we cant delete the renamed file at reboot its
287        # not the end of the world. The other cases are more serious
288        # and need to be fatal.
289        _move_file_at_boot( $tmp, [], $installing );
290        return $file;
291    } elsif ( $installing ) {
292        _warnonce("Rename failed: $!. Scheduling '$tmp'\nfor".
293             " installation as '$file' at reboot.\n");
294        _move_file_at_boot( $tmp, $file );
295        return $tmp;
296    } else {
297        _choke("Rename failed:$!", "Cannot proceed.");
298    }
299
300}
301
302
303=pod
304
305=back
306
307=head2 Functions
308
309=begin _private
310
311=over
312
313=item _get_install_skip
314
315Handles loading the INSTALL.SKIP file. Returns an array of patterns to use.
316
317=cut
318
319
320
321sub _get_install_skip {
322    my ( $skip, $verbose )= @_;
323    if ($ENV{EU_INSTALL_IGNORE_SKIP}) {
324        print "EU_INSTALL_IGNORE_SKIP is set, ignore skipfile settings\n"
325            if $verbose>2;
326        return [];
327    }
328    if ( ! defined $skip ) {
329        print "Looking for install skip list\n"
330            if $verbose>2;
331        for my $file ( 'INSTALL.SKIP', $ENV{EU_INSTALL_SITE_SKIPFILE} ) {
332            next unless $file;
333            print "\tChecking for $file\n"
334                if $verbose>2;
335            if (-e $file) {
336                $skip= $file;
337                last;
338            }
339        }
340    }
341    if ($skip && !ref $skip) {
342        print "Reading skip patterns from '$skip'.\n"
343            if $verbose;
344        if (open my $fh,$skip ) {
345            my @patterns;
346            while (<$fh>) {
347                chomp;
348                next if /^\s*(?:#|$)/;
349                print "\tSkip pattern: $_\n" if $verbose>3;
350                push @patterns, $_;
351            }
352            $skip= \@patterns;
353        } else {
354            warn "Can't read skip file:'$skip':$!\n";
355            $skip=[];
356        }
357    } elsif ( UNIVERSAL::isa($skip,'ARRAY') ) {
358        print "Using array for skip list\n"
359            if $verbose>2;
360    } elsif ($verbose) {
361        print "No skip list found.\n"
362            if $verbose>1;
363        $skip= [];
364    }
365    warn "Got @{[0+@$skip]} skip patterns.\n"
366        if $verbose>3;
367    return $skip
368}
369
370=pod
371
372=item _have_write_access
373
374Abstract a -w check that tries to use POSIX::access() if possible.
375
376=cut
377
378{
379    my  $has_posix;
380    sub _have_write_access {
381        my $dir=shift;
382        unless (defined $has_posix) {
383            $has_posix= (!$Is_cygwin && !$Is_Win32
384             && eval 'local $^W; require POSIX; 1') || 0;
385        }
386        if ($has_posix) {
387            return POSIX::access($dir, POSIX::W_OK());
388        } else {
389            return -w $dir;
390        }
391    }
392}
393
394=pod
395
396=item _can_write_dir(C<$dir>)
397
398Checks whether a given directory is writable, taking account
399the possibility that the directory might not exist and would have to
400be created first.
401
402Returns a list, containing: C<($writable, $determined_by, @create)>
403
404C<$writable> says whether the directory is (hypothetically) writable
405
406C<$determined_by> is the directory the status was determined from. It will be
407either the C<$dir>, or one of its parents.
408
409C<@create> is a list of directories that would probably have to be created
410to make the requested directory. It may not actually be correct on
411relative paths with C<..> in them. But for our purposes it should work ok
412
413=cut
414
415
416sub _can_write_dir {
417    my $dir=shift;
418    return
419        unless defined $dir and length $dir;
420
421    my ($vol, $dirs, $file) = File::Spec->splitpath($dir,1);
422    my @dirs = File::Spec->splitdir($dirs);
423    unshift @dirs, File::Spec->curdir
424        unless File::Spec->file_name_is_absolute($dir);
425
426    my $path='';
427    my @make;
428    while (@dirs) {
429        if ($Is_VMS) {
430            $dir = File::Spec->catdir($vol,@dirs);
431        }
432        else {
433            $dir = File::Spec->catdir(@dirs);
434            $dir = File::Spec->catpath($vol,$dir,'')
435                    if defined $vol and length $vol;
436        }
437        next if ( $dir eq $path );
438        if ( ! -e $dir ) {
439            unshift @make,$dir;
440            next;
441        }
442        if ( _have_write_access($dir) ) {
443            return 1,$dir,@make
444        } else {
445            return 0,$dir,@make
446        }
447    } continue {
448        pop @dirs;
449    }
450    return 0;
451}
452
453=pod
454
455=item _mkpath($dir,$show,$mode,$verbose,$dry_run)
456
457Wrapper around File::Path::mkpath() to handle errors.
458
459If $verbose is true and >1 then additional diagnostics will be produced, also
460this will force $show to true.
461
462If $dry_run is true then the directory will not be created but a check will be
463made to see whether it would be possible to write to the directory, or that
464it would be possible to create the directory.
465
466If $dry_run is not true dies if the directory can not be created or is not
467writable.
468
469=cut
470
471sub _mkpath {
472    my ($dir,$show,$mode,$verbose,$dry_run)=@_;
473    if ( $verbose && $verbose > 1 && ! -d $dir) {
474        $show= 1;
475        printf "mkpath(%s,%d,%#o)\n", $dir, $show, $mode;
476    }
477    if (!$dry_run) {
478        if ( ! eval { File::Path::mkpath($dir,$show,$mode); 1 } ) {
479            _choke("Can't create '$dir'","$@");
480        }
481
482    }
483    my ($can,$root,@make)=_can_write_dir($dir);
484    if (!$can) {
485        my @msg=(
486            "Can't create '$dir'",
487            $root ? "Do not have write permissions on '$root'"
488                  : "Unknown Error"
489        );
490        if ($dry_run) {
491            _warnonce @msg;
492        } else {
493            _choke @msg;
494        }
495    } elsif ($show and $dry_run) {
496        print "$_\n" for @make;
497    }
498
499}
500
501=pod
502
503=item _copy($from,$to,$verbose,$dry_run)
504
505Wrapper around File::Copy::copy to handle errors.
506
507If $verbose is true and >1 then additional diagnostics will be emitted.
508
509If $dry_run is true then the copy will not actually occur.
510
511Dies if the copy fails.
512
513=cut
514
515
516sub _copy {
517    my ( $from, $to, $verbose, $dry_run)=@_;
518    if ($verbose && $verbose>1) {
519        printf "copy(%s,%s)\n", $from, $to;
520    }
521    if (!$dry_run) {
522        File::Copy::copy($from,$to)
523            or Carp::croak( _estr "ERROR: Cannot copy '$from' to '$to': $!" );
524    }
525}
526
527=pod
528
529=item _chdir($from)
530
531Wrapper around chdir to catch errors.
532
533If not called in void context returns the cwd from before the chdir.
534
535dies on error.
536
537=cut
538
539sub _chdir {
540    my ($dir)= @_;
541    my $ret;
542    if (defined wantarray) {
543        $ret= cwd;
544    }
545    chdir $dir
546        or _choke("Couldn't chdir to '$dir': $!");
547    return $ret;
548}
549
550=pod
551
552=back
553
554=end _private
555
556=over
557
558=item B<install>
559
560    # deprecated forms
561    install(\%from_to);
562    install(\%from_to, $verbose, $dry_run, $uninstall_shadows,
563                $skip, $always_copy, \%result);
564
565    # recommended form as of 1.47
566    install([
567        from_to => \%from_to,
568        verbose => 1,
569        dry_run => 0,
570        uninstall_shadows => 1,
571        skip => undef,
572        always_copy => 1,
573        result => \%install_results,
574    ]);
575
576
577Copies each directory tree of %from_to to its corresponding value
578preserving timestamps and permissions.
579
580There are two keys with a special meaning in the hash: "read" and
581"write".  These contain packlist files.  After the copying is done,
582install() will write the list of target files to $from_to{write}. If
583$from_to{read} is given the contents of this file will be merged into
584the written file. The read and the written file may be identical, but
585on AFS it is quite likely that people are installing to a different
586directory than the one where the files later appear.
587
588If $verbose is true, will print out each file removed.  Default is
589false.  This is "make install VERBINST=1". $verbose values going
590up to 5 show increasingly more diagnostics output.
591
592If $dry_run is true it will only print what it was going to do
593without actually doing it.  Default is false.
594
595If $uninstall_shadows is true any differing versions throughout @INC
596will be uninstalled.  This is "make install UNINST=1"
597
598As of 1.37_02 install() supports the use of a list of patterns to filter out
599files that shouldn't be installed. If $skip is omitted or undefined then
600install will try to read the list from INSTALL.SKIP in the CWD. This file is
601a list of regular expressions and is just like the MANIFEST.SKIP file used
602by L<ExtUtils::Manifest>.
603
604A default site INSTALL.SKIP may be provided by setting then environment
605variable EU_INSTALL_SITE_SKIPFILE, this will only be used when there isn't a
606distribution specific INSTALL.SKIP. If the environment variable
607EU_INSTALL_IGNORE_SKIP is true then no install file filtering will be
608performed.
609
610If $skip is undefined then the skip file will be autodetected and used if it
611is found. If $skip is a reference to an array then it is assumed the array
612contains the list of patterns, if $skip is a true non reference it is
613assumed to be the filename holding the list of patterns, any other value of
614$skip is taken to mean that no install filtering should occur.
615
616B<Changes As of Version 1.47>
617
618As of version 1.47 the following additions were made to the install interface.
619Note that the new argument style and use of the %result hash is recommended.
620
621The $always_copy parameter which when true causes files to be updated
622regardless as to whether they have changed, if it is defined but false then
623copies are made only if the files have changed, if it is undefined then the
624value of the environment variable EU_INSTALL_ALWAYS_COPY is used as default.
625
626The %result hash will be populated with the various keys/subhashes reflecting
627the install. Currently these keys and their structure are:
628
629    install             => { $target    => $source },
630    install_fail        => { $target    => $source },
631    install_unchanged   => { $target    => $source },
632
633    install_filtered    => { $source    => $pattern },
634
635    uninstall           => { $uninstalled => $source },
636    uninstall_fail      => { $uninstalled => $source },
637
638where C<$source> is the filespec of the file being installed. C<$target> is where
639it is being installed to, and C<$uninstalled> is any shadow file that is in C<@INC>
640or C<$ENV{PERL5LIB}> or other standard locations, and C<$pattern> is the pattern that
641caused a source file to be skipped. In future more keys will be added, such as to
642show created directories, however this requires changes in other modules and must
643therefore wait.
644
645These keys will be populated before any exceptions are thrown should there be an
646error.
647
648Note that all updates of the %result are additive, the hash will not be
649cleared before use, thus allowing status results of many installs to be easily
650aggregated.
651
652B<NEW ARGUMENT STYLE>
653
654If there is only one argument and it is a reference to an array then
655the array is assumed to contain a list of key-value pairs specifying
656the options. In this case the option "from_to" is mandatory. This style
657means that you do not have to supply a cryptic list of arguments and can
658use a self documenting argument list that is easier to understand.
659
660This is now the recommended interface to install().
661
662B<RETURN>
663
664If all actions were successful install will return a hashref of the results
665as described above for the $result parameter. If any action is a failure
666then install will die, therefore it is recommended to pass in the $result
667parameter instead of using the return value. If the result parameter is
668provided then the returned hashref will be the passed in hashref.
669
670=cut
671
672sub install { #XXX OS-SPECIFIC
673    my($from_to,$verbose,$dry_run,$uninstall_shadows,$skip,$always_copy,$result) = @_;
674    if (@_==1 and eval { 1+@$from_to }) {
675        my %opts        = @$from_to;
676        $from_to        = $opts{from_to}
677                            or Carp::confess("from_to is a mandatory parameter");
678        $verbose        = $opts{verbose};
679        $dry_run        = $opts{dry_run};
680        $uninstall_shadows  = $opts{uninstall_shadows};
681        $skip           = $opts{skip};
682        $always_copy    = $opts{always_copy};
683        $result         = $opts{result};
684    }
685
686    $result ||= {};
687    $verbose ||= 0;
688    $dry_run  ||= 0;
689
690    $skip= _get_install_skip($skip,$verbose);
691    $always_copy =  $ENV{EU_INSTALL_ALWAYS_COPY}
692                 || $ENV{EU_ALWAYS_COPY}
693                 || 0
694        unless defined $always_copy;
695
696    my(%from_to) = %$from_to;
697    my(%pack, $dir, %warned);
698    my($packlist) = ExtUtils::Packlist->new();
699
700    local(*DIR);
701    for (qw/read write/) {
702        $pack{$_}=$from_to{$_};
703        delete $from_to{$_};
704    }
705    my $tmpfile = install_rooted_file($pack{"read"});
706    $packlist->read($tmpfile) if (-f $tmpfile);
707    my $cwd = cwd();
708    my @found_files;
709    my %check_dirs;
710
711    MOD_INSTALL: foreach my $source (sort keys %from_to) {
712        #copy the tree to the target directory without altering
713        #timestamp and permission and remember for the .packlist
714        #file. The packlist file contains the absolute paths of the
715        #install locations. AFS users may call this a bug. We'll have
716        #to reconsider how to add the means to satisfy AFS users also.
717
718        #October 1997: we want to install .pm files into archlib if
719        #there are any files in arch. So we depend on having ./blib/arch
720        #hardcoded here.
721
722        my $targetroot = install_rooted_dir($from_to{$source});
723
724        my $blib_lib  = File::Spec->catdir('blib', 'lib');
725        my $blib_arch = File::Spec->catdir('blib', 'arch');
726        if ($source eq $blib_lib and
727            exists $from_to{$blib_arch} and
728            directory_not_empty($blib_arch)
729        ){
730            $targetroot = install_rooted_dir($from_to{$blib_arch});
731            print "Files found in $blib_arch: installing files in $blib_lib into architecture dependent library tree\n";
732        }
733
734        next unless -d $source;
735        _chdir($source);
736        # 5.5.3's File::Find missing no_chdir option
737        # XXX OS-SPECIFIC
738        # File::Find seems to always be Unixy except on MacPerl :(
739        my $current_directory= $Is_MacPerl ? $Curdir : '.';
740        find(sub {
741            my ($mode,$size,$atime,$mtime) = (stat)[2,7,8,9];
742
743            return if !-f _;
744            my $origfile = $_;
745
746            return if $origfile eq ".exists";
747            my $targetdir  = File::Spec->catdir($targetroot, $File::Find::dir);
748            my $targetfile = File::Spec->catfile($targetdir, $origfile);
749            my $sourcedir  = File::Spec->catdir($source, $File::Find::dir);
750            my $sourcefile = File::Spec->catfile($sourcedir, $origfile);
751
752            for my $pat (@$skip) {
753                if ( $sourcefile=~/$pat/ ) {
754                    print "Skipping $targetfile (filtered)\n"
755                        if $verbose>1;
756                    $result->{install_filtered}{$sourcefile} = $pat;
757                    return;
758                }
759            }
760            # we have to do this for back compat with old File::Finds
761            # and because the target is relative
762            my $save_cwd = _chdir($cwd);
763            my $diff = 0;
764            # XXX: I wonder how useful this logic is actually -- demerphq
765            if ( $always_copy or !-f $targetfile or -s $targetfile != $size) {
766                $diff++;
767            } else {
768                # we might not need to copy this file
769                $diff = compare($sourcefile, $targetfile);
770            }
771            $check_dirs{$targetdir}++
772                unless -w $targetfile;
773
774            push @found_files,
775                [ $diff, $File::Find::dir, $origfile,
776                  $mode, $size, $atime, $mtime,
777                  $targetdir, $targetfile, $sourcedir, $sourcefile,
778
779                ];
780            #restore the original directory we were in when File::Find
781            #called us so that it doesn't get horribly confused.
782            _chdir($save_cwd);
783        }, $current_directory );
784        _chdir($cwd);
785    }
786    foreach my $targetdir (sort keys %check_dirs) {
787        _mkpath( $targetdir, 0, $Perm_Dir, $verbose, $dry_run );
788    }
789    foreach my $found (@found_files) {
790        my ($diff, $ffd, $origfile, $mode, $size, $atime, $mtime,
791            $targetdir, $targetfile, $sourcedir, $sourcefile)= @$found;
792
793        my $realtarget= $targetfile;
794        if ($diff) {
795            eval {
796                if (-f $targetfile) {
797                    print "_unlink_or_rename($targetfile)\n" if $verbose>1;
798                    $targetfile= _unlink_or_rename( $targetfile, 'tryhard', 'install' )
799                        unless $dry_run;
800                } elsif ( ! -d $targetdir ) {
801                    _mkpath( $targetdir, 0, $Perm_Dir, $verbose, $dry_run );
802                }
803                print "Installing $targetfile\n";
804
805                _copy( $sourcefile, $targetfile, $verbose, $dry_run, );
806
807
808                #XXX OS-SPECIFIC
809                print "utime($atime,$mtime,$targetfile)\n" if $verbose>1;
810                utime($atime,$mtime + $Is_VMS,$targetfile) unless $dry_run>1;
811
812
813                $mode = 0444 | ( $mode & 0111 ? 0111 : 0 );
814                $mode = $mode | 0222
815                    if $realtarget ne $targetfile;
816                _chmod( $mode, $targetfile, $verbose );
817                $result->{install}{$targetfile} = $sourcefile;
818                1
819            } or do {
820                $result->{install_fail}{$targetfile} = $sourcefile;
821                die $@;
822            };
823        } else {
824            $result->{install_unchanged}{$targetfile} = $sourcefile;
825            print "Skipping $targetfile (unchanged)\n" if $verbose;
826        }
827
828        if ( $uninstall_shadows ) {
829            inc_uninstall($sourcefile,$ffd, $verbose,
830                          $dry_run,
831                          $realtarget ne $targetfile ? $realtarget : "",
832                          $result);
833        }
834
835        # Record the full pathname.
836        $packlist->{$targetfile}++;
837    }
838
839    if ($pack{'write'}) {
840        $dir = install_rooted_dir(dirname($pack{'write'}));
841        _mkpath( $dir, 0, $Perm_Dir, $verbose, $dry_run );
842        print "Writing $pack{'write'}\n" if $verbose;
843        $packlist->write(install_rooted_file($pack{'write'})) unless $dry_run;
844    }
845
846    _do_cleanup($verbose);
847    return $result;
848}
849
850=begin _private
851
852=item _do_cleanup
853
854Standardize finish event for after another instruction has occurred.
855Handles converting $MUST_REBOOT to a die for instance.
856
857=end _private
858
859=cut
860
861sub _do_cleanup {
862    my ($verbose) = @_;
863    if ($MUST_REBOOT) {
864        die _estr "Operation not completed! ",
865            "You must reboot to complete the installation.",
866            "Sorry.";
867    } elsif (defined $MUST_REBOOT & $verbose) {
868        warn _estr "Installation will be completed at the next reboot.\n",
869             "However it is not necessary to reboot immediately.\n";
870    }
871}
872
873=begin _undocumented
874
875=item install_rooted_file( $file )
876
877Returns $file, or catfile($INSTALL_ROOT,$file) if $INSTALL_ROOT
878is defined.
879
880=item install_rooted_dir( $dir )
881
882Returns $dir, or catdir($INSTALL_ROOT,$dir) if $INSTALL_ROOT
883is defined.
884
885=end _undocumented
886
887=cut
888
889
890sub install_rooted_file {
891    if (defined $INSTALL_ROOT) {
892        File::Spec->catfile($INSTALL_ROOT, $_[0]);
893    } else {
894        $_[0];
895    }
896}
897
898
899sub install_rooted_dir {
900    if (defined $INSTALL_ROOT) {
901        File::Spec->catdir($INSTALL_ROOT, $_[0]);
902    } else {
903        $_[0];
904    }
905}
906
907=begin _undocumented
908
909=item forceunlink( $file, $tryhard )
910
911Tries to delete a file. If $tryhard is true then we will use whatever
912devious tricks we can to delete the file. Currently this only applies to
913Win32 in that it will try to use Win32API::File to schedule a delete at
914reboot. A wrapper for _unlink_or_rename().
915
916=end _undocumented
917
918=cut
919
920
921sub forceunlink {
922    my ( $file, $tryhard )= @_; #XXX OS-SPECIFIC
923    _unlink_or_rename( $file, $tryhard, not("installing") );
924}
925
926=begin _undocumented
927
928=item directory_not_empty( $dir )
929
930Returns 1 if there is an .exists file somewhere in a directory tree.
931Returns 0 if there is not.
932
933=end _undocumented
934
935=cut
936
937sub directory_not_empty ($) {
938  my($dir) = @_;
939  my $files = 0;
940  find(sub {
941           return if $_ eq ".exists";
942           if (-f) {
943             $File::Find::prune++;
944             $files = 1;
945           }
946       }, $dir);
947  return $files;
948}
949
950=pod
951
952=item B<install_default> I<DISCOURAGED>
953
954    install_default();
955    install_default($fullext);
956
957Calls install() with arguments to copy a module from blib/ to the
958default site installation location.
959
960$fullext is the name of the module converted to a directory
961(ie. Foo::Bar would be Foo/Bar).  If $fullext is not specified, it
962will attempt to read it from @ARGV.
963
964This is primarily useful for install scripts.
965
966B<NOTE> This function is not really useful because of the hard-coded
967install location with no way to control site vs core vs vendor
968directories and the strange way in which the module name is given.
969Consider its use discouraged.
970
971=cut
972
973sub install_default {
974  @_ < 2 or Carp::croak("install_default should be called with 0 or 1 argument");
975  my $FULLEXT = @_ ? shift : $ARGV[0];
976  defined $FULLEXT or die "Do not know to where to write install log";
977  my $INST_LIB = File::Spec->catdir($Curdir,"blib","lib");
978  my $INST_ARCHLIB = File::Spec->catdir($Curdir,"blib","arch");
979  my $INST_BIN = File::Spec->catdir($Curdir,'blib','bin');
980  my $INST_SCRIPT = File::Spec->catdir($Curdir,'blib','script');
981  my $INST_MAN1DIR = File::Spec->catdir($Curdir,'blib','man1');
982  my $INST_MAN3DIR = File::Spec->catdir($Curdir,'blib','man3');
983
984  my @INST_HTML;
985  if($Config{installhtmldir}) {
986      my $INST_HTMLDIR = File::Spec->catdir($Curdir,'blib','html');
987      @INST_HTML = ($INST_HTMLDIR => $Config{installhtmldir});
988  }
989
990  install({
991           read => "$Config{sitearchexp}/auto/$FULLEXT/.packlist",
992           write => "$Config{installsitearch}/auto/$FULLEXT/.packlist",
993           $INST_LIB => (directory_not_empty($INST_ARCHLIB)) ?
994                         $Config{installsitearch} :
995                         $Config{installsitelib},
996           $INST_ARCHLIB => $Config{installsitearch},
997           $INST_BIN => $Config{installbin} ,
998           $INST_SCRIPT => $Config{installscript},
999           $INST_MAN1DIR => $Config{installman1dir},
1000           $INST_MAN3DIR => $Config{installman3dir},
1001       @INST_HTML,
1002          },1,0,0);
1003}
1004
1005
1006=item B<uninstall>
1007
1008    uninstall($packlist_file);
1009    uninstall($packlist_file, $verbose, $dont_execute);
1010
1011Removes the files listed in a $packlist_file.
1012
1013If $verbose is true, will print out each file removed.  Default is
1014false.
1015
1016If $dont_execute is true it will only print what it was going to do
1017without actually doing it.  Default is false.
1018
1019=cut
1020
1021sub uninstall {
1022    my($fil,$verbose,$dry_run) = @_;
1023    $verbose ||= 0;
1024    $dry_run  ||= 0;
1025
1026    die _estr "ERROR: no packlist file found: '$fil'"
1027        unless -f $fil;
1028    # my $my_req = $self->catfile(qw(auto ExtUtils Install forceunlink.al));
1029    # require $my_req; # Hairy, but for the first
1030    my ($packlist) = ExtUtils::Packlist->new($fil);
1031    foreach (sort(keys(%$packlist))) {
1032        chomp;
1033        print "unlink $_\n" if $verbose;
1034        forceunlink($_,'tryhard') unless $dry_run;
1035    }
1036    print "unlink $fil\n" if $verbose;
1037    forceunlink($fil, 'tryhard') unless $dry_run;
1038    _do_cleanup($verbose);
1039}
1040
1041=begin _undocumented
1042
1043=item inc_uninstall($filepath,$libdir,$verbose,$dry_run,$ignore,$results)
1044
1045Remove shadowed files. If $ignore is true then it is assumed to hold
1046a filename to ignore. This is used to prevent spurious warnings from
1047occurring when doing an install at reboot.
1048
1049We now only die when failing to remove a file that has precedence over
1050our own, when our install has precedence we only warn.
1051
1052$results is assumed to contain a hashref which will have the keys
1053'uninstall' and 'uninstall_fail' populated with  keys for the files
1054removed and values of the source files they would shadow.
1055
1056=end _undocumented
1057
1058=cut
1059
1060sub inc_uninstall {
1061    my($filepath,$libdir,$verbose,$dry_run,$ignore,$results) = @_;
1062    my($dir);
1063    $ignore||="";
1064    my $file = (File::Spec->splitpath($filepath))[2];
1065    my %seen_dir = ();
1066
1067    my @PERL_ENV_LIB = split $Config{path_sep}, defined $ENV{'PERL5LIB'}
1068      ? $ENV{'PERL5LIB'} : $ENV{'PERLLIB'} || '';
1069
1070    my @dirs=( @PERL_ENV_LIB,
1071               @INC,
1072               @Config{qw(archlibexp
1073                          privlibexp
1074                          sitearchexp
1075                          sitelibexp)});
1076
1077    #warn join "\n","---",@dirs,"---";
1078    my $seen_ours;
1079    foreach $dir ( @dirs ) {
1080        my $canonpath = $Is_VMS ? $dir : File::Spec->canonpath($dir);
1081        next if $canonpath eq $Curdir;
1082        next if $seen_dir{$canonpath}++;
1083        my $targetfile = File::Spec->catfile($canonpath,$libdir,$file);
1084        next unless -f $targetfile;
1085
1086        # The reason why we compare file's contents is, that we cannot
1087        # know, which is the file we just installed (AFS). So we leave
1088        # an identical file in place
1089        my $diff = 0;
1090        if ( -f $targetfile && -s _ == -s $filepath) {
1091            # We have a good chance, we can skip this one
1092            $diff = compare($filepath,$targetfile);
1093        } else {
1094            $diff++;
1095        }
1096        print "#$file and $targetfile differ\n" if $diff && $verbose > 1;
1097
1098        if (!$diff or $targetfile eq $ignore) {
1099            $seen_ours = 1;
1100            next;
1101        }
1102        if ($dry_run) {
1103            $results->{uninstall}{$targetfile} = $filepath;
1104            if ($verbose) {
1105                $Inc_uninstall_warn_handler ||= ExtUtils::Install::Warn->new();
1106                $libdir =~ s|^\./||s ; # That's just cosmetics, no need to port. It looks prettier.
1107                $Inc_uninstall_warn_handler->add(
1108                                     File::Spec->catfile($libdir, $file),
1109                                     $targetfile
1110                                    );
1111            }
1112            # if not verbose, we just say nothing
1113        } else {
1114            print "Unlinking $targetfile (shadowing?)\n" if $verbose;
1115            eval {
1116                die "Fake die for testing"
1117                    if $ExtUtils::Install::Testing and
1118                       ucase(File::Spec->canonpath($ExtUtils::Install::Testing)) eq ucase($targetfile);
1119                forceunlink($targetfile,'tryhard');
1120                $results->{uninstall}{$targetfile} = $filepath;
1121                1;
1122            } or do {
1123                $results->{fail_uninstall}{$targetfile} = $filepath;
1124                if ($seen_ours) {
1125                    warn "Failed to remove probably harmless shadow file '$targetfile'\n";
1126                } else {
1127                    die "$@\n";
1128                }
1129            };
1130        }
1131    }
1132}
1133
1134=begin _undocumented
1135
1136=item run_filter($cmd,$src,$dest)
1137
1138Filter $src using $cmd into $dest.
1139
1140=end _undocumented
1141
1142=cut
1143
1144sub run_filter {
1145    my ($cmd, $src, $dest) = @_;
1146    local(*CMD, *SRC);
1147    open(CMD, "|$cmd >$dest") || die "Cannot fork: $!";
1148    open(SRC, $src)           || die "Cannot open $src: $!";
1149    my $buf;
1150    my $sz = 1024;
1151    while (my $len = sysread(SRC, $buf, $sz)) {
1152        syswrite(CMD, $buf, $len);
1153    }
1154    close SRC;
1155    close CMD or die "Filter command '$cmd' failed for $src";
1156}
1157
1158=pod
1159
1160=item B<pm_to_blib>
1161
1162    pm_to_blib(\%from_to, $autosplit_dir);
1163    pm_to_blib(\%from_to, $autosplit_dir, $filter_cmd);
1164
1165Copies each key of %from_to to its corresponding value efficiently.
1166Filenames with the extension .pm are autosplit into the $autosplit_dir.
1167Any destination directories are created.
1168
1169$filter_cmd is an optional shell command to run each .pm file through
1170prior to splitting and copying.  Input is the contents of the module,
1171output the new module contents.
1172
1173You can have an environment variable PERL_INSTALL_ROOT set which will
1174be prepended as a directory to each installed file (and directory).
1175
1176By default verbose output is generated, setting the PERL_INSTALL_QUIET
1177environment variable will silence this output.
1178
1179=cut
1180
1181sub pm_to_blib {
1182    my($fromto,$autodir,$pm_filter) = @_;
1183
1184    _mkpath($autodir,0,$Perm_Dir);
1185    while(my($from, $to) = each %$fromto) {
1186        if( -f $to && -s $from == -s $to && -M $to < -M $from ) {
1187            print "Skip $to (unchanged)\n" unless $INSTALL_QUIET;
1188            next;
1189        }
1190
1191        # When a pm_filter is defined, we need to pre-process the source first
1192        # to determine whether it has changed or not.  Therefore, only perform
1193        # the comparison check when there's no filter to be ran.
1194        #    -- RAM, 03/01/2001
1195
1196        my $need_filtering = defined $pm_filter && length $pm_filter &&
1197                             $from =~ /\.pm$/;
1198
1199        if (!$need_filtering && 0 == compare($from,$to)) {
1200            print "Skip $to (unchanged)\n" unless $INSTALL_QUIET;
1201            next;
1202        }
1203        if (-f $to){
1204            # we wont try hard here. its too likely to mess things up.
1205            forceunlink($to);
1206        } else {
1207            _mkpath(dirname($to),0,$Perm_Dir);
1208        }
1209        if ($need_filtering) {
1210            run_filter($pm_filter, $from, $to);
1211            print "$pm_filter <$from >$to\n";
1212        } else {
1213            _copy( $from, $to );
1214            print "cp $from $to\n" unless $INSTALL_QUIET;
1215        }
1216        my($mode,$atime,$mtime) = (stat $from)[2,8,9];
1217        utime($atime,$mtime+$Is_VMS,$to);
1218        _chmod(0444 | ( $mode & 0111 ? 0111 : 0 ),$to);
1219        next unless $from =~ /\.pm$/;
1220        _autosplit($to,$autodir);
1221    }
1222}
1223
1224
1225=begin _private
1226
1227=item _autosplit
1228
1229From 1.0307 back, AutoSplit will sometimes leave an open filehandle to
1230the file being split.  This causes problems on systems with mandatory
1231locking (ie. Windows).  So we wrap it and close the filehandle.
1232
1233=end _private
1234
1235=cut
1236
1237sub _autosplit { #XXX OS-SPECIFIC
1238    my $retval = autosplit(@_);
1239    close *AutoSplit::IN if defined *AutoSplit::IN{IO};
1240
1241    return $retval;
1242}
1243
1244
1245package ExtUtils::Install::Warn;
1246
1247sub new { bless {}, shift }
1248
1249sub add {
1250    my($self,$file,$targetfile) = @_;
1251    push @{$self->{$file}}, $targetfile;
1252}
1253
1254sub DESTROY {
1255    unless(defined $INSTALL_ROOT) {
1256        my $self = shift;
1257        my($file,$i,$plural);
1258        foreach $file (sort keys %$self) {
1259            $plural = @{$self->{$file}} > 1 ? "s" : "";
1260            print "## Differing version$plural of $file found. You might like to\n";
1261            for (0..$#{$self->{$file}}) {
1262                print "rm ", $self->{$file}[$_], "\n";
1263                $i++;
1264            }
1265        }
1266        $plural = $i>1 ? "all those files" : "this file";
1267        my $inst = (_invokant() eq 'ExtUtils::MakeMaker')
1268                 ? ( $Config::Config{make} || 'make' ).' install'
1269                     . ( $Is_VMS ? '/MACRO="UNINST"=1' : ' UNINST=1' )
1270                 : './Build install uninst=1';
1271        print "## Running '$inst' will unlink $plural for you.\n";
1272    }
1273}
1274
1275=begin _private
1276
1277=item _invokant
1278
1279Does a heuristic on the stack to see who called us for more intelligent
1280error messages. Currently assumes we will be called only by Module::Build
1281or by ExtUtils::MakeMaker.
1282
1283=end _private
1284
1285=cut
1286
1287sub _invokant {
1288    my @stack;
1289    my $frame = 0;
1290    while (my $file = (caller($frame++))[1]) {
1291        push @stack, (File::Spec->splitpath($file))[2];
1292    }
1293
1294    my $builder;
1295    my $top = pop @stack;
1296    if ($top =~ /^Build/i || exists($INC{'Module/Build.pm'})) {
1297        $builder = 'Module::Build';
1298    } else {
1299        $builder = 'ExtUtils::MakeMaker';
1300    }
1301    return $builder;
1302}
1303
1304=pod
1305
1306=back
1307
1308=head1 ENVIRONMENT
1309
1310=over 4
1311
1312=item B<PERL_INSTALL_ROOT>
1313
1314Will be prepended to each install path.
1315
1316=item B<EU_INSTALL_IGNORE_SKIP>
1317
1318Will prevent the automatic use of INSTALL.SKIP as the install skip file.
1319
1320=item B<EU_INSTALL_SITE_SKIPFILE>
1321
1322If there is no INSTALL.SKIP file in the make directory then this value
1323can be used to provide a default.
1324
1325=item B<EU_INSTALL_ALWAYS_COPY>
1326
1327If this environment variable is true then normal install processes will
1328always overwrite older identical files during the install process.
1329
1330Note that the alias EU_ALWAYS_COPY will be supported if EU_INSTALL_ALWAYS_COPY
1331is not defined until at least the 1.50 release. Please ensure you use the
1332correct EU_INSTALL_ALWAYS_COPY.
1333
1334=back
1335
1336=head1 AUTHOR
1337
1338Original author lost in the mists of time.  Probably the same as Makemaker.
1339
1340Production release currently maintained by demerphq C<yves at cpan.org>,
1341extensive changes by Michael G. Schwern.
1342
1343Send bug reports via http://rt.cpan.org/.  Please send your
1344generated Makefile along with your report.
1345
1346=head1 LICENSE
1347
1348This program is free software; you can redistribute it and/or
1349modify it under the same terms as Perl itself.
1350
1351See L<http://www.perl.com/perl/misc/Artistic.html>
1352
1353
1354=cut
1355
13561;
1357