iesd 1.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +9 -0
  3. data/README.md +4 -0
  4. data/bin/iesd +131 -0
  5. data/iesd.gemspec +19 -0
  6. data/lib/iesd.rb +13 -0
  7. data/lib/iesd/InstallESD.rb +35 -0
  8. data/lib/iesd/InstallESD/BaseSystem.dmg.rb +56 -0
  9. data/lib/iesd/InstallESD/Extensions.rb +78 -0
  10. data/lib/iesd/InstallESD/InstallESD.dmg.rb +105 -0
  11. data/lib/iesd/InstallESD/InstallOSX.app.rb +23 -0
  12. data/lib/iesd/InstallESD/InstallOSX.dmg.rb +11 -0
  13. data/lib/iesd/InstallESD/Packages.rb +7 -0
  14. data/lib/iesd/InstallESD/Packages/AdditionalEssentials.pkg.rb +0 -0
  15. data/lib/iesd/InstallESD/Packages/AdditionalSpeechVoices.pkg.rb +0 -0
  16. data/lib/iesd/InstallESD/Packages/AsianLanguagesSupport.pkg.rb +0 -0
  17. data/lib/iesd/InstallESD/Packages/BSD.pkg.rb +0 -0
  18. data/lib/iesd/InstallESD/Packages/BaseSystemBinaries.pkg.rb +26 -0
  19. data/lib/iesd/InstallESD/Packages/BaseSystemResources.pkg.rb +0 -0
  20. data/lib/iesd/InstallESD/Packages/Essentials.pkg.rb +0 -0
  21. data/lib/iesd/InstallESD/Packages/JavaEssentials.pkg.rb +0 -0
  22. data/lib/iesd/InstallESD/Packages/JavaTools.pkg.rb +0 -0
  23. data/lib/iesd/InstallESD/Packages/MediaFiles.pkg.rb +0 -0
  24. data/lib/iesd/InstallESD/Packages/OSInstall.mpkg.rb +6 -0
  25. data/lib/iesd/InstallESD/Packages/OSInstall.pkg.rb +25 -0
  26. data/lib/iesd/InstallESD/Packages/OSUpgrade.pkg.rb +0 -0
  27. data/lib/iesd/InstallESD/Packages/OxfordDictionaries.pkg.rb +0 -0
  28. data/lib/iesd/InstallESD/Packages/X11redirect.pkg.rb +0 -0
  29. data/lib/iesd/utility.rb +18 -0
  30. data/lib/iesd/utility/hdiutil.rb +98 -0
  31. data/lib/iesd/utility/pkgutil.rb +69 -0
  32. data/lib/iesd/utility/tty.rb +81 -0
  33. metadata +75 -0
@@ -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
@@ -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.
@@ -0,0 +1,4 @@
1
+ iESD
2
+ ====
3
+
4
+ Customize OS X InstallESD.
@@ -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
+
@@ -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
@@ -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
@@ -0,0 +1,11 @@
1
+ module IESD
2
+ class DMG
3
+ class InstallOSX < HDIUtil::DMG
4
+ def export options
5
+ show { |mountpoint|
6
+ IESD::APP::InstallOSX.new(Dir[File.join(mountpoint, "*.app")][0]).export options
7
+ }
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ Dir[File.join(File.dirname(__FILE__), "Packages", "*.rb")].each { |rb| require rb }
2
+
3
+ module IESD
4
+ class Packages
5
+
6
+ end
7
+ end
@@ -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
@@ -0,0 +1,6 @@
1
+ module InstallESD
2
+ class Packages
3
+ class OSInstallM < PKGUtil::PKG
4
+ end
5
+ end
6
+ end
@@ -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
@@ -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: []