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