Home | History | Annotate | Download | only in tools
      1 #!/usr/perl5/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 2008 Sun Microsystems, Inc.  All rights reserved.
     23 # Use is subject to license terms.
     24 #
     25 #ident	"@(#)protofix.pl	1.2	08/03/26 SMI"
     26 #
     27 # Fix the attributes of paths in the proto area to match the packaging
     28 #
     29 
     30 use Getopt::Long;
     31 use Cwd;
     32 
     33 my ($root_dir, $src_dir, $mach) = ($ENV{'ROOT'}, $ENV{'SRC'}, $ENV{'MACH'});
     34 my (%PKGENV, %entries, @packages, $fix_perm, $fix_user, $fix_group) = ();
     35 my ($manscript) = ();
     36 
     37 sub read_pkginfo {
     38 	local ($pkg, $file) = @_;
     39 	my $lineno = 0;
     40 
     41 	open(IFH, "<$file") || return (1);
     42 
     43 	while ($line = <IFH>) {
     44 		$lineno++;
     45 
     46 		chop $line;	# eat trailing newline
     47 
     48 		# ignore comment lines 
     49 		($line =~ /^#.*$/) && next;
     50 
     51 		# ignore blank lines
     52 		($line =~ /^\s*$/) && next;
     53 
     54 		if (($line =~ /^([^=]+)="(.*)"\s*$/) ||
     55 		    ($line =~ /^([^=]+)=(.*)\s*$/)) {
     56 			$PKGENV{$1}=$2;
     57 		}
     58 	}
     59 	close (IFH);
     60 }
     61 
     62 sub read_prototype {
     63 	local ($pkg, $file, *paths) = @_;
     64 	my $lineno = 0;
     65 	my $FH;
     66 
     67 	open($FH, "<$file") || return (1);
     68 
     69 	while ($line = <$FH>) {
     70 		$lineno++;
     71 		local ($type, $class, $src, $dst, $owner, $group, $perm) = ();
     72 
     73 		chop $line;	# eat trailing newline
     74 
     75 		# ignore comment lines 
     76 		($line =~ /^#.*$/) && next;
     77 
     78 		# ignore blank lines
     79 		($line =~ /^\s*$/) && next;
     80 
     81 		# !include (file)				included file
     82 		if ($line =~ /^!include ([^\s]+)(.*)/) {
     83 			read_prototype($pkg, $1, *paths);
     84 			next;
     85 		}
     86 
     87 		# i (file)					install file
     88 		if ($line =~ /^i ([^ ]+)(.*)$/) {
     89 			my $file = $1;
     90 
     91 			# read in the pkginfo file contents
     92 			($file eq 'pkginfo') && read_pkginfo($pkg, $file);
     93 
     94 			next;
     95 		}
     96 
     97 		# b (class) (path) (mode) (owner) (group)	block
     98 		# c (class) (path) (mode) (owner) (group)	char
     99 		# d (class) (path) (mode) (owner) (group)	directory
    100 		# e (class) (path) (mode) (owner) (group)	editable
    101 		# f (class) (path) (mode) (owner) (group)	file
    102 		# p (class) (path) (mode) (owner) (group)	pipe
    103 		# x (class) (path) (mode) (owner) (group)	exclusive dir
    104 		# v (class) (path) (mode) (owner) (group)	volatile
    105 		if ($line =~ /^([bcdefpv])(\s+)([^ ]+)(\s+)([^ ]+)(\s+)(\d+)(\s+)([^ ]+)(\s+)([^ ]+)(.*)$/) {
    106 			($type, $class, $dst, $perm, $owner, $group) =
    107 				($1, $3, $5, oct($7), $9, $11);
    108 
    109 			my $entry = {
    110 				type => $type,
    111 				class => $class,
    112 				perm => $perm,
    113 				owner => $owner,
    114 				group => $group
    115 			};
    116 			$paths{$dst} = $entry;
    117 
    118 			next;
    119 		}
    120 
    121 		# l (class) (dst)=(src)				hard link
    122 		# s (class) (dst)=(src)				symlink
    123 		if ($line =~ /^([ls]) (.+) (.+)=([^\s]+)(.*)$/) {
    124 			($type, $class, $dst, $src) =
    125 				($1, $2, $3, $4);
    126 
    127 			my $entry = {
    128 				type => $type,
    129 				class => $class,
    130 				src => $src
    131 			};
    132 			$paths{$dst} = $entry;
    133 
    134 			next;
    135 		}
    136 
    137 		printf("$pkg $file:$lineno ($line): %s\n", "bad entry");
    138 	}
    139 
    140 	close ($FH);
    141 }
    142 
    143 #
    144 # Execution begins here
    145 #
    146 
    147 GetOptions('root' => \$root_dir, 'src' => \$src_dir, 'mach' => \$mach,
    148 	   'package|pkg=s' => \@packages, 'permission|perm' => \$fix_perm,
    149 	   'user' => \$fix_user, 'group' => \$fix_group,
    150 	   'manscript=s' => \$manscript);
    151 
    152 @packages = split(/,/, join(',', @packages));	# split comma seperated lists
    153 
    154 (-z $root_dir) || (-d $root_dir) || die "ROOT ($root_dir): $!";
    155 (-z $src_dir) || (-d $src_dir) || die "SRC ($src_dir): $!";
    156 my $pkg_dir = $src_dir.'/pkgdefs';
    157 (-d $pkg_dir) || die "packages ($pkg_dir: $!";
    158 
    159 # read in the package data
    160 chdir ($pkg_dir);
    161 foreach $pkg (@packages) {
    162 	my $cwd = getcwd();
    163 	chdir ($pkg);
    164 	# try the template file if there is one
    165 	my $prototype = 'prototype_'.$mach.'.tmpl';
    166 	read_prototype($pkg, $prototype, \%entries);
    167 	# try the archtecture specific one
    168 	my $prototype = 'prototype_'.$mach;
    169 	read_prototype($pkg, $prototype, \%entries);
    170 	chdir ($cwd);
    171 }
    172 
    173 # process the package entries
    174 chdir ($root_dir);
    175 @ekeys = sort keys %entries;
    176 foreach $path (@ekeys) {
    177 	my ($type) = $entries{$path}->{type};
    178 
    179 	# skip links
    180 	if ($type =~ /[ls]/) {
    181 		next;
    182 	}
    183 
    184 	if (($type =~ /[dx]/) && (! -d $path)) {
    185 		print "$path: packaging/proto directory mismatch\n";
    186 		next;
    187 	}
    188 
    189 	if (($type =~ /[efv]/) && (! -f $path)) {
    190 		print "$path: packaging/proto file mismatch\n";
    191 		next;
    192 	}
    193 
    194 	if (defined($manscript) && ($type =~ /f/) &&
    195 	    ($path =~ /man\/man.+\/.+\.\d+.*/)) {
    196 		system ("sed -f ${manscript} <$path >$path");
    197 	}
    198 
    199 	if ($fix_perm == 1) {
    200 		my $perm = $entries{$path}->{perm};
    201 		(defined($perm)) && chmod($perm, $path);
    202 	}
    203 
    204 	if (($fix_user == 1) || ($fix_group == 1)) {
    205 		my ($uid, $gid) = (-1, -1);
    206 
    207 		if ($fix_user == 1) {
    208 			($x, $x, $uid) = getpwnam($entries{$path}->{owner});
    209 		}
    210 		if ($fix_group == 1) {
    211 			($x, $x, $gid) = getgrnam($entries{$path}->{group});
    212 		}
    213 
    214 		chown($uid, $gid, $path);
    215 	}
    216 }
    217 
    218 exit 0;
    219