home *** CD-ROM | disk | FTP | other *** search
- #!/usr/local/bin/perl
- #
- # Copyright (C) Ready-to-Run Software, Inc. 1991-1997.
- # 4 Pleasant Street
- # Forge Village, MA 01886.
- #
- # All Rights Reserved.
- #
- # This Module contains Proprietary Information of
- # Ready-to-Run Software, Inc.
- #
- # Ready-to-Run Software, Inc. is a software service company. Most
- # of the software provided to our customers is "publically
- # available"; we provide the service of locating and building
- # the software for you. In general, you may make as many copies
- # as you want of the software that we deliver to you (individual
- # package license information is provided during the installation
- # process). The major exception to that is Ready-to-Run Software's
- # "Smart Installation System". We view the installation system
- # and the proprietary techniques used in it, as the vehicle that
- # allows us to effectively deliver our services to you. Accordingly:
- #
- # Use of this "Smart Installation System" is limited as follows:
- #
- # 1) by anyone, to install a SAMPLE ReadyPak(tm) from
- # Ready-to-Run Software, Inc.
- # 2) by a ReadyPak Purchaser to install a ReadyPak obtained from
- # Ready-to-Run Software, Inc. on any machine within your
- # organization.
- # 3) It may not be copied or otherwise distributed without written
- # permission from Ready-to-Run Software, Inc.
- #
- #
- # $Id: install.rtr,v 1.3 1997/06/18 18:45:26 mike Exp $
- #
- # $Log: install.rtr,v $
- # Revision 1.3 1997/06/18 18:45:26 mike
- # fis for perl5
- #
- # Revision 1.2 1997/06/18 18:44:21 jeff
- # updated copyright/address info
- #
- # Revision 1.1 1992/12/14 21:56:45 jeff
- # Initial revision
- #
- # Revision 1.13 1992/12/06 21:16:58 jeff
- # Another RS6000 patch change shared library patch change.
- # Symbolic Links fix.
- #
- # Revision 1.12 1992/09/11 14:50:14 jeff
- # Added installation logging.
- #
- # Revision 1.11 1992/07/13 12:30:42 jeff
- # Handle dynamic load library paths on RS6000.
- #
- # Revision 1.10 1992/07/13 11:38:45 jeff
- # Make sure that we only issue / warnings in Verbose mode.
- #
- # Revision 1.9 1992/03/13 11:04:20 jeff
- # Fix symbolic link testing for SCO.
- #
- # Revision 1.8 1992/02/14 19:39:55 jeff
- # Fix intermittent problem with bad format on SCO machines.
- #
- # Revision 1.7 1992/01/22 14:38:42 jeff
- # Full release version
- #
- # Revision 1.6 1992/01/06 19:42:06 jeff
- # General cleanup, new options to support "readypak", copying files
- # a few bug fixes (primarily with text files).
- #
- # Revision 1.5 1991/12/04 22:30:52 jeff
- # Fixed some small problems (including modes on install directories).
- # Added support for hard and symbolic links (if a hard link can't be
- # created, typically due to partition destinations, a copy will be
- # made instead).
- # Added checks for relative path problems (now that we're allowing
- # shareable files to move and shareable directories to be renamed,
- # a potential problem exists with relative path names).
- #
- # Revision 1.4 1991/12/04 19:45:10 jeff
- # Fix references to ABS and/or shareable files.
- # Handle paths with leading /'s better (-i and -s options)
- #
- # Revision 1.3 1991/12/04 14:49:58 jeff
- # Many changes:
- # -s option (size) is now -t (totals)
- # added -h for help (and usage message)
- # -i to override default install path
- # -s to override default shareables install path
- # -c to convert slib->lib, sbin->bin, sspool->spool
- #
- # Revision 1.2 1991/12/04 11:29:35 jeff
- # Cleaned up the -r option (in particular, we now wait until all
- # files are removed before attempting to remove the directories,
- # and the directories are removed in the correct order to guarantee
- # that they can all be removed in a single pass if they're empty).
- #
- # Added -v option to turn on verbose messages.
- # Added -s option to display size of installed or removed files.
- #
- # Revision 1.1 1991/12/03 18:18:38 jeff
- # Initial revision
- #
-
- $0 =~ m|(.*/)(.*)|, $PROG = $2; $EXECDIR = $1; # find program name
-
- $TRUE = 1;
- $FALSE = 0;
- $DO_INFO = $FALSE; # don't add info files to "dir"
- $TESTING = $FALSE; # Should be FALSE when we ship
-
- $INFO = 1;
- $START = 1;
- $PROCESS = 2;
- $END = 3;
-
- $DEFAULT = 1;
- $REQUIRED = 2;
- $OPTIONAL = 3;
-
-
- $SUID = 04000;
- $SGID = 02000;
-
- $BlockSize = 4096;
- $PathPrefix = '/' x 50;
- $STAGEPath = 'usr/STAGE';
- $InstallPath = '/usr/local';
- $InstallSharePath = '/usr/local/share';
- $ShareDirs = '(sbin|slib|sspool|sinclude|man|texinfo|doc|hardcopy)';
- $ConvertDirs = '(sbin|slib|sspool|sinclude)';
- $AbsDir = 'ABS';
- $RelativePathPrefix = '../';
-
-
- $SYMLINK_EXISTS = (eval 'symlink("","");', $@ eq '' );
-
- $TotalFiles = 0;
- $TotalLinks = 0;
- $TotalDirs = 0;
- $TotalFailFiles = 0;
- $TotalFailLinks = 0;
- $TotalFailDirs = 0;
- $TotalFailSize = 0;
- $ShowTotals = $FALSE;
- $Verbose = $FALSE;
- $ConvertShareables = $FALSE;
- $DeleteWhileInstalling = $FALSE;
- $Log = 'RTRinstall.log';
-
- $stat = 'lstat';
- $stat = 'stat' if !$SYMLINK_EXISTS;
- $routine = Xfer;
- $FileMessage = "installed";
- $LinkMessage = "created";
- $DirMessage = "added";
-
- &GetOptions();
-
- if (defined $PakName) {
- open( LOG, ">>$Log" );
- printf LOG "\n\nPackage: $PakName -- installed " . `date` . "\n";
- close LOG;
- }
-
- open( LOG, "| sort >>$Log" );
-
- &EnsureInstallDirs;
-
- while (<>) {
- chop;
- $copy = $FALSE;
- $name = "/$STAGEOrigin/$_";
- if ($name =~ /(.*)\*(.*)$/) {
- $copy = $TRUE;
- $name = $1 . $2;
- }
- &wanted();
- }
-
- &FinishRemove if ($routine eq Remove);
-
- if ($ShowTotals)
- {
- $TotalLinks -= $TotalFailLinks;
- $TotalFiles -= $TotalFailFiles;
- $TotalSize -= $TotalFailSize;
- printf("\n");
- printf("$TotalDirs director%s $DirMessage, ",($TotalDirs==1) ? 'y':'ies');
- printf("$TotalFiles file%s $FileMessage, ", ($TotalFiles == 1) ? '':'s' );
- printf("$TotalLinks symbolic link%s $LinkMessage.\n",($TotalLinks==1) ? '':'s');
- printf( "Approximately %s $FileMessage.\n", &FmtSize($TotalSize) );
-
- # only print failure stats if something failed
- printf("$TotalFailDirs director%s not $DirMessage",
- ($TotalFailDirs==1) ? 'y':'ies') if $TotalFailDirs;
- print ", " if $TotalFailDirs && $TotalFailFiles;
- printf("$TotalFailFiles file%s not $FileMessage",
- ($TotalFailFiles == 1) ? '':'s' ) if $TotalFailFiles;
- print ", " if $TotalFailDirs || $TotalFailFiles;
- printf("$TotalFailLinks link%s not $LinkMessage",
- ($TotalFailLinks == 1) ? '':'s' ) if $TotalFailLinks;
- print ".\n" if $TotalFailDirs || $TotalFailFiles || $TotalFailLinks;
- printf( "Approximately %s not $FileMessage.\n",
- &FmtSize($TotalFailSize) ) if $TotalFailFiles;
- }
-
- {
- close LOG;
- open( LOG, ">>$Log" );
- printf( LOG "\n");
- printf( LOG "$TotalDirs director%s $DirMessage, ",($TotalDirs==1) ? 'y':'ies');
- printf( LOG "$TotalFiles file%s $FileMessage.\n", ($TotalFiles == 1) ? '':'s' );
- printf( LOG "Approximately %s $FileMessage.\n", &FmtSize($TotalSize) );
-
- # only print failure stats if something failed
- printf( LOG "$TotalFailDirs director%s not $DirMessage",
- ($TotalFailDirs==1) ? 'y':'ies') if $TotalFailDirs;
- print LOG ", " if $TotalFailDirs && $TotalFailFiles;
- printf( LOG "$TotalFailFiles file%s not $FileMessage",
- ($TotalFailFiles == 1) ? '':'s' ) if $TotalFailFiles;
- print LOG ".\n" if $TotalFailDirs || $TotalFailFiles;
- printf( LOG "Approximately %s not $FileMessage.\n",
- &FmtSize($TotalFailSize) ) if $TotalFailFiles;
- printf( LOG "\n\n ********************************\n" );
- }
-
- close LOG;
-
- exit;
-
- sub GetOptions
- {
- while ($ARGV[0] =~ /^-/) {
- $_ = shift @ARGV;
- $ShowTotals = !$ShowTotals ,next if (/^-t/i);
- $Verbose = !$Verbose ,next if (/^-v/i);
- $Log = shift @ARGV ,next if (/^-L/);
- $PakName = shift @ARGV ,next if (/^-N/);
- $ConvertShareables = !$ConvertShareables ,next if (/^-c/i);
- $DeleteWhileInstalling = !$DeleteWhileInstalling ,next if (/^-d/i);
- $PrereqTrans{shift @ARGV} = shift @ARGV ,next if (/^-p/i);
- if (/^-i/i)
- {
- $InstallPath = shift @ARGV;
- $InstallPath =~ s|^/+||;
- next;
- }
- if (/^-r/i)
- {
- $routine = Remove ;
- $DirMessage = "removed";
- $FileMessage = "removed";
- next;
- }
- if (/^-s/i)
- {
- $InstallSharePath = shift @ARGV;
- $InstallSharePath =~ s|^/+||;
- next;
- }
- if (/^-o/i)
- {
- $STAGEOrigin = shift @ARGV;
- $STAGEOrigin =~ s|^/+||;
- &SetOrigin( $STAGEOrigin );
- next;
- }
-
- # we only get here for -h or unknown options
- print "\nUnknown option: $_" if (!/^-h/i);
-
- print "\nUsage: $PROG [-cdfhrsv] [-ios dir] [-p name1 name2]\n";
- print " -c convert slib->lib, sbin->bin, sspool->spool\n";
- print " -d delete from STAGE while installing\n";
- print " -f find files to install\n";
- print " -h this help message\n";
- print " -i dir install package at dir (default /usr/local)\n";
- print " -o dir origin (STAGE)\n";
- print " -p n1 n2 prequisite translation\n";
- print " -r remove package\n";
- print " -s dir install shareable portion of package at dir\n";
- print " -t show totals\n";
- print " -v verbose output\n";
- print " -L file create install log (file)\n";
- print " -N name indicate package name in log\n\n";
- exit;
- }
- }
-
- sub wanted {
- (($dev,$ino,$mode,$nlink,$uid,$gid) = eval "$stat(\"$name\")") &&
- eval '&$routine';
- if ($@ && -e $name) {
- print " ERROR: $@";
- $TotalFailFiles++, $TotalFailSize += (-s _) if -f _;
- $TotalFailDirs++ if -d _;
- }
- &Extras;
- return (1);
- }
-
- sub Extras
- {
- # do any applicable extra processing after the file has been processed
- }
-
- sub Xfer
- {
- local($in) = $name;
- local($out) = &TranslateName($name);
-
- if ($SYMLINK_EXISTS && -l $name) # symbolic link?
- {
- local($inl) = readlink $in;
- $inl =~ s:/usr/STAGE:$STAGEOrigin:;
- unlink($out);
- (symlink( &TranslateName($inl), $out ) && ++$TotalLinks) ||
- $TotalFailLinks++;
- }
- elsif (-f $name)
- {
- $TotalFiles++;
- $TotalSize += -s _;
- print "$out" if $Verbose;
- printf LOG " $out\n";
-
- # if we want to copy this file without reformating...
- # try to "link the file", otherwise just "rewrite"
- ($copy && unlink( $out ) && link( $in, $out )) || &ReWrite;
- unlink($in) if $DeleteWhileInstalling;
- print "\n" if $Verbose;
- }
- elsif (! -e $out)
- {
- return if $out eq "/$InstallPath/$AbsDir"; # Don't create the ABS dir
- print "$out: Making directory\n" if $Verbose;
- printf LOG " $out: Making directory\n";
- mkdir($out, $mode)
- || die("Can't mkdir $out: $!\n");
- $TotalDirs++;
- if ($SYMLINK_EXISTS) { lstat($_); }
- else { stat($_); }
- }
- else { return; } # return if we didn't do anything.
- }
-
- sub ReWrite
- {
- local(*IH, *OH, $buf, $pos, $outPos, $subs, $isTxt, $target);
-
- open(IH, $in)
- || die("Can't open $in for reading: $!\n");
-
- unlink( $out );
-
-
- # check for links before copying file
- # hard link?
- if ($nlink > 1) {
- # have we already copied this file ?
- $target = $LinkMap[ $dev, $ino ];
- if (($target ne "") && link( $target, $out )) {
- # don't count the space when we're only linking
- $TotalSize -= -s _;
- return (undef);
- }
- # if we can't link to the target, copy this one over and make it the
- # new target.
- $LinkMap[ $dev, $ino ] = $out;
- }
-
- open(OH, ">$out") || die("Can't open $out for writing: $!\n");
-
- warn("Warning: $in is empty!\n")
- if (!&RWBlockRead && $Verbose);
- do
- {
- &RWBlockRead;
- if (!$copy) {
- $pos = index($buf, $PathPrefix, 0);
- while ($pos != -1 && $pos <= $BlockSize)
- {
- $pos = &RWSubst;
- $pos = index($buf, $PathPrefix, $pos);
- }
- $pos = index($buf, $RelativePathPrefix, 0);
- while ($pos != -1 && $pos <= $BlockSize)
- {
- $pos = &RelativePathCheck($in);
- $pos = index($buf, $RelativePathPrefix, $pos);
- }
- }
- }
- while (&RWBlockWrite);
-
- print ": $subs Substitutions."
- if ($subs && $Verbose);
-
- close(IH);
- close(OH);
-
- return (undef);
- }
-
-
- sub RelativePathCheck
- {
- local($in) = @_;
- local($curPos, $path) = $outPos + $pos;
-
- # let's be paranoid and look for relative path problems
- # after this regex, $1 = entire path
- # $2 = leading ../
- # $3 = rest of path
- return $pos+1 if (!(substr($buf, $pos) =~ m|((../+)([\!-\~]+))|o));
- $path = $1;
- warn "Warning: Relative Path Problem: $path in $in\n"
- if ($path =~ m:/$ShareDirs(\W|$):o ||
- $in =~ m:/$ShareDirs(\W|$):o) &&
- ($ConvertShareables ||
- $InstallPath ne $InstallSharePath)
- && $INTERNAL_RELATIVE_CHECK;
- return ($pos + length($path));
- }
-
- sub RWSubst
- {
- local($curPos, $new) = $outPos + $pos;
- local($length1, $path);
-
- # after this regex, $1 = entire path
- # $2 = leading ///'s
- # $3 = "$STAGEPath"
- # $4 = after "$STAGEPath"
- if (!(substr($buf, $pos) =~ m:((/+)($STAGEPath)(\W[\!-\~]*|$)):o))
- {
- warn("Warning at offset $curPos: lots of '/'s, but bad path\n")
- if $Verbose;
- substr($buf, $pos) =~ m|(/+)|;
- return ($pos + length($1));
- }
-
- $length1 = length($1);
-
- warn("Warning at offset $curPos: The chain of '/'s is less than 75\n")
- if (length($2) < 75) && $Verbose;
- warn("Warning at offset $curPos: The chain of '/'s is more than 75\n")
- if (length($2) > 75) && $Verbose;
-
- $path = $4;
-
- if ($path =~ m:^/$ShareDirs(\W|$):o) {
- $path =~ s|^/s|/| if ($ConvertShareables); # remove leading "s"?
- $new = "/$InstallSharePath$path";
- }
- elsif ($path =~ m|^$AbsDir(/)([\!-\~]+)|o) {
- $new = "/$2";
- }
- else {
- $new = "/$InstallPath$path";
- }
-
- # in case a prerequisite package was installed somewhere else
- $new = $PrereqTrans{$new} if defined($PrereqTrans{$new});
-
- if ($new =~ /:((\/usr)?\/lib)$/) { $new .= ':' x ($length1 - length($new)); }
- else { $new .= "\000" x ($length1 - length($new)); }
- substr($buf, $pos, $length1) = $new;
- $subs++;
-
- return ($pos);
- }
-
-
- sub RWBlockRead
- {
- local($lbuf, $len);
-
- $len = sysread(IH, $lbuf, $BlockSize);
- $buf = $buf . $lbuf;
-
- return ($len > 0);
- }
-
-
- sub RWBlockWrite
- {
- local($pos, $wlen, $len, $wbuf);
-
- return ($FALSE)
- if (length($buf) == 0);
-
- $isTxt = !($buf =~ /[\001-\010\013\015-\037]/) if (!$outPos);
-
- $wlen = length($buf);
- $wlen = $BlockSize
- if ($wlen > $BlockSize);
- $wbuf = substr($buf, 0, $wlen);
-
- if ($isTxt && $subs)
- {
- $wbuf =~ s/\000//g;
- $wlen = length($wbuf);
- }
-
- $len = syswrite(OH, $wbuf, $wlen);
- die("Error writing to $out: $!\n")
- if ($len != $wlen);
-
- $outPos += $len;
-
- $buf = substr($buf, $BlockSize);
-
- return ($TRUE);
- }
-
-
- sub Remove
- {
- local($in) = $name;
- local($out) = &TranslateName($name);
-
- if (-f _)
- {
- if (unlink($out)) {
- $TotalFiles++;
- $TotalSize += -s _;
- print "$out...removed\n" if $Verbose;
- printf LOG " $out...removed\n";
- }
- elsif (-f $out) {
- print "$out...can`t remove\n" if $Verbose;
- printf LOG " $out...can`t remove\n";
- }
- else {
- print "$out...already removed\n" if $Verbose;
- printf LOG " $out...already removed\n";
- }
- }
- elsif (-d $out)
- {
- $dirlist{ $out } = $TRUE;
- }
- return ($TRUE);
- }
-
- sub ReverseLength
- {
- return (length($b) <=> length($a));
- }
-
- sub FinishRemove
- {
- foreach (sort ReverseLength keys %dirlist)
- {
- if (rmdir $_)
- {
- $TotalDirs++;
- print "$_...removed\n" if $Verbose;
- printf LOG " $_...removed\n";
- }
- }
- return ($TRUE);
- }
-
- sub EnsureInstallDirs {
- local($out);
-
- $mode = 0755; # create these directories rwxr-xr-x
- $out = '/' . $InstallPath;
- if (! -e $out) {
- print "$out: Making directory\n" if $Verbose;
- printf LOG " $out: Making directory\n" ;
- mkdir($out, $mode)
- || die("Can't mkdir $out: $!\n");
- $TotalDirs++;
- chmod($mode, $out) || die("Can't chmod $out to $mode: $!\n");
- }
-
- $out = '/' . $InstallSharePath;
- if (! -e $out) {
- print "$out: Making directory\n" if $Verbose;
- printf LOG " $out: Making directory\n" ;
- mkdir($out, $mode)
- || die("Can't mkdir $out: $!\n");
- $TotalDirs++;
- chmod($mode, $out) || die("Can't chmod $out to $mode: $!\n");
- }
- }
-
- sub RemoveLS
- {
- local( $name ) = @_;
- $name =~ s:^//+:/:;
- return $name;
- }
-
- # both SetOrigin and TranslateName strip leading /'s so they are mutually
- # consistent
- # remember to update RWSubst if changing translation rules.
- sub TranslateName
- {
- local($out, $in) = @_;
- local($ip, $isp);
- ($ip = $InstallPath) =~ s|^/+||;
- ($isp = $InstallSharePath) =~ s|^/+||;
- if ($out =~ /$SharePattern/o) {
- # currently, all convertable shareables start with $STAGEOrigin."/s"
- # so we simply remove the "s"
- $out =~ s/$ConvertFrom/$ConvertTo/o if ($ConvertShareables);
- $out =~ s/$STAGEOrigin/$isp/o;
- return &RemoveLS($out);
- }
- return &RemoveLS($out) if ($out =~ s/$AbsPath//o);
- return &RemoveLS($out) if ($out=~ s/$STAGEOrigin/$ip/o);
- # Problems exist if we have a relative path referencing a
- # shareable file and we convert or relocate shareable entries
- warn "Relative Path Problem: $out\n"
- if $out =~ m|\.\./| &&
- ($out =~ m:/$ShareDirs(\W|$):o ||
- $in =~ m:/$ShareDirs(\W|$):o)
- &&($ConvertShareables ||
- $ip ne $isp)
- && $INTERNAL_RELATIVE_CHECK;
- return &RemoveLS($out);
- }
-
- sub FmtSize {
- local($size) = @_;
-
- return sprintf( "%.1fMb", $size/1048576.0 ) if $size > 1000000.0;#1048576.0;
- return sprintf( "%3dKb", int($size/1024) ) if $size > 1024;
- return sprintf( "%d bytes", $size );
- }
-
- # both SetOrigin and TranslateName strip leading /'s so they are mutually
- # consistent
- sub SetOrigin {
- ($STAGEOrigin) = @_;
- $STAGEOrigin =~ s|^/+||;
- $SharePattern = $STAGEOrigin . '/' . $ShareDirs;
- $ConvertFrom = $STAGEOrigin . '/s';
- $ConvertTo = $STAGEOrigin . '/';
- $AbsPath = "$STAGEOrigin/ABS"; # staged component - absolute path
- }
-
- sub EmptySTDIN {
- while (&key_ready) { getc; }
- }
-
- sub Help {
- local($help) = @_;
- if (substr($help,0,1) eq '&') {
- eval($help);
- return;
- }
- printf( STDERR "\n$HELP{$help}" );
- }
-
- sub FileName {
- local($in,$out,$d) = @_;
- {
- $out = $in, last if $in !~ m:^~([^/]*):;
- if ($1 eq '') {
- $out = ($ENV{'HOME'} || $ENV{'LOGDIR'} ||
- (getpwuid($<))[7]) . substr($in,1);
- }
- else
- {
- $out = (getpwnam($1))[7] . $' ;
- }
- }
- return $out if substr($out,0,1) eq '/';
- $d = $cwd;
- while ($out =~ m:(\.{1,2}/)(.*$):) {
- $out = $2;
- next if ($1 eq './');
- $d =~ s:(.*)/[^/]+$:$1:;
- }
- return "$d/$out";
- }
-
- sub GetAnswer {
- local($msg,$default,$help,$validate) = @_;
- local($answer,$msgidx);
- ($msgidx = $msg) =~ s/\(Approx.*\)//;
- &EmptySTDIN;
- return $DefaultAnswer{$msgidx} if defined $DefaultAnswer{$msgidx};
- if (!$UseDefaultAnswers) {
- substr( $default, -1 ) = '' if substr($default,-1) eq "\n";
- for (;;) {
- printf( STDERR "$msg [$default]? " );
- $answer = <STDIN>;
- chop $answer;
- $UseDefaultAnswers = $TRUE, last if $answer =~ /\+\+/;
- $DefaultAnswer{$msgidx} = $answer = $default, last if $answer =~ /\+/;
- &Help($help), redo if $answer eq '?';
- last if $validate eq '' || $answer =~ /$validate|^$/;
- printf( STDERR "'$answer' is not a valid response (enter ? for help)\n" );
- }
- }
- return $default if ($UseDefaultAnswers || $answer eq '');
- if ($answer =~ /^[^a-z]+$/) {
- $answer =~ tr/A-Z/a-z/;
- $DefaultAnswer{$msgidx} = $answer ;
- }
- return ($answer);
- }
-
- sub GetReturn {
- local($msg) = @_;
- return if $UseDefaultAnswers;
- printf STDERR "$msg ... hit RETURN to continue ...";
- &EmptySTDIN;
- <STDIN>;
- }
-
- sub YesNo {
- local($msg,$help,$deflt) = @_;
- $deflt = 'y' if $deflt eq '';
- return $TRUE
- if &GetAnswer( $msg, $deflt, $help, '^[YyNn]' ) =~ /^(y|\s*)$/i;
- return $FALSE;
- }
-
- sub Name {
- local($name,$ext,$limit) = @_;
- $name = substr( $name, 0, $limit - (length($ext)+1) );
- return "$name.$ext";
- }
-
- sub FixOwnersAndModes {
- local($in,$owner,$group,$perms,$force_owner) = @_;
- $force_owner = '\|' if $force_owner eq '';
- local($mode,$file,$grp);
- $file = &TranslateName("/$STAGEOrigin/$in");
- $mode = (~ umask) & 0777;
- $mode &= 0666 if $perms !~ /[sgx]/ && !-d $file;
- $grp = $(;
- if (substr($perms, $[+6, 1) eq 's') { # it's sgid!!
- if (!defined $gid{$group}) {
- local($n, $p, $g, $m) = getgrnam($group);
- $gid{$group} = $g;
- }
- chown($<, $grp = $gid{$group}, $file)
- || warn ("Can't change group of $file to $group: $!\n");
- $mode |= $SGID;
- }
- if (substr($perms, $[+3, 1) eq 's' || $owner =~ $force_owner) {
- if (!defined $uid{$owner}) {
- local($n, $p, $u, $g) = getpwnam($owner);
- $uid{$owner} = $u;
- }
- chown($uid{$owner}, $grp, $file)
- || warn ("Can't change owner of $file to $owner: $!\n");
- $mode |= $SUID if (substr($perms, $[+3, 1) eq 's'); # it's suid!!
- }
- chmod $mode, $file
- || ($mode = sprintf("o", $mode), warn("Can't chmod $out to $mode: $!\n"));
- }
-