Showing posts with label datastream. Show all posts
Showing posts with label datastream. Show all posts

Wednesday, April 30, 2008

Creating Solaris Pkg's From RPM's - Take Two

Hey there,

Special thanks to K.Jans for pointing out the problem with our original script's specificity and for his help in putting together this new version which will address some other RPM's CPIO signatures!

I don't know if we can chalk it up to my enthusiasm or transient thought process, but, of course, the rpm2pkg rpm-to-pkg conversion script that we put out a while ago doesn't perfectly translate every Linux RPM into a usable Solaris Unix datastream pkg file (Mostly because of Solaris being fussy with the pkg names). Unfortunately, there are too many vendors creating too many different versions of the same file type, and using Perl to scrape around inside their CPIO files requires a little bit of modification for every single variation. Not that I'm complaining. I love to do this stuff :)

Still, I will probably write a post on the "process" one of these days (very soon), so that anyone can do it without having to try and read what might be some cryptic scripting ;)

So, today, we have another version of our original RPM to PKG conversion script (which will work with more RPM's, but not the one's the original one worked for, and probably not a lot of other ones ;) for you. If there's any interest in a patch, I can post one (or just email it to you if you request), but it's probably easier to just use one or the other script at this point.

And, here we go again... Enjoy :)


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/usr/bin/perl

#
# rpm2pkg - creating Solaris pkg files from Linux rpm's
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

$rpm=$ARGV[0];
$tmp_dir="dir.$$";
$orig_dir=`pwd`;

mkdir("$tmp_dir");
chdir("$tmp_dir");
## FIX system("rpm2cpio ../$rpm|cpio -dim");
system("rpm2cpio ../$rpm >rpm.cpio.file");
system("cpio -d -i -m <rpm.cpio.file");
## ENDFIX
$proto_list=`find . -print|pkgproto|grep -v prototype`;
open(TMP_FILE, ">>prototype");
print TMP_FILE "i pkginfo\n";
print TMP_FILE $proto_list;
close(TMP_FILE);
# FIX @pkg_info=`strings ../$rpm`;
@pkg_info=`strings rpm.cpio.file`;
$count = 0;
foreach (@pkg_info) {
if ( $_ =~ /^Begin4/ ) {
push(@rpm_info, $_);
$count++;
} elsif ( $_ =~ /(^Copying-policy:|GPL$)/ ) {
last;
} elsif ( $count > 0 ) {
push(@rpm_info, $_);
}
}
$uname_s = `uname -s`;
$uname_r = `uname -r`;
$uname_p = `uname -p`;
$rpm_version = $rpm;
$rpm_version =~ s/\.rpm//;
chomp $uname_s;
chomp $uname_r;
chomp $uname_p;
chomp $rpm_info[1];
chomp $rpm_info[2];
chomp $rpm_info[4];
$rpm_info[1] =~ s/ * *//g;
$rpm_info[2] =~ s/ * *//g;
$rpm_info[4] =~ s/ * *//g;
$rpm_info[1] =~ s/Title://g;
$rpm_info[2] =~ s/Version://g;
open(PKGINFO, ">>pkginfo");
print PKGINFO "SUNW_PRODNAME=\"$uname_s\"\n";
print PKGINFO "SUNW_PRODVERS=\"$uname_r\"\n";
print PKGINFO "SUNW_PKGTYPE=\"usr\"\n";
print PKGINFO "PKG=\"$rpm_info[1]\"\n";
print PKGINFO "NAME=\"$rpm_info[1]\"\n";
print PKGINFO "VERSION=\"$rpm_info[2]\"\n";
print PKGINFO "VSTOCK=\"$rpm_version\"\n";
print PKGINFO "VENDOR=\"GENERIC\"\n";
print PKGINFO "ARCH=\"$uname_p\"\n";
print PKGINFO "EMAIL=\"me@xyz.com\"\n";
print PKGINFO "CATEGORY=\"application\"\n";
print PKGINFO "BASEDIR=/\n";
print PKGINFO "DESC=\"$rpm_info[4]\"\n";
print PKGINFO "PSTAMP=\"Your Name Here\"\n";
print PKGINFO "CLASSES=\"none\"\n";
close(PKGINFO);
system("pkgmk -o -b `pwd` -d /tmp");
system("pkgtrans -o -s /tmp `pwd`/${rpm_info[1]}.pkg $rpm_info[1]");
system("mv ${rpm_info[1]}.pkg ../");
system("cd ../;pwd;rm -r $tmp_dir");


