Home | History | Annotate | Download | only in tools
      1 #!/usr/bin/perl
      2 #
      3 # CDDL HEADER START
      4 #
      5 # The contents of this file are subject to the terms of the
      6 # Common Development and Distribution License (the "License").
      7 # You may not use this file except in compliance with the License.
      8 #
      9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10 # or http://www.opensolaris.org/os/licensing.
     11 # See the License for the specific language governing permissions
     12 # and limitations under the License.
     13 #
     14 # When distributing Covered Code, include this CDDL HEADER in each
     15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16 # If applicable, add the following below this CDDL HEADER, with the
     17 # fields enclosed by brackets "[]" replaced with your own identifying
     18 # information: Portions Copyright [yyyy] [name of copyright owner]
     19 #
     20 # CDDL HEADER END
     21 #
     22 # Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     23 # Use is subject to license terms.
     24 #
     25 #ident	"@(#)install-proto.pl	1.2	07/07/24 SMI"
     26 #
     27 # BSD compatible install(1b) that honors DESTDIR and performs SFW post
     28 # processing on various file types
     29 #
     30 
     31 use Getopt::Std;
     32 use File::Basename;
     33 use File::Copy;
     34 
     35 my ($DESTDIR, $SRC, $MANSCRIPT, %opts, @paths) =
     36 	($ENV{'DESTDIR'}, $ENV{'SRC'}, $ENV{'MANSCRIPT'});
     37 my ($post_process, $post_process_so, $strip) = (
     38 	$SRC.'/tools/post_process',
     39 	$SRC.'/tools/post_process_so',
     40 	'/usr/ccs/bin/strip');
     41 my $progname = basename($0);
     42 
     43 (defined($DESTDIR)) || ($DESTDIR = $ENV{'ROOT'});
     44 
     45 sub usage {
     46 	print "$progname [-cs] [-g group] [-o owner] [-m mode] file1 file2\n";
     47 	print "$progname [-cs] [-g group] [-o owner] [-m mode] file... dir\n";
     48 	print "$progname -d [-g group] [-o owner] [-m mode] dir\n";
     49 	exit (1);
     50 }
     51 
     52 sub file_type {
     53 	local ($path) = @_;
     54 
     55 	open(FH, "/bin/file $path|");
     56 	my $line = <FH>;
     57 	close(FH);
     58 
     59 	# if the path matches the pattern, it's a man page.
     60 	($path =~ /.*\/man\/man.+\/.*\.[1-9].*/) && ($line = 'roff');
     61 	
     62 	return($line);
     63 }
     64 
     65 sub copyfile {
     66 	local ($src, $dst) = @_;
     67 
     68 	if (! -f $src) {	# if there is no src, skip it
     69 		warn("$src: no such file\n");
     70 		return;
     71 	}
     72 
     73 	unlink($dst);		# remove the original
     74 
     75 	my $type = file_type($src);
     76 	if ((defined($MANSCRIPT)) && ($type =~ /roff,/)) {
     77 		(-f $MANSCRIPT) ||
     78 			die "$progname: error: $MANSCRIPT does not exist\n";
     79 		system("sed -f $MANSCRIPT <$src >$dst");
     80 	} elsif ($type =~ /perl .*script/) {
     81 		system("sed -e '1s|^#\!.*perl|#\!/usr/perl5/bin/perl|' <$src >$dst");
     82 	} elsif (-T $src) {
     83 		system("sed -e 's|${DESTDIR}||g' <$src >$dst");
     84 	} else {
     85 		copy($src, $dst);
     86 	}
     87 
     88 	# ELF files get post processing
     89 	if (($type =~ /ELF .*dynamic lib/) && (-x $post_process_so)) {
     90 		system("$post_process_so $dst");
     91 		chmod(0555, $dst); # default to ugo rx
     92 	} elsif (($type =~ /ELF .*executable/) && (-x $post_process) &&
     93 		 (-x $strip)) {
     94 		system("$post_process $dst ; $strip $dst");
     95 		chmod(0555, $dst); # default to ugo rx
     96 	} elsif ($type =~ /executable/) {
     97 		chmod(0555, $dst); # default to ugo rx
     98 	}
     99 }
    100 sub mkdir_p {
    101 	local($path, $mode) = @_;
    102 
    103 	(-d $path) && return;		# found it, return
    104 
    105 	mkdir_p(dirname($path), $mode);	# make the parent first
    106 	mkdir($path, $mode);
    107 }
    108 
    109 #
    110 # Execution begins here
    111 #
    112 getopts('cdg:m:o:s', \%opts);
    113 
    114 # the last argument is the destination (file or dir)
    115 my $dst = $ARGV[$#ARGV];
    116 $#ARGV--;
    117 
    118 (defined($opts{'d'})) && ($#ARGV != -1) && usage();
    119 ($#ARGV > 0) && (! -d $dst) && usage();
    120 
    121 # dst should include the DESTDIR
    122 ($DESTDIR ne substr($dst, 0, length($DESTDIR))) &&
    123 	($dst = $DESTDIR.'/'.$dst);
    124 
    125 if (defined($opts{'d'})) {	# ... -d dir
    126 	mkdir_p($dst, 0755);
    127 	push(@paths, $dst);
    128 } elsif (-d $dst) {		# ... file... dir
    129 	foreach $path (@ARGV) {
    130 		my $file = $dst.'/'.basename($path);
    131 		copyfile($path, $file);
    132 		push(@paths, $file);
    133 	}	
    134 } else {			# ... file1 file2
    135 	copyfile($ARGV[0], $dst);
    136 	push(@paths, $dst);
    137 }
    138 
    139 # fix the file attributes
    140 foreach $path (@paths) {
    141 	# fix the mode
    142 	if (defined($opts{'m'})) {
    143 		chmod(oct($opts{'m'}), $path);
    144 	}
    145 
    146 	# fix the owner/group information
    147 	if (defined($opts{'o'}) || defined($opts{'g'})) {
    148 		my ($uid, $gid) = (-1, -1);
    149 
    150 		(defined($opts{'o'})) && (($x,$x,$uid) = getpwnam($opts{'o'}));
    151 		(defined($opts{'g'})) && (($x,$x,$gid) = getgrnam($opts{'g'}));
    152 		chown($uid, $gid, $path);
    153 	}
    154 }
    155 
    156 exit 0;
    157