|
Looking for an easy way to deploy Office 2004 updates through ARD? As many people have suggested, the easiest way is to repackage the update as an Apple .pkg installer by examining the installer log file. Since it installs outside the /Applications/Office 2004 directory, snapshotting from PackageMaker isn't so nice. This script makes the process a whole lot easier.
Update 2006-08-11: Adjusted the script to read the computer's HD name, rather than hard code it, for more widespread use.
I didn't really want to go through the log file line by line and copy over all of the files, so I wrote this script to parse the log file, and recreate the directory structure which you base the new PKG off of. Just run the script, giving it the two parameters it requires (path to installer log, and path to the pkg_root - which must not exist, it will create it). After it's done, open up PackageMaker, and create a package based on that pkg_root folder.
I was hoping that the log format for all VISE installers would be the same, but it does not appear to be the case. To get this script to work with other VISE installed applications, you may need to modify it.
If you make any significant/interesting changes, please
This e-mail address is being protected from spam bots, you need JavaScript enabled to view it
, or post the changes to MacEnterprise.
#!/usr/bin/perl
# MS Office Installer re-packager
#
# Created by Geoff Franks
# Hauptman-Woodward Medical Research Institute
# July 27, 2006
#
# This script takes two parameters. The first is the path to the MS
# Office Installer log file. The second is the folder which you would like to
# create your Root directory for the PKG installer to base from. This folder
# MUST NOT exist, or the script will fail.
#
# It parses the log file, regenerating the drectory structure of added files
# and directories, preserving permissions, modification times, and resource
# forks as tightly as possible. IMPORTANT: To preserve all permissions, run this
# with root level permissions.
#
# In theory this may be usable with any VISE installer log file, however that
# has not been tested. Since my installer logs were in utf-16, rather than utf-8
# I was forced to specify the encoding for the log file when it opens. If yours
# is not in utf-16, change the $CHARSET variable.
#
# Other than that, the script should work for pretty any 10.4/Office 2004
# environment. Once it's finished, double check the directory structure it
# created, and create a package through PackageMaker.
#
# Update: I have looked at the installer logs for Stuffit 9.0. The format for
# this log file was a bit different. Not drastically, but significant enough to
# be incompatible with this script without modification.
#
use strict;
#Set up some globalish variables- charset for the encoding on the log file
#srclog for the log file, root dir for the base directory, and loglines for data
my $CHARSET = "utf-16";
my $SRCLOG;
my $ROOTDIR;
my @loglines;
# Variables to define what the file and directory lines are, for easier porting
# HDNAME is the name of the root HD, varies in most cases, this will affect
# installer log parsing, so grab the name from the computer you're running
# it on.
my $HDNAME = `/usr/sbin/diskutil info / | grep "Volume Name:" | cut -d ":" -f2`;
$HDNAME =~ s/^\s+//;
$HDNAME =~ s/\n//;
my $FILELINE = "Installed $HDNAME:";
my $DIRLINE = "Created the Folder: $HDNAME:";
#function for warn about usage and exit
sub usage{
warn "Usage: officepkgr <path to update log file> <path of pkg root>\n";
exit(1);
}
#function for checking arguments
sub getarguments{
#we need arguments
if($#ARGV == -1){
&usage;
exit(0);
#and only 2
}elsif($#ARGV != 1){
&usage;
exit(0);
}
#so if we have them, set the two args
$SRCLOG = shift @ARGV;
$ROOTDIR= shift @ARGV;
#if the log file doesn't exist, quit now.
unless(-e $SRCLOG){
&usage;
exit(0);
}
}
#first line actually run- check the arguments.
&getarguments;
#create the root directory with default perms of root:admin, 1775 (sticky bit)
mkdir($ROOTDIR) or die ("Could not create $ROOTDIR");
chown "root","admin", $ROOTDIR;
chmod oct("1775"), $ROOTDIR;
#open the log file, and read it in
open FILE , "<:encoding($CHARSET)", $SRCLOG or die ("Could not open log file $SRCLOG");
my $logdata = <FILE>;
#swap any mac line endings to unix line endings
$logdata =~ s/\r/\n/g;
#and split the log file into an array of lines to loop through
@loglines = split "\n", $logdata;
close FILE;
#loop through the lines
for my $line (@loglines)
{
#any matches to this unless statement are lines you do not want parsed
# if the script dies due to meaningless filler info like the date, install
# mesages - anything not referring to a file, add them here to be ignored
unless (
$line =~ /Beginning installation/ ||
$line =~ /^Office 2004 11\.[0-9]+\.[0-9]+ Update/ ||
$line =~ /^Type of Install/ ||
$line =~ /^The installation is complete/ ||
$line =~ /^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)/ )
{
# set up some variables for use within the loop- type for file type, file
# for file path
my $type;
my $file;
#check to see if it's a file
if ($line =~ /^$FILELINE(.*)/)
{
#set that it's a file, and save the path.
$type = "file";
$file = "$1";
# print "File: $file\n";
}
else
{
#otherwise, check to see if it's a directory, and save the path
if ($line =~ /^$DIRLINE(.*)/)
{
$type = "dir";
$file = "$1";
# print "Dir: $file\n";
}
else
{
#otherwise, I don't know what the line means, so quit and say what
#the line was
print "Unknown line: $line\n";
die("Exiting prematurely...");
}
}
#change any :s to /s
$file =~ s/:/\//g;
#strip any trailing slashes
$file =~ s/\/$//;
#get an array of directories leading up to the file
my @dirs = split "/" , $file;
my $dir;
my $count = scalar(@dirs);
#loop through all but the file/directory name itself
for (my $i = 0; $i < $count - 1; $i++)
{
#grab the next directory in the array
$dir .= shift @dirs;
$dir .= "/";
#grab file attributes on the real directory
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
$blksize,$blocks) = stat("/$dir");
#translate the mode/type to just the permissions mode
$mode = sprintf("%04o",$mode & 07777);
#if the directory doesn't exist in the recreated structure
unless (-d "$ROOTDIR/$dir")
{
#make it, setting ownership and perms to the original's
#print "Mode: $mode\n";
mkdir("$ROOTDIR/$dir");
chown($uid,$gid,"$ROOTDIR/$dir");
chmod oct($mode), "$ROOTDIR/$dir";
}
}
#by the time we get here, we know the parent directories exist
if ( $type eq "file")
{
#so it's time to copy the file if it's a file
print "Copying $file\n";
system "cp -p \"/$file\" \"$ROOTDIR/$file\"";
}
else
{
#or if it's a directory,
if ( $type eq "dir")
{
#recreate it with the original perms/ownership
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
$blksize,$blocks) = stat("/$file");
print "Creating $file\n";
$mode = sprintf("%o",$mode & 07777);
mkdir("$ROOTDIR/$file");
chown($uid,$gid,"$ROOTDIR/$file");
chmod oct($mode), "$ROOTDIR/$file";
}
else
{
die( "How the heck did we get here?\n");
}
}
}
}
#after it loops through the log file, that's pretty much it, so it exits.
|