tazlito view tazlito @ rev 453

may recompress addfiles (again)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Mon May 01 11:04:41 2017 +0200 (2017-05-01)
parents 2d7a7cbb50cd
children c9ed5c101d4e
line source
1 #!/bin/sh
2 # TazLito - SliTaz Live Tool.
3 #
4 # Tazlito is a tool to help generate and configure SliTaz Live CD
5 # ISO images. You can create a custom distro in one command from a list of
6 # packages, extract an existing ISO image to hack it, create a new initramfs
7 # and/or a new ISO. Most commands must be run by root, except the stats
8 # and the configuration file manipulation.
9 #
10 # (C) 2007-2016 SliTaz - GNU General Public License.
11 #
12 # Authors: see the AUTHORS file
13 #
15 VERSION='6.0'
17 . /lib/libtaz.sh
18 # Force to use Busybox cpio and wget
19 alias cpio='busybox cpio'
20 alias wget='busybox wget'
22 # Tazlito configuration variables to be shorter
23 # and to use words rather than numbers.
24 COMMAND="$1"
25 LIST_NAME="$2"
26 TMP_DIR="/tmp/tazlito-$$-$RANDOM"
27 TMP_MNT="/media/tazlito-$$-$RANDOM"
28 TOP_DIR="$(pwd)"
29 INITRAMFS='rootfs.gz'
30 LOCALSTATE='/var/lib/tazpkg'
31 INSTALLED="$LOCALSTATE/installed"
32 CACHE_DIR='/var/cache/tazpkg'
33 MIRROR="$LOCALSTATE/mirror"
34 DEFAULT_MIRROR="http://mirror1.slitaz.org/packages/$(cat /etc/slitaz-release)/"
36 log='/var/log/tazlito.log'
37 if [ $(id -u) -eq 0 ]; then
38 newline > $log
39 fi
42 cleanup() {
43 if [ -d "$TMP_MNT" ]; then
44 umount $TMP_MNT
45 rmdir $TMP_MNT
46 rm -f /boot
47 fi
48 [ -d "$tmp_dir" ] && rm -r "$tmp_dir"
49 [ -d "$flv_dir" ] && rm -r "$flv_dir"
50 }
53 # Report error and finish work
55 die() {
56 emsg "<n>$(longline "$@")<n> " >&2
57 cleanup
58 exit 1
59 }
62 # Run Tazlito module
63 module() {
64 local mod="$1"; shift
65 /usr/libexec/tazlito/$mod $@
66 }
70 # Try to include config file, continue if command is gen-config or exit.
71 # The main config used by default is in /etc/tazlito.
72 # Specific distro config file can be put in a distro tree.
73 for i in /etc/tazlito "$TOP_DIR"; do
74 [ -f "$i/tazlito.conf" ] && CONFIG_FILE="$i/tazlito.conf"
75 done
77 [ -z "$CONFIG_FILE" -a "$COMMAND" != 'gen-config' ] && \
78 die 'Unable to find any configuration file.' \
79 'Please read the docs or run `tazlito gen-config` to get an empty config file.'
81 . $CONFIG_FILE
83 # While Tazpkg is not used the default mirror URL file does not exist
84 # and user can't recharge the list of flavors.
85 [ $(id -u) -eq 0 -a ! -f "$MIRROR" ] && echo "$DEFAULT_MIRROR" > $MIRROR
87 # Set the rootfs and rootcd path with $DISTRO
88 # configuration variable.
89 ROOTFS="$DISTRO/rootfs"
90 ROOTCD="$DISTRO/rootcd"
95 #####################
96 # Tazlito functions #
97 #####################
100 # Print the usage.
102 usage () {
103 [ $(basename $0) == 'tazlito' ] && cat <<EOT
105 SliTaz Live Tool - Version: $(colorize 34 "$VERSION")
107 $(boldify "Usage:") tazlito [command] [list|iso|flavor|compression] [dir|iso]
109 $(boldify "Commands:")
110 EOT
111 optlist "\
112 usage Print this short usage.
113 stats View Tazlito and distro configuration statistics.
114 list-addfiles Simple list of additional files in the rootfs.
115 gen-config Generate a new configuration file for a distro.
116 configure Configure the main config file or a specific tazlito.conf.
117 gen-iso Generate a new ISO from a distro tree.
118 gen-initiso Generate a new initramfs and ISO from the distro tree.
119 list-flavors List all flavors available on the mirror.
120 gen-flavor Generate a new Live CD description.
121 gen-liveflavor Generate a Live CD description from current system.
122 show-flavor Show Live CD description.
123 get-flavor Get a flavor's list of packages (--noup to skip update).
124 upgrade-flavor Update package list to the latest available versions.
125 extract-flavor Extract a *.flavor file into $FLAVORS_REPOSITORY.
126 pack-flavor Pack (and update) a flavor from $FLAVORS_REPOSITORY.
127 iso2flavor Create a flavor file from a SliTaz ISO image.
128 extract-distro Extract an ISO to a directory and rebuild Live CD tree.
129 gen-distro Generate a Live distro and ISO from a list of packages.
130 clean-distro Remove all files generated by gen-distro.
131 check-distro Help to check if distro is ready to release.
132 writeiso Use running system to generate a bootable ISO (with /home).
133 merge Merge multiple rootfs into one ISO.
134 deduplicate Deduplicate files in a tree.
135 repack Recompress rootfs into ISO with maximum ratio.
136 build-loram Generate a Live CD for low-RAM systems.
137 emu-iso Emulate an ISO image with QEMU.
138 burn-iso Burn ISO image to a CD-ROM using Wodim.
139 "
140 }
143 yesorno() {
144 local answer
145 echo -n "$1 (y=yes, n=no) [$2] " >&2
146 case "$DEFAULT_ANSWER" in
147 Y|y) answer="y";;
148 N|n) answer="n";;
149 *)
150 read -t 30 answer
151 [ -z "$answer" ] && answer="$2"
152 [ "$answer" != 'y' -a "$answer" != 'n' ] && answer="$2"
153 ;;
154 esac
155 echo "$answer"
156 }
159 field() {
160 grep "^$1" "$2" | \
161 case "$1" in
162 Desc*) sed 's|^.*: *||';;
163 *) sed 's/.*: \([0-9KMG\.]*\).*/\1/';;
164 esac
165 }
168 todomsg() {
169 echo -e "\\033[70G[ \\033[1;31mTODO\\033[0;39m ]"
170 }
173 # Download a file from this mirror
175 download_from() {
176 local i mirrors="$1"
177 shift
178 for i in $mirrors; do
179 case "$i" in
180 http://*|ftp://*|https://*)
181 wget -c $i$@ && break;;
182 *)
183 cp $i/$1 . && break;;
184 esac
185 done
186 }
189 # Download a file trying all mirrors
191 download() {
192 local i
193 for i in $(cat $MIRROR $LOCALSTATE/undigest/*/mirror 2>/dev/null); do
194 download_from "$i" "$@" && break
195 done
196 }
199 # Execute hooks provided by some packages
201 genisohooks() {
202 local here="$(pwd)"
203 for i in $(ls $ROOTFS/etc/tazlito/*.$1 2>/dev/null); do
204 cd $ROOTFS
205 . $i $ROOTCD
206 done
207 cd "$here"
208 }
211 # Echo the package name if the tazpkg is already installed
213 installed_package_name() {
214 local tazpkg="$1" package VERSION EXTRAVERSION
216 # Try to find package name and version to be able
217 # to repack it from installation
218 # A dash (-) can exist in name *and* in version
219 package=${tazpkg%-*}
220 i=$package
221 while true; do
222 unset VERSION EXTRAVERSION
223 eval $(grep -s ^VERSION= $INSTALLED/$i/receipt)
224 eval $(grep -s ^EXTRAVERSION= $INSTALLED/$i/receipt)
225 if [ "$i-$VERSION$EXTRAVERSION" == "$tazpkg" ]; then
226 echo $i
227 break
228 fi
229 case "$i" in
230 *-*);;
231 *) break;;
232 esac
233 i=${i%-*}
234 done
235 }
238 # Check for the rootfs tree.
240 check_rootfs() {
241 [ -d "$ROOTFS/etc" ] || die 'Unable to find a distro rootfs...'
242 }
245 # Check for the boot dir into the root CD tree.
247 verify_rootcd() {
248 [ -d "$ROOTCD/boot" ] || die 'Unable to find the rootcd boot directory...'
249 }
252 # isolinux.conf doesn't know the kernel version.
253 # We name the kernel image 'bzImage'.
254 # isolinux/syslinux first tries the '64' suffix with a 64bits cpu.
256 make_bzImage_hardlink() {
257 if [ -s ${1:-.}/vmlinuz*slitaz ]; then
258 rm -f ${1:-.}/bzImage 2>/dev/null
259 ln ${1:-.}/vmlinuz*slitaz ${1:-.}/bzImage
260 fi
261 if [ -s ${1:-.}/vmlinuz*slitaz64 ]; then
262 rm -f ${1:-.}/bzImage64 2> /dev/null
263 ln ${1:-.}/vmlinuz*slitaz64 ${1:-.}/bzImage64
264 fi
265 }
268 create_iso() {
269 cd $2
270 deduplicate
272 cat > /tmp/cdsort$$ <<EOT
273 $PWD/boot 100
274 $PWD/boot/bzImage 200
275 $(n=199; ls -r $PWD/boot/rootfs* | while read f; do echo "$f $((n--))"; done)
276 $PWD/boot/isolinux 300
277 $PWD/boot/isolinux/boot.cat 400
278 $PWD/boot/isolinux/isolinux.bin 399
279 EOT
281 action 'Computing md5...'
282 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; > md5sum
283 sed -i -e '/ boot\/isolinux\/isolinux.bin$/d' \
284 -e '/ boot\/isolinux\/boot.cat$/d' md5sum
285 status
287 cd - >/dev/null
288 title 'Generating ISO image'
290 _ 'Generating %s' "$1"
291 make_bzImage_hardlink $2/boot
292 uefi="$(cd $2 ; ls boot/isolinux/*efi*img 2> /dev/null)"
293 genisoimage -R -o $1 -hide-rr-moved -sort /tmp/cdsort$$ \
294 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
295 -no-emul-boot -boot-load-size 4 -boot-info-table \
296 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
297 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
298 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
299 -A "tazlito $VERSION/$(genisoimage --version)" \
300 -copyright README -P "www.slitaz.org" $2
301 rm -f /tmp/cdsort$$
302 if [ -s '/etc/tazlito/info' ]; then
303 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
304 action 'Storing ISO info...'
305 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
306 status
307 fi
308 fi
310 if [ -x '/usr/bin/isohybrid' ]; then
311 action 'Creating hybrid ISO...'
312 /usr/bin/isohybrid $1 -entry 2 2>/dev/null
313 status
314 fi
316 if [ -x '/usr/bin/iso2exe' ]; then
317 echo 'Creating EXE header...'
318 /usr/bin/iso2exe $1 2>/dev/null
319 fi
320 }
323 # Generate a new ISO image using isolinux.
325 gen_livecd_isolinux() {
326 # Some packages may want to alter iso
327 genisohooks iso
328 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
330 # Set date for boot msg.
331 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
332 DATE=$(date +%Y%m%d)
333 action 'Setting build date to: %s...' "$DATE"
334 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
335 status
336 fi
338 cd $DISTRO
339 create_iso $ISO_NAME.iso $ROOTCD
341 action 'Creating the ISO md5sum...'
342 md5sum $ISO_NAME.iso > $ISO_NAME.md5
343 status
345 separator
346 # Some packages may want to alter final iso
347 genisohooks final
348 }
351 lzma_history_bits() {
352 #
353 # This generates an ISO which boots with Qemu but gives
354 # rootfs errors in frugal or liveUSB mode.
355 #
356 # local n
357 # local sz
358 # n=20 # 1Mb
359 # sz=$(du -sk $1 | cut -f1)
360 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
361 # n=$(( $n + 1 ))
362 # sz=$(( $sz / 2 ))
363 # done
364 # echo $n
365 echo ${LZMA_HISTORY_BITS:-24}
366 }
369 lzma_switches() {
370 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
371 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
372 }
375 lzma_set_size() {
376 # Update size field for lzma'd file packed using -si switch
377 return # Need to fix kernel code?
379 local n i
380 n=$(unlzma < $1 | wc -c)
381 for i in $(seq 1 8); do
382 printf '\\\\x%02X' $(($n & 255))
383 n=$(($n >> 8))
384 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
385 }
388 align_to_32bits() {
389 local size=$(stat -c %s ${1:-/dev/null})
390 [ $((${size:-0} & 3)) -ne 0 ] &&
391 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
392 }
395 dogzip() {
396 gzip -9 > $1
397 [ -x /usr/bin/advdef ] && advdef -qz4 $1
398 }
401 # Pack rootfs
403 pack_rootfs() {
404 ( cd $1; find . -print | cpio -o -H newc ) | \
405 case "$COMPRESSION" in
406 none)
407 _ 'Creating %s without compression...' 'initramfs'
408 cat > $2
409 ;;
410 gzip)
411 _ 'Creating %s with gzip compression...' 'initramfs'
412 dogzip $2
413 ;;
414 *)
415 _ 'Creating %s with lzma compression...' 'initramfs'
416 lzma e -si -so $(lzma_switches $1) > $2
417 lzma_set_size $2
418 ;;
419 esac
420 align_to_32bits $2
421 echo 1 > /tmp/rootfs
422 }
425 # Compression functions for writeiso.
427 write_initramfs() {
428 case "$COMPRESSION" in
429 lzma)
430 _n 'Creating %s with lzma compression...' "$INITRAMFS"
431 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
432 align='y'
433 lzma_set_size "/$INITRAMFS"
434 ;;
435 gzip)
436 _ 'Creating %s with gzip compression...' "$INITRAMFS"
437 cpio -o -H newc | dogzip "/$INITRAMFS"
438 ;;
439 *)
440 # align='y'
441 _ 'Creating %s without compression...' "$INITRAMFS"
442 cpio -o -H newc > "/$INITRAMFS"
443 ;;
444 esac < /tmp/list
445 [ "$align" == 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
446 echo 1 > /tmp/rootfs
447 }
450 # Deduplicate files (MUST be on the same filesystem).
452 deduplicate() {
453 find "${@:-.}" -type f -size +0c -xdev -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
454 (
455 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""
456 while read attr inode link file; do
457 [ -L "$file" ] && continue
458 if [ "$attr" == "$old_attr" -a "$inode" != "$old_inode" ]; then
459 if cmp "$file" "$old_file" >/dev/null 2>&1 ; then
460 rm -f "$file"
461 if ln "$old_file" "$file" 2>/dev/null; then
462 inode="$old_inode"
463 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
464 save="$(($save+(${attr%%-*}+512)/1024))"
465 else
466 cp -a "$old_file" "$file"
467 fi
468 fi
469 fi
470 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
471 done
472 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
473 )
475 find "$@" -type l -xdev -exec stat -c '%s-%u-%g-TARGET- %i %h %n' {} \; | sort | \
476 (
477 old_attr=""; hardlinks=0;
478 while read attr inode link file; do
479 attr="${attr/-TARGET-/-$(readlink $file)}"
480 if [ "$attr" == "$old_attr" ]; then
481 if [ "$inode" != "$old_inode" ]; then
482 rm -f "$file"
483 if ln "$old_file" "$file" 2>/dev/null; then
484 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
485 else
486 cp -a "$old_file" "$file"
487 fi
488 fi
489 else
490 old_file="$file"
491 old_attr="$attr"
492 old_inode="$inode"
493 fi
494 done
495 _ '%s duplicate symlinks.' "$hardlinks"
496 )
497 }
500 # Generate a new initramfs from the root filesystem.
502 gen_initramfs() {
503 # Just in case CTRL+c
504 rm -f $DISTRO/gen
506 # Some packages may want to alter rootfs
507 genisohooks rootfs
508 cd $1
510 # Normalize file time
511 find $1 -newer $1 -exec touch -hr $1 {} \;
513 # Link duplicate files
514 deduplicate
516 # Use lzma if installed. Display rootfs size in realtime.
517 rm -f /tmp/rootfs 2>/dev/null
518 pack_rootfs . $DISTRO/$(basename $1).gz &
519 sleep 2
520 echo -en "\nFilesystem size:"
521 while [ ! -f /tmp/rootfs ]; do
522 sleep 1
523 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
524 done
525 echo -e "\n"
526 rm -f /tmp/rootfs
527 cd $DISTRO
528 mv $(basename $1).gz $ROOTCD/boot
529 }
532 distro_sizes() {
533 if [ -n "$start_time" ]; then
534 time=$(($(date +%s) - $start_time))
535 sec=$time
536 div=$(( ($time + 30) / 60))
537 [ "$div" -ne 0 ] && min="~ ${div}m"
538 _ 'Build time : %ss %s' "$sec" "$min"
539 fi
540 cat <<EOT
541 Build date : $(date +%Y%m%d)
542 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
543 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
544 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
545 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
546 EOT
547 footer "Image is ready: $ISO_NAME.iso"
548 }
551 # Print ISO and rootfs size.
553 distro_stats() {
554 title 'Distro statistics: %s' "$DISTRO"
555 distro_sizes
556 }
559 # Create an empty configuration file.
561 empty_config_file() {
562 cat >> tazlito.conf <<"EOF"
563 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
564 #
566 # Name of the ISO image to generate.
567 ISO_NAME=""
569 # ISO image volume name.
570 VOLUM_NAME="SliTaz"
572 # Name of the preparer.
573 PREPARED="$USER"
575 # Path to the packages repository and the packages.list.
576 PACKAGES_REPOSITORY=""
578 # Path to the distro tree to gen-distro from a list of packages.
579 DISTRO=""
581 # Path to the directory containing additional files
582 # to copy into the rootfs and rootcd of the LiveCD.
583 ADDFILES="$DISTRO/addfiles"
585 # Default answer for binary question (Y or N)
586 DEFAULT_ANSWER="ASK"
588 # Compression utility (lzma, gzip or none)
589 COMPRESSION="lzma"
590 EOF
591 }
594 # Extract rootfs.gz somewhere
596 extract_rootfs() {
597 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
598 # First part (lzcat or zcat) may not fail, but cpio will fail on uncorrect format
599 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
600 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
601 (cd "$2"; cat "$1" | cpio -idm --quiet 2>/dev/null)
602 }
605 # Extract flavor file to temp directory
607 extract_flavor() {
608 # Input: $1 - flavor name to extract;
609 # $2 = absent/empty: just extract 'outer layer'
610 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
611 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
612 # Output: temp dir path where flavor was extracted
613 local f="$1.flavor" from to infos="$1.desc"
614 [ -f "$f" ] || die "File '$f' not found"
615 local dir="$(mktemp -d)"
616 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
618 if [ -n "$2" ]; then
619 cd $dir
621 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
623 for i in rootcd rootfs; do
624 [ -f "$1.$i" ] || continue
625 mkdir "$i"
626 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
627 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
628 rm "$1.$i"
629 done
630 touch -t 197001010100.00 "$1.*"
631 # Info to be stored inside ISO
632 [ "$2" == info ] && echo -e $infos | cpio -o -H newc | dogzip info
633 rm $1.list*
635 # Renames
636 while read from to; do
637 [ -f "$from" ] || continue
638 mv "$from" "$to"
639 done <<EOT
640 $1.nonfree non-free.list
641 $1.pkglist packages.list
642 $1-distro.sh distro.sh
643 $1.receipt receipt
644 $1.mirrors mirrors
645 $1.desc description
646 EOT
647 fi
649 echo $dir
650 }
653 # Pack flavor file from temp directory
655 pack_flavor() {
656 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
657 }
660 # Remove duplicate files
662 mergefs() {
663 # Note, many packages have files with spaces in the name
664 IFS=$'\n'
666 local size1=$(du -hs "$1" | awk '{ print $1 }')
667 local size2=$(du -hs "$2" | awk '{ print $1 }')
668 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
670 # merge symlinks files and devices
671 ( cd "$1"; find ) | \
672 while read file; do
673 if [ -L "$1/$file" ]; then
674 [ -L "$2/$file" -a "$(readlink "$1/$file")" == "$(readlink "$2/$file")" ] &&
675 rm -f "$2/$file"
677 elif [ -f "$1/$file" ]; then
678 [ -f "$2/$file" ] && cmp -s "$1/$file" "$2/$file" &&
679 rm -f "$2/$file"
681 [ -f "$2/$file" ] &&
682 [ "$(basename "$file")" == 'volatile.cpio.gz' ] &&
683 [ "$(dirname $(dirname "$file"))" == ".$INSTALLED" ] &&
684 rm -f "$2/$file"
686 elif [ -b "$1/$file" ]; then
687 [ -b "$2/$file" ] &&
688 [ "$(stat -c '%a:%u:%g:%t:%T' "$1/$file")" == \
689 "$(stat -c '%a:%u:%g:%t:%T' "$2/$file")" ] &&
690 rm -f "$2/$file"
692 elif [ -c "$1/$file" ]; then
693 [ -c "$2/$file" ] &&
694 [ "$(stat -c '%a:%u:%g:%t:%T' "$1/$file")" == \
695 "$(stat -c '%a:%u:%g:%t:%T' "$2/$file")" ] &&
696 rm -f "$2/$file"
697 fi
698 done
700 # cleanup directories; TODO: simplify
701 ( cd "$1"; find . -type d ) | sed '1!G;h;$!d' | \
702 while read file; do
703 [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
704 done
706 unset IFS
707 status
708 }
711 cleanup_merge() {
712 rm -rf $TMP_DIR
713 exit 1
714 }
717 # Update isolinux config files for multiple rootfs
719 update_bootconfig() {
720 local files
721 action 'Updating boot config files...'
722 files="$(grep -l 'include common' $1/*.cfg)"
723 for file in $files; do
724 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
725 if (/label/) label=$0;
726 else if (/kernel/) kernel=$0;
727 else if (/append/) {
728 i=index($0,"rootfs.gz");
729 append=substr($0,i+9);
730 }
731 else if (/include/) {
732 for (i = 1; i <= n; i++) {
733 print label i
734 print kernel;
735 initrd="initrd=/boot/rootfs" n ".gz"
736 for (j = n - 1; j >= i; j--) {
737 initrd=initrd ",/boot/rootfs" j ".gz";
738 }
739 printf "\tappend %s%s\n",initrd,append;
740 print "";
741 }
742 print;
743 }
744 else print;
745 }' < $file > $file.$$
746 mv -f $file.$$ $file
747 done
748 sel="$(echo $2 | awk '{
749 for (i=1; i<=NF; i++)
750 if (i % 2 == 0) printf " slitaz%d", i/2
751 else printf " %s", $i
752 }')"
754 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
756 label slitaz
757 kernel /boot/isolinux/ifmem.c32
758 append$sel noram
760 label noram
761 config noram.cfg
763 EOT
765 # Update vesamenu
766 if [ -s "$1/isolinux.cfg" ]; then
767 files="$files $1/isolinux.cfg"
768 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
769 BEGIN {
770 kernel = " COM32 c32box.c32"
771 }
772 {
773 if (/ROWS/) print "MENU ROWS " n+$3;
774 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
775 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
776 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
777 else if (/VSHIFT/) {
778 x = $3-n;
779 if (x < 0) x = 0;
780 print "MENU VSHIFT " x;
781 }
782 else if (/rootfs.gz/) {
783 linux = "";
784 if (/bzImage/) linux = "linux /boot/bzImage ";
785 i = index($0, "rootfs.gz");
786 append = substr($0, i+9);
787 printf "\tkernel /boot/isolinux/ifmem.c32\n";
788 printf "\tappend%s noram\n", sel;
789 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
790 for (i = 1; i <= n; i++) {
791 print "LABEL slitaz" i
792 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
793 printf "%s\n", kernel;
794 initrd = "initrd=/boot/rootfs" n ".gz"
795 for (j = n - 1; j >= i; j--) {
796 initrd = initrd ",/boot/rootfs" j ".gz";
797 }
798 printf "\tappend %s%s%s\n\n", linux, initrd, append;
799 }
800 }
801 else if (/bzImage/) kernel = $0;
802 else print;
803 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
804 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
805 fi
807 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
808 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
809 cat > $1/noram.cfg <<EOT
810 implicit 0
811 prompt 1
812 timeout 80
813 $(grep '^F[0-9]' $1/isolinux.cfg)
815 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
816 say Not enough RAM to boot slitaz. Trying hacker mode...
817 default hacker
818 label hacker
819 KERNEL /boot/bzImage
820 append rw root=/dev/null vga=normal
822 label reboot
823 EOT
825 if [ -s $1/c32box.c32 ]; then
826 cat >> $1/noram.cfg <<EOT
827 COM32 c32box.c32
828 append reboot
830 label poweroff
831 COM32 c32box.c32
832 append poweroff
834 EOT
835 else
836 echo " com32 reboot.c32" >> $1/noram.cfg
837 fi
839 # Restore real label names
840 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
841 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
842 while read pat; do
843 sed -i "s/slitaz$pat/" $files
844 done
845 status
846 }
849 # Uncompress rootfs or module to stdout
851 uncompress() {
852 zcat $1 2> /dev/null || xzcat $1 2> /dev/null || unlzma < $1 || cat $i
853 }
856 # Install a missing package
858 install_package() {
859 if [ -z "$2" ]; then
860 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
861 else
862 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
863 fi
864 case "$answer" in
865 y)
866 # We don't want package on host cache.
867 action 'Getting and installing package: %s' "$1"
868 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
869 status ;;
870 *)
871 return 1 ;;
872 esac
873 }
876 # Check iso for loram transformation
878 check_iso_for_loram() {
879 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
880 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
881 }
884 # Build initial rootfs for loram ISO ram/cdrom/http
886 build_initfs() {
887 urliso="mirror.switch.ch/ftp/mirror/slitaz \
888 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
889 mirror3.slitaz.org mirror.slitaz.org"
890 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
891 [ -z "$version" ] && die "Can't find the kernel version." \
892 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
894 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
895 need_lib=false
896 for i in bin dev run mnt proc tmp sys lib/modules; do
897 mkdir -p $TMP_DIR/initfs/$i
898 done
899 ln -s bin $TMP_DIR/initfs/sbin
900 ln -s . $TMP_DIR/initfs/usr
901 for aufs in aufs overlayfs; do
902 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
903 install_package $aufs $version && break
904 done || return 1
905 cp /init $TMP_DIR/initfs/
906 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
907 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
908 $TMP_DIR/initfs/lib/modules 2>/dev/null
909 cp -a /dev/tty0 /dev/fd0 $TMP_DIR/initfs/dev 2>/dev/null
910 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
911 $TMP_DIR/initfs/lib/modules
912 if [ "$1" == 'cdrom' ]; then
913 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
914 else
915 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
916 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
917 install_package linux-squashfs $version || return 1
918 done
919 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
920 $TMP_DIR/initfs/lib/modules
921 ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
922 cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
923 fi
924 for i in $(ls /dev/[hs]d[a-f]*); do
925 cp -a $i $TMP_DIR/initfs/dev
926 done
927 if [ "$1" == 'http' ]; then
928 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
929 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
930 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
931 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
932 cp -a /dev/fuse $TMP_DIR/initfs/dev
933 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
934 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
935 else
936 need_lib=true
937 fi
938 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
939 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
940 else
941 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
942 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
943 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
944 cp -a /lib/librt* $TMP_DIR/initfs/lib
945 cp -a /lib/libdl* $TMP_DIR/initfs/lib
946 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
947 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
948 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
949 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
950 need_lib=true
951 fi
952 cd $TMP_DIR/fs
953 echo 'Getting slitaz-release & ethernet modules...'
954 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
955 uncompress $i | cpio -idmu etc/slitaz-release lib/modules* >/dev/null
956 done
957 cd - > /dev/null
958 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
959 find $TMP_DIR/fs/lib/modules/*/kernel/drivers/net/ethernet \
960 -type f -name '*.ko*' | while read mod; do
961 f=$TMP_DIR/initfs/lib/modules/$(basename $mod | sed s/..z$//)
962 uncompress $mod > $f
963 grep -q alias=pci: $f || rm -f $f
964 done
965 for i in $TMP_DIR/initfs/lib/modules/*.ko ; do
966 f=$(basename $i)..z
967 grep -q $f:$ $TMP_DIR/fs/lib/modules/*/modules.dep && continue
968 deps="$(grep $f: $TMP_DIR/fs/lib/modules/*/modules.dep | sed 's/.*: //')"
969 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > $TMP_DIR/initfs/lib/modules/$(basename $i .ko).dep
970 for j in $deps; do
971 mod=$(ls $TMP_DIR/fs/lib/modules/*/$j)
972 uncompress $mod > $TMP_DIR/initfs/lib/modules/$(basename $j | sed s/..z$//)
973 done
974 done
975 longline "Default URLs for /iso/$(cat $TMP_DIR/initfs/etc/slitaz-release)/flavors/slitaz-loram-cdrom.iso /iso/$(cat $TMP_DIR/initfs/etc/slitaz-release)/flavors/slitaz-$(cat $TMP_DIR/initfs/etc/slitaz-release)-loram-cdrom.iso: $urliso"
976 _n 'List of URLs to insert: '
977 read -t 30 urliso2
978 urliso="$urliso2 $urliso"
979 fi
980 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
981 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
982 sed -i 's/LD_T.*ot/newline/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
983 else
984 cp /bin/busybox $TMP_DIR/initfs/bin
985 need_lib=true
986 fi
987 for i in $($TMP_DIR/initfs/bin/busybox | awk \
988 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
989 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
990 done
991 for i in /dev/console /dev/loop* /dev/null /dev/tty /dev/zero \
992 /dev/kmem /dev/mem /dev/random /dev/urandom; do
993 cp -a $i $TMP_DIR/initfs/dev
994 done
995 $need_lib && for i in /lib/ld-* /lib/lib[cm].so* /lib/lib[cm]-* ; do
996 cp -a $i $TMP_DIR/initfs/lib
997 done
998 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
999 #!/bin/sh
1001 getarg() {
1002 grep -q " \$1=" /proc/cmdline || return 1
1003 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1004 return 0
1007 copy_rootfs() {
1008 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1009 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1010 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1011 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1012 path=/mnt/
1013 return 0
1014 else
1015 rm -f /mnt/rootfs*
1016 return 1
1017 fi
1020 echo "Switching / to tmpfs..."
1021 mount -t proc proc /proc
1022 size="\$(grep rootfssize= < /proc/cmdline | \\
1023 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1024 [ -n "\$size" ] || size="-o size=90%"
1026 mount -t sysfs sysfs /sys
1027 for i in /lib/modules/*.ko ; do
1028 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1029 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1030 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1031 insmod /lib/modules/\$k.ko 2> /dev/null
1032 done
1033 insmod \$i 2> /dev/null
1034 break
1035 done
1036 done
1037 umount /sys
1038 while read var default; do
1039 eval \$var=\$default
1040 getarg \$var \$var
1041 done <<EOT
1042 eth eth0
1043 dns 208.67.222.222,208.67.220.220
1044 netmask 255.255.255.0
1045 gw
1046 ip
1047 EOT
1048 if [ -n "\$ip" ]; then
1049 ifconfig \$eth \$ip netmask \$netmask up
1050 route add default gateway \$gw
1051 for i in \$(echo \$dns | sed 's/,/ /g'); do
1052 echo "nameserver \$i" >> /etc/resolv.conf
1053 done
1054 else
1055 udhcpc -f -q -s /lib/udhcpc -i \$eth
1056 fi
1057 for i in $urliso ; do
1058 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1059 URLISO="\${URLISO}http://\$i/iso/\$(cat /etc/slitaz-release)/flavors/slitaz-loram-cdrom.iso,http://\$i/iso/\$(cat /etc/slitaz-release)/flavors/slitaz-\$(cat /etc/slitaz-release)-loram-cdrom.iso"
1060 done
1061 getarg urliso URLISO
1062 DIR=fs
1063 if getarg loram DIR; then
1064 DEVICE=\${DIR%,*}
1065 DIR=/\${DIR#*,}
1066 fi
1067 mount -t tmpfs \$size tmpfs /mnt
1068 path2=/mnt/.httpfs/
1069 path=/mnt/.cdrom/
1070 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1071 while [ ! -d \$path/boot ]; do
1072 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1073 httpfs \$i \$path2 && break
1074 done
1075 mount -o loop,ro -t iso9660 \$path2/*.iso \$path
1076 done
1078 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1079 umount /proc
1080 branch=:/mnt/.cdrom/\$DIR
1081 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1082 branch=
1083 for i in \${path}rootfs* ; do
1084 fs=\${i#*root}
1085 branch=\$branch:/mnt/.\$fs
1086 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1087 insmod /lib/modules/squashfs.ko 2> /dev/null
1088 mount -o loop,ro -t squashfs \${path}root\$fs /mnt/.\$fs
1089 done
1090 else
1091 mkdir -p /mnt/.rw/mnt/.httpfs
1092 fi
1093 while read type opt; do
1094 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1095 done <<EOT
1096 aufs br=/mnt/.rw\$branch
1097 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1098 EOT
1099 rm -rf /lib/modules
1100 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1101 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1102 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1103 EOTEOT
1104 chmod +x $TMP_DIR/initfs/init
1105 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1106 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1107 rm -f $i
1108 dogzip ${i%.gz}
1109 done 2>/dev/null
1110 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1111 lzma e $TMP_DIR/initfs.gz -si
1112 lzma_set_size $TMP_DIR/initfs.gz
1113 rm -rf $TMP_DIR/initfs
1114 align_to_32bits $TMP_DIR/initfs.gz
1115 return 0
1119 # Move each initramfs to squashfs
1121 build_loram_rootfs() {
1122 rootfs_sizes=""
1123 for i in $TMP_DIR/iso/boot/rootfs*; do
1124 mkdir -p $TMP_DIR/fs
1125 cd $TMP_DIR/fs
1126 uncompress $i | cpio -idm
1127 deduplicate
1128 cd - > /dev/null
1129 rootfs=$TMP_DIR/$(basename $i)
1130 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp xz -Xbcj x86
1131 cd $TMP_DIR
1132 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1133 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1134 rm -f $rootfs
1135 mv $rootfs.cpio $rootfs
1136 cd - > /dev/null
1137 rm -rf $TMP_DIR/fs
1138 done
1142 # Move meta boot configuration files to basic configuration files
1143 # because meta loram flavor is useless when rootfs is not loaded in RAM
1145 unmeta_boot() {
1146 local root=${1:-$TMP_DIR/loramiso}
1147 if [ -f $root/boot/isolinux/noram.cfg ]; then
1148 # We keep enough information to do unloram...
1149 [ -s $root/boot/isolinux/common.cfg ] &&
1150 sed -i 's/label slitaz/label orgslitaz/' \
1151 $root/boot/isolinux/common.cfg
1152 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1153 shift
1154 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1155 $root/boot/isolinux/isolinux.cfg
1156 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1157 sed -i "s/label $3\$/label slitaz/;s|=/boot/rootfs\(.*\).gz |=/boot/rootfs.gz |" \
1158 $root/boot/isolinux/*.cfg
1159 fi
1163 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1164 # These squashfs may be loaded in RAM at boot time.
1165 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1166 # Meta flavors are converted to normal flavors.
1168 build_loram_cdrom() {
1169 build_initfs cdrom || return 1
1170 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1171 mkdir $TMP_DIR/loramiso/fs
1172 cd $TMP_DIR/loramiso/fs
1173 for i in $( ls ../boot/root* | sort -r ) ; do
1174 uncompress $i | cpio -idmu
1175 rm -f $i
1176 done
1177 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1178 cd - >/dev/null
1179 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1180 unmeta_boot
1181 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1182 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1183 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1184 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1185 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1186 create_iso $OUTPUT $TMP_DIR/loramiso
1190 # Create http bootstrap to load and remove loram_cdrom
1191 # Meta flavors are converted to normal flavors.
1193 build_loram_http() {
1194 build_initfs http || return 1
1195 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1196 rm -f $TMP_DIR/loramiso/boot/rootfs*
1197 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1198 unmeta_boot
1199 create_iso $OUTPUT $TMP_DIR/loramiso
1203 # Update meta flavor selection sizes.
1204 # Reduce sizes with rootfs gains.
1206 update_metaiso_sizes() {
1207 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1208 do
1209 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1210 local sizes="$rootfs_sizes"
1211 local new
1212 set -- $append
1213 shift
1214 [ "$1" == "ifmem" ] && shift
1215 new=""
1216 while [ -n "$2" ]; do
1217 local s
1218 case "$1" in
1219 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1220 *M) s=$(( ${1%M} * 1024 ));;
1221 *) s=${1%K};;
1222 esac
1223 sizes=${sizes#* }
1224 for i in $sizes ; do
1225 s=$(( $s - $i ))
1226 done
1227 new="$new $s $2"
1228 shift 2
1229 done
1230 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1231 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1232 sed -i 's|\(initrd=\)\(/boot/rootfs.\.gz\)|\1/boot/rootfs.gz,\2|' $cfg
1233 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1234 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1235 done
1239 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1240 # Meta flavor selection sizes are updated.
1242 build_loram_ram() {
1243 build_initfs ram || return 1
1244 build_loram_rootfs
1245 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1246 make_bzImage_hardlink $TMP_DIR/loramiso/boot
1247 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1248 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1249 update_metaiso_sizes
1250 create_iso $OUTPUT $TMP_DIR/loramiso
1254 # Remove files installed by packages
1256 find_flavor_rootfs() {
1257 for i in $1/etc/tazlito/*.extract; do
1258 [ -e $i ] || continue
1259 chroot $1 /bin/sh ${i#$1}
1260 done
1262 # Clean hardlinks and files patched by genisofs in /boot
1263 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1264 rm -f $1/boot/$i*
1265 done
1267 # Clean files generated in post_install
1268 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1269 $1/dev/core $1/dev/fd $1/dev/std*
1271 # Verify md5
1272 cat $1$INSTALLED/*/md5sum | \
1273 while read md5 file; do
1274 [ -e "$1$file" ] || continue
1275 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1276 rm -f "$1$file"
1277 done
1279 # Check configuration files
1280 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1281 [ -e $i ] || continue
1282 mkdir /tmp/volatile$$
1283 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1284 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1285 while read file ; do
1286 [ -e "$1/$file" ] || continue
1287 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1288 done
1289 rm -rf /tmp/volatile$$
1290 done
1292 # Remove other files blindly
1293 for i in $1$INSTALLED/*/files.list; do
1294 for file in $(cat "$i"); do
1295 [ "$1$file" -nt "$i" ] && continue
1296 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1297 [ -d "$1$file" ] || rm -f "$1$file"
1298 done
1299 done
1301 # Remove tazpkg files and tmp files
1302 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1303 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1304 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1305 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1306 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1308 # Cleanup directory tree
1309 cd $1
1310 find * -type d | sort -r | while read dir; do
1311 rmdir "$dir" 2>/dev/null
1312 done
1313 cd - > /dev/null
1317 # Get byte(s) from a binary file
1319 get() {
1320 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null
1324 # Get cpio flavor info from the ISO image
1326 flavordata() {
1327 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1328 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1332 # Restore undigest mirrors
1334 restore_mirrors() {
1335 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1336 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1338 action 'Restoring mirrors...'
1339 if [ -d "$undigest.bak" ]; then
1340 [ -d "$undigest" ] && rm -r "$undigest"
1341 mv "$undigest.bak" "$undigest"
1342 fi
1343 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1344 :; status
1348 # Setup undigest mirrors
1350 setup_mirrors() {
1351 # Setup mirrors in plain system or in chroot (with variable root=)
1352 local mirrorlist="$1" fresh repacked
1353 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1355 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1356 restore_mirrors
1358 _ 'Setting up mirrors for %s...' "$root/"
1359 # Backing up current undigest mirrors and priority
1360 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1361 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1362 rm -rf '/var/www/tazlito/'
1363 mkdir -p '/var/www/tazlito/'
1365 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1366 fresh='/home/slitaz/packages'
1367 if [ -d "$fresh" ]; then
1368 # Setup first undigest mirror
1369 mkdir -p "$undigest/fresh"
1370 echo "$fresh" > "$undigest/fresh/mirror"
1371 echo 'fresh' >> "$priority"
1372 # Rebuild mirror DB if needed
1373 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1374 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1375 tazpkg mkdb "$fresh" --forced --root=''
1376 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1377 fi
1379 # Repacked packages: high priority
1380 repacked="$PACKAGES_REPOSITORY"
1381 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1382 # According to Tazlito setup file (tazlito.conf):
1383 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1384 # or
1385 # WORK_DIR="/home/slitaz"
1386 # and
1387 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1388 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1390 # Setup second undigest mirror
1391 mkdir -p "$undigest/repacked"
1392 echo "$repacked" > "$undigest/repacked/mirror"
1393 echo 'repacked' >> "$priority"
1394 # Rebuild mirror DB if needed
1395 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1396 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1397 tazpkg mkdb "$repacked" --forced --root=''
1398 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1399 fi
1401 # All repositories listed in mirrors list: normal priority
1402 [ -e "$mirrorlist" ] && \
1403 while read mirror; do
1404 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1405 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1406 mkdir -p "$undigest/$mirrorid"
1407 echo "$mirror" > "$undigest/$mirrorid/mirror"
1408 echo "$mirrorid" >> "$priority"
1409 done < "$mirrorlist"
1411 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1413 # Show list of mirrors
1414 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1415 function show(num, name, url) {
1416 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1419 num++;
1420 "cat " db "/undigest/" $0 "/mirror" | getline url;
1421 show(num, $0, url);
1423 END {
1424 num++;
1425 "cat " db "/mirror" | getline url;
1426 show(num, "main", url);
1427 }' "$priority"
1429 tazpkg recharge --quiet >/dev/null
1433 # Get list of 'packages.info' lists using priority
1435 pi_lists() {
1436 local pi
1437 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1438 local priority="$root$LOCALSTATE/priority"
1439 local undigest="$root$LOCALSTATE/undigest"
1442 [ -s "$priority" ] && cat "$priority"
1443 echo 'main'
1444 [ -d "$undigest" ] && ls "$undigest"
1445 } | awk -vun="$undigest/" '
1447 if (arr[$0] != 1) {
1448 arr[$0] = 1;
1449 print un $0 "/packages.info";
1451 }' | sed 's|/undigest/main||' | \
1452 while read pi; do
1453 [ -e "$pi" ] && echo "$pi"
1454 done
1458 # Strip versions from packages list
1460 strip_versions() {
1461 action 'Strip versions from list %s...' "$(basename "$1")"
1462 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1463 [ -f "$in_list" ] || die "List '$in_list' not found."
1465 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1466 awk '
1468 if (FILENAME ~ "packages.info") {
1469 # Collect package names
1470 FS = "\t"; pkg[$1] = 1;
1471 } else {
1472 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1473 while (NF > 1 && ! pkg[$0])
1474 NF --;
1475 printf "%s\n", $0;
1477 }' $(pi_lists) "$in_list" > "$tmp_list"
1479 cat "$tmp_list" > "$in_list"
1480 rm "$tmp_list"
1481 status
1485 # Display list of unknown packages (informative)
1487 display_unknown() {
1488 [ -s "$1" ] || return
1489 echo "Unknown packages:" >&2
1490 cat "$1" >&2
1491 rm "$1"
1495 # Display warnings about critical packages absent (informative)
1497 display_warn() {
1498 [ -s "$1" ] || return
1499 echo "Absent critical packages:" >&2
1500 cat "$1" >&2
1501 rm "$1"
1502 echo "Probably ISO image will be unusable."
1506 # Install packages to rootfs
1508 install_list_to_rootfs() {
1509 local list="$1" rootfs="$2" pkg i ii
1510 local undigest="$rootfs/var/lib/tazpkg/undigest"
1512 # initial tazpkg setup in empty rootfs
1513 tazpkg --root=$rootfs >/dev/null 2>&1
1514 # link rootfs packages cache to the regular packages cache
1515 rm -r "$rootfs/var/cache/tazpkg"
1516 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1518 setup_mirrors mirrors
1520 # Just in case if flavor not contains "tazlito" package
1521 mkdir -p "$rootfs/etc/tazlito"
1523 newline
1524 for pkg in $(cat $list); do
1525 action 'Installing package: %s' "$pkg"
1526 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1527 status
1528 done
1529 newline
1531 restore_mirrors
1532 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1533 for i in fresh repacked; do
1534 ii="$undigest/$i"
1535 [ -d "$ii" ] && rm -rf "$ii"
1536 ii="$rootfs/var/lib/tazpkg/priority"
1537 if [ -f "$ii" ]; then
1538 sed -i "/$i/d" "$ii"
1539 [ -s "$ii" ] || rm "$ii"
1540 fi
1541 done
1542 [ -d "$undigest" ] && \
1543 for i in $(find "$undigest" -type f); do
1544 # Remove all undigest PKGDB files but 'mirror'
1545 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1546 done
1547 [ -d "$undigest" ] && \
1548 rmdir --ignore-fail-on-non-empty "$undigest"
1550 # Un-link packages cache
1551 rm "$rootfs/var/cache/tazpkg"
1553 # Clean /var/lib/tazpkg
1554 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1560 ####################
1561 # Tazlito commands #
1562 ####################
1564 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1565 case "$0" in
1566 *reduplicate)
1567 find ${@:-.} ! -type d -links +1 \
1568 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1569 exit 0 ;;
1570 *deduplicate)
1571 deduplicate "$@"
1572 exit 0 ;;
1573 esac
1576 case "$COMMAND" in
1577 stats)
1578 # Tazlito general statistics from the config file.
1580 title 'Tazlito statistics'
1581 optlist "\
1582 Config file : $CONFIG_FILE
1583 ISO name : $ISO_NAME.iso
1584 Volume name : $VOLUM_NAME
1585 Prepared : $PREPARED
1586 Packages repository : $PACKAGES_REPOSITORY
1587 Distro directory : $DISTRO
1588 Additional files : $ADDFILES
1589 " | sed '/: $/d'
1590 footer
1591 ;;
1594 list-addfiles)
1595 # Simple list of additional files in the rootfs
1596 newline
1597 if [ -d "$ADDFILES/rootfs" ]; then
1598 cd $ADDFILES
1599 find rootfs -type f
1600 else
1601 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1602 fi
1603 newline
1604 ;;
1607 gen-config)
1608 # Generate a new config file in the current dir or the specified
1609 # directory by $2.
1611 if [ -n "$2" ]; then
1612 mkdir -p "$2" && cd "$2"
1613 fi
1615 newline
1616 action 'Generating empty tazlito.conf...'
1617 empty_config_file
1618 status
1620 separator
1621 if [ -f 'tazlito.conf' ] ; then
1622 _ 'Configuration file is ready to edit.'
1623 _ 'File location: %s' "$(pwd)/tazlito.conf"
1624 newline
1625 fi
1626 ;;
1629 configure)
1630 # Configure a tazlito.conf config file. Start by getting
1631 # a empty config file and sed it.
1633 if [ -f 'tazlito.conf' ]; then
1634 rm tazlito.conf
1635 else
1636 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1637 'or in the same directory of the file you want to configure.'
1638 cd /etc
1639 fi
1641 empty_config_file
1643 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1645 # ISO name.
1646 echo -n "ISO name : " ; read answer
1647 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1648 # Volume name.
1649 echo -n "Volume name : " ; read answer
1650 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1651 # Packages repository.
1652 echo -n "Packages repository : " ; read answer
1653 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1654 # Distro path.
1655 echo -n "Distro path : " ; read answer
1656 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1657 footer "Config file is ready to use."
1658 echo 'You can now extract an ISO or generate a distro.'
1659 newline
1660 ;;
1663 gen-iso)
1664 # Simply generate a new iso.
1666 check_root
1667 verify_rootcd
1668 gen_livecd_isolinux
1669 distro_stats
1670 ;;
1673 gen-initiso)
1674 # Simply generate a new initramfs with a new iso.
1676 check_root
1677 verify_rootcd
1678 gen_initramfs "$ROOTFS"
1679 gen_livecd_isolinux
1680 distro_stats
1681 ;;
1684 extract-distro)
1685 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1687 check_root
1688 ISO_IMAGE="$2"
1689 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1690 'Example:\n tazlito image.iso /path/target'
1692 # Set the distro path by checking for $3 on cmdline.
1693 TARGET="${3:-$DISTRO}"
1695 # Exit if existing distro is found.
1696 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1697 'Please clean the distro tree or change directory path.'
1699 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
1701 # Start to mount the ISO.
1702 action 'Mounting ISO image...'
1703 mkdir -p "$TMP_DIR"
1704 # Get ISO file size.
1705 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
1706 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
1707 sleep 2
1708 # Prepare target dir, copy the kernel and the rootfs.
1709 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
1710 status
1712 action 'Copying the Linux kernel...'
1713 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
1714 make_bzImage_hardlink "$TARGET/rootcd/boot"
1715 else
1716 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
1717 fi
1718 status
1720 for i in $(ls $TMP_DIR); do
1721 [ "$i" == 'boot' ] && continue
1722 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
1723 done
1725 for loader in isolinux syslinux extlinux grub; do
1726 [ -d "$TMP_DIR/boot/$loader" ] || continue
1727 action 'Copying %s files...' "$loader"
1728 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
1729 status
1730 done
1732 action 'Copying the rootfs...'
1733 cp $TMP_DIR/boot/rootfs.?z "$TARGET/rootcd/boot"
1734 status
1736 # Extract initramfs.
1737 cd "$TARGET/rootfs"
1738 action 'Extracting the rootfs...'
1739 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
1740 # unpack /usr
1741 for i in etc/tazlito/*.extract; do
1742 [ -f "$i" ] && . $i ../rootcd
1743 done
1744 # Umount and remove temp directory and cd to $TARGET to get stats.
1745 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
1746 cd ..
1747 status
1749 newline
1750 separator
1751 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
1752 echo "Distro tree : $(pwd)"
1753 echo "Rootfs size : $(du -sh rootfs)"
1754 echo "Rootcd size : $(du -sh rootcd)"
1755 footer
1756 ;;
1759 list-flavors)
1760 # Show available flavors.
1761 local list='/etc/tazlito/flavors.list'
1762 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
1763 title 'List of flavors'
1764 cat $list
1765 footer
1766 ;;
1769 show-flavor)
1770 # Show flavor description.
1771 set -e
1772 flavor=${2%.flavor}
1773 flv_dir="$(extract_flavor "$flavor")"
1774 desc="$flv_dir/$flavor.desc"
1775 if [ -n "$brief" ]; then
1776 if [ -z "$noheader" ]; then
1777 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
1778 separator
1779 fi
1780 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
1781 "$(field ISO "$desc")" \
1782 "$(field Rootfs "$desc")" \
1783 "$(field Description "$desc")"
1784 else
1785 separator
1786 cat "$desc"
1787 fi
1788 cleanup
1789 ;;
1792 gen-liveflavor)
1793 # Generate a new flavor from the live system.
1794 FLAVOR=${2%.flavor}
1795 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1797 case "$FLAVOR" in
1798 -?|-h*|--help)
1799 cat <<EOT
1800 SliTaz Live Tool - Version: $VERSION
1802 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
1804 $(boldify '<flavor-patch-file> format:')
1805 $(optlist "\
1806 code data
1807 + package to add
1808 - package to remove
1809 ! non-free package to add
1810 ? display message
1811 @ flavor description
1812 ")
1814 $(boldify 'Example:')
1815 $(optlist "\
1816 @ Developer tools for SliTaz maintainers
1817 + slitaz-toolchain
1818 + mercurial
1819 ")
1820 EOT
1821 exit 1
1822 ;;
1823 esac
1824 mv /etc/tazlito/distro-packages.list \
1825 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
1826 rm -f distro-packages.list non-free.list 2>/dev/null
1827 tazpkg recharge
1829 DESC=""
1830 [ -n "$3" ] && \
1831 while read action pkg; do
1832 case "$action" in
1833 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
1834 -) yes | tazpkg remove $pkg ;;
1835 !) echo $pkg >> non-free.list ;;
1836 @) DESC="$pkg" ;;
1837 \?) echo -en "$pkg"; read action ;;
1838 esac
1839 done < $3
1841 yes '' | tazlito gen-distro
1842 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
1843 mv /etc/tazlito/distro-packages.list.$$ \
1844 /etc/tazlito/distro-packages.list 2>/dev/null
1845 ;;
1848 gen-flavor)
1849 # Generate a new flavor from the last ISO image generated
1850 FLAVOR=${2%.flavor}
1851 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1853 title 'Flavor generation'
1854 check_rootfs
1855 FILES="$FLAVOR.pkglist"
1857 action 'Creating file %s...' "$FLAVOR.flavor"
1858 for i in rootcd rootfs; do
1859 if [ -d "$ADDFILES/$i" ] ; then
1860 FILES="$FILES\n$FLAVOR.$i"
1861 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
1862 fi
1863 done
1864 status
1866 answer=$(grep -s ^Description $FLAVOR.desc)
1867 answer=${answer#Description : }
1868 if [ -z "$answer" ]; then
1869 echo -n "Description: "
1870 read answer
1871 fi
1873 action 'Compressing flavor %s...' "$FLAVOR"
1874 echo "Flavor : $FLAVOR" > $FLAVOR.desc
1875 echo "Description : $answer" >> $FLAVOR.desc
1876 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
1877 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
1878 for i in $(ls $ROOTFS$INSTALLED); do
1879 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
1880 EXTRAVERSION=""
1881 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
1882 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
1883 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
1884 echo "$i" >> $FLAVOR.nonfree
1885 else
1886 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
1887 fi
1888 done
1889 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
1890 for i in $LOCALSTATE/undigest/*/mirror ; do
1891 [ -s $i ] && cat $i >> $FLAVOR.mirrors
1892 done
1893 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
1894 touch -t 197001010100.00 $FLAVOR.*
1895 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
1896 rm $(echo -e $FILES)
1897 status
1899 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
1900 ;;
1903 upgrade-flavor)
1904 # Strip versions from pkglist and update estimated numbers in flavor.desc
1905 flavor="${2%.flavor}"
1906 set -e
1907 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1908 set +e
1910 flv_dir="$(extract_flavor "$flavor")"
1912 strip_versions "$flv_dir/$flavor.pkglist"
1914 action 'Updating %s...' "$flavor.desc"
1916 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
1917 set -- $(module calc_sizes "$flv_dir" "$flavor")
1918 restore_mirrors >/dev/null
1920 sed -i -e '/Image is ready/d' \
1921 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
1922 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
1923 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
1924 -e "s|\(Packages *:\).*$|\1 $4|" \
1925 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
1926 "$flv_dir/$flavor.desc"
1928 pack_flavor "$flv_dir" "$flavor"
1929 status
1930 display_unknown "$flv_dir/err"
1931 display_warn "$flv_dir/warn"
1932 cleanup
1933 ;;
1936 extract-flavor)
1937 # Extract a flavor into $FLAVORS_REPOSITORY
1938 flavor="${2%.flavor}"
1939 set -e
1940 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1941 set +e
1943 action 'Extracting %s...' "$flavor.flavor"
1944 flv_dir="$(extract_flavor "$flavor" full)"
1945 storage="$FLAVORS_REPOSITORY/$flavor"
1947 rm -rf "$storage" 2>/dev/null
1948 mkdir -p "$storage"
1949 cp -a "$flv_dir"/* "$storage"
1950 rm "$storage/description"
1951 status
1953 strip_versions "$storage/packages.list"
1955 cleanup
1956 ;;
1959 pack-flavor)
1960 # Create a flavor from $FLAVORS_REPOSITORY.
1961 flavor=${2%.flavor}
1962 storage="$FLAVORS_REPOSITORY/$flavor"
1964 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
1966 action 'Creating flavor %s...' "$flavor"
1967 tmp_dir="$(mktemp -d)"
1969 while read from to; do
1970 [ -s "$storage/$from" ] || continue
1971 cp -a "$storage/$from" "$tmp_dir/$to"
1972 done <<EOT
1973 mirrors $flavor.mirrors
1974 distro.sh $flavor-distro.sh
1975 receipt $flavor.receipt
1976 non-free.list $flavor.nonfree
1977 EOT
1979 # Build the package list.
1980 # It can include a list from another flavor with the keyword @include
1981 if [ -s "$storage/packages.list" ]; then
1982 include=$(grep '^@include' "$storage/packages.list")
1983 if [ -n "$include" ]; then
1984 include=${include#@include }
1985 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
1986 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
1987 else
1988 echo -e "\nERROR: Can't find include package list from $include\n"
1989 fi
1990 fi
1991 # Generate the final/initial package list
1992 [ -s "$storage/packages.list" ] && \
1993 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
1994 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
1995 fi
1997 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
1998 # Process multi-rootfs flavor
1999 . "$storage/receipt"
2000 set -- $ROOTFS_SELECTION
2001 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2002 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2003 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2005 for i in rootcd rootfs; do
2006 mkdir "$tmp_dir/$i"
2007 # Copy extra files from the first flavor
2008 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2009 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2010 # Overload extra files by meta flavor
2011 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2012 [ -n "$(ls $tmp_dir/$i)" ] &&
2013 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2014 dogzip "$tmp_dir/$flavor.$i"
2015 rm -rf "$tmp_dir/$i"
2016 done
2017 else
2018 # Process plain flavor
2019 for i in rootcd rootfs; do
2020 [ -d "$storage/$i" ] || continue
2021 (cd "$storage/$i";
2022 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2023 done
2024 fi
2026 unset VERSION MAINTAINER ROOTFS_SELECTION
2027 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2028 ROOTFS_SIZE="$1 (estimated)"
2029 INITRAMFS_SIZE="$2 (estimated)"
2030 ISO_SIZE="$3 (estimated)"
2031 PKGNUM="$4"
2032 . "$storage/receipt"
2034 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2035 Flavor : $FLAVOR
2036 Description : $SHORT_DESC
2037 Version : $VERSION
2038 Maintainer : $MAINTAINER
2039 LiveCD RAM size : $FRUGAL_RAM
2040 Rootfs list : $ROOTFS_SELECTION
2041 Build date : $(date '+%Y%m%d at %T')
2042 Packages : $PKGNUM
2043 Rootfs size : $ROOTFS_SIZE
2044 Initramfs size : $INITRAMFS_SIZE
2045 ISO image size : $ISO_SIZE
2046 ================================================================================
2048 EOT
2050 rm -f $tmp_dir/packages.list
2051 pack_flavor "$tmp_dir" "$flavor"
2052 status
2053 display_unknown "$tmp_dir/err"
2054 display_warn "$flv_dir/warn"
2055 cleanup
2056 ;;
2059 get-flavor)
2060 # Get a flavor's files and prepare for gen-distro.
2061 flavor=${2%.flavor}
2062 title 'Preparing %s distro flavor' "$flavor"
2063 set -e
2064 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2065 set +e
2067 action 'Cleaning %s...' "$DISTRO"
2068 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2069 # Clean old files
2070 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2071 [ -f "$i" ] && rm "$i"
2072 done
2073 mkdir -p "$DISTRO"
2074 status
2076 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2078 action 'Extracting flavor %s...' "$flavor.flavor"
2079 flv_dir="$(extract_flavor "$flavor" info)"
2080 cp -a "$flv_dir"/* .
2081 mv packages.list distro-packages.list
2082 mv -f info /etc/tazlito
2083 status
2085 for i in rootcd rootfs; do
2086 if [ -d "$i" ]; then
2087 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2088 fi
2089 done
2091 rm -f /etc/tazlito/rootfs.list
2092 grep -q '^Rootfs list' description &&
2093 grep '^Rootfs list' description | sed 's/.*: \(.*\)$/\1/' > /etc/tazlito/rootfs.list
2095 action 'Updating %s...' 'tazlito.conf'
2096 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2097 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2098 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2099 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2100 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2101 status
2103 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2104 cleanup
2105 ;;
2108 iso2flavor)
2109 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2110 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2112 FLAVOR=${3%.flavor}
2113 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2114 mount -o loop,ro $2 $TMP_DIR/iso
2115 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2116 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2117 ! -s $TMP_DIR/flavor/*.desc ]; then
2118 _ 'META flavors are not supported.'
2119 umount -d $TMP_DIR/iso
2120 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2121 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2122 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2123 umount -d $TMP_DIR/iso
2124 else
2125 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2126 uncompress $i | \
2127 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2128 done
2129 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2130 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2131 '/etc/slitaz-release' '/boot/rootfs.gz'
2132 umount -d $TMP_DIR/iso
2133 else
2134 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2135 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2136 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2137 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2138 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2139 umount -d $TMP_DIR/iso
2140 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2141 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2142 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2143 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2144 < $TMP_DIR/rootfs$INSTALLED.md5
2145 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2146 if [ -s $TMP_DIR/flavor/*desc ]; then
2147 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2148 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2149 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2150 for i in rootfs rootcd ; do
2151 [ -s $TMP_DIR/flavor/*.list$i ] &&
2152 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2153 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2154 done
2155 else
2156 find_flavor_rootfs $TMP_DIR/rootfs
2157 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2158 for i in rootfs rootcd ; do
2159 [ "$(ls $TMP_DIR/$i)" ] &&
2160 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2161 done
2162 unset VERSION MAINTAINER
2163 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2164 if [ -n "$DESCRIPTION" ]; then
2165 _n 'Flavor version : '; read -t 30 VERSION
2166 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2167 fi
2169 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2170 Flavor : $FLAVOR
2171 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2172 Version : ${VERSION:-1.0}
2173 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2174 LiveCD RAM size : $RAM_SIZE
2175 Build date : $BUILD_DATE
2176 Packages : $PKGCNT
2177 Rootfs size : $ROOTFS_SIZE
2178 Initramfs size : $INITRAMFS_SIZE
2179 ISO image size : $ISO_SIZE
2180 ================================================================================
2182 EOT
2183 longline "Tazlito can't detect each file installed during \
2184 a package post_install. You should extract this flavor (tazlito extract-flavor \
2185 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2186 tree and remove files generated by post_installs.
2187 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2188 repack the flavor (tazlito pack-flavor $FLAVOR)"
2189 fi
2190 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2191 fi
2192 fi
2193 rm -rf $TMP_DIR
2194 ;;
2197 gen-distro)
2198 # Generate a live distro tree with a set of packages.
2200 check_root
2201 start_time=$(date +%s)
2203 # Tazlito options: --iso or --cdrom
2204 CDROM=''
2205 [ -n "$iso" ] && CDROM="-o loop $iso"
2206 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2208 # Check if a package list was specified on cmdline.
2209 if [ -f "$2" ]; then
2210 LIST_NAME="$2"
2211 else
2212 LIST_NAME='distro-packages.list'
2213 fi
2215 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2216 'Please clean the distro tree or change directory path.'
2217 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2218 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2220 # If list not given: build list with all installed packages
2221 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2222 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2223 fi
2225 # Exit if no list name.
2226 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2228 # Start generation.
2229 title 'Tazlito generating a distro'
2231 # Misc checks
2232 mkdir -p "$PACKAGES_REPOSITORY"
2233 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2234 newline
2236 # Mount CD-ROM to be able to repack boot-loader packages
2237 if [ ! -e /boot -a -n "$CDROM" ]; then
2238 mkdir $TMP_MNT
2239 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2240 ln -s "$TMP_MNT/boot" /
2241 if [ ! -d "$ADDFILES/rootcd" ] ; then
2242 mkdir -p "$ADDFILES/rootcd"
2243 for i in $(ls $TMP_MNT); do
2244 [ "$i" == 'boot' ] && continue
2245 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2246 done
2247 fi
2248 else
2249 rmdir "$TMP_MNT"
2250 fi
2251 fi
2253 # Rootfs stuff.
2254 echo 'Preparing the rootfs directory...'
2255 mkdir -p "$ROOTFS"
2256 export root="$ROOTFS"
2257 strip_versions "$LIST_NAME"
2259 if [ "$REPACK" == 'y' ]; then
2260 # Determine full packages list with all dependencies
2261 tmp_dir="$(mktemp -d)"
2262 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2263 touch "$tmp_dir/full.pkglist"
2264 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2266 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2267 while read pkgname pkgver; do
2268 # Is package in full list?
2269 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2270 # Is package already repacked?
2271 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2272 _ 'Repacking %s...' "$pkgname-$pkgver"
2273 tazpkg repack "$pkgname" --quiet
2274 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2275 status
2276 done
2278 rm -r "$tmp_dir"
2279 fi
2281 if [ -f non-free.list ]; then
2282 # FIXME: working in the ROOTFS chroot?
2283 newline
2284 echo 'Preparing non-free packages...'
2285 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2286 for pkg in $(cat 'non-free.list'); do
2287 if [ ! -d "$INSTALLED/$pkg" ]; then
2288 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2289 tazpkg get-install get-$pkg
2290 fi
2291 get-$pkg "$ROOTFS"
2292 fi
2293 tazpkg repack $pkg
2294 pkg=$(ls $pkg*.tazpkg)
2295 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2296 mv $pkg $PACKAGES_REPOSITORY
2297 done
2298 fi
2299 cp $LIST_NAME $DISTRO/distro-packages.list
2300 newline
2302 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2304 cd $DISTRO
2305 cp distro-packages.list $ROOTFS/etc/tazlito
2306 # Copy all files from $ADDFILES/rootfs to the rootfs.
2307 if [ -d "$ADDFILES/rootfs" ] ; then
2308 action 'Copying addfiles content to the rootfs...'
2309 cp -a $ADDFILES/rootfs/* $ROOTFS
2310 status
2311 fi
2313 action 'Root filesystem is generated...'; status
2315 # Root CD part.
2316 action 'Preparing the rootcd directory...'
2317 mkdir -p $ROOTCD
2318 status
2320 # Move the boot dir with the Linux kernel from rootfs.
2321 # The boot dir goes directly on the CD.
2322 if [ -d "$ROOTFS/boot" ] ; then
2323 action 'Moving the boot directory...'
2324 mv $ROOTFS/boot $ROOTCD
2325 cd $ROOTCD/boot
2326 make_bzImage_hardlink
2327 status
2328 fi
2329 cd $DISTRO
2330 # Copy all files from $ADDFILES/rootcd to the rootcd.
2331 if [ -d "$ADDFILES/rootcd" ] ; then
2332 action 'Copying addfiles content to the rootcd...'
2333 cp -a $ADDFILES/rootcd/* $ROOTCD
2334 status
2335 fi
2336 # Execute the distro script used to perform tasks in the rootfs
2337 # before compression. Give rootfs path in arg
2338 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2339 if [ -x "$DISTRO_SCRIPT" ]; then
2340 echo 'Executing distro script...'
2341 sh $DISTRO_SCRIPT $DISTRO
2342 fi
2344 # Execute the custom_rules() found in receipt.
2345 if [ -s "$TOP_DIR/receipt" ]; then
2346 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2347 echo -e "Executing: custom_rules()\n"
2348 . "$TOP_DIR/receipt"
2349 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2350 fi
2351 fi
2353 # Multi-rootfs
2354 if [ -s /etc/tazlito/rootfs.list ]; then
2356 FLAVOR_LIST="$(awk '{
2357 for (i = 2; i <= NF; i+=2)
2358 printf "%s ", i;
2359 }' /etc/tazlito/rootfs.list)"
2361 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2362 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2363 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2365 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2366 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2367 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2368 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2370 n=0
2371 last=$ROOTFS
2372 while read flavor; do
2373 n=$(($n+1))
2374 mkdir ${ROOTFS}0$n
2375 export root="${ROOTFS}0$n"
2376 # initial tazpkg setup in empty rootfs
2377 tazpkg --root=$root >/dev/null 2>&1
2379 newline
2380 boldify "Building $flavor rootfs..."
2382 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2383 cp "$TOP_DIR/$flavor.flavor" .
2385 if [ ! -s "$flavor.flavor" ]; then
2386 # We may have it in $FLAVORS_REPOSITORY
2387 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2388 tazlito pack-flavor $flavor
2389 else
2390 download $flavor.flavor
2391 fi
2392 fi
2394 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2395 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2396 cp $flavor.pkglist $DISTRO/list-packages0$n
2397 status
2399 strip_versions "$DISTRO/list-packages0$n"
2401 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2403 rm -rf ${ROOTFS}0$n/boot
2405 cd $DISTRO
2406 if [ -s $flavor.rootfs ]; then
2407 _n 'Adding %s rootfs extra files...' "$flavor"
2408 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2409 fi
2411 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2412 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2413 status
2415 rm -f $flavor.flavor install-list
2416 mergefs ${ROOTFS}0$n $last
2417 last=${ROOTFS}0$n
2418 done <<EOT
2419 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2420 EOT
2421 #'
2422 i=$(($n+1))
2423 while [ $n -gt 0 ]; do
2424 mv ${ROOTFS}0$n ${ROOTFS}$i
2425 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2426 gen_initramfs ${ROOTFS}$i
2427 n=$(($n-1))
2428 i=$(($i-1))
2429 export LZMA_HISTORY_BITS=26
2430 done
2431 mv $ROOTFS ${ROOTFS}$i
2432 gen_initramfs ${ROOTFS}$i
2433 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2434 else
2435 # Initramfs and ISO image stuff.
2436 gen_initramfs $ROOTFS
2437 fi
2438 gen_livecd_isolinux
2439 distro_stats
2440 cleanup
2441 ;;
2444 clean-distro)
2445 # Remove old distro tree.
2447 check_root
2448 title 'Cleaning: %s' "$DISTRO"
2449 if [ -d "$DISTRO" ] ; then
2450 if [ -d "$ROOTFS" ] ; then
2451 action 'Removing the rootfs...'
2452 rm -f $DISTRO/$INITRAMFS
2453 rm -rf $ROOTFS
2454 status
2455 fi
2456 if [ -d "$ROOTCD" ] ; then
2457 action 'Removing the rootcd...'
2458 rm -rf $ROOTCD
2459 status
2460 fi
2461 action 'Removing eventual ISO image...'
2462 rm -f $DISTRO/$ISO_NAME.iso
2463 rm -f $DISTRO/$ISO_NAME.md5
2464 status
2465 fi
2466 footer
2467 ;;
2470 check-distro)
2471 # Check for a few LiveCD needed files not installed by packages.
2473 # TODO: Remove this function.
2474 # First two files are maintained by tazpkg while it runs on rootfs,
2475 # while last one file should be maintained by tazlito itself.
2476 check_rootfs
2477 title 'Checking distro: %s' "$ROOTFS"
2478 # SliTaz release info.
2479 rel='/etc/slitaz-release'
2480 if [ ! -f "$ROOTFS$rel" ]; then
2481 _ 'Missing release info: %s' "$rel"
2482 else
2483 action 'Release : %s' "$(cat $ROOTFS$rel)"
2484 status
2485 fi
2486 # Tazpkg mirror.
2487 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2488 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2489 todomsg
2490 else
2491 action 'Mirror configuration exists...'
2492 status
2493 fi
2494 # Isolinux msg
2495 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2496 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2497 todomsg
2498 else
2499 action 'Isolinux message seems good...'
2500 status
2501 fi
2502 footer
2503 ;;
2506 writeiso)
2507 # Writefs to ISO image including /home unlike gen-distro we don't use
2508 # packages to generate a rootfs, we build a compressed rootfs with all
2509 # the current filesystem similar to 'tazusb writefs'.
2511 DISTRO='/home/slitaz/distro'
2512 ROOTCD="$DISTRO/rootcd"
2513 COMPRESSION="${2:-none}"
2514 ISO_NAME="${3:-slitaz}"
2515 check_root
2516 # Start info
2517 title 'Write filesystem to ISO'
2518 longline "The command writeiso will write the current filesystem into a \
2519 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2520 newline
2521 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2523 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2524 # Save some space
2525 rm -rf /var/cache/tazpkg/*
2526 rm -f /var/lib/tazpkg/*.bak
2527 rm -rf $DISTRO
2529 # Optionally remove sound card selection and screen resolution.
2530 if [ -z $LaunchedByTazpanel ]; then
2531 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2532 case $anser in
2533 y)
2534 action 'Removing current sound card and screen configurations...'
2535 rm -f /var/lib/sound-card-driver
2536 rm -f /var/lib/alsa/asound.state
2537 rm -f /etc/X11/xorg.conf ;;
2538 *)
2539 action 'Keeping current sound card and screen configurations...' ;;
2540 esac
2541 status
2542 newline
2544 # Optionally remove i18n settings
2545 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2546 case $anser in
2547 y)
2548 action 'Removing current locale/keymap settings...'
2549 newline > /etc/locale.conf
2550 newline > /etc/keymap.conf ;;
2551 *)
2552 action 'Keeping current locale/keymap settings...' ;;
2553 esac
2554 status
2555 fi
2557 # Clean-up files by default
2558 newline > /etc/udev/rules.d/70-persistent-net.rules
2559 newline > /etc/udev/rules.d/70-persistant-cd.rules
2561 # Create list of files including default user files since it is defined in /etc/passwd
2562 # and some new users might have been added.
2563 cd /
2564 echo 'init' > /tmp/list
2565 for dir in bin etc sbin var dev lib root usr home opt; do
2566 [ -d $dir ] && find $dir
2567 done >> /tmp/list
2569 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2570 [ -d $dir ] && echo $dir
2571 done >> /tmp/list
2573 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2575 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2576 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2577 #fi
2578 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2579 touch /var/log/wtmp
2581 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2582 sed -i "/var\/log\/$removelog/d" /tmp/list
2583 done
2585 # Generate initramfs with specified compression and display rootfs
2586 # size in realtime.
2587 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2589 write_initramfs &
2590 sleep 2
2591 cd - > /dev/null
2592 echo -en "\nFilesystem size:"
2593 while [ ! -f /tmp/rootfs ]; do
2594 sleep 1
2595 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2596 done
2597 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2598 echo -e "\n"
2599 rm -f /tmp/rootfs
2601 # Move freshly generated rootfs to the cdrom.
2602 mkdir -p $ROOTCD/boot
2603 mv -f /$INITRAMFS $ROOTCD/boot
2604 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2606 # Now we need the kernel and isolinux files.
2607 copy_from_cd() {
2608 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2609 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2610 unmeta_boot $ROOTCD
2611 umount /media/cdrom
2614 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2615 copy_from_cd;
2616 elif mount | grep /media/cdrom; then
2617 copy_from_cd;
2618 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2619 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2620 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2621 else
2622 touch /tmp/.write-iso-error
2623 longline "When SliTaz is running in RAM the kernel and bootloader \
2624 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
2625 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
2626 echo -en "----\nENTER to continue..."; read i
2627 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2628 copy_from_cd
2629 fi
2631 # Generate the iso image.
2632 touch /tmp/.write-iso
2633 newline
2634 cd $DISTRO
2635 create_iso $ISO_NAME.iso $ROOTCD
2636 action 'Creating the ISO md5sum...'
2637 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2638 status
2640 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2641 rm -f /tmp/.write-iso
2643 if [ -z $LaunchedByTazpanel ]; then
2644 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2645 case $anser in
2646 y)
2647 umount /dev/cdrom 2>/dev/null
2648 eject
2649 echo -n "Please insert a blank CD-ROM and press ENTER..."
2650 read i && sleep 2
2651 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2652 echo -en "----\nENTER to continue..."; read i ;;
2653 *)
2654 exit 0 ;;
2655 esac
2656 fi
2657 ;;
2660 burn-iso)
2661 # Guess CD-ROM device, ask user and burn the ISO.
2663 check_root
2664 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2665 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2666 # We can specify an alternative ISO from the cmdline.
2667 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2668 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2670 title 'Tazlito burn ISO'
2671 echo "CD-ROM device : /dev/$DRIVE_NAME"
2672 echo "Drive speed : $DRIVE_SPEED"
2673 echo "ISO image : $iso"
2674 footer
2676 case $(yesorno 'Burn ISO image?' 'n') in
2677 y)
2678 title 'Starting Wodim to burn the ISO...'
2679 sleep 2
2680 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2681 footer 'ISO image is burned to CD-ROM.'
2682 ;;
2683 *)
2684 die 'Exiting. No ISO burned.'
2685 ;;
2686 esac
2687 ;;
2690 merge)
2691 # Merge multiple rootfs into one iso.
2693 if [ -z "$2" ]; then
2694 cat <<EOT
2695 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2697 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2698 i.e: rootfsN is a subset of rootfsN-1
2699 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2700 The boot loader will select the rootfs according to the RAM size detected.
2702 Example:
2703 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
2705 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
2706 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
2708 EOT
2709 exit 2
2710 fi
2712 shift # skip merge
2713 append="$1 slitaz1"
2714 shift # skip size1
2715 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
2717 ISO=$1.merged
2719 # Extract filesystems
2720 action 'Mounting %s' "$1"
2721 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
2722 status || cleanup_merge
2724 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2725 make_bzImage_hardlink $TMP_DIR/iso/boot
2726 umount -d $TMP_DIR/mnt
2727 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
2728 _ '%s is already a merged iso. Aborting.' "$1"
2729 cleanup_merge
2730 fi
2731 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
2732 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
2733 if [ ! -f /boot/isolinux/ifmem.c32 -a
2734 ! -f /boot/isolinux/c32box.c32 ]; then
2735 cat <<EOT
2736 No file /boot/isolinux/ifmem.c32
2737 Please install syslinux package !
2738 EOT
2739 rm -rf $TMP_DIR
2740 exit 1
2741 fi
2742 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
2743 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
2744 fi
2746 action 'Extracting %s' 'iso/rootfs.gz'
2747 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
2748 [ -d $TMP_DIR/rootfs1/etc ]
2749 status || cleanup_merge
2751 n=1
2752 while [ -n "$2" ]; do
2753 shift # skip rootfs N-1
2754 p=$n
2755 n=$(($n + 1))
2756 append="$append $1 slitaz$n"
2757 shift # skip size N
2758 mkdir -p $TMP_DIR/rootfs$n
2760 action 'Extracting %s' "$1"
2761 extract_rootfs $1 $TMP_DIR/rootfs$n &&
2762 [ -d "$TMP_DIR/rootfs$n/etc" ]
2763 status || cleanup_merge
2765 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
2766 action 'Creating %s' "rootfs$p.gz"
2767 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
2768 status
2769 done
2770 action 'Creating %s' "rootfs$n.gz"
2771 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
2772 status
2773 rm -f $TMP_DIR/iso/boot/rootfs.gz
2774 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
2775 create_iso $ISO $TMP_DIR/iso
2776 rm -rf $TMP_DIR
2777 ;;
2780 repack)
2781 # Repack an iso with maximum lzma compression ratio.
2783 ISO=$2
2784 mkdir -p $TMP_DIR/mnt
2786 # Extract filesystems
2787 action 'Mounting %s' "$ISO"
2788 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
2789 status || cleanup_merge
2791 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2792 umount -d $TMP_DIR/mnt
2794 for i in $TMP_DIR/iso/boot/rootfs* ; do
2795 action 'Repacking %s' "$(basename $i)"
2796 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
2797 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
2798 align_to_32bits $i
2799 status
2800 done
2802 create_iso $ISO $TMP_DIR/iso
2803 rm -rf $TMP_DIR
2804 ;;
2807 build-loram)
2808 # Build a Live CD for low RAM systems.
2810 ISO="$2"
2811 OUTPUT="$3"
2812 [ -z "$3" ] && \
2813 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
2814 mkdir -p "$TMP_DIR/iso"
2815 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
2816 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
2817 if ! check_iso_for_loram ; then
2818 umount -d "$TMP_DIR/iso"
2819 die "$ISO is not a valid SliTaz live CD. Abort."
2820 fi
2821 case "$4" in
2822 cdrom) build_loram_cdrom ;;
2823 http) build_loram_http ;;
2824 *) build_loram_ram ;;
2825 esac
2826 umount $TMP_DIR/iso # no -d: needs /proc
2827 losetup -d $loopdev
2828 rm -rf $TMP_DIR
2829 ;;
2832 emu-iso)
2833 # Emulate an ISO image with Qemu.
2834 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2835 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
2836 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
2837 echo -e "\nStarting Qemu emulator:\n"
2838 echo -e "qemu $QEMU_OPTS $iso\n"
2839 qemu $QEMU_OPTS $iso
2840 ;;
2843 deduplicate)
2844 # Deduplicate files in a tree
2845 shift
2846 deduplicate "$@"
2847 ;;
2850 usage|*)
2851 # Print usage also for all unknown commands.
2852 usage
2853 ;;
2854 esac
2856 exit 0