shoes 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (275) hide show
  1. data/.gitignore +12 -0
  2. data/CHANGELOG +29 -0
  3. data/COPYING +30 -0
  4. data/README.md +76 -0
  5. data/README.old +117 -0
  6. data/Rakefile +130 -0
  7. data/Rakefile.bk +651 -0
  8. data/app.yaml +7 -0
  9. data/bin/main.skel +104 -0
  10. data/bugs/issue-012e9468ddc7b0cb7e1503413a8a11c4f8707b67.yaml +21 -0
  11. data/bugs/issue-0711ff8b67baa63586f11d0096fee9dd4436bf58.yaml +23 -0
  12. data/bugs/issue-07f87998d93eb401e22395c11085676389b935c4.yaml +22 -0
  13. data/bugs/issue-0bff2d80008803cbc7efbcdacdc60ef2163664d2.yaml +22 -0
  14. data/bugs/issue-0c66f223d19efbca7b692f3b91961f407ad7abec.yaml +24 -0
  15. data/bugs/issue-183bc3c7a8f575aff2b24e0bf22aa0dfcc8e4fc2.yaml +29 -0
  16. data/bugs/issue-1bad1e60a04cb3adb6a8f3ded128af2e16b56ffe.yaml +18 -0
  17. data/bugs/issue-1f1d43f76bf4de79d7f94adbae6dd506a9d81633.yaml +41 -0
  18. data/bugs/issue-320924117cadb045cc91f2a6fca922b4d81d4bb5.yaml +20 -0
  19. data/bugs/issue-33e5c8355fbf65252ea9e939714651df8bd8cb3b.yaml +25 -0
  20. data/bugs/issue-36f7c8262a72bcd5e28cfa4ed29328b8237ea79b.yaml +20 -0
  21. data/bugs/issue-39bf04ee50c3bef67b89b8e9beb28657805587ce.yaml +18 -0
  22. data/bugs/issue-3e28ba7754f73d02ef416eef989af707a8c00f01.yaml +23 -0
  23. data/bugs/issue-3f638cc03f41f9c3fdf217355321f1563f8fee45.yaml +22 -0
  24. data/bugs/issue-41e48e14f1ef4f6deb69be68165d7dd3ffd99156.yaml +22 -0
  25. data/bugs/issue-4c9408166a2aa5dd333bbb05520deebf4ded08e0.yaml +22 -0
  26. data/bugs/issue-55c687e108ecd5aeb8e0d0aeb4294984f84acd3e.yaml +18 -0
  27. data/bugs/issue-5811d34692cc292717a58ec1df1f8948cf30d826.yaml +28 -0
  28. data/bugs/issue-5a7c1f59a0526f9cea7fb366867cf1e6ed8ef69d.yaml +22 -0
  29. data/bugs/issue-688a2c2566bef6a03efa57a4ae1f7cfa8fc74444.yaml +21 -0
  30. data/bugs/issue-78b16c7988ade2ef96e716fa8cb9a004bd4ced65.yaml +33 -0
  31. data/bugs/issue-804ee49f9800154eddf0650690c7a9bb5626253f.yaml +27 -0
  32. data/bugs/issue-807dd1c610b2e941a5d454e26b2eac27e89a0ab4.yaml +22 -0
  33. data/bugs/issue-822ee33ec11ebd25f90ea86e8438de7891e63aee.yaml +18 -0
  34. data/bugs/issue-82ff7152cebb8a1cb065b864cb4fe22de2328146.yaml +29 -0
  35. data/bugs/issue-856afbdcdd4970ad54b8ce4a6c017fbaab45f49d.yaml +31 -0
  36. data/bugs/issue-8d49e32fb21522651c67490adb4d80076dbb14e1.yaml +24 -0
  37. data/bugs/issue-91583359653a9d530c1e32be72d874d847a306e7.yaml +21 -0
  38. data/bugs/issue-af41a5229613172764e7d3c98431172db337053d.yaml +20 -0
  39. data/bugs/issue-bd9856b3788dd429c998a5af1b2aae8221cb80b7.yaml +28 -0
  40. data/bugs/issue-be22aef5c564fb7b5e9938343136a9cd6a2edb7b.yaml +22 -0
  41. data/bugs/issue-bf8697523c77c326e7e35fc82cf3dd739ae92310.yaml +27 -0
  42. data/bugs/issue-cdd4b4795f34d6ff46e56ece10f8216a4a5456b2.yaml +25 -0
  43. data/bugs/issue-d9bfb5581d745ef9deb3b9b2e08ef74d1cd43082.yaml +20 -0
  44. data/bugs/issue-e0ce2f687cc096f35715d28b0af88589f4ab6cc6.yaml +18 -0
  45. data/bugs/issue-e4b0aca4a10a574b333aeaecaaf221dbc5ed22c6.yaml +38 -0
  46. data/bugs/issue-f263746594b95ba778455730478ee8df60ee639d.yaml +22 -0
  47. data/bugs/project.yaml +72 -0
  48. data/builddeps.sh +102 -0
  49. data/fonts/Coolvetica.ttf +0 -0
  50. data/fonts/Lacuna.ttf +0 -0
  51. data/gemlib/shoes.rb +1 -0
  52. data/lib/shoes.rb +548 -0
  53. data/lib/shoes/cache.rb +54 -0
  54. data/lib/shoes/chipmunk.rb +35 -0
  55. data/lib/shoes/data.rb +39 -0
  56. data/lib/shoes/help.rb +468 -0
  57. data/lib/shoes/image.rb +25 -0
  58. data/lib/shoes/inspect.rb +128 -0
  59. data/lib/shoes/log.rb +48 -0
  60. data/lib/shoes/minitar.rb +986 -0
  61. data/lib/shoes/override.rb +38 -0
  62. data/lib/shoes/pack.rb +543 -0
  63. data/lib/shoes/search.rb +46 -0
  64. data/lib/shoes/setup.rb +329 -0
  65. data/lib/shoes/shy.rb +131 -0
  66. data/lib/shoes/shybuilder.rb +44 -0
  67. data/lib/shoes/version.rb +3 -0
  68. data/make/darwin/deps.vlc +12 -0
  69. data/make/darwin/dylibs.shoes +22 -0
  70. data/make/darwin/dylibs.video +11 -0
  71. data/make/darwin/env.rb +81 -0
  72. data/make/darwin/tasks.rb +105 -0
  73. data/make/linux/env.rb +65 -0
  74. data/make/linux/tasks.rb +61 -0
  75. data/make/make.rb +85 -0
  76. data/make/mingw/dlls +19 -0
  77. data/make/mingw/env.rb +69 -0
  78. data/make/mingw/tasks.rb +70 -0
  79. data/make/rakefile_common.rb +8 -0
  80. data/manual-snapshots/class-book.png +0 -0
  81. data/manual-snapshots/expert-definr.png +0 -0
  82. data/manual-snapshots/expert-funnies.png +0 -0
  83. data/manual-snapshots/expert-irb.png +0 -0
  84. data/manual-snapshots/expert-minesweeper.png +0 -0
  85. data/manual-snapshots/expert-othello.png +0 -0
  86. data/manual-snapshots/expert-pong.png +0 -0
  87. data/manual-snapshots/expert-tankspank.png +0 -0
  88. data/manual-snapshots/good-arc.png +0 -0
  89. data/manual-snapshots/good-clock.png +0 -0
  90. data/manual-snapshots/good-follow.png +0 -0
  91. data/manual-snapshots/good-reminder.png +0 -0
  92. data/manual-snapshots/good-vjot.png +0 -0
  93. data/manual-snapshots/simple-accordion.png +0 -0
  94. data/manual-snapshots/simple-anim-shapes.png +0 -0
  95. data/manual-snapshots/simple-anim-text.png +0 -0
  96. data/manual-snapshots/simple-arc.png +0 -0
  97. data/manual-snapshots/simple-bounce.png +0 -0
  98. data/manual-snapshots/simple-calc.png +0 -0
  99. data/manual-snapshots/simple-chipmunk.png +0 -0
  100. data/manual-snapshots/simple-control-sizes.png +0 -0
  101. data/manual-snapshots/simple-curve.png +0 -0
  102. data/manual-snapshots/simple-dialogs.png +0 -0
  103. data/manual-snapshots/simple-downloader.png +0 -0
  104. data/manual-snapshots/simple-draw.png +0 -0
  105. data/manual-snapshots/simple-editor.png +0 -0
  106. data/manual-snapshots/simple-form.png +0 -0
  107. data/manual-snapshots/simple-mask.png +0 -0
  108. data/manual-snapshots/simple-menu.png +0 -0
  109. data/manual-snapshots/simple-menu1.png +0 -0
  110. data/manual-snapshots/simple-rubygems.png +0 -0
  111. data/manual-snapshots/simple-slide.png +0 -0
  112. data/manual-snapshots/simple-sphere.png +0 -0
  113. data/manual-snapshots/simple-sqlite3.png +0 -0
  114. data/manual-snapshots/simple-timer.png +0 -0
  115. data/manual-snapshots/simple-video.png +0 -0
  116. data/platform/mac/Info.plist +55 -0
  117. data/platform/mac/build-deps.sh +658 -0
  118. data/platform/mac/command-manual.rb +1 -0
  119. data/platform/mac/deps-osx.patch +159 -0
  120. data/platform/mac/dmg_ds_store +0 -0
  121. data/platform/mac/pangorc +2 -0
  122. data/platform/mac/pkg-dmg +1447 -0
  123. data/platform/mac/shoes +31 -0
  124. data/platform/mac/shoes-launch +7 -0
  125. data/platform/mac/stub.m +178 -0
  126. data/platform/mac/version.plist +14 -0
  127. data/platform/msw/base.nsi +644 -0
  128. data/platform/msw/installer-1.bmp +0 -0
  129. data/platform/msw/installer-2.bmp +0 -0
  130. data/platform/msw/shoes.exe.manifest +17 -0
  131. data/platform/msw/shoes.ico +0 -0
  132. data/platform/msw/stub-inject.c +59 -0
  133. data/platform/msw/stub.c +271 -0
  134. data/platform/msw/stub32.h +14 -0
  135. data/platform/msw/stub32.rc +16 -0
  136. data/platform/nix/INSTALL +56 -0
  137. data/platform/nix/Makefile +144 -0
  138. data/platform/nix/shoes.launch +20 -0
  139. data/platform/skel.rb +27 -0
  140. data/rakefile_darwin.rb +7 -0
  141. data/rakefile_linux.rb +3 -0
  142. data/rakefile_mingw.rb +7 -0
  143. data/samples/class-book.rb +43 -0
  144. data/samples/class-book.yaml +387 -0
  145. data/samples/expert-definr.rb +23 -0
  146. data/samples/expert-funnies.rb +51 -0
  147. data/samples/expert-irb.rb +112 -0
  148. data/samples/expert-minesweeper.rb +267 -0
  149. data/samples/expert-othello.rb +319 -0
  150. data/samples/expert-pong.rb +62 -0
  151. data/samples/expert-tankspank.rb +385 -0
  152. data/samples/good-arc.rb +37 -0
  153. data/samples/good-clock.rb +51 -0
  154. data/samples/good-follow.rb +26 -0
  155. data/samples/good-reminder.rb +174 -0
  156. data/samples/good-vjot.rb +56 -0
  157. data/samples/simple-accordion.rb +75 -0
  158. data/samples/simple-anim-shapes.rb +17 -0
  159. data/samples/simple-anim-text.rb +13 -0
  160. data/samples/simple-arc.rb +23 -0
  161. data/samples/simple-bounce.rb +24 -0
  162. data/samples/simple-calc.rb +70 -0
  163. data/samples/simple-chipmunk.rb +26 -0
  164. data/samples/simple-control-sizes.rb +24 -0
  165. data/samples/simple-curve.rb +26 -0
  166. data/samples/simple-dialogs.rb +29 -0
  167. data/samples/simple-downloader.rb +27 -0
  168. data/samples/simple-draw.rb +13 -0
  169. data/samples/simple-editor.rb +28 -0
  170. data/samples/simple-form.rb +28 -0
  171. data/samples/simple-form.shy +0 -0
  172. data/samples/simple-mask.rb +21 -0
  173. data/samples/simple-menu.rb +31 -0
  174. data/samples/simple-menu1.rb +35 -0
  175. data/samples/simple-rubygems.rb +29 -0
  176. data/samples/simple-slide.rb +45 -0
  177. data/samples/simple-sphere.rb +28 -0
  178. data/samples/simple-sqlite3.rb +13 -0
  179. data/samples/simple-timer.rb +13 -0
  180. data/samples/simple-video.rb +13 -0
  181. data/shoes.gemspec +21 -0
  182. data/shoes/app.c +591 -0
  183. data/shoes/app.h +110 -0
  184. data/shoes/appwin32.h +13 -0
  185. data/shoes/appwin32.rc +28 -0
  186. data/shoes/canvas.c +2202 -0
  187. data/shoes/canvas.h +682 -0
  188. data/shoes/code.h +14 -0
  189. data/shoes/config.h +232 -0
  190. data/shoes/effects.c +243 -0
  191. data/shoes/effects.h +7 -0
  192. data/shoes/http.h +44 -0
  193. data/shoes/http/common.h +86 -0
  194. data/shoes/http/curl.c +259 -0
  195. data/shoes/http/nsurl.m +274 -0
  196. data/shoes/http/windownload.c +114 -0
  197. data/shoes/http/winhttp.c +216 -0
  198. data/shoes/http/winhttp.h +19 -0
  199. data/shoes/image.c +1020 -0
  200. data/shoes/internal.c +46 -0
  201. data/shoes/internal.h +63 -0
  202. data/shoes/native.h +110 -0
  203. data/shoes/native/cocoa.h +105 -0
  204. data/shoes/native/cocoa.m +1557 -0
  205. data/shoes/native/gtk.c +1257 -0
  206. data/shoes/native/windows.c +2392 -0
  207. data/shoes/ruby.c +5221 -0
  208. data/shoes/ruby.h +299 -0
  209. data/shoes/world.c +243 -0
  210. data/shoes/world.h +63 -0
  211. data/static/Shoes.icns +0 -0
  212. data/static/avatar.png +0 -0
  213. data/static/code_highlighter.js +188 -0
  214. data/static/code_highlighter_ruby.js +26 -0
  215. data/static/icon-debug.png +0 -0
  216. data/static/icon-error.png +0 -0
  217. data/static/icon-info.png +0 -0
  218. data/static/icon-warn.png +0 -0
  219. data/static/listbox_button1.png +0 -0
  220. data/static/listbox_button2.png +0 -0
  221. data/static/man-app.png +0 -0
  222. data/static/man-builds.png +0 -0
  223. data/static/man-builds1.png +0 -0
  224. data/static/man-editor-notepad.png +0 -0
  225. data/static/man-editor-osx.png +0 -0
  226. data/static/man-ele-background.png +0 -0
  227. data/static/man-ele-border.png +0 -0
  228. data/static/man-ele-button.png +0 -0
  229. data/static/man-ele-check.png +0 -0
  230. data/static/man-ele-editbox.png +0 -0
  231. data/static/man-ele-editline.png +0 -0
  232. data/static/man-ele-image.png +0 -0
  233. data/static/man-ele-listbox.png +0 -0
  234. data/static/man-ele-progress.png +0 -0
  235. data/static/man-ele-radio.png +0 -0
  236. data/static/man-ele-shape.png +0 -0
  237. data/static/man-ele-textblock.png +0 -0
  238. data/static/man-ele-video.png +0 -0
  239. data/static/man-intro-dmg.png +0 -0
  240. data/static/man-intro-exe.png +0 -0
  241. data/static/man-look-tiger.png +0 -0
  242. data/static/man-look-ubuntu.png +0 -0
  243. data/static/man-look-vista.png +0 -0
  244. data/static/man-run-osx.png +0 -0
  245. data/static/man-run-vista.png +0 -0
  246. data/static/man-run-xp.png +0 -0
  247. data/static/man-shot1.png +0 -0
  248. data/static/manual-en.txt +3531 -0
  249. data/static/manual-ja.txt +2825 -0
  250. data/static/manual.css +167 -0
  251. data/static/menu-corner1.png +0 -0
  252. data/static/menu-corner2.png +0 -0
  253. data/static/menu-gray.png +0 -0
  254. data/static/menu-left.png +0 -0
  255. data/static/menu-right.png +0 -0
  256. data/static/menu-top.png +0 -0
  257. data/static/shoes-dmg.jpg +0 -0
  258. data/static/shoes-icon-blue.png +0 -0
  259. data/static/shoes-icon.png +0 -0
  260. data/static/shoes-manual-apps.gif +0 -0
  261. data/static/shoes_main_window.png +0 -0
  262. data/static/stripe.png +0 -0
  263. data/static/stubs/blank.exe +0 -0
  264. data/static/stubs/blank.hfz +0 -0
  265. data/static/stubs/blank.run +375 -0
  266. data/static/stubs/cocoa-install +0 -0
  267. data/static/stubs/sh-install +49 -0
  268. data/static/stubs/shoes-stub-inject.exe +0 -0
  269. data/static/stubs/shoes-stub.exe +0 -0
  270. data/static/tutor-back.png +0 -0
  271. data/test/shoes_test.rb +8 -0
  272. data/test/test_helper.rb +25 -0
  273. data/use-deps +12 -0
  274. data/use-tmp-dep +8 -0
  275. metadata +509 -0