, Mike

Monday, April 14, 2008

Converting Solaris Pkg's Into RPM's on Linux

Greetings,

Today, we're going to wrap up our series of posts on rpm/pkg mixing and matching, as this is about the last thing that's, technically, really worthwhile doing (I think). So far we've created the following scripts based on Linux RPM and/or Solaris Unix pkg dissection, translation and derivation:

How to unpack Solaris datastream packages without using Sun's pkg tools

How to build pkg's using spec files, like in Linux, with pkg-build

How to create RPM's from already installed RPM packages

How to create Solaris datastream pkg's from already installed pkg's

How to convert Linux RPM's into Solaris datastream pkg's

How to build Linux RPM's part 1- Initial points

How to build Linux RPM's part 2 - Starting your spec file

How to build Linux RPM's part 3 - Finalizing the spec file and building the RPM

How to build your own Solaris datastream pkg's quickly

How to build your own Solaris datastream pkg's (more theory than practice)


And, now, whether or not it will ever be practical, we've put together a script to convert Solaris pkg's to RPM's on a Linux system. If nothing else, it rounds everything out :)

The script is easy to run, and only requires one argument of the pkg file that you'll be converting. For instance, to convert the Solaris 9 m4 pkg from SunFreeware.com, you'd just type this (after unzipping the package with gunzip):

host # ./pkg2rpm m4-1.4.10-sol9-sparc-local

One special note about this Perl script: When the pkg gets converted to an RPM, it's done so with the files (listed under the "%files" specification in the "spec file") saved in the RPM with the full path to the temporary build root. This is done because "%files" won't accept relative pathnames and also won't allow you to add files that don't exist (if you, say, populate "%files" with %{prefix}/bin/whatever, etc). Instead, the "Prefix:" value is set to the "BASEDIR" value in the pkg file (e.g. /usr/local), but the "%files" listed are in their actual location during the build (otherwise we'd be forced to overwrite good Linux binaries with potentially unexecutable Solaris binaries just to build the RPM). Therefore, you'll need to install the newly created RPM with the "--relocate" switch.

So, in our example, assuming we ran the above command from "/home/user" (with the pkg file being in that directory), we would want to install the resulting RPM file by first determining where it's supposed to be relocated and then running the "rpm" command, like so:

host # ls
m4-1.4.10-sol9-sparc-local m4-1.4.10-1.x86_64.rpm
host # rpm -qif m4-1.4.10-1.x86_64.rpm|grep -i reloc
Name : m4-1.4.10-1 Relocations: /usr/local
<--- The "Relocations:" specification is where we'll be relocating "to."
host # rpm -qlf m4-1.4.10-1|head -1 <--- The trunk of this output shows us where we will be relocating "from." In this case "/home/user/SMCm4"
/home/user/SMCm4/bin/m4

Now we know where we're relocating "from" and "to," so we're ready to install (Note that you can install this RPM in your home directory, or the build directory, if you want to. The only downside is the inconvenience ;)

host # rpm --force --nodeps --relocate=/home/user/SMCm4=/usr/local -ivh m4-1.4.10-1.x86_64.rpm
Preparing... ########################################### [100%]
1:m4 ########################################### [100%]


Now, all we have to do is a quick verify and we should see that we're all set:

host # rpm -q m4-1.4.10-1
m4-1.4.10-1
host # rpm -ql m4-1.4.10-1.x86_64.rpm|head -5
/usr/local/bin/m4
/usr/local/doc/m4/AUTHORS
/usr/local/doc/m4/BACKLOG
/usr/local/doc/m4/COPYING
/usr/local/doc/m4/ChangeLog


Here's hoping we've covered every useful angle of Solaris Unix datastream pkg to Linux RPM conversion and manipulation that we possibly can. At least for the here and now ;)


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

Cheers,

#!/usr/bin/perl

#
# pkg2rpm - convert Solaris datastream pkg files to RPM's for Linux
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

if ( $#ARGV != 0 ) {
print "Usage: $0 pkg_file\n";
exit(1);
}

$pkg_name = $ARGV[0];

chomp($simple_header_check=`grep -i "package datastream" $pkg_name >/dev/null 2>&1;echo \$?`);

