Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
DISCONTINUED:openSUSE:11.1:Update
rembrand
rpm-rembrand.pl
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File rpm-rembrand.pl of Package rembrand
#! /usr/bin/perl -w # # rpm-rembrand.pl -- Remove Branding. # # (C) 2006 jw@suse.de # Distribute under GPL 2.0 # # A tool to find and remove openSUSE and Novell marks # from an opensuse distribution. # # Use of this tool shall be limited to the extent allowed and/or # required by the openSUSE End User License Agreement. # # One tool to rule them all, one tool to find them, one tool # to change them all and in the tempdir bind them. # # We run rpm packages (passed as parameters on the command line) against # a builtin list of images, and check where we have to replace something. # replacements are taken from the directory indicated by the environment variable # $REMBRAND_INPUT_DIR or - if missing - are created on the fly as blank white images # of the same size. # rpm packages are modified inplace. # A list of substituted files and their original md5sums are written into the file # named by $REMBRAND_ORIG_LIST or (orig_list.txt if missing.) # This list can later be used to verify that a product was indeed debranded. # # rembrand.pl # # 2006-11-19, V0.1, jw -- unpacking, checking, replacing done. # cannot re-pack RPMs yet. # 2006-11-21, V0.2, jw -- added option parser and usage. # 2006-11-22, V0.3, jw -- added loop around rpminjectfile. Ready for testing. # 2006-11-24, V0.4, jw -- added more icons. optional flag added. # emtpy.svg, empty.eps, empty.mng added as defaults. # svg, svgz, bmp, gif, mng, eps not yet supported. # 2006-11-30, V1.0, jw -- print a usage with suggested package list when # called without parameters. Small bugfixes. # svg, svgz, bmp, gif, mng, eps added. # 2006-11-30, V1.1, jw -- eps support added. # 2006-12-01, V1.1a, jw -- creating missing directories. # 2006-12-01, V1.1b, jw -- added missing mng files in kdebase3 # 2006-12-04, V1.1c, jw -- added option -a, added titlebar_decor.png # Picks RPMs from a directory, if given a directory # 2006-12-04, V1.1d, jw -- added some gnome splash and wallpapers. # Typos in matching opensuse-updater kdebas3-SuSE. # 2006-12-05, V1.2, jw -- Some white PNG's were falsly flagged optional. # Option -n added. One level of magic subdirectory # expansion is now supported. # # TODO: #------ # * kicker/ui/kmenubase.ui contains a hexadecimal representation of 'image0', # (found in kdebase3/kickoff.diff). I believe this is the 'openSUSE' button in the # kickoff menue. # This graphics gets compiled into the binary. No chance to postprocess it. # # * what about initrd? # # * modifying buildrelease is a dangerous default. It break e.g. OOo dependencies. # Do we want to do that? # use Digest::MD5; use Data::Dumper; $Data::Dumper::Terse = 1; $Data::Dumper::Sortkeys = 1; $Data::Dumper::Indent = 1; my $version = '1.2'; my $cp = '/bin/cp'; my $rpm = '/bin/rpm'; my $cpio = '/usr/bin/cpio --quiet'; my $file = '/usr/bin/file'; my $gzip = '/usr/bin/gzip -f'; my $djpeg = '/usr/bin/djpeg'; my $cjpeg = '/usr/bin/cjpeg'; my $ppmmake = '/usr/bin/ppmmake'; my $ppmtobmp = '/usr/bin/ppmtobmp 2> /dev/null'; my $ppmtogif = '/usr/bin/ppmtogif 2> /dev/null'; my $pnmtopng = '/usr/bin/pnmtopng --quiet'; my $rpminjectfile = 'rpminjectfile --quiet'; # not yet packaged? my $defaults_dir = '/usr/share/rembrand/defaults'; my $verbose = 1; my $input_dir = $ENV{REMBRAND_INPUT_DIR}; my $output_dir = $ENV{REMBRAND_OUTOUT_DIR} || "/tmp/rembrand-$$/%s"; my $md5list_file = $ENV{REMBRAND_ORIG_LIST} || 'orig_list.txt'; my $rpmout_dir = $ENV{REMBRAND_RPMOUT_DIR} || 'rpm_out'; my $dump_only = 0; my $inputlist_file; my $release_pat = "%s.mod"; my $user = $ENV{LOGNAME} || 'unknown'; my $vendor_pat = "$user (originally from %s)"; my $bgcolor = "#777777"; # a medium gray. my $skip_optional = 1; my $noexec = 0; while (defined(my $arg = shift)) { if ($arg =~ m{^-v}) { $verbose++; } elsif ($arg =~ m{^-q}) { $verbose = 0; } elsif ($arg =~ m{^--$}) { last; } elsif ($arg =~ m{^-i}) { $inputlist_file = shift; } elsif ($arg =~ m{^-d}) { $dump_only++; } elsif ($arg =~ m{^-a}) { $skip_optional = 0; } elsif ($arg =~ m{^-o}) { $md5list_file = shift; } elsif ($arg =~ m{^-I}) { $input_dir = shift; } elsif ($arg =~ m{^-O}) { $output_dir = shift; } elsif ($arg =~ m{^-R}) { $rpmout_dir = shift; } elsif ($arg =~ m{^-b}) { $bgcolor = shift; } elsif ($arg =~ m{^-n}) { $noexec++; } elsif ($arg =~ m{^-rel}) { $release_pat = shift; } elsif ($arg =~ m{^-ven}) { $vendor_pat = shift; } elsif ($arg =~ m{^-}) { usage("unknown option '$arg'"); } else { unshift @ARGV, $arg; last } } $md5list_file = "$rpmout_dir/$md5list_file" unless $md5list_file =~ m{/}; # flags:package:path # flags o=optional my @imagelist = qw( :opensuse-updater:/opt/kde3/share/icons/hicolor/*/apps/opensuse*updater.png :opensuse-updater:/opt/kde3/share/apps/opensuseupdater/pics/suse_logo.png o:opensuse-updater:/opt/kde3/share/apps/opensuseupdater/pics/suse_green.png o:opensuse-updater:/opt/kde3/share/apps/opensuseupdater/pics/suse_yellow.png o:opensuse-updater:/opt/kde3/share/apps/opensuseupdater/pics/suse_red.png o:opensuse-updater:/opt/kde3/share/apps/opensuseupdater/pics/opensuseupdater.png :kdebase3-SuSE:/opt/kde3/share/icons/*/*/apps/suse.png :kdebase3-SuSE:/opt/kde3/share/icons/*/*/apps/susehelpcenter.png :kdebase3-SuSE:/opt/kde3/share/icons/*/*/apps/kmenu.png :kdebase3-SuSE:/opt/kde3/share/icons/*/*/apps/SuSEmenu.png :kdebase3-SuSE:/opt/kde3/share/icons/*/*/apps/SuSEconf.png :kdebase3-SuSE:/opt/kde3/share/icons/*/*/apps/SuSElogo1.png :kdebase3-SuSE:/opt/kde3/share/icons/*/*/apps/suse_doc.png :kdebase3-SuSE:/opt/kde3/share/icons/*/*/apps/suse_link.png :kdebase3-SuSE:/opt/kde3/share/icons/*/*/apps/suse_sdb.png :kdebase3-SuSE:/opt/kde3/share/icons/*/*/apps/gnome-suse.png :kdebase3-SuSE:/opt/kde3/share/apps/SUSEgreeter/bg-head-800x58.png :kdebase3-SuSE:/opt/kde3/share/apps/SUSEgreeter/cr64-novell.png :kdebase3-SuSE:/opt/kde3/share/apps/SUSEgreeter/cr64-suse.png :kdebase3-SuSE:/opt/kde3/share/apps/SUSEgreeter/suse-logo.png :kdebase3-SuSE:/opt/kde3/share/apps/SUSEgreeter/misc48.png :kdebase3-SuSE:/opt/kde3/share/apps/SUSEgreeter/online_update.png :kdebase3-SuSE:/opt/kde3/share/apps/SUSEgreeter/system_update.png :kdebase3-SuSE:/opt/kde3/share/apps/SUSEgreeter/suse_doc.png :kdebase3-SuSE:/opt/kde3/share/apps/SUSEgreeter/YaST.png :kdebase3-SuSE:/opt/kde3/share/icons/hicolor/scalable/apps/SuSEmenu.svgz :kdebase3-SuSE:/opt/kde3/share/apps/ksplash/Themes/ksplashx-suse/1600x1200/spinner.png :kdebase3-SuSE:/opt/kde3/share/apps/ksplash/Themes/ksplashx-suse/Preview.png :kdebase3-SuSE:/opt/kde3/share/apps/kdm/themes/SUSE/opensuse.png :kdebase3-SuSE:/opt/kde3/share/apps/kdm/themes/SUSE/suse.png :kdebase3-SuSE:/opt/kde3/share/apps/kdm/themes/SUSE/novell.png :kdebase3-SuSE:/opt/kde3/share/apps/ksplash/Themes/ksplashx-suse/1600x1200/title.png o:kdebase3-SuSE:/opt/kde3/share/apps/kdm/themes/SUSE/Background.jpeg o:kdebase3-SuSE:/opt/kde3/share/apps/kdm/themes/SUSE/screenshot.jpg o:kdebase3-SuSE:/opt/kde3/share/apps/kdm/themes/SUSE/screenshot.png o:kdebase3-SuSE:/opt/kde3/share/apps/kicker/wallpapers/SuSE.png o:kdebase3-SuSE:/etc/opt/kde3/share/doc/HTML/en/common/suse.png o:kdebase3-SuSE:/opt/kde3/share/apps/ksplash/Themes/ksplashx-suse/1600x1200/background.png o:kdebase3-SuSE:/opt/kde3/share/apps/kthememanager/themes/SUSE_Default/SUSE_Default.preview.png o:kdebase3-SuSE:/opt/kde3/share/icons/hicolor/*/apps/suse_portal.png o:kdebase3-SuSE:/opt/kde3/share/icons/hicolor/*/apps/suse_tour.png :kdebase3:/opt/kde3/share/apps/kicker/pics/kmenu_basic.mng :kdebase3:/opt/kde3/share/apps/kicker/pics/kmenu_flipped.mng :kdebase3:/opt/kde3/share/apps/kicker/pics/kmenu_vertical.mng :gnome2-SuSE:/opt/gnome/share/dist/icons/suse-yast.png :gnome2-SuSE:/opt/gnome/share/dist/icons/susehelpcenter.png :gnome2-SuSE:/opt/gnome/share/pixmaps/suse-menustripe.png :gnome2-SuSE:/opt/gnome/share/dist/icons/SuSElogo1.png :gnome2-SuSE:/opt/gnome/share/dist/icons/SuSEmenu.png :gnome2-SuSE:/opt/gnome/share/dist/splash/dist-splash.png :gnome2-SuSE:/opt/gnome/share/dist/wallpapers/dist-Desktop_*.jpg :gnome2-SuSE:/opt/gnome/share/gdm/themes/GDM-SuSE/opensuse.png :gnome2-SuSE:/opt/gnome/share/gdm/themes/GDM-SuSE/suse.png :gnome2-SuSE:/opt/gnome/share/gdm/themes/GDM-SuSE/novell.png o:gnome2-SuSE:/opt/gnome/share/dist/icons/assis.png o:gnome2-SuSE:/opt/gnome/share/dist/icons/32x32.png o:gnome2-SuSE:/opt/gnome/share/gdm/themes/GDM-SuSE/Background.jpeg o:gnome2-SuSE:/opt/gnome/share/gdm/themes/GDM-SuSE/screenshot.png o:gnome-icon-theme:/opt/gnome/share/icons/gnome/*/apps/susehelpcenter.png o:tango-icon-theme:/opt/gnome/share/icons/Tango/*/apps/susehelpcenter.png :gnome-desktop:/opt/gnome/share/pixmaps/gnome-suse.png :compiz:/usr/share/compiz/opensuse.png :susehelp:/usr/share/susehelp/img/suse_150.png o:susehelp:/usr/share/susehelp/img/susehelpcenter.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/control-center/title-bar-right.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/wizard/title-bar-right.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/desktops/gnome.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/desktops/kde.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/misc.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/misc2.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/SuSEconf.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/susehelpcenter.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/SuSEmenu.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/bootdisk_create.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-bootfloppy.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/suse_doc.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-desktop-select.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-online_update.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-software.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-sw_single.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-sw_source.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-sysconfig.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-update.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-you_server.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/YaST.png :yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/testpage/logo.eps o:yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/suse_link.png o:yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/suse_portal.png o:yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/suse_tour.png o:yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-backup.png o:yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-bootfloppy.png o:yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-cd-creator.png o:yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-cd_update.png o:yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-checkmedia.png o:yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-dirinstall.png o:yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-xen-dirinstall.png o:yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-instserver.png o:yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-release-notes.png o:yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-restore.png o:yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/icons/*/apps/yast-x11.png o:yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/control-center/title-bar-left.png o:yast2-theme-openSUSE:/usr/share/YaST2/theme/openSUSE/wizard/title-bar-left.png :bootsplash-theme-SuSE:/etc/bootsplash/themes/SuSE/animations/spinner.mng :bootsplash-theme-SuSE:/etc/bootsplash/themes/SuSE/images/logo.mng :bootsplash-theme-SuSE:/etc/bootsplash/themes/SuSE/images/logov.mng o:bootsplash-theme-SuSE:/etc/bootsplash/themes/SuSE/images/bootsplash-*.jpg o:bootsplash-theme-SuSE:/etc/bootsplash/themes/SuSE/images/silent-*.jpg o:desktop-data-SuSE:/usr/share/wallpapers/suse*.jpg :OpenOffice_org:/usr/lib/ooo-2.0/program/openabout_suse.bmp :OpenOffice_org:/usr/lib/ooo-2.0/program/openintro_suse.bmp :gnome-icon-theme:/opt/gnome/share/icons/*/scalable/apps/im-nov.svg o:gnome-icon-theme:/opt/gnome/share/icons/*/scalable/apps/susehelpcenter.svg o:gnome-icon-theme:/opt/gnome/share/icons/*/gnome/scalable/places/novell-button.svg o:sax2-gui:/usr/share/xfine/figures/minisuse.gif o:sax2-gui:/usr/share/xfine/figures/suse.gif :kwin-decor-suse2:/opt/kde3/share/apps/kwin/pics/titlebar_decor.png ); if ($dump_only) { print join("\n", @imagelist). "\n"; exit 0; } if ($inputlist_file) { open IN, "<$inputlist_file" or die "cannot read inputlist_file $inputlist_file: $!\n"; chomp (@imagelist = <IN>); close IN; } my %orig_list; my %imagelist; for my $i (@imagelist) { if ($i =~ m{^([^:]*):([^:]+):\s*(\S+)}) { $orig_list{$2}{$3} .= $1; } } for my $p (keys %orig_list) { for my $i (keys %{$orig_list{$p}}) { push @{$imagelist{$p}}, $i; my $flags = $orig_list{$p}{$i}; $orig_list{$p}{$i} = {missing => 1}; $orig_list{$p}{$i}{flags} = $flags if $flags; } } my $rpm_filter_pat = join '|', map { "\Q$_\E" } sort keys %orig_list; $rpm_filter_pat = qr{^($rpm_filter_pat)(-\d.*)?\.rpm$}; my %subdir; ## look for directories, replace them by matching rpm files. for my $i (reverse 0..$#ARGV) { next unless -d $ARGV[$i]; opendir DIR, $ARGV[$i] or die "opendir($ARGV[$i]) failed: $!\n"; my @rpms = grep { /$rpm_filter_pat/ } readdir DIR; rewinddir DIR; my @subdirs = grep { !/^\./ and -d "$ARGV[$i]/$_" } readdir DIR; closedir DIR; # Now here comes a trick: # we allow for one level of subdirecories before taking the RPM. # If that produces any RPMs, we record the single subdirectoy name # in %subdir, so that we can maintain such a subdriectory # in $rpm_out directory. # for my $d (@subdirs) { my $dir = "$ARGV[$i]/$d"; opendir DIR, $dir or die "opendir($dir) failed: $!\n"; my @sub_rpms = map { "$d/$_" } grep { /$rpm_filter_pat/ } readdir DIR; closedir DIR; $subdir{"$ARGV[$i]/$_"} = $d for @sub_rpms; push @rpms, @sub_rpms; } splice @ARGV, $i, 1, map { "$ARGV[$i]/$_" } @rpms; } unless (scalar @ARGV) { my @pkg = sort keys %orig_list; usage("No RPM package names or no RPMs found in given directories.\nSuggested packages to process:\n\n\t*/" . join(".rpm */", @pkg) . ".rpm\n\n"); } my $new = 0; for my $rpm_file (@ARGV) { my $name = rpm_header($rpm_file, 'name'); if ($imagelist{$name}) { $new += rembrand_rpm($rpm_file, $name, $imagelist{$name}, $input_dir ? (sprintf $input_dir, $name) : undef, $subdir{$rpm_file}); } else { print "$rpm_file ($name) skipped\n" if $verbose; } } ## no empty hashes, please. my $missing; for my $p (keys %orig_list) { my $v = $orig_list{$p}; for my $k (keys %$v) { $missing->{$p}++ if $v->{$k}{missing} and ($v->{$k}{flags}||'') !~ m{o}; delete $v->{$k} unless keys %{$v->{$k}}; } } ## okay, record what we did. mkdir_pf($md5list_file); open OUT, ">$md5list_file" or die "after all, cannot write $md5list_file: $!"; print OUT Dumper \%orig_list; close OUT or die "could not write $md5list_file: $!"; printf "%d other RPMs need processing.\n", scalar(keys %$missing) if $verbose and $missing; print "Original files stored in '$output_dir'\n" if $verbose; print "$new files created in '$input_dir'\n" if $input_dir and $verbose; print "$md5list_file written.\n" if $verbose; exit 0; ################################################################# sub rembrand_rpm { my ($pkg, $name, $images, $path, $subdir) = @_; my @l = rpm_filelist($pkg); $name = $pkg unless $name; $name =~ s{[/\.]}{_}g; my $create_count = 0; my @files_o = (); my @files = (); for my $i (@$images) { my $re = "^$i\$"; $re =~ s{\*}{.*}g; # glob2re my @m = grep { /$re/ } @l; delete $orig_list{$name}{$i}{missing} if scalar @m; # delete here, in case it is a glob. if (($orig_list{$name}{$i}{flags}||'') =~ m{o}) { push @files_o, @m; } else { push @files, @m; } } push @files, @files_o unless $skip_optional; unless (scalar @files) { printf "no matching files in $pkg, expected at least %d\n", scalar @$images unless scalar(@files_o) => scalar(@$images); return; } printf "$pkg: %d files.\n", scalar(@files) if $verbose; printf "(%d optional files skipped.)\n", scalar @files_o if $verbose and $skip_optional and scalar @files_o; my $root = sprintf "$output_dir", $name; # where created files go. mkdir_pf("$root/."); unrpm($pkg, $root, \@files); for my $i (@files) { my $f = "$root/$i"; if (-f $f) { delete $orig_list{$name}{$i}{missing}; # may already be deleted delete $orig_list{$name}{$i}{listed}; # may not yet exist... $orig_list{$name}{$i}{orig_size} = -s $f; $orig_list{$name}{$i}{orig_md5sum} = file_md5sum($f); my $geom = file_imgsize($f); unlink $f or die "unlink $f failed: $!"; $create_count += file_substitute($f, $path, $i, $geom); } else { $orig_list{$name}{$i} = {missing => 1, listed => $pkg } unless $orig_list{$name}{$i}{size}; # not packaged here, let us hope it is in some other rpm, # if not, report it as missing although listed in the rpm package. } } $subdir = $subdir ? "/$subdir" : ''; my ($outname) = $pkg =~ m{([^/]+)$}; print "$pkg -> $rpmout_dir$subdir/$outname\n"; mkdir_pf("$rpmout_dir$subdir/$outname"); my $tmp_pkg_out = "$rpmout_dir$subdir/$outname-$$"; my $tmp_pkg_in = "$pkg"; my $rel = sprintf $release_pat, ($release_pat =~ m{%}) ? rpm_header($pkg, 'release') : undef; my $ven = sprintf $vendor_pat, ($vendor_pat =~ m{%}) ? rpm_header($pkg, 'vendor') : undef; die "Can not use single-quotes (') in release or vendor string.\n" if $rel =~ m{'} or $ven =~ m{'}; my $opt = ''; $opt .= "--release '$rel' " if length $rel; $opt .= "--vendor '$ven' " if length $ven; for my $i (@files) { print STDERR "." if $verbose; run_cmd("$rpminjectfile $opt '$tmp_pkg_in' '$tmp_pkg_out' '$root/$i' '$i'"); $tmp_pkg_in = "$tmp_pkg_out-in"; $opt = ''; rename "$tmp_pkg_out", "$tmp_pkg_in" or die "rename($tmp_pkg_out) failed: $!\n"; } print STDERR "\n" if $verbose; rename "$tmp_pkg_in", "$rpmout_dir/$outname" or die "rename($tmp_pkg_in) failed: $!\n"; return $create_count; } sub rpm_header { my ($file, $name) = @_; my $cmd = "$rpm -qp --qf '%{$name}' '$file'"; open RPM, "$cmd|" or die "cannot run $cmd: $!"; my $r = join '', <RPM>; close RPM or die "failed to run $cmd: $!"; die "$cmd: failed\n" unless length $r; return $r; } sub rpm_filelist { my ($file, $name) = @_; my $cmd = "$rpm -qpl '$file'"; open RPM, "$cmd|" or die "cannot run $cmd: $!"; my @r = <RPM>; chomp @r; close RPM or die "failed to run $cmd: $!"; die "$cmd: failed\n" unless scalar @r; return @r; } # extract an RPM file, optionally limited to certain files. # sub unrpm { my ($pkg, $dir, $files) = @_; my $pattern = ''; if ($files) { # we put leading dots in front of the file name list. # This is how rpm2cpio exports the names. # And we escape '?' and '*' because cpio reads shell globbing # patterns, not files. $pattern = " '." . join("' '.", @$files) . "'" if $files; $pattern =~ s{([\*\?])}{\\$1}g; } run_cmd("rpm2cpio '$pkg' | (cd $dir && $cpio -uidm$pattern)"); } sub file_md5sum { my ($file) = @_; my $md5 = Digest::MD5->new; open IN, "<$file" or die "cannot read $file:$!"; $md5->addfile(*IN); close IN; return $md5->hexdigest; } sub file_imgsize { my ($img) = @_; my $magic = `$file -b '$img'`; if ($magic =~ m{PNG image data,\s+(\d+)\s*x\s*(\d+)}) { return { t => 'png', w => $1, h => $2 }; } if ($magic =~ m{^JPEG image data}) { my $cmd = "$djpeg '$img' | head -2"; my $r = `$cmd`; if ($r =~ m{^P\d\s+(\d+)\s+(\d+)}s) { return { t => 'jpeg', w => $1, h => $2 }; } } if ($magic =~ m{^PC bitmap data,.*\s(\d+)\s*x\s*(\d+)\s*x\s*(\d+)\s*$}) { return { t => 'bmp', w => $1, h => $2 }; } if ($magic =~ m{^MNG video data,\s+(\d+)\s*x\s*(\d+)}) { return { t => 'mng', w => $1, h => $2 }; } if ($magic =~ m{^GIF image data,.*\s+(\d+)\s*x\s*(\d+)}) { return { t => 'gif', w => $1, h => $2 }; } if ($magic =~ m{^XML} and $img =~ m{\.svg}i) { return { t => 'svg', w => 1, h => 1 }; } if ($magic =~ m{^PostScript document text .* type EPS$}) { return { t => 'eps', w => 1, h => 1 }; } if ($magic =~ m{^gzip compressed} and $img =~ m{\.svgz}i) { return { t => 'svgz', w => 1, h => 1 }; } return { t => $magic }; } sub file_substitute { my ($file, $dir, $name, $img) = @_; my $cmd; my $substitute = "$dir/$name" if $dir; if ($substitute && -f $substitute) { run_cmd("$cp '$substitute' '$file'"); return 0; } print "creating blank $name $img->{w}x$img->{h}\n" if $verbose; $cmd = qq{$ppmmake "$bgcolor" $img->{w} $img->{h}}; if ($img->{t} eq 'jpeg') { $cmd .= "|$cjpeg > '$file'"; } elsif ($img->{t} eq 'png') { $cmd .= "|$pnmtopng > '$file'"; } elsif ($img->{t} eq 'gif') { $cmd .= "|$ppmtogif > '$file'"; } elsif ($img->{t} eq 'bmp') { $cmd .= "|$ppmtobmp > '$file'"; } elsif ($img->{t} eq 'mng' || $img->{t} eq 'eps' || $img->{t} eq 'svg') { $cmd = "cp '$defaults_dir/empty.$img->{t}' '$file'"; } elsif ($img->{t} eq 'svgz') { $cmd = "$gzip -c '$defaults_dir/empty.svg' > '$file'"; } else { die "cannot create unknown image type $img->{t},\nplease update file_imgsize()"; } run_cmd($cmd); if ($substitute) { mkdir_pf($substitute); run_cmd("$cp '$file' '$substitute'"); # expose the white image } return 1; } sub run_cmd { my ($cmd) = @_; print "\n$cmd\n" if $verbose > 1 or $noexec; return if $noexec; system "$cmd" and die "$cmd failed: $@ $!"; } ## ## this version of mkdir_pf handles relative and absolute paths. ## sub mkdir_pf { my ($path) = @_; my @dirs = split "/", $path; pop @dirs; # nuke trailing filename $path = ($dirs[0] eq '') ? '/' : ''; for my $d (@dirs) { $path .= "$d/"; mkdir $path, 0777 or die "mkdir $path failed: $!" unless -d $path; } return 1; # success, be mkdir compatible } ## rm_rf -- recursive file tree delete ## ## fn is a predicate, that receives a file path name as parameter. ## If fn returns zero for a file object, it is excluded from removal. ## Directories are removed unconditionally, if we can empty them first. ## ## Directories are traversed in reverse alphabetical order; ## thus dotfiles usually still exist while fn is called for other files. ## fn defaults to a true value. ## Adds write perm on the dir, if unlink/rmdir fails. ## ## Caution: No taint checks here. ## ## Does not follow symlinks for opendir; this could carry us out of the tree. ## Tries unlink after rmdir, just in case it is a weird directory symlik. ## ## rm_rf fails on very deep directory structures. It should ## - chdir downward (remembering inode numbers), ## - clear one level, ## - cd(..), check if ## - inode matches, clear one level ## - or, if it does not match redo from start. ## - done. ## sub rm_rf { my ($path, $fn, $comment) = @_; $comment ||=''; if (!-l $path and opendir DIR, $path) { my @e = grep { !/^(\.|\.\.)$/ } readdir DIR; closedir DIR; rm_rf("$path/$_") for reverse sort @e; $path = $1 if $path =~ m{^(.*)$}; print "rmdir $path\n" if $verbose > 2; unless (unlink $path or rmdir $path) { my $dir; $dir = $1 if $path =~ m{^(.*/).}; $dir = '.' unless defined $dir; chmod 0777, $dir; return if unlink $path or rmdir $path; warn "rm_rf: rmdir($path) failed: $!\n"; } } else { if (!$fn or &$fn($path)) { $path = $1 if $path =~ m{^(.*)$}; # UNTAINT. brute print "unlink $path\n" if $verbose > 2; unless (unlink $path) { my $dir; $dir = $1 if $path =~ m{^(.*/).}; $dir = '.' unless defined $dir; chmod 0777, $dir; return if unlink $path; warn "rm_rf: unlink($path) failed: $!\n"; } } else { print "rm_rf: skip $path, $comment\n" if $verbose > 2; } } } sub usage { my ($msg) = @_; $msg .= "\n" if $msg and $msg !~ m{\n$}; $msg = "Error: " . $msg if $msg; $input_dir ||= "<undefined>"; print qq{ rembrand.pl version $version $msg Usage: $0 [options] *.rpm [directory ...] Valid options are: -v Be more verbose. Default: $verbose -q Be quiet. -a Replace all files. Default: skip those marked as optional. -b bgcolor Color used for blank images. Default: "$bgcolor". -i input_list File with substitution list. Defaults to a built in list. -d Dump built in substitution list and exit. -n Do nothing. Just print the command that would execute. -o out_list Write filenames substituted to listfile. Default $md5list_file or \$REMBRAND_ORIG_LIST -I input_dir A root directory containing replacement files in their respective subdirectories. Default $input_dir or \$REMBRAND_INPUT_DIR The name of the current RPM is substituted for '%s'. -O output_dir A root directory containing the original versions of the replaced files. Default $output_dir or \$REMBRAND_OUTPUT_DIR The name of the current RPM is substituted for '%s'. -R rpmout_dir Directory, where to write the modified RPM packages. Default $rpmout_dir or \$REMBRAND_RPMOUT_DIR -rel release_nr Modify RPM header 'Release'. Default : $release_pat The release of the current RPM is substituted for '%s'. -ven vendor_str Modify RPM header 'Vendor'. Default : $vendor_pat The vendor of the current RPM is substituted for '%s'. Blank files are used for missing files below input_dir. These are also placed into input_dir. }; exit 0; }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor