From 1be510f9529cb082f802408b472a77d074b394c0 Mon Sep 17 00:00:00 2001 From: Nicolas Vigier Date: Sun, 14 Apr 2013 13:46:12 +0000 Subject: Add zarb MLs html archives --- zarb-ml/mageia-sysadm/2011-February/002546.html | 4468 +++++++++++++++++++++++ 1 file changed, 4468 insertions(+) create mode 100644 zarb-ml/mageia-sysadm/2011-February/002546.html (limited to 'zarb-ml/mageia-sysadm/2011-February/002546.html') diff --git a/zarb-ml/mageia-sysadm/2011-February/002546.html b/zarb-ml/mageia-sysadm/2011-February/002546.html new file mode 100644 index 000000000..1ed51124d --- /dev/null +++ b/zarb-ml/mageia-sysadm/2011-February/002546.html @@ -0,0 +1,4468 @@ + + + + [Mageia-sysadm] [397] Import cleaned draklive + + + + + + + + + +

[Mageia-sysadm] [397] Import cleaned draklive

+ root at mageia.org + root at mageia.org +
+ Thu Feb 3 18:53:55 CET 2011 +

+
+ +
Revision: 397
+Author:   dmorgan
+Date:     2011-02-03 18:53:54 +0100 (Thu, 03 Feb 2011)
+Log Message:
+-----------
+Import cleaned draklive
+
+Added Paths:
+-----------
+    draklive/
+    draklive/CLEANUP_PROGRESS.txt
+    draklive/trunk/
+    draklive/trunk/.perl_checker
+    draklive/trunk/ChangeLog
+    draklive/trunk/Makefile
+    draklive/trunk/NEWS
+    draklive/trunk/draklive
+    draklive/trunk/draklive-copy-wizard.desktop
+    draklive/trunk/kmod/
+    draklive/trunk/kmod/readlog.c
+    draklive/trunk/lib/
+    draklive/trunk/lib/MDV/
+    draklive/trunk/lib/MDV/Draklive/
+    draklive/trunk/lib/MDV/Draklive/Config.pm
+    draklive/trunk/lib/MDV/Draklive/CustomMedia.pm
+    draklive/trunk/lib/MDV/Draklive/Initrd.pm
+    draklive/trunk/lib/MDV/Draklive/Live.pm
+    draklive/trunk/lib/MDV/Draklive/Loopback.pm
+    draklive/trunk/lib/MDV/Draklive/Media.pm
+    draklive/trunk/lib/MDV/Draklive/Mounts.pm
+    draklive/trunk/lib/MDV/Draklive/Overlay.pm
+    draklive/trunk/lib/MDV/Draklive/Progress.pm
+    draklive/trunk/lib/MDV/Draklive/Storage.pm
+    draklive/trunk/lib/MDV/Draklive/StorageFS.pm
+    draklive/trunk/lib/MDV/Draklive/Utils.pm
+    draklive/trunk/mkinitrd-draklive
+    draklive/trunk/write_flash.sh
+
+Added: draklive/CLEANUP_PROGRESS.txt
+===================================================================
+--- 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 "Mandriva" to "Mageia" in draklive as it'll be visible to
++  users
+
+
+Property changes on: draklive/CLEANUP_PROGRESS.txt
+___________________________________________________________________
+Added: svn:eol-style
+   + native
+
+Added: draklive/trunk/.perl_checker
+===================================================================
+--- 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
+
+Added: draklive/trunk/ChangeLog
+===================================================================
+--- 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 <oblin at mandriva.com>
++
++	* draklive: do not run service_harddrake stop anymore, it does not
++	  exist in 2008.0
++
++2007-09-25 15:20  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: fix typo
++
++2007-09-25 14:05  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: add newlines in die messages, not to trigger the
++	  infamous drakbug
++
++2007-09-25 13:55  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: print usage if no option is specified
++
++2007-09-25 10:31  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: fix division by zero /o\
++
++2007-09-19 14:53  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: copy additional modules after plain modules, so that
++	  they can overwrite them
++
++2007-09-19 14:53  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: fix additional modules copy
++
++2007-09-03 08:44  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: please perl_checker
++
++2007-09-03 08:42  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: don't check symlinks when looking for kernels (fix
++	  matching vmlinuz-tmb-desktop586)
++
++2007-09-03 08:41  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: simplify
++
++2007-08-28 08:52  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: allow to copy per-fs files in mkinitrd
++
++2007-08-28 08:50  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: move mount actions in a storage_fs hash
++
++2007-08-28 08:49  Olivier Blin <oblin at mandriva.com>
++
++	* .perl_checker: supplement perl_checker blacklist
++
++2007-08-28 08:41  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: run mkdevices to create nodes for existing devices
++
++2007-08-28 08:40  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: fix typo
++
++2007-08-28 08:39  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: move modules mount point in new root
++
++2007-08-28 08:39  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: cosmetics
++
++2007-08-28 08:38  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: remove more dirs
++
++2007-08-28 08:35  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: add a new is_loopback variable to better list selected
++	  loopbacks
++
++2007-08-28 08:33  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: create less loop devices by default
++
++2007-08-28 08:23  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: allow to specify ro unionfs branches
++
++2007-08-28 08:19  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: make bootloader timeout configurable
++
++2007-08-28 08:16  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: fix unionfs branches list by removing trailing colon
++	  (for unionfs2)
++
++2007-08-28 08:15  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: make boot and loopbacks read-only
++
++2007-08-28 08:15  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: mark hidden files hidden only
++
++2007-07-16 12:56  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: fix vfat check...
++
++2007-06-12 09:47  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: oops, I really meant vfat when stripping labels for
++	  nash
++
++2007-06-11 15:26  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: add a get_media_source_for_nash functions that formats
++	  ext2 labels accordingly
++
++2007-06-07 16:33  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: do not select modules directory together with loopbacks
++
++2007-06-07 14:43  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: hidden_files is a better name
++
++2007-06-07 14:42  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: hide more autorun files
++
++2007-06-07 09:47  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: remove multi squash union, better replaced with modules
++
++2007-06-07 09:47  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: use modules in volatile_squash_union mounts
++
++2007-06-07 09:41  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: fix extra files selection in cdrom master
++
++2007-06-05 18:57  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: perl_checker fixes
++
++2007-06-05 18:57  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: only run mattrib for vfat
++
++2007-06-05 18:55  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: also hide autorun.inf (yes, hardcode it)
++
++2007-06-05 18:54  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: hide all files begining with a dot on USB media
++
++2007-06-05 11:54  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: do not copy extra media files in boot images
++
++2007-06-05 07:17  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: add a glob wrapper that dotglob behavior and expand
++	  only if needed
++
++2007-06-05 01:12  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: protect rm_rf from die
++
++2007-06-04 15:48  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: run mattrib with MTOOLS_SKIP_CHECK
++
++2007-06-04 15:48  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: create mtools_run_
++
++2007-06-04 14:49  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: use glob_ to match dot files (since File::Glob does not
++	  provide a dotglob option)
++
++2007-05-31 15:14  Olivier Blin <oblin at mandriva.com>
++
++	* 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 <oblin at mandriva.com>
++
++	* draklive: modify custom nfs syntax
++
++2007-05-31 13:38  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: oops, add back mountpoint
++
++2007-05-31 13:36  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: use modules source for squash_union
++
++2007-05-31 13:35  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: add modules source type
++
++2007-05-31 13:19  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: allow to get loopbacks list from a file
++
++2007-05-31 13:16  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: allow to delay mount of specific loopbacks
++
++2007-05-31 12:29  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: try to get interactive debug shell
++
++2007-05-31 12:08  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: allow to specify module options in
++	  $live->{system}{module_options}
++
++2007-05-31 12:06  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: allow to use real glob patterns in
++	  live->{system}{remove_files}
++
++2007-05-31 12:05  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: fix directory creation when dest is a dir in
++	  copy_files_to
++
++2007-05-31 12:04  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: clean build files before creating new ones
++
++2007-05-29 16:39  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: pre-create devfsd compatibility loop devices (since
++	  busybox is still built with devfsd support)
++
++2007-05-29 16:37  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: pre-create more loop devices
++
++2007-05-26 17:39  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: modify loopback modules syntax to be compatible with
++	  file list expansion
++
++2007-05-26 17:38  Olivier Blin <oblin at mandriva.com>
++
++	* 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 <oblin at mandriva.com>
++
++	* draklive: fix excluded loopback path
++
++2007-05-21 13:14  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: pass opts when formatting
++
++2007-05-21 13:13  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: fix typo...
++
++2007-05-21 13:12  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: make optional device usage more consistent
++
++2007-05-21 13:05  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: remove extra media support
++
++2007-05-21 13:02  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: fix some typos
++
++2007-05-21 13:02  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: remove optional media support
++
++2007-05-17 22:07  Olivier Blin <oblin at mandriva.com>
++
++	* 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 <oblin at mandriva.com>
++
++	* draklive: remove more initrd relics
++
++2007-05-16 22:06  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: use busybox's mkdir since nash's "mkdir -p" does not
++	  have the standard behavior
++
++2007-05-16 21:02  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: fix silly typo
++
++2007-05-16 20:48  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: allow to include loopback modules in master images by
++	  defining modules sets in live->{packs} and selecting them from
++	  live->{settings}{pack}
++
++2007-05-16 20:42  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: define /modules in prefix hash
++
++2007-05-16 20:40  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: make directory path prefixed by / (to make subpath
++	  usage easier)
++
++2007-05-16 20:38  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: rename directory "location" field as "path"
++
++2007-05-16 20:31  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: allow to create loopback modules from
++	  live->{loopbacks}{modules} (to be used for separate i18n
++	  loopbacks)
++
++2007-05-16 20:25  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: archive excluded files list as loopback type defined by
++	  live->{loopbacks}{exclude}{type}} instead of tarball
++
++2007-05-16 20:23  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: use hardlink_filtered to build excluded files tarball
++
++2007-05-16 20:18  Olivier Blin <oblin at mandriva.com>
++
++	* 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 <oblin at mandriva.com>
++
++	* draklive: allow to use glob when expand file list
++
++2007-05-16 20:14  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: protect deref
++
++2007-05-16 20:13  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: rename live->{loopbacks}{exclude_files} as
++	  live->{loopbacks}{exclude}{files}
++
++2007-05-16 20:12  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: transform list_excluded_files as more generic
++	  expand_file_list
++
++2007-05-16 20:10  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: pass excluded files list in loopback directory hash to
++	  allow refined exclusion
++
++2007-05-16 20:03  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: really set bootlogo variable (and simplify)
++
++2007-05-16 19:56  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: add extension for some loopback types
++
++2007-05-16 19:42  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: add list_selected_loopbacks() function
++
++2007-05-16 19:35  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: copy only selected loopbacks in master image
++
++2007-05-16 19:29  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: allow to build squashfs with prefix different from
++	  chroot
++
++2007-05-16 19:26  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: differentiate squashfs source and prefix to be able to
++	  build from sources != '/'
++
++2007-05-16 19:23  Olivier Blin <oblin at mandriva.com>
++
++	* 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 <oblin at mandriva.com>
++
++	* draklive: really use $dir variable and not indefinite $_
++
++2007-05-16 19:17  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: rename directory "source" field as "location"
++
++2007-05-16 19:01  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: use initramfs instead of initrd
++
++2007-05-16 18:57  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: rename create_initrd_linuxrc as create_initrd_scriptlet
++
++2007-05-02 11:56  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: pre-create tarballs directory
++
++2007-05-02 09:48  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: perl_checker fix
++
++2007-05-02 09:47  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: include media files on CD as well
++
++2007-05-02 09:46  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: move media files copy in post-install step
++
++2007-05-02 09:45  Olivier Blin <oblin at mandriva.com>
++
++	* draklive: move umask restoration at end of post-install
++
++2007-05-02 09:23  Olivier Blin <oblin at mandriva.com>
++
++	* ., .perl_checker, Makefile, NEWS, draklive,
++	  draklive-copy-wizard.desktop: reimport draklive in SVN
++
+
+Added: draklive/trunk/Makefile
+===================================================================
+--- 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 ".svn" ]; then \
++		$(MAKE) dist-svn; \
++	elif [ -e ".git" ]; then \
++		$(MAKE) dist-git; \
++	else \
++		echo "Unknown SCM (not SVN nor GIT)";\
++		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 >../$(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
+
+Added: draklive/trunk/NEWS
+===================================================================
+--- 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->{mount_options}
++- make it possible to specify mount options for tmpfs mounts
++- allow to skip writing fstab with live->{system}{skip_fstab}
++- allow to skip writing bootloader config with live->{system}{skip_bootloader_config}
++- allow to skip bootloader install with live->{system}{skip_bootloader_install}
++- allow not to create initrd with live->{system}{no_initrd}
++- allow to select which settings fields are used to build name, in live->{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->{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 "classical" 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->{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->{oem_rescue})
++- preset fs_type for OEM_RESCUE partition too
++- allow to set inode size in media->{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->{settings}{replicator_type} to "drakx")
++- 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->{system}{append}
++- specify root in bootloader append for harddisk installs
++- create "classical" 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->{replicator}{append}
++
++* initrd
++- splashy support
++- generate "classical" 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->{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->{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 "showlabels --removable" 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 "images" directory as "dist"
++- 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 "must be root" message,
++  it's broken outside of X
++
++
++0.6:
++
++* config
++- use config and additional files from live->{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->{system}{gfxboot} is set
++- remove extra media support
++- remove optional media support
++- allow to specify bootloader timeout in
++  live->{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 "loop" 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->{system}{exclude_modules}
++- use busybox's mkdir since nash's "mkdir -p" 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->{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->{system}{remove_files} now (dbus/modprobe/udev files
++  for example)
++- allow to use real glob patterns in live->{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->{loopbacks}{modules}
++  (to be used for separate i18n loopbacks)
++- allow to include loopback modules in master images by defining
++  modules sets in live->{packs} and selecting them from live->{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 "modules" 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->{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->{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->{system}{files} and live->{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 "plain" 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->{media}{files}
++  (see details in "master" section)
++- allow to use glob patterns in live->{system}{files} and
++  live->{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->{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->{post} as live->{system}{initrd_post}
++- export region as DRAKLIVE_REGION for auto_install
++- allow to provide stage2 updates with live->{system}{stage2_updates}
++- allow to make the initrd reread a device partition table using
++  live->{media}{rereadpt}
++  (useful if USB partition changes after some PIN input)
++- allow to customize bootloader title in live->{media}{title}
++- default to config/live.cfg config path
++- allow to load live->{settings} from a file and default to
++  config/settings.cfg
++- use region/repository/root/workdir variables from live->{settings}
++- rename "workdir" setting as "builddir"
++- rename "root" setting as "chroot"
++- 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->{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 "debug" 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
+
+Added: draklive/trunk/draklive
+===================================================================
+--- 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 <oblin at mandriva.com>
++#
++# 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->{storage} . '/syslinux' . ($opts->{boot} && '-boot-' . $opts->{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->{append} || $live->{system}{append};
++    join(' ',
++         if_(!need_media_specific_boot($live),
++             'root=' . $live->{media}->get_media_source_for_nash),
++         if_($live->{system}{vga_mode} && $append !~ /\bvga=\b/,
++             'splash=silent',
++             'vga=' . $live->{system}{vga_mode}),
++         if_($append, $append),
++     );
++}
++
++sub get_bootloader_timeout {
++    my ($live) = @_;
++    defined $live->{media}{bootloader_timeout} ? $live->{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->get_boot_setting('fs', $opts) eq 'vfat';
++    my $boot = $live->get_media_prefix('boot', $opts->{boot});
++    my ($initrd, $kernel, $bootlogo, $help) = map { $to_root ? basename($_) : $_ }
++      map { $boot . $_ } $media->get_initrd_path, @syslinux_boot_files;
++    my $has_bootlogo = $live->{system}{gfxboot} &&
++      -e ($live->get_builddir . $live->{prefix}{build}{boot} . '/syslinux/bootlogo');
++    my $timeout = get_bootloader_timeout($live) * 10;
++    my $title = $media->{title} || $live->{media}{title};
++    join("\n",
++         "default $title",
++         "prompt 1",
++         "timeout $timeout",
++         "display $help",
++         if_($has_bootlogo, "ui gfxboot.com $bootlogo"),
++         (map {
++             my ($name, $cmdline) = @$_;
++             $name =~ s/\s/_/g;
++	     if ($name eq "harddisk") {
++		 "label " . $name,
++		 "    localboot 0x80";
++	     } else {
++		"label " . ($name || $title),
++		"    kernel $kernel",
++		"    append initrd=$initrd $append $cmdline";
++	    }
++         } group_by2(@{$media->{boot_entries}})),
++         "",
++     );
++}
++
++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->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 = "(hd0" . (defined $part_idx ? "," . $part_idx : "") . ")";
++    my $boot = $live->get_media_prefix('boot'); #- FIXME handle boot media
++    #- remove prefix if installing bootloader on separate /boot partition
++    $media->{partitions}[$part_idx]{mntpoint} eq $boot and $boot = "";
++
++    my $title = $media->{title} || $live->{media}{title};
++
++    join("\n",
++         "timeout " . get_bootloader_timeout($live),
++         if_($live->{system}{gfxboot}, "gfxmenu $grub_part" . $boot . "/gfxmenu"),
++         "default 0",
++         (map {
++             my ($name, $cmdline) = @$_;
++             "title " . $title . if_($name, " ($name)"),
++             "kernel $grub_part" . $boot . "/vmlinuz " . get_default_append($live, $opts) . if_($cmdline, " $cmdline"),
++             if_($initrd, "initrd " . $boot . $initrd);
++         } group_by2(@{$media->{boot_entries}})),
++         ($live->{oem_rescue} && defined $opts->{oem_rescue_idx} ? (
++             #- FIXME: factorize with above, build_grub_cfg_entry($media)
++             "title " . $live->{oem_rescue}{media}{title},
++             "kernel (hd0,$opts->{oem_rescue_idx})" . $boot . "/vmlinuz " . $live->{oem_rescue}{append},
++             "initrd (hd0,$opts->{oem_rescue_idx})" . $boot . $media->get_initrd_path,
++         ) : ()),
++         "",
++     );
++}
++
++sub get_langs {
++    my ($live) = @_;
++    uniq(
++        (ref $live->{regions} ? @{$live->{regions}{$live->{settings}{region}}} : ()),
++        @{$live->{system}{langs_always}}
++    );
++}
++
++sub install_system {
++    my ($live) = @_;
++
++    my $repository = $live->{settings}{repository} . '/' . $live->{settings}{arch};
++
++    my $drakx_in_chroot = $repository . '/misc/drakx-in-chroot';
++    my $remote_repository = $repository =~ m!^(ftp|http)://! && $1;
++    if ($remote_repository) {
++        my $local_drakx_in_chroot = $live->get_builddir . $live->{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 "unable to get drakx-in-chroot from remote repository\n";
++        $drakx_in_chroot = $local_drakx_in_chroot;
++    }
++
++    local %ENV = (
++        %ENV,
++        (map { "DRAKLIVE_". uc($_->[0]) => $_->[1] } group_by2(%{$live->{settings}})),
++        %{$live->{system}{install_env}},
++    );
++    $ENV{DRAKLIVE_LANGS} = join(':', get_langs($live));
++    run_({ targetarch => $live->{settings}{arch} },
++	 'perl', $drakx_in_chroot,
++         $repository,
++         $live->get_system_root,
++         if_($live->{system}{auto_install}, '--auto_install', $live->{settings}{config_root} . '/' . $live->{system}{auto_install}),
++         if_($live->{system}{patch_install}, '--defcfg', $live->{settings}{config_root} . '/' . $live->{system}{patch_install}),
++         if_($live->{system}{rpmsrate}, '--rpmsrate', $live->{settings}{config_root} . '/' . $live->{system}{rpmsrate}),
++         ($live->{system}{stage2_updates} ? (map { ('--stage2-update', $live->{settings}{config_root} . '/' . $_->[0], $_->[1]) } @{$live->{system}{stage2_updates}}) : ()),
++    ) or die "unable to install system chroot\n";
++    post_install_system($live);
++}
++
++sub configure_draklive_resize {
++    my ($live) = @_;
++
++    my $resizable_loopback = find { $_->{min_size} } @{$live->{mount}{dirs} || []};
++    if ($resizable_loopback) {
++        my $media_loopbacks = $live->get_media_prefix('loopbacks');
++        my $ext = $loop_types{$resizable_loopback->{type}}{extension};
++        output($live->get_system_root . '/etc/sysconfig/draklive-resize', <<EOF);
++DRAKLIVE_RESIZE=yes
++LOOPBACK=$live->{prefix}{live}{mnt}$live->{prefix}{media}{mnt}${media_loopbacks}$resizable_loopback->{path}$ext
++TYPE=$resizable_loopback->{fs}
++MIN_SIZE=$resizable_loopback->{min_size}
++MOUNT=$live->{prefix}{live}{mnt}$resizable_loopback->{mountpoint}_resized
++OLD_MOUNT=$live->{prefix}{live}{mnt}$resizable_loopback->{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->{settings}{config_root} . '/' . $source);
++        print STDERR "copying @sources to $dest\n";
++        cp_af(@sources, $dest);
++        my $o_perm = $o_opts && $o_opts->{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 && @$files;
++}
++
++sub clean_system_conf_file {
++    my ($live, $file) = @_;
++    substInFile { undef $_ if /^[^#]/ } $live->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->get_system_root . '/proc');
++    run_('mount', '-t', 'sysfs', '/sys', $live->get_system_root . '/sys');
++
++    #- copy resolv.conf for name resolution to work when adding media
++    cp_f("/etc/resolv.conf", $live->get_system_root . "/etc/");
++
++    #- remove previous draklive leftovers if needed
++    run_({ root => $live->get_system_root }, 'urpmi.removemedia', '-a');
++
++    foreach (@{$live->{system}{additional_media}}) {
++        run_({ root => $live->get_system_root }, 'urpmi.addmedia', if_($_->{distrib}, '--distrib'), $_->{name}, $_->{path})
++          or die "unable to add media from $_->{path}\n";
++        @{$_->{packages} || []} or next;
++        run_({ root => $live->get_system_root, targetarch => $live->{settings}{arch} },
++	     'urpmi', '--auto', '--no-verify-rpm', if_(!$_->{distrib}, '--searchmedia', $_->{name}), @{$_->{packages}})
++          or die "unable to install packages from $_->{path}\n";
++    }
++
++    #- additional rpms may have dependencies in additional media
++    if (@{$live->{system}{rpms} || []}) {
++        my $rpm_tmp_dir = '/tmp/draklive_rpms';
++        mkdir_p($live->get_system_root . $rpm_tmp_dir);
++        cp_f((map { $live->{settings}{config_root} . '/' . $_ } @{$live->{system}{rpms}}), $live->get_system_root . $rpm_tmp_dir);
++        run_({ root => $live->get_system_root, targetarch => $live->{settings}{arch} },
++	     'urpmi', '--auto', '--no-verify-rpm',
++             map { $rpm_tmp_dir . '/' . basename($_) } @{$live->{system}{rpms}})
++          or die "unable to install additional system rpms\n";
++        rm_rf($live->get_system_root . $rpm_tmp_dir);
++    }
++
++    #- remove urpmi media added by drakx-in-chroot and additional media, they're unusable
++    run_({ root => $live->get_system_root }, 'urpmi.removemedia', '-a');
++
++    my $erase = join(' ', @{$live->{system}{erase_rpms} || []});
++    run_({ root => $live->get_system_root, targetarch => $live->{settings}{arch} },
++	 'sh', '-c', "rpm -qa $erase | xargs rpm -e ") if $erase;
++
++    run_({ root => $live->get_system_root }, 'chkconfig', '--del', $_) foreach @{$live->{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 => $live->get_system_root },
++         'perl', '-MStorable', '-e', qq(Storable::store({ UNKNOWN => {} }, '/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->{system}{skip_fstab}, '/etc/fstab');
++    unlink($_) foreach map { glob($live->get_system_root . $_) } @{$live->{system}{remove_files} || []};
++
++    if ($live->{system}{modules_conf}) {
++        local $::prefix = $live->get_system_root;
++        local *modules::write_preload_conf = sub {}; #- FIXME, make this an option
++        my $modules_conf = modules::any_conf->vnew;
++        put_in_hash($modules_conf, $live->{system}{modules_conf});
++        $modules_conf->write;
++    }
++
++    my $mount_options = $live->{media}->get_media_setting('mount_options') || "defaults";
++    output_with_perm($live->get_system_root . '/etc/fstab', 0644,
++                     $live->{mount}{overlay}
++                     ? "none / $live->{mount}{overlay} $mount_options 0 0\n"
++                     : $live->{media}->get_media_setting('source') . " / " . $live->{media}->get_media_setting('fs') . " $mount_options 1 1\n"
++                 ) unless $live->{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->get_system_root . '/etc/sysconfig/init';
++
++    configure_draklive_resize($live);
++
++    if ($live->{system}{preselect_kdm_user}) {
++        #- preselect specified user in kdm
++        my $kdm_cfg = $live->get_system_root . '/etc/kde/kdm/kdmrc';
++        update_gnomekderc($kdm_cfg, 'X-:0-Greeter' => (PreselectUser => 'Default', DefaultUser => $live->{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->{system}{patches}}) {
++        my $patch = $live->{settings}{config_root} . '/' . $_;
++        my @args = ('-p0', '-d', $live->get_system_root, '-i', $patch);
++        run_program::run('patch', '>', '/dev/null', '--dry-run', '-f', '-R', @args) || run_('patch', @args)
++            or die "unable to apply patch " . $patch . "\n";
++    }
++
++    copy_files_to($live, $live->{system}{files}, $live->get_system_root);
++    my @no_install_files = map { $_->[1] } grep { $_->[2] && $_->[2]{no_install} } @{$live->{system}{files}};
++    output_p($live->get_system_root . '/etc/draklive-install.d/remove.d/draklive', map { "$_\n" } @no_install_files);
++
++    eval { rm_rf($live->get_builddir . $live->{prefix}{build}{files}) };
++    mkdir_p($live->get_builddir . $live->{prefix}{build}{files});
++    if ($live->{media}{files}) {
++        copy_files_to($live, $live->{media}{files}, $live->get_builddir . $live->{prefix}{build}{files});
++    }
++    remove_files_from($live->{media}{remove_files}, $live->get_builddir . $live->{prefix}{build}{files});
++
++    run_({ targetarch => $live->{settings}{arch} },
++	 "chroot", $live->get_system_root, "bash", "-c", $live->{system}{postInstall}) if $live->{system}{postInstall};
++
++    clean_system_conf_file($live, "/etc/resolv.conf");
++    write_dist_lists($live);
++
++    run_('umount', $live->get_system_root . '/sys');
++    run_('umount', $live->get_system_root . '/proc/bus/usb');
++    run_('umount', $live->get_system_root . '/proc');
++
++    umask $previous_umask;
++}
++
++sub write_dist_lists {
++    my ($live) = @_;
++
++    my $lists_dir = $live->get_builddir . $live->{prefix}{build}{dist};
++    mkdir_p($lists_dir);
++
++    run_("chroot " . $live->get_system_root . " rpm -qa | sort > " .
++         $lists_dir . '/' . $live->get_name . '.lst');
++
++    run_("chroot " . $live->get_system_root . " rpm -qa --qf '%{name}\n' | sort > " .
++         $lists_dir . '/' . $live->get_name . '.lst.names');
++
++    run_("chroot " . $live->get_system_root .
++           qq( sh -c "rpm -qa --qf '%{size}      \t%{name}\n' | sort -n" > ) .
++         $lists_dir . '/' . $live->get_name . '.lst.full');
++
++    run_("chroot " . $live->get_system_root .
++           qq( sh -c "urpmi_rpm-find-leaves | xargs rpm -q --qf '%{size}       \t%{name}\n' | sort -n" > ) .
++         $lists_dir . '/' . $live->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->get_name . '.langs';
++    output_p($langs_file, map { lang::l2name($_) . " (" . $_ . ")\n" } sort(@langs));
++}
++
++sub umount_external_filesystem {
++    my ($live) = @_;
++    my $mnt = $live->get_system_root . "/mnt/";
++    eval { fs::mount::umount("$mnt/$_") } foreach all($mnt);
++}
++
++sub expand_file_list {
++    my ($live, @files) = @_;
++    map {
++        $_->{path} ?
++          $_->{path} :
++          chomp_(cat_(glob(($_->{rooted} && $live->get_system_root) . $_->{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 { "$_\n" } 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 => $l->{type}, name => $name, files => [ expand_file_list($live, { source => $list }) ] };
++        } glob(($_->{rooted} && $live->get_system_root) . $_->{source});
++    } @{$live->{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->{loopbacks}{exclude}{files} || []});
++    my @modules_files = expand_file_list($live, @{$live->{loopbacks}{modules} || []});
++
++    foreach (grep { exists $loop_types{$_->{type}}{build} } @{$live->{mount}{dirs} || []}) {
++        local $_->{exclude} = [ @excluded_files, @modules_files ];
++        $loop_types{$_->{type}}{build}->($live, $_);
++    }
++
++    foreach my $module (list_loopback_modules($live)) {
++        my $copy_tree = $live->get_system_root . "/tmp/draklive/loop/$module->{name}";
++        eval { rm_rf($copy_tree) };
++        hardlink_filtered($live->get_system_root, $copy_tree, $module->{files});
++        my $loop = $loop_types{$module->{type}};
++        $loop->{build}->($live, { path => "$live->{prefix}{build}{modules}/$module->{name}", root => $copy_tree, exclude => \@excluded_files });
++        eval { rm_rf($copy_tree) };
++    }
++
++    if (@excluded_files) {
++        my $excluded_tree = $live->get_system_root . "/tmp/draklive/excluded/all";
++        eval { rm_rf($excluded_tree) };
++        hardlink_filtered($live->get_system_root, $excluded_tree, \@excluded_files);
++
++        foreach my $module (list_loopback_modules($live)) {
++            my $copy_tree = $live->get_system_root . "/tmp/draklive/excluded/$module->{name}";
++            eval { rm_rf($copy_tree) };
++            hardlink_filtered($excluded_tree, $copy_tree, $module->{files});
++            my $loop = $loop_types{$module->{type}};
++            $loop->{build}->($live, { path => "$live->{prefix}{build}{modules}/excluded-$module->{name}", root => $copy_tree });
++            eval { rm_rf($copy_tree) };
++        }
++
++        my $loop = $loop_types{$live->{loopbacks}{exclude}{type}};
++        $loop->{build}->($live, { path => "/excluded", root => $excluded_tree, exclude => \@modules_files });
++
++        eval { rm_rf($excluded_tree) };
++    }
++}
++
++sub list_selected_loopbacks {
++    my ($live) = @_;
++    my @pack = $live->{settings}{pack} ? @{$live->{packs}{$live->{settings}{pack}} || []} : ();
++    my @pack_modules = grep { member($_->{name}, @pack) } list_loopback_modules($live);
++    (map { $loop_types{$_->{type}}{is_loopback} && $_->{path} ? $_->{path} . $loop_types{$_->{type}}{extension} : () } @{$live->{mount}{dirs} || []}),
++    (map { $live->{prefix}{build}{modules} . '/' . $_->{name} . $loop_types{$_->{type}}{extension} } @pack_modules);
++}
++
++sub get_media_device {
++    my ($live, $opts) = @_;
++    return $opts->{device} if $opts->{device};
++    my $label = $live->{media}->get_media_label
++      or die "no device and no label";
++    my $device = chomp_(`readlink -f /dev/disk/by-label/$label`)
++      or die "unable to find device for /dev/disk/by-label/$label\n";
++    $device;
++}
++
++sub prepare_bootloader {
++    my ($live) = @_;
++    create_initrd($live);
++    create_bootloader($live) if !($live->{system}{skip_bootloader_config} || $live->{system}{skip_bootloader_install});
++}
++
++sub create_initrd {
++    my ($live) = @_;
++    my $root = $live->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->get_system_root;
++    my $kernel = $live->find_kernel->{version};
++    my $vmlinuz_long = '/boot/vmlinuz-' . $kernel;
++    -e $root . $vmlinuz_long or die "can not find kernel $kernel\n";
++
++    if ($live->{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 => $root }, '/usr/share/bootsplash/scripts/switch-themes', '-u');
++	#- grub-gfxmenu would be run by bootloader::write_grub from DrakX
++	run_({ root => $root }, '/usr/sbin/grub-gfxmenu', '--update-gfxmenu');
++	my $gfxmenu = $root . '/boot/gfxmenu';
++	if (-e $gfxmenu) {
++	    my $boot_dir = $live->get_builddir . $live->{prefix}{build}{boot};
++	    mkdir_p($boot_dir);
++	    cp_f($gfxmenu, $boot_dir);
++	} else {
++	    warn "no gfxmenu file\n";
++	}
++
++        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("mdvgfxbootXXXX", CLEANUP => 1);
++    chdir $tempdir;
++    !system("cpio -id < $bootlogo") or return;
++
++    # Make sure we include the en locale
++    push @locales, 'en';
++    my @kept_locales;
++    foreach my $file (glob "*.tr") {
++        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 "s/ /\\n/g" |cpio -o >$bootlogo));
++    chdir $cwd;
++
++    print "gfxboot locales: " . join(" ", @kept_locales) . "\n";
++    return @kept_locales;
++}
++
++#- forked from bootsplash::themes_read_sysconfig
++sub get_bootsplash_theme() {
++    my $sysconfig_file = "/etc/sysconfig/bootsplash";
++    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->get_builddir . $live->{prefix}{build}{boot} . '/syslinux';
++    mkdir_p($syslinux_dir);
++
++    if ($live->{system}{gfxboot}) {
++	my $default_gfxboot_theme = "Mandriva";
++	require bootsplash;
++	my $theme = do {
++            local $::prefix = $live->get_system_root;
++            get_bootsplash_theme();
++	};
++	print "copying $default_gfxboot_theme gfxboot theme\n";
++	cp_f(glob_($live->get_system_root . "/usr/share/gfxboot/themes/$default_gfxboot_theme/install/*"), $syslinux_dir);
++	if ($theme->{name} ne $default_gfxboot_theme) {
++	    print "copying $theme->{name} gfxboot theme\n";
++	    cp_f(glob_($live->get_system_root . "/usr/share/gfxboot/themes/$theme->{name}/*"), $syslinux_dir);
++	}
++	my $bootlogo = $syslinux_dir . '/bootlogo';
++	warn "unable to find gfxboot splash ($bootlogo)\n" if ! -f $bootlogo;
++	my @locales = remove_unneeded_bootlogo_locales($bootlogo, get_langs($live));
++	output_p($syslinux_dir . '/langs', join("\n", @locales) . "\n");
++	output_p($syslinux_dir . '/gfxboot.cfg', join("\n",
++                                                      "livecd=1",
++                                                      "mainmenu.pos=210,235",
++                                                      "mainmenu.bar.minwidth=400",
++                                                      "panel.f-key.fg=0x33358c",
++                                                      "",
++                                                  ));
++    }
++
++    output($live->get_builddir . $live->{prefix}{build}{boot} . '/help.msg',
++           pack("C*", 0x0E, 0x80, 0x03, 0x00, 0xC) . qq(
++Welcome to Mageia live!
++
++The command line can be used to specify kernel options.
++
++$live->{media}{title} <kernel options>
++
++));
++}
++
++sub create_media_bootloader {
++    my ($live) = @_;
++    cp_f($live->get_system_root . '/boot/vmlinuz-' . $live->find_kernel->{version}, $live->get_builddir . $live->{prefix}{build}{boot} . '/vmlinuz');
++    foreach my $boot ('', @{$live->{media}{extra_boot}}) {
++        my $opts = { boot => $boot };
++        output($live->get_builddir . $live->{prefix}{build}{boot} . get_syslinux_path($live->{media}, $opts),
++               build_syslinux_cfg($live, $live->{media}, $opts));
++    }
++}
++
++sub create_classical_bootloader {
++    my ($live) = @_;
++    my $initrd_prefix = "/initrd.img";
++    my $initrd = $live->get_system_root . $live->get_media_prefix('boot') . $initrd_prefix;
++    my $part_idx = $live->{media}->find_boot_partition_index;
++    my $oem_rescue_idx = $live->{media}->find_partition_index('OEM_RESCUE');
++    output_p($live->get_system_root . '/boot/grub/menu.lst', build_grub_cfg_raw($live, $live->{media}, -e $initrd && $initrd_prefix, { oem_rescue_idx => $oem_rescue_idx }, $part_idx));
++}
++
++sub create_tarball {
++    my ($live) = @_;
++    run_("tar", "cjf", get_disk_master_prefix($live) . ".tar.bz2", $live->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 "unable to set label for unsupported media type $type\n";
++    }
++}
++
++sub get_cdrom_master_path {
++    my ($live, $opts) = @_;
++    $live->get_builddir . $live->{prefix}{build}{dist} . '/' . $live->get_name . ($opts->{boot} && "-boot-$opts->{boot}") . '.iso';
++}
++
++sub get_cdrom_replicator_path {
++    my ($live) = @_;
++    get_disk_replicator_prefix($live) . ".iso";
++}
++
++sub create_cdrom_master {
++    my ($live, $opts) = @_;
++    my $label = $live->{media}->get_media_label or die "the source device must be described by a label\n";
++    my $dest;
++    unless ($opts->{onthefly}) {
++        $dest = get_cdrom_master_path($live, $opts);
++        mkdir_p(dirname($dest));
++    }
++    build_iso_image(
++        $live, $opts,
++        $dest,
++        $live->get_builddir . $live->{prefix}{build}{boot} . get_syslinux_path($live->{media}, $opts),
++        $label,
++        $live->get_media_prefix('boot', $opts->{boot}) . '=' . $live->get_builddir . $live->{prefix}{build}{boot},
++        if_(!$opts->{boot_only},
++            (map {
++                 $live->get_media_prefix('loopbacks', $opts->{boot}) . $_ .
++                 '=' .
++                 $live->get_builddir . $live->{prefix}{build}{loopbacks} . $_;
++             } list_selected_loopbacks($live)),
++             if_($live->{media}{files},
++                map { 
++                    $_ . '=' . $live->get_builddir . $live->{prefix}{build}{files} . '/' . $_;
++                } all($live->get_builddir . $live->{prefix}{build}{files})
++             ),
++        ),
++    );
++}
++
++sub build_iso_image {
++    my ($live, $opts, $dest, $isolinux_cfg, $label, @opts) = @_;
++
++    my $progress = MDV::Draklive::Progress->new(100, time());
++    my $in_progress;
++    autoflush STDOUT 1;
++    run_foreach(sub {
++                    if (/^\s*([0-9.]+)%\s*done,/) {
++                        $progress->{current} = int($1);
++                        $progress->show(time());
++                        $in_progress = 1;
++                    } else {
++                        print "\n" 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->get_builddir . $live->{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 "unable to run genisoimage\n";
++    autoflush STDOUT 0;
++    $progress->end;
++    if ($dest) {
++        my $dir = dirname($dest);
++        my $filename = basename($dest);
++        run_('isohybrid', '-fatfirst', $dest);
++        run_('mkcd', '>', '/dev/null', '2>', '/dev/null', '--addmd5', $dest);
++        run_({ chdir => $dir }, 'md5sum', '>', $dest . '.md5', $filename);
++        run_({ chdir => $dir }, 'sha1sum', '>', $dest . '.sha1', $filename);
++    }
++}
++
++sub get_disk_master_prefix {
++    my ($live) = @_;
++    $live->get_builddir . $live->{prefix}{build}{dist} . '/' . $live->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->{start} * $common::SECTORSIZE, '-s', $part->{size} * $common::SECTORSIZE, $loop, $hd->{file})
++      or die "unable to setup loop device";
++    return $loop;
++}
++
++sub get_harddisk_geometry {
++    my ($media) = @_;
++    my $geom = $media->{geom} || {
++        heads => 16,
++        sectors => 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 { $_->{size} } @{$media->{partitions}};
++    $required_sectors += $geom->{sectors}; # keep one more track
++    $geom->{cylinders} = POSIX::ceil($required_sectors / ($geom->{sectors} * $geom->{heads}));
++    my $total_sectors = $geom->{cylinders} * $geom->{heads} * $geom->{sectors};
++    my $hd = bless {
++        totalsectors => $total_sectors,
++        geom => $geom,
++        file => $dest,
++    }, 'partition_table::dos';
++}
++
++sub get_hd_from_file {
++    my ($media, $file) = @_;
++    my $hd = bless {
++        geom => get_harddisk_geometry($media),
++        file => $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->{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->{file} =~ m!^/dev/mmcblk! ? 'p' : '';
++    $part->{real_device} = -f $hd->{file} ? get_partition_loop($hd, $part) : ($hd->{file} . $ext . $part->{device});
++}
++
++sub allocate_master {
++    my ($live, $media, $opts) = @_;
++
++    $media->supplement_slash_size($opts->{slash_size}) if $opts->{slash_size};
++    my $hd = get_hd_from_layout($media, $opts->{device});
++
++    mkdir_p(dirname($opts->{device}));
++    MDV::Draklive::Utils::device_allocate_file($opts->{device}, $hd->{totalsectors} * $common::SECTORSIZE);
++}
++
++sub format_master {
++    my ($live, $media, $opts) = @_;
++
++    $media->supplement_slash_size($opts->{slash_size}) if $opts->{slash_size};
++
++    my $hd = get_hd_from_layout($media, $opts->{device});
++    partition_table::raw::zero_MBR($hd);
++
++    #- FIXME: maybe use fsedit::allocatePartitions to factorize even more?
++    foreach my $part (@{$media->{partitions}}) {
++        my $hole = find { fs::type::isEmpty($_) && $_->{size} >= $part->{size} } partition_table::get_normal_parts_and_holes($hd)
++          or die "not enough room for $part->{mntpoint}";
++        $part->{start} = $hole->{start};
++        fs::type::set_fs_type($part, $part->{fs_type});
++        partition_table::add($hd, $part, 'Primary');
++    }
++
++    print "writing partition table\n";
++    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->get_media_setting('inode_size');
++    foreach my $part (@{$media->{partitions}}) {
++        set_part_real_device($hd, $part);
++        MDV::Draklive::Utils::device_mkfs($part->{real_device}, $part->{fs_type}, $part->{device_LABEL}, $inode_size)
++            or die "unable to format $part->{real_device} in $hd->{file}\n";
++        devices::del_loop($part->{real_device}) if -f $hd->{file};
++    }
++}
++
++sub format_disk {
++    my ($live, $opts) = @_;
++    local $opts->{slash_size} = guess_disk_master_size($live);
++    format_master($live, $live->{media}, $opts);
++}
++
++sub guess_disk_master_size {
++    my ($live) = @_;
++
++    my $slash_size = @{$live->{mount}{dirs} || []} ?
++      (directory_usage($live->get_builddir . $live->{prefix}{build}{loopbacks}, 'apparent') +
++       directory_usage($live->get_builddir . $live->{prefix}{build}{boot}) +
++       directory_usage($live->get_builddir . $live->{prefix}{build}{files})
++      ) :
++      directory_usage($live->get_system_root);
++}
++
++sub create_disk_master {
++    my ($live, $opts) = @_;
++    local $opts->{slash_size} = guess_disk_master_size($live);
++    local $opts->{device} = get_disk_master_path($live);
++    allocate_master($live, $live->{media}, $opts);
++    format_master($live, $live->{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->{media}->get_boot_setting('create', $opts)) {
++        $create->($live, $opts);
++    } else {
++        warn "not implemented yet\n";
++    }
++}
++
++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), "blank=fast");
++}
++
++#- $opts:
++#-   media: alternate media
++sub format_device {
++    my ($live, $opts) = @_;
++
++    get_media_device($live, $opts) or die "no device defined in media configuration\n";
++    if (my $format = $live->{media}->get_boot_setting('format', $opts)) {
++        $format->($live, $opts);
++    } else {
++        warn "not implemented yet\n";
++    }
++}
++
++sub record_cdrom_path {
++    my ($live, $path, $opts) = @_;
++    my $device = get_media_device($live, $opts)
++      or die "no device defined in media configuration\n";
++
++    #- CD-Rom images can be hybrid, thus handle recording on both CD-Rom and disks
++    my $_device = basename(expand_symlinks($device));
++    my $sysfs_device = "/sys/block/$_device/capability";
++    #- GENHD_FL_CD is 8 (include/linux/genhd.h)
++    my $is_cdrom = !-e $sysfs_device || hex(cat_($sysfs_device)) & 8;
++
++    if ($is_cdrom) {
++        my $src = $opts->{onthefly} ? '-' : $path;
++        run_('wodim', '-v', 'dev=' . $device, $src);
++    } else {
++        run_('dd', if_(!$opts->{onthefly}, "if=$path"), "of=$device", "bs=2M");
++    }
++}
++
++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->{keep_files} ? () : '--delete';
++}
++
++sub install_grub_to_image {
++    my ($live, $media, $img, $opts) = @_;
++    my $media_boot = $live->get_media_prefix('boot', $opts->{boot});
++    my $grub_dir = "$media_boot/grub";
++    my $grub_script = $grub_dir . "/install.sh";
++    my $grub_src = first(glob_($live->get_system_root . "/lib/grub/*-mandriva"));
++    mkdir_p($live->{mnt} . $grub_dir);
++    cp_af(glob_("$grub_src/*"), $live->{mnt} . $grub_dir);
++
++    my $part_idx = $media->find_boot_partition_index;
++    my $grub_prefix = $media->find_partition_index('/boot') ? "/grub" : $grub_dir;
++
++    open(my $grub, "| /sbin/grub --batch --no-floppy");
++    # using disk loopback fails, have to use image path
++    print $grub <<EOF;
++device (hd0) $img
++root (hd0,$part_idx)
++setup --prefix=$grub_prefix (hd0)
++quit
++EOF
++    close($grub) or die "unable to run grub\n";
++
++    output($live->{mnt} . $grub_script, <<EOG);
++grub --device-map=$media_boot/grub/device.map --batch <<EOF
++root (hd0,$part_idx)
++setup --stage2=$media_boot/grub/stage2 (hd0)
++quit
++EOF
++EOG
++
++    chmod 0755, $live->{mnt} . $grub_script;
++}
++
++sub install_disk_bootloader {
++    my ($live, $media, $boot_device, $opts) = @_;
++
++    return if $live->{system}{skip_bootloader_install};
++
++    my $media_boot = $live->get_media_prefix('boot', $opts->{boot});
++    my $device = get_media_device($live, $opts);
++    my $bootloader = $media->get_boot_setting('bootloader', $opts);
++
++    member($bootloader, 'grub', 'syslinux') or die "no bootloader defined in media configuration\n";
++    if ($bootloader eq 'syslinux') {
++        cp_f($live->get_builddir . $_, $live->{mnt}) foreach map {
++            $live->{prefix}{boot} . $_;
++        } get_syslinux_path($media, $opts), $media->get_initrd_path, @syslinux_boot_files;
++    } elsif ($bootloader eq 'grub') {
++        if (need_media_specific_boot($live) || $opts->{force_bootloader_config}) {
++            #- FIXME: add get_grub_path (when building boot configuration files)
++            #         and get_bootloader_path (when copying)
++            mkdir_p($live->{mnt} . $media_boot . '/grub');
++            cp_f($live->get_builddir . $live->{prefix}{build}{boot} . '/gfxmenu', $live->{mnt} . $media_boot) if $live->{system}{gfxboot};
++            output_p($live->{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, "safe, slow and stupid" version of SYSLINUX, unless specified otherwise
++            run_('syslinux', if_(!$media->{fast_syslinux}, '-s'), $boot_device)
++              or die "unable to run syslinux on $device\n";
++        } elsif ($bootloader eq 'grub') {
++            install_grub_to_image($live, $media, $device, $opts);
++        }
++    } else {
++        warn "not running $bootloader on non block device $device\n";
++    }
++}
++
++sub record_usb_master {
++    my ($live, $opts) = @_;
++    my $media = $live->{media};
++    my $media_boot = $live->get_media_prefix('boot', $opts->{boot});
++    my $media_loopbacks = $live->get_media_prefix('loopbacks', $opts->{boot});
++
++    my $main_device = get_media_device($live, $opts)
++      or die "unable to find recording device (missing label? try with --device <device>)\n";
++
++    my $hd = get_hd_from_file($media, $main_device);
++    supplement_media_partitions($media, $hd);
++
++    my $slash_idx = $media->find_partition_index('/');
++    my $slash = $media->{partitions}[$slash_idx];
++    set_part_real_device($hd, $slash);
++
++    if (my $label = !$opts->{boot_only} && $media->get_media_label) {
++        set_device_label($slash->{real_device}, $media->get_media_setting('fs'), $label);
++    }
++
++    mkdir_p($live->{mnt});
++    run_('mount', $slash->{real_device}, $live->{mnt})
++      or die "unable to mount $slash->{real_device}\n";
++
++    rm_rf($live->{mnt} . $media_boot) if -e $live->{mnt} . $media_boot;
++    cp_af($live->get_builddir . $live->{prefix}{build}{boot}, $live->{mnt} . $media_boot);
++
++    install_disk_bootloader($live, $media, $slash->{real_device}, $opts);
++
++    do {
++        my $loopbacks_source = $live->get_builddir . $live->{prefix}{build}{loopbacks} . '/';
++        my $total = directory_usage($loopbacks_source);
++        my $list_file = tmpnam();
++        output_p($list_file, map { ".$_\n" } list_selected_loopbacks($live));
++        local $/ = "\r";
++        my $r = run_foreach(update_progress_rsync($live, $total),
++                            'rsync', '-vdP', '--inplace', '--files-from=' . $list_file, rsync_delete_options($opts),
++                            $loopbacks_source, $live->{mnt} . $media_loopbacks,
++        );
++        unlink $list_file;
++        if (!$r) {
++            run_('umount', $slash->{real_device});
++            maybe_umount_device($slash->{real_device});
++            devices::del_loop($slash->{real_device}) if -f $hd->{file};
++            die "unable to copy loopback files\n";
++        }
++
++        cp_af(glob_($live->get_builddir . $live->{prefix}{build}{files} . '/*'), $live->{mnt});
++    } unless $opts->{boot_only};
++
++    my @hidden_files = map { basename($_) } glob_($live->{mnt} . "/.*"), glob_($live->{mnt} . "/autorun.*");
++
++    run_('umount', $slash->{real_device});
++    maybe_umount_device($slash->{real_device});
++
++    if ($media->get_media_setting('fs') eq 'vfat') {
++        MDV::Draklive::Utils::mtools_run_('mattrib', '+h', '-i', $slash->{real_device}, '::' . $_) foreach @hidden_files;
++        MDV::Draklive::Utils::mtools_run_('mattrib', '+r', '+s', '-/', '-i', $slash->{real_device}, '::' . $_)
++          foreach $media_boot, $media_loopbacks;
++    }
++
++    devices::del_loop($slash->{real_device}) if -f $hd->{file};
++}
++
++sub record_harddisk_master {
++    my ($live, $opts) = @_;
++
++    my $media = $live->{media};
++    my $media_boot = $live->get_media_prefix('boot', $opts->{boot});
++    my $media_loopbacks = $live->get_media_prefix('loopbacks', $opts->{boot});
++
++    my $main_device = get_media_device($live, $opts)
++      or die "unable to find recording device (missing label? try with --device <device>)\n";
++
++    my $hd = get_hd_from_file($media, $main_device);
++    supplement_media_partitions($media, $hd);
++    my @partitions = grep { $_->{mntpoint} =~ m!^/! } @{$media->{partitions}};
++
++    mkdir_p($live->{mnt});
++    foreach my $part (sort { $a->{mntpoint} cmp $b->{mntpoint} } @partitions) {
++        set_part_real_device($hd, $part);
++        my $mnt = $live->{mnt} . $part->{mntpoint};
++        mkdir_p($mnt);
++        run_('mount', $part->{real_device}, $mnt)
++          or die "unable to mount $part->{real_device}\n";
++    }
++
++    my $r = 1;
++    do {
++        my $source = $live->get_system_root;
++        my $total = directory_usage($source);
++        local $/ = "\r";
++        $r = run_foreach(update_progress_rsync($live, $total), 'rsync', rsync_delete_options($opts), '-a', $source . '/', $live->{mnt})
++          or last;
++    } unless $opts->{boot_only};
++
++    my $boot_idx = $media->find_boot_partition_index;
++    my $boot_part = $media->{partitions}[$boot_idx];
++    install_disk_bootloader($live, $media, $boot_part->{real_device}, $opts);
++
++    foreach my $part (sort { $b->{mntpoint} cmp $a->{mntpoint} } @partitions) {
++        run_('umount', $part->{real_device});
++        maybe_umount_device($part->{real_device});
++        devices::del_loop($part->{real_device}) if -f $hd->{file};
++    }
++
++    $r or die "unable to copy system files\n";
++
++    record_oem_rescue($live, $opts) if $live->{oem_rescue};
++}
++
++#- $opts:
++#-   onthefly : if true, the record function must read from stdin
++sub record_master {
++    my ($live, $opts) = @_;
++
++    if (my $record = $live->{media}->get_boot_setting('record', $opts)) {
++        $record->($live, $opts);
++    } else {
++        warn "not implemented yet\n";
++    }
++}
++
++#- $opts:
++#-   onthefly : if true, the record function must read from stdin
++sub record_replicator {
++    my ($live, $opts) = @_;
++
++    my $replicator_media = $live->{replicator}{media} or die "no replicator media";
++    if (my $record_replicator = $replicator_media->get_boot_setting('record_replicator', $opts)) {
++        $record_replicator->($live, $opts);
++    } else {
++        warn "not implemented yet\n";
++    }
++}
++
++sub pipe_subs {
++    my ($writer, $reader) = @_;
++    my ($r, $w) = POSIX::pipe;
++    if (my $pid = fork()) {
++        POSIX::close($w) or die "couldn't close: $!\n";
++        my $stdin = POSIX::dup(0) or die "couldn't dup: $!\n";
++        POSIX::dup2($r, 0) or die "couldn't dup2: $!\n";
++        POSIX::close($r);
++        $reader->();
++        POSIX::close(0) or warn "writer exited $?\n";
++        POSIX::dup2($stdin, 0) or die "couldn't dup2: $!\n";
++        waitpid($pid, 0);
++    } else {
++        POSIX::close($r) or die "couldn't close: $!\n";
++        #- don't screw up reader
++        POSIX::dup2(POSIX::open('/dev/null', &POSIX::O_WRONLY), 2) or die "couldn't dup2: $!\n";
++        POSIX::dup2($w, 1) or die "couldn't dup2: $!\n";
++        POSIX::close($w);
++        $| = 1; #- autoflush write
++        exit !$writer->();
++    }
++}
++
++sub record_onthefly {
++    my ($live, $opts) = @_;
++
++    my $record = $live->{media}->get_storage_setting('record');
++    unless ($record) {
++        warn "not implemented yet\n";
++        return;
++    }
++    if (my $create = $live->{media}->get_storage_setting('record_needs_master') && $live->{media}->get_storage_setting('create')) {
++        local $opts->{onthefly} = 1;
++        #- pipe creation step to recording step
++        pipe_subs(sub { $create->($live, $opts) },
++                  sub { $record->($live, $opts) });
++    } else {
++        #- no creation step, record directly
++        $record->($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->{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 "already using loopback: skipping image creation\n";
++        return;
++    }
++    my $master = get_disk_master_path($live);
++    my $dest = get_disk_image_path($live);
++    mkdir_p(dirname($dest));
++
++    if ($live->{settings}{compression_method} eq 'gzip') {
++        run_('gzip', '>', $dest, '-f', '-c', '--fast', $master);
++    }
++    else {
++        run_('bzip2', '>', $dest, '-f', '-k', '-c', $master);
++    }
++}
++
++sub create_image {
++    my ($live) = @_;
++
++    if (my $create = $live->{media}->get_media_setting('image')) {
++        $create->($live);
++    } else {
++        warn "not implemented yet\n";
++    }
++}
++
++sub create_vm_image {
++    my ($live) = @_;
++
++    my $vm_type = $live->{settings}{vm_type};
++    if (!$vm_type) {
++        warn "no vm_type has been set in settings, skipping";
++        return;
++    }
++
++    if (!$live->{media}->get_media_setting('image')) {
++        warn "not implemented yet\n";
++        return;
++    }
++
++    my $master = get_disk_master_path($live);
++    if (!-f $master) {
++        warn "no master image, skipping\n";
++    }
++
++    my $vm_image = get_disk_master_prefix($live) . ".$vm_type";
++    run_("qemu-img", "convert", "-O", $vm_type, $master, $vm_image);
++}
++
++sub get_rescue_files {
++    my ($live, $rescue_opts, $extra_files) = @_;
++    my $media_boot = $live->get_media_prefix('boot');
++    my $initrd = $media_boot . $rescue_opts->{media}->get_initrd_path;
++    my @stage2_files = $live->{settings}{replicator_type} eq 'drakx' ? (
++        '/usr/lib/drakx-installer-stage2/install/stage2/mdkinst.sqfs',
++        $live->get_system_root . '/bin/dd',
++    ) : '/usr/lib/drakx-installer-rescue/rescue.sqfs';
++    (
++        '/usr/lib/drakx-installer-images/isolinux/alt0/vmlinuz' => $media_boot . '/vmlinuz',
++        '/usr/lib/drakx-installer-images/isolinux/alt0/all.rdz' => $initrd,
++        (map { $_ => '/install/stage2/' } @stage2_files),
++        @{$extra_files || []},
++        #- FIXME: factorize with copy_files_to to handle glob
++        (map { $live->{settings}{config_root} . '/' . $_->[0] => '/' . $_->[1] } @{$rescue_opts->{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 "unable to copy rescue files\n";
++    }
++}
++
++sub record_oem_rescue {
++    my ($live, $opts) = @_;
++
++    my $media = $live->{media};
++    my $oem_rescue_idx = $media->find_partition_index('OEM_RESCUE');
++    defined $oem_rescue_idx or die "no OEM_RESCUE partition";
++
++    my $main_device = get_media_device($live, $opts)
++      or die "unable to find recording device (missing label? try with --device <device>)\n";
++
++    my $hd = get_hd_from_file($media, $main_device);
++    supplement_media_partitions($media, $hd);
++
++    my $oem_rescue = $media->{partitions}[$oem_rescue_idx];
++    set_part_real_device($hd, $oem_rescue);
++
++    mkdir_p($live->{mnt});
++    run_('mount', $oem_rescue->{real_device}, $live->{mnt})
++      or die "unable to mount $oem_rescue->{real_device}\n";
++
++    record_rescue_files($live->{mnt}, $oem_rescue->{real_device}, [ get_rescue_files($live, $live->{oem_rescue}) ]);
++
++    run_('umount', $oem_rescue->{real_device});
++    maybe_umount_device($oem_rescue->{real_device});
++    devices::del_loop($oem_rescue->{real_device}) if -f $hd->{file};
++}
++
++sub get_disk_replicator_prefix {
++    my ($live) = @_;
++    $live->get_builddir . $live->{prefix}{build}{dist} . '/' . $live->get_name . '.rest';
++}
++
++sub get_disk_replicator_path {
++    my ($live) = @_;
++    get_disk_replicator_prefix($live) . ".img";
++}
++
++sub get_disk_replicator_files {
++    my ($live) = @_;
++    get_rescue_files($live, $live->{replicator}, [ get_disk_image_path($live) => '/images/' ]);
++}
++
++sub get_disk_replicator_images_list {
++    my ($live) = @_;
++    my $master_path = get_disk_master_path($live);
++    my $master_size = (stat($master_path))[7];
++    "EN,English," . basename(get_disk_image_path($live)) . ",on,$master_size\n";
++}
++
++sub create_usb_replicator {
++    my ($live, $opts) = @_;
++    my %files = get_disk_replicator_files($live);
++    local $opts->{slash_size} = fold_left { $::a + $::b } map { directory_usage($_, 'apparent') } keys(%files);
++    local $opts->{device} = get_disk_replicator_path($live);
++    allocate_master($live, $live->{replicator}{media}, $opts);
++    format_master($live, $live->{replicator}{media}, $opts);
++    record_usb_replicator($live, $opts);
++}
++
++sub record_usb_replicator {
++    my ($live, $opts) = @_;
++
++    my $media = $live->{replicator}{media};
++    my $media_boot = $live->get_media_prefix('boot');
++
++    $opts->{append} ||= $live->{replicator}{append};
++    my $main_device = get_media_device($live, $opts)
++      or die "unable to find recording device (missing label? try with --device <device>)\n";
++
++    my $hd = get_hd_from_file($media, $main_device);
++    supplement_media_partitions($media, $hd);
++
++    my $slash_idx = $media->find_partition_index('/');
++    my $slash = $media->{partitions}[$slash_idx];
++    set_part_real_device($hd, $slash);
++
++    mkdir_p($live->{mnt});
++    run_('mount', $slash->{real_device}, $live->{mnt})
++      or die "unable to mount $slash->{real_device}\n";
++    rm_rf($live->{mnt} . $media_boot) if -e $live->{mnt} . $media_boot;
++    {
++        local $opts->{force_bootloader_config} = 1;
++        install_disk_bootloader($live, $media, $slash->{real_device}, $opts);
++    }
++
++    record_rescue_files($live->{mnt}, $slash->{real_device}, [ get_disk_replicator_files($live) ]);
++    output_p($live->{mnt} . "/images/list", get_disk_replicator_images_list($live));
++
++    run_('umount', $slash->{real_device});
++    maybe_umount_device($slash->{real_device});
++    devices::del_loop($slash->{real_device}) if -f $hd->{file};
++}
++
++sub create_cdrom_replicator {
++    my ($live, $opts) = @_;
++
++    # FIXME: factorize with usb replicator, write in builddir/replicator/images-list
++    my $images_list = "/tmp/images-replicator.list";
++    output_p($images_list, get_disk_replicator_images_list($live));
++
++    # FIXME: write in builddir/replicator/syslinux.cfg
++    my $syslinux_cfg = "/tmp/syslinux-replicator.cfg";
++    local $opts->{append} = $live->{replicator}{append};
++    output_p($syslinux_cfg, build_syslinux_cfg($live, $live->{replicator}{media}, $opts));
++
++    my $label = $live->{replicator}{media}->get_media_label or die "the source device must be described by a label\n";
++    my $dest = get_cdrom_replicator_path($live);
++    build_iso_image(
++        $live, $opts,
++        $dest,
++        $syslinux_cfg,
++        $label,
++        $live->get_media_prefix('boot', $opts->{boot}) . '/syslinux=' . $live->get_builddir . $live->{prefix}{build}{boot} . '/syslinux',
++        "/images/list=$images_list",
++        (map {
++            my ($src, $dest) = @$_;
++            my $dest_file = $dest =~ m!/$! ? $dest . basename($src) : $dest;
++            $dest_file . "=" . $src;
++        } group_by2(get_disk_replicator_files($live))),
++    );
++}
++
++sub create_replicator {
++    my ($live, $opts) = @_;
++
++    if (my $create = $live->{replicator}{media} && $live->{replicator}{media}->get_media_setting('replicator')) {
++        $create->($live, $opts);
++    } else {
++        warn "not implemented yet\n";
++    }
++}
++
++sub update_progress_rsync {
++    my ($live, $total) = @_;
++    my $all_files = 0;
++    my $current_file = 0;
++    $live->{update_progress} ? sub {
++        if (/^\s*(\d+)\s+\d+%\s+/) {
++            $current_file = $1;
++            $live->{update_progress}->(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->{system}{vga_mode} = 788 if !defined $live->{system}{vga_mode};
++    my $live_media = $live->{prefix}{live}{mnt} . $live->{prefix}{media}{mnt};
++
++    require interactive;
++    require wizards;
++    my $in = 'interactive'->vnew('su');
++    my (@available_storage, @available_devices);
++    my ($storage, $device, $format);
++    my %source_types = (
++        live => N("Use current live system"),
++        file => N("Select a file"),
++    );
++    my ($source_type, $source_path);
++    my $media_boot = $live->get_media_prefix('boot');
++    my $media_loopbacks = $live->get_media_prefix('loopbacks');
++    my $source_is_mounted = sub { -d ($live->{settings}{builddir} . $media_boot) };
++    my $umount_source = sub {
++        if ($source_type ne 'live' && $source_is_mounted->()) {
++            run_('umount', $live->{settings}{builddir});
++            rmdir($live->{settings}{builddir});
++        }
++    };
++    my $w;
++    $w = wizards->new({
++        name => N("Live system copy wizard"),
++        pages => {
++            welcome => {
++                name => N("Welcome to the live system copy wizard"),
++                no_back => 1,
++                next => 'source',
++            },
++            source => {
++                name => N("Which live system do you want to copy?"),
++                data => [ if_(-d ($live_media . $media_loopbacks),
++                              { type => 'list', val => \$source_type,
++                                list => sort(keys(%source_types)),
++                                format => sub { $source_types{$_[0]} } }),
++                          { type => 'file', val => \$source_path,
++                            disabled => sub { $source_type eq 'live' } } ],
++                pre => $umount_source,
++                complete => sub {
++                    if ($source_type eq 'live') {
++                        $live->{settings}{builddir} = $live_media;
++                    } else {
++                        $live->{settings}{builddir} = File::Temp::tempdir();
++                        if (!run_('mount', '-o', 'loop', $source_path, $live->{settings}{builddir})) {
++                            $in->ask_warn(N("Error"), N("Unable to use selected file"));
++                            return 1;
++                        }
++                    }
++                    0;
++                },
++                post => sub {
++                    my $boot = $live->{settings}{builddir} . $media_boot;
++                    @available_storage = sort(grep { -d "$boot/$_" && exists $MDV::Draklive::Storage::storage_types{$_}{detect} } all($boot));
++                    if (@available_storage == 1) {
++                        $storage = $available_storage[0];
++                        return 'device';
++                    }
++                    return 'storage';
++                }
++            },
++            storage => {
++                name => N("Please select the medium type"),
++                data => [ { type => 'list', allow_empty_list => 1,
++                            val => \$storage, list => \@available_storage } ],
++                next => 'device',
++            },
++            device => {
++                name => N("Please select the device that will contain the new live system"),
++                pre => sub {
++                    my %devices = map { $_->{device} => $_ } $MDV::Draklive::Storage::storage_types{$storage}{detect}->();
++                    $_->{formatted_name} = $_->{usb_description} || $_->{info} || $_->{device} foreach values %devices;
++                    @available_devices = ();
++                    require fs::proc_partitions;
++                    foreach (fs::proc_partitions::read([ values %devices ])) {
++                        if ($_->{rootDevice} && exists $devices{$_->{rootDevice}}) {
++                            my $description = $devices{$_->{rootDevice}}{usb_description} || $devices{$_->{rootDevice}}{info};
++                            $_->{formatted_name} = $description ? "$description ($_->{device})" : $_->{device};
++                            push @available_devices, $_;
++                        }
++                    }
++                    delete $devices{$_->{rootDevice}} foreach @available_devices;
++                    unshift @available_devices, map { $devices{$_} } sort keys %devices;
++                    undef $device;
++                },
++                data => [ { type => 'list', allow_empty_list => 1,
++                            val => \$device, , list => \@available_devices,
++                            format => sub { $_[0]{formatted_name} } },
++                          { text => N("Format selected device"), val => \$format, type => 'bool' } ],
++                complete => sub {
++                    return 0 if defined $device;
++                    $in->ask_warn(N("Error"), N("You must select a device!"));
++                    1;
++                },
++                post => sub {
++                    (my $_wait, $live->{update_progress}) = $in->wait_message_with_progress_bar;
++                    do {
++                        local $::isInstall = 1; # quick hack to embed the wait message
++                        $live->{update_progress}->(N("Copying in progress"));
++                    };
++                    eval {
++                        my $opts = { media => { storage => $storage, device => '/dev/' . $device->{device} } };
++                        format_device($live, $opts) if $format;
++                        record_onthefly($live, $opts);
++                    };
++                    delete $live->{update_progress};
++                    if (my $error = $@) {
++                        $in->ask_warn(N("Error"), $error);
++                        $w->{pages}{device}{end} = 1;
++                    }
++                    return "end";
++                },
++            },
++            end => {
++                name => N("Congratulations") . "\n\n" . N("Your live system is now copied."),
++                no_back => 1,
++                end => 1,
++            },
++        }
++    });
++    $w->process($in);
++    $umount_source->();
++    $in->exit;
++}
++
++sub clean {
++    my ($live) = @_;
++    # umount filesystem in the live before cleaning
++    umount_external_filesystem($live);
++    rm_rf($_) foreach grep { -e $_ } $live->get_builddir, $live->get_system_root;
++}
++
++my @actions = (
++    { name => 'dump-config', do => \&MDV::Draklive::Config::dump_config },
++    { name => 'clean', do => \&clean },
++    { name => 'install', do => \&install_system },
++    { name => 'post-install', do => \&post_install_system },
++    { name => 'initrd', do => \&create_initrd },
++    { name => 'boot', do => \&prepare_bootloader },
++    { name => 'tarball', do => \&create_tarball },
++    { name => 'loop', do => \&create_loopback_files },
++    { name => 'master', do => \&create_master },
++    { name => 'image', do => \&create_image },
++    { name => 'vm-image', do => \&create_vm_image },
++    { name => 'replicator', do => \&create_replicator },
++    { name => 'format', do => \&format_device },
++    { name => 'record', do => \&record_master },
++    { name => 'record-onthefly', do => \&record_onthefly },
++    { name => 'record-replicator', do => \&record_replicator },
++);
++my @all = qw(install boot loop master image vm-image replicator);
++
++die "you must be root to run this program\n" if $>;
++
++my $live_object = 'MDV::Draklive::Live'->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(
++    "help" => sub { Pod::Usage::pod2usage('-verbose' => 1) },
++    "copy-wizard" => \$live_object->{copy_wizard},
++    "keep-files" => \$opts{keep_files},
++    "boot-only" => \$opts{boot_only},
++    "boot-image=s" => sub { $opts{boot} = $_[1]; $opts{boot_only} = 1 },
++    "all" => sub { $_->{to_run} = 1 foreach grep { member($_->{name}, @all) } @actions },
++    (map { $_->{name} => \$_->{to_run} } @actions),
++    "device=s" => sub { $opts{device} = $_[1] },
++    "all-regions" => sub { $live_object->{all_regions} = 1 },
++    "config-root=s" => \$config_root,
++    "config=s" => \$config_path,
++    "settings=s" => \$settings_path,
++    "define=s" => \%{$live_object->{settings}},
++) or Pod::Usage::pod2usage();
++
++require standalone;
++if ($live_object->{copy_wizard}) {
++    copy_wizard($live_object);
++} else {
++    every { !$_->{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->{all_regions} ? sort(keys %{$live_object->{regions}}) : $live_object->{settings}{region}) {
++        $region and print qq(=== proceeding with region "$region"\n);
++        $live_object->{settings}{region} = $region;
++        foreach (grep { $_->{to_run} } @actions) {
++            print qq(* entering step "$_->{name}"\n);
++            $_->{do}->($live_object, \%opts);
++            print qq(* step "$_->{name}" 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 <dev>    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 <dir>
++                     root directory containing config files and additionnal files
++                     defaults to current directory if it contains a configuration file
++                     else, "/etc/draklive" is used
++
++   --config <file>   use this configuration file as live description
++                     defaults to "config/live.cfg"
++
++   --settings <file> use this file as live settings (key=value format)
++                     defaults to "config/settings.cfg"
++   --define key=value
++                     set setting "key" to "value"
++                     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 <method>
++                     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<--config>
++
++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 => '/mnt/ken/2006.0',
++        root => '/chroot/live-move',
++    },
++    system => {
++        kernel => '2.6.12-12mdk-i586-up-1GB',
++        auto_install => 'config/auto_inst.cfg.pl',
++        patch_install => 'config/patch-2006-live.pl',
++        rpmsrate => 'config/rpmsrate',
++        rpms => [
++             'rpms/unionfs-kernel-2.6.12-12mdk-i586-up-1GB-1.1.1.1.20051124.1mdk-1mdk.i586.rpm'
++        ],
++        patches => [
++             'patches/halt.loopfs.patch',
++        ],
++        vga_mode => 788,
++        no_initrd => 0,
++    },
++    media => {
++        storage => 'cdrom',
++    },
++    mount => $predefined{mounts}{squash_union}
++  };
++
++=item B<--settings>
++
++Makes draklive load the next argument as a file in key=value format
++into the $live->{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<draklive> builds a live distribution according to a
++configuration file, creates a master image,
++and optionally installs it on a device.
++
++See L<http://qa.mandriva.com/twiki/bin/view/Main/DrakLive>
++
++=head1 AUTHOR
++
++Olivier Blin <oblin at mandriva.com>
++
++=cut
+
+
+Property changes on: draklive/trunk/draklive
+___________________________________________________________________
+Added: svn:executable
+   + *
+
+Added: draklive/trunk/draklive-copy-wizard.desktop
+===================================================================
+--- 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
+
+Added: draklive/trunk/kmod/readlog.c
+===================================================================
+--- 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 <linux/init.h>
++#include <linux/module.h>
++
++#include <linux/kernel.h>
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/sched.h>
++#include <linux/syscalls.h>
++#include <linux/time.h>
++
++#include <asm/unistd.h>
++
++#include <asm/current.h>
++#include <linux/debugfs.h>
++#include <linux/seq_file.h>
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Olivier Blin <blino at mandriva.com>");
++
++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(&files_mutex);
++    list_for_each(p, &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)->s_list.next;
++    (*pos)++;
++    return p == &bp.s_list ? NULL : list_entry(p, struct opened_file, s_list);
++}
++
++static void profile_seq_stop(struct seq_file *file, void *v)
++{
++    up(&files_mutex);
++}
++
++static int profile_seq_show(struct seq_file *file, void *v)
++{
++    seq_printf(file, ((struct opened_file *)v)->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, &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) & 0xfffffffc);
++	 p < (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->name = kmalloc(strlen(filename) + 1, GFP_KERNEL);
++    if (f->name == NULL)
++	return;
++    strcpy(f->name, filename);
++
++    INIT_LIST_HEAD(&f->s_list);
++
++    printk(KERN_INFO "locking while adding: %s\n", filename);
++
++    down(&files_mutex);
++    list_add_tail(&f->s_list, &bp.s_list);
++    up(&files_mutex);
++
++    printk(KERN_INFO "unlocking after adding: %s\n", 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 "opening fd %ld for %s\n", fd, filename);
++
++    if(fd > 0 && current) {
++        f = current->files->fd_array[fd];
++        if(f && f->f_dentry && f->f_vfsmnt) {
++            char tmpname[PATH_MAX];
++            char *name = d_path(f->f_dentry, f->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(&tv);
++
++    if(current)
++        f = current->files->fd_array[fd];
++
++    printk(KERN_DEBUG "READ: f: %p\n", f);
++
++
++    if(f)
++        offset = f->f_pos;
++
++    if (f)
++        printk(KERN_DEBUG "READ: d_entry: %p, vfsmnt: %p\n", f->f_dentry, f->f_vfsmnt);
++
++    if(f && f->f_dentry && f->f_vfsmnt) {
++        printk(KERN_DEBUG "READ: d_path\n");
++        name = d_path(f->f_dentry, f->f_vfsmnt, tmpname, sizeof(tmpname) - 1);
++        if (name)
++            addfilename(name);
++    }
++
++    printk(KERN_DEBUG "READ: %lu.%lu (%s/%d) %Lu %s\n",
++           tv.tv_sec, tv.tv_usec,
++           current ? current->comm : "?",
++           current ? current->pid : 0,
++           offset,
++           name ? name : "<no dentry>"
++        );
++
++	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 "Found sys_call_table at %p\n", 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("dmc", NULL);
++    if (IS_ERR(dbg_dir)) {
++	printk(KERN_NOTICE ": debugfs is not available\n");
++	return -ENODEV;
++    }
++    if (dbg_dir == NULL) {
++	printk(KERN_NOTICE ": unable to create usbmon directory\n");
++	return -ENODEV;
++    }
++
++    dbg_file = debugfs_create_file("bp", 0600, dbg_dir, NULL, &profile_fops);
++    if (dbg_file == NULL) {
++	debugfs_remove(dbg_dir);
++	return -ENODEV;
++    }
++
++    INIT_LIST_HEAD(&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 "sys_call_table restored\n");
++
++}
++
++module_init(readlog_init);
++module_exit(readlog_exit);
+
+
+Property changes on: draklive/trunk/kmod/readlog.c
+___________________________________________________________________
+Added: svn:eol-style
+   + native
+
+Added: draklive/trunk/lib/MDV/Draklive/Config.pm
+===================================================================
+--- 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 && -e getcwd() . '/' . $config_path) {
++        $config_root = getcwd();
++    }
++    print "using $config_root as directory root\n";
++
++    add2hash($live->{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 "unable to load $config_path: $@\n";
++        put_in_hash($live, $cfg);
++        print "loaded $config_path as config file\n";
++    }
++    $live->{settings}{config_root} = $config_root;
++}
++
++sub check_config {
++    my ($live) = @_;
++    unless (keys(%$live)) {
++        warn "no live definition\n";
++        Pod::Usage::pod2usage();
++    }
++    #- check for minimum requirements
++    ref $live->{media} && $live->{media}{storage} or die "no media storage definition\n";
++    ref $live->{system} or die "no system definition\n";
++}
++
++sub complete_config {
++    my ($live) = @_;
++
++    my $default_prefix = {
++        build => {
++            boot => '/boot',
++            files => '/files',
++            dist => '/dist',
++            initrd => '/initrd',
++            loopbacks => '/loopbacks',
++            modules => '/modules',
++            scripts => '/scripts',
++        },
++        media => {
++            boot => '/boot',
++            hidden_boot => '/.boot',
++            loopbacks => '/loopbacks',
++            hidden_loopbacks => '/.loopbacks',
++            mnt => '/media',
++        },
++        live => {
++            mnt => '/live',
++        },
++    };
++
++    #- set unsupplied config dirs
++    add2hash($live->{prefix}{$_} ||= {}, $default_prefix->{$_}) foreach keys %$default_prefix;
++
++    $live->{settings}{builddir} ||= '/var/lib/draklive/build';
++    $live->{settings}{chroot} ||= '/var/lib/draklive/chroot';
++
++    $live->{settings}{arch} ||= chomp_(`rpm --eval '%{_target_cpu}'`);
++    $live->{media}{title} ||= "live";
++
++    $_ = MDV::Draklive::Media::new($_) foreach (
++        $live->{media},
++        ($live->{replicator} ? $live->{replicator}{media} : ()),
++        ($live->{oem_rescue} ? $live->{oem_rescue}{media} : ()),
++    );
++
++    mkdir_p($live->get_builddir);
++    mkdir_p($live->get_system_root);
++    $live->{mnt} ||= $live->get_builddir . "/mnt";
++}
++
++sub dump_config {
++    my ($live) = @_;
++    use Data::Dumper;
++    print Data::Dumper->Dump([ $live ], [ "live" ]);
++}
++
++1;
+
+Added: draklive/trunk/lib/MDV/Draklive/CustomMedia.pm
+===================================================================
+--- 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 => 'nfs',
++        modules => 'nfs',
++        extra_modules => [ $module ],
++        pre => "ifconfig eth0 $client up",
++        source => $path,
++    );
++}
++
++1;
+
+Added: draklive/trunk/lib/MDV/Draklive/Initrd.pm
+===================================================================
+--- 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 => 'EXT3_FS',
++    sd_mod => 'BLK_DEV_SD',
++);
++
++sub require_list_modules_chroot {
++    my ($live) = @_;
++    my $chroot_list_modules = cat_($live->get_system_root . "/usr/lib/libDrakX/list_modules.pm");
++    $chroot_list_modules =~ s/^package list_modules;\B/package list_modules_chroot;/;
++    my $tmp_list_modules = $live->get_system_root . "/tmp/list_modules_chroot.pm";
++    output_p($tmp_list_modules, $chroot_list_modules);
++    require $tmp_list_modules;
++    unlink $tmp_list_modules;
++}
++
++sub nls_modules {
++    my ($live) = @_;
++    my $fs = $live->{media}->get_media_setting('fs');
++    if_($fs eq 'vfat', 'nls_cp437'), #- default FAT codepage
++    if_($fs !~ /^ext/, map { "nls_$_" } (map { "iso8859_$_" } 1..7, 9, 13..15), 'utf8');
++}
++
++sub create_media_initrd {
++    my ($live) = @_;
++    create_initrd_for_media($live, $live->{media});
++    cp_f($live->get_builddir . $live->{prefix}{build}{boot} . $live->{media}->get_initrd_path,
++         $live->{copy_initrd}) if $live->{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 "unable to copy $file from system chroot\n";
++    }
++}
++
++sub inst_initrd_dso_deps {
++    my ($root, $initrd_tree, $dso) = @_;
++    foreach my $file (`chroot $root ldd $dso | awk '/\\// {if(\$2 == "=>") {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 "unable to copy $filename from system chroot\n";
++    }
++}
++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->get_builddir . $live->{prefix}{build}{boot} . $media->get_initrd_path;
++    create_media_specific_initrd($live, $media, $live->get_system_root, $initrd, $live->find_kernel->{version});
++}
++
++sub create_media_specific_initrd {
++    my ($live, $media, $root, $initrd, $kernel) = @_;
++
++    require_list_modules_chroot($live);
++
++    my $lib_prefix = $live->get_lib_prefix;
++    my $initrd_tree = $live->get_builddir . $live->{prefix}{build}{initrd} . '/' . $media->{storage};
++    rm_rf($initrd_tree) if -e $initrd_tree;
++
++    mkdir_p($initrd_tree . $_) foreach
++      qw(/bin /dev /proc /sys /tmp),
++      map { $live->{prefix}{live}{mnt} . $_ }
++        $live->{prefix}{media}{mnt},
++        $live->{mount}{root},
++        map { $_->{mountpoint} } grep { !$loop_types{$_->{type}}{skip_mkdir} } @{$live->{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->get_media_setting('rereadpt');
++    inst_initrd_bin($root, $initrd_tree, '/usr/bin/strace')
++      if $live->{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 . "/bin/$_") foreach @l;
++
++    my $fs = $media->get_media_setting('fs');
++    my @used_loop_types = uniq(map { $_->{type} } @{$live->{mount}{dirs}});
++    inst_initrd_bin($root, $initrd_tree, $_) foreach
++      MDV::Draklive::StorageFS::get_files($fs),
++      (map { @{$loop_types{$_} && $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->get_media_setting('rereadpt');
++    require devices;
++    devices::make($initrd_tree . "/dev/$_") foreach
++        if_($rrpt_dev, $rrpt_dev),
++        qw(console initrd null ram systty tty tty1),
++        (map { "tty$_" } 0..8),
++        (map { "loop$_" } 0 .. $loop_nb);
++    syscall_('mknod', $initrd_tree . "/dev/ptmx", c::S_IFCHR(), makedev(5, 2)) or die "mknod failed (dev $_): $!";
++    syscall_('mknod', $initrd_tree . "/dev/fb", c::S_IFCHR(), makedev(29, 0)) or die "mknod failed (dev $_): $!";
++    #- pre-create devfsd compatibility loop devices (since busybox is still built with devfsd support)
++    mkdir_p($initrd_tree . "/dev/loop");
++    cp_af($initrd_tree . "/dev/loop$_", $initrd_tree . "/dev/loop/$_") foreach 0 .. $loop_nb;
++
++    print "using kernel $kernel\n";
++    my $kernel_root = "/lib/modules/" . $kernel;
++    list_modules::load_dependencies($kernel_root . "/modules.dep", $root);
++
++    my ($storage_modules, $skipped) = partition { list_modules::modname2filename($_) }
++      uniq(map { modules::cond_mapping_24_26($_) } list_modules_chroot::category2modules($media->get_media_setting('modules')));
++    my ($extra_modules, $extra_missing) = partition { list_modules::modname2filename($_) }
++      list_modules_chroot::category2modules($media->get_media_setting('media_modules')),
++      nls_modules($live),
++      $media->get_media_fs_module,
++      @{$media->get_media_setting('extra_modules') || []},
++      (map { MDV::Draklive::Loopback::get_loop_modules($live, $_) } uniq(map { $_->{type} } @{$live->{mount}{dirs} || []})),
++      ($live->{mount}{overlay} ? @{$MDV::Draklive::Overlay::overlay{$live->{mount}{overlay}}{modules} || []} : ());
++
++    my @additional_modules = map { if_(m!([^/]+)\.ko(?:\.gz)?!, list_modules::filename2modname($1)) } @{$live->{system}{additional_modules}};
++    @$extra_modules = difference2($extra_modules, \@additional_modules);
++    if (@{$live->{system}{exclude_modules} || []}) {
++        print STDERR "excluding modules: " . join(' ', @{$live->{system}{exclude_modules}}) . "\n";
++        @$_ = difference2($_, $live->{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 . "/boot/config-" . $kernel);
++        my @really_missing = grep { !member($module_to_config{$_}, @config) } @missing;
++        @really_missing and die "missing mandatory modules:\n" . join("\n", @really_missing, '');
++    }
++
++    mkdir_p($initrd_tree . $kernel_root . "/kernel");
++    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->{system}{additional_modules}}) {
++        my $destdir = $initrd_tree . $kernel_root . "/kernel";
++        if ($f =~ /.gz$/) {
++            cp_f($live->{settings}{config_root} . '/' . $f, $destdir);
++        } else {
++            my $m = basename($f);
++            run_program::run('gzip', '>', "$destdir/$m.gz", '-c', $live->{settings}{config_root} . '/' . $f);
++        }
++    }
++    run_('depmod', '-b', $initrd_tree, $kernel);
++
++    mkdir_p($initrd_tree . "/etc/blkid"); #- for nash and showlabels cache
++    mkdir_p($initrd_tree . "/lib/module-init-tools");
++    cp_f($root . "/lib/module-init-tools/ldetect-lst-modules.alias", $initrd_tree . "/lib/module-init-tools");
++    mkdir_p($initrd_tree . "/usr/share/ldetect-lst");
++    cp_f($root . "/usr/share/pci.ids", $initrd_tree . "/usr/share");
++    cp_f($root . "/usr/share/ldetect-lst/" . $_, $initrd_tree . "/usr/share/ldetect-lst")
++      foreach qw(fallback-modules.alias pcitable.gz usbtable.gz);
++
++    @$skipped and print STDERR "skipped modules: " . join(' ', sort(@$skipped)) . "\n";
++
++    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 "Compressing initrd\n";
++    compress_initrd_tree($live, $initrd_tree, $initrd);
++    add_splash($live, $initrd);
++}
++
++sub create_initrd_scriptlet {
++    my ($live, $media, @modules) = @_;
++    my $target = $live->{prefix}{live}{mnt} . ($live->{mount}{root} || $live->{prefix}{media}{mnt});
++    my $pre = $media->get_media_setting('pre');
++    my $fs = $media->get_media_setting('fs');
++    my $rrpt_dev = $media->get_media_setting('rereadpt');
++    my $debug_shell = "sh -c 'if grep -q initrd_debug /proc/cmdline; then plymouth --quit; exec sh </dev/console >/dev/console 2>/dev/console; fi'";
++    my ($mount_first, $mount_last) = partition { !$loop_types{$_->{type}}{delay_mount} }
++      grep { exists $loop_types{$_->{type}}{mount} } @{$live->{mount}{dirs} || []};
++    my $initrdroot = "/initrd";
++
++    output_with_perm($live->get_builddir . $live->{prefix}{build}{initrd} . '/' . $media->{storage} . '/linuxrc', 0755,
++                     join("\n",
++                          "#!/bin/nash",
++                          #- required for labels and ps
++                          "nash-mount -t proc /proc /proc",
++                          #- required for cdrom labels
++                          "nash-mount -t sysfs /sys /sys",
++			  "/bin/plymouthd",
++			  "plymouth --show-splash",
++                          (map { join(" ", "probe-modules", list_modules::filename2modname($_), grep { $_ } $live->{system}{module_options}{$_}) } @modules),
++                          "probe-modules --$media->{storage}",
++                          if_($rrpt_dev,
++                              "echo *** Waiting for new partitions on device ${rrpt_dev} ***",
++                              "sh -c 'while ! ls /sys/block/${rrpt_dev}/${rrpt_dev}* >/dev/null 2>&1; do sleep 3; blockdev --rereadpt /dev/${rrpt_dev} >/dev/null 2>&1; done'"),
++                          $debug_shell,
++                          if_($pre, deref_array($pre)),
++                          "showlabels --removable",
++                          MDV::Draklive::StorageFS::get_mount($fs)->($live, $media),
++                          (map { $loop_types{$_->{type}}{mount}->($live, $_) } @$mount_first, @$mount_last),
++                          ($live->{mount}{overlay} ? $MDV::Draklive::Overlay::overlay{$live->{mount}{overlay}}{mount}->($live) : ()),
++                          if_($live->{system}{initrd_pre_pivot}, deref_array($live->{system}{initrd_pre_pivot})),
++			  "plymouth --newroot=$target",
++                          "echo 0x0100 > /proc/sys/kernel/real-root-dev",
++                          "umount /sys",
++                          "sh -c 'umount /proc/bus/usb 2>/dev/null'",
++                          "umount /proc",
++			  "pivot_root $target $target$initrdroot",
++                          if_($live->{mount}{root}, "sh -c 'rmdir $initrdroot$live->{prefix}{live}{mnt}$live->{mount}{root}'"),
++                          (map { $loop_types{$_->{type}}{pivot_clean}->($live, $_, $initrdroot) } grep { $loop_types{$_->{type}}{pivot_clean} } @{$live->{mount}{dirs} || []}),
++                          "sh -c 'cd $initrdroot$live->{prefix}{live}{mnt}; for i in `ls -1`; do [ -d \$i ] || continue; mkdir -p $live->{prefix}{live}{mnt}/\$i; mount -n --move \$i $live->{prefix}{live}{mnt}/\$i; rmdir \$i; done'",
++                          "rmdir $initrdroot$live->{prefix}{live}{mnt}",
++                          "nash-mount -o mode=0755 -t tmpfs /dev /dev",
++                          "sh -c 'rm -rf /dev/loop'", #- not needed after initrd
++                          "sh -c 'mv $initrdroot/dev/* /dev/'",
++                          if_($live->{system}{initrd_post}, deref_array($live->{system}{initrd_post})),
++                          ""));
++}
++
++sub compress_initrd_tree {
++    my ($live, $initrd_tree, $initrd) = @_;
++
++    my $size = chomp_(run_program::get_stdout("du -ks $initrd_tree | awk '{print \$1}'"));
++    my $inodes = chomp_(run_program::get_stdout("find $initrd_tree | wc -l")) + 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', "of=$initrd", 'bs=1k', "count=$initrd_size");
++    run_('mke2fs', '-q', '-m', 0, '-F', '-N', $inodes, '-s', 1, $initrd);
++    mkdir_p($live->{mnt});
++    run_('mount', '-o', 'loop', '-t', 'ext2', $initrd, $live->{mnt});
++    cp_af(glob("$initrd_tree/*"), $live->{mnt});
++    rm_rf($live->{mnt} . "/lost+found");
++    my $left = chomp_(run_program::get_stdout("df -Pk $live->{mnt} | tail -n 1 | awk '{ print \$4 }'"));
++    run_('umount', $live->{mnt});
++    $left < 200 and die "not enough room to create initrd (only ${left}K left)\n";
++    run_('gzip', '-f', '-9', $initrd);
++}
++
++sub add_splash {
++    my ($live, $initrd) = @_;
++    if ($live->{system}{vga_mode} && $live->{system}{splash} ne 'no') {
++        my $chroot_initrd;
++        if ($initrd !~ m,^/boot/,) {
++            $chroot_initrd = '/tmp/initrd.gz';
++            cp_f($initrd, $live->get_system_root . $chroot_initrd);
++        } else {
++            $chroot_initrd = $initrd;
++        }
++
++        {
++            local $::prefix = $live->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->{system}{vga_mode});
++        }
++
++        if ($chroot_initrd ne $initrd) {
++            cp_f($live->get_system_root . $chroot_initrd, $initrd);
++            unlink($live->get_system_root . $chroot_initrd);
++        }
++    }
++}
++
++sub create_classical_initrd {
++    my ($live) = @_;
++    my $root = $live->get_system_root;
++    my $kernel = $live->find_kernel;
++    print "using kernel $kernel->{version}\n";
++
++    my $initrd_long = '/boot/initrd-'. $kernel . '.img';
++    unlink($root . $initrd_long);
++
++    {
++        my $bootloader = {};
++        local $::prefix = $root;
++        bootloader::add_kernel($bootloader, $kernel, { label => 'linux', vga => $live->{system}{vga_mode} }, '', $live->{system}{no_initrd});
++    }
++}
++
++1;
+
+Added: draklive/trunk/lib/MDV/Draklive/Live.pm
+===================================================================
+--- 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->{name_fields} || [ qw(name product version desktop region media arch) ];
++    join('-', grep { $_ } @{$live->{settings}}{@$fields});
++}
++
++sub get_builddir {
++    my ($live) = @_;
++    $live->{settings}{builddir} . '/' . $live->get_name;
++}
++
++sub get_system_root {
++    my ($live) = @_;
++    $live->{settings}{chroot} . '/' . $live->get_name;
++}
++
++sub get_media_prefix {
++    my ($live, $setting, $o_boot) = @_;
++    my $hidden = $live->{system}{hide_media_dirs} && $live->{media}->get_boot_setting('can_hide', { boot => $o_boot });
++    $live->{prefix}{media}{$hidden ? "hidden_$setting" : $setting};
++}
++
++sub find_kernel {
++    my ($live) = @_;
++    require bootloader;
++    local $::prefix = $live->get_system_root;
++    my @kernels = bootloader::get_kernels_and_labels();
++    my $kernel;
++    if ($live->{system}{kernel}) {
++        $kernel = find { $_->{version} eq $live->{system}{kernel} } @kernels;
++        $kernel or die "kernel $live->{system}{kernel} can not be found\n";
++    }
++    $kernel ||= first(@kernels) or die "no kernel can be found\n";
++}
++
++sub get_lib_prefix {
++    my ($live) = @_;
++    my $lib_prefix = find { glob($live->get_system_root . $_ . '/libc.so.*') } qw(/lib64 /lib);
++    $lib_prefix or die 'unable to find system libraries in /lib or /lib64';
++    $lib_prefix;
++}
++
++1;
+
+Added: draklive/trunk/lib/MDV/Draklive/Loopback.pm
+===================================================================
+--- 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 => {
++        read_only => 1,
++        is_loopback => 1,
++        modules => sub { "loop", has_squashfs4_with_lzma($_[0]) ? "squashfs" : "squashfs_lzma" },
++        extension => '-lzma.sqfs',
++        build => sub {
++            my ($live, $dir) = @_;
++            my $dest = $live->get_builddir . $live->{prefix}{build}{loopbacks} . $dir->{path} . $loop_types{squashfs}{extension};
++            mkdir_p(dirname($dest));
++            my $root = $dir->{root} || $live->get_system_root;
++            my $src = $root . $dir->{build_from};
++            my $total = directory_usage($src);
++            print "have to process " . int($total/1000000) . " MB\n";
++            my $progress = MDV::Draklive::Progress->new($total, time(), 6);
++            my $exclude_file = tmpnam();
++            output_p($exclude_file, map { $root . "$_\n" }  grep { -e $root . $_ } @{$dir->{exclude} || []});
++            my $sort = $live->{settings}{config_root} . '/' . $dir->{sort};
++            my $squashfs4 = has_squashfs4_with_lzma($live);
++            run_foreach(sub {
++                            if (/^mksquashfs: file .*, uncompressed size (\d+) bytes\s*(?:DUPLICATE|LINK)?$/) {
++                                $progress->{current} += $1;
++                                $progress->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 "unable to run mksquashfs\n";
++            $progress->end;
++            unlink $exclude_file;
++        },
++        mount => sub {
++            my ($live, $dir) = @_;
++            $dir->{loop} = "/dev/loop" . $loop_number++;
++            my $media_loopbacks = $live->get_media_prefix('loopbacks');
++            (
++                "/bin/losetup $dir->{loop} $live->{prefix}{live}{mnt}$live->{prefix}{media}{mnt}${media_loopbacks}$dir->{path}$loop_types{squashfs}{extension}",
++                "nash-mount -o ro -t squashfs $dir->{loop} $live->{prefix}{live}{mnt}$dir->{mountpoint}",
++            );
++        },
++    },
++    modules => {
++        read_only => 1,
++        delay_mount => 1,
++        mount => sub {
++            my ($live, $dir) = @_;
++            my $media_loopbacks = $live->get_media_prefix('loopbacks');
++            "sh -c 'modules=; for m in $live->{prefix}{live}{mnt}$live->{prefix}{media}{mnt}${media_loopbacks}$dir->{path}/*; do n=\$(basename \$m); n=\${n%.sqfs}; d=$live->{prefix}{live}{mnt}$dir->{mountpoint}/\$n; mkdir -p \$d; mount -n -o loop,ro -t squashfs \$m \$d && modules=\$modules\$d=ro:; done; echo \$modules | sed -e s/:\$// > $live->{prefix}{live}{mnt}/$dir->{list}'";
++        },
++        pivot_clean => sub {
++            my ($live, $dir, $initrdroot) = @_;
++            (
++                "sh -c 'cd $initrdroot$live->{prefix}{live}{mnt}$dir->{mountpoint}; for i in `ls -1`; do mkdir -p $live->{prefix}{live}{mnt}$dir->{mountpoint}/\$i; mount -n --move \$i $live->{prefix}{live}{mnt}$dir->{mountpoint}/\$i; rmdir \$i; done; rmdir $initrdroot$live->{prefix}{live}{mnt}$dir->{mountpoint}'",
++                "sh -c 'mv $initrdroot$live->{prefix}{live}{mnt}/$dir->{list} $live->{prefix}{live}{mnt}/'",
++            );
++        },
++    },
++    loopfs => {
++        is_loopback => 1,
++        modules => [],
++        extension => '.loop',
++        build => sub {
++            my ($live, $dir) = @_;
++            my $dest = $live->get_builddir . $live->{prefix}{build}{loopbacks} . $dir->{path} . $loop_types{loopfs}{extension};
++            mkdir_p(dirname($dest));
++            MDV::Draklive::Utils::device_allocate_file($dest, $dir->{pre_allocate});
++            MDV::Draklive::Utils::device_mkfs($dest, $dir->{fs}) if !defined $dir->{min_size};
++        },
++        mount => sub {
++            my ($live, $dir) = @_;
++            $dir->{loop} = "/dev/loop" . $loop_number++;
++            my $fsck = "chroot </dev/tty1 $live->{prefix}{live}{mnt}$dir_distrib_sqfs->{mountpoint} /sbin/fsck $dir->{loop}";
++            my $media_loopbacks = $live->get_media_prefix('loopbacks');
++            (
++                "losetup $dir->{loop} $live->{prefix}{live}{mnt}$live->{prefix}{media}{mnt}${media_loopbacks}$dir->{path}$loop_types{loopfs}{extension}",
++                qq(sh -c "$fsck -a || $fsck -y"),
++                "nash-mount -t $dir->{fs} $dir->{loop} $live->{prefix}{live}{mnt}$dir->{mountpoint}",
++            );
++        },
++    },
++    plain => {
++        skip_mkdir => 1,
++        mount => sub { 
++	    my ($live, $dir) = @_;
++            qq(sh -c "mkdir -p $live->{prefix}{live}{mnt}$dir->{mountpoint}");
++        },
++    },
++    partition => {
++	files => [ '/sbin/fsck', '/sbin/blkid' ],
++	mount => sub {
++	    my ($live, $dir) = @_;
++            my $fsck = "/bin/fsck";
++	    (
++	     qq(sh -c 'dev=`blkid -l -t $dir->{path} -o device`; [ -z "\$dev" ] || $fsck -a \$dev || $fsck -y \$dev'),
++	     "nash-mount -t $dir->{fs} $dir->{path} $live->{prefix}{live}{mnt}$dir->{mountpoint}",
++	    );
++	},
++    },
++    tmpfs => {
++        mount => sub {
++            my ($live, $dir) = @_;
++            my $mnt = $live->{prefix}{live}{mnt} . $dir->{mountpoint};
++            my $mount_opts = $dir->{mount_opts}?"-o $dir->{mount_opts}":"";
++            my $cmd = "mount -t tmpfs $mount_opts $mnt $mnt";
++            $dir->{fallback} ? qq(sh -c 'if ! grep -q " $mnt " /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->($live) :
++           $type eq 'ARRAY' ? @$modules :
++           ();
++}
++
++sub has_squashfs4_with_lzma {
++    my ($live) = @_;
++    my $kernel = $live->find_kernel;
++    cat_($live->get_system_root . "/boot/config-" . $live->find_kernel->{version}) =~ /^CONFIG_DECOMPRESS_LZMA_NEEDED=y$/m;
++}
++
++1;
+
+Added: draklive/trunk/lib/MDV/Draklive/Media.pm
+===================================================================
+--- 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->{partitions} ||= [ { mntpoint => '/' } ];
++
++    for $mntpoint (qw(/ OEM_RESCUE)) {
++        my $part = find { $_->{mntpoint} eq $mntpoint } @{$media->{partitions}};
++        $part->{fs_type} ||= $media->get_media_setting('fs');
++        if (my $label = $mntpoint eq '/' && $media->get_media_label) {
++            $part->{device_LABEL} ||= $label;
++        }
++    }
++
++    $media->{boot_entries} ||= [ '' => '' ];
++
++    $media;
++}
++
++sub get_initrd_path {
++    my ($media) = @_;
++    '/' . $media->{storage} . '/initrd.gz';
++}
++
++#- mainly for storage-specific subroutines
++sub get_storage_setting {
++    my ($media, $setting) = @_;
++    $MDV::Draklive::Storage::storage_types{$media->{storage}}{$setting};
++}
++
++#- for actions that support an optional boot storage type
++sub get_boot_setting {
++    my ($media, $setting, $opts) = @_;
++    $opts->{boot} ? $MDV::Draklive::Storage::storage_types{$opts->{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->{$setting} || $media->get_storage_setting($setting);
++}
++
++sub get_media_fs_module {
++    my ($media) = @_;
++    my $fs = $media->get_media_setting('fs');
++    $fs eq 'iso9660' ? 'isofs' : $fs eq 'ext2' ? @{[]} : $fs;
++}
++
++sub get_media_label {
++    my ($media) = @_;
++    first($media->get_media_setting('source') =~ /^LABEL=(.*)$/);
++}
++
++sub get_media_source_for_nash {
++    my ($media) = @_;
++    my $label = $media->get_media_label;
++    #- strip vfat labels to 11 chars and upper-case it
++    $label && $media->get_media_setting('fs') eq 'vfat' ?
++      'LABEL=' . uc(substr($label, 0, 11)) :
++      $media->get_media_setting('source');
++}
++
++sub find_partition_index {
++    my ($media, $mntpoint) = @_;
++    eval { find_index { $_->{mntpoint} eq $mntpoint } @{$media->{partitions}} };
++}
++
++sub find_boot_partition_index {
++    my ($media) = @_;
++    $media->find_partition_index('/boot') || $media->find_partition_index('/');
++}
++
++sub supplement_slash_size {
++    my ($media, $total_size) = @_;
++    my $correction = 1.2;
++    my $slash = find { $_->{mntpoint} eq '/' } @{$media->{partitions}};
++    $slash->{size} ||= POSIX::ceil($total_size * $correction / $common::SECTORSIZE);
++}
++
++1;
+
+Added: draklive/trunk/lib/MDV/Draklive/Mounts.pm
+===================================================================
+--- 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 => '/distrib',
++    type => 'squashfs',
++    path => '/distrib',
++    # perl -MMDK::Common -e 'print map_index { (32767 - $::i) . " $_" } grep { !m,^/(?:dev|proc|sys|live/distrib), } uniq(<>)' < bootlog.list > config/distrib.sort
++    sort => "config/distrib.sort",
++    build_from => '/',
++};
++my $_dir_memory = {
++    mountpoint => '/memory',
++    type => 'tmpfs',
++    mount_opts => 'mode=755',
++};
++
++my $_dir_modules = {
++    mountpoint => '/modules',
++    type => 'modules',
++    path => '/modules',
++    list => 'modules.lst',
++};
++
++#- use distro default
++our $default = {
++    dirs => [],
++};
++
++our $simple_union = {
++            root => '/union',
++            overlay => 'unionfs',
++            dirs => [
++                {
++                    mountpoint => '/media',
++                    type => 'plain',
++                },
++                $_dir_memory,
++            ],
++        };
++
++our $squash_rw_union = {
++            root => '/union',
++            overlay => 'unionfs',
++            dirs => [
++                $_dir_distrib_sqfs,
++                {
++                    mountpoint => '/media/system',
++                    type => 'plain',
++                },
++            ],
++        };
++
++sub volatile_squash_union {
++            my ($o_modules) = @_;
++            {
++                root => '/union',
++                overlay => 'unionfs',
++                dirs => [
++                    $_dir_distrib_sqfs,
++                    if_($o_modules, $_dir_modules),
++                    $_dir_memory,
++                ],
++            };
++}
++
++sub squash_union {
++            my ($default_size, $o_min_size, $o_modules) = @_;
++            {
++                root => '/union',
++                overlay => 'unionfs',
++                dirs => [
++                    $_dir_distrib_sqfs,
++                    if_($o_modules, $_dir_modules),
++                    {
++                        mountpoint => '/system',
++                        type => 'loopfs',
++                        pre_allocate => $default_size,
++                        if_(defined $o_min_size, min_size => $o_min_size),
++                        fs => 'ext2',
++                        path => '/system'
++                    },
++                    {
++                        mountpoint => '/system',
++                        type => 'tmpfs',
++                        fallback => 1,
++                    },
++                ],
++            };
++}
++
++1;
+
+Added: draklive/trunk/lib/MDV/Draklive/Overlay.pm
+===================================================================
+--- 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 => {
++        modules => [ qw(unionfs) ],
++        mount => sub {
++            my ($live) = @_;
++            #- build dirs list: "dir1=ro:dir2:ro:dir3=rw"
++            my $dirs = join(':',
++                            map {
++                                $_->{list} ? "\$(cat $live->{prefix}{live}{mnt}/$_->{list})" :
++                                  "$live->{prefix}{live}{mnt}$_->{mountpoint}=" .
++                                    (!$loop_types{$_->{type}}{read_only} && !$_->{read_only} ? 'rw' : 'ro');
++                            } reverse grep { !$_->{fallback} } @{$live->{mount}{dirs} || []});
++            "sh -c 'mount -o dirs=$dirs -t unionfs unionfs $live->{prefix}{live}{mnt}$live->{mount}{root}'";
++        },
++    },
++);
++
++1;
+
+Added: draklive/trunk/lib/MDV/Draklive/Progress.pm
+===================================================================
+--- 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 => $total,
++        current => 0,
++        start_time => $time,
++        exp_divide => $o_exp_divide,
++        maxl => length($total) - $o_exp_divide,
++    }, $class;
++}
++
++sub show {
++    my ($progress, $time) = @_;
++    my $elapsed_time = $time - $progress->{start_time};
++    my $eta = $progress->{current} ? int($elapsed_time*$progress->{total}/$progress->{current}) : -1;
++    printf("\r%3d%% (%$progress->{maxl}s/%-$progress->{maxl}s), %8s/%8s (ETA)",
++           int(100*$progress->{current}/$progress->{total}),
++           (map { substr($_, 0, length($_)-$progress->{exp_divide}) } $progress->{current}, $progress->{total}),
++           (map { POSIX::strftime("%H:%M:%S", gmtime($_)) } $elapsed_time, $eta));
++}
++
++sub end {
++    my ($_progress) = @_;
++    print "\n";
++}
++
++1;
+
+Added: draklive/trunk/lib/MDV/Draklive/Storage.pm
+===================================================================
+--- 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 => {
++        modules => 'bus/firewire|usb disk/firewire|hardware_raid|ide|sata|scsi|usb',
++        media_modules => 'disk/cdrom',
++        fs => 'iso9660',
++        can_hide => 0,
++        source => 'LABEL=MDVCDROOT',
++        read_only => 1,
++        detect => \&detect_devices::burners,
++        create => \&main::create_cdrom_master,
++        format => \&main::format_cdrom_device,
++        record_needs_master => 1,
++        record => \&main::record_cdrom_master,
++        replicator => \&main::create_cdrom_replicator,
++        record_replicator => \&main::record_cdrom_replicator,
++    },
++    usb => {
++        modules => 'bus/usb disk/usb',
++        media_modules => 'disk/raw',
++        fs => 'vfat',
++        can_hide => 1,
++        bootloader => 'grub',
++        source => 'LABEL=MDVUSBROOT',
++        detect => sub { grep { detect_devices::isKeyUsb($_) } detect_devices::get() },
++        create => \&main::create_disk_master,
++        format => \&main::format_disk,
++        record => \&main::record_usb_master,
++        image => \&main::create_disk_image,
++        replicator => \&main::create_usb_replicator,
++        record_replicator => \&main::record_usb_replicator,
++    },
++    harddisk => {
++        fs => 'ext4',
++        bootloader => 'grub',
++        source => 'LABEL=MDVROOT',
++        create => \&main::create_disk_master,
++        format => \&main::format_disk,
++        record => \&main::record_harddisk_master,
++        image => \&main::create_disk_image,
++    },
++);
++
++1;
+
+Added: draklive/trunk/lib/MDV/Draklive/StorageFS.pm
+===================================================================
+--- 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 => {
++        mount => sub {
++            my ($live, $media) = @_;
++            my @mount_options = (
++                if_($media->get_media_setting('read_only'), "ro"),
++                grep { $_ } $media->get_media_setting('mount_options'),
++            );
++            'nash-mount' . if_(@mount_options, " -o " . join(",", @mount_options)) . " -t " . $media->get_media_setting('fs') .
++              " " . $media->get_media_source_for_nash . " $live->{prefix}{live}{mnt}$live->{prefix}{media}{mnt}";
++        },
++    },
++    nfs => {
++        files => [ '/sbin/ifconfig', '/bin/mount' ], #- needed to mount NFS (with nolock)
++        mount => sub {
++            my ($live, $media) = @_;
++            '/bin/mount -n -o ro,nolock -t nfs ' . $media->get_media_source_for_nash . " $live->{prefix}{live}{mnt}$live->{prefix}{media}{mnt}";
++        }
++    },
++    ext2 => {
++        files => [ '/sbin/fsck.ext2' ],
++        mount => sub {
++	    my ($live, $media) = @_;
++            my $fsck = "/bin/fsck.ext2";
++            my $source = $media->get_media_setting('source');
++            qq(sh -c '$fsck -a $source || $fsck -y $source'),
++            $storage_fs{generic}{mount}->($live, $media);
++        },
++    },
++    vfat => {
++	#files => [ '/sbin/dosfsck' ],
++	mount => sub {
++	    my ($live, $media) = @_;
++	    #$storage_fs{generic}{mount}->($live, $media),
++	    #qq(awk '\$2 == "$live->{prefix}{live}{mnt}$live->{prefix}{media}{mnt}" { system("umount " \$1 "; mount; echo dosfsck -a " \$1 "; dosfsck -a " \$1) }' /proc/mounts),
++            $storage_fs{generic}{mount}->($live, $media);
++        },
++    },
++);
++
++sub get_files {
++    my ($fs) = @_;
++    @{$storage_fs{$fs} && $storage_fs{$fs}{files} || []};
++}
++
++sub get_mount {
++    my ($fs) = @_;
++    $storage_fs{exists $storage_fs{$fs}{mount} ? $fs : 'generic'}{mount};
++}
++
++1;
+
+Added: draklive/trunk/lib/MDV/Draklive/Utils.pm
+===================================================================
+--- 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 && "--apparent-size";
++    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->{timeout} ||= 'never';
++    if (arch() !~ /^arm/) {
++        my $targetarch = delete $options->{targetarch};
++        unshift @cmd, 'setarch', $targetarch if $targetarch;
++    }
++    print STDERR "running " . (exists $options->{root} && "(in chroot) ") . join(' ', @cmd) . "\n";
++    run_program::raw($options, @cmd);
++}
++
++sub run_foreach {
++    my ($foreach, @command) = @_;
++    print STDERR "running " . join(' ', @command) . "\n";
++    my $pid = open3(my $cmd_in, my $cmd_out, undef, @command);
++    my $selector = IO::Select->new($cmd_out);
++    while (my @ready = $selector->can_read) {
++        foreach my $fh (@ready) {
++            local $_ = scalar<$fh>;
++            return if /^open3:/;
++            $foreach->();
++            $selector->remove($fh) if eof($fh);
++        }
++    }
++    close($cmd_out);
++    close($cmd_in);
++    return waitpid($pid, 0) > 0 && !($? >> 8);
++}
++
++sub mtools_run_ {
++    local $ENV{MTOOLS_SKIP_CHECK} = 1;
++    &run_;
++}
++
++sub device_allocate_file {
++    my ($device, $size) = @_;
++    run_('dd', "of=$device", 'count=0', 'bs=1', "seek=" . 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_("mkfs.$type", "-m", 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 "unable to mkfs for unsupported media type $type\n";
++    }
++}
++
++1;
+
+Added: draklive/trunk/mkinitrd-draklive
+===================================================================
+--- 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 && $kernel or die "usage $0 <initrd> <kernel>\n";
++
++my $live = 'MDV::Draklive::Live'->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->{media}, "/", $initrd, $kernel);
+
+Added: draklive/trunk/write_flash.sh
+===================================================================
+--- 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="USB image dump"
++
++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 "$* (on $(date))"
++}
++
++show_wait() {
++    log $*
++    zenity --progress --auto-kill --title "$title" --text "$*" &
++}
++
++show_progress() {
++    log $*
++    zenity --progress --auto-kill --pulsate --title "$title" --text "$*" &
++}
++
++show_error() {
++    log $*
++    zenity --error --title $title --text "$*"
++}
++
++# 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 "Please insert new key"
++ wait_pid=$!
++ while sleep 5; do
++  dev=$(grep 'sd[^a]$' /proc/partitions | awk '{ print $4 }')
++  if [ -n "$dev" ]; then
++      dest=/dev/$dev
++      break
++  fi
++ done
++
++ sleep 2
++ grep "^$dest" /proc/mounts | awk '{ print $1 }' | xargs -r umount
++ kill $wait_pid
++
++ show_progress "Key found, writing image"
++ wait_pid=$!
++
++ dd if=$source of=$dest bs=$dump_block_size
++ kill $wait_pid
++ if [ $? -ne 0 ]; then
++     show_error "Key dump failed"
++     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 "Key dumped, checking"
++ 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 "md5: dumped = $dumped_md5"
++ echo "md5: source = $image_md5"
++ if [ "$dumped_md5" != "$image_md5" ]; then
++     show_error "Key has errors"
++     exit 1
++ fi
++ show_wait "Key dumped and verified"$'\n'$'\n'"Please remove key"
++ wait_pid=$!
++
++ while sleep 5; do
++  grep -q 'sd[^a]$' /proc/partitions || break
++ done
++ kill $wait_pid
++ echo "Key removed"
++done
++#umount /mnt/loop
+
+
+Property changes on: draklive/trunk/write_flash.sh
+___________________________________________________________________
+Added: svn:executable
+   + *
+Added: svn:eol-style
+   + native
+-------------- next part --------------
+An HTML attachment was scrubbed...
+URL: </pipermail/mageia-sysadm/attachments/20110203/978af990/attachment-0001.html>
+
+ + + +
+

+ +
+More information about the Mageia-sysadm +mailing list
+ -- cgit v1.2.1