if ( $simple_header_check != 0 ) {
print "This doesn't appear to be a valid SVR4 DataStream pkg file. Exiting...\n";
exit;
}

open(PKG, "<$pkg_name");
@pkg_file = <PKG>;
close(PKG);

$header_end = 0;
$cpio_start = 0;
open (P_HEADERS, ">$pkg_name.headers");
foreach $line (@pkg_file) {
if ( $header_end == 0 && $line =~ /TRAILER/ && $line =~ /pkginfo/ ) {
print P_HEADERS $line;
$header_end = 1;
} elsif ( $header_end == 1 && $line =~ /pkginfo/ ) {
print P_HEADERS $line;
close(P_HEADERS);
$cpio_start = 1;
open(P_CPIO, ">$pkg_name.cpio");
} elsif ( $cpio_start == 0 ) {
print P_HEADERS $line;
} elsif ( $cpio_start == 1 ) {
print P_CPIO $line;
} else {
print STDERR "WTF?\n";
}
}
close(P_CPIO);

open(P_HEADERS, "<$pkg_name.headers");
@p_headers = <P_HEADERS>;
close(P_HEADERS);

$output_dir = 0;
$pkginfo_start = 0;
$pkginfo_seek = 0;
$pkgmap_start = 0;
foreach $p_head (@p_headers) {
if ( $output_dir eq 1 && $pkginfo_seek == 0 ) {
$output_dir = $p_head;
$output_dir =~ s/^(\w+)\W*.*$/$1/;
chomp($output_dir);
$pkginfo_seek = 1;
} elsif ( $output_dir eq 0 && $p_head =~ /datastream/i ) {
$output_dir = 1;
} elsif ( $output_dir eq 0 && $pkginfo_start == 0 ) {
next;
} elsif ( $output_dir ne 0 && $p_head =~ /pkgmap/ ) {
$pkgmap_start = 1;
$pkginfo_start = 0;
} elsif ( $pkgmap_start == 1 && $p_head =~ /pkginfo/ ) {
chomp($p_head);
push(@pkgmap, $p_head);
last;
} elsif ( $output_dir ne 0 && $p_head =~ /pkginfo.*PKG=/ ) {
$pkginfo_start = 1;
} elsif ( $output_dir ne 0 && $pkgmap_start == 1 ) {
chomp($p_head);
push(@pkgmap, $p_head);
} elsif ( $output_dir ne 0 && $pkginfo_start == 1 ) {
chomp($p_head);
push(@pkginfo, $p_head);
}
}

mkdir("$output_dir");
chdir("$output_dir");
open(PKGINFO_OUT, ">>pkginfo");
foreach $info (@pkginfo) {
print PKGINFO_OUT "$info\n";
}
close(PKGINFO_OUT);
open(PKGMAP_OUT, ">>pkgmap");
foreach $map (@pkgmap) {
print PKGMAP_OUT "$map\n";
}
close(PKGMAP_OUT);
open(RPM_SPEC_FILES, ">>${pkg_name}.specfiles");
foreach $specfile (@pkgmap) {
@specfile = split(" ", $specfile);
if ( $specfile[1] !~ /^d$/ && $specfile[2] =~ /^none$/ ) {
print RPM_SPEC_FILES "$specfile[3]\n";
}
}
close(RPM_SPEC_FILES);
system("cpio -iv <../$pkg_name.cpio >/dev/null 2>&1");
chdir("reloc");
system("tar cpf - *|(cd ../;tar xpf -)");
chdir("../");

$rpm_name=$pkg_name;
chomp($starting_point=`pwd`);
$temp_var=$$;

