summaryrefslogtreecommitdiffstats
path: root/zarb-ml/mageia-sysadm/attachments/20110203/978af990/attachment-0001.html
diff options
context:
space:
mode:
Diffstat (limited to 'zarb-ml/mageia-sysadm/attachments/20110203/978af990/attachment-0001.html')
-rw-r--r--zarb-ml/mageia-sysadm/attachments/20110203/978af990/attachment-0001.html4462
1 files changed, 4462 insertions, 0 deletions
diff --git a/zarb-ml/mageia-sysadm/attachments/20110203/978af990/attachment-0001.html b/zarb-ml/mageia-sysadm/attachments/20110203/978af990/attachment-0001.html
new file mode 100644
index 000000000..af0108c9f
--- /dev/null
+++ b/zarb-ml/mageia-sysadm/attachments/20110203/978af990/attachment-0001.html
@@ -0,0 +1,4462 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<title>[397] Import cleaned draklive</title>
+</head>
+<body>
+
+<style type="text/css"><!--
+#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
+#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
+#msg dt:after { content:':';}
+#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
+#msg dl a { font-weight: bold}
+#msg dl a:link { color:#fc3; }
+#msg dl a:active { color:#ff0; }
+#msg dl a:visited { color:#cc6; }
+h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
+#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
+#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
+#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
+#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
+#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
+#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
+#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
+#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
+#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
+#logmsg pre { background: #eee; padding: 1em; }
+#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
+#logmsg dl { margin: 0; }
+#logmsg dt { font-weight: bold; }
+#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
+#logmsg dd:before { content:'\00bb';}
+#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
+#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
+#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
+#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
+#logmsg table th.Corner { text-align: left; }
+#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
+#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
+#patch { width: 100%; }
+--></style>
+<div id="msg">
+<dl class="meta">
+<dt>Revision</dt> <dd>397</dd>
+<dt>Author</dt> <dd>dmorgan</dd>
+<dt>Date</dt> <dd>2011-02-03 18:53:54 +0100 (Thu, 03 Feb 2011)</dd>
+</dl>
+
+<h3>Log Message</h3>
+<pre>Import cleaned draklive</pre>
+
+<h3>Added Paths</h3>
+<ul>
+<li>draklive/</li>
+<li><a href="#drakliveCLEANUP_PROGRESStxt">draklive/CLEANUP_PROGRESS.txt</a></li>
+<li>draklive/trunk/</li>
+<li><a href="#draklivetrunkperl_checker">draklive/trunk/.perl_checker</a></li>
+<li><a href="#draklivetrunkChangeLog">draklive/trunk/ChangeLog</a></li>
+<li><a href="#draklivetrunkMakefile">draklive/trunk/Makefile</a></li>
+<li><a href="#draklivetrunkNEWS">draklive/trunk/NEWS</a></li>
+<li><a href="#draklivetrunkdraklive">draklive/trunk/draklive</a></li>
+<li><a href="#draklivetrunkdraklivecopywizarddesktop">draklive/trunk/draklive-copy-wizard.desktop</a></li>
+<li>draklive/trunk/kmod/</li>
+<li><a href="#draklivetrunkkmodreadlogc">draklive/trunk/kmod/readlog.c</a></li>
+<li>draklive/trunk/lib/</li>
+<li>draklive/trunk/lib/MDV/</li>
+<li>draklive/trunk/lib/MDV/Draklive/</li>
+<li><a href="#draklivetrunklibMDVDrakliveConfigpm">draklive/trunk/lib/MDV/Draklive/Config.pm</a></li>
+<li><a href="#draklivetrunklibMDVDrakliveCustomMediapm">draklive/trunk/lib/MDV/Draklive/CustomMedia.pm</a></li>
+<li><a href="#draklivetrunklibMDVDrakliveInitrdpm">draklive/trunk/lib/MDV/Draklive/Initrd.pm</a></li>
+<li><a href="#draklivetrunklibMDVDrakliveLivepm">draklive/trunk/lib/MDV/Draklive/Live.pm</a></li>
+<li><a href="#draklivetrunklibMDVDrakliveLoopbackpm">draklive/trunk/lib/MDV/Draklive/Loopback.pm</a></li>
+<li><a href="#draklivetrunklibMDVDrakliveMediapm">draklive/trunk/lib/MDV/Draklive/Media.pm</a></li>
+<li><a href="#draklivetrunklibMDVDrakliveMountspm">draklive/trunk/lib/MDV/Draklive/Mounts.pm</a></li>
+<li><a href="#draklivetrunklibMDVDrakliveOverlaypm">draklive/trunk/lib/MDV/Draklive/Overlay.pm</a></li>
+<li><a href="#draklivetrunklibMDVDrakliveProgresspm">draklive/trunk/lib/MDV/Draklive/Progress.pm</a></li>
+<li><a href="#draklivetrunklibMDVDrakliveStoragepm">draklive/trunk/lib/MDV/Draklive/Storage.pm</a></li>
+<li><a href="#draklivetrunklibMDVDrakliveStorageFSpm">draklive/trunk/lib/MDV/Draklive/StorageFS.pm</a></li>
+<li><a href="#draklivetrunklibMDVDrakliveUtilspm">draklive/trunk/lib/MDV/Draklive/Utils.pm</a></li>
+<li><a href="#draklivetrunkmkinitrddraklive">draklive/trunk/mkinitrd-draklive</a></li>
+<li><a href="#draklivetrunkwrite_flashsh">draklive/trunk/write_flash.sh</a></li>
+</ul>
+
+</div>
+<div id="patch"><pre>
+<a id="drakliveCLEANUP_PROGRESStxt">Added: draklive/CLEANUP_PROGRESS.txt</a>
+===================================================================
+--- draklive/CLEANUP_PROGRESS.txt (rev 0)
++++ draklive/CLEANUP_PROGRESS.txt 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,3 @@
++- License is GPLv2+ according to the copyright header
++- Change one occurance of &quot;Mandriva&quot; to &quot;Mageia&quot; in draklive as it'll be visible to
++ users
+
+
+Property changes on: draklive/CLEANUP_PROGRESS.txt
+___________________________________________________________________
+<a id="svneolstyle">Added: svn:eol-style</a>
+ + native
+
+<a id="draklivetrunkperl_checker">Added: draklive/trunk/.perl_checker</a>
+===================================================================
+--- draklive/trunk/.perl_checker (rev 0)
++++ draklive/trunk/.perl_checker 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,27 @@
++constant
++AutoLoader
++Carp::Heavy
++Compress::Zlib
++Cwd
++Date::Manip
++Digest::MD5
++Encode
++encoding
++File::Find
++File::FnMatch
++File::GlobMapper
++File::Path
++File::Temp
++Gtk2::Gdk::Keysyms
++IO::Compress::Gzip
++IO::Uncompress::Gunzip
++IO::Handle
++IO::Pipe
++Pod::Usage
++Scalar::Util
++String::ShellQuote
++Symbol
++Text::ParseWords
++Term::ReadKey
++urpm::media
++urpm::parallel
+
+<a id="draklivetrunkChangeLog">Added: draklive/trunk/ChangeLog</a>
+===================================================================
+--- draklive/trunk/ChangeLog (rev 0)
++++ draklive/trunk/ChangeLog 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,437 @@
++2007-09-29 15:57 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: do not run service_harddrake stop anymore, it does not
++ exist in 2008.0
++
++2007-09-25 15:20 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: fix typo
++
++2007-09-25 14:05 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: add newlines in die messages, not to trigger the
++ infamous drakbug
++
++2007-09-25 13:55 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: print usage if no option is specified
++
++2007-09-25 10:31 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: fix division by zero /o\
++
++2007-09-19 14:53 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: copy additional modules after plain modules, so that
++ they can overwrite them
++
++2007-09-19 14:53 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: fix additional modules copy
++
++2007-09-03 08:44 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: please perl_checker
++
++2007-09-03 08:42 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: don't check symlinks when looking for kernels (fix
++ matching vmlinuz-tmb-desktop586)
++
++2007-09-03 08:41 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: simplify
++
++2007-08-28 08:52 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: allow to copy per-fs files in mkinitrd
++
++2007-08-28 08:50 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: move mount actions in a storage_fs hash
++
++2007-08-28 08:49 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * .perl_checker: supplement perl_checker blacklist
++
++2007-08-28 08:41 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: run mkdevices to create nodes for existing devices
++
++2007-08-28 08:40 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: fix typo
++
++2007-08-28 08:39 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: move modules mount point in new root
++
++2007-08-28 08:39 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: cosmetics
++
++2007-08-28 08:38 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: remove more dirs
++
++2007-08-28 08:35 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: add a new is_loopback variable to better list selected
++ loopbacks
++
++2007-08-28 08:33 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: create less loop devices by default
++
++2007-08-28 08:23 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: allow to specify ro unionfs branches
++
++2007-08-28 08:19 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: make bootloader timeout configurable
++
++2007-08-28 08:16 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: fix unionfs branches list by removing trailing colon
++ (for unionfs2)
++
++2007-08-28 08:15 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: make boot and loopbacks read-only
++
++2007-08-28 08:15 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: mark hidden files hidden only
++
++2007-07-16 12:56 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: fix vfat check...
++
++2007-06-12 09:47 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: oops, I really meant vfat when stripping labels for
++ nash
++
++2007-06-11 15:26 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: add a get_media_source_for_nash functions that formats
++ ext2 labels accordingly
++
++2007-06-07 16:33 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: do not select modules directory together with loopbacks
++
++2007-06-07 14:43 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: hidden_files is a better name
++
++2007-06-07 14:42 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: hide more autorun files
++
++2007-06-07 09:47 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: remove multi squash union, better replaced with modules
++
++2007-06-07 09:47 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: use modules in volatile_squash_union mounts
++
++2007-06-07 09:41 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: fix extra files selection in cdrom master
++
++2007-06-05 18:57 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: perl_checker fixes
++
++2007-06-05 18:57 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: only run mattrib for vfat
++
++2007-06-05 18:55 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: also hide autorun.inf (yes, hardcode it)
++
++2007-06-05 18:54 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: hide all files begining with a dot on USB media
++
++2007-06-05 11:54 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: do not copy extra media files in boot images
++
++2007-06-05 07:17 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: add a glob wrapper that dotglob behavior and expand
++ only if needed
++
++2007-06-05 01:12 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: protect rm_rf from die
++
++2007-06-04 15:48 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: run mattrib with MTOOLS_SKIP_CHECK
++
++2007-06-04 15:48 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: create mtools_run_
++
++2007-06-04 14:49 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: use glob_ to match dot files (since File::Glob does not
++ provide a dotglob option)
++
++2007-05-31 15:14 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: revert to initrd + pivot_root (or else unionfs panicks
++ in unionfs_file_revalidate when using unionctl in new root)
++
++2007-05-31 13:39 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: modify custom nfs syntax
++
++2007-05-31 13:38 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: oops, add back mountpoint
++
++2007-05-31 13:36 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: use modules source for squash_union
++
++2007-05-31 13:35 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: add modules source type
++
++2007-05-31 13:19 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: allow to get loopbacks list from a file
++
++2007-05-31 13:16 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: allow to delay mount of specific loopbacks
++
++2007-05-31 12:29 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: try to get interactive debug shell
++
++2007-05-31 12:08 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: allow to specify module options in
++ $live-&gt;{system}{module_options}
++
++2007-05-31 12:06 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: allow to use real glob patterns in
++ live-&gt;{system}{remove_files}
++
++2007-05-31 12:05 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: fix directory creation when dest is a dir in
++ copy_files_to
++
++2007-05-31 12:04 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: clean build files before creating new ones
++
++2007-05-29 16:39 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: pre-create devfsd compatibility loop devices (since
++ busybox is still built with devfsd support)
++
++2007-05-29 16:37 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: pre-create more loop devices
++
++2007-05-26 17:39 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: modify loopback modules syntax to be compatible with
++ file list expansion
++
++2007-05-26 17:38 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: copy resolv.conf in chroot for urpmi to work (and clean
++ it at end of post-install)
++
++2007-05-25 16:32 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: fix excluded loopback path
++
++2007-05-21 13:14 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: pass opts when formatting
++
++2007-05-21 13:13 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: fix typo...
++
++2007-05-21 13:12 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: make optional device usage more consistent
++
++2007-05-21 13:05 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: remove extra media support
++
++2007-05-21 13:02 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: fix some typos
++
++2007-05-21 13:02 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: remove optional media support
++
++2007-05-17 22:07 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: move new root mount point in /sysroot, so that live dir
++ can be properly removed from initramfs
++
++2007-05-16 22:07 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: remove more initrd relics
++
++2007-05-16 22:06 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: use busybox's mkdir since nash's &quot;mkdir -p&quot; does not
++ have the standard behavior
++
++2007-05-16 21:02 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: fix silly typo
++
++2007-05-16 20:48 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: allow to include loopback modules in master images by
++ defining modules sets in live-&gt;{packs} and selecting them from
++ live-&gt;{settings}{pack}
++
++2007-05-16 20:42 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: define /modules in prefix hash
++
++2007-05-16 20:40 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: make directory path prefixed by / (to make subpath
++ usage easier)
++
++2007-05-16 20:38 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: rename directory &quot;location&quot; field as &quot;path&quot;
++
++2007-05-16 20:31 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: allow to create loopback modules from
++ live-&gt;{loopbacks}{modules} (to be used for separate i18n
++ loopbacks)
++
++2007-05-16 20:25 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: archive excluded files list as loopback type defined by
++ live-&gt;{loopbacks}{exclude}{type}} instead of tarball
++
++2007-05-16 20:23 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: use hardlink_filtered to build excluded files tarball
++
++2007-05-16 20:18 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: add hardlink_filtered function to hardlink recursively
++ file list to a directory (using rsync --files-from --link-dest)
++
++2007-05-16 20:14 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: allow to use glob when expand file list
++
++2007-05-16 20:14 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: protect deref
++
++2007-05-16 20:13 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: rename live-&gt;{loopbacks}{exclude_files} as
++ live-&gt;{loopbacks}{exclude}{files}
++
++2007-05-16 20:12 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: transform list_excluded_files as more generic
++ expand_file_list
++
++2007-05-16 20:10 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: pass excluded files list in loopback directory hash to
++ allow refined exclusion
++
++2007-05-16 20:03 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: really set bootlogo variable (and simplify)
++
++2007-05-16 19:56 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: add extension for some loopback types
++
++2007-05-16 19:42 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: add list_selected_loopbacks() function
++
++2007-05-16 19:35 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: copy only selected loopbacks in master image
++
++2007-05-16 19:29 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: allow to build squashfs with prefix different from
++ chroot
++
++2007-05-16 19:26 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: differentiate squashfs source and prefix to be able to
++ build from sources != '/'
++
++2007-05-16 19:23 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: create loopbacks directory in indivual build functions
++ and not on top directory (they may have to create subdirs anyway)
++
++2007-05-16 19:20 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: really use $dir variable and not indefinite $_
++
++2007-05-16 19:17 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: rename directory &quot;source&quot; field as &quot;location&quot;
++
++2007-05-16 19:01 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: use initramfs instead of initrd
++
++2007-05-16 18:57 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: rename create_initrd_linuxrc as create_initrd_scriptlet
++
++2007-05-02 11:56 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: pre-create tarballs directory
++
++2007-05-02 09:48 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: perl_checker fix
++
++2007-05-02 09:47 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: include media files on CD as well
++
++2007-05-02 09:46 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: move media files copy in post-install step
++
++2007-05-02 09:45 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * draklive: move umask restoration at end of post-install
++
++2007-05-02 09:23 Olivier Blin &lt;oblin at mandriva.com&gt;
++
++ * ., .perl_checker, Makefile, NEWS, draklive,
++ draklive-copy-wizard.desktop: reimport draklive in SVN
++
+
+<a id="draklivetrunkMakefile">Added: draklive/trunk/Makefile</a>
+===================================================================
+--- draklive/trunk/Makefile (rev 0)
++++ draklive/trunk/Makefile 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,40 @@
++NAME = draklive
++VERSION = 0.9
++
++check:
++ perl -cw -I./lib $(NAME)
++
++clean:
++ find -name '*~' -exec rm {} \;
++
++dist: dis
++dis: clean
++ rm -f ../$(NAME)-$(VERSION)*.tar*
++ @if [ -e &quot;.svn&quot; ]; then \
++ $(MAKE) dist-svn; \
++ elif [ -e &quot;.git&quot; ]; then \
++ $(MAKE) dist-git; \
++ else \
++ echo &quot;Unknown SCM (not SVN nor GIT)&quot;;\
++ exit 1; \
++ fi;
++ $(info $(NAME)-$(VERSION).tar.xz is ready)
++
++dist-svn:
++ rm -rf $(NAME)-$(VERSION)
++ svn export -q -rBASE . $(NAME)-$(VERSION)
++ tar cfJ ../$(NAME)-$(VERSION).tar.xz $(NAME)-$(VERSION)
++ rm -rf $(NAME)-$(VERSION)
++
++dist-git:
++ @git archive --prefix=$(NAME)-$(VERSION)/ HEAD | xz &gt;../$(NAME)-$(VERSION).tar.xz;
++
++.PHONY: ChangeLog log changelog
++
++log: ChangeLog
++
++changelog: ChangeLog
++
++ChangeLog:
++ svn2cl --accum --authors ../../soft/common/username.xml
++ rm -f *.bak
+
+
+Property changes on: draklive/trunk/Makefile
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+
+<a id="draklivetrunkNEWS">Added: draklive/trunk/NEWS</a>
+===================================================================
+--- draklive/trunk/NEWS (rev 0)
++++ draklive/trunk/NEWS 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,508 @@
++0.9:
++
++* config
++- automatically export draklive settings to DRAKLIVE_ environment variables for install
++- allow to specify mount options in fstab in media-&gt;{mount_options}
++- make it possible to specify mount options for tmpfs mounts
++- allow to skip writing fstab with live-&gt;{system}{skip_fstab}
++- allow to skip writing bootloader config with live-&gt;{system}{skip_bootloader_config}
++- allow to skip bootloader install with live-&gt;{system}{skip_bootloader_install}
++- allow not to create initrd with live-&gt;{system}{no_initrd}
++- allow to select which settings fields are used to build name, in live-&gt;{name_fields}
++
++* install
++- generate lst.names files list
++- make sure zh_TW and zh_CN will be included in language list
++- clean resolv.conf later (so that network can be used in post)
++
++* initrd
++- dropped splashy support, added plymouth support
++ (using bootloader::add_boot_splash)
++- don't mount /dev/pts since this causes huge slowdowns
++- mount tmpfs partitions with 0755 perms (#51565):
++ When using the obsolete --attach-to-session plymouth option, /dev/pts
++ has to be mounted. But for some reason, nash interacts badly with
++ mounted /dev/pts and freezes for dozen of seconds when running a builtin
++ command. Remote --attach-to-session from plymouth which lets us get rid
++ of /dev/pts mounting.
++- add hack to use modules list from chroot
++ (to handle different IDE modules name in build and target environments)
++- detect some modules as built-in and do not wrongly abort
++- do not create initrd symlink or append splash if no initrd has been created
++- make sure /proc and /sys are available when building initrd (useful
++ to see error messages at least, from Paulo Ricardo Zanoni)
++- use bootloader module to build initrd and create kernel symlinks
++ (Gdium friendly)
++
++* bootloader
++- default to grub bootloader for harddisk storage
++- fix installing grub to separate /boot partition
++- use per-media additional boot_entries
++- do not add default boot entry if media-&gt;{boot_entries} is specified
++ (to allow having a custom default entry)
++- fix installing grub to hidden /boot in master image
++- set LD_LIBRARY_PATH to chroot libraries when running grub
++- die in bootloader step if selected kernel does not exist
++- do not add initrd in grub menu if it does not exist
++- allow to install bootloader on separate /boot partition
++- make sure the grub install script is executable
++- do not overwrite grub conf for &quot;classical&quot; boot when installing
++ bootloader
++- use same bootloader install code for disks and USB masters
++- remove hardcoded splashy code and use back bootloader::add_boot_splash
++- run switch-themes -u
++- use bootloader module to find kernel (Gdium friendly)
++- update gfxboot theme before copying gfxboot files
++- fix getting bootsplash theme (fixes gfxboot theme)
++- do not add vga mode on kernel command line if forced in append
++ (for drakx-based replicator)
++- fix setting splash for classical bootloader
++- create media specific gfxmenu if needed only
++- always copy gfxmenu in build boot dir (needed for replicator)
++- do not create bootloader files if bootloader install is to be skipped
++- fix writing media specific boot for disk masters
++
++* master
++- use -fatfirst option when hybridifying an image
++- use DrakX partitioning/formatting code
++- run udevsettle, like done in diskdrake::interactive::write_partitions
++- allow to set custom media geometry in media-&gt;{geom}
++- allow to format disk devices
++- add ext4 and swap support in mkfs
++- use ext4 by default for harddisk
++- set label at mkfs time
++- fix setting label on fat
++- fix setting label for USB devices
++- add default label for harddisk storage
++- always compute master size from pre-computed partition sizes
++- use apparent size when computing loopbacks size (system loopback can be sparse)
++- supplement / partition label with default one if needed
++- allow to add an OEM rescue partition in the master (quite hackish, using live-&gt;{oem_rescue})
++- preset fs_type for OEM_RESCUE partition too
++- allow to set inode size in media-&gt;{inode_size} for ext2/ext3 file systems
++- preserve timestamps when copying files
++
++* image
++- allow to compress master images as gzip instead of bzip2 by setting
++ compression_method=gzip in settings.cfg (from Paulo Ricardo Zanoni)
++
++* vm-image
++- create vmdk virtual machine images (for VMware, VirtualBox, qemu)
++
++* replicator
++- copy syslinux dir for replicator too
++- always create syslinux msg files (useful for cdrom replicator)
++- allow drakx-based replicator
++ (by setting live-&gt;{settings}{replicator_type} to &quot;drakx&quot;)
++- write image size in master list file
++- write bootloader config for replicator media
++
++* record
++- use full disk device when recording harddisk/oem_rescue/replicator/USB masters
++- allow to mount multiple partitions before recording target master
++- do not try to use configured media source when it is not a label, it
++ could be a device (/dev/sda1) that should not be touched on the
++ build machine, force it to be passed as an option
++
++
++0.8:
++
++* loop
++- use lzma by default (should be an option)
++- use legacy mksquashfs3 instead of the new mksquashfs
++- use 1MB squashfs blocks, this gives us about 10% better compression
++- fix loopback extension in /etc/sysconfig/draklive-resize
++
++* bootloader
++- remove unneeded locale files from gfxboot bootlogo file (causes boot issues
++ on some machines)
++- add 'harddrive' boot entry to chainload to the harddrive bootloader
++- use latest syslinux + gfxboot COM module
++- do not crash if there is no gfxmenu file
++- use live-&gt;{system}{append}
++- specify root in bootloader append for harddisk installs
++- create &quot;classical&quot; bootloader files (grub menu and gfxmenu)
++- upper-case FAT labels again (we switched to blkid in nash)
++- fix installing probe-modules for x86_64 (spotted by imr)
++
++* master
++- allow to create harddisk masters (for OEM images)
++- hybridify generated ISOs so that they can be dumped on USB keys
++- create bigger vfat and disk masters
++- setup loop device with its real size (so that mkfs does not make a too large fs)
++- write a /boot/grub/install.sh script when installing grub, and run
++ grub in chroot (requires to bind-mount the image inside its mount point)
++- use again du --apparent-size for some sparse files
++
++* images
++- build compressed harddisk image (for now bzipped, could be extracted
++ through partimage later)
++
++* replicator
++- allow to create replicator images (cdrom and USB)
++ using stage1 and restore scripts to dump OEM master on final systems
++- add --replicator to build replicator image
++- allow to customize replicator append in live-&gt;{replicator}{append}
++
++* initrd
++- splashy support
++- generate &quot;classical&quot; initrd (for harddisk installs)
++- handle non-gzipped additional modules
++- fix checking missing modules (do it after parsing additional modules)
++- mount /dev as tmpfs after pivot_root, so that finit's /dev/initctl
++ does not get forgotten when start_udev remounts /dev
++- remove deprecated mkdevices call
++- do not use nash-mount to mount tmpfs (run by busybox when using fallback)
++- do not include nls modules for ext2/ext3 filesystems
++- add support for external pre-pivot-root command in initrd
++ (live-&gt;{system}{initrd_pre_pivot})
++- skip non-dirs when mount moving to new root (avoid error messages)
++
++* config
++- allow to split version out of name (to follow name-product-version naming)
++
++* chroot
++- use media source instead of /dev/root in fstab, since the later
++ confuses mkinitrd
++- write live-&gt;{system}{files} with no_install option in
++ /etc/draklive-install.d/remove.d/draklive
++
++* code architecture
++- split code and MDV::Draklive submodules
++- add initial mkinitrd-draklive prototype
++ (to allow rebuilding live initrd on installed system)
++- add a default mount (for harddisk master)
++- extract predefined and custom mounts/fs in MDV::Draklive::Mounts and
++ MDV::Draklive::CustomMedia modules (breaks config files compatibility)
++
++
++0.7:
++
++* initrd
++- do not copy and load twice additional modules if they were listed in
++ extra modules
++- use nash-mount instead of mount
++- create /etc/blkid and use &quot;showlabels --removable&quot; to get CD-Rom
++ labels in blkid cache
++- adapt to new probe-modules syntax for storage bus
++- use stage1's probe-modules instead of dropped nash's insmod
++- move initrd modules in /lib/modules/`uname -r`
++- gzip initrd modules
++- use depmod to generate modules.dep
++- do not print excluding modules warning if not needed
++- check that there is enough space left in initrd
++- umount /proc/bus/usb before pivot_root in initrd
++- add firewire controllers (bus and disk) in CDROM live (#31356)
++- use libraries from /lib instead of /lib/i686 (#38649) and /lib/tls
++ (#21683) to be able to boot on processors without cmov
++
++* bootloader
++- remove hardcoded fastboot option (new initscripts do not fsck rw /)
++
++* master
++- handle genisoimage progress more nicely
++- insert mkcd checksum before computing md5/sha1 checksums
++- hide mkcd output
++
++* dist
++- rename &quot;images&quot; directory as &quot;dist&quot;
++- create packages lst in dist
++- write a .langs file with human-readable langs list
++- write full list of rpm packages and list of rpm leaves, sorted by package size
++
++* misc
++- do not try to use consolehelper to display &quot;must be root&quot; message,
++ it's broken outside of X
++
++
++0.6:
++
++* config
++- use config and additional files from live-&gt;{settings}{config_root},
++ defaulting to current directory, or to /etc/draklive if no config file
++ is present in current directory
++- allow to configure files root directory with --config-root
++- use /var/lib/draklive/build as default build dir and
++ /var/lib/draklive/chroot as default chroot dir
++
++* bootloader
++- improve gfxboot support by copying files from both Mandriva and
++ system-chosen theme
++- install gfxboot files in /isolinux on CD image
++- gfxboot support for grub
++- drop unused F1 binding when gfxboot is used
++- use livecd mode in gfxboot (thanks Pixel \o/)
++- copy gfxmenu instead of moving it (#31879)
++- enable gfxboot only if live-&gt;{system}{gfxboot} is set
++- remove extra media support
++- remove optional media support
++- allow to specify bootloader timeout in
++ live-&gt;{media}{bootloader_timeout}
++
++* initrd
++- rename debug command line option as initrd_debug not to conflict
++ with kernel option
++- handle module names with underscores, using new module dependencies
++ functions from list_modules (such as modname2path)
++- add and use probe-modules helper from stage1 to load modules
++- drop useless ide-generic hack, probe-modules will load it as
++ fallback only
++- drop usb-storage hack, done by probe-modules
++- do not explicitely load storage module in linuxrc
++ (done by probe-modules helper)
++- add modules.dep, modules.description, modules.alias, ldetect-lst
++ tables, pci.ids and fallback-modules.alias for probe-modules
++- add .ko.gz symlinks to .ko files (used by probe-modules, gzopen
++ transparently opens uncompressed files)
++- load dependencies of extra modules only
++- install modules in /modules instead of /lib in initrd
++- add partition &quot;loop&quot; type to be able to mount partitions in initrd
++- create empty fstab and mtab for fsck programs not to complain
++- run fsck when mounting ext2 partition
++- move mount actions in a storage_fs hash
++- be less verbose when compressing modules
++- be less verbose when printing skipped modules
++- allow to exclude modules from initrd in
++ live-&gt;{system}{exclude_modules}
++- use busybox's mkdir since nash's &quot;mkdir -p&quot; does not have the
++ standard behavior
++- pre-create devfsd compatibility loop devices (since busybox is still
++ built with devfsd support)
++- pre-create more loop devices
++- allow to specify module options in live-&gt;{system}{module_options}
++- allow to delay mount of specific loopbacks
++- do not add disk/raw category for cdrom media
++- allow to specify ro unionfs branches
++- fix unionfs branches list by removing trailing colon (for unionfs2)
++- don't check symlinks when looking for kernels
++ (fix matching vmlinuz-tmb-desktop586)
++- run mkdevices to create nodes for existing devices
++- move modules mount point in new root
++- do not mess / tree if no live modules are used
++- allow to copy per-fs files in initrd
++- copy additional modules after plain modules, so that they can overwrite them
++- do not uppercase label anymore for vfat partitions, nash with vol_id
++ seems to handle it fine
++
++* chroot
++- be less verbose when running patch dry runs
++- don't hardcode list of files to be removed in chroot, they must be
++ listed in live-&gt;{system}{remove_files} now (dbus/modprobe/udev files
++ for example)
++- allow to use real glob patterns in live-&gt;{system}{remove_files}
++- copy resolv.conf in chroot for urpmi to work (and clean it at end of
++ post-install)
++- do not run service_harddrake stop anymore, it does not exist in 2008.0
++- run postInstall after copying packages
++
++* loopbacks
++- allow to create loopback modules from live-&gt;{loopbacks}{modules}
++ (to be used for separate i18n loopbacks)
++- allow to include loopback modules in master images by defining
++ modules sets in live-&gt;{packs} and selecting them from live-&gt;{settings}{pack}
++- write a loopbacks/excluded.tar.bz2 tarball containing files that
++ have been excluded from other loopbacks
++- write excluded.tar.bz2 in /tarballs, so that it does not get
++ included in final ISO image
++- remove multi squash union, better replaced with modules
++- add &quot;modules&quot; source type, and use it for squash_union and
++ volatile_squash_union mounts (which are now custom mounts)
++- allow to exclude files in loopbacks with live-&gt;{system}{exclude_files}
++- pass -no-progress option to mksquashfs, draklive handles its own
++ progress bar
++- fix division by zero in progress code /o\
++
++* master
++- drop some genisoimage verbosity
++- do not allow to create USB master, it is not correctly implemented yet
++- name images after live name instead of live.iso/live.img
++- compute md5sum and sha1sum for ISO images
++ (in addition to the mkcd checksum)
++- do not copy extra media files in boot images
++- fix extra files selection in cdrom master
++- compute media dirs on the fly instead of hardcoding at start
++ (to support CD-Rom boot images with non-hidden media directories)
++
++* record
++- make device option used for boot-only as well
++- do not set label if boot-only
++- use bootloader setting from optional media if specified
++- umount usb device if loopback copy fails
++- unlink list file if loopbacks copy fails as well
++- mark as read-only boot and loopbacks on vfat USB media
++- mark as hidden files beginning with a dot, autorun files, boot and
++ loopbacks read-only on vfat USB media
++- only run mattrib for vfat
++- run mattrib with MTOOLS_SKIP_CHECK (like mlabel)
++
++* misc
++- print usage if no option is specified
++- log files copy
++- add newlines in die messages, not to trigger the infamous drakbug
++- make warn messages less verbose
++- use live-&gt;{settings}{name/product/media/desktop/region} in
++ build/chroot names
++- write a packages.lst file containing the installed packages list
++- add a glob wrapper with dotglob behavior, and expand only if needed
++- custom NFS is now in custom{fs} instead of custom{mounts}
++- reorder init so that arch is set before calling get_builddir and
++ get_system_root (#35105)
++- chomp arch returned by rpm to fix directory names when arch is not
++ in settings.cfg (#35105)
++
++
++0.5:
++
++* chroot
++- use glob() instead of glob_() to support again non-wildcarded
++ filenames in live-&gt;{system}{files} and live-&gt;{media}{files}
++
++* loopbacks
++- use noappend option in mksquashfs to overwrite previous loopbacks
++
++
++0.4:
++
++* config
++- make loopback fs configurable
++- allow to define fallbacks directories
++ (will be mounted only if the mountpoint is not already mounted)
++- XiB are now used instead of XB when specified fs size is expanded
++- allow to specify min_size in custom squash_union helper
++- introduce &quot;plain&quot; mount type (instead of empty mount type)
++- split build/media prefixes
++- allow to specify additional mount options for storage media
++ (such as umask=...)
++- add live-{system}{hide_media_dirs} and live-&gt;{media}{files}
++ (see details in &quot;master&quot; section)
++- allow to use glob patterns in live-&gt;{system}{files} and
++ live-&gt;{media}{files}
++
++* bootloader
++- use grub-install and grub files from chroot, and make it use custom
++ boot directory
++
++* chroot
++- create draklive-resize configuration file and do not build loopback
++ fs if min_size is specified
++
++* loopbacks
++- use tmpfs as fallback if the ext2 loopback can not be mounted
++- repair loopbacks non-interactively
++
++* master
++- set MTOOLS_SKIP_CHECK to 1 when running mlabel (some USB pens are
++ misdetected by mtools)
++- allow to hide media dirs by adding '.' in prefixes when
++ live-{system}{hide_media_dirs} is set
++- use mattrib to hide media dirs from windows
++- install grub on both master device and partition (fix boot on buggy
++ Intel BIOS)
++- allow to copy files directly to the final image/media using
++ live-&gt;{media}{files} (implemented for USB only)
++
++
++0.3:
++
++* interface
++- make --boot-only copy only boot files (instead of using boot media)
++- add --boot-image option to create a boot image for the selected
++ method
++- make string command line options mandatory
++- add --dump-config option
++- allow to load settings from command line using --define options
++- drop --region option (use --define region=)
++
++* config
++- make the system.loop size configurable
++- handle GigaBytes for loopback sizes
++- rename live-&gt;{post} as live-&gt;{system}{initrd_post}
++- export region as DRAKLIVE_REGION for auto_install
++- allow to provide stage2 updates with live-&gt;{system}{stage2_updates}
++- allow to make the initrd reread a device partition table using
++ live-&gt;{media}{rereadpt}
++ (useful if USB partition changes after some PIN input)
++- allow to customize bootloader title in live-&gt;{media}{title}
++- default to config/live.cfg config path
++- allow to load live-&gt;{settings} from a file and default to
++ config/settings.cfg
++- use region/repository/root/workdir variables from live-&gt;{settings}
++- rename &quot;workdir&quot; setting as &quot;builddir&quot;
++- rename &quot;root&quot; setting as &quot;chroot&quot;
++- automatically add arch to specified repository
++
++* chroot installation
++- remove /etc/dbus-1/machine-id
++- really don't apply patches if they look already applied
++- workaround buggy installation of directories that are not owned by
++ any packages (using 022 umask)
++- do not try to install packages if the additional media is only aimed
++ at adding extra sources (warly)
++- remove urpmi media before starting additional media installation
++- install additional media just before they are required
++- get drakx-in-chroot from the repository
++- run install/rpm commands for targetted architecture
++
++* bootloader
++- unlink grub device map so that grub rechecks the map
++- die when grub or rsync fail
++- don't install bootloader on non-block device
++- partial gfxboot support (#26430)
++- build bootloader files for boot methods listed in
++ media-&gt;{extra_boot}
++- display help file if not bootlogo is available
++- add missing newlines in syslinux/grub configuration files
++
++* loopbacks
++- don't use sort file if it doesn't exist
++- adapt mksquashfs output parsing to latest release
++- die if mksquashfs fails
++- don't pass float to mkfs.vfat
++- run fsck on rw loopback files before mounting them
++- don't reserv blocks on ext2/3 filesystems, we don't create root fs
++- compute an approximative size for USB master images
++
++* master/record
++- don't use a timeout for rsync copy (should fix USB mastering)
++- pass -F option to mke2fs only for non-block devices
++- use genisoimage
++- die if genisoimage can not be run
++- use wodim instead of cdrecord
++
++* copy wizard
++- don't create a master for onthefly USB recording
++- don't show Previous button in copy wizard (#25868)
++- allow to select a master image in the copy wizard
++- update progress during live USB recording
++- add an end step
++- warn if an error occurs during live copy
++- use 788 as default vga mode
++
++* misc:
++- don't add splash/vga settings on cmdline if no vga mode is defined
++- umount any nfs volume in /mnt (warly)
++- use the 'never' timeout value instead of hardcoded values
++- automatically select storage type if only one is available
++- define directory mounts in their mount order, and reverse the order
++ when mounting unionfs
++- guess arch using rpm _target_cpu macro
++- add arch in chroot and builddir paths
++- include desktop in builddir/chroot name if specified
++
++
++0.2:
++
++- remove modprobe.preload.d files
++- remove /etc/udev/rules.d/61-*_config.rules files
++- use patch batch mode (-t) not to apply already applied patches and die if a patch can't be applied
++- run shell in initrd when the &quot;debug&quot; option is on cmdline
++- allow to add additionnal boot entries
++- umount filesystem which could stay mounted in the chroot before cleaning (warly)
++- default splash image is now splash.xpm.gz for grub
++- rename draklive.desktop as draklive-copy-wizard.desktop
++
++
++0.1:
++
++- use system's mount to mount NFS loopbacks
++- sort squashfs loopback if a config/distrib.sort file is present
+
+<a id="draklivetrunkdraklive">Added: draklive/trunk/draklive</a>
+===================================================================
+--- draklive/trunk/draklive (rev 0)
++++ draklive/trunk/draklive 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,1800 @@
++#!/usr/bin/perl
++
++# draklive $Id: draklive 150793 2007-04-05 12:08:47Z blino $
++
++# Copyright (C) 2005 Mandriva
++# Olivier Blin &lt;oblin@mandriva.com&gt;
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2, or (at your option)
++# any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++use lib qw(/usr/lib/libDrakX);
++use strict;
++use MDK::Common;
++use common;
++use fs;
++use modules;
++use run_program;
++use Getopt::Long;
++use Pod::Usage;
++use File::Temp;
++use IO::Handle; #- autoflush
++use POSIX;
++use MDV::Draklive::Utils;
++use MDV::Draklive::Live;
++use MDV::Draklive::Progress;
++use MDV::Draklive::Loopback;
++use MDV::Draklive::Initrd;
++use MDV::Draklive::Config;
++use MDV::Draklive::Storage;
++
++sub get_syslinux_path {
++ my ($media, $opts) = @_;
++ '/' . $media-&gt;{storage} . '/syslinux' . ($opts-&gt;{boot} &amp;&amp; '-boot-' . $opts-&gt;{boot}) . '.cfg';
++}
++
++sub need_media_specific_boot {
++ my ($live) = @_;
++ to_bool(list_selected_loopbacks($live));
++}
++
++sub get_default_append {
++ my ($live, $opts) = @_;
++ my $append = $opts-&gt;{append} || $live-&gt;{system}{append};
++ join(' ',
++ if_(!need_media_specific_boot($live),
++ 'root=' . $live-&gt;{media}-&gt;get_media_source_for_nash),
++ if_($live-&gt;{system}{vga_mode} &amp;&amp; $append !~ /\bvga=\b/,
++ 'splash=silent',
++ 'vga=' . $live-&gt;{system}{vga_mode}),
++ if_($append, $append),
++ );
++}
++
++sub get_bootloader_timeout {
++ my ($live) = @_;
++ defined $live-&gt;{media}{bootloader_timeout} ? $live-&gt;{media}{bootloader_timeout} : 4;
++}
++
++my @syslinux_boot_files = qw(/vmlinuz /syslinux/bootlogo /help.msg);
++
++sub build_syslinux_cfg {
++ my ($live, $media, $opts) = @_;
++ my $append = get_default_append($live, $opts);
++ #- syslinux wants files at root (used with vfat fs)
++ my $to_root = $media-&gt;get_boot_setting('fs', $opts) eq 'vfat';
++ my $boot = $live-&gt;get_media_prefix('boot', $opts-&gt;{boot});
++ my ($initrd, $kernel, $bootlogo, $help) = map { $to_root ? basename($_) : $_ }
++ map { $boot . $_ } $media-&gt;get_initrd_path, @syslinux_boot_files;
++ my $has_bootlogo = $live-&gt;{system}{gfxboot} &amp;&amp;
++ -e ($live-&gt;get_builddir . $live-&gt;{prefix}{build}{boot} . '/syslinux/bootlogo');
++ my $timeout = get_bootloader_timeout($live) * 10;
++ my $title = $media-&gt;{title} || $live-&gt;{media}{title};
++ join(&quot;\n&quot;,
++ &quot;default $title&quot;,
++ &quot;prompt 1&quot;,
++ &quot;timeout $timeout&quot;,
++ &quot;display $help&quot;,
++ if_($has_bootlogo, &quot;ui gfxboot.com $bootlogo&quot;),
++ (map {
++ my ($name, $cmdline) = @$_;
++ $name =~ s/\s/_/g;
++ if ($name eq &quot;harddisk&quot;) {
++ &quot;label &quot; . $name,
++ &quot; localboot 0x80&quot;;
++ } else {
++ &quot;label &quot; . ($name || $title),
++ &quot; kernel $kernel&quot;,
++ &quot; append initrd=$initrd $append $cmdline&quot;;
++ }
++ } group_by2(@{$media-&gt;{boot_entries}})),
++ &quot;&quot;,
++ );
++}
++
++sub build_grub_cfg {
++ my ($live, $media, $opts, $device) = @_;
++ #- FIXME? first partition is hardcoded for loopback (master images)
++ #- FIXME? use find_partition_index
++ my ($part_nb) = $device =~ m!/dev/loop! ? 1 : $device =~ /(\d+)$/;
++ my $part_idx = $part_nb - 1;
++ my $initrd = $media-&gt;get_initrd_path;
++ build_grub_cfg_raw($live, $media, $initrd, $opts, $part_idx);
++}
++
++sub build_grub_cfg_raw {
++ my ($live, $media, $initrd, $opts, $part_idx) = @_;
++ #- FIXME: use the bootloader module from drakx
++ my $grub_part = &quot;(hd0&quot; . (defined $part_idx ? &quot;,&quot; . $part_idx : &quot;&quot;) . &quot;)&quot;;
++ my $boot = $live-&gt;get_media_prefix('boot'); #- FIXME handle boot media
++ #- remove prefix if installing bootloader on separate /boot partition
++ $media-&gt;{partitions}[$part_idx]{mntpoint} eq $boot and $boot = &quot;&quot;;
++
++ my $title = $media-&gt;{title} || $live-&gt;{media}{title};
++
++ join(&quot;\n&quot;,
++ &quot;timeout &quot; . get_bootloader_timeout($live),
++ if_($live-&gt;{system}{gfxboot}, &quot;gfxmenu $grub_part&quot; . $boot . &quot;/gfxmenu&quot;),
++ &quot;default 0&quot;,
++ (map {
++ my ($name, $cmdline) = @$_;
++ &quot;title &quot; . $title . if_($name, &quot; ($name)&quot;),
++ &quot;kernel $grub_part&quot; . $boot . &quot;/vmlinuz &quot; . get_default_append($live, $opts) . if_($cmdline, &quot; $cmdline&quot;),
++ if_($initrd, &quot;initrd &quot; . $boot . $initrd);
++ } group_by2(@{$media-&gt;{boot_entries}})),
++ ($live-&gt;{oem_rescue} &amp;&amp; defined $opts-&gt;{oem_rescue_idx} ? (
++ #- FIXME: factorize with above, build_grub_cfg_entry($media)
++ &quot;title &quot; . $live-&gt;{oem_rescue}{media}{title},
++ &quot;kernel (hd0,$opts-&gt;{oem_rescue_idx})&quot; . $boot . &quot;/vmlinuz &quot; . $live-&gt;{oem_rescue}{append},
++ &quot;initrd (hd0,$opts-&gt;{oem_rescue_idx})&quot; . $boot . $media-&gt;get_initrd_path,
++ ) : ()),
++ &quot;&quot;,
++ );
++}
++
++sub get_langs {
++ my ($live) = @_;
++ uniq(
++ (ref $live-&gt;{regions} ? @{$live-&gt;{regions}{$live-&gt;{settings}{region}}} : ()),
++ @{$live-&gt;{system}{langs_always}}
++ );
++}
++
++sub install_system {
++ my ($live) = @_;
++
++ my $repository = $live-&gt;{settings}{repository} . '/' . $live-&gt;{settings}{arch};
++
++ my $drakx_in_chroot = $repository . '/misc/drakx-in-chroot';
++ my $remote_repository = $repository =~ m!^(ftp|http)://! &amp;&amp; $1;
++ if ($remote_repository) {
++ my $local_drakx_in_chroot = $live-&gt;get_builddir . $live-&gt;{prefix}{build}{scripts} . '/drakx-in-chroot';
++ mkdir_p(dirname($local_drakx_in_chroot));
++ run_('curl', '--silent', '-o', $local_drakx_in_chroot, $drakx_in_chroot)
++ or die &quot;unable to get drakx-in-chroot from remote repository\n&quot;;
++ $drakx_in_chroot = $local_drakx_in_chroot;
++ }
++
++ local %ENV = (
++ %ENV,
++ (map { &quot;DRAKLIVE_&quot;. uc($_-&gt;[0]) =&gt; $_-&gt;[1] } group_by2(%{$live-&gt;{settings}})),
++ %{$live-&gt;{system}{install_env}},
++ );
++ $ENV{DRAKLIVE_LANGS} = join(':', get_langs($live));
++ run_({ targetarch =&gt; $live-&gt;{settings}{arch} },
++ 'perl', $drakx_in_chroot,
++ $repository,
++ $live-&gt;get_system_root,
++ if_($live-&gt;{system}{auto_install}, '--auto_install', $live-&gt;{settings}{config_root} . '/' . $live-&gt;{system}{auto_install}),
++ if_($live-&gt;{system}{patch_install}, '--defcfg', $live-&gt;{settings}{config_root} . '/' . $live-&gt;{system}{patch_install}),
++ if_($live-&gt;{system}{rpmsrate}, '--rpmsrate', $live-&gt;{settings}{config_root} . '/' . $live-&gt;{system}{rpmsrate}),
++ ($live-&gt;{system}{stage2_updates} ? (map { ('--stage2-update', $live-&gt;{settings}{config_root} . '/' . $_-&gt;[0], $_-&gt;[1]) } @{$live-&gt;{system}{stage2_updates}}) : ()),
++ ) or die &quot;unable to install system chroot\n&quot;;
++ post_install_system($live);
++}
++
++sub configure_draklive_resize {
++ my ($live) = @_;
++
++ my $resizable_loopback = find { $_-&gt;{min_size} } @{$live-&gt;{mount}{dirs} || []};
++ if ($resizable_loopback) {
++ my $media_loopbacks = $live-&gt;get_media_prefix('loopbacks');
++ my $ext = $loop_types{$resizable_loopback-&gt;{type}}{extension};
++ output($live-&gt;get_system_root . '/etc/sysconfig/draklive-resize', &lt;&lt;EOF);
++DRAKLIVE_RESIZE=yes
++LOOPBACK=$live-&gt;{prefix}{live}{mnt}$live-&gt;{prefix}{media}{mnt}${media_loopbacks}$resizable_loopback-&gt;{path}$ext
++TYPE=$resizable_loopback-&gt;{fs}
++MIN_SIZE=$resizable_loopback-&gt;{min_size}
++MOUNT=$live-&gt;{prefix}{live}{mnt}$resizable_loopback-&gt;{mountpoint}_resized
++OLD_MOUNT=$live-&gt;{prefix}{live}{mnt}$resizable_loopback-&gt;{mountpoint}
++UNION=/
++EOF
++ }
++}
++
++sub copy_files_to {
++ my ($live, $files, $root) = @_;
++ foreach (@$files) {
++ my ($source, $dest, $o_opts) = @$_;
++ $dest = $root . '/' . $dest;
++ mkdir_p($dest =~ m|/$| ? $dest : dirname($dest));
++ my @sources = MDV::Draklive::Utils::glob__($live-&gt;{settings}{config_root} . '/' . $source);
++ print STDERR &quot;copying @sources to $dest\n&quot;;
++ cp_af(@sources, $dest);
++ my $o_perm = $o_opts &amp;&amp; $o_opts-&gt;{mode};
++ chmod $o_perm, $dest if $o_perm;
++ }
++}
++
++sub join_lists {
++ my ($separator, $head, @lists) = @_;
++ @{$head || []}, map { $separator, @$_ } @lists;
++}
++
++sub remove_files_from {
++ my ($files, $root) = @_;
++ run_('find', $root, '(', join_lists('-o', map { [ '-name', $_ ] } @$files), ')', '-exec', 'rm', '-r', '{}', ';')
++ if $files &amp;&amp; @$files;
++}
++
++sub clean_system_conf_file {
++ my ($live, $file) = @_;
++ substInFile { undef $_ if /^[^#]/ } $live-&gt;get_system_root . $file;
++}
++
++sub post_install_system {
++ my ($live) = @_;
++
++ my $previous_umask = umask;
++ #- workaround buggy installation of directories that are not owned by any packages
++ umask 022;
++
++ run_('mount', '-t', 'proc', '/proc', $live-&gt;get_system_root . '/proc');
++ run_('mount', '-t', 'sysfs', '/sys', $live-&gt;get_system_root . '/sys');
++
++ #- copy resolv.conf for name resolution to work when adding media
++ cp_f(&quot;/etc/resolv.conf&quot;, $live-&gt;get_system_root . &quot;/etc/&quot;);
++
++ #- remove previous draklive leftovers if needed
++ run_({ root =&gt; $live-&gt;get_system_root }, 'urpmi.removemedia', '-a');
++
++ foreach (@{$live-&gt;{system}{additional_media}}) {
++ run_({ root =&gt; $live-&gt;get_system_root }, 'urpmi.addmedia', if_($_-&gt;{distrib}, '--distrib'), $_-&gt;{name}, $_-&gt;{path})
++ or die &quot;unable to add media from $_-&gt;{path}\n&quot;;
++ @{$_-&gt;{packages} || []} or next;
++ run_({ root =&gt; $live-&gt;get_system_root, targetarch =&gt; $live-&gt;{settings}{arch} },
++ 'urpmi', '--auto', '--no-verify-rpm', if_(!$_-&gt;{distrib}, '--searchmedia', $_-&gt;{name}), @{$_-&gt;{packages}})
++ or die &quot;unable to install packages from $_-&gt;{path}\n&quot;;
++ }
++
++ #- additional rpms may have dependencies in additional media
++ if (@{$live-&gt;{system}{rpms} || []}) {
++ my $rpm_tmp_dir = '/tmp/draklive_rpms';
++ mkdir_p($live-&gt;get_system_root . $rpm_tmp_dir);
++ cp_f((map { $live-&gt;{settings}{config_root} . '/' . $_ } @{$live-&gt;{system}{rpms}}), $live-&gt;get_system_root . $rpm_tmp_dir);
++ run_({ root =&gt; $live-&gt;get_system_root, targetarch =&gt; $live-&gt;{settings}{arch} },
++ 'urpmi', '--auto', '--no-verify-rpm',
++ map { $rpm_tmp_dir . '/' . basename($_) } @{$live-&gt;{system}{rpms}})
++ or die &quot;unable to install additional system rpms\n&quot;;
++ rm_rf($live-&gt;get_system_root . $rpm_tmp_dir);
++ }
++
++ #- remove urpmi media added by drakx-in-chroot and additional media, they're unusable
++ run_({ root =&gt; $live-&gt;get_system_root }, 'urpmi.removemedia', '-a');
++
++ my $erase = join(' ', @{$live-&gt;{system}{erase_rpms} || []});
++ run_({ root =&gt; $live-&gt;get_system_root, targetarch =&gt; $live-&gt;{settings}{arch} },
++ 'sh', '-c', &quot;rpm -qa $erase | xargs rpm -e &quot;) if $erase;
++
++ run_({ root =&gt; $live-&gt;get_system_root }, 'chkconfig', '--del', $_) foreach @{$live-&gt;{system}{disable_services}};
++
++ #- make sure harddrake is run:
++ #- if previous HW config file is empty, we assumes DrakX has just completed the installation
++ #- (do it in chroot, or else Storable from the build box may write an incompatible config file)
++ run_({ root =&gt; $live-&gt;get_system_root },
++ 'perl', '-MStorable', '-e', qq(Storable::store({ UNKNOWN =&gt; {} }, '/etc/sysconfig/harddrake2/previous_hw')));
++
++ #- remove some build-machine specific configuration
++ clean_system_conf_file($live, $_)
++ foreach qw(/etc/mtab /etc/modprobe.conf /etc/modprobe.preload /etc/iftab /etc/shorewall/interfaces /etc/mdadm.conf),
++ if_(!$live-&gt;{system}{skip_fstab}, '/etc/fstab');
++ unlink($_) foreach map { glob($live-&gt;get_system_root . $_) } @{$live-&gt;{system}{remove_files} || []};
++
++ if ($live-&gt;{system}{modules_conf}) {
++ local $::prefix = $live-&gt;get_system_root;
++ local *modules::write_preload_conf = sub {}; #- FIXME, make this an option
++ my $modules_conf = modules::any_conf-&gt;vnew;
++ put_in_hash($modules_conf, $live-&gt;{system}{modules_conf});
++ $modules_conf-&gt;write;
++ }
++
++ my $mount_options = $live-&gt;{media}-&gt;get_media_setting('mount_options') || &quot;defaults&quot;;
++ output_with_perm($live-&gt;get_system_root . '/etc/fstab', 0644,
++ $live-&gt;{mount}{overlay}
++ ? &quot;none / $live-&gt;{mount}{overlay} $mount_options 0 0\n&quot;
++ : $live-&gt;{media}-&gt;get_media_setting('source') . &quot; / &quot; . $live-&gt;{media}-&gt;get_media_setting('fs') . &quot; $mount_options 1 1\n&quot;
++ ) unless $live-&gt;{system}{skip_fstab};
++
++ #- interactive mode can lead to race in initscripts
++ #- (don't use addVarsInSh from MDK::Common, it breaks shell escapes)
++ substInFile { s/^PROMPT=.*/PROMPT=no/ } $live-&gt;get_system_root . '/etc/sysconfig/init';
++
++ configure_draklive_resize($live);
++
++ if ($live-&gt;{system}{preselect_kdm_user}) {
++ #- preselect specified user in kdm
++ my $kdm_cfg = $live-&gt;get_system_root . '/etc/kde/kdm/kdmrc';
++ update_gnomekderc($kdm_cfg, 'X-:0-Greeter' =&gt; (PreselectUser =&gt; 'Default', DefaultUser =&gt; $live-&gt;{system}{preselect_kdm_user})) if -f $kdm_cfg;
++ }
++
++ #- apply patches and install files after the configuration is cleaned
++ #- to allow special configuration files (especially modprobe.preload)
++ foreach (@{$live-&gt;{system}{patches}}) {
++ my $patch = $live-&gt;{settings}{config_root} . '/' . $_;
++ my @args = ('-p0', '-d', $live-&gt;get_system_root, '-i', $patch);
++ run_program::run('patch', '&gt;', '/dev/null', '--dry-run', '-f', '-R', @args) || run_('patch', @args)
++ or die &quot;unable to apply patch &quot; . $patch . &quot;\n&quot;;
++ }
++
++ copy_files_to($live, $live-&gt;{system}{files}, $live-&gt;get_system_root);
++ my @no_install_files = map { $_-&gt;[1] } grep { $_-&gt;[2] &amp;&amp; $_-&gt;[2]{no_install} } @{$live-&gt;{system}{files}};
++ output_p($live-&gt;get_system_root . '/etc/draklive-install.d/remove.d/draklive', map { &quot;$_\n&quot; } @no_install_files);
++
++ eval { rm_rf($live-&gt;get_builddir . $live-&gt;{prefix}{build}{files}) };
++ mkdir_p($live-&gt;get_builddir . $live-&gt;{prefix}{build}{files});
++ if ($live-&gt;{media}{files}) {
++ copy_files_to($live, $live-&gt;{media}{files}, $live-&gt;get_builddir . $live-&gt;{prefix}{build}{files});
++ }
++ remove_files_from($live-&gt;{media}{remove_files}, $live-&gt;get_builddir . $live-&gt;{prefix}{build}{files});
++
++ run_({ targetarch =&gt; $live-&gt;{settings}{arch} },
++ &quot;chroot&quot;, $live-&gt;get_system_root, &quot;bash&quot;, &quot;-c&quot;, $live-&gt;{system}{postInstall}) if $live-&gt;{system}{postInstall};
++
++ clean_system_conf_file($live, &quot;/etc/resolv.conf&quot;);
++ write_dist_lists($live);
++
++ run_('umount', $live-&gt;get_system_root . '/sys');
++ run_('umount', $live-&gt;get_system_root . '/proc/bus/usb');
++ run_('umount', $live-&gt;get_system_root . '/proc');
++
++ umask $previous_umask;
++}
++
++sub write_dist_lists {
++ my ($live) = @_;
++
++ my $lists_dir = $live-&gt;get_builddir . $live-&gt;{prefix}{build}{dist};
++ mkdir_p($lists_dir);
++
++ run_(&quot;chroot &quot; . $live-&gt;get_system_root . &quot; rpm -qa | sort &gt; &quot; .
++ $lists_dir . '/' . $live-&gt;get_name . '.lst');
++
++ run_(&quot;chroot &quot; . $live-&gt;get_system_root . &quot; rpm -qa --qf '%{name}\n' | sort &gt; &quot; .
++ $lists_dir . '/' . $live-&gt;get_name . '.lst.names');
++
++ run_(&quot;chroot &quot; . $live-&gt;get_system_root .
++ qq( sh -c &quot;rpm -qa --qf '%{size} \t%{name}\n' | sort -n&quot; &gt; ) .
++ $lists_dir . '/' . $live-&gt;get_name . '.lst.full');
++
++ run_(&quot;chroot &quot; . $live-&gt;get_system_root .
++ qq( sh -c &quot;urpmi_rpm-find-leaves | xargs rpm -q --qf '%{size} \t%{name}\n' | sort -n&quot; &gt; ) .
++ $lists_dir . '/' . $live-&gt;get_name . '.lst.leaves');
++
++ require lang;
++ my @live_langs = get_langs($live);
++ my @langs = grep { member($_, @live_langs) || member(lang::locale_to_main_locale($_), @live_langs) } lang::list_langs();
++ my $langs_file = $lists_dir . '/' . $live-&gt;get_name . '.langs';
++ output_p($langs_file, map { lang::l2name($_) . &quot; (&quot; . $_ . &quot;)\n&quot; } sort(@langs));
++}
++
++sub umount_external_filesystem {
++ my ($live) = @_;
++ my $mnt = $live-&gt;get_system_root . &quot;/mnt/&quot;;
++ eval { fs::mount::umount(&quot;$mnt/$_&quot;) } foreach all($mnt);
++}
++
++sub expand_file_list {
++ my ($live, @files) = @_;
++ map {
++ $_-&gt;{path} ?
++ $_-&gt;{path} :
++ chomp_(cat_(glob(($_-&gt;{rooted} &amp;&amp; $live-&gt;get_system_root) . $_-&gt;{source})));
++ } @files;
++}
++
++#- hardlink recursively file list to a directory
++sub hardlink_filtered {
++ my ($src, $dest, $files) = @_;
++ mkdir_p($dest);
++ my $pwd = $ENV{PWD};
++ chdir($src);
++ my $list_file = tmpnam();
++ output_p($list_file, map { &quot;$_\n&quot; } grep { -e $src . $_ } @$files);
++ #- cpio -pldm won't copy recursively, use rsync -r instead
++ system('rsync', '-ar', '--files-from=' . $list_file, '--link-dest=' . $src, $src, $dest);
++ unlink $list_file;
++ chdir($pwd);
++}
++
++sub list_loopback_modules {
++ my ($live) = @_;
++ map {
++ my $l = $_;
++ map {
++ my $list = $_;
++ my $name = basename($list);
++ $name =~ s/\.[^.]+$//;
++ { type =&gt; $l-&gt;{type}, name =&gt; $name, files =&gt; [ expand_file_list($live, { source =&gt; $list }) ] };
++ } glob(($_-&gt;{rooted} &amp;&amp; $live-&gt;get_system_root) . $_-&gt;{source});
++ } @{$live-&gt;{loopbacks}{modules}};
++}
++
++sub create_loopback_files {
++ my ($live) = @_;
++ # umount filesystem in the live before creating the loopback
++ umount_external_filesystem($live);
++
++ my @excluded_files = expand_file_list($live, @{$live-&gt;{loopbacks}{exclude}{files} || []});
++ my @modules_files = expand_file_list($live, @{$live-&gt;{loopbacks}{modules} || []});
++
++ foreach (grep { exists $loop_types{$_-&gt;{type}}{build} } @{$live-&gt;{mount}{dirs} || []}) {
++ local $_-&gt;{exclude} = [ @excluded_files, @modules_files ];
++ $loop_types{$_-&gt;{type}}{build}-&gt;($live, $_);
++ }
++
++ foreach my $module (list_loopback_modules($live)) {
++ my $copy_tree = $live-&gt;get_system_root . &quot;/tmp/draklive/loop/$module-&gt;{name}&quot;;
++ eval { rm_rf($copy_tree) };
++ hardlink_filtered($live-&gt;get_system_root, $copy_tree, $module-&gt;{files});
++ my $loop = $loop_types{$module-&gt;{type}};
++ $loop-&gt;{build}-&gt;($live, { path =&gt; &quot;$live-&gt;{prefix}{build}{modules}/$module-&gt;{name}&quot;, root =&gt; $copy_tree, exclude =&gt; \@excluded_files });
++ eval { rm_rf($copy_tree) };
++ }
++
++ if (@excluded_files) {
++ my $excluded_tree = $live-&gt;get_system_root . &quot;/tmp/draklive/excluded/all&quot;;
++ eval { rm_rf($excluded_tree) };
++ hardlink_filtered($live-&gt;get_system_root, $excluded_tree, \@excluded_files);
++
++ foreach my $module (list_loopback_modules($live)) {
++ my $copy_tree = $live-&gt;get_system_root . &quot;/tmp/draklive/excluded/$module-&gt;{name}&quot;;
++ eval { rm_rf($copy_tree) };
++ hardlink_filtered($excluded_tree, $copy_tree, $module-&gt;{files});
++ my $loop = $loop_types{$module-&gt;{type}};
++ $loop-&gt;{build}-&gt;($live, { path =&gt; &quot;$live-&gt;{prefix}{build}{modules}/excluded-$module-&gt;{name}&quot;, root =&gt; $copy_tree });
++ eval { rm_rf($copy_tree) };
++ }
++
++ my $loop = $loop_types{$live-&gt;{loopbacks}{exclude}{type}};
++ $loop-&gt;{build}-&gt;($live, { path =&gt; &quot;/excluded&quot;, root =&gt; $excluded_tree, exclude =&gt; \@modules_files });
++
++ eval { rm_rf($excluded_tree) };
++ }
++}
++
++sub list_selected_loopbacks {
++ my ($live) = @_;
++ my @pack = $live-&gt;{settings}{pack} ? @{$live-&gt;{packs}{$live-&gt;{settings}{pack}} || []} : ();
++ my @pack_modules = grep { member($_-&gt;{name}, @pack) } list_loopback_modules($live);
++ (map { $loop_types{$_-&gt;{type}}{is_loopback} &amp;&amp; $_-&gt;{path} ? $_-&gt;{path} . $loop_types{$_-&gt;{type}}{extension} : () } @{$live-&gt;{mount}{dirs} || []}),
++ (map { $live-&gt;{prefix}{build}{modules} . '/' . $_-&gt;{name} . $loop_types{$_-&gt;{type}}{extension} } @pack_modules);
++}
++
++sub get_media_device {
++ my ($live, $opts) = @_;
++ return $opts-&gt;{device} if $opts-&gt;{device};
++ my $label = $live-&gt;{media}-&gt;get_media_label
++ or die &quot;no device and no label&quot;;
++ my $device = chomp_(`readlink -f /dev/disk/by-label/$label`)
++ or die &quot;unable to find device for /dev/disk/by-label/$label\n&quot;;
++ $device;
++}
++
++sub prepare_bootloader {
++ my ($live) = @_;
++ create_initrd($live);
++ create_bootloader($live) if !($live-&gt;{system}{skip_bootloader_config} || $live-&gt;{system}{skip_bootloader_install});
++}
++
++sub create_initrd {
++ my ($live) = @_;
++ my $root = $live-&gt;get_system_root;
++
++ run_('mount', '-t', 'proc', 'none', $root . '/proc');
++ run_('mount', '-t', 'sysfs', 'none', $root . '/sys');
++
++ if (need_media_specific_boot($live)) {
++ MDV::Draklive::Initrd::create_media_initrd($live);
++ } else {
++ MDV::Draklive::Initrd::create_classical_initrd($live);
++ }
++
++ run_('umount', $root . '/sys');
++ run_('umount', $root . '/proc');
++}
++
++sub create_bootloader {
++ my ($live) = @_;
++
++ my $root = $live-&gt;get_system_root;
++ my $kernel = $live-&gt;find_kernel-&gt;{version};
++ my $vmlinuz_long = '/boot/vmlinuz-' . $kernel;
++ -e $root . $vmlinuz_long or die &quot;can not find kernel $kernel\n&quot;;
++
++ if ($live-&gt;{system}{gfxboot}) {
++ run_('mount', '-t', 'proc', 'none', $root . '/proc');
++ run_('mount', '-t', 'sysfs', 'none', $root . '/sys');
++
++ #- would be run by bootloader::add_boot_splash and make-boot-splash, but not called when we don't generate an initrd
++ run_({ root =&gt; $root }, '/usr/share/bootsplash/scripts/switch-themes', '-u');
++ #- grub-gfxmenu would be run by bootloader::write_grub from DrakX
++ run_({ root =&gt; $root }, '/usr/sbin/grub-gfxmenu', '--update-gfxmenu');
++ my $gfxmenu = $root . '/boot/gfxmenu';
++ if (-e $gfxmenu) {
++ my $boot_dir = $live-&gt;get_builddir . $live-&gt;{prefix}{build}{boot};
++ mkdir_p($boot_dir);
++ cp_f($gfxmenu, $boot_dir);
++ } else {
++ warn &quot;no gfxmenu file\n&quot;;
++ }
++
++ run_('umount', $root . '/sys');
++ run_('umount', $root . '/proc');
++ }
++
++ # this will copy (among other things) the gfxboot theme to the media
++ # so this must be done before the creating the bootloader since the code
++ # in there may check if a bootlogo is present or not
++ create_syslinux_msg_files($live);
++
++ if (need_media_specific_boot($live)) {
++ create_media_bootloader($live);
++ } else {
++ create_classical_bootloader($live);
++ }
++}
++
++sub remove_unneeded_bootlogo_locales {
++ use File::Temp;
++ use Cwd;
++
++ my ($bootlogo, @locales) = @_;
++
++ $bootlogo = Cwd::realpath($bootlogo);
++ -f $bootlogo or return;
++
++ my $cwd = Cwd::getcwd();
++ my $tempdir = File::Temp::tempdir(&quot;mdvgfxbootXXXX&quot;, CLEANUP =&gt; 1);
++ chdir $tempdir;
++ !system(&quot;cpio -id &lt; $bootlogo&quot;) or return;
++
++ # Make sure we include the en locale
++ push @locales, 'en';
++ my @kept_locales;
++ foreach my $file (glob &quot;*.tr&quot;) {
++ if (!any { $file =~ /^$_\.tr$/ } @locales) {
++ unlink $file;
++ } else {
++ my ($locale_name) = $file =~ /(.*)\.tr$/;
++ push @kept_locales, $locale_name;
++ }
++ }
++ system(qq(echo init 16x16.fnt *.tr |sed &quot;s/ /\\n/g&quot; |cpio -o &gt;$bootlogo));
++ chdir $cwd;
++
++ print &quot;gfxboot locales: &quot; . join(&quot; &quot;, @kept_locales) . &quot;\n&quot;;
++ return @kept_locales;
++}
++
++#- forked from bootsplash::themes_read_sysconfig
++sub get_bootsplash_theme() {
++ my $sysconfig_file = &quot;/etc/sysconfig/bootsplash&quot;;
++ local $_;
++ my %theme;
++ foreach (cat_($::prefix . $sysconfig_file)) {
++ /^THEME=(.*)/ and $theme{name} = $1;
++ }
++ \%theme;
++}
++
++sub create_syslinux_msg_files {
++ my ($live) = @_;
++ my $syslinux_dir = $live-&gt;get_builddir . $live-&gt;{prefix}{build}{boot} . '/syslinux';
++ mkdir_p($syslinux_dir);
++
++ if ($live-&gt;{system}{gfxboot}) {
++ my $default_gfxboot_theme = &quot;Mandriva&quot;;
++ require bootsplash;
++ my $theme = do {
++ local $::prefix = $live-&gt;get_system_root;
++ get_bootsplash_theme();
++ };
++ print &quot;copying $default_gfxboot_theme gfxboot theme\n&quot;;
++ cp_f(glob_($live-&gt;get_system_root . &quot;/usr/share/gfxboot/themes/$default_gfxboot_theme/install/*&quot;), $syslinux_dir);
++ if ($theme-&gt;{name} ne $default_gfxboot_theme) {
++ print &quot;copying $theme-&gt;{name} gfxboot theme\n&quot;;
++ cp_f(glob_($live-&gt;get_system_root . &quot;/usr/share/gfxboot/themes/$theme-&gt;{name}/*&quot;), $syslinux_dir);
++ }
++ my $bootlogo = $syslinux_dir . '/bootlogo';
++ warn &quot;unable to find gfxboot splash ($bootlogo)\n&quot; if ! -f $bootlogo;
++ my @locales = remove_unneeded_bootlogo_locales($bootlogo, get_langs($live));
++ output_p($syslinux_dir . '/langs', join(&quot;\n&quot;, @locales) . &quot;\n&quot;);
++ output_p($syslinux_dir . '/gfxboot.cfg', join(&quot;\n&quot;,
++ &quot;livecd=1&quot;,
++ &quot;mainmenu.pos=210,235&quot;,
++ &quot;mainmenu.bar.minwidth=400&quot;,
++ &quot;panel.f-key.fg=0x33358c&quot;,
++ &quot;&quot;,
++ ));
++ }
++
++ output($live-&gt;get_builddir . $live-&gt;{prefix}{build}{boot} . '/help.msg',
++ pack(&quot;C*&quot;, 0x0E, 0x80, 0x03, 0x00, 0xC) . qq(
++Welcome to Mageia live!
++
++The command line can be used to specify kernel options.
++
++$live-&gt;{media}{title} &lt;kernel options&gt;
++
++));
++}
++
++sub create_media_bootloader {
++ my ($live) = @_;
++ cp_f($live-&gt;get_system_root . '/boot/vmlinuz-' . $live-&gt;find_kernel-&gt;{version}, $live-&gt;get_builddir . $live-&gt;{prefix}{build}{boot} . '/vmlinuz');
++ foreach my $boot ('', @{$live-&gt;{media}{extra_boot}}) {
++ my $opts = { boot =&gt; $boot };
++ output($live-&gt;get_builddir . $live-&gt;{prefix}{build}{boot} . get_syslinux_path($live-&gt;{media}, $opts),
++ build_syslinux_cfg($live, $live-&gt;{media}, $opts));
++ }
++}
++
++sub create_classical_bootloader {
++ my ($live) = @_;
++ my $initrd_prefix = &quot;/initrd.img&quot;;
++ my $initrd = $live-&gt;get_system_root . $live-&gt;get_media_prefix('boot') . $initrd_prefix;
++ my $part_idx = $live-&gt;{media}-&gt;find_boot_partition_index;
++ my $oem_rescue_idx = $live-&gt;{media}-&gt;find_partition_index('OEM_RESCUE');
++ output_p($live-&gt;get_system_root . '/boot/grub/menu.lst', build_grub_cfg_raw($live, $live-&gt;{media}, -e $initrd &amp;&amp; $initrd_prefix, { oem_rescue_idx =&gt; $oem_rescue_idx }, $part_idx));
++}
++
++sub create_tarball {
++ my ($live) = @_;
++ run_(&quot;tar&quot;, &quot;cjf&quot;, get_disk_master_prefix($live) . &quot;.tar.bz2&quot;, $live-&gt;get_system_root);
++}
++
++sub set_device_label {
++ my ($device, $type, $label) = @_;
++ if ($type eq 'vfat') {
++ MDV::Draklive::Utils::mtools_run_('mlabel', '-i', $device, '::' . $label);
++ } elsif (member($type, 'ext2', 'ext3')) {
++ run_('e2label', $device, $label);
++ } else {
++ die &quot;unable to set label for unsupported media type $type\n&quot;;
++ }
++}
++
++sub get_cdrom_master_path {
++ my ($live, $opts) = @_;
++ $live-&gt;get_builddir . $live-&gt;{prefix}{build}{dist} . '/' . $live-&gt;get_name . ($opts-&gt;{boot} &amp;&amp; &quot;-boot-$opts-&gt;{boot}&quot;) . '.iso';
++}
++
++sub get_cdrom_replicator_path {
++ my ($live) = @_;
++ get_disk_replicator_prefix($live) . &quot;.iso&quot;;
++}
++
++sub create_cdrom_master {
++ my ($live, $opts) = @_;
++ my $label = $live-&gt;{media}-&gt;get_media_label or die &quot;the source device must be described by a label\n&quot;;
++ my $dest;
++ unless ($opts-&gt;{onthefly}) {
++ $dest = get_cdrom_master_path($live, $opts);
++ mkdir_p(dirname($dest));
++ }
++ build_iso_image(
++ $live, $opts,
++ $dest,
++ $live-&gt;get_builddir . $live-&gt;{prefix}{build}{boot} . get_syslinux_path($live-&gt;{media}, $opts),
++ $label,
++ $live-&gt;get_media_prefix('boot', $opts-&gt;{boot}) . '=' . $live-&gt;get_builddir . $live-&gt;{prefix}{build}{boot},
++ if_(!$opts-&gt;{boot_only},
++ (map {
++ $live-&gt;get_media_prefix('loopbacks', $opts-&gt;{boot}) . $_ .
++ '=' .
++ $live-&gt;get_builddir . $live-&gt;{prefix}{build}{loopbacks} . $_;
++ } list_selected_loopbacks($live)),
++ if_($live-&gt;{media}{files},
++ map {
++ $_ . '=' . $live-&gt;get_builddir . $live-&gt;{prefix}{build}{files} . '/' . $_;
++ } all($live-&gt;get_builddir . $live-&gt;{prefix}{build}{files})
++ ),
++ ),
++ );
++}
++
++sub build_iso_image {
++ my ($live, $opts, $dest, $isolinux_cfg, $label, @opts) = @_;
++
++ my $progress = MDV::Draklive::Progress-&gt;new(100, time());
++ my $in_progress;
++ autoflush STDOUT 1;
++ run_foreach(sub {
++ if (/^\s*([0-9.]+)%\s*done,/) {
++ $progress-&gt;{current} = int($1);
++ $progress-&gt;show(time());
++ $in_progress = 1;
++ } else {
++ print &quot;\n&quot; if $in_progress;
++ print $_;
++ $in_progress = 0;
++ }
++ },
++ 'genisoimage', '-pad', '-l', '-R', '-J',
++ '-V', $label, #'-A', $application, '-p', $preparer, '-P', $publisher,
++ '-b', 'isolinux/isolinux.bin',
++ '-c', 'isolinux/boot.cat',
++ '-hide-rr-moved', '-no-emul-boot',
++ '-boot-load-size', 4, '-boot-info-table',
++ '-graft-points',
++ if_($dest, '-o', $dest),
++ 'isolinux=' . $live-&gt;get_builddir . $live-&gt;{prefix}{build}{boot} . '/syslinux',
++ 'isolinux/isolinux.cfg=' . $isolinux_cfg,
++ 'isolinux/isolinux.bin=/usr/lib/syslinux/isolinux.bin',
++ 'isolinux/gfxboot.com=/usr/lib/syslinux/gfxboot.com',
++ @opts,
++ ) or die &quot;unable to run genisoimage\n&quot;;
++ autoflush STDOUT 0;
++ $progress-&gt;end;
++ if ($dest) {
++ my $dir = dirname($dest);
++ my $filename = basename($dest);
++ run_('isohybrid', '-fatfirst', $dest);
++ run_('mkcd', '&gt;', '/dev/null', '2&gt;', '/dev/null', '--addmd5', $dest);
++ run_({ chdir =&gt; $dir }, 'md5sum', '&gt;', $dest . '.md5', $filename);
++ run_({ chdir =&gt; $dir }, 'sha1sum', '&gt;', $dest . '.sha1', $filename);
++ }
++}
++
++sub get_disk_master_prefix {
++ my ($live) = @_;
++ $live-&gt;get_builddir . $live-&gt;{prefix}{build}{dist} . '/' . $live-&gt;get_name;
++}
++
++sub get_disk_master_path {
++ my ($live) = @_;
++ get_disk_master_prefix($live) . '.img';
++}
++
++sub get_partition_loop {
++ my ($hd, $part) = @_;
++ require devices;
++ my $loop = devices::find_free_loop();
++ run_('losetup', '-o', $part-&gt;{start} * $common::SECTORSIZE, '-s', $part-&gt;{size} * $common::SECTORSIZE, $loop, $hd-&gt;{file})
++ or die &quot;unable to setup loop device&quot;;
++ return $loop;
++}
++
++sub get_harddisk_geometry {
++ my ($media) = @_;
++ my $geom = $media-&gt;{geom} || {
++ heads =&gt; 16,
++ sectors =&gt; 63, # sectors per track
++ };
++}
++
++sub get_hd_from_layout {
++ my ($media, $dest) = @_;
++ my $geom = get_harddisk_geometry($media);
++ my $required_sectors = fold_left { $::a + $::b } map { $_-&gt;{size} } @{$media-&gt;{partitions}};
++ $required_sectors += $geom-&gt;{sectors}; # keep one more track
++ $geom-&gt;{cylinders} = POSIX::ceil($required_sectors / ($geom-&gt;{sectors} * $geom-&gt;{heads}));
++ my $total_sectors = $geom-&gt;{cylinders} * $geom-&gt;{heads} * $geom-&gt;{sectors};
++ my $hd = bless {
++ totalsectors =&gt; $total_sectors,
++ geom =&gt; $geom,
++ file =&gt; $dest,
++ }, 'partition_table::dos';
++}
++
++sub get_hd_from_file {
++ my ($media, $file) = @_;
++ my $hd = bless {
++ geom =&gt; get_harddisk_geometry($media),
++ file =&gt; $file,
++ }, 'partition_table::dos';
++ partition_table::read($hd);
++ return $hd;
++}
++
++sub supplement_media_partitions {
++ my ($media, $hd) = @_;
++ #- try to find additional partition details (start, device)
++ #- by matching actual partition table and partitions list
++ my @all_parts = partition_table::get_normal_parts($hd);
++ foreach my $idx (0 .. $#all_parts) {
++ $media-&gt;{partitions}[$idx]{$_} = $all_parts[$idx]{$_} foreach qw(start device);
++ }
++}
++
++sub set_part_real_device {
++ my ($hd, $part) = @_;
++ #- FIXME: find a better way to compute mmcblk device path
++ my $ext = $hd-&gt;{file} =~ m!^/dev/mmcblk! ? 'p' : '';
++ $part-&gt;{real_device} = -f $hd-&gt;{file} ? get_partition_loop($hd, $part) : ($hd-&gt;{file} . $ext . $part-&gt;{device});
++}
++
++sub allocate_master {
++ my ($live, $media, $opts) = @_;
++
++ $media-&gt;supplement_slash_size($opts-&gt;{slash_size}) if $opts-&gt;{slash_size};
++ my $hd = get_hd_from_layout($media, $opts-&gt;{device});
++
++ mkdir_p(dirname($opts-&gt;{device}));
++ MDV::Draklive::Utils::device_allocate_file($opts-&gt;{device}, $hd-&gt;{totalsectors} * $common::SECTORSIZE);
++}
++
++sub format_master {
++ my ($live, $media, $opts) = @_;
++
++ $media-&gt;supplement_slash_size($opts-&gt;{slash_size}) if $opts-&gt;{slash_size};
++
++ my $hd = get_hd_from_layout($media, $opts-&gt;{device});
++ partition_table::raw::zero_MBR($hd);
++
++ #- FIXME: maybe use fsedit::allocatePartitions to factorize even more?
++ foreach my $part (@{$media-&gt;{partitions}}) {
++ my $hole = find { fs::type::isEmpty($_) &amp;&amp; $_-&gt;{size} &gt;= $part-&gt;{size} } partition_table::get_normal_parts_and_holes($hd)
++ or die &quot;not enough room for $part-&gt;{mntpoint}&quot;;
++ $part-&gt;{start} = $hole-&gt;{start};
++ fs::type::set_fs_type($part, $part-&gt;{fs_type});
++ partition_table::add($hd, $part, 'Primary');
++ }
++
++ print &quot;writing partition table\n&quot;;
++ partition_table::write($hd);
++ #- FIXME: move out from diskdrake::interactive::write_partitions to partition_table::write ?
++ run_program::run('udevadm', 'settle');
++
++ my $inode_size = $media-&gt;get_media_setting('inode_size');
++ foreach my $part (@{$media-&gt;{partitions}}) {
++ set_part_real_device($hd, $part);
++ MDV::Draklive::Utils::device_mkfs($part-&gt;{real_device}, $part-&gt;{fs_type}, $part-&gt;{device_LABEL}, $inode_size)
++ or die &quot;unable to format $part-&gt;{real_device} in $hd-&gt;{file}\n&quot;;
++ devices::del_loop($part-&gt;{real_device}) if -f $hd-&gt;{file};
++ }
++}
++
++sub format_disk {
++ my ($live, $opts) = @_;
++ local $opts-&gt;{slash_size} = guess_disk_master_size($live);
++ format_master($live, $live-&gt;{media}, $opts);
++}
++
++sub guess_disk_master_size {
++ my ($live) = @_;
++
++ my $slash_size = @{$live-&gt;{mount}{dirs} || []} ?
++ (directory_usage($live-&gt;get_builddir . $live-&gt;{prefix}{build}{loopbacks}, 'apparent') +
++ directory_usage($live-&gt;get_builddir . $live-&gt;{prefix}{build}{boot}) +
++ directory_usage($live-&gt;get_builddir . $live-&gt;{prefix}{build}{files})
++ ) :
++ directory_usage($live-&gt;get_system_root);
++}
++
++sub create_disk_master {
++ my ($live, $opts) = @_;
++ local $opts-&gt;{slash_size} = guess_disk_master_size($live);
++ local $opts-&gt;{device} = get_disk_master_path($live);
++ allocate_master($live, $live-&gt;{media}, $opts);
++ format_master($live, $live-&gt;{media}, $opts);
++ record_master($live, $opts);
++}
++
++#- $opts:
++#- media: alternate media
++#- onthefly : if true, the create function must output to stdout
++sub create_master {
++ my ($live, $opts) = @_;
++
++ if (my $create = $live-&gt;{media}-&gt;get_boot_setting('create', $opts)) {
++ $create-&gt;($live, $opts);
++ } else {
++ warn &quot;not implemented yet\n&quot;;
++ }
++}
++
++sub maybe_umount_device {
++ my ($device) = @_;
++ run_('umount', $device) if cat_('/proc/mounts') =~ m!^$device\s+!m;
++}
++
++sub format_cdrom_device {
++ my ($live, $opts) = @_;
++ run_('wodim', '-v', 'dev=' . get_media_device($live, $opts), &quot;blank=fast&quot;);
++}
++
++#- $opts:
++#- media: alternate media
++sub format_device {
++ my ($live, $opts) = @_;
++
++ get_media_device($live, $opts) or die &quot;no device defined in media configuration\n&quot;;
++ if (my $format = $live-&gt;{media}-&gt;get_boot_setting('format', $opts)) {
++ $format-&gt;($live, $opts);
++ } else {
++ warn &quot;not implemented yet\n&quot;;
++ }
++}
++
++sub record_cdrom_path {
++ my ($live, $path, $opts) = @_;
++ my $device = get_media_device($live, $opts)
++ or die &quot;no device defined in media configuration\n&quot;;
++
++ #- CD-Rom images can be hybrid, thus handle recording on both CD-Rom and disks
++ my $_device = basename(expand_symlinks($device));
++ my $sysfs_device = &quot;/sys/block/$_device/capability&quot;;
++ #- GENHD_FL_CD is 8 (include/linux/genhd.h)
++ my $is_cdrom = !-e $sysfs_device || hex(cat_($sysfs_device)) &amp; 8;
++
++ if ($is_cdrom) {
++ my $src = $opts-&gt;{onthefly} ? '-' : $path;
++ run_('wodim', '-v', 'dev=' . $device, $src);
++ } else {
++ run_('dd', if_(!$opts-&gt;{onthefly}, &quot;if=$path&quot;), &quot;of=$device&quot;, &quot;bs=2M&quot;);
++ }
++}
++
++sub record_cdrom_master {
++ my ($live, $opts) = @_;
++ record_cdrom_path($live, get_cdrom_master_path($live, $opts), $opts);
++}
++
++sub record_cdrom_replicator {
++ my ($live, $opts) = @_;
++ record_cdrom_path($live, get_cdrom_replicator_path($live), $opts);
++}
++
++sub rsync_delete_options {
++ my ($opts) = @_;
++ $opts-&gt;{keep_files} ? () : '--delete';
++}
++
++sub install_grub_to_image {
++ my ($live, $media, $img, $opts) = @_;
++ my $media_boot = $live-&gt;get_media_prefix('boot', $opts-&gt;{boot});
++ my $grub_dir = &quot;$media_boot/grub&quot;;
++ my $grub_script = $grub_dir . &quot;/install.sh&quot;;
++ my $grub_src = first(glob_($live-&gt;get_system_root . &quot;/lib/grub/*-mandriva&quot;));
++ mkdir_p($live-&gt;{mnt} . $grub_dir);
++ cp_af(glob_(&quot;$grub_src/*&quot;), $live-&gt;{mnt} . $grub_dir);
++
++ my $part_idx = $media-&gt;find_boot_partition_index;
++ my $grub_prefix = $media-&gt;find_partition_index('/boot') ? &quot;/grub&quot; : $grub_dir;
++
++ open(my $grub, &quot;| /sbin/grub --batch --no-floppy&quot;);
++ # using disk loopback fails, have to use image path
++ print $grub &lt;&lt;EOF;
++device (hd0) $img
++root (hd0,$part_idx)
++setup --prefix=$grub_prefix (hd0)
++quit
++EOF
++ close($grub) or die &quot;unable to run grub\n&quot;;
++
++ output($live-&gt;{mnt} . $grub_script, &lt;&lt;EOG);
++grub --device-map=$media_boot/grub/device.map --batch &lt;&lt;EOF
++root (hd0,$part_idx)
++setup --stage2=$media_boot/grub/stage2 (hd0)
++quit
++EOF
++EOG
++
++ chmod 0755, $live-&gt;{mnt} . $grub_script;
++}
++
++sub install_disk_bootloader {
++ my ($live, $media, $boot_device, $opts) = @_;
++
++ return if $live-&gt;{system}{skip_bootloader_install};
++
++ my $media_boot = $live-&gt;get_media_prefix('boot', $opts-&gt;{boot});
++ my $device = get_media_device($live, $opts);
++ my $bootloader = $media-&gt;get_boot_setting('bootloader', $opts);
++
++ member($bootloader, 'grub', 'syslinux') or die &quot;no bootloader defined in media configuration\n&quot;;
++ if ($bootloader eq 'syslinux') {
++ cp_f($live-&gt;get_builddir . $_, $live-&gt;{mnt}) foreach map {
++ $live-&gt;{prefix}{boot} . $_;
++ } get_syslinux_path($media, $opts), $media-&gt;get_initrd_path, @syslinux_boot_files;
++ } elsif ($bootloader eq 'grub') {
++ if (need_media_specific_boot($live) || $opts-&gt;{force_bootloader_config}) {
++ #- FIXME: add get_grub_path (when building boot configuration files)
++ # and get_bootloader_path (when copying)
++ mkdir_p($live-&gt;{mnt} . $media_boot . '/grub');
++ cp_f($live-&gt;get_builddir . $live-&gt;{prefix}{build}{boot} . '/gfxmenu', $live-&gt;{mnt} . $media_boot) if $live-&gt;{system}{gfxboot};
++ output_p($live-&gt;{mnt} . $media_boot . '/grub/menu.lst', build_grub_cfg($live, $media, $opts, $boot_device));
++ }
++ }
++
++ if (-b $boot_device) {
++ if ($bootloader eq 'syslinux') {
++ #- use syslinux -s, &quot;safe, slow and stupid&quot; version of SYSLINUX, unless specified otherwise
++ run_('syslinux', if_(!$media-&gt;{fast_syslinux}, '-s'), $boot_device)
++ or die &quot;unable to run syslinux on $device\n&quot;;
++ } elsif ($bootloader eq 'grub') {
++ install_grub_to_image($live, $media, $device, $opts);
++ }
++ } else {
++ warn &quot;not running $bootloader on non block device $device\n&quot;;
++ }
++}
++
++sub record_usb_master {
++ my ($live, $opts) = @_;
++ my $media = $live-&gt;{media};
++ my $media_boot = $live-&gt;get_media_prefix('boot', $opts-&gt;{boot});
++ my $media_loopbacks = $live-&gt;get_media_prefix('loopbacks', $opts-&gt;{boot});
++
++ my $main_device = get_media_device($live, $opts)
++ or die &quot;unable to find recording device (missing label? try with --device &lt;device&gt;)\n&quot;;
++
++ my $hd = get_hd_from_file($media, $main_device);
++ supplement_media_partitions($media, $hd);
++
++ my $slash_idx = $media-&gt;find_partition_index('/');
++ my $slash = $media-&gt;{partitions}[$slash_idx];
++ set_part_real_device($hd, $slash);
++
++ if (my $label = !$opts-&gt;{boot_only} &amp;&amp; $media-&gt;get_media_label) {
++ set_device_label($slash-&gt;{real_device}, $media-&gt;get_media_setting('fs'), $label);
++ }
++
++ mkdir_p($live-&gt;{mnt});
++ run_('mount', $slash-&gt;{real_device}, $live-&gt;{mnt})
++ or die &quot;unable to mount $slash-&gt;{real_device}\n&quot;;
++
++ rm_rf($live-&gt;{mnt} . $media_boot) if -e $live-&gt;{mnt} . $media_boot;
++ cp_af($live-&gt;get_builddir . $live-&gt;{prefix}{build}{boot}, $live-&gt;{mnt} . $media_boot);
++
++ install_disk_bootloader($live, $media, $slash-&gt;{real_device}, $opts);
++
++ do {
++ my $loopbacks_source = $live-&gt;get_builddir . $live-&gt;{prefix}{build}{loopbacks} . '/';
++ my $total = directory_usage($loopbacks_source);
++ my $list_file = tmpnam();
++ output_p($list_file, map { &quot;.$_\n&quot; } list_selected_loopbacks($live));
++ local $/ = &quot;\r&quot;;
++ my $r = run_foreach(update_progress_rsync($live, $total),
++ 'rsync', '-vdP', '--inplace', '--files-from=' . $list_file, rsync_delete_options($opts),
++ $loopbacks_source, $live-&gt;{mnt} . $media_loopbacks,
++ );
++ unlink $list_file;
++ if (!$r) {
++ run_('umount', $slash-&gt;{real_device});
++ maybe_umount_device($slash-&gt;{real_device});
++ devices::del_loop($slash-&gt;{real_device}) if -f $hd-&gt;{file};
++ die &quot;unable to copy loopback files\n&quot;;
++ }
++
++ cp_af(glob_($live-&gt;get_builddir . $live-&gt;{prefix}{build}{files} . '/*'), $live-&gt;{mnt});
++ } unless $opts-&gt;{boot_only};
++
++ my @hidden_files = map { basename($_) } glob_($live-&gt;{mnt} . &quot;/.*&quot;), glob_($live-&gt;{mnt} . &quot;/autorun.*&quot;);
++
++ run_('umount', $slash-&gt;{real_device});
++ maybe_umount_device($slash-&gt;{real_device});
++
++ if ($media-&gt;get_media_setting('fs') eq 'vfat') {
++ MDV::Draklive::Utils::mtools_run_('mattrib', '+h', '-i', $slash-&gt;{real_device}, '::' . $_) foreach @hidden_files;
++ MDV::Draklive::Utils::mtools_run_('mattrib', '+r', '+s', '-/', '-i', $slash-&gt;{real_device}, '::' . $_)
++ foreach $media_boot, $media_loopbacks;
++ }
++
++ devices::del_loop($slash-&gt;{real_device}) if -f $hd-&gt;{file};
++}
++
++sub record_harddisk_master {
++ my ($live, $opts) = @_;
++
++ my $media = $live-&gt;{media};
++ my $media_boot = $live-&gt;get_media_prefix('boot', $opts-&gt;{boot});
++ my $media_loopbacks = $live-&gt;get_media_prefix('loopbacks', $opts-&gt;{boot});
++
++ my $main_device = get_media_device($live, $opts)
++ or die &quot;unable to find recording device (missing label? try with --device &lt;device&gt;)\n&quot;;
++
++ my $hd = get_hd_from_file($media, $main_device);
++ supplement_media_partitions($media, $hd);
++ my @partitions = grep { $_-&gt;{mntpoint} =~ m!^/! } @{$media-&gt;{partitions}};
++
++ mkdir_p($live-&gt;{mnt});
++ foreach my $part (sort { $a-&gt;{mntpoint} cmp $b-&gt;{mntpoint} } @partitions) {
++ set_part_real_device($hd, $part);
++ my $mnt = $live-&gt;{mnt} . $part-&gt;{mntpoint};
++ mkdir_p($mnt);
++ run_('mount', $part-&gt;{real_device}, $mnt)
++ or die &quot;unable to mount $part-&gt;{real_device}\n&quot;;
++ }
++
++ my $r = 1;
++ do {
++ my $source = $live-&gt;get_system_root;
++ my $total = directory_usage($source);
++ local $/ = &quot;\r&quot;;
++ $r = run_foreach(update_progress_rsync($live, $total), 'rsync', rsync_delete_options($opts), '-a', $source . '/', $live-&gt;{mnt})
++ or last;
++ } unless $opts-&gt;{boot_only};
++
++ my $boot_idx = $media-&gt;find_boot_partition_index;
++ my $boot_part = $media-&gt;{partitions}[$boot_idx];
++ install_disk_bootloader($live, $media, $boot_part-&gt;{real_device}, $opts);
++
++ foreach my $part (sort { $b-&gt;{mntpoint} cmp $a-&gt;{mntpoint} } @partitions) {
++ run_('umount', $part-&gt;{real_device});
++ maybe_umount_device($part-&gt;{real_device});
++ devices::del_loop($part-&gt;{real_device}) if -f $hd-&gt;{file};
++ }
++
++ $r or die &quot;unable to copy system files\n&quot;;
++
++ record_oem_rescue($live, $opts) if $live-&gt;{oem_rescue};
++}
++
++#- $opts:
++#- onthefly : if true, the record function must read from stdin
++sub record_master {
++ my ($live, $opts) = @_;
++
++ if (my $record = $live-&gt;{media}-&gt;get_boot_setting('record', $opts)) {
++ $record-&gt;($live, $opts);
++ } else {
++ warn &quot;not implemented yet\n&quot;;
++ }
++}
++
++#- $opts:
++#- onthefly : if true, the record function must read from stdin
++sub record_replicator {
++ my ($live, $opts) = @_;
++
++ my $replicator_media = $live-&gt;{replicator}{media} or die &quot;no replicator media&quot;;
++ if (my $record_replicator = $replicator_media-&gt;get_boot_setting('record_replicator', $opts)) {
++ $record_replicator-&gt;($live, $opts);
++ } else {
++ warn &quot;not implemented yet\n&quot;;
++ }
++}
++
++sub pipe_subs {
++ my ($writer, $reader) = @_;
++ my ($r, $w) = POSIX::pipe;
++ if (my $pid = fork()) {
++ POSIX::close($w) or die &quot;couldn't close: $!\n&quot;;
++ my $stdin = POSIX::dup(0) or die &quot;couldn't dup: $!\n&quot;;
++ POSIX::dup2($r, 0) or die &quot;couldn't dup2: $!\n&quot;;
++ POSIX::close($r);
++ $reader-&gt;();
++ POSIX::close(0) or warn &quot;writer exited $?\n&quot;;
++ POSIX::dup2($stdin, 0) or die &quot;couldn't dup2: $!\n&quot;;
++ waitpid($pid, 0);
++ } else {
++ POSIX::close($r) or die &quot;couldn't close: $!\n&quot;;
++ #- don't screw up reader
++ POSIX::dup2(POSIX::open('/dev/null', &amp;POSIX::O_WRONLY), 2) or die &quot;couldn't dup2: $!\n&quot;;
++ POSIX::dup2($w, 1) or die &quot;couldn't dup2: $!\n&quot;;
++ POSIX::close($w);
++ $| = 1; #- autoflush write
++ exit !$writer-&gt;();
++ }
++}
++
++sub record_onthefly {
++ my ($live, $opts) = @_;
++
++ my $record = $live-&gt;{media}-&gt;get_storage_setting('record');
++ unless ($record) {
++ warn &quot;not implemented yet\n&quot;;
++ return;
++ }
++ if (my $create = $live-&gt;{media}-&gt;get_storage_setting('record_needs_master') &amp;&amp; $live-&gt;{media}-&gt;get_storage_setting('create')) {
++ local $opts-&gt;{onthefly} = 1;
++ #- pipe creation step to recording step
++ pipe_subs(sub { $create-&gt;($live, $opts) },
++ sub { $record-&gt;($live, $opts) });
++ } else {
++ #- no creation step, record directly
++ $record-&gt;($live, $opts);
++ }
++}
++
++sub need_compressed_image {
++ my ($live) = @_;
++ #- compress image if not having loopbacks already
++ !to_bool(list_selected_loopbacks($live));
++}
++
++sub get_disk_image_path {
++ my ($live) = @_;
++ if ($live-&gt;{settings}{compression_method} eq 'gzip') {
++ get_disk_master_path($live) . if_(need_compressed_image($live), '.gz');
++ }
++ else {
++ get_disk_master_path($live) . if_(need_compressed_image($live), '.bz2');
++ }
++}
++
++sub create_disk_image {
++ my ($live) = @_;
++ if (!need_compressed_image($live)) {
++ warn &quot;already using loopback: skipping image creation\n&quot;;
++ return;
++ }
++ my $master = get_disk_master_path($live);
++ my $dest = get_disk_image_path($live);
++ mkdir_p(dirname($dest));
++
++ if ($live-&gt;{settings}{compression_method} eq 'gzip') {
++ run_('gzip', '&gt;', $dest, '-f', '-c', '--fast', $master);
++ }
++ else {
++ run_('bzip2', '&gt;', $dest, '-f', '-k', '-c', $master);
++ }
++}
++
++sub create_image {
++ my ($live) = @_;
++
++ if (my $create = $live-&gt;{media}-&gt;get_media_setting('image')) {
++ $create-&gt;($live);
++ } else {
++ warn &quot;not implemented yet\n&quot;;
++ }
++}
++
++sub create_vm_image {
++ my ($live) = @_;
++
++ my $vm_type = $live-&gt;{settings}{vm_type};
++ if (!$vm_type) {
++ warn &quot;no vm_type has been set in settings, skipping&quot;;
++ return;
++ }
++
++ if (!$live-&gt;{media}-&gt;get_media_setting('image')) {
++ warn &quot;not implemented yet\n&quot;;
++ return;
++ }
++
++ my $master = get_disk_master_path($live);
++ if (!-f $master) {
++ warn &quot;no master image, skipping\n&quot;;
++ }
++
++ my $vm_image = get_disk_master_prefix($live) . &quot;.$vm_type&quot;;
++ run_(&quot;qemu-img&quot;, &quot;convert&quot;, &quot;-O&quot;, $vm_type, $master, $vm_image);
++}
++
++sub get_rescue_files {
++ my ($live, $rescue_opts, $extra_files) = @_;
++ my $media_boot = $live-&gt;get_media_prefix('boot');
++ my $initrd = $media_boot . $rescue_opts-&gt;{media}-&gt;get_initrd_path;
++ my @stage2_files = $live-&gt;{settings}{replicator_type} eq 'drakx' ? (
++ '/usr/lib/drakx-installer-stage2/install/stage2/mdkinst.sqfs',
++ $live-&gt;get_system_root . '/bin/dd',
++ ) : '/usr/lib/drakx-installer-rescue/rescue.sqfs';
++ (
++ '/usr/lib/drakx-installer-images/isolinux/alt0/vmlinuz' =&gt; $media_boot . '/vmlinuz',
++ '/usr/lib/drakx-installer-images/isolinux/alt0/all.rdz' =&gt; $initrd,
++ (map { $_ =&gt; '/install/stage2/' } @stage2_files),
++ @{$extra_files || []},
++ #- FIXME: factorize with copy_files_to to handle glob
++ (map { $live-&gt;{settings}{config_root} . '/' . $_-&gt;[0] =&gt; '/' . $_-&gt;[1] } @{$rescue_opts-&gt;{files} || []}),
++ );
++}
++
++sub record_rescue_files {
++ my ($mnt, $device, $rescue_files) = @_;
++ my $failed;
++ foreach (group_by2(@$rescue_files)) {
++ my ($src, $dest) = @$_;
++ $dest = $mnt . $dest;
++ mkdir_p($dest =~ m!/$! ? $dest : dirname($dest));
++ if (!run_('rsync', '-vdP', '--inplace', $src, $dest)) {
++ $failed = 1;
++ last;
++ }
++ }
++
++ #- FIXME
++ chmod 0755, $mnt . '/' . 'oem-rescue.sh';
++
++ if ($failed) {
++ run_('umount', $mnt);
++ maybe_umount_device($device);
++ die &quot;unable to copy rescue files\n&quot;;
++ }
++}
++
++sub record_oem_rescue {
++ my ($live, $opts) = @_;
++
++ my $media = $live-&gt;{media};
++ my $oem_rescue_idx = $media-&gt;find_partition_index('OEM_RESCUE');
++ defined $oem_rescue_idx or die &quot;no OEM_RESCUE partition&quot;;
++
++ my $main_device = get_media_device($live, $opts)
++ or die &quot;unable to find recording device (missing label? try with --device &lt;device&gt;)\n&quot;;
++
++ my $hd = get_hd_from_file($media, $main_device);
++ supplement_media_partitions($media, $hd);
++
++ my $oem_rescue = $media-&gt;{partitions}[$oem_rescue_idx];
++ set_part_real_device($hd, $oem_rescue);
++
++ mkdir_p($live-&gt;{mnt});
++ run_('mount', $oem_rescue-&gt;{real_device}, $live-&gt;{mnt})
++ or die &quot;unable to mount $oem_rescue-&gt;{real_device}\n&quot;;
++
++ record_rescue_files($live-&gt;{mnt}, $oem_rescue-&gt;{real_device}, [ get_rescue_files($live, $live-&gt;{oem_rescue}) ]);
++
++ run_('umount', $oem_rescue-&gt;{real_device});
++ maybe_umount_device($oem_rescue-&gt;{real_device});
++ devices::del_loop($oem_rescue-&gt;{real_device}) if -f $hd-&gt;{file};
++}
++
++sub get_disk_replicator_prefix {
++ my ($live) = @_;
++ $live-&gt;get_builddir . $live-&gt;{prefix}{build}{dist} . '/' . $live-&gt;get_name . '.rest';
++}
++
++sub get_disk_replicator_path {
++ my ($live) = @_;
++ get_disk_replicator_prefix($live) . &quot;.img&quot;;
++}
++
++sub get_disk_replicator_files {
++ my ($live) = @_;
++ get_rescue_files($live, $live-&gt;{replicator}, [ get_disk_image_path($live) =&gt; '/images/' ]);
++}
++
++sub get_disk_replicator_images_list {
++ my ($live) = @_;
++ my $master_path = get_disk_master_path($live);
++ my $master_size = (stat($master_path))[7];
++ &quot;EN,English,&quot; . basename(get_disk_image_path($live)) . &quot;,on,$master_size\n&quot;;
++}
++
++sub create_usb_replicator {
++ my ($live, $opts) = @_;
++ my %files = get_disk_replicator_files($live);
++ local $opts-&gt;{slash_size} = fold_left { $::a + $::b } map { directory_usage($_, 'apparent') } keys(%files);
++ local $opts-&gt;{device} = get_disk_replicator_path($live);
++ allocate_master($live, $live-&gt;{replicator}{media}, $opts);
++ format_master($live, $live-&gt;{replicator}{media}, $opts);
++ record_usb_replicator($live, $opts);
++}
++
++sub record_usb_replicator {
++ my ($live, $opts) = @_;
++
++ my $media = $live-&gt;{replicator}{media};
++ my $media_boot = $live-&gt;get_media_prefix('boot');
++
++ $opts-&gt;{append} ||= $live-&gt;{replicator}{append};
++ my $main_device = get_media_device($live, $opts)
++ or die &quot;unable to find recording device (missing label? try with --device &lt;device&gt;)\n&quot;;
++
++ my $hd = get_hd_from_file($media, $main_device);
++ supplement_media_partitions($media, $hd);
++
++ my $slash_idx = $media-&gt;find_partition_index('/');
++ my $slash = $media-&gt;{partitions}[$slash_idx];
++ set_part_real_device($hd, $slash);
++
++ mkdir_p($live-&gt;{mnt});
++ run_('mount', $slash-&gt;{real_device}, $live-&gt;{mnt})
++ or die &quot;unable to mount $slash-&gt;{real_device}\n&quot;;
++ rm_rf($live-&gt;{mnt} . $media_boot) if -e $live-&gt;{mnt} . $media_boot;
++ {
++ local $opts-&gt;{force_bootloader_config} = 1;
++ install_disk_bootloader($live, $media, $slash-&gt;{real_device}, $opts);
++ }
++
++ record_rescue_files($live-&gt;{mnt}, $slash-&gt;{real_device}, [ get_disk_replicator_files($live) ]);
++ output_p($live-&gt;{mnt} . &quot;/images/list&quot;, get_disk_replicator_images_list($live));
++
++ run_('umount', $slash-&gt;{real_device});
++ maybe_umount_device($slash-&gt;{real_device});
++ devices::del_loop($slash-&gt;{real_device}) if -f $hd-&gt;{file};
++}
++
++sub create_cdrom_replicator {
++ my ($live, $opts) = @_;
++
++ # FIXME: factorize with usb replicator, write in builddir/replicator/images-list
++ my $images_list = &quot;/tmp/images-replicator.list&quot;;
++ output_p($images_list, get_disk_replicator_images_list($live));
++
++ # FIXME: write in builddir/replicator/syslinux.cfg
++ my $syslinux_cfg = &quot;/tmp/syslinux-replicator.cfg&quot;;
++ local $opts-&gt;{append} = $live-&gt;{replicator}{append};
++ output_p($syslinux_cfg, build_syslinux_cfg($live, $live-&gt;{replicator}{media}, $opts));
++
++ my $label = $live-&gt;{replicator}{media}-&gt;get_media_label or die &quot;the source device must be described by a label\n&quot;;
++ my $dest = get_cdrom_replicator_path($live);
++ build_iso_image(
++ $live, $opts,
++ $dest,
++ $syslinux_cfg,
++ $label,
++ $live-&gt;get_media_prefix('boot', $opts-&gt;{boot}) . '/syslinux=' . $live-&gt;get_builddir . $live-&gt;{prefix}{build}{boot} . '/syslinux',
++ &quot;/images/list=$images_list&quot;,
++ (map {
++ my ($src, $dest) = @$_;
++ my $dest_file = $dest =~ m!/$! ? $dest . basename($src) : $dest;
++ $dest_file . &quot;=&quot; . $src;
++ } group_by2(get_disk_replicator_files($live))),
++ );
++}
++
++sub create_replicator {
++ my ($live, $opts) = @_;
++
++ if (my $create = $live-&gt;{replicator}{media} &amp;&amp; $live-&gt;{replicator}{media}-&gt;get_media_setting('replicator')) {
++ $create-&gt;($live, $opts);
++ } else {
++ warn &quot;not implemented yet\n&quot;;
++ }
++}
++
++sub update_progress_rsync {
++ my ($live, $total) = @_;
++ my $all_files = 0;
++ my $current_file = 0;
++ $live-&gt;{update_progress} ? sub {
++ if (/^\s*(\d+)\s+\d+%\s+/) {
++ $current_file = $1;
++ $live-&gt;{update_progress}-&gt;(undef, $all_files + $current_file, $total);
++ }
++ if (/(?:^|\n)\S+/) {
++ $all_files += $current_file;
++ $current_file = 0;
++ }
++ } : sub { print };
++}
++
++sub copy_wizard {
++ my ($live) = @_;
++
++ MDV::Draklive::Config::complete_config($live);
++ $live-&gt;{system}{vga_mode} = 788 if !defined $live-&gt;{system}{vga_mode};
++ my $live_media = $live-&gt;{prefix}{live}{mnt} . $live-&gt;{prefix}{media}{mnt};
++
++ require interactive;
++ require wizards;
++ my $in = 'interactive'-&gt;vnew('su');
++ my (@available_storage, @available_devices);
++ my ($storage, $device, $format);
++ my %source_types = (
++ live =&gt; N(&quot;Use current live system&quot;),
++ file =&gt; N(&quot;Select a file&quot;),
++ );
++ my ($source_type, $source_path);
++ my $media_boot = $live-&gt;get_media_prefix('boot');
++ my $media_loopbacks = $live-&gt;get_media_prefix('loopbacks');
++ my $source_is_mounted = sub { -d ($live-&gt;{settings}{builddir} . $media_boot) };
++ my $umount_source = sub {
++ if ($source_type ne 'live' &amp;&amp; $source_is_mounted-&gt;()) {
++ run_('umount', $live-&gt;{settings}{builddir});
++ rmdir($live-&gt;{settings}{builddir});
++ }
++ };
++ my $w;
++ $w = wizards-&gt;new({
++ name =&gt; N(&quot;Live system copy wizard&quot;),
++ pages =&gt; {
++ welcome =&gt; {
++ name =&gt; N(&quot;Welcome to the live system copy wizard&quot;),
++ no_back =&gt; 1,
++ next =&gt; 'source',
++ },
++ source =&gt; {
++ name =&gt; N(&quot;Which live system do you want to copy?&quot;),
++ data =&gt; [ if_(-d ($live_media . $media_loopbacks),
++ { type =&gt; 'list', val =&gt; \$source_type,
++ list =&gt; sort(keys(%source_types)),
++ format =&gt; sub { $source_types{$_[0]} } }),
++ { type =&gt; 'file', val =&gt; \$source_path,
++ disabled =&gt; sub { $source_type eq 'live' } } ],
++ pre =&gt; $umount_source,
++ complete =&gt; sub {
++ if ($source_type eq 'live') {
++ $live-&gt;{settings}{builddir} = $live_media;
++ } else {
++ $live-&gt;{settings}{builddir} = File::Temp::tempdir();
++ if (!run_('mount', '-o', 'loop', $source_path, $live-&gt;{settings}{builddir})) {
++ $in-&gt;ask_warn(N(&quot;Error&quot;), N(&quot;Unable to use selected file&quot;));
++ return 1;
++ }
++ }
++ 0;
++ },
++ post =&gt; sub {
++ my $boot = $live-&gt;{settings}{builddir} . $media_boot;
++ @available_storage = sort(grep { -d &quot;$boot/$_&quot; &amp;&amp; exists $MDV::Draklive::Storage::storage_types{$_}{detect} } all($boot));
++ if (@available_storage == 1) {
++ $storage = $available_storage[0];
++ return 'device';
++ }
++ return 'storage';
++ }
++ },
++ storage =&gt; {
++ name =&gt; N(&quot;Please select the medium type&quot;),
++ data =&gt; [ { type =&gt; 'list', allow_empty_list =&gt; 1,
++ val =&gt; \$storage, list =&gt; \@available_storage } ],
++ next =&gt; 'device',
++ },
++ device =&gt; {
++ name =&gt; N(&quot;Please select the device that will contain the new live system&quot;),
++ pre =&gt; sub {
++ my %devices = map { $_-&gt;{device} =&gt; $_ } $MDV::Draklive::Storage::storage_types{$storage}{detect}-&gt;();
++ $_-&gt;{formatted_name} = $_-&gt;{usb_description} || $_-&gt;{info} || $_-&gt;{device} foreach values %devices;
++ @available_devices = ();
++ require fs::proc_partitions;
++ foreach (fs::proc_partitions::read([ values %devices ])) {
++ if ($_-&gt;{rootDevice} &amp;&amp; exists $devices{$_-&gt;{rootDevice}}) {
++ my $description = $devices{$_-&gt;{rootDevice}}{usb_description} || $devices{$_-&gt;{rootDevice}}{info};
++ $_-&gt;{formatted_name} = $description ? &quot;$description ($_-&gt;{device})&quot; : $_-&gt;{device};
++ push @available_devices, $_;
++ }
++ }
++ delete $devices{$_-&gt;{rootDevice}} foreach @available_devices;
++ unshift @available_devices, map { $devices{$_} } sort keys %devices;
++ undef $device;
++ },
++ data =&gt; [ { type =&gt; 'list', allow_empty_list =&gt; 1,
++ val =&gt; \$device, , list =&gt; \@available_devices,
++ format =&gt; sub { $_[0]{formatted_name} } },
++ { text =&gt; N(&quot;Format selected device&quot;), val =&gt; \$format, type =&gt; 'bool' } ],
++ complete =&gt; sub {
++ return 0 if defined $device;
++ $in-&gt;ask_warn(N(&quot;Error&quot;), N(&quot;You must select a device!&quot;));
++ 1;
++ },
++ post =&gt; sub {
++ (my $_wait, $live-&gt;{update_progress}) = $in-&gt;wait_message_with_progress_bar;
++ do {
++ local $::isInstall = 1; # quick hack to embed the wait message
++ $live-&gt;{update_progress}-&gt;(N(&quot;Copying in progress&quot;));
++ };
++ eval {
++ my $opts = { media =&gt; { storage =&gt; $storage, device =&gt; '/dev/' . $device-&gt;{device} } };
++ format_device($live, $opts) if $format;
++ record_onthefly($live, $opts);
++ };
++ delete $live-&gt;{update_progress};
++ if (my $error = $@) {
++ $in-&gt;ask_warn(N(&quot;Error&quot;), $error);
++ $w-&gt;{pages}{device}{end} = 1;
++ }
++ return &quot;end&quot;;
++ },
++ },
++ end =&gt; {
++ name =&gt; N(&quot;Congratulations&quot;) . &quot;\n\n&quot; . N(&quot;Your live system is now copied.&quot;),
++ no_back =&gt; 1,
++ end =&gt; 1,
++ },
++ }
++ });
++ $w-&gt;process($in);
++ $umount_source-&gt;();
++ $in-&gt;exit;
++}
++
++sub clean {
++ my ($live) = @_;
++ # umount filesystem in the live before cleaning
++ umount_external_filesystem($live);
++ rm_rf($_) foreach grep { -e $_ } $live-&gt;get_builddir, $live-&gt;get_system_root;
++}
++
++my @actions = (
++ { name =&gt; 'dump-config', do =&gt; \&amp;MDV::Draklive::Config::dump_config },
++ { name =&gt; 'clean', do =&gt; \&amp;clean },
++ { name =&gt; 'install', do =&gt; \&amp;install_system },
++ { name =&gt; 'post-install', do =&gt; \&amp;post_install_system },
++ { name =&gt; 'initrd', do =&gt; \&amp;create_initrd },
++ { name =&gt; 'boot', do =&gt; \&amp;prepare_bootloader },
++ { name =&gt; 'tarball', do =&gt; \&amp;create_tarball },
++ { name =&gt; 'loop', do =&gt; \&amp;create_loopback_files },
++ { name =&gt; 'master', do =&gt; \&amp;create_master },
++ { name =&gt; 'image', do =&gt; \&amp;create_image },
++ { name =&gt; 'vm-image', do =&gt; \&amp;create_vm_image },
++ { name =&gt; 'replicator', do =&gt; \&amp;create_replicator },
++ { name =&gt; 'format', do =&gt; \&amp;format_device },
++ { name =&gt; 'record', do =&gt; \&amp;record_master },
++ { name =&gt; 'record-onthefly', do =&gt; \&amp;record_onthefly },
++ { name =&gt; 'record-replicator', do =&gt; \&amp;record_replicator },
++);
++my @all = qw(install boot loop master image vm-image replicator);
++
++die &quot;you must be root to run this program\n&quot; if $&gt;;
++
++my $live_object = 'MDV::Draklive::Live'-&gt;new;
++my %opts;
++my $config_root = $MDV::Draklive::Config::default_config_root;
++my $config_path = $MDV::Draklive::Config::default_config_path;
++my $settings_path = $MDV::Draklive::Config::default_settings_path;
++GetOptions(
++ &quot;help&quot; =&gt; sub { Pod::Usage::pod2usage('-verbose' =&gt; 1) },
++ &quot;copy-wizard&quot; =&gt; \$live_object-&gt;{copy_wizard},
++ &quot;keep-files&quot; =&gt; \$opts{keep_files},
++ &quot;boot-only&quot; =&gt; \$opts{boot_only},
++ &quot;boot-image=s&quot; =&gt; sub { $opts{boot} = $_[1]; $opts{boot_only} = 1 },
++ &quot;all&quot; =&gt; sub { $_-&gt;{to_run} = 1 foreach grep { member($_-&gt;{name}, @all) } @actions },
++ (map { $_-&gt;{name} =&gt; \$_-&gt;{to_run} } @actions),
++ &quot;device=s&quot; =&gt; sub { $opts{device} = $_[1] },
++ &quot;all-regions&quot; =&gt; sub { $live_object-&gt;{all_regions} = 1 },
++ &quot;config-root=s&quot; =&gt; \$config_root,
++ &quot;config=s&quot; =&gt; \$config_path,
++ &quot;settings=s&quot; =&gt; \$settings_path,
++ &quot;define=s&quot; =&gt; \%{$live_object-&gt;{settings}},
++) or Pod::Usage::pod2usage();
++
++require standalone;
++if ($live_object-&gt;{copy_wizard}) {
++ copy_wizard($live_object);
++} else {
++ every { !$_-&gt;{to_run} } @actions and Pod::Usage::pod2usage();
++ MDV::Draklive::Config::read_config($live_object, $config_root, $config_path, $settings_path);
++ MDV::Draklive::Config::check_config($live_object);
++ MDV::Draklive::Config::complete_config($live_object);
++ foreach my $region ($live_object-&gt;{all_regions} ? sort(keys %{$live_object-&gt;{regions}}) : $live_object-&gt;{settings}{region}) {
++ $region and print qq(=== proceeding with region &quot;$region&quot;\n);
++ $live_object-&gt;{settings}{region} = $region;
++ foreach (grep { $_-&gt;{to_run} } @actions) {
++ print qq(* entering step &quot;$_-&gt;{name}&quot;\n);
++ $_-&gt;{do}-&gt;($live_object, \%opts);
++ print qq(* step &quot;$_-&gt;{name}&quot; done\n);
++ }
++ }
++}
++
++__END__
++
++=head1 NAME
++
++draklive - A live distribution mastering tool
++
++=head1 SYNOPSIS
++
++draklive [options]
++
++ Options:
++ --help long help message
++
++ --install install selected distribution in chroot
++ --boot prepare initrd and bootloader files
++ --tarball build chroot tarball
++ --loop build compressed loopback files
++ --master build master image
++ --image build compressed master image
++ --replicator build replicator image (to dump master on systems)
++
++ --all run all steps, from installation to mastering
++
++ --clean clean installation chroot and work directory
++
++ --device &lt;dev&gt; use this device for live recording (not needed
++ if the device already has the required label)
++ --format format selected device
++ --record record live on selected media
++ --record-onthefly record live by creating master from loopback files
++ on the fly
++ --keep-files keep existing files on media when recording
++ --record-replicator
++ record replicator on selected media
++
++ --initrd build initrd only
++ --post-install run post install only (rpms and patches installation)
++
++ --config-root &lt;dir&gt;
++ root directory containing config files and additionnal files
++ defaults to current directory if it contains a configuration file
++ else, &quot;/etc/draklive&quot; is used
++
++ --config &lt;file&gt; use this configuration file as live description
++ defaults to &quot;config/live.cfg&quot;
++
++ --settings &lt;file&gt; use this file as live settings (key=value format)
++ defaults to &quot;config/settings.cfg&quot;
++ --define key=value
++ set setting &quot;key&quot; to &quot;value&quot;
++ takes precedence over values from a settings file
++
++ --all-regions proceed with all configured regions
++
++ --copy-wizard run the copy wizard
++
++ --boot-only copy only boot files
++ (affects master/record steps)
++
++ --boot-image &lt;method&gt;
++ create a boot image for the selected method
++ (affects master/record steps, implies --boot-only)
++
++Examples:
++
++ draklive --clean
++
++ draklive --all
++
++ draklive --record --device /dev/sdb1
++
++ draklive --config config/live.cfg --install
++
++=head1 OPTIONS
++
++=over 8
++
++=item B&lt;--config&gt;
++
++Makes draklive use the next argument as a configuration file.
++This file should contain an hash describing the live distribution,
++meaning the system (chroot and boot), media (usb, cdrom, nfs),
++and mount type (simple R/W union, union with squash files).
++
++Here's a configuration sample:
++
++ {
++ settings {
++ repository =&gt; '/mnt/ken/2006.0',
++ root =&gt; '/chroot/live-move',
++ },
++ system =&gt; {
++ kernel =&gt; '2.6.12-12mdk-i586-up-1GB',
++ auto_install =&gt; 'config/auto_inst.cfg.pl',
++ patch_install =&gt; 'config/patch-2006-live.pl',
++ rpmsrate =&gt; 'config/rpmsrate',
++ rpms =&gt; [
++ 'rpms/unionfs-kernel-2.6.12-12mdk-i586-up-1GB-1.1.1.1.20051124.1mdk-1mdk.i586.rpm'
++ ],
++ patches =&gt; [
++ 'patches/halt.loopfs.patch',
++ ],
++ vga_mode =&gt; 788,
++ no_initrd =&gt; 0,
++ },
++ media =&gt; {
++ storage =&gt; 'cdrom',
++ },
++ mount =&gt; $predefined{mounts}{squash_union}
++ };
++
++=item B&lt;--settings&gt;
++
++Makes draklive load the next argument as a file in key=value format
++into the $live-&gt;{settings} hash ($live being the global live configuration hash).
++
++Built-in keys:
++ arch: build architecture
++ builddir: directory hosting build files (initrd, loopbacks, images)
++ chroot: directory hosting chrooted installations
++ region: use the matching set of langs from the regions configuration hash
++ repository: path to the Mandriva distribution repository (ftp/http/local)
++
++Example keys:
++ desktop
++ media
++ product
++
++=back
++
++=head1 DESCRIPTION
++
++B&lt;draklive&gt; builds a live distribution according to a
++configuration file, creates a master image,
++and optionally installs it on a device.
++
++See L&lt;http://qa.mandriva.com/twiki/bin/view/Main/DrakLive&gt;
++
++=head1 AUTHOR
++
++Olivier Blin &lt;oblin@mandriva.com&gt;
++
++=cut
+
+
+Property changes on: draklive/trunk/draklive
+___________________________________________________________________
+<a id="svnexecutable">Added: svn:executable</a>
+ + *
+
+<a id="draklivetrunkdraklivecopywizarddesktop">Added: draklive/trunk/draklive-copy-wizard.desktop</a>
+===================================================================
+--- draklive/trunk/draklive-copy-wizard.desktop (rev 0)
++++ draklive/trunk/draklive-copy-wizard.desktop 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,7 @@
++[Desktop Entry]
++Encoding=UTF-8
++Exec=/usr/sbin/draklive --copy-wizard
++Icon=MandrivaOne-copy-icon
++Terminal=false
++Type=Application
++Name=Live copy
+
+<a id="draklivetrunkkmodreadlogc">Added: draklive/trunk/kmod/readlog.c</a>
+===================================================================
+--- draklive/trunk/kmod/readlog.c (rev 0)
++++ draklive/trunk/kmod/readlog.c 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,230 @@
++#include &lt;linux/init.h&gt;
++#include &lt;linux/module.h&gt;
++
++#include &lt;linux/kernel.h&gt;
++#include &lt;linux/file.h&gt;
++#include &lt;linux/fs.h&gt;
++#include &lt;linux/sched.h&gt;
++#include &lt;linux/syscalls.h&gt;
++#include &lt;linux/time.h&gt;
++
++#include &lt;asm/unistd.h&gt;
++
++#include &lt;asm/current.h&gt;
++#include &lt;linux/debugfs.h&gt;
++#include &lt;linux/seq_file.h&gt;
++
++MODULE_LICENSE(&quot;GPL&quot;);
++MODULE_AUTHOR(&quot;Olivier Blin &lt;blino@mandriva.com&gt;&quot;);
++
++struct opened_file {
++ struct list_head s_list;
++ char *name;
++};
++
++unsigned long **sys_call_table;
++static struct dentry *dbg_dir;
++static struct dentry *dbg_file;
++struct opened_file bp;
++DECLARE_MUTEX(files_mutex);
++
++ssize_t (*read)(int f, const void *buf, size_t n);
++long (*open)(const char __user *filename, int flags, int mode);
++
++static void *profile_seq_start(struct seq_file *file, loff_t *pos)
++{
++ struct list_head *p;
++ loff_t l = *pos;
++ down(&amp;files_mutex);
++ list_for_each(p, &amp;bp.s_list)
++ if (!l--)
++ return list_entry(p, struct opened_file, s_list);
++ return NULL;
++}
++
++static void *profile_seq_next(struct seq_file *file, void *v, loff_t *pos)
++{
++ struct list_head *p = ((struct opened_file *)v)-&gt;s_list.next;
++ (*pos)++;
++ return p == &amp;bp.s_list ? NULL : list_entry(p, struct opened_file, s_list);
++}
++
++static void profile_seq_stop(struct seq_file *file, void *v)
++{
++ up(&amp;files_mutex);
++}
++
++static int profile_seq_show(struct seq_file *file, void *v)
++{
++ seq_printf(file, ((struct opened_file *)v)-&gt;name);
++ seq_putc(file, '\n');
++ return 0;
++}
++
++static struct seq_operations profile_seq_ops = {
++ .start = profile_seq_start,
++ .next = profile_seq_next,
++ .stop = profile_seq_stop,
++ .show = profile_seq_show,
++};
++
++static int profile_open(struct inode *inode, struct file *file)
++{
++ return seq_open(file, &amp;profile_seq_ops);
++}
++
++static struct file_operations profile_fops = {
++ .owner = THIS_MODULE,
++ .open = profile_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = seq_release
++};
++
++/* Borrowed from
++ * http://downloads.securityfocus.com/downloads/scprint.tar.gz
++ * http://www.gnome.org/~lcolitti/gnome-startup/linux-iolog/readlog.c
++ * http://kerneltrap.org/node/5793
++ */
++unsigned long **find_sys_call_table(void) {
++ unsigned long *p;
++
++ for (p = (unsigned long *)((init_mm.end_code + 4) &amp; 0xfffffffc);
++ p &lt; (unsigned long *)init_mm.end_data; p++) {
++ if (p[__NR_close] == (unsigned long) sys_close){
++ return (unsigned long **) p;
++ }
++ }
++
++ return NULL;
++}
++
++void addfilename(const char *filename) {
++ struct opened_file *f;
++
++ f = kmalloc(sizeof(struct opened_file), GFP_KERNEL);
++ if (f == NULL)
++ return;
++
++ f-&gt;name = kmalloc(strlen(filename) + 1, GFP_KERNEL);
++ if (f-&gt;name == NULL)
++ return;
++ strcpy(f-&gt;name, filename);
++
++ INIT_LIST_HEAD(&amp;f-&gt;s_list);
++
++ printk(KERN_INFO &quot;locking while adding: %s\n&quot;, filename);
++
++ down(&amp;files_mutex);
++ list_add_tail(&amp;f-&gt;s_list, &amp;bp.s_list);
++ up(&amp;files_mutex);
++
++ printk(KERN_INFO &quot;unlocking after adding: %s\n&quot;, filename);
++}
++
++long loggingopen(const char __user *filename, int flags, int mode) {
++ struct file *f = NULL;
++ long fd;
++
++ fd = open(filename, flags, mode);
++
++ printk(KERN_INFO &quot;opening fd %ld for %s\n&quot;, fd, filename);
++
++ if(fd &gt; 0 &amp;&amp; current) {
++ f = current-&gt;files-&gt;fd_array[fd];
++ if(f &amp;&amp; f-&gt;f_dentry &amp;&amp; f-&gt;f_vfsmnt) {
++ char tmpname[PATH_MAX];
++ char *name = d_path(f-&gt;f_dentry, f-&gt;f_vfsmnt, tmpname, sizeof(tmpname) - 1);
++ if (name)
++ addfilename(name);
++ }
++ }
++
++ return fd;
++}
++
++
++ssize_t loggingread(int fd, const void *buf, size_t n) {
++ struct file *f = NULL;
++ char *name = NULL;
++ loff_t offset = 0;
++ struct timeval tv;
++ char tmpname[256];
++
++ do_gettimeofday(&amp;tv);
++
++ if(current)
++ f = current-&gt;files-&gt;fd_array[fd];
++
++ printk(KERN_DEBUG &quot;READ: f: %p\n&quot;, f);
++
++
++ if(f)
++ offset = f-&gt;f_pos;
++
++ if (f)
++ printk(KERN_DEBUG &quot;READ: d_entry: %p, vfsmnt: %p\n&quot;, f-&gt;f_dentry, f-&gt;f_vfsmnt);
++
++ if(f &amp;&amp; f-&gt;f_dentry &amp;&amp; f-&gt;f_vfsmnt) {
++ printk(KERN_DEBUG &quot;READ: d_path\n&quot;);
++ name = d_path(f-&gt;f_dentry, f-&gt;f_vfsmnt, tmpname, sizeof(tmpname) - 1);
++ if (name)
++ addfilename(name);
++ }
++
++ printk(KERN_DEBUG &quot;READ: %lu.%lu (%s/%d) %Lu %s\n&quot;,
++ tv.tv_sec, tv.tv_usec,
++ current ? current-&gt;comm : &quot;?&quot;,
++ current ? current-&gt;pid : 0,
++ offset,
++ name ? name : &quot;&lt;no dentry&gt;&quot;
++ );
++
++ return read(fd, buf, n);
++}
++
++static int __init readlog_init(void) {
++ sys_call_table = find_sys_call_table();
++ /* compare with grep sys_call_table /boot/System.map */
++ printk(KERN_INFO &quot;Found sys_call_table at %p\n&quot;, sys_call_table);
++
++ open = (void *) (sys_call_table[__NR_open]);
++ sys_call_table[__NR_open] = (void *) loggingopen;
++
++ read = (void *) (sys_call_table[__NR_read]);
++ /* sys_call_table[__NR_read] = (void *) loggingread; */
++
++ dbg_dir = debugfs_create_dir(&quot;dmc&quot;, NULL);
++ if (IS_ERR(dbg_dir)) {
++ printk(KERN_NOTICE &quot;: debugfs is not available\n&quot;);
++ return -ENODEV;
++ }
++ if (dbg_dir == NULL) {
++ printk(KERN_NOTICE &quot;: unable to create usbmon directory\n&quot;);
++ return -ENODEV;
++ }
++
++ dbg_file = debugfs_create_file(&quot;bp&quot;, 0600, dbg_dir, NULL, &amp;profile_fops);
++ if (dbg_file == NULL) {
++ debugfs_remove(dbg_dir);
++ return -ENODEV;
++ }
++
++ INIT_LIST_HEAD(&amp;bp.s_list);
++
++ return 0;
++}
++
++static void __exit readlog_exit(void) {
++ debugfs_remove(dbg_file);
++ debugfs_remove(dbg_dir);
++
++ sys_call_table[__NR_open] = (void *) open;
++ sys_call_table[__NR_read] = (void *) read;
++
++ printk(KERN_INFO &quot;sys_call_table restored\n&quot;);
++
++}
++
++module_init(readlog_init);
++module_exit(readlog_exit);
+
+
+Property changes on: draklive/trunk/kmod/readlog.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+
+<a id="draklivetrunklibMDVDrakliveConfigpm">Added: draklive/trunk/lib/MDV/Draklive/Config.pm</a>
+===================================================================
+--- draklive/trunk/lib/MDV/Draklive/Config.pm (rev 0)
++++ draklive/trunk/lib/MDV/Draklive/Config.pm 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,97 @@
++package MDV::Draklive::Config;
++
++use MDK::Common;
++use Pod::Usage;
++use Cwd 'getcwd';
++
++#- we bless Media objects here
++use MDV::Draklive::Media;
++#- these modules can be used from config files
++use MDV::Draklive::Mounts;
++use MDV::Draklive::CustomMedia;
++
++our $default_config_root = '/etc/draklive';
++our $default_config_path = 'config/live.cfg';
++our $default_settings_path = 'config/settings.cfg';
++
++sub read_config {
++ my ($live, $config_root, $config_path, $settings_path) = @_;
++
++ if ($config_path &amp;&amp; -e getcwd() . '/' . $config_path) {
++ $config_root = getcwd();
++ }
++ print &quot;using $config_root as directory root\n&quot;;
++
++ add2hash($live-&gt;{settings} ||= {}, { getVarsFromSh($config_root . '/' . $settings_path) }) if $settings_path;
++ if ($config_path) {
++ #- don't use do(), since it can't see lexicals in the enclosing scope
++ my $cfg = eval(cat_($config_root . '/' . $config_path)) or die &quot;unable to load $config_path: $@\n&quot;;
++ put_in_hash($live, $cfg);
++ print &quot;loaded $config_path as config file\n&quot;;
++ }
++ $live-&gt;{settings}{config_root} = $config_root;
++}
++
++sub check_config {
++ my ($live) = @_;
++ unless (keys(%$live)) {
++ warn &quot;no live definition\n&quot;;
++ Pod::Usage::pod2usage();
++ }
++ #- check for minimum requirements
++ ref $live-&gt;{media} &amp;&amp; $live-&gt;{media}{storage} or die &quot;no media storage definition\n&quot;;
++ ref $live-&gt;{system} or die &quot;no system definition\n&quot;;
++}
++
++sub complete_config {
++ my ($live) = @_;
++
++ my $default_prefix = {
++ build =&gt; {
++ boot =&gt; '/boot',
++ files =&gt; '/files',
++ dist =&gt; '/dist',
++ initrd =&gt; '/initrd',
++ loopbacks =&gt; '/loopbacks',
++ modules =&gt; '/modules',
++ scripts =&gt; '/scripts',
++ },
++ media =&gt; {
++ boot =&gt; '/boot',
++ hidden_boot =&gt; '/.boot',
++ loopbacks =&gt; '/loopbacks',
++ hidden_loopbacks =&gt; '/.loopbacks',
++ mnt =&gt; '/media',
++ },
++ live =&gt; {
++ mnt =&gt; '/live',
++ },
++ };
++
++ #- set unsupplied config dirs
++ add2hash($live-&gt;{prefix}{$_} ||= {}, $default_prefix-&gt;{$_}) foreach keys %$default_prefix;
++
++ $live-&gt;{settings}{builddir} ||= '/var/lib/draklive/build';
++ $live-&gt;{settings}{chroot} ||= '/var/lib/draklive/chroot';
++
++ $live-&gt;{settings}{arch} ||= chomp_(`rpm --eval '%{_target_cpu}'`);
++ $live-&gt;{media}{title} ||= &quot;live&quot;;
++
++ $_ = MDV::Draklive::Media::new($_) foreach (
++ $live-&gt;{media},
++ ($live-&gt;{replicator} ? $live-&gt;{replicator}{media} : ()),
++ ($live-&gt;{oem_rescue} ? $live-&gt;{oem_rescue}{media} : ()),
++ );
++
++ mkdir_p($live-&gt;get_builddir);
++ mkdir_p($live-&gt;get_system_root);
++ $live-&gt;{mnt} ||= $live-&gt;get_builddir . &quot;/mnt&quot;;
++}
++
++sub dump_config {
++ my ($live) = @_;
++ use Data::Dumper;
++ print Data::Dumper-&gt;Dump([ $live ], [ &quot;live&quot; ]);
++}
++
++1;
+
+<a id="draklivetrunklibMDVDrakliveCustomMediapm">Added: draklive/trunk/lib/MDV/Draklive/CustomMedia.pm</a>
+===================================================================
+--- draklive/trunk/lib/MDV/Draklive/CustomMedia.pm (rev 0)
++++ draklive/trunk/lib/MDV/Draklive/CustomMedia.pm 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,14 @@
++package MDV::Draklive::CustomMedia;
++
++sub nfs_media {
++ my ($module, $client, $path) = @_;
++ (
++ fs =&gt; 'nfs',
++ modules =&gt; 'nfs',
++ extra_modules =&gt; [ $module ],
++ pre =&gt; &quot;ifconfig eth0 $client up&quot;,
++ source =&gt; $path,
++ );
++}
++
++1;
+
+<a id="draklivetrunklibMDVDrakliveInitrdpm">Added: draklive/trunk/lib/MDV/Draklive/Initrd.pm</a>
+===================================================================
+--- draklive/trunk/lib/MDV/Draklive/Initrd.pm (rev 0)
++++ draklive/trunk/lib/MDV/Draklive/Initrd.pm 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,314 @@
++package MDV::Draklive::Initrd;
++
++use MDK::Common;
++use common;
++use list_modules;
++use MDV::Draklive::Utils;
++use MDV::Draklive::StorageFS;
++use MDV::Draklive::Loopback;
++use MDV::Draklive::Overlay;
++use File::Basename;
++
++my %module_to_config = (
++ ext3 =&gt; 'EXT3_FS',
++ sd_mod =&gt; 'BLK_DEV_SD',
++);
++
++sub require_list_modules_chroot {
++ my ($live) = @_;
++ my $chroot_list_modules = cat_($live-&gt;get_system_root . &quot;/usr/lib/libDrakX/list_modules.pm&quot;);
++ $chroot_list_modules =~ s/^package list_modules;\B/package list_modules_chroot;/;
++ my $tmp_list_modules = $live-&gt;get_system_root . &quot;/tmp/list_modules_chroot.pm&quot;;
++ output_p($tmp_list_modules, $chroot_list_modules);
++ require $tmp_list_modules;
++ unlink $tmp_list_modules;
++}
++
++sub nls_modules {
++ my ($live) = @_;
++ my $fs = $live-&gt;{media}-&gt;get_media_setting('fs');
++ if_($fs eq 'vfat', 'nls_cp437'), #- default FAT codepage
++ if_($fs !~ /^ext/, map { &quot;nls_$_&quot; } (map { &quot;iso8859_$_&quot; } 1..7, 9, 13..15), 'utf8');
++}
++
++sub create_media_initrd {
++ my ($live) = @_;
++ create_initrd_for_media($live, $live-&gt;{media});
++ cp_f($live-&gt;get_builddir . $live-&gt;{prefix}{build}{boot} . $live-&gt;{media}-&gt;get_initrd_path,
++ $live-&gt;{copy_initrd}) if $live-&gt;{copy_initrd};
++}
++
++sub inst_initrd_file {
++ my ($root, $initrd_tree, $file) = @_;
++ if ($file =~ m|/s?bin/|) {
++ inst_initrd_bin($root, $initrd_tree, $file);
++ } else {
++ mkdir_p($initrd_tree . dirname($file));
++ inst_initrd_dso_deps($root, $initrd_tree, $file) if $file =~ m|/lib[^/]*/|;
++ cp_f($root . $file, $initrd_tree . $file) or die &quot;unable to copy $file from system chroot\n&quot;;
++ }
++}
++
++sub inst_initrd_dso_deps {
++ my ($root, $initrd_tree, $dso) = @_;
++ foreach my $file (`chroot $root ldd $dso | awk '/\\// {if(\$2 == &quot;=&gt;&quot;) {print \$3} else {print \$1}}'`) {
++ chomp $file;
++ $file =~ s!^(/lib[^/]*)/(?:i686|tls)!$1!;
++ my ($lib_prefix, $filename) = $file =~ m|(/lib[^/]*).*/([^/]+)$| or next;
++ my $dest = $initrd_tree . $lib_prefix . '/' . $filename;
++ mkdir_p($initrd_tree . $lib_prefix);
++ -f $dest || cp_f($root . $file, $dest) or die &quot;unable to copy $filename from system chroot\n&quot;;
++ }
++}
++sub inst_initrd_bin {
++ my ($root, $initrd_tree, $bin) = @_;
++ cp_f($root . $bin, $initrd_tree . '/bin/');
++ inst_initrd_dso_deps($root, $initrd_tree, $bin);
++}
++
++sub create_initrd_for_media {
++ my ($live, $media) = @_;
++ my $initrd = $live-&gt;get_builddir . $live-&gt;{prefix}{build}{boot} . $media-&gt;get_initrd_path;
++ create_media_specific_initrd($live, $media, $live-&gt;get_system_root, $initrd, $live-&gt;find_kernel-&gt;{version});
++}
++
++sub create_media_specific_initrd {
++ my ($live, $media, $root, $initrd, $kernel) = @_;
++
++ require_list_modules_chroot($live);
++
++ my $lib_prefix = $live-&gt;get_lib_prefix;
++ my $initrd_tree = $live-&gt;get_builddir . $live-&gt;{prefix}{build}{initrd} . '/' . $media-&gt;{storage};
++ rm_rf($initrd_tree) if -e $initrd_tree;
++
++ mkdir_p($initrd_tree . $_) foreach
++ qw(/bin /dev /proc /sys /tmp),
++ map { $live-&gt;{prefix}{live}{mnt} . $_ }
++ $live-&gt;{prefix}{media}{mnt},
++ $live-&gt;{mount}{root},
++ map { $_-&gt;{mountpoint} } grep { !$loop_types{$_-&gt;{type}}{skip_mkdir} } @{$live-&gt;{mount}{dirs} || []};
++
++ #- use nash with label support
++ inst_initrd_bin($root, $initrd_tree, '/sbin/nash');
++ inst_initrd_bin($root, $initrd_tree, '/usr' . $lib_prefix . '/drakx-installer-binaries/probe-modules');
++ inst_initrd_bin($root, $initrd_tree, '/sbin/blockdev')
++ if $media-&gt;get_media_setting('rereadpt');
++ inst_initrd_bin($root, $initrd_tree, '/usr/bin/strace')
++ if $live-&gt;{debug};
++
++ #- busybox is required to:
++ #- detect usb-storage process (we need sh/while/ps/grep)
++ #- mount loopbacks read-only with losetup (useful over NFS)
++ my $busybox = '/usr/bin/busybox';
++ my $busybox_static = '/bin/busybox.static';
++ $busybox = $busybox_static if -e $root . $busybox_static;
++
++ inst_initrd_bin($root, $initrd_tree, $busybox);
++ my @l = map { /functions:/ .. /^$/ ? do { s/\s//g; split /,/ } : () } run_program::rooted_get_stdout($root, $busybox);
++ shift @l;
++ symlink(basename($busybox), $initrd_tree . &quot;/bin/$_&quot;) foreach @l;
++
++ my $fs = $media-&gt;get_media_setting('fs');
++ my @used_loop_types = uniq(map { $_-&gt;{type} } @{$live-&gt;{mount}{dirs}});
++ inst_initrd_bin($root, $initrd_tree, $_) foreach
++ MDV::Draklive::StorageFS::get_files($fs),
++ (map { @{$loop_types{$_} &amp;&amp; $loop_types{$_}{files} || []} } @used_loop_types);
++
++ output_p($initrd_tree . '/etc/fstab', '');
++ output_p($initrd_tree . '/etc/mtab', '');
++
++ my $loop_nb = 254;
++ my $rrpt_dev = $media-&gt;get_media_setting('rereadpt');
++ require devices;
++ devices::make($initrd_tree . &quot;/dev/$_&quot;) foreach
++ if_($rrpt_dev, $rrpt_dev),
++ qw(console initrd null ram systty tty tty1),
++ (map { &quot;tty$_&quot; } 0..8),
++ (map { &quot;loop$_&quot; } 0 .. $loop_nb);
++ syscall_('mknod', $initrd_tree . &quot;/dev/ptmx&quot;, c::S_IFCHR(), makedev(5, 2)) or die &quot;mknod failed (dev $_): $!&quot;;
++ syscall_('mknod', $initrd_tree . &quot;/dev/fb&quot;, c::S_IFCHR(), makedev(29, 0)) or die &quot;mknod failed (dev $_): $!&quot;;
++ #- pre-create devfsd compatibility loop devices (since busybox is still built with devfsd support)
++ mkdir_p($initrd_tree . &quot;/dev/loop&quot;);
++ cp_af($initrd_tree . &quot;/dev/loop$_&quot;, $initrd_tree . &quot;/dev/loop/$_&quot;) foreach 0 .. $loop_nb;
++
++ print &quot;using kernel $kernel\n&quot;;
++ my $kernel_root = &quot;/lib/modules/&quot; . $kernel;
++ list_modules::load_dependencies($kernel_root . &quot;/modules.dep&quot;, $root);
++
++ my ($storage_modules, $skipped) = partition { list_modules::modname2filename($_) }
++ uniq(map { modules::cond_mapping_24_26($_) } list_modules_chroot::category2modules($media-&gt;get_media_setting('modules')));
++ my ($extra_modules, $extra_missing) = partition { list_modules::modname2filename($_) }
++ list_modules_chroot::category2modules($media-&gt;get_media_setting('media_modules')),
++ nls_modules($live),
++ $media-&gt;get_media_fs_module,
++ @{$media-&gt;get_media_setting('extra_modules') || []},
++ (map { MDV::Draklive::Loopback::get_loop_modules($live, $_) } uniq(map { $_-&gt;{type} } @{$live-&gt;{mount}{dirs} || []})),
++ ($live-&gt;{mount}{overlay} ? @{$MDV::Draklive::Overlay::overlay{$live-&gt;{mount}{overlay}}{modules} || []} : ());
++
++ my @additional_modules = map { if_(m!([^/]+)\.ko(?:\.gz)?!, list_modules::filename2modname($1)) } @{$live-&gt;{system}{additional_modules}};
++ @$extra_modules = difference2($extra_modules, \@additional_modules);
++ if (@{$live-&gt;{system}{exclude_modules} || []}) {
++ print STDERR &quot;excluding modules: &quot; . join(' ', @{$live-&gt;{system}{exclude_modules}}) . &quot;\n&quot;;
++ @$_ = difference2($_, $live-&gt;{system}{exclude_modules}) foreach $storage_modules, $extra_modules, $extra_missing;
++ }
++
++ my @missing = sort(difference2($extra_missing, \@additional_modules));
++ if (@missing) {
++ my @config = map { if_(/^CONFIG_(.*)=y$/, $1) } cat_($root . &quot;/boot/config-&quot; . $kernel);
++ my @really_missing = grep { !member($module_to_config{$_}, @config) } @missing;
++ @really_missing and die &quot;missing mandatory modules:\n&quot; . join(&quot;\n&quot;, @really_missing, '');
++ }
++
++ mkdir_p($initrd_tree . $kernel_root . &quot;/kernel&quot;);
++ my @modules = (@$storage_modules, @$extra_modules);
++ my @modules_closure = uniq(map { list_modules::dependencies_closure($_) } @modules);
++ foreach my $m (@modules_closure) {
++ my $full = list_modules::modname2path($m);
++ mkdir_p(dirname($initrd_tree . $full));
++ cp_f($root . $full, $initrd_tree . $full);
++ }
++ foreach my $f (@{$live-&gt;{system}{additional_modules}}) {
++ my $destdir = $initrd_tree . $kernel_root . &quot;/kernel&quot;;
++ if ($f =~ /.gz$/) {
++ cp_f($live-&gt;{settings}{config_root} . '/' . $f, $destdir);
++ } else {
++ my $m = basename($f);
++ run_program::run('gzip', '&gt;', &quot;$destdir/$m.gz&quot;, '-c', $live-&gt;{settings}{config_root} . '/' . $f);
++ }
++ }
++ run_('depmod', '-b', $initrd_tree, $kernel);
++
++ mkdir_p($initrd_tree . &quot;/etc/blkid&quot;); #- for nash and showlabels cache
++ mkdir_p($initrd_tree . &quot;/lib/module-init-tools&quot;);
++ cp_f($root . &quot;/lib/module-init-tools/ldetect-lst-modules.alias&quot;, $initrd_tree . &quot;/lib/module-init-tools&quot;);
++ mkdir_p($initrd_tree . &quot;/usr/share/ldetect-lst&quot;);
++ cp_f($root . &quot;/usr/share/pci.ids&quot;, $initrd_tree . &quot;/usr/share&quot;);
++ cp_f($root . &quot;/usr/share/ldetect-lst/&quot; . $_, $initrd_tree . &quot;/usr/share/ldetect-lst&quot;)
++ foreach qw(fallback-modules.alias pcitable.gz usbtable.gz);
++
++ @$skipped and print STDERR &quot;skipped modules: &quot; . join(' ', sort(@$skipped)) . &quot;\n&quot;;
++
++ my @extra_modules_closure = map { list_modules::modname2filename($_) }
++ uniq(map { list_modules::dependencies_closure($_) } @$extra_modules);
++ create_initrd_scriptlet($live, $media, @extra_modules_closure, @additional_modules);
++
++ print &quot;Compressing initrd\n&quot;;
++ compress_initrd_tree($live, $initrd_tree, $initrd);
++ add_splash($live, $initrd);
++}
++
++sub create_initrd_scriptlet {
++ my ($live, $media, @modules) = @_;
++ my $target = $live-&gt;{prefix}{live}{mnt} . ($live-&gt;{mount}{root} || $live-&gt;{prefix}{media}{mnt});
++ my $pre = $media-&gt;get_media_setting('pre');
++ my $fs = $media-&gt;get_media_setting('fs');
++ my $rrpt_dev = $media-&gt;get_media_setting('rereadpt');
++ my $debug_shell = &quot;sh -c 'if grep -q initrd_debug /proc/cmdline; then plymouth --quit; exec sh &lt;/dev/console &gt;/dev/console 2&gt;/dev/console; fi'&quot;;
++ my ($mount_first, $mount_last) = partition { !$loop_types{$_-&gt;{type}}{delay_mount} }
++ grep { exists $loop_types{$_-&gt;{type}}{mount} } @{$live-&gt;{mount}{dirs} || []};
++ my $initrdroot = &quot;/initrd&quot;;
++
++ output_with_perm($live-&gt;get_builddir . $live-&gt;{prefix}{build}{initrd} . '/' . $media-&gt;{storage} . '/linuxrc', 0755,
++ join(&quot;\n&quot;,
++ &quot;#!/bin/nash&quot;,
++ #- required for labels and ps
++ &quot;nash-mount -t proc /proc /proc&quot;,
++ #- required for cdrom labels
++ &quot;nash-mount -t sysfs /sys /sys&quot;,
++ &quot;/bin/plymouthd&quot;,
++ &quot;plymouth --show-splash&quot;,
++ (map { join(&quot; &quot;, &quot;probe-modules&quot;, list_modules::filename2modname($_), grep { $_ } $live-&gt;{system}{module_options}{$_}) } @modules),
++ &quot;probe-modules --$media-&gt;{storage}&quot;,
++ if_($rrpt_dev,
++ &quot;echo *** Waiting for new partitions on device ${rrpt_dev} ***&quot;,
++ &quot;sh -c 'while ! ls /sys/block/${rrpt_dev}/${rrpt_dev}* &gt;/dev/null 2&gt;&amp;1; do sleep 3; blockdev --rereadpt /dev/${rrpt_dev} &gt;/dev/null 2&gt;&amp;1; done'&quot;),
++ $debug_shell,
++ if_($pre, deref_array($pre)),
++ &quot;showlabels --removable&quot;,
++ MDV::Draklive::StorageFS::get_mount($fs)-&gt;($live, $media),
++ (map { $loop_types{$_-&gt;{type}}{mount}-&gt;($live, $_) } @$mount_first, @$mount_last),
++ ($live-&gt;{mount}{overlay} ? $MDV::Draklive::Overlay::overlay{$live-&gt;{mount}{overlay}}{mount}-&gt;($live) : ()),
++ if_($live-&gt;{system}{initrd_pre_pivot}, deref_array($live-&gt;{system}{initrd_pre_pivot})),
++ &quot;plymouth --newroot=$target&quot;,
++ &quot;echo 0x0100 &gt; /proc/sys/kernel/real-root-dev&quot;,
++ &quot;umount /sys&quot;,
++ &quot;sh -c 'umount /proc/bus/usb 2&gt;/dev/null'&quot;,
++ &quot;umount /proc&quot;,
++ &quot;pivot_root $target $target$initrdroot&quot;,
++ if_($live-&gt;{mount}{root}, &quot;sh -c 'rmdir $initrdroot$live-&gt;{prefix}{live}{mnt}$live-&gt;{mount}{root}'&quot;),
++ (map { $loop_types{$_-&gt;{type}}{pivot_clean}-&gt;($live, $_, $initrdroot) } grep { $loop_types{$_-&gt;{type}}{pivot_clean} } @{$live-&gt;{mount}{dirs} || []}),
++ &quot;sh -c 'cd $initrdroot$live-&gt;{prefix}{live}{mnt}; for i in `ls -1`; do [ -d \$i ] || continue; mkdir -p $live-&gt;{prefix}{live}{mnt}/\$i; mount -n --move \$i $live-&gt;{prefix}{live}{mnt}/\$i; rmdir \$i; done'&quot;,
++ &quot;rmdir $initrdroot$live-&gt;{prefix}{live}{mnt}&quot;,
++ &quot;nash-mount -o mode=0755 -t tmpfs /dev /dev&quot;,
++ &quot;sh -c 'rm -rf /dev/loop'&quot;, #- not needed after initrd
++ &quot;sh -c 'mv $initrdroot/dev/* /dev/'&quot;,
++ if_($live-&gt;{system}{initrd_post}, deref_array($live-&gt;{system}{initrd_post})),
++ &quot;&quot;));
++}
++
++sub compress_initrd_tree {
++ my ($live, $initrd_tree, $initrd) = @_;
++
++ my $size = chomp_(run_program::get_stdout(&quot;du -ks $initrd_tree | awk '{print \$1}'&quot;));
++ my $inodes = chomp_(run_program::get_stdout(&quot;find $initrd_tree | wc -l&quot;)) + 100;
++ my $initrd_size = $size + 350 + int($inodes / 10); #- 10 inodes needs 1K
++ $initrd_size += 1000; # splashy
++
++ $initrd =~ s/.gz$//;
++
++ mkdir_p(dirname($initrd));
++ run_('dd', 'if=/dev/zero', &quot;of=$initrd&quot;, 'bs=1k', &quot;count=$initrd_size&quot;);
++ run_('mke2fs', '-q', '-m', 0, '-F', '-N', $inodes, '-s', 1, $initrd);
++ mkdir_p($live-&gt;{mnt});
++ run_('mount', '-o', 'loop', '-t', 'ext2', $initrd, $live-&gt;{mnt});
++ cp_af(glob(&quot;$initrd_tree/*&quot;), $live-&gt;{mnt});
++ rm_rf($live-&gt;{mnt} . &quot;/lost+found&quot;);
++ my $left = chomp_(run_program::get_stdout(&quot;df -Pk $live-&gt;{mnt} | tail -n 1 | awk '{ print \$4 }'&quot;));
++ run_('umount', $live-&gt;{mnt});
++ $left &lt; 200 and die &quot;not enough room to create initrd (only ${left}K left)\n&quot;;
++ run_('gzip', '-f', '-9', $initrd);
++}
++
++sub add_splash {
++ my ($live, $initrd) = @_;
++ if ($live-&gt;{system}{vga_mode} &amp;&amp; $live-&gt;{system}{splash} ne 'no') {
++ my $chroot_initrd;
++ if ($initrd !~ m,^/boot/,) {
++ $chroot_initrd = '/tmp/initrd.gz';
++ cp_f($initrd, $live-&gt;get_system_root . $chroot_initrd);
++ } else {
++ $chroot_initrd = $initrd;
++ }
++
++ {
++ local $::prefix = $live-&gt;get_system_root;
++ #- also calls switch-themes -u (through make-boot-splash)
++ #- which will regenerate gfxboot current link
++ require bootloader;
++ bootloader::add_boot_splash($chroot_initrd, $live-&gt;{system}{vga_mode});
++ }
++
++ if ($chroot_initrd ne $initrd) {
++ cp_f($live-&gt;get_system_root . $chroot_initrd, $initrd);
++ unlink($live-&gt;get_system_root . $chroot_initrd);
++ }
++ }
++}
++
++sub create_classical_initrd {
++ my ($live) = @_;
++ my $root = $live-&gt;get_system_root;
++ my $kernel = $live-&gt;find_kernel;
++ print &quot;using kernel $kernel-&gt;{version}\n&quot;;
++
++ my $initrd_long = '/boot/initrd-'. $kernel . '.img';
++ unlink($root . $initrd_long);
++
++ {
++ my $bootloader = {};
++ local $::prefix = $root;
++ bootloader::add_kernel($bootloader, $kernel, { label =&gt; 'linux', vga =&gt; $live-&gt;{system}{vga_mode} }, '', $live-&gt;{system}{no_initrd});
++ }
++}
++
++1;
+
+<a id="draklivetrunklibMDVDrakliveLivepm">Added: draklive/trunk/lib/MDV/Draklive/Live.pm</a>
+===================================================================
+--- draklive/trunk/lib/MDV/Draklive/Live.pm (rev 0)
++++ draklive/trunk/lib/MDV/Draklive/Live.pm 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,52 @@
++package MDV::Draklive::Live;
++
++use MDK::Common;
++
++sub new {
++ my ($class) = @_;
++ bless {}, $class;
++}
++
++sub get_name {
++ my ($live) = @_;
++ my $fields = $live-&gt;{name_fields} || [ qw(name product version desktop region media arch) ];
++ join('-', grep { $_ } @{$live-&gt;{settings}}{@$fields});
++}
++
++sub get_builddir {
++ my ($live) = @_;
++ $live-&gt;{settings}{builddir} . '/' . $live-&gt;get_name;
++}
++
++sub get_system_root {
++ my ($live) = @_;
++ $live-&gt;{settings}{chroot} . '/' . $live-&gt;get_name;
++}
++
++sub get_media_prefix {
++ my ($live, $setting, $o_boot) = @_;
++ my $hidden = $live-&gt;{system}{hide_media_dirs} &amp;&amp; $live-&gt;{media}-&gt;get_boot_setting('can_hide', { boot =&gt; $o_boot });
++ $live-&gt;{prefix}{media}{$hidden ? &quot;hidden_$setting&quot; : $setting};
++}
++
++sub find_kernel {
++ my ($live) = @_;
++ require bootloader;
++ local $::prefix = $live-&gt;get_system_root;
++ my @kernels = bootloader::get_kernels_and_labels();
++ my $kernel;
++ if ($live-&gt;{system}{kernel}) {
++ $kernel = find { $_-&gt;{version} eq $live-&gt;{system}{kernel} } @kernels;
++ $kernel or die &quot;kernel $live-&gt;{system}{kernel} can not be found\n&quot;;
++ }
++ $kernel ||= first(@kernels) or die &quot;no kernel can be found\n&quot;;
++}
++
++sub get_lib_prefix {
++ my ($live) = @_;
++ my $lib_prefix = find { glob($live-&gt;get_system_root . $_ . '/libc.so.*') } qw(/lib64 /lib);
++ $lib_prefix or die 'unable to find system libraries in /lib or /lib64';
++ $lib_prefix;
++}
++
++1;
+
+<a id="draklivetrunklibMDVDrakliveLoopbackpm">Added: draklive/trunk/lib/MDV/Draklive/Loopback.pm</a>
+===================================================================
+--- draklive/trunk/lib/MDV/Draklive/Loopback.pm (rev 0)
++++ draklive/trunk/lib/MDV/Draklive/Loopback.pm 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,142 @@
++package MDV::Draklive::Loopback;
++
++use MDK::Common;
++use File::Temp;
++use MDV::Draklive::Progress;
++use MDV::Draklive::Utils;
++
++use Exporter;
++our @ISA = qw(Exporter);
++our @EXPORT = qw(%loop_types);
++
++my $loop_number = 0;
++our %loop_types;
++%loop_types = (
++ squashfs =&gt; {
++ read_only =&gt; 1,
++ is_loopback =&gt; 1,
++ modules =&gt; sub { &quot;loop&quot;, has_squashfs4_with_lzma($_[0]) ? &quot;squashfs&quot; : &quot;squashfs_lzma&quot; },
++ extension =&gt; '-lzma.sqfs',
++ build =&gt; sub {
++ my ($live, $dir) = @_;
++ my $dest = $live-&gt;get_builddir . $live-&gt;{prefix}{build}{loopbacks} . $dir-&gt;{path} . $loop_types{squashfs}{extension};
++ mkdir_p(dirname($dest));
++ my $root = $dir-&gt;{root} || $live-&gt;get_system_root;
++ my $src = $root . $dir-&gt;{build_from};
++ my $total = directory_usage($src);
++ print &quot;have to process &quot; . int($total/1000000) . &quot; MB\n&quot;;
++ my $progress = MDV::Draklive::Progress-&gt;new($total, time(), 6);
++ my $exclude_file = tmpnam();
++ output_p($exclude_file, map { $root . &quot;$_\n&quot; } grep { -e $root . $_ } @{$dir-&gt;{exclude} || []});
++ my $sort = $live-&gt;{settings}{config_root} . '/' . $dir-&gt;{sort};
++ my $squashfs4 = has_squashfs4_with_lzma($live);
++ run_foreach(sub {
++ if (/^mksquashfs: file .*, uncompressed size (\d+) bytes\s*(?:DUPLICATE|LINK)?$/) {
++ $progress-&gt;{current} += $1;
++ $progress-&gt;show(time());
++ }
++ },
++ $squashfs4 ? 'mksquashfs' : 'mksquashfs3', $src, $dest,
++ $squashfs4 ? ('-comp', 'lzma') : '-lzma',
++ '-noappend', '-no-progress', '-info', '-b', '1048576',
++ #'-processors', 1,
++ '-ef', $exclude_file,
++ if_(-f $sort, '-sort', $sort),
++ ) or die &quot;unable to run mksquashfs\n&quot;;
++ $progress-&gt;end;
++ unlink $exclude_file;
++ },
++ mount =&gt; sub {
++ my ($live, $dir) = @_;
++ $dir-&gt;{loop} = &quot;/dev/loop&quot; . $loop_number++;
++ my $media_loopbacks = $live-&gt;get_media_prefix('loopbacks');
++ (
++ &quot;/bin/losetup $dir-&gt;{loop} $live-&gt;{prefix}{live}{mnt}$live-&gt;{prefix}{media}{mnt}${media_loopbacks}$dir-&gt;{path}$loop_types{squashfs}{extension}&quot;,
++ &quot;nash-mount -o ro -t squashfs $dir-&gt;{loop} $live-&gt;{prefix}{live}{mnt}$dir-&gt;{mountpoint}&quot;,
++ );
++ },
++ },
++ modules =&gt; {
++ read_only =&gt; 1,
++ delay_mount =&gt; 1,
++ mount =&gt; sub {
++ my ($live, $dir) = @_;
++ my $media_loopbacks = $live-&gt;get_media_prefix('loopbacks');
++ &quot;sh -c 'modules=; for m in $live-&gt;{prefix}{live}{mnt}$live-&gt;{prefix}{media}{mnt}${media_loopbacks}$dir-&gt;{path}/*; do n=\$(basename \$m); n=\${n%.sqfs}; d=$live-&gt;{prefix}{live}{mnt}$dir-&gt;{mountpoint}/\$n; mkdir -p \$d; mount -n -o loop,ro -t squashfs \$m \$d &amp;&amp; modules=\$modules\$d=ro:; done; echo \$modules | sed -e s/:\$// &gt; $live-&gt;{prefix}{live}{mnt}/$dir-&gt;{list}'&quot;;
++ },
++ pivot_clean =&gt; sub {
++ my ($live, $dir, $initrdroot) = @_;
++ (
++ &quot;sh -c 'cd $initrdroot$live-&gt;{prefix}{live}{mnt}$dir-&gt;{mountpoint}; for i in `ls -1`; do mkdir -p $live-&gt;{prefix}{live}{mnt}$dir-&gt;{mountpoint}/\$i; mount -n --move \$i $live-&gt;{prefix}{live}{mnt}$dir-&gt;{mountpoint}/\$i; rmdir \$i; done; rmdir $initrdroot$live-&gt;{prefix}{live}{mnt}$dir-&gt;{mountpoint}'&quot;,
++ &quot;sh -c 'mv $initrdroot$live-&gt;{prefix}{live}{mnt}/$dir-&gt;{list} $live-&gt;{prefix}{live}{mnt}/'&quot;,
++ );
++ },
++ },
++ loopfs =&gt; {
++ is_loopback =&gt; 1,
++ modules =&gt; [],
++ extension =&gt; '.loop',
++ build =&gt; sub {
++ my ($live, $dir) = @_;
++ my $dest = $live-&gt;get_builddir . $live-&gt;{prefix}{build}{loopbacks} . $dir-&gt;{path} . $loop_types{loopfs}{extension};
++ mkdir_p(dirname($dest));
++ MDV::Draklive::Utils::device_allocate_file($dest, $dir-&gt;{pre_allocate});
++ MDV::Draklive::Utils::device_mkfs($dest, $dir-&gt;{fs}) if !defined $dir-&gt;{min_size};
++ },
++ mount =&gt; sub {
++ my ($live, $dir) = @_;
++ $dir-&gt;{loop} = &quot;/dev/loop&quot; . $loop_number++;
++ my $fsck = &quot;chroot &lt;/dev/tty1 $live-&gt;{prefix}{live}{mnt}$dir_distrib_sqfs-&gt;{mountpoint} /sbin/fsck $dir-&gt;{loop}&quot;;
++ my $media_loopbacks = $live-&gt;get_media_prefix('loopbacks');
++ (
++ &quot;losetup $dir-&gt;{loop} $live-&gt;{prefix}{live}{mnt}$live-&gt;{prefix}{media}{mnt}${media_loopbacks}$dir-&gt;{path}$loop_types{loopfs}{extension}&quot;,
++ qq(sh -c &quot;$fsck -a || $fsck -y&quot;),
++ &quot;nash-mount -t $dir-&gt;{fs} $dir-&gt;{loop} $live-&gt;{prefix}{live}{mnt}$dir-&gt;{mountpoint}&quot;,
++ );
++ },
++ },
++ plain =&gt; {
++ skip_mkdir =&gt; 1,
++ mount =&gt; sub {
++ my ($live, $dir) = @_;
++ qq(sh -c &quot;mkdir -p $live-&gt;{prefix}{live}{mnt}$dir-&gt;{mountpoint}&quot;);
++ },
++ },
++ partition =&gt; {
++ files =&gt; [ '/sbin/fsck', '/sbin/blkid' ],
++ mount =&gt; sub {
++ my ($live, $dir) = @_;
++ my $fsck = &quot;/bin/fsck&quot;;
++ (
++ qq(sh -c 'dev=`blkid -l -t $dir-&gt;{path} -o device`; [ -z &quot;\$dev&quot; ] || $fsck -a \$dev || $fsck -y \$dev'),
++ &quot;nash-mount -t $dir-&gt;{fs} $dir-&gt;{path} $live-&gt;{prefix}{live}{mnt}$dir-&gt;{mountpoint}&quot;,
++ );
++ },
++ },
++ tmpfs =&gt; {
++ mount =&gt; sub {
++ my ($live, $dir) = @_;
++ my $mnt = $live-&gt;{prefix}{live}{mnt} . $dir-&gt;{mountpoint};
++ my $mount_opts = $dir-&gt;{mount_opts}?&quot;-o $dir-&gt;{mount_opts}&quot;:&quot;&quot;;
++ my $cmd = &quot;mount -t tmpfs $mount_opts $mnt $mnt&quot;;
++ $dir-&gt;{fallback} ? qq(sh -c 'if ! grep -q &quot; $mnt &quot; /proc/mounts; then $cmd; fi') : $cmd;
++ },
++ },
++);
++
++sub get_loop_modules {
++ my ($live, $type) = @_;
++ my $modules = $loop_types{$_}{modules};
++ my $type = ref $modules;
++ return $type eq 'CODE' ? $modules-&gt;($live) :
++ $type eq 'ARRAY' ? @$modules :
++ ();
++}
++
++sub has_squashfs4_with_lzma {
++ my ($live) = @_;
++ my $kernel = $live-&gt;find_kernel;
++ cat_($live-&gt;get_system_root . &quot;/boot/config-&quot; . $live-&gt;find_kernel-&gt;{version}) =~ /^CONFIG_DECOMPRESS_LZMA_NEEDED=y$/m;
++}
++
++1;
+
+<a id="draklivetrunklibMDVDrakliveMediapm">Added: draklive/trunk/lib/MDV/Draklive/Media.pm</a>
+===================================================================
+--- draklive/trunk/lib/MDV/Draklive/Media.pm (rev 0)
++++ draklive/trunk/lib/MDV/Draklive/Media.pm 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,88 @@
++package MDV::Draklive::Media;
++
++use MDK::Common;
++use MDV::Draklive::Storage;
++use POSIX;
++use common;
++
++sub new {
++ my ($media) = @_;
++
++ bless $media, 'MDV::Draklive::Media';
++
++ $media-&gt;{partitions} ||= [ { mntpoint =&gt; '/' } ];
++
++ for $mntpoint (qw(/ OEM_RESCUE)) {
++ my $part = find { $_-&gt;{mntpoint} eq $mntpoint } @{$media-&gt;{partitions}};
++ $part-&gt;{fs_type} ||= $media-&gt;get_media_setting('fs');
++ if (my $label = $mntpoint eq '/' &amp;&amp; $media-&gt;get_media_label) {
++ $part-&gt;{device_LABEL} ||= $label;
++ }
++ }
++
++ $media-&gt;{boot_entries} ||= [ '' =&gt; '' ];
++
++ $media;
++}
++
++sub get_initrd_path {
++ my ($media) = @_;
++ '/' . $media-&gt;{storage} . '/initrd.gz';
++}
++
++#- mainly for storage-specific subroutines
++sub get_storage_setting {
++ my ($media, $setting) = @_;
++ $MDV::Draklive::Storage::storage_types{$media-&gt;{storage}}{$setting};
++}
++
++#- for actions that support an optional boot storage type
++sub get_boot_setting {
++ my ($media, $setting, $opts) = @_;
++ $opts-&gt;{boot} ? $MDV::Draklive::Storage::storage_types{$opts-&gt;{boot}}{$setting} : get_media_setting($media, $setting);
++}
++
++#- for user-customisable media setting, that can override storage setting
++sub get_media_setting {
++ my ($media, $setting) = @_;
++ $media-&gt;{$setting} || $media-&gt;get_storage_setting($setting);
++}
++
++sub get_media_fs_module {
++ my ($media) = @_;
++ my $fs = $media-&gt;get_media_setting('fs');
++ $fs eq 'iso9660' ? 'isofs' : $fs eq 'ext2' ? @{[]} : $fs;
++}
++
++sub get_media_label {
++ my ($media) = @_;
++ first($media-&gt;get_media_setting('source') =~ /^LABEL=(.*)$/);
++}
++
++sub get_media_source_for_nash {
++ my ($media) = @_;
++ my $label = $media-&gt;get_media_label;
++ #- strip vfat labels to 11 chars and upper-case it
++ $label &amp;&amp; $media-&gt;get_media_setting('fs') eq 'vfat' ?
++ 'LABEL=' . uc(substr($label, 0, 11)) :
++ $media-&gt;get_media_setting('source');
++}
++
++sub find_partition_index {
++ my ($media, $mntpoint) = @_;
++ eval { find_index { $_-&gt;{mntpoint} eq $mntpoint } @{$media-&gt;{partitions}} };
++}
++
++sub find_boot_partition_index {
++ my ($media) = @_;
++ $media-&gt;find_partition_index('/boot') || $media-&gt;find_partition_index('/');
++}
++
++sub supplement_slash_size {
++ my ($media, $total_size) = @_;
++ my $correction = 1.2;
++ my $slash = find { $_-&gt;{mntpoint} eq '/' } @{$media-&gt;{partitions}};
++ $slash-&gt;{size} ||= POSIX::ceil($total_size * $correction / $common::SECTORSIZE);
++}
++
++1;
+
+<a id="draklivetrunklibMDVDrakliveMountspm">Added: draklive/trunk/lib/MDV/Draklive/Mounts.pm</a>
+===================================================================
+--- draklive/trunk/lib/MDV/Draklive/Mounts.pm (rev 0)
++++ draklive/trunk/lib/MDV/Draklive/Mounts.pm 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,93 @@
++package MDV::Draklive::Mounts;
++
++use MDK::Common;
++
++my $_dir_distrib_sqfs = {
++ mountpoint =&gt; '/distrib',
++ type =&gt; 'squashfs',
++ path =&gt; '/distrib',
++ # perl -MMDK::Common -e 'print map_index { (32767 - $::i) . &quot; $_&quot; } grep { !m,^/(?:dev|proc|sys|live/distrib), } uniq(&lt;&gt;)' &lt; bootlog.list &gt; config/distrib.sort
++ sort =&gt; &quot;config/distrib.sort&quot;,
++ build_from =&gt; '/',
++};
++my $_dir_memory = {
++ mountpoint =&gt; '/memory',
++ type =&gt; 'tmpfs',
++ mount_opts =&gt; 'mode=755',
++};
++
++my $_dir_modules = {
++ mountpoint =&gt; '/modules',
++ type =&gt; 'modules',
++ path =&gt; '/modules',
++ list =&gt; 'modules.lst',
++};
++
++#- use distro default
++our $default = {
++ dirs =&gt; [],
++};
++
++our $simple_union = {
++ root =&gt; '/union',
++ overlay =&gt; 'unionfs',
++ dirs =&gt; [
++ {
++ mountpoint =&gt; '/media',
++ type =&gt; 'plain',
++ },
++ $_dir_memory,
++ ],
++ };
++
++our $squash_rw_union = {
++ root =&gt; '/union',
++ overlay =&gt; 'unionfs',
++ dirs =&gt; [
++ $_dir_distrib_sqfs,
++ {
++ mountpoint =&gt; '/media/system',
++ type =&gt; 'plain',
++ },
++ ],
++ };
++
++sub volatile_squash_union {
++ my ($o_modules) = @_;
++ {
++ root =&gt; '/union',
++ overlay =&gt; 'unionfs',
++ dirs =&gt; [
++ $_dir_distrib_sqfs,
++ if_($o_modules, $_dir_modules),
++ $_dir_memory,
++ ],
++ };
++}
++
++sub squash_union {
++ my ($default_size, $o_min_size, $o_modules) = @_;
++ {
++ root =&gt; '/union',
++ overlay =&gt; 'unionfs',
++ dirs =&gt; [
++ $_dir_distrib_sqfs,
++ if_($o_modules, $_dir_modules),
++ {
++ mountpoint =&gt; '/system',
++ type =&gt; 'loopfs',
++ pre_allocate =&gt; $default_size,
++ if_(defined $o_min_size, min_size =&gt; $o_min_size),
++ fs =&gt; 'ext2',
++ path =&gt; '/system'
++ },
++ {
++ mountpoint =&gt; '/system',
++ type =&gt; 'tmpfs',
++ fallback =&gt; 1,
++ },
++ ],
++ };
++}
++
++1;
+
+<a id="draklivetrunklibMDVDrakliveOverlaypm">Added: draklive/trunk/lib/MDV/Draklive/Overlay.pm</a>
+===================================================================
+--- draklive/trunk/lib/MDV/Draklive/Overlay.pm (rev 0)
++++ draklive/trunk/lib/MDV/Draklive/Overlay.pm 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,22 @@
++package MDV::Draklive::Overlay;
++
++use MDV::Draklive::Loopback;
++
++our %overlay = (
++ unionfs =&gt; {
++ modules =&gt; [ qw(unionfs) ],
++ mount =&gt; sub {
++ my ($live) = @_;
++ #- build dirs list: &quot;dir1=ro:dir2:ro:dir3=rw&quot;
++ my $dirs = join(':',
++ map {
++ $_-&gt;{list} ? &quot;\$(cat $live-&gt;{prefix}{live}{mnt}/$_-&gt;{list})&quot; :
++ &quot;$live-&gt;{prefix}{live}{mnt}$_-&gt;{mountpoint}=&quot; .
++ (!$loop_types{$_-&gt;{type}}{read_only} &amp;&amp; !$_-&gt;{read_only} ? 'rw' : 'ro');
++ } reverse grep { !$_-&gt;{fallback} } @{$live-&gt;{mount}{dirs} || []});
++ &quot;sh -c 'mount -o dirs=$dirs -t unionfs unionfs $live-&gt;{prefix}{live}{mnt}$live-&gt;{mount}{root}'&quot;;
++ },
++ },
++);
++
++1;
+
+<a id="draklivetrunklibMDVDrakliveProgresspm">Added: draklive/trunk/lib/MDV/Draklive/Progress.pm</a>
+===================================================================
+--- draklive/trunk/lib/MDV/Draklive/Progress.pm (rev 0)
++++ draklive/trunk/lib/MDV/Draklive/Progress.pm 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,31 @@
++package MDV::Draklive::Progress;
++
++use POSIX qw(strftime);
++
++sub new {
++ my ($class, $total, $time, $o_exp_divide) = @_;
++ bless {
++ total =&gt; $total,
++ current =&gt; 0,
++ start_time =&gt; $time,
++ exp_divide =&gt; $o_exp_divide,
++ maxl =&gt; length($total) - $o_exp_divide,
++ }, $class;
++}
++
++sub show {
++ my ($progress, $time) = @_;
++ my $elapsed_time = $time - $progress-&gt;{start_time};
++ my $eta = $progress-&gt;{current} ? int($elapsed_time*$progress-&gt;{total}/$progress-&gt;{current}) : -1;
++ printf(&quot;\r%3d%% (%$progress-&gt;{maxl}s/%-$progress-&gt;{maxl}s), %8s/%8s (ETA)&quot;,
++ int(100*$progress-&gt;{current}/$progress-&gt;{total}),
++ (map { substr($_, 0, length($_)-$progress-&gt;{exp_divide}) } $progress-&gt;{current}, $progress-&gt;{total}),
++ (map { POSIX::strftime(&quot;%H:%M:%S&quot;, gmtime($_)) } $elapsed_time, $eta));
++}
++
++sub end {
++ my ($_progress) = @_;
++ print &quot;\n&quot;;
++}
++
++1;
+
+<a id="draklivetrunklibMDVDrakliveStoragepm">Added: draklive/trunk/lib/MDV/Draklive/Storage.pm</a>
+===================================================================
+--- draklive/trunk/lib/MDV/Draklive/Storage.pm (rev 0)
++++ draklive/trunk/lib/MDV/Draklive/Storage.pm 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,47 @@
++package MDV::Draklive::Storage;
++
++use detect_devices;
++
++our %storage_types = (
++ cdrom =&gt; {
++ modules =&gt; 'bus/firewire|usb disk/firewire|hardware_raid|ide|sata|scsi|usb',
++ media_modules =&gt; 'disk/cdrom',
++ fs =&gt; 'iso9660',
++ can_hide =&gt; 0,
++ source =&gt; 'LABEL=MDVCDROOT',
++ read_only =&gt; 1,
++ detect =&gt; \&amp;detect_devices::burners,
++ create =&gt; \&amp;main::create_cdrom_master,
++ format =&gt; \&amp;main::format_cdrom_device,
++ record_needs_master =&gt; 1,
++ record =&gt; \&amp;main::record_cdrom_master,
++ replicator =&gt; \&amp;main::create_cdrom_replicator,
++ record_replicator =&gt; \&amp;main::record_cdrom_replicator,
++ },
++ usb =&gt; {
++ modules =&gt; 'bus/usb disk/usb',
++ media_modules =&gt; 'disk/raw',
++ fs =&gt; 'vfat',
++ can_hide =&gt; 1,
++ bootloader =&gt; 'grub',
++ source =&gt; 'LABEL=MDVUSBROOT',
++ detect =&gt; sub { grep { detect_devices::isKeyUsb($_) } detect_devices::get() },
++ create =&gt; \&amp;main::create_disk_master,
++ format =&gt; \&amp;main::format_disk,
++ record =&gt; \&amp;main::record_usb_master,
++ image =&gt; \&amp;main::create_disk_image,
++ replicator =&gt; \&amp;main::create_usb_replicator,
++ record_replicator =&gt; \&amp;main::record_usb_replicator,
++ },
++ harddisk =&gt; {
++ fs =&gt; 'ext4',
++ bootloader =&gt; 'grub',
++ source =&gt; 'LABEL=MDVROOT',
++ create =&gt; \&amp;main::create_disk_master,
++ format =&gt; \&amp;main::format_disk,
++ record =&gt; \&amp;main::record_harddisk_master,
++ image =&gt; \&amp;main::create_disk_image,
++ },
++);
++
++1;
+
+<a id="draklivetrunklibMDVDrakliveStorageFSpm">Added: draklive/trunk/lib/MDV/Draklive/StorageFS.pm</a>
+===================================================================
+--- draklive/trunk/lib/MDV/Draklive/StorageFS.pm (rev 0)
++++ draklive/trunk/lib/MDV/Draklive/StorageFS.pm 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,56 @@
++package MDV::Draklive::StorageFS;
++
++use MDK::Common;
++
++my %storage_fs;
++%storage_fs = (
++ generic =&gt; {
++ mount =&gt; sub {
++ my ($live, $media) = @_;
++ my @mount_options = (
++ if_($media-&gt;get_media_setting('read_only'), &quot;ro&quot;),
++ grep { $_ } $media-&gt;get_media_setting('mount_options'),
++ );
++ 'nash-mount' . if_(@mount_options, &quot; -o &quot; . join(&quot;,&quot;, @mount_options)) . &quot; -t &quot; . $media-&gt;get_media_setting('fs') .
++ &quot; &quot; . $media-&gt;get_media_source_for_nash . &quot; $live-&gt;{prefix}{live}{mnt}$live-&gt;{prefix}{media}{mnt}&quot;;
++ },
++ },
++ nfs =&gt; {
++ files =&gt; [ '/sbin/ifconfig', '/bin/mount' ], #- needed to mount NFS (with nolock)
++ mount =&gt; sub {
++ my ($live, $media) = @_;
++ '/bin/mount -n -o ro,nolock -t nfs ' . $media-&gt;get_media_source_for_nash . &quot; $live-&gt;{prefix}{live}{mnt}$live-&gt;{prefix}{media}{mnt}&quot;;
++ }
++ },
++ ext2 =&gt; {
++ files =&gt; [ '/sbin/fsck.ext2' ],
++ mount =&gt; sub {
++ my ($live, $media) = @_;
++ my $fsck = &quot;/bin/fsck.ext2&quot;;
++ my $source = $media-&gt;get_media_setting('source');
++ qq(sh -c '$fsck -a $source || $fsck -y $source'),
++ $storage_fs{generic}{mount}-&gt;($live, $media);
++ },
++ },
++ vfat =&gt; {
++ #files =&gt; [ '/sbin/dosfsck' ],
++ mount =&gt; sub {
++ my ($live, $media) = @_;
++ #$storage_fs{generic}{mount}-&gt;($live, $media),
++ #qq(awk '\$2 == &quot;$live-&gt;{prefix}{live}{mnt}$live-&gt;{prefix}{media}{mnt}&quot; { system(&quot;umount &quot; \$1 &quot;; mount; echo dosfsck -a &quot; \$1 &quot;; dosfsck -a &quot; \$1) }' /proc/mounts),
++ $storage_fs{generic}{mount}-&gt;($live, $media);
++ },
++ },
++);
++
++sub get_files {
++ my ($fs) = @_;
++ @{$storage_fs{$fs} &amp;&amp; $storage_fs{$fs}{files} || []};
++}
++
++sub get_mount {
++ my ($fs) = @_;
++ $storage_fs{exists $storage_fs{$fs}{mount} ? $fs : 'generic'}{mount};
++}
++
++1;
+
+<a id="draklivetrunklibMDVDrakliveUtilspm">Added: draklive/trunk/lib/MDV/Draklive/Utils.pm</a>
+===================================================================
+--- draklive/trunk/lib/MDV/Draklive/Utils.pm (rev 0)
++++ draklive/trunk/lib/MDV/Draklive/Utils.pm 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,85 @@
++package MDV::Draklive::Utils;
++
++use MDK::Common;
++use common;
++use run_program;
++use IPC::Open3;
++use IO::Select;
++
++use Exporter;
++our @ISA = qw(Exporter);
++our @EXPORT = qw(directory_usage run_ run_foreach);
++
++sub directory_usage {
++ my ($dir, $o_apparent) = @_;
++ my $apparent = $o_apparent &amp;&amp; &quot;--apparent-size&quot;;
++ first(split /\s/, `du -s -B 1 $apparent $_[0]`);
++ }
++
++#- expand only if the pattern contains '*'
++#- and matches dot characters (like shell dotglob)
++sub glob__ {
++ my ($pattern) = @_;
++ $pattern =~ /\*/ ? glob_($pattern) : $pattern;
++}
++
++sub run_ {
++ my $options = ref $_[0] eq 'HASH' ? shift @_ : {};
++ my @cmd = @_;
++ $options-&gt;{timeout} ||= 'never';
++ if (arch() !~ /^arm/) {
++ my $targetarch = delete $options-&gt;{targetarch};
++ unshift @cmd, 'setarch', $targetarch if $targetarch;
++ }
++ print STDERR &quot;running &quot; . (exists $options-&gt;{root} &amp;&amp; &quot;(in chroot) &quot;) . join(' ', @cmd) . &quot;\n&quot;;
++ run_program::raw($options, @cmd);
++}
++
++sub run_foreach {
++ my ($foreach, @command) = @_;
++ print STDERR &quot;running &quot; . join(' ', @command) . &quot;\n&quot;;
++ my $pid = open3(my $cmd_in, my $cmd_out, undef, @command);
++ my $selector = IO::Select-&gt;new($cmd_out);
++ while (my @ready = $selector-&gt;can_read) {
++ foreach my $fh (@ready) {
++ local $_ = scalar&lt;$fh&gt;;
++ return if /^open3:/;
++ $foreach-&gt;();
++ $selector-&gt;remove($fh) if eof($fh);
++ }
++ }
++ close($cmd_out);
++ close($cmd_in);
++ return waitpid($pid, 0) &gt; 0 &amp;&amp; !($? &gt;&gt; 8);
++}
++
++sub mtools_run_ {
++ local $ENV{MTOOLS_SKIP_CHECK} = 1;
++ &amp;run_;
++}
++
++sub device_allocate_file {
++ my ($device, $size) = @_;
++ run_('dd', &quot;of=$device&quot;, 'count=0', 'bs=1', &quot;seek=&quot; . removeXiBSuffix($size));
++}
++
++#- format $device as type $type
++# FIXME: use fs::format
++sub device_mkfs {
++ my ($device, $type, $o_label, $o_inode_size) = @_;
++ if ($type eq 'vfat') {
++ run_('mkfs.vfat', if_(defined $o_label, '-n', $o_label), $device);
++ } elsif (member($type, 'ext2', 'ext3', 'ext4')) {
++ run_(&quot;mkfs.$type&quot;, &quot;-m&quot;, 0,
++ if_(defined $o_label, '-L', $o_label),
++ if_($o_inode_size, '-I', $o_inode_size),
++ if_(!-b $device, '-F'),
++ $device);
++ } elsif ($type eq 'swap') {
++ run_('mkswap', if_(defined $o_label, '-L', $o_label), $device);
++ } else {
++ die &quot;unable to mkfs for unsupported media type $type\n&quot;;
++ }
++}
++
++1;
+
+<a id="draklivetrunkmkinitrddraklive">Added: draklive/trunk/mkinitrd-draklive</a>
+===================================================================
+--- draklive/trunk/mkinitrd-draklive (rev 0)
++++ draklive/trunk/mkinitrd-draklive 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,20 @@
++#!/usr/bin/perl
++
++use lib qw(/usr/lib/libDrakX);
++
++use MDV::Draklive::Live;
++use MDV::Draklive::Config;
++use MDV::Draklive::Initrd;
++
++my ($initrd, $kernel) = @ARGV;
++$initrd &amp;&amp; $kernel or die &quot;usage $0 &lt;initrd&gt; &lt;kernel&gt;\n&quot;;
++
++my $live = 'MDV::Draklive::Live'-&gt;new;
++MDV::Draklive::Config::read_config($live,
++ $MDV::Draklive::Config::default_config_root,
++ $MDV::Draklive::Config::default_config_path,
++ $MDV::Draklive::Config::default_settings_path);
++MDV::Draklive::Config::check_config($live);
++MDV::Draklive::Config::complete_config($live);
++
++MDV::Draklive::Initrd::create_media_specific_initrd($live, $live-&gt;{media}, &quot;/&quot;, $initrd, $kernel);
+
+<a id="draklivetrunkwrite_flashsh">Added: draklive/trunk/write_flash.sh</a>
+===================================================================
+--- draklive/trunk/write_flash.sh (rev 0)
++++ draklive/trunk/write_flash.sh 2011-02-03 17:53:54 UTC (rev 397)
+@@ -0,0 +1,95 @@
++#!/bin/sh
++
++source=mandriva-linux-flash-2010-KDE4-all-usb-i586.img
++dump_block_size=$((2*1024*1024))
++
++title=&quot;USB image dump&quot;
++
++image_size=$(stat -c %s $source)
++image_md5=$(awk '{ print $1 }' $source.md5)
++mbr_size=512
++
++image_blocks=$((image_size/dump_block_size))
++image_remainder_bytes=$((image_size%dump_block_size))
++image_remainder_skip=$((image_size-image_remainder_bytes))
++
++log() {
++ echo &quot;$* (on $(date))&quot;
++}
++
++show_wait() {
++ log $*
++ zenity --progress --auto-kill --title &quot;$title&quot; --text &quot;$*&quot; &amp;
++}
++
++show_progress() {
++ log $*
++ zenity --progress --auto-kill --pulsate --title &quot;$title&quot; --text &quot;$*&quot; &amp;
++}
++
++show_error() {
++ log $*
++ zenity --error --title $title --text &quot;$*&quot;
++}
++
++# forbid auto-mount on LXDE
++killall halevt
++
++#mkdir -p /mnt/loop
++#mount -o offset=$((62*512)),ro $source /mnt/loop
++while true; do
++ show_wait &quot;Please insert new key&quot;
++ wait_pid=$!
++ while sleep 5; do
++ dev=$(grep 'sd[^a]$' /proc/partitions | awk '{ print $4 }')
++ if [ -n &quot;$dev&quot; ]; then
++ dest=/dev/$dev
++ break
++ fi
++ done
++
++ sleep 2
++ grep &quot;^$dest&quot; /proc/mounts | awk '{ print $1 }' | xargs -r umount
++ kill $wait_pid
++
++ show_progress &quot;Key found, writing image&quot;
++ wait_pid=$!
++
++ dd if=$source of=$dest bs=$dump_block_size
++ kill $wait_pid
++ if [ $? -ne 0 ]; then
++ show_error &quot;Key dump failed&quot;
++ exit 1
++ fi
++
++ #- more optimized write method, but harder to check
++ #dd if=$source of=$dest count=$mbr_size
++ #blockdev --rereadpt $dest
++ #mkdir -p /mnt/disk
++ #mount ${dest}1 /mnt/disk
++ #rsync -avP /mnt/loop /mnt/disk
++ #umount /mnt/disk
++
++ show_progress &quot;Key dumped, checking&quot;
++ wait_pid=$!
++ sync
++
++ dumped_md5=$((dd if=$dest bs=$dump_block_size count=$image_blocks; dd if=$dest bs=1 skip=$image_remainder_skip count=$image_remainder_bytes) | md5sum - | awk '{ print $1 }')
++ kill $wait_pid
++
++ echo &quot;md5: dumped = $dumped_md5&quot;
++ echo &quot;md5: source = $image_md5&quot;
++ if [ &quot;$dumped_md5&quot; != &quot;$image_md5&quot; ]; then
++ show_error &quot;Key has errors&quot;
++ exit 1
++ fi
++ show_wait &quot;Key dumped and verified&quot;$'\n'$'\n'&quot;Please remove key&quot;
++ wait_pid=$!
++
++ while sleep 5; do
++ grep -q 'sd[^a]$' /proc/partitions || break
++ done
++ kill $wait_pid
++ echo &quot;Key removed&quot;
++done
++#umount /mnt/loop
+
+
+Property changes on: draklive/trunk/write_flash.sh
+___________________________________________________________________
+Added: svn:executable
+ + *
+Added: svn:eol-style
+ + native
+
+</pre></div>
+
+</body>
+</html> \ No newline at end of file