@@ -0,0 +1 @@
1
+ Shoes.show_manual
@@ -0,0 +1,159 @@
1
+ diff -wur /tmp/dep/bin/gem deps/bin/gem
2
+ --- /tmp/dep/bin/gem 2007-08-23 10:55:28.000000000 -0400
3
+ +++ deps/bin/gem 2007-08-01 17:38:51.000000000 -0400
4
+ @@ -1,4 +1,4 @@
5
+ -#! /tmp/dep/bin/ruby
6
+ +#! ./deps/bin/ruby
7
+ #--
8
+ # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
9
+ # All rights reserved.
10
+ diff -wur /tmp/dep/bin/gemwhich deps/bin/gemwhich
11
+ --- /tmp/dep/bin/gemwhich 2007-08-23 10:55:28.000000000 -0400
12
+ +++ deps/bin/gemwhich 2007-08-01 17:41:37.000000000 -0400
13
+ @@ -1,4 +1,4 @@
14
+ -#! /tmp/dep/bin/ruby
15
+ +#!./deps/bin/ruby
16
+ #--
17
+ # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
18
+ # All rights reserved.
19
+ diff -wur /tmp/dep/bin/irb deps/bin/irb
20
+ --- /tmp/dep/bin/irb 2007-08-23 10:54:56.000000000 -0400
21
+ +++ deps/bin/irb 2007-08-01 17:42:18.000000000 -0400
22
+ @@ -1,4 +1,4 @@
23
+ -#!/tmp/dep/bin/ruby
24
+ +#!./deps/bin/ruby
25
+ #
26
+ # irb.rb - intaractive ruby
27
+ # $Release Version: 0.9.5 $
28
+ diff -wur /tmp/dep/bin/rake deps/bin/rake
29
+ --- /tmp/dep/bin/rake 2007-08-23 10:56:54.000000000 -0400
30
+ +++ deps/bin/rake 2007-08-01 17:40:19.000000000 -0400
31
+ @@ -1,4 +1,4 @@
32
+ -#!/tmp/dep/bin/ruby
33
+ +#!./deps/bin/ruby
34
+ #
35
+ # This file was generated by RubyGems.
36
+ #
37
+ diff -wur /tmp/dep/etc/pango/pango.modules deps/etc/pango/pango.modules
38
+ --- /tmp/dep/etc/pango/pango.modules 2007-08-23 10:54:37.000000000 -0400
39
+ +++ deps/etc/pango/pango.modules 2007-08-01 18:35:50.000000000 -0400
40
+ @@ -1,17 +1,17 @@
41
+ # Pango Modules file
42
+ # Automatically generated file, do not edit
43
+ #
44
+ -# ModulesPath = /tmp/dep/lib/pango/1.6.0/modules
45
+ +# ModulesPath = .
46
+ #
47
+ -/tmp/dep/lib/pango/1.6.0/modules/pango-arabic-lang.so ArabicScriptEngineLang PangoEngineLang PangoRenderNone arabic:*
48
+ -/tmp/dep/lib/pango/1.6.0/modules/pango-basic-atsui.so BasicScriptEngineATSUI PangoEngineShape PangoRenderATSUI armenian:* bopomofo:* cherokee:* coptic:* cyrillic:* deseret:* ethiopic:* georgian:* gothic:* greek:* han:* hiragana:* katakana:* latin:* ogham:* old-italic:* runic:* canadian-aboriginal:* yi:* braille:* cypriot:* limbu:* osmanya:* shavian:* linear-b:* ugaritic:* common:
49
+ -/tmp/dep/lib/pango/1.6.0/modules/pango-indic-lang.so devaIndicScriptEngineLang PangoEngineLang PangoRenderNone devanagari:*
50
+ -/tmp/dep/lib/pango/1.6.0/modules/pango-indic-lang.so bengIndicScriptEngineLang PangoEngineLang PangoRenderNone bengali:*
51
+ -/tmp/dep/lib/pango/1.6.0/modules/pango-indic-lang.so guruIndicScriptEngineLang PangoEngineLang PangoRenderNone gurmukhi:*
52
+ -/tmp/dep/lib/pango/1.6.0/modules/pango-indic-lang.so gujrIndicScriptEngineLang PangoEngineLang PangoRenderNone gujarati:*
53
+ -/tmp/dep/lib/pango/1.6.0/modules/pango-indic-lang.so oryaIndicScriptEngineLang PangoEngineLang PangoRenderNone oriya:*
54
+ -/tmp/dep/lib/pango/1.6.0/modules/pango-indic-lang.so tamlIndicScriptEngineLang PangoEngineLang PangoRenderNone tamil:*
55
+ -/tmp/dep/lib/pango/1.6.0/modules/pango-indic-lang.so teluIndicScriptEngineLang PangoEngineLang PangoRenderNone telugu:*
56
+ -/tmp/dep/lib/pango/1.6.0/modules/pango-indic-lang.so kndaIndicScriptEngineLang PangoEngineLang PangoRenderNone kannada:*
57
+ -/tmp/dep/lib/pango/1.6.0/modules/pango-indic-lang.so mlymIndicScriptEngineLang PangoEngineLang PangoRenderNone malayalam:*
58
+ -/tmp/dep/lib/pango/1.6.0/modules/pango-indic-lang.so sinhIndicScriptEngineLang PangoEngineLang PangoRenderNone sinhala:*
59
+ +./pango-arabic-lang.so ArabicScriptEngineLang PangoEngineLang PangoRenderNone arabic:*
60
+ +./pango-basic-atsui.so BasicScriptEngineATSUI PangoEngineShape PangoRenderATSUI armenian:* bopomofo:* cherokee:* coptic:* cyrillic:* deseret:* ethiopic:* georgian:* gothic:* greek:* han:* hiragana:* katakana:* latin:* ogham:* old-italic:* runic:* canadian-aboriginal:* yi:* braille:* cypriot:* limbu:* osmanya:* shavian:* linear-b:* ugaritic:* common:
61
+ +./pango-indic-lang.so devaIndicScriptEngineLang PangoEngineLang PangoRenderNone devanagari:*
62
+ +./pango-indic-lang.so bengIndicScriptEngineLang PangoEngineLang PangoRenderNone bengali:*
63
+ +./pango-indic-lang.so guruIndicScriptEngineLang PangoEngineLang PangoRenderNone gurmukhi:*
64
+ +./pango-indic-lang.so gujrIndicScriptEngineLang PangoEngineLang PangoRenderNone gujarati:*
65
+ +./pango-indic-lang.so oryaIndicScriptEngineLang PangoEngineLang PangoRenderNone oriya:*
66
+ +./pango-indic-lang.so tamlIndicScriptEngineLang PangoEngineLang PangoRenderNone tamil:*
67
+ +./pango-indic-lang.so teluIndicScriptEngineLang PangoEngineLang PangoRenderNone telugu:*
68
+ +./pango-indic-lang.so kndaIndicScriptEngineLang PangoEngineLang PangoRenderNone kannada:*
69
+ +./pango-indic-lang.so mlymIndicScriptEngineLang PangoEngineLang PangoRenderNone malayalam:*
70
+ +./pango-indic-lang.so sinhIndicScriptEngineLang PangoEngineLang PangoRenderNone sinhala:*
71
+ diff -wur /tmp/dep/lib/pkgconfig/cairo.pc deps/lib/pkgconfig/cairo.pc
72
+ --- /tmp/dep/lib/pkgconfig/cairo.pc 2007-08-23 10:53:36.000000000 -0400
73
+ +++ deps/lib/pkgconfig/cairo.pc 2007-08-01 18:37:01.000000000 -0400
74
+ @@ -1,4 +1,4 @@
75
+ -prefix=/tmp/dep
76
+ +prefix=./deps
77
+ exec_prefix=${prefix}
78
+ libdir=${exec_prefix}/lib
79
+ includedir=${prefix}/include
80
+ @@ -8,6 +8,6 @@
81
+ Version: 1.4.10
82
+
83
+ Requires.private: libpng12
84
+ -Libs: -L${libdir} -lcairo
85
+ +Libs: -L${libdir} -lcairo -dylib_file /tmp/dep/lib/libpng12.0.dylib:./deps/lib/libpng12.0.dylib
86
+ Libs.private: -lz
87
+ Cflags: -I${includedir}/cairo
88
+ diff -wur /tmp/dep/lib/pkgconfig/glib-2.0.pc deps/lib/pkgconfig/glib-2.0.pc
89
+ --- /tmp/dep/lib/pkgconfig/glib-2.0.pc 2007-08-23 10:52:41.000000000 -0400
90
+ +++ deps/lib/pkgconfig/glib-2.0.pc 2007-08-01 17:52:56.000000000 -0400
91
+ @@ -1,4 +1,4 @@
92
+ -prefix=/tmp/dep
93
+ +prefix=./deps
94
+ exec_prefix=${prefix}
95
+ libdir=${exec_prefix}/lib
96
+ includedir=${prefix}/include
97
+ diff -wur /tmp/dep/lib/pkgconfig/gmodule-2.0.pc deps/lib/pkgconfig/gmodule-2.0.pc
98
+ --- /tmp/dep/lib/pkgconfig/gmodule-2.0.pc 2007-08-23 10:52:41.000000000 -0400
99
+ +++ deps/lib/pkgconfig/gmodule-2.0.pc 2007-08-01 17:54:55.000000000 -0400
100
+ @@ -1,4 +1,4 @@
101
+ -prefix=/tmp/dep
102
+ +prefix=./deps
103
+ exec_prefix=${prefix}
104
+ libdir=${exec_prefix}/lib
105
+ includedir=${prefix}/include
106
+ diff -wur /tmp/dep/lib/pkgconfig/gmodule-export-2.0.pc deps/lib/pkgconfig/gmodule-export-2.0.pc
107
+ --- /tmp/dep/lib/pkgconfig/gmodule-export-2.0.pc 2007-08-23 10:52:41.000000000 -0400
108
+ +++ deps/lib/pkgconfig/gmodule-export-2.0.pc 2007-08-01 17:55:02.000000000 -0400
109
+ @@ -1,4 +1,4 @@
110
+ -prefix=/tmp/dep
111
+ +prefix=./deps
112
+ exec_prefix=${prefix}
113
+ libdir=${exec_prefix}/lib
114
+ includedir=${prefix}/include
115
+ diff -wur /tmp/dep/lib/pkgconfig/gmodule-no-export-2.0.pc deps/lib/pkgconfig/gmodule-no-export-2.0.pc
116
+ --- /tmp/dep/lib/pkgconfig/gmodule-no-export-2.0.pc 2007-08-23 10:52:41.000000000 -0400
117
+ +++ deps/lib/pkgconfig/gmodule-no-export-2.0.pc 2007-08-01 17:55:11.000000000 -0400
118
+ @@ -1,4 +1,4 @@
119
+ -prefix=/tmp/dep
120
+ +prefix=./deps
121
+ exec_prefix=${prefix}
122
+ libdir=${exec_prefix}/lib
123
+ includedir=${prefix}/include
124
+ diff -wur /tmp/dep/lib/pkgconfig/gobject-2.0.pc deps/lib/pkgconfig/gobject-2.0.pc
125
+ --- /tmp/dep/lib/pkgconfig/gobject-2.0.pc 2007-08-23 10:52:41.000000000 -0400
126
+ +++ deps/lib/pkgconfig/gobject-2.0.pc 2007-08-01 17:54:42.000000000 -0400
127
+ @@ -1,4 +1,4 @@
128
+ -prefix=/tmp/dep
129
+ +prefix=./deps
130
+ exec_prefix=${prefix}
131
+ libdir=${exec_prefix}/lib
132
+ includedir=${prefix}/include
133
+ diff -wur /tmp/dep/lib/pkgconfig/libpng.pc deps/lib/pkgconfig/libpng.pc
134
+ --- /tmp/dep/lib/pkgconfig/libpng.pc 2007-08-23 10:51:13.000000000 -0400
135
+ +++ deps/lib/pkgconfig/libpng.pc 2007-08-01 17:53:29.000000000 -0400
136
+ @@ -1,4 +1,4 @@
137
+ -prefix=/tmp/dep
138
+ +prefix=./deps
139
+ exec_prefix=${prefix}
140
+ libdir=${exec_prefix}/lib
141
+ includedir=${prefix}/include/libpng12
142
+ diff -wur /tmp/dep/lib/pkgconfig/libpng12.pc deps/lib/pkgconfig/libpng12.pc
143
+ --- /tmp/dep/lib/pkgconfig/libpng12.pc 2007-08-23 10:51:13.000000000 -0400
144
+ +++ deps/lib/pkgconfig/libpng12.pc 2007-08-01 17:53:29.000000000 -0400
145
+ @@ -1,4 +1,4 @@
146
+ -prefix=/tmp/dep
147
+ +prefix=./deps
148
+ exec_prefix=${prefix}
149
+ libdir=${exec_prefix}/lib
150
+ includedir=${prefix}/include/libpng12
151
+ diff -wur /tmp/dep/lib/pkgconfig/pango.pc deps/lib/pkgconfig/pango.pc
152
+ --- /tmp/dep/lib/pkgconfig/pango.pc 2007-08-23 10:54:46.000000000 -0400
153
+ +++ deps/lib/pkgconfig/pango.pc 2007-08-01 17:52:24.000000000 -0400
154
+ @@ -1,4 +1,4 @@
155
+ -prefix=/tmp/dep
156
+ +prefix=./deps
157
+ exec_prefix=${prefix}
158
+ libdir=${exec_prefix}/lib
159
+ includedir=${prefix}/include
Binary file
@@ -0,0 +1,2 @@
1
+ [Pango]
2
+ ModuleFiles=/Volumes/#{APPNAME}/#{APPNAME}.app/Contents/MacOS/pango.modules
@@ -0,0 +1,1447 @@
1
+ #!/usr/bin/perl
2
+ # ***** BEGIN LICENSE BLOCK *****
3
+ # Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
+ #
5
+ # The contents of this file are subject to the Mozilla Public License Version
6
+ # 1.1 (the "License"); you may not use this file except in compliance with
7
+ # the License. You may obtain a copy of the License at
8
+ # http://www.mozilla.org/MPL/
9
+ #
10
+ # Software distributed under the License is distributed on an "AS IS" basis,
11
+ # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
+ # for the specific language governing rights and limitations under the
13
+ # License.
14
+ #
15
+ # The Original Code is pkg-dmg, a Mac OS X disk image (.dmg) packager
16
+ #
17
+ # The Initial Developer of the Original Code is
18
+ # Mark Mentovai <mark@moxienet.com>.
19
+ # Portions created by the Initial Developer are Copyright (C) 2005
20
+ # the Initial Developer. All Rights Reserved.
21
+ #
22
+ # Contributor(s):
23
+ #
24
+ # Alternatively, the contents of this file may be used under the terms of
25
+ # either the GNU General Public License Version 2 or later (the "GPL"), or
26
+ # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
+ # in which case the provisions of the GPL or the LGPL are applicable instead
28
+ # of those above. If you wish to allow use of your version of this file only
29
+ # under the terms of either the GPL or the LGPL, and not to allow others to
30
+ # use your version of this file under the terms of the MPL, indicate your
31
+ # decision by deleting the provisions above and replace them with the notice
32
+ # and other provisions required by the GPL or the LGPL. If you do not delete
33
+ # the provisions above, a recipient may use your version of this file under
34
+ # the terms of any one of the MPL, the GPL or the LGPL.
35
+ #
36
+ # ***** END LICENSE BLOCK *****
37
+
38
+ use strict;
39
+ use warnings;
40
+
41
+ =pod
42
+
43
+ =head1 NAME
44
+
45
+ B<pkg-dmg> - Mac OS X disk image (.dmg) packager
46
+
47
+ =head1 SYNOPSIS
48
+
49
+ B<pkg-dmg>
50
+ B<--source> I<source-folder>
51
+ B<--target> I<target-image>
52
+ [B<--format> I<format>]
53
+ [B<--volname> I<volume-name>]
54
+ [B<--tempdir> I<temp-dir>]
55
+ [B<--mkdir> I<directory>]
56
+ [B<--copy> I<source>[:I<dest>]]
57
+ [B<--license> I<file>]
58
+ [B<--resource> I<file>]
59
+ [B<--icon> I<icns-file>]
60
+ [B<--attribute> I<a>:I<file>[:I<file>...]
61
+ [B<--idme>]
62
+ [B<--sourcefile>]
63
+ [B<--verbosity> I<level>]
64
+ [B<--dry-run>]
65
+
66
+ =head1 DESCRIPTION
67
+
68
+ I<pkg-dmg> takes a directory identified by I<source-folder> and transforms
69
+ it into a disk image stored as I<target-image>. The disk image will
70
+ occupy the least space possible for its format, or the least space that the
71
+ authors have been able to figure out how to achieve.
72
+
73
+ =head1 OPTIONS
74
+
75
+ =over 5
76
+
77
+ ==item B<--source> I<source-folder>
78
+
79
+ Identifies the directory that will be packaged up. This directory is not
80
+ touched, a copy will be made in a temporary directory for staging purposes.
81
+ See B<--tempdir>.
82
+
83
+ ==item B<--target> I<target-image>
84
+
85
+ The disk image to create. If it exists and is not in use, it will be
86
+ overwritten. If I<target-image> already contains a suitable extension,
87
+ it will be used unmodified. If no extension is present, or the extension
88
+ is incorrect for the selected format, the proper extension will be added.
89
+ See B<--format>.
90
+
91
+ ==item B<--format> I<format>
92
+
93
+ The format to create the disk image in. Valid values for I<format> are:
94
+ - UDZO - zlib-compressed, read-only; extension I<.dmg>
95
+ - UDRW - read-write; extension I<.dmg>
96
+ - UDSP - read-write, sparse; extension I<.sparseimage>
97
+
98
+ UDZO is the default format.
99
+
100
+ See L<hdiutil(1)> for a description of these formats.
101
+
102
+ =item B<--volname> I<volume-name>
103
+
104
+ The name of the volume in the disk image. If not specified, I<volume-name>
105
+ defaults to the name of the source directory from B<--source>.
106
+
107
+ =item B<--tempdir> I<temp-dir>
108
+
109
+ A temporary directory to stage intermediate files in. I<temp-dir> must
110
+ have enough space available to accommodate twice the size of the files
111
+ being packaged. If not specified, defaults to the same directory that
112
+ the I<target-image> is to be placed in. B<pkg-dmg> will remove any
113
+ temporary files it places in I<temp-dir>.
114
+
115
+ =item B<--mkdir> I<directory>
116
+
117
+ Specifies a directory that should be created in the disk image.
118
+ I<directory> and any ancestor directories will be created. This is
119
+ useful in conjunction with B<--copy>, when copying files to directories
120
+ that may not exist in I<source-folder>. B<--mkdir> may appear multiple
121
+ times.
122
+
123
+ =item B<--copy> I<source>[:I<dest>]
124
+
125
+ Additional files to copy into the disk image. If I<dest> is
126
+ specified, I<source> is copied to the location I<dest> identifies,
127
+ otherwise, I<source> is copied to the root of the new volume. B<--copy>
128
+ provides a way to package up a I<source-folder> by adding files to it
129
+ without modifying the original I<source-folder>. B<--copy> may appear
130
+ multiple times.
131
+
132
+ This option is useful for adding .DS_Store files and window backgrounds
133
+ to disk images.
134
+
135
+ =item B<--license> I<file>
136
+
137
+ A plain text file containing a license agreement to be displayed before
138
+ the disk image is mounted. English is the only supported language. To
139
+ include license agreements in other languages, in multiple languages,
140
+ or to use formatted text, prepare a resource and use L<--resource>.
141
+
142
+ =item B<--resource> I<file>
143
+
144
+ A resource file to merge into I<target-image>. If I<format> is UDZO,
145
+ the disk image will be flattened to a single-fork file that contains
146
+ the resource but may be freely transferred without any special encodings.
147
+ I<file> must be in a format suitable for L<Rez(1)>. See L<Rez(1)> for a
148
+ description of the format, and L<hdiutil(1)> for a discussion on flattened
149
+ disk images. B<--resource> may appear multiple times.
150
+
151
+ This option is useful for adding license agreements and other messages
152
+ to disk images.
153
+
154
+ =item B<--icon> I<icns-file>
155
+
156
+ Specifies an I<icns> file that will be used as the icon for the root of
157
+ the volume. This file will be copied to the new volume and the custom
158
+ icon attribute will be set on the root folder.
159
+
160
+ =item B<--attribute> I<a>:I<file>[:I<file>...]
161
+
162
+ Sets the attributes of I<file> to the attribute list in I<a>. See
163
+ L<SetFile(1)>
164
+
165
+ =item B<--idme>
166
+
167
+ Enable IDME to make the disk image "Internet-enabled." The first time
168
+ the image is mounted, if IDME processing is enabled on the system, the
169
+ contents of the image will be copied out of the image and the image will
170
+ be placed in the trash with IDME disabled.
171
+
172
+ =item B<--sourcefile>
173
+
174
+ If this option is present, I<source-folder> is treated as a file, and is
175
+ placed as a file within the volume's root folder. Without this option,
176
+ I<source-folder> is treated as the volume root itself.
177
+
178
+ =item B<--verbosity> I<level>
179
+
180
+ Adjusts the level of loudness of B<pkg-dmg>. The possible values for
181
+ I<level> are:
182
+ 0 - Only error messages are displayed.
183
+ 1 - Print error messages and command invocations.
184
+ 2 - Print everything, including command output.
185
+
186
+ The default I<level> is 2.
187
+
188
+ =item B<--dry-run>
189
+
190
+ When specified, the commands that would be executed are printed, without
191
+ actually executing them. When commands depend on the output of previous
192
+ commands, dummy values are displayed.
193
+
194
+ =back
195
+
196
+ =head1 NON-OPTIONS
197
+
198
+ =over 5
199
+
200
+ =item
201
+
202
+ Resource forks aren't copied.
203
+
204
+ =item
205
+
206
+ The root folder of the created volume is designated as the folder
207
+ to open when the volume is mounted. See L<bless(8)>.
208
+
209
+ =item
210
+
211
+ All files in the volume are set to be world-readable, only writable
212
+ by the owner, and world-executable when appropriate. All other
213
+ permissions bits are cleared.
214
+
215
+ =item
216
+
217
+ When possible, disk images are created without any partition tables. This
218
+ is what L<hdiutil(1)> refers to as I<-layout NONE>, and saves a handful of
219
+ kilobytes. The alternative, I<SPUD>, contains a partition table that
220
+ is not terribly handy on disk images that are not intended to represent any
221
+ physical disk.
222
+
223
+ =item
224
+
225
+ Read-write images are created with journaling off. Any read-write image
226
+ created by this tool is expected to be transient, and the goal of this tool
227
+ is to create images which consume a minimum of space.
228
+
229
+ =back
230
+
231
+ =head1 EXAMPLE
232
+
233
+ pkg-dmg --source /Applications/DeerPark.app --target ~/DeerPark.dmg
234
+ --sourcefile --volname DeerPark --icon ~/DeerPark.icns
235
+ --mkdir /.background
236
+ --copy DeerParkBackground.png:/.background/background.png
237
+ --copy DeerParkDSStore:/.DS_Store
238
+
239
+ =head1 REQUIREMENTS
240
+
241
+ I<pkg-dmg> has been tested with Mac OS X releases 10.2 ("Jaguar")
242
+ through 10.4 ("Tiger"). Certain adjustments to behavior are made
243
+ depending on the host system's release. Mac OS X 10.3 ("Panther") or
244
+ later are recommended.
245
+
246
+ =head1 LICENSE
247
+
248
+ MPL 1.1/GPL 2.0/LGPL 2.1. Your choice.
249
+
250
+ =head1 AUTHOR
251
+
252
+ Mark Mentovai
253
+
254
+ =head1 SEE ALSO
255
+
256
+ L<bless(8)>, L<diskutil(8)>, L<hdid(8)>, L<hdiutil(1)>, L<Rez(1)>,
257
+ L<rsync(1)>, L<SetFile(1)>
258
+
259
+ =cut
260
+
261
+ use Fcntl;
262
+ use POSIX;
263
+ use Getopt::Long;
264
+
265
+ sub argumentEscape(@);
266
+ sub cleanupDie($);
267
+ sub command(@);
268
+ sub commandInternal($@);
269
+ sub commandInternalVerbosity($$@);
270
+ sub commandOutput(@);
271
+ sub commandOutputVerbosity($@);
272
+ sub commandVerbosity($@);
273
+ sub diskImageMaker($$$$$$$$);
274
+ sub giveExtension($$);
275
+ sub hdidMountImage($@);
276
+ sub licenseMaker($$);
277
+ sub pathSplit($);
278
+ sub setAttributes($@);
279
+ sub trapSignal($);
280
+ sub usage();
281
+
282
+ # Variables used as globals
283
+ my(@gCleanup, %gConfig, $gDarwinMajor, $gDryRun, $gVerbosity);
284
+
285
+ # Use the commands by name if they're expected to be in the user's
286
+ # $PATH (/bin:/sbin:/usr/bin:/usr/sbin). Otherwise, go by absolute
287
+ # path. These may be overridden with --config.
288
+ %gConfig = ('cmd_bless' => 'bless',
289
+ 'cmd_chmod' => 'chmod',
290
+ 'cmd_diskutil' => 'diskutil',
291
+ 'cmd_du' => 'du',
292
+ 'cmd_hdid' => 'hdid',
293
+ 'cmd_hdiutil' => 'hdiutil',
294
+ 'cmd_mkdir' => 'mkdir',
295
+ 'cmd_mktemp' => 'mktemp',
296
+ 'cmd_Rez' => '/Developer/Tools/Rez',
297
+ 'cmd_rm' => 'rm',
298
+ 'cmd_rsync' => 'rsync',
299
+ 'cmd_SetFile' => '/Developer/Tools/SetFile',
300
+
301
+ # create_directly indicates whether hdiutil create supports
302
+ # -srcfolder and -srcdevice. It does on >= 10.3 (Panther).
303
+ # This is fixed up for earlier systems below. If false,
304
+ # hdiutil create is used to create empty disk images that
305
+ # are manually filled.
306
+ 'create_directly' => 1,
307
+
308
+ # If hdiutil attach -mountpoint exists, use it to avoid
309
+ # mounting disk images in the default /Volumes. This reduces
310
+ # the likelihood that someone will notice a mounted image and
311
+ # interfere with it. Only available on >= 10.3 (Panther),
312
+ # fixed up for earlier systems below.
313
+ #
314
+ # This is presently turned off for all systems, because there
315
+ # is an infrequent synchronization problem during ejection.
316
+ # diskutil eject might return before the image is actually
317
+ # unmounted. If pkg-dmg then attempts to clean up its
318
+ # temporary directory, it could remove items from a read-write
319
+ # disk image or attempt to remove items from a read-only disk
320
+ # image (or a read-only item from a read-write image) and fail,
321
+ # causing pkg-dmg to abort. This problem is experienced
322
+ # under Tiger, which appears to eject asynchronously where
323
+ # previous systems treated it as a synchronous operation.
324
+ # Using hdiutil attach -mountpoint didn't always keep images
325
+ # from showing up on the desktop anyway.
326
+ 'hdiutil_mountpoint' => 0,
327
+
328
+ # hdiutil makehybrid results in optimized disk images that
329
+ # consume less space and mount more quickly. Use it when
330
+ # it's available, but that's only on >= 10.3 (Panther).
331
+ # If false, hdiutil create is used instead. Fixed up for
332
+ # earlier systems below.
333
+ 'makehybrid' => 1,
334
+
335
+ # hdiutil create doesn't allow specifying a folder to open
336
+ # at volume mount time, so those images are mounted and
337
+ # their root folders made holy with bless -openfolder. But
338
+ # only on >= 10.3 (Panther). Earlier systems are out of luck.
339
+ # Even on Panther, bless refuses to run unless root.
340
+ # Fixed up below.
341
+ 'openfolder_bless' => 1,
342
+
343
+ # It's possible to save a few more kilobytes by including the
344
+ # partition only without any partition table in the image.
345
+ # This is a good idea on any system, so turn this option off.
346
+ #
347
+ # Except it's buggy. "-layout NONE" seems to be creating
348
+ # disk images with more data than just the partition table
349
+ # stripped out. You might wind up losing the end of the
350
+ # filesystem - the last file (or several) might be incomplete.
351
+ 'partition_table' => 1,
352
+
353
+ # To create a partition table-less image from something
354
+ # created by makehybrid, the hybrid image needs to be
355
+ # mounted and a new image made from the device associated
356
+ # with the relevant partition. This requires >= 10.4
357
+ # (Tiger), presumably because earlier systems have
358
+ # problems creating images from devices themselves attached
359
+ # to images. If this is false, makehybrid images will
360
+ # have partition tables, regardless of the partition_table
361
+ # setting. Fixed up for earlier systems below.
362
+ 'recursive_access' => 1);
363
+
364
+ # --verbosity
365
+ $gVerbosity = 2;
366
+
367
+ # --dry-run
368
+ $gDryRun = 0;
369
+
370
+ # %gConfig fix-ups based on features and bugs present in certain releases.
371
+ my($ignore, $uname_r, $uname_s);
372
+ ($uname_s, $ignore, $uname_r, $ignore, $ignore) = POSIX::uname();
373
+ if($uname_s eq 'Darwin') {
374
+ ($gDarwinMajor, $ignore) = split(/\./, $uname_r, 2);
375
+
376
+ # $major is the Darwin major release, which for our purposes, is 4 higher
377
+ # than the interesting digit in a Mac OS X release.
378
+ if($gDarwinMajor <= 6) {
379
+ # <= 10.2 (Jaguar)
380
+ # hdiutil create does not support -srcfolder or -srcdevice
381
+ $gConfig{'create_directly'} = 0;
382
+ # hdiutil attach does not support -mountpoint
383
+ $gConfig{'hdiutil_mountpoint'} = 0;
384
+ # hdiutil mkhybrid does not exist
385
+ $gConfig{'makehybrid'} = 0;
386
+ }
387
+ if($gDarwinMajor <= 7) {
388
+ # <= 10.3 (Panther)
389
+ # Can't mount a disk image and then make a disk image from the device
390
+ $gConfig{'recursive_access'} = 0;
391
+ # bless does not support -openfolder on 10.2 (Jaguar) and must run
392
+ # as root under 10.3 (Panther)
393
+ $gConfig{'openfolder_bless'} = 0;
394
+ }
395
+ }
396
+ else {
397
+ # If it's not Mac OS X, just assume all of those good features are
398
+ # available. They're not, but things will fail long before they
399
+ # have a chance to make a difference.
400
+ #
401
+ # Now, if someone wanted to document some of these private formats...
402
+ print STDERR ($0.": warning, not running on Mac OS X, ".
403
+ "this could be interesting.\n");
404
+ }
405
+
406
+ # Non-global variables used in Getopt
407
+ my(@attributes, @copyFiles, $iconFile, $idme, $licenseFile, @makeDirs,
408
+ $outputFormat, @resourceFiles, $sourceFile, $sourceFolder, $targetImage,
409
+ $tempDir, $volumeName);
410
+
411
+ # --format
412
+ $outputFormat = 'UDZO';
413
+
414
+ # --idme
415
+ $idme = 0;
416
+
417
+ # --sourcefile
418
+ $sourceFile = 0;
419
+
420
+ # Leaving this might screw up the Apple tools.
421
+ delete $ENV{'NEXT_ROOT'};
422
+
423
+ # This script can get pretty messy, so trap a few signals.
424
+ $SIG{'INT'} = \&trapSignal;
425
+ $SIG{'HUP'} = \&trapSignal;
426
+ $SIG{'TERM'} = \&trapSignal;
427
+
428
+ Getopt::Long::Configure('pass_through');
429
+ GetOptions('source=s' => \$sourceFolder,
430
+ 'target=s' => \$targetImage,
431
+ 'volname=s' => \$volumeName,
432
+ 'format=s' => \$outputFormat,
433
+ 'tempdir=s' => \$tempDir,
434
+ 'mkdir=s' => \@makeDirs,
435
+ 'copy=s' => \@copyFiles,
436
+ 'license=s' => \$licenseFile,
437
+ 'resource=s' => \@resourceFiles,
438
+ 'icon=s' => \$iconFile,
439
+ 'attribute=s' => \@attributes,
440
+ 'idme' => \$idme,
441
+ 'sourcefile' => \$sourceFile,
442
+ 'verbosity=i' => \$gVerbosity,
443
+ 'dry-run' => \$gDryRun,
444
+ 'config=s' => \%gConfig); # "hidden" option not in usage()
445
+
446
+ if(@ARGV) {
447
+ # All arguments are parsed by Getopt
448
+ usage();
449
+ exit(1);
450
+ }
451
+
452
+ if($gVerbosity<0 || $gVerbosity>2) {
453
+ usage();
454
+ exit(1);
455
+ }
456
+
457
+ if(!defined($sourceFolder) || $sourceFolder eq '' ||
458
+ !defined($targetImage) || $targetImage eq '') {
459
+ # --source and --target are required arguments
460
+ usage();
461
+ exit(1);
462
+ }
463
+
464
+ # Make sure $sourceFolder doesn't contain trailing slashes. It messes with
465
+ # rsync.
466
+ while(substr($sourceFolder, -1) eq '/') {
467
+ chop($sourceFolder);
468
+ }
469
+
470
+ if(!defined($volumeName)) {
471
+ # Default volumeName is the name of the source directory.
472
+ my(@components);
473
+ @components = pathSplit($sourceFolder);
474
+ $volumeName = pop(@components);
475
+ }
476
+
477
+ my(@tempDirComponents, $targetImageFilename);
478
+ @tempDirComponents = pathSplit($targetImage);
479
+ $targetImageFilename = pop(@tempDirComponents);
480
+
481
+ if(defined($tempDir)) {
482
+ @tempDirComponents = pathSplit($tempDir);
483
+ }
484
+ else {
485
+ # Default tempDir is the same directory as what is specified for
486
+ # targetImage
487
+ $tempDir = join('/', @tempDirComponents);
488
+ }
489
+
490
+ # Ensure that the path of the target image has a suitable extension. If
491
+ # it didn't, hdiutil would add one, and we wouldn't be able to find the
492
+ # file.
493
+ #
494
+ # Note that $targetImageFilename is not being reset. This is because it's
495
+ # used to build other names below, and we don't need to be adding all sorts
496
+ # of extra unnecessary extensions to the name.
497
+ my($originalTargetImage, $requiredExtension);
498
+ $originalTargetImage = $targetImage;
499
+ if($outputFormat eq 'UDSP') {
500
+ $requiredExtension = '.sparseimage';
501
+ }
502
+ else {
503
+ $requiredExtension = '.dmg';
504
+ }
505
+ $targetImage = giveExtension($originalTargetImage, $requiredExtension);
506
+
507
+ if($targetImage ne $originalTargetImage) {
508
+ print STDERR ($0.": warning: target image extension is being added\n");
509
+ print STDERR (' The new filename is '.
510
+ giveExtension($targetImageFilename,$requiredExtension)."\n");
511
+ }
512
+
513
+ # Make a temporary directory in $tempDir for our own nefarious purposes.
514
+ my(@output, $tempSubdir, $tempSubdirTemplate);
515
+ $tempSubdirTemplate=join('/', @tempDirComponents,
516
+ 'pkg-dmg.'.$$.'.XXXXXXXX');
517
+ if(!(@output = commandOutput($gConfig{'cmd_mktemp'}, '-d',
518
+ $tempSubdirTemplate)) || $#output != 0) {
519
+ cleanupDie('mktemp failed');
520
+ }
521
+
522
+ if($gDryRun) {
523
+ (@output)=($tempSubdirTemplate);
524
+ }
525
+
526
+ ($tempSubdir) = @output;
527
+
528
+ push(@gCleanup,
529
+ sub {commandVerbosity(0, $gConfig{'cmd_rm'}, '-rf', $tempSubdir);});
530
+
531
+ my($tempMount, $tempRoot, @tempsToMake);
532
+ $tempRoot = $tempSubdir.'/stage';
533
+ $tempMount = $tempSubdir.'/mount';
534
+ push(@tempsToMake, $tempRoot);
535
+ if($gConfig{'hdiutil_mountpoint'}) {
536
+ push(@tempsToMake, $tempMount);
537
+ }
538
+
539
+ if(command($gConfig{'cmd_mkdir'}, @tempsToMake) != 0) {
540
+ cleanupDie('mkdir tempRoot/tempMount failed');
541
+ }
542
+
543
+ # This cleanup object is not strictly necessary, because $tempRoot is inside
544
+ # of $tempSubdir, but the rest of the script relies on this object being
545
+ # on the cleanup stack and expects to remove it.
546
+ push(@gCleanup,
547
+ sub {commandVerbosity(0, $gConfig{'cmd_rm'}, '-rf', $tempRoot);});
548
+
549
+ # If $sourceFile is true, it means that $sourceFolder is to be treated as
550
+ # a file and placed as a file within the volume root, as opposed to being
551
+ # treated as the volume root itself. rsync will do this by default, if no
552
+ # trailing '/' is present. With a trailing '/', $sourceFolder becomes
553
+ # $tempRoot, instead of becoming an entry in $tempRoot.
554
+ if(command($gConfig{'cmd_rsync'}, '-a',
555
+ $sourceFolder.($sourceFile?'':'/'),$tempRoot) != 0) {
556
+ cleanupDie('rsync failed');
557
+ }
558
+
559
+ if(@makeDirs) {
560
+ my($makeDir, @tempDirsToMake);
561
+ foreach $makeDir (@makeDirs) {
562
+ if($makeDir =~ /^\//) {
563
+ push(@tempDirsToMake, $tempRoot.$makeDir);
564
+ }
565
+ else {
566
+ push(@tempDirsToMake, $tempRoot.'/'.$makeDir);
567
+ }
568
+ }
569
+ if(command($gConfig{'cmd_mkdir'}, '-p', @tempDirsToMake) != 0) {
570
+ cleanupDie('mkdir failed');
571
+ }
572
+ }
573
+
574
+ my($copyFile);
575
+ foreach $copyFile (@copyFiles) {
576
+ my($copySource, $copyDestination);
577
+ ($copySource, $copyDestination) = split(/:/, $copyFile);
578
+ if(!defined($copyDestination)) {
579
+ $copyDestination = $tempRoot;
580
+ }
581
+ elsif($copyDestination =~ /^\//) {
582
+ $copyDestination = $tempRoot.$copyDestination;
583
+ }
584
+ else {
585
+ $copyDestination = $tempRoot.'/'.$copyDestination;
586
+ }
587
+ if(command($gConfig{'cmd_rsync'}, '-a',
588
+ $copySource, $copyDestination) != 0) {
589
+ cleanupDie('rsync failed for item copy');
590
+ }
591
+ }
592
+
593
+ if($gConfig{'create_directly'}) {
594
+ # If create_directly is false, the contents will be rsynced into a
595
+ # disk image and they would lose their attributes.
596
+ setAttributes($tempRoot, @attributes);
597
+ }
598
+
599
+ if(defined($iconFile)) {
600
+ if(command($gConfig{'cmd_rsync'}, '-a', $iconFile,
601
+ $tempRoot.'/.VolumeIcon.icns') != 0) {
602
+ cleanupDie('rsync failed for volume icon');
603
+ }
604
+
605
+ # It's pointless to set the attributes of the root when diskutil create
606
+ # -srcfolder is being used. In that case, the attributes will be set
607
+ # later, after the image is already created.
608
+ if($outputFormat eq 'UDZO' &&
609
+ (command($gConfig{'cmd_SetFile'}, '-a', 'C', $tempRoot) != 0)) {
610
+ cleanupDie('SetFile failed');
611
+ }
612
+ }
613
+
614
+ if(command($gConfig{'cmd_chmod'}, '-R', 'a+rX,a-st,u+w,go-w',
615
+ $tempRoot) != 0) {
616
+ cleanupDie('chmod failed');
617
+ }
618
+
619
+ my($unflattenable);
620
+ if($outputFormat eq 'UDZO') {
621
+ $unflattenable = 1;
622
+ }
623
+ else {
624
+ $unflattenable = 0;
625
+ }
626
+
627
+ diskImageMaker($tempRoot, $targetImage, $outputFormat, $volumeName,
628
+ $tempSubdir, $tempMount, $targetImageFilename, defined($iconFile));
629
+
630
+ if(defined($licenseFile) && $licenseFile ne '') {
631
+ my($licenseResource);
632
+ $licenseResource = $tempSubdir.'/license.r';
633
+ if(!licenseMaker($licenseFile, $licenseResource)) {
634
+ cleanupDie('licenseMaker failed');
635
+ }
636
+ push(@resourceFiles, $licenseResource);
637
+ # Don't add a cleanup object because licenseResource is in tempSubdir.
638
+ }
639
+
640
+ if(@resourceFiles) {
641
+ # Add resources, such as a license agreement.
642
+
643
+ # Only unflatten read-only and compressed images. It's not supported
644
+ # on other image times.
645
+ if($unflattenable &&
646
+ (command($gConfig{'cmd_hdiutil'}, 'unflatten', $targetImage)) != 0) {
647
+ cleanupDie('hdiutil unflatten failed');
648
+ }
649
+ # Don't push flatten onto the cleanup stack. If we fail now, we'll be
650
+ # removing $targetImage anyway.
651
+
652
+ # Type definitions come from Carbon.r.
653
+ if(command($gConfig{'cmd_Rez'}, 'Carbon.r', @resourceFiles, '-a', '-o',
654
+ $targetImage) != 0) {
655
+ cleanupDie('Rez failed');
656
+ }
657
+
658
+ # Flatten. This merges the resource fork into the data fork, so no
659
+ # special encoding is needed to transfer the file.
660
+ if($unflattenable &&
661
+ (command($gConfig{'cmd_hdiutil'}, 'flatten', $targetImage)) != 0) {
662
+ cleanupDie('hdiutil flatten failed');
663
+ }
664
+ }
665
+
666
+ # $tempSubdir is no longer needed. It's buried on the stack below the
667
+ # rm of the fresh image file. Splice in this fashion is equivalent to
668
+ # pop-save, pop, push-save.
669
+ splice(@gCleanup, -2, 1);
670
+ # No need to remove licenseResource separately, it's in tempSubdir.
671
+ if(command($gConfig{'cmd_rm'}, '-rf', $tempSubdir) != 0) {
672
+ cleanupDie('rm -rf tempSubdir failed');
673
+ }
674
+
675
+ if($idme) {
676
+ if(command($gConfig{'cmd_hdiutil'}, 'internet-enable', '-yes',
677
+ $targetImage) != 0) {
678
+ cleanupDie('hdiutil internet-enable failed');
679
+ }
680
+ }
681
+
682
+ # Done.
683
+
684
+ exit(0);
685
+
686
+ # argumentEscape(@arguments)
687
+ #
688
+ # Takes a list of @arguments and makes them shell-safe.
689
+ sub argumentEscape(@) {
690
+ my(@arguments);
691
+ @arguments = @_;
692
+ my($argument, @argumentsOut);
693
+ foreach $argument (@arguments) {
694
+ $argument =~ s%([^A-Za-z0-9_\-/.=+,])%\\$1%g;
695
+ push(@argumentsOut, $argument);
696
+ }
697
+ return @argumentsOut;
698
+ }
699
+
700
+ # cleanupDie($message)
701
+ #
702
+ # Displays $message as an error message, and then runs through the
703
+ # @gCleanup stack, performing any cleanup operations needed before
704
+ # exiting. Does not return, exits with exit status 1.
705
+ sub cleanupDie($) {
706
+ my($message);
707
+ ($message) = @_;
708
+ print STDERR ($0.': '.$message.(@gCleanup?' (cleaning up)':'')."\n");
709
+ while(@gCleanup) {
710
+ my($subroutine);
711
+ $subroutine = pop(@gCleanup);
712
+ &$subroutine;
713
+ }
714
+ exit(1);
715
+ }
716
+
717
+ # command(@arguments)
718
+ #
719
+ # Runs the specified command at the verbosity level defined by $gVerbosity.
720
+ # Returns nonzero on failure, returning the exit status if appropriate.
721
+ # Discards command output.
722
+ sub command(@) {
723
+ my(@arguments);
724
+ @arguments = @_;
725
+ return commandVerbosity($gVerbosity,@arguments);
726
+ }
727
+
728
+ # commandInternal($command, @arguments)
729
+ #
730
+ # Removes the files specified by @arguments with a verbosity level specified
731
+ # by $gVerbosity.
732
+ sub commandInternal($@) {
733
+ my(@arguments, $command);
734
+ ($command, @arguments) = @_;
735
+ return commandInternalVerbosity($gVerbosity, $command, @arguments);
736
+ }
737
+
738
+ # commandInternalVerbosity($verbosity, $command, @arguments)
739
+ #
740
+ # Run an internal command, printing a bogus command invocation message if
741
+ # $verbosity is true.
742
+ #
743
+ # If $command is unlink:
744
+ # Removes the files specified by @arguments. Wraps unlink.
745
+ #
746
+ # If $command is mkdir:
747
+ # Creates the directory specified by @arguments, with an optional mask
748
+ # argument, wrapping mkdir.
749
+ sub commandInternalVerbosity($$@) {
750
+ my(@arguments, $command, $verbosity);
751
+ ($verbosity, $command, @arguments) = @_;
752
+ if($command eq 'unlink') {
753
+ if($verbosity || $gDryRun) {
754
+ print(join(' ', 'rm', '-f', argumentEscape(@arguments))."\n");
755
+ }
756
+ if($gDryRun) {
757
+ return $#arguments+1;
758
+ }
759
+ return unlink(@arguments);
760
+ }
761
+ }
762
+
763
+ # commandOutput(@arguments)
764
+ #
765
+ # Runs the specified command at the verbosity level defined by $gVerbosity.
766
+ # Output is returned in an array of lines. undef is returned on failure.
767
+ # The exit status is available in $?.
768
+ sub commandOutput(@) {
769
+ my(@arguments);
770
+ @arguments = @_;
771
+ return commandOutputVerbosity($gVerbosity, @arguments);
772
+ }
773
+
774
+ # commandOutputVerbosity($verbosity, @arguments)
775
+ #
776
+ # Runs the specified command at the verbosity level defined by the
777
+ # $verbosity argument. Output is returned in an array of lines. undef is
778
+ # returned on failure. The exit status is available in $?.
779
+ #
780
+ # If an error occurs in fork or exec, an error message is printed to
781
+ # stderr and undef is returned.
782
+ #
783
+ # If $verbosity is 0, the command invocation is not printed, and its
784
+ # stdout is not echoed back to stdout.
785
+ #
786
+ # If $verbosity is 1, the command invocation is printed.
787
+ #
788
+ # If $verbosity is 2, the command invocation is printed and the output
789
+ # from stdout is echoed back to stdout.
790
+ #
791
+ # Regardless of $verbosity, stderr is left connected.
792
+ sub commandOutputVerbosity($@) {
793
+ my(@arguments, $verbosity);
794
+ ($verbosity, @arguments) = @_;
795
+ my($pid);
796
+ if($verbosity || $gDryRun) {
797
+ print(join(' ', argumentEscape(@arguments))."\n");
798
+ }
799
+ if($gDryRun) {
800
+ return(1);
801
+ }
802
+ if (!defined($pid = open(*COMMAND, '-|'))) {
803
+ printf STDERR ($0.': fork: '.$!."\n");
804
+ return undef;
805
+ }
806
+ elsif ($pid) {
807
+ # parent
808
+ my(@lines);
809
+ while(!eof(*COMMAND)) {
810
+ my($line);
811
+ chop($line = <COMMAND>);
812
+ if($verbosity > 1) {
813
+ print($line."\n");
814
+ }
815
+ push(@lines, $line);
816
+ }
817
+ close(*COMMAND);
818
+ if ($? == -1) {
819
+ printf STDERR ($0.': fork: '.$!."\n");
820
+ return undef;
821
+ }
822
+ elsif ($? & 127) {
823
+ printf STDERR ($0.': exited on signal '.($? & 127).
824
+ ($? & 128 ? ', core dumped' : '')."\n");
825
+ return undef;
826
+ }
827
+ return @lines;
828
+ }
829
+ else {
830
+ # child; this form of exec is immune to shell games
831
+ if(!exec {$arguments[0]} (@arguments)) {
832
+ printf STDERR ($0.': exec: '.$!."\n");
833
+ exit(-1);
834
+ }
835
+ }
836
+ }
837
+
838
+ # commandVerbosity($verbosity, @arguments)
839
+ #
840
+ # Runs the specified command at the verbosity level defined by the
841
+ # $verbosity argument. Returns nonzero on failure, returning the exit
842
+ # status if appropriate. Discards command output.
843
+ sub commandVerbosity($@) {
844
+ my(@arguments, $verbosity);
845
+ ($verbosity, @arguments) = @_;
846
+ if(!defined(commandOutputVerbosity($verbosity, @arguments))) {
847
+ return -1;
848
+ }
849
+ return $?;
850
+ }
851
+
852
+ # diskImageMaker($source, $destination, $format, $name, $tempDir, $tempMount,
853
+ # $baseName, $setRootIcon)
854
+ #
855
+ # Creates a disk image in $destination of format $format corresponding to the
856
+ # source directory $source. $name is the volume name. $tempDir is a good
857
+ # place to write temporary files, which should be empty (aside from the other
858
+ # things that this script might create there, like stage and mount).
859
+ # $tempMount is a mount point for temporary disk images. $baseName is the
860
+ # name of the disk image, and is presently unused. $setRootIcon is true if
861
+ # a volume icon was added to the staged $source and indicates that the
862
+ # custom volume icon bit on the volume root needs to be set.
863
+ sub diskImageMaker($$$$$$$$) {
864
+ my($baseName, $destination, $format, $name, $setRootIcon, $source,
865
+ $tempDir, $tempMount);
866
+ ($source, $destination, $format, $name, $tempDir, $tempMount,
867
+ $baseName, $setRootIcon) = @_;
868
+ if($format eq 'UDZO') {
869
+ my($uncompressedImage);
870
+
871
+ if($gConfig{'makehybrid'}) {
872
+ my($hybridImage);
873
+ $hybridImage = giveExtension($tempDir.'/hybrid', '.dmg');
874
+
875
+ if(command($gConfig{'cmd_hdiutil'}, 'makehybrid', '-hfs',
876
+ '-hfs-volume-name', $name, '-hfs-openfolder', $source, '-ov',
877
+ $source, '-o', $hybridImage) != 0) {
878
+ cleanupDie('hdiutil makehybrid failed');
879
+ }
880
+
881
+ $uncompressedImage = $hybridImage;
882
+
883
+ # $source is no longer needed and will be removed before anything
884
+ # else can fail. splice in this form is the same as pop/push.
885
+ splice(@gCleanup, -1, 1,
886
+ sub {commandInternalVerbosity(0, 'unlink', $hybridImage);});
887
+
888
+ if(command($gConfig{'cmd_rm'}, '-rf', $source) != 0) {
889
+ cleanupDie('rm -rf failed');
890
+ }
891
+
892
+ if(!$gConfig{'partition_table'} && $gConfig{'recursive_access'}) {
893
+ # Even if we do want to create disk images without partition tables,
894
+ # it's impossible unless recursive_access is set.
895
+ my($rootDevice, $partitionDevice, $partitionMountPoint);
896
+
897
+ if(!(($rootDevice, $partitionDevice, $partitionMountPoint) =
898
+ hdidMountImage($tempMount, '-readonly', $hybridImage))) {
899
+ cleanupDie('hdid mount failed');
900
+ }
901
+
902
+ push(@gCleanup, sub {commandVerbosity(0,
903
+ $gConfig{'cmd_diskutil'}, 'eject', $rootDevice);});
904
+
905
+ my($udrwImage);
906
+ $udrwImage = giveExtension($tempDir.'/udrw', '.dmg');
907
+
908
+ if(command($gConfig{'cmd_hdiutil'}, 'create', '-format', 'UDRW',
909
+ '-ov', '-srcdevice', $partitionDevice, $udrwImage) != 0) {
910
+ cleanupDie('hdiutil create failed');
911
+ }
912
+
913
+ $uncompressedImage = $udrwImage;
914
+
915
+ # Going to eject before anything else can fail. Get the eject off
916
+ # the stack.
917
+ pop(@gCleanup);
918
+
919
+ # $hybridImage will be removed soon, but until then, it needs to
920
+ # stay on the cleanup stack. It needs to wait until after
921
+ # ejection. $udrwImage is staying around. Make it appear as
922
+ # though it's been done before $hybridImage.
923
+ #
924
+ # splice in this form is the same as popping one element to
925
+ # @tempCleanup and pushing the subroutine.
926
+ my(@tempCleanup);
927
+ @tempCleanup = splice(@gCleanup, -1, 1,
928
+ sub {commandInternalVerbosity(0, 'unlink', $udrwImage);});
929
+ push(@gCleanup, @tempCleanup);
930
+
931
+ if(command($gConfig{'cmd_diskutil'}, 'eject', $rootDevice) != 0) {
932
+ cleanupDie('diskutil eject failed');
933
+ }
934
+
935
+ # Pop unlink of $uncompressedImage
936
+ pop(@gCleanup);
937
+
938
+ if(commandInternal('unlink', $hybridImage) != 1) {
939
+ cleanupDie('unlink hybridImage failed: '.$!);
940
+ }
941
+ }
942
+ }
943
+ else {
944
+ # makehybrid is not available, fall back to making a UDRW and
945
+ # converting to UDZO. It ought to be possible to do a UDZO directly,
946
+ # but those come out far too large (journaling?) and need to be
947
+ # read-write to fix up the volume icon anyway. Luckily, we can
948
+ # take advantage of a single call back into this function.
949
+ my($udrwImage);
950
+ $udrwImage = giveExtension($tempDir.'/udrw', '.dmg');
951
+
952
+ diskImageMaker($source, $udrwImage, 'UDRW', $name, $tempDir,
953
+ $tempMount, $baseName, $setRootIcon);
954
+
955
+ # The call back into diskImageMaker already removed $source.
956
+
957
+ $uncompressedImage = $udrwImage;
958
+ }
959
+
960
+ # The uncompressed disk image is now in its final form. Compress it.
961
+ # Jaguar doesn't support hdiutil convert -ov, but it always allows
962
+ # overwriting.
963
+ if(command($gConfig{'cmd_hdiutil'}, 'convert', '-format', 'UDZO',
964
+ '-imagekey', 'zlib-level=9',
965
+ (defined($gDarwinMajor) && $gDarwinMajor <= 6 ? () : ('-ov')),
966
+ $uncompressedImage, '-o', $destination) != 0) {
967
+ cleanupDie('hdiutil convert failed');
968
+ }
969
+
970
+ # $uncompressedImage is going to be unlinked before anything else can
971
+ # fail. splice in this form is the same as pop/push.
972
+ splice(@gCleanup, -1, 1,
973
+ sub {commandInternalVerbosity(0, 'unlink', $destination);});
974
+
975
+ if(commandInternal('unlink', $uncompressedImage) != 1) {
976
+ cleanupDie('unlink uncompressedImage failed: '.$!);
977
+ }
978
+
979
+ # At this point, the only thing that the UDZO block has added to the
980
+ # cleanup stack is the removal of $destination. $source has already
981
+ # been removed, and its cleanup entry has been removed as well.
982
+ }
983
+ elsif($format eq 'UDRW' || $format eq 'UDSP') {
984
+ my(@extraArguments);
985
+ if(!$gConfig{'partition_table'}) {
986
+ @extraArguments = ('-layout', 'NONE');
987
+ }
988
+
989
+ if($gConfig{'create_directly'}) {
990
+ # Use -fs HFS+ to suppress the journal.
991
+ if(command($gConfig{'cmd_hdiutil'}, 'create', '-format', $format,
992
+ @extraArguments, '-fs', 'HFS+', '-volname', $name,
993
+ '-ov', '-srcfolder', $source, $destination) != 0) {
994
+ cleanupDie('hdiutil create failed');
995
+ }
996
+
997
+ # $source is no longer needed and will be removed before anything
998
+ # else can fail. splice in this form is the same as pop/push.
999
+ splice(@gCleanup, -1, 1,
1000
+ sub {commandInternalVerbosity(0, 'unlink', $destination);});
1001
+
1002
+ if(command($gConfig{'cmd_rm'}, '-rf', $source) != 0) {
1003
+ cleanupDie('rm -rf failed');
1004
+ }
1005
+ }
1006
+ else {
1007
+ # hdiutil create does not support -srcfolder or -srcdevice, it only
1008
+ # knows how to create blank images. Figure out how large an image
1009
+ # is needed, create it, and fill it. This is needed for Jaguar.
1010
+
1011
+ # Use native block size for hdiutil create -sectors.
1012
+ delete $ENV{'BLOCKSIZE'};
1013
+
1014
+ my(@duOutput, $ignore, $sizeBlocks, $sizeOverhead, $sizeTotal, $type);
1015
+ if(!(@output = commandOutput($gConfig{'cmd_du'}, '-s', $tempRoot)) ||
1016
+ $? != 0) {
1017
+ cleanupDie('du failed');
1018
+ }
1019
+ ($sizeBlocks, $ignore) = split(' ', $output[0], 2);
1020
+
1021
+ # The filesystem itself takes up 152 blocks of its own blocks for the
1022
+ # filesystem up to 8192 blocks, plus 64 blocks for every additional
1023
+ # 4096 blocks or portion thereof.
1024
+ $sizeOverhead = 152 + 64 * POSIX::ceil(
1025
+ (($sizeBlocks - 8192) > 0) ? (($sizeBlocks - 8192) / (4096 - 64)) : 0);
1026
+
1027
+ # The number of blocks must be divisible by 8.
1028
+ my($mod);
1029
+ if($mod = ($sizeOverhead % 8)) {
1030
+ $sizeOverhead += 8 - $mod;
1031
+ }
1032
+
1033
+ # sectors is taken as the size of a disk, not a filesystem, so the
1034
+ # partition table eats into it.
1035
+ if($gConfig{'partition_table'}) {
1036
+ $sizeOverhead += 80;
1037
+ }
1038
+
1039
+ # That was hard. Leave some breathing room anyway. Use 1024 sectors
1040
+ # (512kB). These read-write images wouldn't be useful if they didn't
1041
+ # have at least a little free space.
1042
+ $sizeTotal = $sizeBlocks + $sizeOverhead + 1024;
1043
+
1044
+ # Minimum sizes - these numbers are larger on Jaguar than on later
1045
+ # systems. Just use the Jaguar numbers, since it's unlikely to wind
1046
+ # up here on any other release.
1047
+ if($gConfig{'partition_table'} && $sizeTotal < 8272) {
1048
+ $sizeTotal = 8272;
1049
+ }
1050
+ if(!$gConfig{'partition_table'} && $sizeTotal < 8192) {
1051
+ $sizeTotal = 8192;
1052
+ }
1053
+
1054
+ # hdiutil create without -srcfolder or -srcdevice will not accept
1055
+ # -format. It uses -type. Fortunately, the two supported formats
1056
+ # here map directly to the only two supported types.
1057
+ if ($format eq 'UDSP') {
1058
+ $type = 'SPARSE';
1059
+ }
1060
+ else {
1061
+ $type = 'UDIF';
1062
+ }
1063
+
1064
+ if(command($gConfig{'cmd_hdiutil'}, 'create', '-type', $type,
1065
+ @extraArguments, '-fs', 'HFS+', '-volname', $name,
1066
+ '-ov', '-sectors', $sizeTotal, $destination) != 0) {
1067
+ cleanupDie('hdiutil create failed');
1068
+ }
1069
+
1070
+ push(@gCleanup,
1071
+ sub {commandInternalVerbosity(0, 'unlink', $destination);});
1072
+
1073
+ # The rsync will occur shortly.
1074
+ }
1075
+
1076
+ my($mounted, $rootDevice, $partitionDevice, $partitionMountPoint);
1077
+
1078
+ $mounted=0;
1079
+ if(!$gConfig{'create_directly'} || $gConfig{'openfolder_bless'} ||
1080
+ $setRootIcon) {
1081
+ # The disk image only needs to be mounted if:
1082
+ # create_directly is false, because the content needs to be copied
1083
+ # openfolder_bless is true, because bless -openfolder needs to run
1084
+ # setRootIcon is true, because the root needs its attributes set.
1085
+ if(!(($rootDevice, $partitionDevice, $partitionMountPoint) =
1086
+ hdidMountImage($tempMount, $destination))) {
1087
+ cleanupDie('hdid mount failed');
1088
+ }
1089
+
1090
+ $mounted=1;
1091
+
1092
+ push(@gCleanup, sub {commandVerbosity(0,
1093
+ $gConfig{'cmd_diskutil'}, 'eject', $rootDevice);});
1094
+ }
1095
+
1096
+ if(!$gConfig{'create_directly'}) {
1097
+ # Couldn't create and copy directly in one fell swoop. Now that
1098
+ # the volume is mounted, copy the files. --copy-unsafe-links is
1099
+ # unnecessary since it was used to copy everything to the staging
1100
+ # area. There can be no more unsafe links.
1101
+ if(command($gConfig{'cmd_rsync'}, '-a',
1102
+ $source.'/',$partitionMountPoint) != 0) {
1103
+ cleanupDie('rsync to new volume failed');
1104
+ }
1105
+
1106
+ # We need to get the rm -rf of $source off the stack, because it's
1107
+ # being cleaned up here. There are two items now on top of it:
1108
+ # removing the target image and, above that, ejecting it. Splice it
1109
+ # out.
1110
+ my(@tempCleanup);
1111
+ @tempCleanup = splice(@gCleanup, -2);
1112
+ # The next splice is the same as popping once and pushing @tempCleanup.
1113
+ splice(@gCleanup, -1, 1, @tempCleanup);
1114
+
1115
+ if(command($gConfig{'cmd_rm'}, '-rf', $source) != 0) {
1116
+ cleanupDie('rm -rf failed');
1117
+ }
1118
+ }
1119
+
1120
+ if($gConfig{'openfolder_bless'}) {
1121
+ # On Tiger, the bless docs say to use --openfolder, but only
1122
+ # --openfolder is accepted on Panther. Tiger takes it with a single
1123
+ # dash too. Jaguar is out of luck.
1124
+ if(command($gConfig{'cmd_bless'}, '-openfolder',
1125
+ $partitionMountPoint) != 0) {
1126
+ cleanupDie('bless failed');
1127
+ }
1128
+ }
1129
+
1130
+ setAttributes($partitionMountPoint, @attributes);
1131
+
1132
+ if($setRootIcon) {
1133
+ # When "hdiutil create -srcfolder" is used, the root folder's
1134
+ # attributes are not copied to the new volume. Fix up.
1135
+
1136
+ if(command($gConfig{'cmd_SetFile'}, '-a', 'C',
1137
+ $partitionMountPoint) != 0) {
1138
+ cleanupDie('SetFile failed');
1139
+ }
1140
+ }
1141
+
1142
+ if($mounted) {
1143
+ # Pop diskutil eject
1144
+ pop(@gCleanup);
1145
+
1146
+ if(command($gConfig{'cmd_diskutil'}, 'eject', $rootDevice) != 0) {
1147
+ cleanupDie('diskutil eject failed');
1148
+ }
1149
+ }
1150
+
1151
+ # End of UDRW/UDSP section. At this point, $source has been removed
1152
+ # and its cleanup entry has been removed from the stack.
1153
+ }
1154
+ else {
1155
+ cleanupDie('unrecognized format');
1156
+ print STDERR ($0.": unrecognized format\n");
1157
+ exit(1);
1158
+ }
1159
+ }
1160
+
1161
+ # giveExtension($file, $extension)
1162
+ #
1163
+ # If $file does not end in $extension, $extension is added. The new
1164
+ # filename is returned.
1165
+ sub giveExtension($$) {
1166
+ my($extension, $file);
1167
+ ($file, $extension) = @_;
1168
+ if(substr($file, -length($extension)) ne $extension) {
1169
+ return $file.$extension;
1170
+ }
1171
+ return $file;
1172
+ }
1173
+
1174
+ # hdidMountImage($mountPoint, @arguments)
1175
+ #
1176
+ # Runs the hdid command with arguments specified by @arguments.
1177
+ # @arguments may be a single-element array containing the name of the
1178
+ # disk image to mount. Returns a three-element array, with elements
1179
+ # corresponding to:
1180
+ # - The root device of the mounted image, suitable for ejection
1181
+ # - The device corresponding to the mounted partition
1182
+ # - The mounted partition's mount point
1183
+ #
1184
+ # If running on a system that supports easy mounting at points outside
1185
+ # of the default /Volumes with hdiutil attach, it is used instead of hdid,
1186
+ # and $mountPoint is used as the mount point.
1187
+ #
1188
+ # The root device will differ from the partition device when the disk
1189
+ # image contains a partition table, otherwise, they will be identical.
1190
+ #
1191
+ # If hdid fails, undef is returned.
1192
+ sub hdidMountImage($@) {
1193
+ my(@arguments, @command, $mountPoint);
1194
+ ($mountPoint, @arguments) = @_;
1195
+ my(@output);
1196
+
1197
+ if($gConfig{'hdiutil_mountpoint'}) {
1198
+ @command=($gConfig{'cmd_hdiutil'}, 'attach', @arguments,
1199
+ '-mountpoint', $mountPoint);
1200
+ }
1201
+ else {
1202
+ @command=($gConfig{'cmd_hdid'}, @arguments);
1203
+ }
1204
+
1205
+ if(!(@output = commandOutput(@command)) ||
1206
+ $? != 0) {
1207
+ return undef;
1208
+ }
1209
+
1210
+ if($gDryRun) {
1211
+ return('/dev/diskX','/dev/diskXsY','/Volumes/'.$volumeName);
1212
+ }
1213
+
1214
+ my($line, $restOfLine, $rootDevice);
1215
+
1216
+ foreach $line (@output) {
1217
+ my($device, $mountpoint);
1218
+ if($line !~ /^\/dev\//) {
1219
+ # Consider only lines that correspond to /dev entries
1220
+ next;
1221
+ }
1222
+ ($device, $restOfLine) = split(' ', $line, 2);
1223
+
1224
+ if(!defined($rootDevice) || $rootDevice eq '') {
1225
+ # If this is the first device seen, it's the root device to be
1226
+ # used for ejection. Keep it.
1227
+ $rootDevice = $device;
1228
+ }
1229
+
1230
+ if($restOfLine =~ /(\/.*)/) {
1231
+ # The first partition with a mount point is the interesting one. It's
1232
+ # usually Apple_HFS and usually the last one in the list, but beware of
1233
+ # the possibility of other filesystem types and the Apple_Free partition.
1234
+ # If the disk image contains no partition table, the partition will not
1235
+ # have a type, so look for the mount point by looking for a slash.
1236
+ $mountpoint = $1;
1237
+ return($rootDevice, $device, $mountpoint);
1238
+ }
1239
+ }
1240
+
1241
+ # No mount point? This is bad. If there's a root device, eject it.
1242
+ if(defined($rootDevice) && $rootDevice ne '') {
1243
+ # Failing anyway, so don't care about failure
1244
+ commandVerbosity(0, $gConfig{'cmd_diskutil'}, 'eject', $rootDevice);
1245
+ }
1246
+
1247
+ return undef;
1248
+ }
1249
+
1250
+ # licenseMaker($text, $resource)
1251
+ #
1252
+ # Takes a plain text file at path $text and creates a license agreement
1253
+ # resource containing the text at path $license. English-only, and
1254
+ # no special formatting. This is the bare-bones stuff. For more
1255
+ # intricate license agreements, create your own resource.
1256
+ #
1257
+ # ftp://ftp.apple.com/developer/Development_Kits/SLAs_for_UDIFs_1.0.dmg
1258
+ sub licenseMaker($$) {
1259
+ my($resource, $text);
1260
+ ($text, $resource) = @_;
1261
+ if(!sysopen(*TEXT, $text, O_RDONLY)) {
1262
+ print STDERR ($0.': licenseMaker: sysopen text: '.$!."\n");
1263
+ return 0;
1264
+ }
1265
+ if(!sysopen(*RESOURCE, $resource, O_WRONLY|O_CREAT|O_EXCL)) {
1266
+ print STDERR ($0.': licenseMaker: sysopen resource: '.$!."\n");
1267
+ return 0;
1268
+ }
1269
+ print RESOURCE << '__EOT__';
1270
+ // See /System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers/Script.h for language IDs.
1271
+ data 'LPic' (5000) {
1272
+ // Default language ID, 0 = English
1273
+ $"0000"
1274
+ // Number of entries in list
1275
+ $"0001"
1276
+
1277
+ // Entry 1
1278
+ // Language ID, 0 = English
1279
+ $"0000"
1280
+ // Resource ID, 0 = STR#/TEXT/styl 5000
1281
+ $"0000"
1282
+ // Multibyte language, 0 = no
1283
+ $"0000"
1284
+ };
1285
+
1286
+ resource 'STR#' (5000, "English") {
1287
+ {
1288
+ // Language (unused?) = English
1289
+ "English",
1290
+ // Agree
1291
+ "Agree",
1292
+ // Disagree
1293
+ "Disagree",
1294
+ __EOT__
1295
+ # This stuff needs double-quotes for interpolations to work.
1296
+ print RESOURCE (" // Print, ellipsis is 0xC9\n");
1297
+ print RESOURCE (" \"Print\xc9\",\n");
1298
+ print RESOURCE (" // Save As, ellipsis is 0xC9\n");
1299
+ print RESOURCE (" \"Save As\xc9\",\n");
1300
+ print RESOURCE (' // Descriptive text, curly quotes are 0xD2 and 0xD3'.
1301
+ "\n");
1302
+ print RESOURCE (' "If you agree to the terms of this license '.
1303
+ "agreement, click \xd2Agree\xd3 to access the software. If you ".
1304
+ "do not agree, press \xd2Disagree.\xd3\"\n");
1305
+ print RESOURCE << '__EOT__';
1306
+ };
1307
+ };
1308
+
1309
+ // Beware of 1024(?) byte (character?) line length limitation. Split up long
1310
+ // lines.
1311
+ // If straight quotes are used ("), remember to escape them (\").
1312
+ // Newline is \n, to leave a blank line, use two of them.
1313
+ // 0xD2 and 0xD3 are curly double-quotes ("), 0xD4 and 0xD5 are curly
1314
+ // single quotes ('), 0xD5 is also the apostrophe.
1315
+ data 'TEXT' (5000, "English") {
1316
+ __EOT__
1317
+
1318
+ while(!eof(*TEXT)) {
1319
+ my($line);
1320
+ chop($line = <TEXT>);
1321
+
1322
+ while(defined($line)) {
1323
+ my($chunk);
1324
+
1325
+ # Rez doesn't care for lines longer than (1024?) characters. Split
1326
+ # at less than half of that limit, in case everything needs to be
1327
+ # backwhacked.
1328
+ if(length($line)>500) {
1329
+ $chunk = substr($line, 0, 500);
1330
+ $line = substr($line, 500);
1331
+ }
1332
+ else {
1333
+ $chunk = $line;
1334
+ $line = undef;
1335
+ }
1336
+
1337
+ if(length($chunk) > 0) {
1338
+ # Unsafe characters are the double-quote (") and backslash (\), escape
1339
+ # them with backslashes.
1340
+ $chunk =~ s/(["\\])/\\$1/g;
1341
+
1342
+ print RESOURCE ' "'.$chunk.'"'."\n";
1343
+ }
1344
+ }
1345
+ print RESOURCE ' "\n"'."\n";
1346
+ }
1347
+ close(*TEXT);
1348
+
1349
+ print RESOURCE << '__EOT__';
1350
+ };
1351
+
1352
+ data 'styl' (5000, "English") {
1353
+ // Number of styles following = 1
1354
+ $"0001"
1355
+
1356
+ // Style 1. This is used to display the first two lines in bold text.
1357
+ // Start character = 0
1358
+ $"0000 0000"
1359
+ // Height = 16
1360
+ $"0010"
1361
+ // Ascent = 12
1362
+ $"000C"
1363
+ // Font family = 1024 (Lucida Grande)
1364
+ $"0400"
1365
+ // Style bitfield, 0x1=bold 0x2=italic 0x4=underline 0x8=outline
1366
+ // 0x10=shadow 0x20=condensed 0x40=extended
1367
+ $"00"
1368
+ // Style, unused?
1369
+ $"02"
1370
+ // Size = 12 point
1371
+ $"000C"
1372
+ // Color, RGB
1373
+ $"0000 0000 0000"
1374
+ };
1375
+ __EOT__
1376
+ close(*RESOURCE);
1377
+
1378
+ return 1;
1379
+ }
1380
+
1381
+ # pathSplit($pathname)
1382
+ #
1383
+ # Splits $pathname into an array of path components.
1384
+ sub pathSplit($) {
1385
+ my($pathname);
1386
+ ($pathname) = @_;
1387
+ return split(/\//, $pathname);
1388
+ }
1389
+
1390
+ # setAttributes($root, @attributeList)
1391
+ #
1392
+ # @attributeList is an array, each element of which must be in the form
1393
+ # <a>:<file>. <a> is a list of attributes, per SetFile. <file> is a file
1394
+ # which is taken as relative to $root (even if it appears as an absolute
1395
+ # path.) SetFile is called to set the attributes on each file in
1396
+ # @attributeList.
1397
+ sub setAttributes($@) {
1398
+ my(@attributes, $root);
1399
+ ($root, @attributes) = @_;
1400
+ my($attribute);
1401
+ foreach $attribute (@attributes) {
1402
+ my($attrList, $file, @fileList, @fixedFileList);
1403
+ ($attrList, @fileList) = split(/:/, $attribute);
1404
+ if(!defined($attrList) || !@fileList) {
1405
+ cleanupDie('--attribute requires <attributes>:<file>');
1406
+ }
1407
+ @fixedFileList=();
1408
+ foreach $file (@fileList) {
1409
+ if($file =~ /^\//) {
1410
+ push(@fixedFileList, $root.$file);
1411
+ }
1412
+ else {
1413
+ push(@fixedFileList, $root.'/'.$file);
1414
+ }
1415
+ }
1416
+ if(command($gConfig{'cmd_SetFile'}, '-a', $attrList, @fixedFileList)) {
1417
+ cleanupDie('SetFile failed to set attributes');
1418
+ }
1419
+ }
1420
+ return;
1421
+ }
1422
+
1423
+ sub trapSignal($) {
1424
+ my($signalName);
1425
+ ($signalName) = @_;
1426
+ cleanupDie('exiting on SIG'.$signalName);
1427
+ }
1428
+
1429
+ sub usage() {
1430
+ print STDERR (
1431
+ "usage: pkg-dmg --source <source-folder>\n".
1432
+ " --target <target-image>\n".
1433
+ " [--format <format>] (default: UDZO)\n".
1434
+ " [--volname <volume-name>] (default: same name as source)\n".
1435
+ " [--tempdir <temp-dir>] (default: same dir as target)\n".
1436
+ " [--mkdir <directory>] (make directory in image)\n".
1437
+ " [--copy <source>[:<dest>]] (extra files to add)\n".
1438
+ " [--license <file>] (plain text license agreement)\n".
1439
+ " [--resource <file>] (flat .r files to merge)\n".
1440
+ " [--icon <icns-file>] (volume icon)\n".
1441
+ " [--attribute <a>:<file>] (set file attributes)\n".
1442
+ " [--idme] (make an Internet-enabled image)\n".
1443
+ " [--sourcefile] (treat --source as a file)\n".
1444
+ " [--verbosity <level>] (0, 1, 2; default=2)\n".
1445
+ " [--dry-run] (print what would be done)\n");
1446
+ return;
1447
+ }