system("mkdir ${starting_point}/BUILD");
system("mkdir ${starting_point}/SOURCES");
system("mkdir ${starting_point}/SPECS");
system("mkdir ${starting_point}/SRPMS");
system("mkdir ${starting_point}/RPMS");
system("mkdir ${starting_point}/RPMS/noarch");
system("mkdir ${starting_point}/RPMS/`uname -i`");
system("mkdir $temp_var");
system("cd $temp_var");
open(PKGINFO_RPM, "<${starting_point}/pkginfo");
@pkginfo_rpm = <PKGINFO_RPM>;
close(PKGINFO_RPM);
($pkgrpm_name,$pkgrpm_arch,$pkgrpm_version,$pkgrpm_category,$pkgrpm_vendor,$pkgrpm_email,$pkgrpm_pstamp,$pkgrpm_basedir,$pkgrpm_classes) = @pkginfo_rpm;
$pkgrpm_name =~ s/.*=(.*)\n$/$1/;
$pkgrpm_arch =~ s/.*=(.*)\n$/$1/;
$pkgrpm_version =~ s/.*=(.*)\n$/$1/;
$pkgrpm_category =~ s/.*=(.*)\n$/$1/;
$pkgrpm_vendor =~ s/.*=(.*)\n$/$1/;
$pkgrpm_email =~ s/.*=(.*)\n$/$1/;
$pkgrpm_pstamp =~ s/.*=(.*)\n$/$1/;
$pkgrpm_basedir =~ s/.*=(.*)\n$/$1/;
$pkgrpm_classes =~ s/.*=(.*)\n$/$1/;
open(RPM_SPECIFICS, ">>$rpm_name.spec");
print RPM_SPECIFICS "%define _topdir $starting_point\n";
print RPM_SPECIFICS "Summary: $pkgrpm_name $pkgrpm_version\n";
print RPM_SPECIFICS "Name: $pkgrpm_name\n";
print RPM_SPECIFICS "Version: $pkgrpm_version\n";
print RPM_SPECIFICS "Release: 1\n";
print RPM_SPECIFICS "Copyright: $pkgrpm_pstamp\n";
print RPM_SPECIFICS "Group: $pkgrpm_category\n";
print RPM_SPECIFICS "Prefix: $pkgrpm_basedir\n";
print RPM_SPECIFICS "%description\n";
print RPM_SPECIFICS "Vendor = $pkgrpm_vendor - Email = $pkgrpm_email - Arch = $pkgrpm_arch - Classes = $pkgrpm_classes\n";
print RPM_SPECIFICS "%files\n";
open(RPM_SPEC_FILES, "<${starting_point}/$pkg_name.specfiles");
@specks = <RPM_SPEC_FILES>;
close(SPECKS);
foreach $speck (@specks) {
print RPM_SPECIFICS "${starting_point}/$speck\n";
}
close(RPM_SPECIFICS);

system("rpmbuild -bb $rpm_name.spec 2>&1|grep -v twice");
chdir("../");
system("mv -f ${starting_point}/RPMS/*/* .");
system("rm -rf $output_dir");
unlink "$pkg_name.headers";
unlink "$pkg_name.cpio";


, Mike




Monday, March 31, 2008

Minor Fix Update - Script To Unpack Solaris Datastream Pkg Files Without Sun's Pkg Utils

Hello again,

Updated 4/4/08 to output pkgproto results to a file named prototype. Originally had it writing to a file named pkgproto. Typo corrected :)

It's been a while since I started looking for a way to finish up our series of articles on RPM and pkg ripping and creating. We started out with creating our own RPM's and did pretty much everything I could think of to those poor packages, all the way through creating RPM's from already installed RPM's and converting RPM's to Solaris pkg's ;)

The only project I had left over (from that bunch) was how to extract the binary contents of Solaris Unix datastream pkg files.

Unfortunately, unlike the "rpm2cpio" command that Solaris includes, they have no regular program for converting a datastream package to an unpackable file (like a cpio or tar), unless you count all the basic pkg commands. What I was looking for was a way to extract a datastream pkg file, and get all the binary contents, without actually installing it. I got no love from Solaris, but I got some free time for myself and eventually figured it out ;)

I've included a script, below, to rip apart a Solaris datastream pkg and create a subdirectory (named the name of the pkg) into which I dump the pkginfo, pkgmap, pkgproto (which I derive from the pkgmap) and all the binary files that the pkg contains. The script, itself, is far from perfect, but if you check it out you can see, fairly easily, how you can manually pull apart a Solaris datastream pkg file and get to the binary contents that you really want (At least, I'm assuming you do - just like me ;)

Note that the version of cpio that comes with Solaris (in the SUNWcsu coreutils package) will complain about garbage bits in your cpio header, when you've clipped off the top of the pkg file. There are really only 2 garbage bits you have to delete (which you can do with vi), but I prefer to use the Gnu version of cpio which will "magically" ignore garbage bits and extract the cpio file no matter what. This version of cpio comes standard on Linux and can be downloaded (in Solaris datastream pkg format) from sunfreeware.com or (in source format, with links to all sorts of OS ports) Gnu's CPIO Download site - just in case you don't want to have to rip apart your Solaris pkg's on Linux (or don't have both OS's at your workplace).

