новые иконки в OpenBoard
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
OpenBoard/release_scripts/osx/refnum/dmgutil.pl

728 lines
18 KiB

#!/usr/bin/perl -w
#============================================================================
# NAME:
# dmgutil.pl
#
# DESCRIPTION:
# Disk image creation utility.
#
# COPYRIGHT:
# Copyright (c) 2006-2008, refNum Software
# <http://www.refnum.com/>
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# o Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# o Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# o Neither the name of refNum Software nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#============================================================================
# Imports
#----------------------------------------------------------------------------
use strict;
use Getopt::Long;
#============================================================================
# Constants
#----------------------------------------------------------------------------
my $kLogging = "-quiet";
my $Rez = "/Developer/Tools/Rez";
my $SetFile = "/Developer/Tools/SetFile";
my $kManPage = <<MANPAGE;
NAME
dmgutil -- create, adjust, and compress a distribution disk image
SYNOPSIS
dmgutil --help
dmgutil --open --volume=name file
dmgutil --set [--x=integer] [--y=integer]
[--width=integer] [--height=integer]
[--iconsize=integer] [--icon=file]
[--background=file] [--bgcol=r,g,b]
[--toolbar=boolean] file
dmgutil --close --volume=name file
DESCRIPTION
dmgutil is used to create distribution disk images, and to adjust
the Finder view settings of these volumes or their contents.
It can be invoked in three modes: open, set, and close.
OPEN MODE
Open Mode has the following options:
--open Select open mode.
--volume=name The volume name for the disk image.
file The output path for the .dmg file.
SET MODE
Set Mode has the following options:
--set Select set mode.
--x=integer The x coordinate of the item.
--y=integer The y coordinate of the item.
--width=integer The width for a Finder window.
--height=integer The height for a Finder window.
--iconsize=integer The icon size for a Finder window.
--icon=file.icns The icon to apply to the item.
--background=file The background picture for a Finder window.
--bgcol=r,g,b The background color for a Finder window.
--toolbar=boolean The toolbar state for a Finder window.
file The file or folder to be set.
CLOSE MODE
Close Mode has the following options:
--close Select close mode.
--volume=name The volume name for the disk image.
file The output path for the .dmg file.
EXAMPLES
OPEN MODE
To create a new disk image for "MyApp 1.0":
dmgutil.pl --open --volume="MyApp 1.0" myapp_1.0.dmg
SET MODE
To set the position of a file or folder:
dmgutil.pl --set --x=100 --y=100 "/Volumes/MyApp 1.0/Read Me.rtf"
dmgutil.pl --set --x=200 --y=100 "/Volumes/MyApp 1.0/MyApp.app"
To set the window size for the volume:
dmgutil.pl --set --width=300 --height=200 "/Volumes/MyApp 1.0"
To set the icon size for the volume:
dmgutil.pl --set --iconsize=128 "/Volumes/MyApp 1.0"
To set a custom icon for a volume, folder, or file:
dmgutil.pl --set --icon=volume.icns "/Volumes/MyApp 1.0"
dmgutil.pl --set --icon=folder.icns "/Volumes/MyApp 1.0/Extras"
dmgutil.pl --set --icon=readme.icns "/Volumes/MyApp 1.0/Read Me.rtf"
To set the background picture for the volume:
dmgutil.pl --set --background=flowers.jpg "/Volumes/MyApp 1.0"
To set the background color for the volume:
dmgutil.pl --set --bgcol=0,65535,0 "/Volumes/MyApp 1.0"
To hide the toolbar for the volume:
dmgutil.pl --set --toolbar=false "/Volumes/MyApp 1.0"
Multiple flags may be combined, to set all of the properties of an
item simultaneously.
CLOSE MODE
To unmount and compress the disk image created for "MyApp 1.0":
dmgutil.pl --close --volume="MyApp 1.0" myapp_1.0.dmg
VERSION
dmgutil 1.1
COPYRIGHT
Copyright (c) refNum Software http://www.refnum.com/
MANPAGE
#============================================================================
# appleScript : Execute an AppleScript.
#----------------------------------------------------------------------------
sub appleScript
{
# Retrieve our parameters
my ($theScript) = @_;
# Save the script
my $theFile = "/tmp/dmgutil_applescript.txt";
open( OUTPUT, ">$theFile") or die "Can't open $theFile for writing: $!\n";
print OUTPUT $theScript;
close(OUTPUT);
# And execute it
system("osascript", $theFile);
unlink($theFile);
}
#============================================================================
# isVolume : Is a path to the root of a volume?
#----------------------------------------------------------------------------
sub isVolume
{
# Retrieve our parameters
my ($thePath) = @_;
# Check the state
#
# After stripping out the leading /Volumes, any further slashes
# indicate we have a folder rather than a volume.
$thePath =~ s/\/Volumes\///;
my $isVolume = ($thePath =~ /.*\/.*/) ? 0 : 1;
return($isVolume);
}
#============================================================================
# setFolderState : Set the state for a folder.
#----------------------------------------------------------------------------
sub setFolderState
{
# Retrieve our parameters
my ($thePath, $iconSize, $flagToolbar, $bgImage, $bgColor) = @_;
# Initialise ourselves
my $cmdBackground = "";
my $cmdIconSize = "";
my $cmdToolbar = "";
# Prepare the background
#
# As of 10.5, the Finder refuses to manipulate files whose names start with
# a period (rdar://5582578). As such we need to use an underscore for the
# image, then make it invisible using SetFile.
if (-f $bgImage)
{
$bgImage =~ /.*\.(\w+)/;
my $dstImage = "$thePath/_Background.$1";
`cp "$bgImage" "$dstImage"`;
$cmdBackground .= "set theImage to posix file \"$dstImage\"\n";
$cmdBackground .= " set background picture of theOptions to theImage\n";
$cmdBackground .= " do shell script \"/Developer/Tools/SetFile -a V '$dstImage'\"\n";
}
elsif ($bgColor ne "")
{
$cmdBackground = "set background color of theOptions to {$bgColor} as RGB color";
}
# Prepare the icon size
if ($iconSize != 0)
{
$cmdIconSize = "set icon size of theOptions to $iconSize";
}
# Prepare the toolbar
#
# The window must be made visible in order to change the toolbar state.
if ($flagToolbar ne "")
{
$cmdToolbar = " open theWindow \n";
$cmdToolbar .= " set toolbar visible of theWindow to $flagToolbar \n";
$cmdToolbar .= " close theWindow \n";
}
# Identify the target
#
# AppleScript requires the correct nomenclature for the target item.
my $theTarget = "folder \"$thePath\"";
if (isVolume($thePath))
{
$theTarget =~ s/folder "\/Volumes\//disk "/;
}
# Set the folder state
#
# Once a change has been made, it must be flushed to disk with update.
my $theScript = "";
$theScript .= "tell application \"Finder\"\n";
$theScript .= " set theTarget to $theTarget \n";
$theScript .= " set theWindow to window of theTarget \n";
$theScript .= "\n";
$theScript .= " set current view of theWindow to icon view \n";
$theScript .= " set theOptions to icon view options of theWindow \n";
$theScript .= " set arrangement of theOptions to not arranged \n";
$theScript .= "\n";
$theScript .= " $cmdBackground\n";
$theScript .= " $cmdIconSize \n";
$theScript .= " $cmdToolbar \n";
$theScript .= "\n";
$theScript .= " update theTarget\n";
$theScript .= "end tell";
appleScript($theScript);
}
#============================================================================
# setCustomIcon : Set a custom icon.
#----------------------------------------------------------------------------
sub setCustomIcon
{
# Retrieve our parameters
my ($thePath, $theIcon) = @_;
# Validate our state
#
# We require several tools inside /Developer/Tools.
die("Setting an icon requires $Rez") if (! -e $Rez);
die("Setting an icon requires $SetFile") if (! -e $SetFile);
# Prepare the flags
#
# Prior to Mac OS X 10.4, SetFile can only set an attribute if it is
# first cleared (rdar://3738867).
my $sysVers = `uname -r`;
my $setHidden = ($sysVers =~ /^[0-7]\./) ? "vV" : "V";
my $setIcon = ($sysVers =~ /^[0-7]\./) ? "cC" : "C";
# Set a volume icon
#
# Volume custom icons are contained in a .VolumeIcon.icns file.
if (isVolume($thePath))
{
my $iconFile = "$thePath/.VolumeIcon.icns";
`cp "$theIcon" "$iconFile"`;
`$SetFile -a $setHidden "$iconFile"`;
`$SetFile -a $setIcon "$thePath"`;
}
# Set a folder icon
#
# Folder custom icons are contained in an ('icns', -16455) resource,
# placed in an invisible "Icon\r" file inside the folder.
elsif (-d $thePath)
{
my $iconFile = "$thePath/Icon\r";
my $tmpR = "/tmp/dmgutil.r";
`echo "read 'icns' (-16455) \\"$theIcon\\";\n" > $tmpR`;
`cd /tmp; $Rez dmgutil.r -append -o "$iconFile"`;
`$SetFile -a $setHidden "$iconFile"`;
`$SetFile -a $setIcon "$thePath"`;
unlink($tmpR);
}
# Set a file icon
#
# File custom icons are contained in an ('icns', -16455) resource.
else
{
my $tmpR = "/tmp/dmgutil.r";
`echo "read 'icns' (-16455) \\"$theIcon\\";\n" > $tmpR`;
`cd /tmp; $Rez dmgutil.r -append -o "$thePath"`;
`$SetFile -a $setIcon "$thePath"`;
unlink($tmpR);
}
}
#============================================================================
# setWindowPos : Set the position of a window.
#----------------------------------------------------------------------------
sub setWindowPos
{
# Retrieve our parameters
my ($thePath, $posX, $posY, $theWidth, $theHeight) = @_;
# Initialise ourselves
my $bottom = $posY + $theHeight;
my $right = $posX + $theWidth;
# Identify the target
#
# AppleScript requires the correct nomenclature for the target item.
my $theTarget = "folder \"$thePath\"";
if (isVolume($thePath))
{
$theTarget =~ s/folder "\/Volumes\//disk "/;
}
# Set the window position
#
# In theory, the "set bounds" command is all that should be necessary
# to set the bounds of a Finder window.
#
# Unfortunately, under 10.4 this will result in a window that will be
# taller than the specified size when the window is next opened.
#
# To reliably set the bounds of a window we must open the window, show
# the status bar, and set the window bounds to be 20 pixels taller (the
# height of the status bar) than necessary.
#
# The status bar can then be hidden, the window closed, and the bounds
# bounds will be the desired size when the window is next opened.
my $theScript = "";
$theScript .= "tell application \"Finder\"\n";
$theScript .= " set theTarget to $theTarget \n";
$theScript .= " set theWindow to window of theTarget \n";
$theScript .= "\n";
$theScript .= " open theWindow \n";
$theScript .= " set statusbar visible of theWindow to true \n";
$theScript .= " set bounds of theWindow to {$posX, $posY, $right, $bottom+20} \n";
$theScript .= " set statusbar visible of theWindow to false \n";
$theScript .= " close theWindow \n";
$theScript .= "\n";
$theScript .= "end tell";
appleScript($theScript);
}
#============================================================================
# setIconPos : Set the position of an icon.
#----------------------------------------------------------------------------
sub setIconPos
{
# Retrieve our parameters
my ($theFile, $posX, $posY) = @_;
# Identify the target
#
# Since the 'posix file' command follows symlinks, in order to set the
# position of a symlink (vs its target) we need to use an HFS path and
# reference it as a file rather than an alias.
my $theTarget = "alias (posix file \"$theFile\")";
if (-l $theFile)
{
$theTarget = $theFile;
$theTarget =~ s/\/Volumes\///;
$theTarget =~ s/\//:/g;
$theTarget = "file \"$theTarget\"";
}
# Set the icon position
#
# Once a change has been made, it must be flushed to disk with update.
my $theScript = "";
$theScript .= "tell application \"Finder\"\n";
$theScript .= " set theTarget to $theTarget \n";
$theScript .= "\n";
$theScript .= " set position of theTarget to {$posX, $posY} \n";
$theScript .= " update theTarget\n";
$theScript .= "end tell";
appleScript($theScript);
}
#============================================================================
# doOpen : Open a new disk image.
#----------------------------------------------------------------------------
sub doOpen
{
# Retrieve our parameters
my ($dmgFile, $volName) = @_;
# Clean up any previous image
system("rm", "-f", "$dmgFile.sparseimage");
system("rm", "-f", "$dmgFile");
# Create the image
#
# A large sparse disk image is created, which will be shrunk down
# and compressed when the disk image is finally closed.
print " creating $dmgFile\n" if ($kLogging eq "-quiet");
system("hdiutil", "create", $dmgFile,
"-volname", $volName,
"-megabytes", "1000",
"-type", "SPARSE",
"-fs", "HFS+",
$kLogging);
system("hdiutil", "mount", $kLogging, "$dmgFile.sparseimage");
}
#============================================================================
# doClose : Close a disk image.
#----------------------------------------------------------------------------
sub doClose
{
# Retrieve our parameters
my ($dmgFile, $volName) = @_;
# Bless the volume
#
# Blessing the volume ensures that the volume always opens in the current
# view, overriding the user's "Open new windows in column view" preference.
system("bless", "--openfolder", "/Volumes/$volName");
# Compress the image
#
# On 10.5, the disk image must be ejected rather than unmounted to allow
# it to be converted from a sparse image to a compressed image.
print " compressing $dmgFile\n" if ($kLogging eq "-quiet");
system("hdiutil", "eject", $kLogging, "/Volumes/$volName");
system("hdiutil", "convert", "$dmgFile.sparseimage",
"-format", "UDZO",
"-o", $dmgFile,
"-imagekey", "zlib-level=9",
$kLogging);
# Clean up
system("rm", "-f", "$dmgFile.sparseimage");
}
#============================================================================
# doSet : Set a file/folder state.
#----------------------------------------------------------------------------
sub doSet
{
# Retrieve our parameters
my ($thePath, $posX, $posY, $theWidth, $theHeight, $iconSize, $theIcon, $bgImage, $bgColor, $flagToolbar) = @_;
# Set the custom icon
if ($theIcon ne "")
{
setCustomIcon($thePath, $theIcon);
}
# Set the folder state
if ($iconSize != 0 || $bgImage ne "" || $bgColor ne "" || $flagToolbar ne "")
{
setFolderState($thePath, $iconSize, $flagToolbar, $bgImage, $bgColor);
}
# Set the position
#
# Window position must be set after applying the folder state.
if ($posX != 0 && $posY != 0)
{
if ($theWidth != 0 && $theHeight != 0)
{
setWindowPos($thePath, $posX, $posY, $theWidth, $theHeight);
}
else
{
setIconPos($thePath, $posX, $posY);
}
}
}
#============================================================================
# dmgUtil : Manipulate a disk image.
#----------------------------------------------------------------------------
sub dmgUtil
{
# Retrieve our parameters
my ($doOpen, $doClose, $doSet) = (0, 0, 0);
my ($posX, $posY, $theWidth, $theHeight, $iconSize) = (0, 0, 0, 0, 0);
my ($volName, $theIcon, $bgImage, $bgColor, $flagToolbar) = ("", "", "", "", "");
GetOptions( "--open+", => \$doOpen,
"--close+", => \$doClose,
"--set+", => \$doSet,
"--volume=s", => \$volName,
"--x=i", => \$posX,
"--y=i", => \$posY,
"--width=i", => \$theWidth,
"--height=i", => \$theHeight,
"--iconsize=i", => \$iconSize,
"--icon=s", => \$theIcon,
"--background=s", => \$bgImage,
"--bgcol=s", => \$bgColor,
"--toolbar=s", => \$flagToolbar);
my ($thePath) = @ARGV;
$thePath = "" if (!defined($thePath));
# Perform the action
if ($doOpen && $thePath ne "" && $volName ne "")
{
doOpen($thePath, $volName);
}
elsif ($doClose && $thePath ne "" && $volName ne "")
{
doClose($thePath, $volName);
}
elsif ($doSet && $thePath ne "")
{
doSet($thePath, $posX, $posY, $theWidth, $theHeight, $iconSize, $theIcon, $bgImage, $bgColor, $flagToolbar);
}
else
{
print $kManPage;
}
}
#============================================================================
# Script entry point
#----------------------------------------------------------------------------
dmgUtil();