iesd 1.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.md +9 -0
- data/README.md +4 -0
- data/bin/iesd +131 -0
- data/iesd.gemspec +19 -0
- data/lib/iesd.rb +13 -0
- data/lib/iesd/InstallESD.rb +35 -0
- data/lib/iesd/InstallESD/BaseSystem.dmg.rb +56 -0
- data/lib/iesd/InstallESD/Extensions.rb +78 -0
- data/lib/iesd/InstallESD/InstallESD.dmg.rb +105 -0
- data/lib/iesd/InstallESD/InstallOSX.app.rb +23 -0
- data/lib/iesd/InstallESD/InstallOSX.dmg.rb +11 -0
- data/lib/iesd/InstallESD/Packages.rb +7 -0
- data/lib/iesd/InstallESD/Packages/AdditionalEssentials.pkg.rb +0 -0
- data/lib/iesd/InstallESD/Packages/AdditionalSpeechVoices.pkg.rb +0 -0
- data/lib/iesd/InstallESD/Packages/AsianLanguagesSupport.pkg.rb +0 -0
- data/lib/iesd/InstallESD/Packages/BSD.pkg.rb +0 -0
- data/lib/iesd/InstallESD/Packages/BaseSystemBinaries.pkg.rb +26 -0
- data/lib/iesd/InstallESD/Packages/BaseSystemResources.pkg.rb +0 -0
- data/lib/iesd/InstallESD/Packages/Essentials.pkg.rb +0 -0
- data/lib/iesd/InstallESD/Packages/JavaEssentials.pkg.rb +0 -0
- data/lib/iesd/InstallESD/Packages/JavaTools.pkg.rb +0 -0
- data/lib/iesd/InstallESD/Packages/MediaFiles.pkg.rb +0 -0
- data/lib/iesd/InstallESD/Packages/OSInstall.mpkg.rb +6 -0
- data/lib/iesd/InstallESD/Packages/OSInstall.pkg.rb +25 -0
- data/lib/iesd/InstallESD/Packages/OSUpgrade.pkg.rb +0 -0
- data/lib/iesd/InstallESD/Packages/OxfordDictionaries.pkg.rb +0 -0
- data/lib/iesd/InstallESD/Packages/X11redirect.pkg.rb +0 -0
- data/lib/iesd/utility.rb +18 -0
- data/lib/iesd/utility/hdiutil.rb +98 -0
- data/lib/iesd/utility/pkgutil.rb +69 -0
- data/lib/iesd/utility/tty.rb +81 -0
- metadata +75 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7455d51c65b772db9a7bcc132f5ab41e2f4ca4e6
|
4
|
+
data.tar.gz: dfddd2efdae889c72e46382e95d865495f696311
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2668dbf90eb8aace836c99fdf24741c6a19051b4baeb010029367703cac774af9d1bd9630525f442af03887592d4a61f73f8899e054edfb49f3c154d06ecc561
|
7
|
+
data.tar.gz: 853b8ac55165fbd4959d38309c301cf8d9522e99bcb569b8f11d50654f98ba007a70f0c4aee8454df95296f56e6ef3417975fc7e06099427d7e4986a3945b626
|
data/LICENSE.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
Copyright (c) 2013, なつき
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
5
|
+
|
6
|
+
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
7
|
+
* 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.
|
8
|
+
|
9
|
+
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 HOLDER 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.
|
data/README.md
ADDED
data/bin/iesd
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
STDOUT.sync = true
|
3
|
+
|
4
|
+
$:.unshift File.join(File.dirname(__FILE__), *%w{ .. lib })
|
5
|
+
|
6
|
+
require 'optparse'
|
7
|
+
require 'iesd'
|
8
|
+
|
9
|
+
begin
|
10
|
+
raise "This tool is only supported on OS X." unless Kernel.system('[ "$(/usr/bin/uname)" = "Darwin" ]')
|
11
|
+
rescue Exception => e
|
12
|
+
opoo e.message
|
13
|
+
abort
|
14
|
+
end
|
15
|
+
|
16
|
+
options = {
|
17
|
+
:input => nil,
|
18
|
+
:output => nil,
|
19
|
+
:type => nil,
|
20
|
+
:extensions => {
|
21
|
+
:install => [],
|
22
|
+
:remove => [],
|
23
|
+
:kextcache => nil,
|
24
|
+
:postinstall => true
|
25
|
+
},
|
26
|
+
:mach_kernel => nil
|
27
|
+
}
|
28
|
+
|
29
|
+
optparse = OptionParser.new do |opts|
|
30
|
+
opts.banner = "Usage: #{File.basename $0} -i <inputfile> -o <outputfile> [options]"
|
31
|
+
|
32
|
+
opts.separator ""
|
33
|
+
opts.separator "Specific options:"
|
34
|
+
|
35
|
+
opts.on("-i", "--input inputfile",
|
36
|
+
"Specify inputfile (dmg or app)") do |input|
|
37
|
+
options[:input] = File.absolute_path input
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on("-o", "--output outputfile",
|
41
|
+
"Specify outputfile (dmg)") do |output|
|
42
|
+
output << ".dmg" if File.extname(output).downcase != ".dmg"
|
43
|
+
options[:output] = File.absolute_path output
|
44
|
+
end
|
45
|
+
|
46
|
+
opts.on("-t", "--type type", [:BaseSystem, :InstallESD],
|
47
|
+
"Specify type (BaseSystem, InstallESD)") do |type|
|
48
|
+
case type
|
49
|
+
when :BaseSystem
|
50
|
+
options[:type] = :root
|
51
|
+
when :InstallESD
|
52
|
+
options[:type] = :container
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
opts.on("--install-kexts x.kext,y.kext,z.kext", Array, "Specify list of kexts to install") do |list|
|
57
|
+
options[:extensions][:install] = list.map { |kext| File.absolute_path kext }
|
58
|
+
end
|
59
|
+
|
60
|
+
opts.on("--remove-kexts x.kext,y.kext,z.kext", Array, "Specify list of kexts to remove") do |list|
|
61
|
+
options[:extensions][:remove] = list
|
62
|
+
end
|
63
|
+
|
64
|
+
opts.on("--[no-]kextcache", "Rebuild kernelcache") do |c|
|
65
|
+
options[:extensions][:kextcache] = c
|
66
|
+
end
|
67
|
+
|
68
|
+
opts.on("--[no-]postinstall-kexts", "Patch OSInstall.pkg for post install") do |p|
|
69
|
+
options[:extensions][:postinstall] = p
|
70
|
+
end
|
71
|
+
|
72
|
+
opts.on("--[no-]kernel", "Use mach_kernel as fallback to kextcache") do |k|
|
73
|
+
options[:mach_kernel] = k
|
74
|
+
end
|
75
|
+
|
76
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
|
77
|
+
ENV['VERBOSE'] = '1'
|
78
|
+
end
|
79
|
+
|
80
|
+
opts.separator ""
|
81
|
+
opts.separator "Common options:"
|
82
|
+
|
83
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
84
|
+
puts opts
|
85
|
+
exit
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
begin
|
90
|
+
optparse.parse!
|
91
|
+
missing_options = [:input, :output].select { |param| options[param].nil? }
|
92
|
+
raise "missing options: #{(missing_options.map { |param| "-#{param.to_s[0]}" }).join(', ')}" unless missing_options.empty?
|
93
|
+
rescue OptionParser::InvalidOption, OptionParser::MissingArgument
|
94
|
+
onoe $!.to_s
|
95
|
+
puts optparse
|
96
|
+
abort
|
97
|
+
rescue SystemExit
|
98
|
+
raise
|
99
|
+
rescue Exception => e
|
100
|
+
onoe e.message
|
101
|
+
puts optparse
|
102
|
+
abort
|
103
|
+
end
|
104
|
+
|
105
|
+
begin
|
106
|
+
raise "input file does not exist" unless File.exist? options[:input]
|
107
|
+
raise "output file already exists" if File.exist? options[:output]
|
108
|
+
options[:extensions][:remove].select { |kext|
|
109
|
+
if File.extname(kext) == ".kext"
|
110
|
+
true
|
111
|
+
else
|
112
|
+
opoo "invalid kext: #{kext}"
|
113
|
+
false
|
114
|
+
end
|
115
|
+
}
|
116
|
+
options[:extensions][:install].each { |kext|
|
117
|
+
raise "invalid kext: #{kext}" unless File.exist? File.join(kext, *%w{ Contents MacOS }, File.basename(kext, ".kext"))
|
118
|
+
}
|
119
|
+
if (iesd = IESD.new options[:input])
|
120
|
+
iesd.export options
|
121
|
+
puts "\xF0\x9F\x8D\xBA #{options[:output]}"
|
122
|
+
else
|
123
|
+
raise "invalid input file"
|
124
|
+
end
|
125
|
+
rescue SignalException => e
|
126
|
+
abort
|
127
|
+
rescue StandardError => e
|
128
|
+
onoe e.message
|
129
|
+
abort
|
130
|
+
end
|
131
|
+
|
data/iesd.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.required_ruby_version = ">= 1.9.0"
|
3
|
+
|
4
|
+
s.name = "iesd"
|
5
|
+
s.version = "1.0.0.pre"
|
6
|
+
s.summary = "Customize OS X InstallESD."
|
7
|
+
s.description = "Modify Extensions, Kextcache and Packages on InstallESD."
|
8
|
+
s.authors = "なつき"
|
9
|
+
s.email = "i@ntk.me"
|
10
|
+
s.homepage = "https://github.com/ntkme/iesd"
|
11
|
+
s.license = "BSD-2-Clause"
|
12
|
+
|
13
|
+
s.executables = ["iesd"]
|
14
|
+
s.files = %w{
|
15
|
+
README.md
|
16
|
+
LICENSE.md
|
17
|
+
iesd.gemspec
|
18
|
+
} + Dir["lib/**/*.rb"] + Dir["bin/iesd.rb"]
|
19
|
+
end
|
data/lib/iesd.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require "tmpdir"
|
4
|
+
|
5
|
+
require "iesd/utility"
|
6
|
+
require "iesd/InstallESD"
|
7
|
+
require "iesd/InstallESD/Extensions"
|
8
|
+
require "iesd/InstallESD/Packages"
|
9
|
+
require "iesd/InstallESD/BaseSystem.dmg"
|
10
|
+
require "iesd/InstallESD/InstallESD.dmg"
|
11
|
+
require "iesd/InstallESD/InstallOSX.app"
|
12
|
+
require "iesd/InstallESD/InstallOSX.dmg"
|
13
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module IESD
|
2
|
+
def self.new url
|
3
|
+
File.extname(url).downcase == ".app" ? IESD::APP.new(url) : IESD::DMG.new(url)
|
4
|
+
end
|
5
|
+
|
6
|
+
class APP
|
7
|
+
def self.new url
|
8
|
+
IESD::APP::InstallOSX.validate(url) ? IESD::APP::InstallOSX.new(url) : nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class DMG
|
13
|
+
def self.new url
|
14
|
+
i = nil
|
15
|
+
if HDIUtil::validate url
|
16
|
+
HDIUtil::DMG.new(url).show { |mountpoint|
|
17
|
+
oh1 "Detecting #{url}"
|
18
|
+
case
|
19
|
+
when (File.exist? File.join(mountpoint, *%w{ .IABootFiles }))
|
20
|
+
i = IESD::DMG::InstallOSX.new url
|
21
|
+
when (File.exist? File.join(mountpoint, *%w{ BaseSystem.dmg }))
|
22
|
+
i = IESD::DMG::InstallESD.new url
|
23
|
+
when (File.exist? File.join(mountpoint, *%w{ System Installation }))
|
24
|
+
i = IESD::DMG::BaseSystem.new url
|
25
|
+
else
|
26
|
+
raise "unknown type"
|
27
|
+
end
|
28
|
+
puts "Detected: #{i.class.name.split("::").last}"
|
29
|
+
}
|
30
|
+
end
|
31
|
+
i
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module IESD
|
2
|
+
class DMG
|
3
|
+
class BaseSystem < HDIUtil::DMG
|
4
|
+
PACKAGES = %w{ System Installation Packages }
|
5
|
+
|
6
|
+
def export options, add_sectors = 0
|
7
|
+
case options[:type]
|
8
|
+
when :root, nil
|
9
|
+
Dir.mktmpdir { |tmp|
|
10
|
+
HDIUtil.write(@url, (tmpfile = File.join(tmp, File.basename(@url))), add_sectors) { |volume_root|
|
11
|
+
options[:extensions][:up_to_date] = (options[:extensions][:remove].empty? and options[:extensions][:install].empty?)
|
12
|
+
options[:mach_kernel] = File.exist? File.join(volume_root, "mach_kernel") if options[:mach_kernel].nil?
|
13
|
+
|
14
|
+
yield volume_root if block_given?
|
15
|
+
|
16
|
+
pre_update volume_root, options
|
17
|
+
|
18
|
+
IESD::DMG::BaseSystem::Extensions.new(volume_root).update options[:extensions]
|
19
|
+
|
20
|
+
post_update volume_root, options
|
21
|
+
}
|
22
|
+
system(Utility::MV, tmpfile, options[:output])
|
23
|
+
}
|
24
|
+
else
|
25
|
+
raise "invalid output type"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def pre_update volume_root, options
|
32
|
+
if !File.exist? (mach_kernel = File.join(volume_root, "mach_kernel")) and (options[:mach_kernel] or !options[:extensions][:up_to_date])
|
33
|
+
IESD::Packages::BaseSystemBinaries.new(File.join(volume_root, *PACKAGES, "BaseSystemBinaries.pkg")).extract_mach_kernel mach_kernel
|
34
|
+
system(Utility::CHFLAGS, "hidden", mach_kernel)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def post_update volume_root, options
|
39
|
+
if !options[:extensions][:up_to_date] and options[:extensions][:postinstall]
|
40
|
+
IESD::Packages::OSInstall.new(File.join(volume_root, *PACKAGES, "OSInstall.pkg")).postinstall_extensions options[:extensions]
|
41
|
+
end
|
42
|
+
if !options[:mach_kernel] and File.exist? (mach_kernel = File.join(volume_root, "mach_kernel"))
|
43
|
+
system(Utility::RM, mach_kernel)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Extensions < IESD::Extensions
|
48
|
+
def update extensions
|
49
|
+
remove extensions[:remove]
|
50
|
+
install extensions[:install]
|
51
|
+
@kextcache.update if extensions[:kextcache] or (extensions[:kextcache].nil? and !extensions[:up_to_date])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module IESD
|
2
|
+
class Extensions
|
3
|
+
EXTENSIONS = %w{ System Library Extensions }
|
4
|
+
|
5
|
+
attr_reader :volume_root, :url, :kextcache
|
6
|
+
|
7
|
+
def initialize volume_root
|
8
|
+
@volume_root = volume_root
|
9
|
+
@url = File.join @volume_root, *EXTENSIONS
|
10
|
+
@kextcache = IESD::Extensions::KextCache.new self
|
11
|
+
end
|
12
|
+
|
13
|
+
def remove kexts
|
14
|
+
if !kexts.empty?
|
15
|
+
oh1 "Removing Extensions"
|
16
|
+
kexts.each { |kext|
|
17
|
+
system(Utility::RM, "-rf", File.join(@url, kext))
|
18
|
+
puts "Removed: #{File.join(@url, kext)}"
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def install kexts
|
24
|
+
if !kexts.empty?
|
25
|
+
oh1 "Installing Extensions"
|
26
|
+
kexts.each { |kext|
|
27
|
+
system(Utility::DITTO, kext, File.join(@url, File.basename(kext)))
|
28
|
+
puts "Installed: #{File.join(@url, File.basename(kext))}"
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class KextCache
|
34
|
+
KEXTCACHE_DEFAULT_OPTIONS = %w{ -v 0 -no-authentication }
|
35
|
+
KERNELCACHE = %w{ System Library Caches com.apple.kext.caches Startup kernelcache }
|
36
|
+
MKEXT = %w{ System Library Caches com.apple.kext.caches Startup Extensions.mkext }
|
37
|
+
MKEXT_PPC = %w{ System Library Extensions.mkext }
|
38
|
+
|
39
|
+
attr_reader :volume_root, :url, :type
|
40
|
+
|
41
|
+
def initialize extensions
|
42
|
+
@extensions = extensions
|
43
|
+
@volume_root = extensions.volume_root
|
44
|
+
|
45
|
+
case
|
46
|
+
when (File.exist? (@url = File.join(@volume_root, *KERNELCACHE)))
|
47
|
+
@type = :kernelcache
|
48
|
+
when (File.exist? (@url = File.join(@volume_root, *MKEXT)))
|
49
|
+
@type = :mkext
|
50
|
+
when (File.exist? (@url = File.join(@volume_root, *MKEXT_PPC)))
|
51
|
+
@type = :mkext_ppc
|
52
|
+
else
|
53
|
+
@url = nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def update
|
58
|
+
if File.exist? (mach_kernel = File.join(@volume_root, "mach_kernel"))
|
59
|
+
oh1 "Updating Kextcache"
|
60
|
+
case @type
|
61
|
+
when :kernelcache
|
62
|
+
system(Utility::KEXTCACHE, *KEXTCACHE_DEFAULT_OPTIONS, "-prelinked-kernel", @url, "-kernel", mach_kernel, "-volume-root", @volume_root, "--", @extensions.url)
|
63
|
+
when :mkext
|
64
|
+
system(Utility::KEXTCACHE, *KEXTCACHE_DEFAULT_OPTIONS, *%w{ -a i386 -a x86_64 }, "-mkext", @url, "-kernel", mach_kernel, "-volume-root", @volume_root, "--", @extensions.url)
|
65
|
+
if File.exist? (mkext_ppc = File.join(@volume_root, *MKEXT_PPC))
|
66
|
+
system(Utility::DITTO, @url, mkext_ppc)
|
67
|
+
end
|
68
|
+
when :mkext_ppc
|
69
|
+
system(Utility::DITTO, *KEXTCACHE_DEFAULT_OPTIONS, *%w{ -a ppc -a i386 }, "-mkext", @url, "-kernel", mach_kernel, "-volume-root", @volume_root, "--", extensions.url)
|
70
|
+
end
|
71
|
+
puts "Updated: #{@url}"
|
72
|
+
else
|
73
|
+
opoo "kextcache aborted because mach_kernel is not available"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module IESD
|
2
|
+
class DMG
|
3
|
+
class InstallESD < HDIUtil::DMG
|
4
|
+
PACKAGES = %w{ Packages }
|
5
|
+
|
6
|
+
def export options
|
7
|
+
case options[:type]
|
8
|
+
when :root
|
9
|
+
resize_limits = `#{Utility::HDIUTIL} resize -limits "#{@url}"`.chomp.split.map { |s| s.to_i }
|
10
|
+
show { |installesd|
|
11
|
+
IESD::DMG::BaseSystem.new(File.join(installesd, "BaseSystem.dmg")).export(options, resize_limits[0]) { |basesystem|
|
12
|
+
installesd_packages = File.join installesd, PACKAGES
|
13
|
+
basesystem_packages = File.join basesystem, *IESD::DMG::BaseSystem::PACKAGES
|
14
|
+
oh1 "Copying #{installesd_packages}"
|
15
|
+
system(Utility::RM, basesystem_packages)
|
16
|
+
system(Utility::DITTO, installesd_packages, basesystem_packages)
|
17
|
+
puts "Copied: #{basesystem_packages}"
|
18
|
+
|
19
|
+
installesd_mach_kernel = File.join installesd, "mach_kernel"
|
20
|
+
basesystem_mach_kernel = File.join basesystem, "mach_kernel"
|
21
|
+
if File.exist? installesd_mach_kernel
|
22
|
+
oh1 "Copying #{installesd_mach_kernel}"
|
23
|
+
system(Utility::DITTO, installesd_mach_kernel, basesystem_mach_kernel)
|
24
|
+
system(Utility::CHFLAGS, "hidden", basesystem_mach_kernel)
|
25
|
+
puts "Copied: #{basesystem_mach_kernel}"
|
26
|
+
end
|
27
|
+
}
|
28
|
+
}
|
29
|
+
when :container, nil
|
30
|
+
Dir.mktmpdir { |tmp|
|
31
|
+
HDIUtil.write(@url, (tmpfile = File.join(tmp, File.basename(@url)))) { |installesd|
|
32
|
+
options[:extensions][:up_to_date] = (options[:extensions][:remove].empty? and options[:extensions][:install].empty?)
|
33
|
+
options[:mach_kernel] = File.exist? File.join(installesd, "mach_kernel") if options[:mach_kernel].nil?
|
34
|
+
|
35
|
+
yield installesd if block_given?
|
36
|
+
|
37
|
+
pre_update installesd, options
|
38
|
+
|
39
|
+
basesystem_options = options.clone
|
40
|
+
basesystem_options[:input] = basesystem_options[:output] = File.join(installesd, "BaseSystem.dmg")
|
41
|
+
basesystem_flags = `#{Utility::LS} -lO "#{basesystem_options[:input]}"`.split[4]
|
42
|
+
IESD::DMG::InstallESD::BaseSystem.new(File.join(basesystem_options[:input])).export(basesystem_options) { |basesystem|
|
43
|
+
installesd_mach_kernel = File.join installesd, "mach_kernel"
|
44
|
+
basesystem_mach_kernel = File.join basesystem, "mach_kernel"
|
45
|
+
if File.exist? installesd_mach_kernel
|
46
|
+
oh1 "Copying #{installesd_mach_kernel}"
|
47
|
+
system(Utility::DITTO, installesd_mach_kernel, basesystem_mach_kernel)
|
48
|
+
system(Utility::CHFLAGS, "hidden", basesystem_mach_kernel)
|
49
|
+
puts "Copied: #{basesystem_mach_kernel}"
|
50
|
+
end
|
51
|
+
}
|
52
|
+
system(Utility::CHFLAGS, basesystem_flags, basesystem_options[:output]) unless basesystem_flags == "-"
|
53
|
+
|
54
|
+
if File.exist? (kextcache = File.join(installesd, "kernelcache"))
|
55
|
+
IESD::DMG::InstallESD::BaseSystem.new(File.join(basesystem_options[:output])).show { |basesystem|
|
56
|
+
oh1 "Updating kextcache"
|
57
|
+
system(Utility::DITTO, IESD::DMG::BaseSystem::Extensions.new(basesystem).kextcache.url, kextcache)
|
58
|
+
system(Utility::CHFLAGS, "hidden", kextcache)
|
59
|
+
puts "Updated: #{kextcache}"
|
60
|
+
}
|
61
|
+
else
|
62
|
+
raise "invalid output type"
|
63
|
+
end
|
64
|
+
|
65
|
+
post_update installesd, options
|
66
|
+
}
|
67
|
+
system(Utility::MV, tmpfile, options[:output])
|
68
|
+
}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def pre_update volume_root, options
|
75
|
+
if !File.exist? (mach_kernel = File.join(volume_root, "mach_kernel")) and (options[:mach_kernel] or !options[:extensions][:up_to_date])
|
76
|
+
IESD::Packages::BaseSystemBinaries.new(File.join(volume_root, *PACKAGES, "BaseSystemBinaries.pkg")).extract_mach_kernel mach_kernel
|
77
|
+
system(Utility::CHFLAGS, "hidden", mach_kernel)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def post_update volume_root, options
|
82
|
+
if !options[:extensions][:up_to_date] and options[:extensions][:postinstall]
|
83
|
+
IESD::Packages::OSInstall.new(File.join(volume_root, *PACKAGES, "OSInstall.pkg")).postinstall_extensions options[:extensions]
|
84
|
+
end
|
85
|
+
if !options[:mach_kernel] and File.exist? (mach_kernel = File.join(volume_root, "mach_kernel"))
|
86
|
+
system(Utility::RM, mach_kernel)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class BaseSystem < IESD::DMG::BaseSystem
|
91
|
+
private
|
92
|
+
|
93
|
+
def pre_update volume_root, options
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
def post_update volume_root, options
|
98
|
+
if File.exist? (mach_kernel = File.join(volume_root, "mach_kernel"))
|
99
|
+
system(Utility::RM, mach_kernel)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module IESD
|
2
|
+
class APP
|
3
|
+
class InstallOSX
|
4
|
+
INSTALLESD_DMG = %w{Contents SharedSupport InstallESD.dmg}
|
5
|
+
|
6
|
+
def self.validate url
|
7
|
+
File.exist? File.join(url, *INSTALLESD_DMG)
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize url
|
11
|
+
@url = File.absolute_path url
|
12
|
+
end
|
13
|
+
|
14
|
+
def export options
|
15
|
+
IESD::DMG::InstallESD.new(File.join @url, *INSTALLESD_DMG).export options
|
16
|
+
end
|
17
|
+
|
18
|
+
def valid?
|
19
|
+
IESD::APP::InstallOSX.validate @url
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module IESD
|
2
|
+
class Packages
|
3
|
+
class BaseSystemBinaries < PKGUtil::PKG
|
4
|
+
def extract_mach_kernel output
|
5
|
+
show { |pkg|
|
6
|
+
payload = "#{pkg}/Payload"
|
7
|
+
cpio = "#{payload}.cpio"
|
8
|
+
ohai "Unarchiving #{payload}"
|
9
|
+
case `#{Utility::FILE} --brief --mime-type #{payload}`.chomp
|
10
|
+
when "application/x-bzip2"
|
11
|
+
system(Utility::MV, payload, "#{cpio}.bz2")
|
12
|
+
system(Utility::BUNZIP2, "#{cpio}.bz2")
|
13
|
+
when "application/x-gzip"
|
14
|
+
system(Utility::MV, payload, "#{cpio}.gz")
|
15
|
+
system(Utility::GUNZIP, "#{cpio}.gz")
|
16
|
+
end
|
17
|
+
puts "Unarchived: #{cpio}"
|
18
|
+
ohai "Extracting /mach_kernel"
|
19
|
+
system("#{Utility::CPIO} -p -d -I \"#{cpio}\" -- \"#{payload}\" <<</mach_kernel >/dev/null 2>&1")
|
20
|
+
system(Utility::MV, "#{payload}/mach_kernel", output)
|
21
|
+
puts "Extracted: #{output}"
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module IESD
|
2
|
+
class Packages
|
3
|
+
class OSInstall < PKGUtil::PKG
|
4
|
+
def postinstall_extensions extensions
|
5
|
+
update { |pkg|
|
6
|
+
oh1 "Creating Extensions Postinstall Script"
|
7
|
+
script = File.join pkg, *%w{ Scripts postinstall_actions kext.tool }
|
8
|
+
File.open(script, "a+") { |f|
|
9
|
+
f.puts("#!/bin/sh")
|
10
|
+
extensions[:remove].each { |kext|
|
11
|
+
f.puts("logger -p install.info \"Removing #{kext}\"")
|
12
|
+
f.puts("/bin/rm -rf \"$3/System/Library/Extensions/#{kext}\"")
|
13
|
+
}
|
14
|
+
extensions[:install].each { |kext|
|
15
|
+
f.puts("logger -p install.info \"Installing #{File.basename kext}\"")
|
16
|
+
f.puts("/usr/bin/ditto \"/System/Library/Extensions/#{File.basename kext}\" \"$3/System/Library/Extensions/#{File.basename kext}\"")
|
17
|
+
}
|
18
|
+
}
|
19
|
+
File.chmod(0755, script)
|
20
|
+
puts "Created: #{script}"
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
data/lib/iesd/utility.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "tmpdir"
|
2
|
+
|
3
|
+
module Utility
|
4
|
+
BUNZIP2 = "/usr/bin/bunzip2"
|
5
|
+
CHFLAGS = "/usr/bin/chflags"
|
6
|
+
CPIO = "/usr/bin/cpio"
|
7
|
+
DITTO = "/usr/bin/ditto"
|
8
|
+
FILE = "/usr/bin/file"
|
9
|
+
GUNZIP = "/usr/bin/gunzip"
|
10
|
+
HDIUTIL = "/usr/bin/hdiutil"
|
11
|
+
KEXTCACHE = "/usr/sbin/kextcache"
|
12
|
+
LS = "/bin/ls"
|
13
|
+
MV = "/bin/mv"
|
14
|
+
PKGUTIL = "/usr/sbin/pkgutil"
|
15
|
+
RM = "/bin/rm"
|
16
|
+
end
|
17
|
+
|
18
|
+
Dir[File.join(File.dirname(__FILE__), "utility", "*.rb")].each { |rb| require rb }
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module HDIUtil
|
2
|
+
DEFAULT_MOUNT_OPTIONS = %w{ -nobrowse -quiet -noverify}
|
3
|
+
DEFAULT_MOUNT_OPTIONS.concat(%w{ -owners on }) if Process.uid == 0
|
4
|
+
DEFAULT_UNMOUNT_OPTIONS = %w{ -quiet }
|
5
|
+
DEFAULT_CONVERT_OPTIONS = %w{ -quiet }
|
6
|
+
|
7
|
+
def self.read input
|
8
|
+
Dir.mktmpdir { |mountpoint|
|
9
|
+
attach input, mountpoint, [*DEFAULT_MOUNT_OPTIONS]
|
10
|
+
if block_given?
|
11
|
+
yield mountpoint
|
12
|
+
else
|
13
|
+
shell mountpoint
|
14
|
+
end
|
15
|
+
detach input, mountpoint, [*DEFAULT_UNMOUNT_OPTIONS]
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.write input, output, add_sectors = 0
|
20
|
+
Dir.mktmpdir { |tmp|
|
21
|
+
shadow = File.join(tmp, "#{File.basename input}.shadow")
|
22
|
+
shadow_options = ["-shadow", shadow]
|
23
|
+
format_options = ["-format", `#{Utility::HDIUTIL} imageinfo -format "#{input}"`.chomp]
|
24
|
+
Dir.mktmpdir(nil, tmp) { |mountpoint|
|
25
|
+
resize_limits = `#{Utility::HDIUTIL} resize -limits -shadow "#{shadow}" "#{input}"`.chomp.split.map { |s| s.to_i }
|
26
|
+
sectors = (resize_limits[1] + add_sectors).to_s
|
27
|
+
system(Utility::HDIUTIL, "resize", "-growonly", "-sectors", sectors, *shadow_options, input)
|
28
|
+
attach input, mountpoint, [*DEFAULT_MOUNT_OPTIONS, *shadow_options]
|
29
|
+
if block_given?
|
30
|
+
yield mountpoint
|
31
|
+
else
|
32
|
+
shell mountpoint
|
33
|
+
end
|
34
|
+
detach input, mountpoint, [*DEFAULT_UNMOUNT_OPTIONS]
|
35
|
+
system(Utility::HDIUTIL, "resize", "-shrinkonly", "-sectors", "min", *shadow_options, input)
|
36
|
+
}
|
37
|
+
oh1 "Merging #{shadow}"
|
38
|
+
system(Utility::HDIUTIL, "convert", *DEFAULT_CONVERT_OPTIONS, *format_options, *shadow_options, "-o", output, input)
|
39
|
+
puts "Merged: #{output}"
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.validate input
|
44
|
+
Kernel.system("#{Utility::HDIUTIL} imageinfo \"#{input}\" >/dev/null 2>&1")
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def self.attach dmg, mountpoint, options = []
|
50
|
+
ohai "Mounting #{dmg}"
|
51
|
+
system(Utility::HDIUTIL, "attach", *options, "-mountpoint", mountpoint, dmg)
|
52
|
+
puts "Mounted: #{mountpoint}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.detach dmg, mountpoint, options = []
|
56
|
+
ohai "Unmounting #{dmg}"
|
57
|
+
system(Utility::HDIUTIL, "detach", *options, mountpoint)
|
58
|
+
puts "Unmounted: #{mountpoint}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.shell dir
|
62
|
+
Dir.chdir(dir) {
|
63
|
+
ohai ENV['SHELL']
|
64
|
+
system(ENV, ENV['SHELL'])
|
65
|
+
}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
module HDIUtil
|
70
|
+
class DMG
|
71
|
+
attr_accessor :url
|
72
|
+
|
73
|
+
def initialize url
|
74
|
+
@url = File.absolute_path url
|
75
|
+
end
|
76
|
+
|
77
|
+
def show &block
|
78
|
+
HDIUtil.read(@url, &block)
|
79
|
+
end
|
80
|
+
|
81
|
+
def edit
|
82
|
+
update
|
83
|
+
end
|
84
|
+
|
85
|
+
def update &block
|
86
|
+
Dir.mktmpdir { |tmp|
|
87
|
+
flags = `#{Utility::LS} -lO "#{@url}"`.split[4]
|
88
|
+
HDIUtil.write(@url, (tmpfile = File.join(tmp, File.basename(@url))), &block)
|
89
|
+
system(Utility::MV, tmpfile, @url)
|
90
|
+
system(Utility::CHFLAGS, flags, @url) unless flags == "-"
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
def valid?
|
95
|
+
HDIUtil.validate @url
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module PKGUtil
|
2
|
+
def self.read input
|
3
|
+
Dir.mktmpdir { |tmp|
|
4
|
+
tmp = File.join tmp, File.basename(input)
|
5
|
+
expand input, tmp
|
6
|
+
if block_given?
|
7
|
+
yield tmp
|
8
|
+
else
|
9
|
+
shell tmp
|
10
|
+
end
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.write input, output = input
|
15
|
+
Dir.mktmpdir { |tmp|
|
16
|
+
tmp = File.join tmp, File.basename(input)
|
17
|
+
expand input, tmp
|
18
|
+
if block_given?
|
19
|
+
yield tmp
|
20
|
+
else
|
21
|
+
shell tmp
|
22
|
+
end
|
23
|
+
flatten tmp, output
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def self.expand pkg, dir
|
30
|
+
ohai "Expanding #{pkg}"
|
31
|
+
system(Utility::PKGUTIL, "--expand", pkg, dir)
|
32
|
+
puts "Expanded: #{dir}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.flatten dir, pkg
|
36
|
+
ohai "Flattening #{dir}"
|
37
|
+
system(Utility::PKGUTIL, "--flatten", dir, pkg)
|
38
|
+
puts "Flattened: #{pkg}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.shell dir
|
42
|
+
Dir.chdir(dir) {
|
43
|
+
ohai ENV['SHELL']
|
44
|
+
system(ENV, ENV['SHELL'])
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
module PKGUtil
|
50
|
+
class PKG
|
51
|
+
attr_accessor :url
|
52
|
+
|
53
|
+
def initialize url
|
54
|
+
@url = File.absolute_path url
|
55
|
+
end
|
56
|
+
|
57
|
+
def show &block
|
58
|
+
PKGUtil.read(@url, &block)
|
59
|
+
end
|
60
|
+
|
61
|
+
def edit
|
62
|
+
update
|
63
|
+
end
|
64
|
+
|
65
|
+
def update &block
|
66
|
+
PKGUtil.write(@url, &block)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Tty extend self
|
2
|
+
def blue; bold 34; end
|
3
|
+
def white; bold 39; end
|
4
|
+
def red; underline 31; end
|
5
|
+
def yellow; underline 33 ; end
|
6
|
+
def reset; escape 0; end
|
7
|
+
def em; underline 39; end
|
8
|
+
def green; color 92 end
|
9
|
+
def gray; bold 30 end
|
10
|
+
|
11
|
+
def width
|
12
|
+
`/usr/bin/tput cols`.strip.to_i
|
13
|
+
end
|
14
|
+
|
15
|
+
def truncate(str)
|
16
|
+
str.to_s[0, width - 4]
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def color n
|
22
|
+
escape "0;#{n}"
|
23
|
+
end
|
24
|
+
def bold n
|
25
|
+
escape "1;#{n}"
|
26
|
+
end
|
27
|
+
def underline n
|
28
|
+
escape "4;#{n}"
|
29
|
+
end
|
30
|
+
def escape n
|
31
|
+
"\033[#{n}m" if $stdout.tty?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Array
|
36
|
+
def shell_s
|
37
|
+
cp = dup
|
38
|
+
first = cp.shift
|
39
|
+
cp.map{ |arg| arg.gsub " ", "\\ " }.unshift(first) * " "
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def ohai title, *sput
|
44
|
+
title = Tty.truncate(title) if $stdout.tty? && ENV['VERBOSE'].nil?
|
45
|
+
puts "#{Tty.blue}==>#{Tty.white} #{title}#{Tty.reset}"
|
46
|
+
puts sput unless sput.empty?
|
47
|
+
end
|
48
|
+
|
49
|
+
def oh1 title
|
50
|
+
title = Tty.truncate(title) if $stdout.tty? && ENV['VERBOSE'].nil?
|
51
|
+
puts "#{Tty.green}==>#{Tty.white} #{title}#{Tty.reset}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def opoo warning
|
55
|
+
STDERR.puts "#{Tty.red}Warning#{Tty.reset}: #{warning}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def onoe error
|
59
|
+
lines = error.to_s.split("\n")
|
60
|
+
STDERR.puts "#{Tty.red}Error#{Tty.reset}: #{lines.shift}"
|
61
|
+
STDERR.puts lines unless lines.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
def odie error
|
65
|
+
onoe error
|
66
|
+
exit 1
|
67
|
+
end
|
68
|
+
|
69
|
+
def system *args
|
70
|
+
abort "Failed during: #{args.shell_s}" unless Kernel.system *args
|
71
|
+
end
|
72
|
+
|
73
|
+
def sudo *args
|
74
|
+
args = if args.length > 1
|
75
|
+
args.unshift "/usr/bin/sudo"
|
76
|
+
else
|
77
|
+
"/usr/bin/sudo #{args.first}"
|
78
|
+
end
|
79
|
+
ohai *args
|
80
|
+
system *args
|
81
|
+
end
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: iesd
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.pre
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "なつき"
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-12-03 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Modify Extensions, Kextcache and Packages on InstallESD.
|
14
|
+
email: i@ntk.me
|
15
|
+
executables:
|
16
|
+
- iesd
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- README.md
|
21
|
+
- LICENSE.md
|
22
|
+
- iesd.gemspec
|
23
|
+
- lib/iesd/InstallESD/BaseSystem.dmg.rb
|
24
|
+
- lib/iesd/InstallESD/Extensions.rb
|
25
|
+
- lib/iesd/InstallESD/InstallESD.dmg.rb
|
26
|
+
- lib/iesd/InstallESD/InstallOSX.app.rb
|
27
|
+
- lib/iesd/InstallESD/InstallOSX.dmg.rb
|
28
|
+
- lib/iesd/InstallESD/Packages/AdditionalEssentials.pkg.rb
|
29
|
+
- lib/iesd/InstallESD/Packages/AdditionalSpeechVoices.pkg.rb
|
30
|
+
- lib/iesd/InstallESD/Packages/AsianLanguagesSupport.pkg.rb
|
31
|
+
- lib/iesd/InstallESD/Packages/BaseSystemBinaries.pkg.rb
|
32
|
+
- lib/iesd/InstallESD/Packages/BaseSystemResources.pkg.rb
|
33
|
+
- lib/iesd/InstallESD/Packages/BSD.pkg.rb
|
34
|
+
- lib/iesd/InstallESD/Packages/Essentials.pkg.rb
|
35
|
+
- lib/iesd/InstallESD/Packages/JavaEssentials.pkg.rb
|
36
|
+
- lib/iesd/InstallESD/Packages/JavaTools.pkg.rb
|
37
|
+
- lib/iesd/InstallESD/Packages/MediaFiles.pkg.rb
|
38
|
+
- lib/iesd/InstallESD/Packages/OSInstall.mpkg.rb
|
39
|
+
- lib/iesd/InstallESD/Packages/OSInstall.pkg.rb
|
40
|
+
- lib/iesd/InstallESD/Packages/OSUpgrade.pkg.rb
|
41
|
+
- lib/iesd/InstallESD/Packages/OxfordDictionaries.pkg.rb
|
42
|
+
- lib/iesd/InstallESD/Packages/X11redirect.pkg.rb
|
43
|
+
- lib/iesd/InstallESD/Packages.rb
|
44
|
+
- lib/iesd/InstallESD.rb
|
45
|
+
- lib/iesd/utility/hdiutil.rb
|
46
|
+
- lib/iesd/utility/pkgutil.rb
|
47
|
+
- lib/iesd/utility/tty.rb
|
48
|
+
- lib/iesd/utility.rb
|
49
|
+
- lib/iesd.rb
|
50
|
+
- bin/iesd
|
51
|
+
homepage: https://github.com/ntkme/iesd
|
52
|
+
licenses:
|
53
|
+
- BSD-2-Clause
|
54
|
+
metadata: {}
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 1.9.0
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.3.1
|
69
|
+
requirements: []
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 2.1.9
|
72
|
+
signing_key:
|
73
|
+
specification_version: 4
|
74
|
+
summary: Customize OS X InstallESD.
|
75
|
+
test_files: []
|