Another strange thing is that Sun's version of cpio won't make directories, by default, that don't exist when you unpack a cpio archive (???) All I'm really saying is: Get the Gnu version - It's free and it'll save you many a gray hair ;)

I've tested today's script on multiple packages from sunfreeware.com and had great success with it working right the first time (assuming that I have Gnu's cpio). The script has broken on a few custom pkg's I've put together myself and can use a lot of work in the "additional" areas (like ensuring pre and post-install scripts get accounted for, depend files get tagged, checkinstall programs are properly extracted, etc). Still, it's a good beginning :)

Hopefully this will be of help to you, if you've been looking all over for something like this, and, almost definitely, can be the starting point for a fully functional Solaris datastream pkg ripper :)

If you want to do this manually, in short terms, just vi the pkg file you're interested in and delete everything up to the final instance of "pkginfo" in the file (after the final "pkgmap" line) and save the rest into another file, which you can manipulate with cpio. Who'd have thought it would end up being that simple? :)

Cheers,


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/usr/bin/perl

#
# rip_pkg - rip apart Solaris pkg's and get the binaries out
#
# 2008 - Mike Golvach - eggi@comcast.net
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

if ( $#ARGV != 0 ) {
print "Usage: $0 pkg_file\n";
exit(1);
}

$pkg_name = $ARGV[0];

# check and make sure it's a SVR4 DataStream Pkg

chomp($simple_header_check=`grep -i "package datastream" $pkg_name >/dev/null 2>&1;echo \$?`);

if ( $simple_header_check != 0 ) {
print "This doesn't appear to be a valid SVR4 DataStream pkg file. Exiting...\n";
exit;
}

# Memory Hogging Here - Until This Cold Quits Me And I Can Think My Way Out Of This ;)

open(PKG, "<$pkg_name");
@pkg_file = <PKG>;
close(PKG);

# Split out header information and kludgey cpio file with binary contents

$header_end = 0;
$cpio_start = 0;
open (P_HEADERS, ">$pkg_name.headers");
foreach $line (@pkg_file) {
if ( $header_end == 0 && $line =~ /TRAILER/ && $line =~ /pkginfo/ ) {
print P_HEADERS $line;
$header_end = 1;
} elsif ( $header_end == 1 && $line =~ /pkginfo/ ) {
print P_HEADERS $line;
close(P_HEADERS);
$cpio_start = 1;
open(P_CPIO, ">$pkg_name.cpio");
} elsif ( $cpio_start == 0 ) {
print P_HEADERS $line;
} elsif ( $cpio_start == 1 ) {
print P_CPIO $line;
} else {
print STDERR "WTF?\n";
}
}
close(P_CPIO);

open(P_HEADERS, "<$pkg_name.headers");
@p_headers = <P_HEADERS>;
close(P_HEADERS);

$output_dir = 0;
$pkginfo_start = 0;
$pkginfo_seek = 0;
$pkgmap_start = 0;
foreach $p_head (@p_headers) {
if ( $output_dir eq 1 && $pkginfo_seek == 0 ) {
$output_dir = $p_head;
$output_dir =~ s/^(\w+)\W*.*$/$1/;
chomp($output_dir);
$pkginfo_seek = 1;
} elsif ( $output_dir eq 0 && $p_head =~ /datastream/i ) {
$output_dir = 1;
} elsif ( $output_dir eq 0 && $pkginfo_start == 0 ) {
next;
} elsif ( $output_dir ne 0 && $p_head =~ /pkgmap/ ) {
$pkgmap_start = 1;
$pkginfo_start = 0;
} elsif ( $pkgmap_start == 1 && $p_head =~ /pkginfo/ ) {
chomp($p_head);
push(@pkgmap, $p_head);
last;
} elsif ( $output_dir ne 0 && $p_head =~ /pkginfo.*PKG=/ ) {
$pkginfo_start = 1;
} elsif ( $output_dir ne 0 && $pkgmap_start == 1 ) {
chomp($p_head);
push(@pkgmap, $p_head);
} elsif ( $output_dir ne 0 && $pkginfo_start == 1 ) {
chomp($p_head);
push(@pkginfo, $p_head);
} else {
print "WTF NOTHING MATCHED\n OD $output_dir PST $pkginfo_start PS $pkginfo_seek PMST $pkgmap_start\n$p_head\n";
}
}

mkdir("$output_dir");
chdir("$output_dir");
open(PKGINFO_OUT, ">>pkginfo");
foreach $info (@pkginfo) {
print PKGINFO_OUT "$info\n";
}
open(PKGMAP_OUT, ">>pkgmap");
foreach $map (@pkgmap) {
print PKGMAP_OUT "$map\n";
}
open(PROTO_OUT, ">>prototype");
foreach $proto (@pkgmap) {
@proto = split(" ", $proto);
print PROTO_OUT "$proto[1] $proto[2] $proto[3] $proto[4] $proto[5] $proto[6]\n";
}
system("cpio -iv <../$pkg_name.cpio >/dev/null 2>&1");
chdir("reloc");
system("tar cpf - *|(cd ../;tar xpf -)");
chdir("../");
system("rm -r reloc");
chdir("../");
unlink "$pkg_name.headers";
unlink "$pkg_name.cpio";


, Mike




Thursday, March 13, 2008

Creating Solaris Pkg Files From Already Installed Packages

pkgremk CSWtop package install output

Please click above for a larger resolution version of the sample output shown.

Hey again,

For today, I put together a shell script, in ksh, to create new Solaris pkg files from already installed packages. The motivation for this sometimes seems hard to explain since you generally don't really "need" to have packages of any software that's installed on your system. It's there already; plus you probably have the install CD or a JumpStart server sitting around somewhere on your network with the original installation packages on them, right?

Other options we've looked at in previous posts include using pkg-get to help you out in a pinch and, if you have the means, creating your own packages from source quickly and making them the long, hard old-fashioned way. For today, we're going to assume none of these avenues are available to you.

I've found that, on more than several occasions, I've been stuck on a machine which needed a package installed and been out-of-luck on both counts (No software CD's and no Network Install Server). And some packages are hard to come by, like some of the obscure, but almost absolutely necessary, Solaris system packages like SUNWexplo. Well, okay, you don't really "need" to have Sun Explorer installed on your machine either, but it's usually the first output Sun's phone support requests you send them, so let's just pretend it's essential for argument's sake ;)

With today's script (called, simply, pkgremk <--- Slight homage to pkgmk since we're remaking the packages ;) you can take any pkg that's installed on your Solaris system and create a perfectly valid datastream package for use on any other machine of suitably similar or compatible architecture and/or Solaris Unix version.

So, for example, if you found yourself in a situation where you were stuck without Sun's Explorer to gather evidence on your Solaris 9 box, you needed to run it to send to Sun support and you had it on a second Solaris 9 box, you could run pkgremk on the second box, transfer the pkg from the second box to the first, install Explorer and run it right then and there! Kind of like this (Glossing over tons of little things here ;)

host b # ./pkgremk SUNWexplo
host b # scp SUNWexplo.pkg hosta:/home/user1/.

host a # pkgadd -d /home/user1/SUNWexplo.pkg
host a # /opt/SUNWexplo/bin/explorer
<--- And the data collection begins.

It's really pretty much that simple. The only things the pkgremk script requires are that you already have the software installed on the server that you want to "remake" the package on, and that you pass it the exact package name as the only argument on the command line (you can find this information out easily by either doing an ls of the /var/sadm/pkg directory or just running pkginfo with no arguments).

I tried to take into account all parts of the pkg making process and accounted for getting all the package file names, types and ownership/permission information from /var/sadm/install/contents, as well as all the pkginfo, dependency and installation files in /var/sadm/pkg and playing with those so that you could, literally, type one quick command line and create any package you need to replicate on your machine, for whatever reason, and be able to use it just about anywhere else (On Solaris, of course - I'll be doing this for Linux soon, as well :) The finished product should be easy to move around since we use pkgtrans to make it a single file datastream format package, rather than a directory structure that you'd have to tar up and mess around with. Basically, you're going to be getting a Sun standards-compliant pkg software distribution file!

This script could be nice for insurance purposes, as well. If, for instance, you weren't sure you wanted to remove the CSWtop package. If you didn't have the pkg file you got originally, you could just create it on the fly and then re-install from that new package if you found you really did need it, like so:

host # ls -d /var/sadm/pkg/CSWtop
/var/sadm/pkg/CSWtop
host # ./pkgremk CSWtop
<--- See the picture above for the full command output
...
Done!
host # ls
CSWtop.pkg CSWtop_mk.12473.out
host # pkgrm CSWtop
...
Removal of <CSWtop> was successful.
host # top
bash: top: command not found
<--- For our example's sake, you've just realized how desperately you need top ;)
host # pkgadd -d CSWtop.pkg <--- or "pkgadd -d /full/path/to/CSWtop.pkg" if you're not in the same directory as the package.

A few keystrokes, and you're back in business :) I hope this script helps you out and you can find even more good uses for it!

Best wishes,


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/bin/ksh

#
# pkgremk - Create pkgs from existing installations on Solaris
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

trap 'cd $orig_pwd;rm -rf $tmp_dir;rm -rf ${pkgname}_mk.out;exit' 1 2 3 9 15

if [ $# -ne 1 ]
then
echo "Usage: $0 PKGname"
echo "Package must be installed on system"
exit
fi

pkgname=$1
orig_pwd=`pwd`

if [ ! -d /var/sadm/pkg/$pkgname ]
then
echo "$pkgname does not exist in the pkg repository. Exiting..."
exit
fi

tmp_dir=pkgremk.$$

if [ -d $tmp_dir ]
then
echo "Removing existing temp dir"
rm -r $tmp_dir
else
echo "Creating temp work directory..."
mkdir $tmp_dir
fi

cd $tmp_dir

echo "Copying over \"install\" directory"
(cd /var/sadm/pkg/$pkgname;tar cpf - install)|tar xpf -

echo "Copying over pkginfo file"
cp /var/sadm/pkg/$pkgname/pkginfo .

if [ -f prototype ]
then
rm prototype
fi

echo "Deriving new prototype file"
echo "Generating includes"
if [ -f pkginfo ]
then
echo "i pkginfo" >>prototype
else
echo "pkginfo disappeared. Package will not build. Exiting..."
exit
fi

cd install
ls -1d * 2>/dev/null|while read line
do
echo "i $line"
echo "i $line" >>../prototype
mv $line ../
done

cd ..

if [ -d install ]
then
echo "Removing install directory"
rm -r install
fi

grep $pkgname /var/sadm/install/contents |cut -d' ' -f 1,2,3,4,5,6|awk '{print $2 " " $3 " " $1 " " $4 " " $5 " " $6}'>>prototype

orig_basedir=`grep BASEDIR pkginfo|awk -F"=" '{print $2 "/"}'`
old_basedir=`grep BASEDIR pkginfo|awk -F"=" '{print $2 "/"}'|sed 's/\//\\\\\//g'`
if [ $orig_basedir = "//" ]
then
orig_basedir="/"
fi
if [ $old_basedir = "\/\/" ]
then
old_basedir="\/"
fi

echo "Stripping pathnames to compensate for BASEDIR=$orig_basedir"
echo "directive in pkginfo file"
this_temp=$$
sed "s/$old_basedir//" prototype >>$this_temp
mv $this_temp prototype

echo "Removing non-pkginfo/pkgmap lines from prototype"
that_temp=$$
awk '{ if ( $1 ~ /^[ifcsd]/ ) print $0}' prototype >>$that_temp
mv $that_temp prototype

echo "Creating distributable pkg from existing files as ${pkgname}.pkg"
echo "Output of pkgmk command dumping to ${pkgname}_mk.out"
/usr/bin/pkgmk -b $orig_basedir -d /tmp >${orig_pwd}/${pkgname}_mk.$$.out 2>&1
cd ..
echo "Transferring package to datastream format"
if [ -f `pwd`/${pkgname}.pkg ]
then
tmp_pid=$$
echo "Found existing `pwd`/${pkgname}.pkg file"
echo "Copying to `pwd`/${pkgname}.pkg.$tmp_pid"
mv `pwd`/${pkgname}.pkg `pwd`/${pkgname}.pkg.$tmp_pid
fi
/usr/bin/pkgtrans -s /tmp `pwd`/${pkgname}.pkg $pkgname
rm -r /tmp/$pkgname

echo "Done!"
cd $orig_pwd
rm -rf $tmp_dir



, Mike