tazlito view tazlito @ rev 439

May use advdef
author Pascal Bellard <pascal.bellard@slitaz.org>
date Fri Oct 21 08:19:50 2016 +0200 (2016-10-21)
parents 6a5f1eda8d1b
children 1a94764ae7b6
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 action 'Computing md5...'
273 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; > md5sum
274 sed -i -e '/ boot\/isolinux\/isolinux.bin$/d' \
275 -e '/ boot\/isolinux\/boot.cat$/d' md5sum
276 status
278 cd - >/dev/null
279 title 'Generating ISO image'
281 _ 'Generating %s' "$1"
282 make_bzImage_hardlink $2/boot
283 uefi="$(cd $2 ; ls boot/isolinux/*efi*img 2> /dev/null)"
284 genisoimage -R -o $1 -hide-rr-moved \
285 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
286 -no-emul-boot -boot-load-size 4 -boot-info-table \
287 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
288 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
289 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
290 -A "tazlito $VERSION/$(genisoimage --version)" \
291 -copyright README -P "www.slitaz.org" $2
292 if [ -s '/etc/tazlito/info' ]; then
293 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
294 action 'Storing ISO info...'
295 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
296 status
297 fi
298 fi
300 if [ -x '/usr/bin/isohybrid' ]; then
301 action 'Creating hybrid ISO...'
302 /usr/bin/isohybrid $1 -entry 2 2>/dev/null
303 status
304 fi
306 if [ -x '/usr/bin/iso2exe' ]; then
307 echo 'Creating EXE header...'
308 /usr/bin/iso2exe $1 2>/dev/null
309 fi
310 }
313 # Generate a new ISO image using isolinux.
315 gen_livecd_isolinux() {
316 # Some packages may want to alter iso
317 genisohooks iso
318 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
320 # Set date for boot msg.
321 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
322 DATE=$(date +%Y%m%d)
323 action 'Setting build date to: %s...' "$DATE"
324 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
325 status
326 fi
328 cd $DISTRO
329 create_iso $ISO_NAME.iso $ROOTCD
331 action 'Creating the ISO md5sum...'
332 md5sum $ISO_NAME.iso > $ISO_NAME.md5
333 status
335 separator
336 # Some packages may want to alter final iso
337 genisohooks final
338 }
341 lzma_history_bits() {
342 #
343 # This generates an ISO which boots with Qemu but gives
344 # rootfs errors in frugal or liveUSB mode.
345 #
346 # local n
347 # local sz
348 # n=20 # 1Mb
349 # sz=$(du -sk $1 | cut -f1)
350 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
351 # n=$(( $n + 1 ))
352 # sz=$(( $sz / 2 ))
353 # done
354 # echo $n
355 echo ${LZMA_HISTORY_BITS:-24}
356 }
359 lzma_switches() {
360 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
361 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
362 }
365 lzma_set_size() {
366 # Update size field for lzma'd file packed using -si switch
367 return # Need to fix kernel code?
369 local n i
370 n=$(unlzma < $1 | wc -c)
371 for i in $(seq 1 8); do
372 printf '\\\\x%02X' $(($n & 255))
373 n=$(($n >> 8))
374 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
375 }
378 align_to_32bits() {
379 local size=$(stat -c %s ${1:-/dev/null})
380 [ $((${size:-0} & 3)) -ne 0 ] &&
381 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
382 }
385 dogzip() {
386 gzip -9 > $1
387 [ -x /usr/bin/advdef ] && advdef -qz4 $1
388 }
391 # Pack rootfs
393 pack_rootfs() {
394 ( cd $1; find . -print | cpio -o -H newc ) | \
395 case "$COMPRESSION" in
396 none)
397 _ 'Creating %s without compression...' 'initramfs'
398 cat > $2
399 ;;
400 gzip)
401 _ 'Creating %s with gzip compression...' 'initramfs'
402 dogzip $2
403 ;;
404 *)
405 _ 'Creating %s with lzma compression...' 'initramfs'
406 lzma e -si -so $(lzma_switches $1) > $2
407 lzma_set_size $2
408 ;;
409 esac
410 align_to_32bits $2
411 echo 1 > /tmp/rootfs
412 }
415 # Compression functions for writeiso.
417 write_initramfs() {
418 case "$COMPRESSION" in
419 lzma)
420 _n 'Creating %s with lzma compression...' "$INITRAMFS"
421 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
422 align='y'
423 lzma_set_size "/$INITRAMFS"
424 ;;
425 gzip)
426 _ 'Creating %s with gzip compression...' "$INITRAMFS"
427 cpio -o -H newc | dogzip "/$INITRAMFS"
428 ;;
429 *)
430 # align='y'
431 _ 'Creating %s without compression...' "$INITRAMFS"
432 cpio -o -H newc > "/$INITRAMFS"
433 ;;
434 esac < /tmp/list
435 [ "$align" == 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
436 echo 1 > /tmp/rootfs
437 }
440 # Deduplicate files (MUST be on the same filesystem).
442 deduplicate() {
443 find "${@:-.}" -type f -size +0c -xdev -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
444 (
445 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""
446 while read attr inode link file; do
447 [ -L "$file" ] && continue
448 if [ "$attr" == "$old_attr" -a "$inode" != "$old_inode" ]; then
449 if cmp "$file" "$old_file" >/dev/null 2>&1 ; then
450 rm -f "$file"
451 if ln "$old_file" "$file" 2>/dev/null; then
452 inode="$old_inode"
453 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
454 save="$(($save+(${attr%%-*}+512)/1024))"
455 else
456 cp -a "$old_file" "$file"
457 fi
458 fi
459 fi
460 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
461 done
462 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
463 )
465 find "$@" -type l -xdev -exec stat -c '%s-%u-%g-TARGET- %i %h %n' {} \; | sort | \
466 (
467 old_attr=""; hardlinks=0;
468 while read attr inode link file; do
469 attr="${attr/-TARGET-/-$(readlink $file)}"
470 if [ "$attr" == "$old_attr" ]; then
471 if [ "$inode" != "$old_inode" ]; then
472 rm -f "$file"
473 if ln "$old_file" "$file" 2>/dev/null; then
474 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
475 else
476 cp -a "$old_file" "$file"
477 fi
478 fi
479 else
480 old_file="$file"
481 old_attr="$attr"
482 old_inode="$inode"
483 fi
484 done
485 _ '%s duplicate symlinks.' "$hardlinks"
486 )
487 }
490 # Generate a new initramfs from the root filesystem.
492 gen_initramfs() {
493 # Just in case CTRL+c
494 rm -f $DISTRO/gen
496 # Some packages may want to alter rootfs
497 genisohooks rootfs
498 cd $1
500 # Link duplicate files
501 deduplicate
503 # Use lzma if installed. Display rootfs size in realtime.
504 rm -f /tmp/rootfs 2>/dev/null
505 pack_rootfs . $DISTRO/$(basename $1).gz &
506 sleep 2
507 echo -en "\nFilesystem size:"
508 while [ ! -f /tmp/rootfs ]; do
509 sleep 1
510 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
511 done
512 echo -e "\n"
513 rm -f /tmp/rootfs
514 cd $DISTRO
515 mv $(basename $1).gz $ROOTCD/boot
516 }
519 distro_sizes() {
520 if [ -n "$start_time" ]; then
521 time=$(($(date +%s) - $start_time))
522 sec=$time
523 div=$(( ($time + 30) / 60))
524 [ "$div" -ne 0 ] && min="~ ${div}m"
525 _ 'Build time : %ss %s' "$sec" "$min"
526 fi
527 cat <<EOT
528 Build date : $(date +%Y%m%d)
529 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
530 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
531 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
532 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
533 EOT
534 footer "Image is ready: $ISO_NAME.iso"
535 }
538 # Print ISO and rootfs size.
540 distro_stats() {
541 title 'Distro statistics: %s' "$DISTRO"
542 distro_sizes
543 }
546 # Create an empty configuration file.
548 empty_config_file() {
549 cat >> tazlito.conf <<"EOF"
550 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
551 #
553 # Name of the ISO image to generate.
554 ISO_NAME=""
556 # ISO image volume name.
557 VOLUM_NAME="SliTaz"
559 # Name of the preparer.
560 PREPARED="$USER"
562 # Path to the packages repository and the packages.list.
563 PACKAGES_REPOSITORY=""
565 # Path to the distro tree to gen-distro from a list of packages.
566 DISTRO=""
568 # Path to the directory containing additional files
569 # to copy into the rootfs and rootcd of the LiveCD.
570 ADDFILES="$DISTRO/addfiles"
572 # Default answer for binary question (Y or N)
573 DEFAULT_ANSWER="ASK"
575 # Compression utility (lzma, gzip or none)
576 COMPRESSION="lzma"
577 EOF
578 }
581 # Extract rootfs.gz somewhere
583 extract_rootfs() {
584 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
585 # First part (lzcat or zcat) may not fail, but cpio will fail on uncorrect format
586 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
587 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
588 (cd "$2"; cat "$1" | cpio -idm --quiet 2>/dev/null)
589 }
592 # Extract flavor file to temp directory
594 extract_flavor() {
595 # Input: $1 - flavor name to extract;
596 # $2 = absent/empty: just extract 'outer layer'
597 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
598 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
599 # Output: temp dir path where flavor was extracted
600 local f="$1.flavor" from to infos="$1.desc"
601 [ -f "$f" ] || die "File '$f' not found"
602 local dir="$(mktemp -d)"
603 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
605 if [ -n "$2" ]; then
606 cd $dir
608 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
610 for i in rootcd rootfs; do
611 [ -f "$1.$i" ] || continue
612 mkdir "$i"
613 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
614 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
615 rm "$1.$i"
616 done
617 # Info to be stored inside ISO
618 [ "$2" == info ] && echo -e $infos | cpio -o -H newc | dogzip info
619 rm $1.list*
621 # Renames
622 while read from to; do
623 [ -f "$from" ] || continue
624 mv "$from" "$to"
625 done <<EOT
626 $1.nonfree non-free.list
627 $1.pkglist packages.list
628 $1-distro.sh distro.sh
629 $1.receipt receipt
630 $1.mirrors mirrors
631 $1.desc description
632 EOT
633 fi
635 echo $dir
636 }
639 # Pack flavor file from temp directory
641 pack_flavor() {
642 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
643 }
646 # Remove duplicate files
648 mergefs() {
649 # Note, many packages have files with spaces in the name
650 IFS=$'\n'
652 local size1=$(du -hs "$1" | awk '{ print $1 }')
653 local size2=$(du -hs "$2" | awk '{ print $1 }')
654 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
656 # merge symlinks files and devices
657 ( cd "$1"; find ) | \
658 while read file; do
659 if [ -L "$1/$file" ]; then
660 [ -L "$2/$file" -a "$(readlink "$1/$file")" == "$(readlink "$2/$file")" ] &&
661 rm -f "$2/$file"
663 elif [ -f "$1/$file" ]; then
664 [ -f "$2/$file" ] && cmp -s "$1/$file" "$2/$file" &&
665 rm -f "$2/$file"
667 [ -f "$2/$file" ] &&
668 [ "$(basename "$file")" == 'volatile.cpio.gz' ] &&
669 [ "$(dirname $(dirname "$file"))" == ".$INSTALLED" ] &&
670 rm -f "$2/$file"
672 elif [ -b "$1/$file" ]; then
673 [ -b "$2/$file" ] &&
674 [ "$(stat -c '%a:%u:%g:%t:%T' "$1/$file")" == \
675 "$(stat -c '%a:%u:%g:%t:%T' "$2/$file")" ] &&
676 rm -f "$2/$file"
678 elif [ -c "$1/$file" ]; then
679 [ -c "$2/$file" ] &&
680 [ "$(stat -c '%a:%u:%g:%t:%T' "$1/$file")" == \
681 "$(stat -c '%a:%u:%g:%t:%T' "$2/$file")" ] &&
682 rm -f "$2/$file"
683 fi
684 done
686 # cleanup directories; TODO: simplify
687 ( cd "$1"; find . -type d ) | sed '1!G;h;$!d' | \
688 while read file; do
689 [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
690 done
692 unset IFS
693 status
694 }
697 cleanup_merge() {
698 rm -rf $TMP_DIR
699 exit 1
700 }
703 # Update isolinux config files for multiple rootfs
705 update_bootconfig() {
706 local files
707 action 'Updating boot config files...'
708 files="$(grep -l 'include common' $1/*.cfg)"
709 for file in $files; do
710 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
711 if (/label/) label=$0;
712 else if (/kernel/) kernel=$0;
713 else if (/append/) {
714 i=index($0,"rootfs.gz");
715 append=substr($0,i+9);
716 }
717 else if (/include/) {
718 for (i = 1; i <= n; i++) {
719 print label i
720 print kernel;
721 initrd="initrd=/boot/rootfs" n ".gz"
722 for (j = n - 1; j >= i; j--) {
723 initrd=initrd ",/boot/rootfs" j ".gz";
724 }
725 printf "\tappend %s%s\n",initrd,append;
726 print "";
727 }
728 print;
729 }
730 else print;
731 }' < $file > $file.$$
732 mv -f $file.$$ $file
733 done
734 sel="$(echo $2 | awk '{
735 for (i=1; i<=NF; i++)
736 if (i % 2 == 0) printf " slitaz%d", i/2
737 else printf " %s", $i
738 }')"
740 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
742 label slitaz
743 kernel /boot/isolinux/ifmem.c32
744 append$sel noram
746 label noram
747 config noram.cfg
749 EOT
751 # Update vesamenu
752 if [ -s "$1/isolinux.cfg" ]; then
753 files="$files $1/isolinux.cfg"
754 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
755 BEGIN {
756 kernel = " COM32 c32box.c32"
757 }
758 {
759 if (/ROWS/) print "MENU ROWS " n+$3;
760 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
761 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
762 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
763 else if (/VSHIFT/) {
764 x = $3-n;
765 if (x < 0) x = 0;
766 print "MENU VSHIFT " x;
767 }
768 else if (/rootfs.gz/) {
769 linux = "";
770 if (/bzImage/) linux = "linux /boot/bzImage ";
771 i = index($0, "rootfs.gz");
772 append = substr($0, i+9);
773 printf "\tkernel /boot/isolinux/ifmem.c32\n";
774 printf "\tappend%s noram\n", sel;
775 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
776 for (i = 1; i <= n; i++) {
777 print "LABEL slitaz" i
778 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
779 printf "%s\n", kernel;
780 initrd = "initrd=/boot/rootfs" n ".gz"
781 for (j = n - 1; j >= i; j--) {
782 initrd = initrd ",/boot/rootfs" j ".gz";
783 }
784 printf "\tappend %s%s%s\n\n", linux, initrd, append;
785 }
786 }
787 else if (/bzImage/) kernel = $0;
788 else print;
789 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
790 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
791 fi
793 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
794 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
795 cat > $1/noram.cfg <<EOT
796 implicit 0
797 prompt 1
798 timeout 80
799 $(grep '^F[0-9]' $1/isolinux.cfg)
801 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
802 say Not enough RAM to boot slitaz. Trying hacker mode...
803 default hacker
804 label hacker
805 KERNEL /boot/bzImage
806 append rw root=/dev/null vga=normal
808 label reboot
809 EOT
811 if [ -s $1/c32box.c32 ]; then
812 cat >> $1/noram.cfg <<EOT
813 COM32 c32box.c32
814 append reboot
816 label poweroff
817 COM32 c32box.c32
818 append poweroff
820 EOT
821 else
822 echo " com32 reboot.c32" >> $1/noram.cfg
823 fi
825 # Restore real label names
826 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
827 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
828 while read pat; do
829 sed -i "s/slitaz$pat/" $files
830 done
831 status
832 }
835 # Uncompress rootfs or module to stdout
837 uncompress() {
838 zcat $1 2> /dev/null || xzcat $1 2> /dev/null || unlzma < $1 || cat $i
839 }
842 # Install a missing package
844 install_package() {
845 if [ -z "$2" ]; then
846 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
847 else
848 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
849 fi
850 case "$answer" in
851 y)
852 # We don't want package on host cache.
853 action 'Getting and installing package: %s' "$1"
854 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
855 status ;;
856 *)
857 return 1 ;;
858 esac
859 }
862 # Check iso for loram transformation
864 check_iso_for_loram() {
865 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
866 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
867 }
870 # Build initial rootfs for loram ISO ram/cdrom/http
872 build_initfs() {
873 urliso="mirror.switch.ch/ftp/mirror/slitaz \
874 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
875 mirror3.slitaz.org mirror.slitaz.org"
876 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
877 [ -z "$version" ] && die "Can't find the kernel version." \
878 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
880 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
881 need_lib=false
882 for i in bin dev run mnt proc tmp sys lib/modules; do
883 mkdir -p $TMP_DIR/initfs/$i
884 done
885 ln -s bin $TMP_DIR/initfs/sbin
886 ln -s . $TMP_DIR/initfs/usr
887 for aufs in aufs overlayfs; do
888 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
889 install_package $aufs $version && break
890 done || return 1
891 cp /init $TMP_DIR/initfs/
892 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
893 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
894 $TMP_DIR/initfs/lib/modules 2>/dev/null
895 cp -a /dev/tty0 /dev/fd0 $TMP_DIR/initfs/dev 2>/dev/null
896 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
897 $TMP_DIR/initfs/lib/modules
898 if [ "$1" == 'cdrom' ]; then
899 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
900 else
901 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
902 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
903 install_package linux-squashfs $version || return 1
904 done
905 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
906 $TMP_DIR/initfs/lib/modules
907 ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
908 cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
909 fi
910 for i in $(ls /dev/[hs]d[a-f]*); do
911 cp -a $i $TMP_DIR/initfs/dev
912 done
913 if [ "$1" == 'http' ]; then
914 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
915 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
916 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
917 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
918 cp -a /dev/fuse $TMP_DIR/initfs/dev
919 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
920 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
921 else
922 need_lib=true
923 fi
924 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
925 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
926 else
927 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
928 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
929 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
930 cp -a /lib/librt* $TMP_DIR/initfs/lib
931 cp -a /lib/libdl* $TMP_DIR/initfs/lib
932 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
933 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
934 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
935 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
936 need_lib=true
937 fi
938 cd $TMP_DIR/fs
939 echo 'Getting slitaz-release & ethernet modules...'
940 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
941 uncompress $i | cpio -idmu etc/slitaz-release lib/modules* >/dev/null
942 done
943 cd - > /dev/null
944 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
945 find $TMP_DIR/fs/lib/modules/*/kernel/drivers/net/ethernet \
946 -type f -name '*.ko*' | while read mod; do
947 f=$TMP_DIR/initfs/lib/modules/$(basename $mod | sed s/..z$//)
948 uncompress $mod > $f
949 grep -q alias=pci: $f || rm -f $f
950 done
951 for i in $TMP_DIR/initfs/lib/modules/*.ko ; do
952 f=$(basename $i)..z
953 grep -q $f:$ $TMP_DIR/fs/lib/modules/*/modules.dep && continue
954 deps="$(grep $f: $TMP_DIR/fs/lib/modules/*/modules.dep | sed 's/.*: //')"
955 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > $TMP_DIR/initfs/lib/modules/$(basename $i .ko).dep
956 for j in $deps; do
957 mod=$(ls $TMP_DIR/fs/lib/modules/*/$j)
958 uncompress $mod > $TMP_DIR/initfs/lib/modules/$(basename $j | sed s/..z$//)
959 done
960 done
961 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"
962 _n 'List of URLs to insert: '
963 read -t 30 urliso2
964 urliso="$urliso2 $urliso"
965 fi
966 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
967 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
968 sed -i 's/LD_T.*ot/newline/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
969 else
970 cp /bin/busybox $TMP_DIR/initfs/bin
971 need_lib=true
972 fi
973 for i in $($TMP_DIR/initfs/bin/busybox | awk \
974 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
975 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
976 done
977 for i in /dev/console /dev/loop* /dev/null /dev/tty /dev/zero \
978 /dev/kmem /dev/mem /dev/random /dev/urandom; do
979 cp -a $i $TMP_DIR/initfs/dev
980 done
981 $need_lib && for i in /lib/ld-* /lib/lib[cm].so* /lib/lib[cm]-* ; do
982 cp -a $i $TMP_DIR/initfs/lib
983 done
984 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
985 #!/bin/sh
987 getarg() {
988 grep -q " \$1=" /proc/cmdline || return 1
989 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
990 return 0
991 }
993 copy_rootfs() {
994 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
995 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
996 [ \$(( \$total / \$need )) -gt 1 ] || return 1
997 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
998 path=/mnt/
999 return 0
1000 else
1001 rm -f /mnt/rootfs*
1002 return 1
1003 fi
1006 echo "Switching / to tmpfs..."
1007 mount -t proc proc /proc
1008 size="\$(grep rootfssize= < /proc/cmdline | \\
1009 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1010 [ -n "\$size" ] || size="-o size=90%"
1012 mount -t sysfs sysfs /sys
1013 for i in /lib/modules/*.ko ; do
1014 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1015 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1016 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1017 insmod /lib/modules/\$k.ko 2> /dev/null
1018 done
1019 insmod \$i 2> /dev/null
1020 break
1021 done
1022 done
1023 umount /sys
1024 while read var default; do
1025 eval \$var=\$default
1026 getarg \$var \$var
1027 done <<EOT
1028 eth eth0
1029 dns 208.67.222.222,208.67.220.220
1030 netmask 255.255.255.0
1031 gw
1032 ip
1033 EOT
1034 if [ -n "\$ip" ]; then
1035 ifconfig \$eth \$ip netmask \$netmask up
1036 route add default gateway \$gw
1037 for i in \$(echo \$dns | sed 's/,/ /g'); do
1038 echo "nameserver \$i" >> /etc/resolv.conf
1039 done
1040 else
1041 udhcpc -f -q -s /lib/udhcpc -i \$eth
1042 fi
1043 for i in $urliso ; do
1044 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1045 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"
1046 done
1047 getarg urliso URLISO
1048 DIR=fs
1049 if getarg loram DIR; then
1050 DEVICE=\${DIR%,*}
1051 DIR=/\${DIR#*,}
1052 fi
1053 mount -t tmpfs \$size tmpfs /mnt
1054 path2=/mnt/.httpfs/
1055 path=/mnt/.cdrom/
1056 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1057 while [ ! -d \$path/boot ]; do
1058 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1059 httpfs \$i \$path2 && break
1060 done
1061 mount -o loop,ro -t iso9660 \$path2/*.iso \$path
1062 done
1064 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1065 umount /proc
1066 branch=:/mnt/.cdrom/\$DIR
1067 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1068 branch=
1069 for i in \${path}rootfs* ; do
1070 fs=\${i#*root}
1071 branch=\$branch:/mnt/.\$fs
1072 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1073 insmod /lib/modules/squashfs.ko 2> /dev/null
1074 mount -o loop,ro -t squashfs \${path}root\$fs /mnt/.\$fs
1075 done
1076 else
1077 mkdir -p /mnt/.rw/mnt/.httpfs
1078 fi
1079 while read type opt; do
1080 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1081 done <<EOT
1082 aufs br=/mnt/.rw\$branch
1083 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1084 EOT
1085 rm -rf /lib/modules
1086 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1087 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1088 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1089 EOTEOT
1090 chmod +x $TMP_DIR/initfs/init
1091 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1092 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1093 rm -f $i
1094 dogzip ${i%.gz}
1095 done 2>/dev/null
1096 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1097 lzma e $TMP_DIR/initfs.gz -si
1098 lzma_set_size $TMP_DIR/initfs.gz
1099 rm -rf $TMP_DIR/initfs
1100 align_to_32bits $TMP_DIR/initfs.gz
1101 return 0
1105 # Move each initramfs to squashfs
1107 build_loram_rootfs() {
1108 rootfs_sizes=""
1109 for i in $TMP_DIR/iso/boot/rootfs*; do
1110 mkdir -p $TMP_DIR/fs
1111 cd $TMP_DIR/fs
1112 uncompress $i | cpio -idm
1113 deduplicate
1114 cd - > /dev/null
1115 rootfs=$TMP_DIR/$(basename $i)
1116 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp xz -Xbcj x86
1117 cd $TMP_DIR
1118 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1119 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1120 rm -f $rootfs
1121 mv $rootfs.cpio $rootfs
1122 cd - > /dev/null
1123 rm -rf $TMP_DIR/fs
1124 done
1128 # Move meta boot configuration files to basic configuration files
1129 # because meta loram flavor is useless when rootfs is not loaded in RAM
1131 unmeta_boot() {
1132 local root=${1:-$TMP_DIR/loramiso}
1133 if [ -f $root/boot/isolinux/noram.cfg ]; then
1134 # We keep enough information to do unloram...
1135 [ -s $root/boot/isolinux/common.cfg ] &&
1136 sed -i 's/label slitaz/label orgslitaz/' \
1137 $root/boot/isolinux/common.cfg
1138 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1139 shift
1140 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1141 $root/boot/isolinux/isolinux.cfg
1142 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1143 sed -i "s/label $3\$/label slitaz/;s|=/boot/rootfs\(.*\).gz |=/boot/rootfs.gz |" \
1144 $root/boot/isolinux/*.cfg
1145 fi
1149 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1150 # These squashfs may be loaded in RAM at boot time.
1151 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1152 # Meta flavors are converted to normal flavors.
1154 build_loram_cdrom() {
1155 build_initfs cdrom || return 1
1156 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1157 mkdir $TMP_DIR/loramiso/fs
1158 cd $TMP_DIR/loramiso/fs
1159 for i in $( ls ../boot/root* | sort -r ) ; do
1160 uncompress $i | cpio -idmu
1161 rm -f $i
1162 done
1163 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1164 cd - >/dev/null
1165 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1166 unmeta_boot
1167 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1168 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1169 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1170 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1171 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1172 create_iso $OUTPUT $TMP_DIR/loramiso
1176 # Create http bootstrap to load and remove loram_cdrom
1177 # Meta flavors are converted to normal flavors.
1179 build_loram_http() {
1180 build_initfs http || return 1
1181 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1182 rm -f $TMP_DIR/loramiso/boot/rootfs*
1183 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1184 unmeta_boot
1185 create_iso $OUTPUT $TMP_DIR/loramiso
1189 # Update meta flavor selection sizes.
1190 # Reduce sizes with rootfs gains.
1192 update_metaiso_sizes() {
1193 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1194 do
1195 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1196 local sizes="$rootfs_sizes"
1197 local new
1198 set -- $append
1199 shift
1200 [ "$1" == "ifmem" ] && shift
1201 new=""
1202 while [ -n "$2" ]; do
1203 local s
1204 case "$1" in
1205 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1206 *M) s=$(( ${1%M} * 1024 ));;
1207 *) s=${1%K};;
1208 esac
1209 sizes=${sizes#* }
1210 for i in $sizes ; do
1211 s=$(( $s - $i ))
1212 done
1213 new="$new $s $2"
1214 shift 2
1215 done
1216 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1217 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1218 sed -i 's|\(initrd=\)\(/boot/rootfs.\.gz\)|\1/boot/rootfs.gz,\2|' $cfg
1219 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1220 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1221 done
1225 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1226 # Meta flavor selection sizes are updated.
1228 build_loram_ram() {
1229 build_initfs ram || return 1
1230 build_loram_rootfs
1231 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1232 make_bzImage_hardlink $TMP_DIR/loramiso/boot
1233 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1234 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1235 update_metaiso_sizes
1236 create_iso $OUTPUT $TMP_DIR/loramiso
1240 # Remove files installed by packages
1242 find_flavor_rootfs() {
1243 for i in $1/etc/tazlito/*.extract; do
1244 [ -e $i ] || continue
1245 chroot $1 /bin/sh ${i#$1}
1246 done
1248 # Clean hardlinks and files patched by genisofs in /boot
1249 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1250 rm -f $1/boot/$i*
1251 done
1253 # Clean files generated in post_install
1254 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1255 $1/dev/core $1/dev/fd $1/dev/std*
1257 # Verify md5
1258 cat $1$INSTALLED/*/md5sum | \
1259 while read md5 file; do
1260 [ -e "$1$file" ] || continue
1261 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1262 rm -f "$1$file"
1263 done
1265 # Check configuration files
1266 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1267 [ -e $i ] || continue
1268 mkdir /tmp/volatile$$
1269 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1270 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1271 while read file ; do
1272 [ -e "$1/$file" ] || continue
1273 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1274 done
1275 rm -rf /tmp/volatile$$
1276 done
1278 # Remove other files blindly
1279 for i in $1$INSTALLED/*/files.list; do
1280 for file in $(cat "$i"); do
1281 [ "$1$file" -nt "$i" ] && continue
1282 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1283 [ -d "$1$file" ] || rm -f "$1$file"
1284 done
1285 done
1287 # Remove tazpkg files and tmp files
1288 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1289 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1290 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1291 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1292 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1294 # Cleanup directory tree
1295 cd $1
1296 find * -type d | sort -r | while read dir; do
1297 rmdir "$dir" 2>/dev/null
1298 done
1299 cd - > /dev/null
1303 # Get byte(s) from a binary file
1305 get() {
1306 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null
1310 # Get cpio flavor info from the ISO image
1312 flavordata() {
1313 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1314 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1318 # Restore undigest mirrors
1320 restore_mirrors() {
1321 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1322 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1324 action 'Restoring mirrors...'
1325 if [ -d "$undigest.bak" ]; then
1326 [ -d "$undigest" ] && rm -r "$undigest"
1327 mv "$undigest.bak" "$undigest"
1328 fi
1329 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1330 :; status
1334 # Setup undigest mirrors
1336 setup_mirrors() {
1337 # Setup mirrors in plain system or in chroot (with variable root=)
1338 local mirrorlist="$1" fresh repacked
1339 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1341 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1342 restore_mirrors
1344 _ 'Setting up mirrors for %s...' "$root/"
1345 # Backing up current undigest mirrors and priority
1346 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1347 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1348 rm -rf '/var/www/tazlito/'
1349 mkdir -p '/var/www/tazlito/'
1351 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1352 fresh='/home/slitaz/packages'
1353 if [ -d "$fresh" ]; then
1354 # Setup first undigest mirror
1355 mkdir -p "$undigest/fresh"
1356 echo "$fresh" > "$undigest/fresh/mirror"
1357 echo 'fresh' >> "$priority"
1358 # Rebuild mirror DB if needed
1359 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1360 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1361 tazpkg mkdb "$fresh" --forced --root=''
1362 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1363 fi
1365 # Repacked packages: high priority
1366 repacked="$PACKAGES_REPOSITORY"
1367 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1368 # According to Tazlito setup file (tazlito.conf):
1369 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1370 # or
1371 # WORK_DIR="/home/slitaz"
1372 # and
1373 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1374 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1376 # Setup second undigest mirror
1377 mkdir -p "$undigest/repacked"
1378 echo "$repacked" > "$undigest/repacked/mirror"
1379 echo 'repacked' >> "$priority"
1380 # Rebuild mirror DB if needed
1381 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1382 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1383 tazpkg mkdb "$repacked" --forced --root=''
1384 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1385 fi
1387 # All repositories listed in mirrors list: normal priority
1388 [ -e "$mirrorlist" ] && \
1389 while read mirror; do
1390 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1391 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1392 mkdir -p "$undigest/$mirrorid"
1393 echo "$mirror" > "$undigest/$mirrorid/mirror"
1394 echo "$mirrorid" >> "$priority"
1395 done < "$mirrorlist"
1397 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1399 # Show list of mirrors
1400 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1401 function show(num, name, url) {
1402 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1405 num++;
1406 "cat " db "/undigest/" $0 "/mirror" | getline url;
1407 show(num, $0, url);
1409 END {
1410 num++;
1411 "cat " db "/mirror" | getline url;
1412 show(num, "main", url);
1413 }' "$priority"
1415 tazpkg recharge --quiet >/dev/null
1419 # Get list of 'packages.info' lists using priority
1421 pi_lists() {
1422 local pi
1423 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1424 local priority="$root$LOCALSTATE/priority"
1425 local undigest="$root$LOCALSTATE/undigest"
1428 [ -s "$priority" ] && cat "$priority"
1429 echo 'main'
1430 [ -d "$undigest" ] && ls "$undigest"
1431 } | awk -vun="$undigest/" '
1433 if (arr[$0] != 1) {
1434 arr[$0] = 1;
1435 print un $0 "/packages.info";
1437 }' | sed 's|/undigest/main||' | \
1438 while read pi; do
1439 [ -e "$pi" ] && echo "$pi"
1440 done
1444 # Strip versions from packages list
1446 strip_versions() {
1447 action 'Strip versions from list %s...' "$(basename "$1")"
1448 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1449 [ -f "$in_list" ] || die "List '$in_list' not found."
1451 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1452 awk '
1454 if (FILENAME ~ "packages.info") {
1455 # Collect package names
1456 FS = "\t"; pkg[$1] = 1;
1457 } else {
1458 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1459 while (NF > 1 && ! pkg[$0])
1460 NF --;
1461 printf "%s\n", $0;
1463 }' $(pi_lists) "$in_list" > "$tmp_list"
1465 cat "$tmp_list" > "$in_list"
1466 rm "$tmp_list"
1467 status
1471 # Display list of unknown packages (informative)
1473 display_unknown() {
1474 [ -s "$1" ] || return
1475 echo "Unknown packages:" >&2
1476 cat "$1" >&2
1477 rm "$1"
1481 # Display warnings about critical packages absent (informative)
1483 display_warn() {
1484 [ -s "$1" ] || return
1485 echo "Absent critical packages:" >&2
1486 cat "$1" >&2
1487 rm "$1"
1488 echo "Probably ISO image will be unusable."
1492 # Install packages to rootfs
1494 install_list_to_rootfs() {
1495 local list="$1" rootfs="$2" pkg i ii
1496 local undigest="$rootfs/var/lib/tazpkg/undigest"
1498 # initial tazpkg setup in empty rootfs
1499 tazpkg --root=$rootfs >/dev/null 2>&1
1500 # link rootfs packages cache to the regular packages cache
1501 rm -r "$rootfs/var/cache/tazpkg"
1502 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1504 setup_mirrors mirrors
1506 # Just in case if flavor not contains "tazlito" package
1507 mkdir -p "$rootfs/etc/tazlito"
1509 newline
1510 for pkg in $(cat $list); do
1511 action 'Installing package: %s' "$pkg"
1512 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1513 status
1514 done
1515 newline
1517 restore_mirrors
1518 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1519 for i in fresh repacked; do
1520 ii="$undigest/$i"
1521 [ -d "$ii" ] && rm -rf "$ii"
1522 ii="$rootfs/var/lib/tazpkg/priority"
1523 if [ -f "$ii" ]; then
1524 sed -i "/$i/d" "$ii"
1525 [ -s "$ii" ] || rm "$ii"
1526 fi
1527 done
1528 [ -d "$undigest" ] && \
1529 for i in $(find "$undigest" -type f); do
1530 # Remove all undigest PKGDB files but 'mirror'
1531 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1532 done
1533 [ -d "$undigest" ] && \
1534 rmdir --ignore-fail-on-non-empty "$undigest"
1536 # Un-link packages cache
1537 rm "$rootfs/var/cache/tazpkg"
1539 # Clean /var/lib/tazpkg
1540 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1546 ####################
1547 # Tazlito commands #
1548 ####################
1550 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1551 case "$0" in
1552 *reduplicate)
1553 find ${@:-.} ! -type d -links +1 \
1554 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1555 exit 0 ;;
1556 *deduplicate)
1557 deduplicate "$@"
1558 exit 0 ;;
1559 esac
1562 case "$COMMAND" in
1563 stats)
1564 # Tazlito general statistics from the config file.
1566 title 'Tazlito statistics'
1567 optlist "\
1568 Config file : $CONFIG_FILE
1569 ISO name : $ISO_NAME.iso
1570 Volume name : $VOLUM_NAME
1571 Prepared : $PREPARED
1572 Packages repository : $PACKAGES_REPOSITORY
1573 Distro directory : $DISTRO
1574 Additional files : $ADDFILES
1575 " | sed '/: $/d'
1576 footer
1577 ;;
1580 list-addfiles)
1581 # Simple list of additional files in the rootfs
1582 newline
1583 if [ -d "$ADDFILES/rootfs" ]; then
1584 cd $ADDFILES
1585 find rootfs -type f
1586 else
1587 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1588 fi
1589 newline
1590 ;;
1593 gen-config)
1594 # Generate a new config file in the current dir or the specified
1595 # directory by $2.
1597 if [ -n "$2" ]; then
1598 mkdir -p "$2" && cd "$2"
1599 fi
1601 newline
1602 action 'Generating empty tazlito.conf...'
1603 empty_config_file
1604 status
1606 separator
1607 if [ -f 'tazlito.conf' ] ; then
1608 _ 'Configuration file is ready to edit.'
1609 _ 'File location: %s' "$(pwd)/tazlito.conf"
1610 newline
1611 fi
1612 ;;
1615 configure)
1616 # Configure a tazlito.conf config file. Start by getting
1617 # a empty config file and sed it.
1619 if [ -f 'tazlito.conf' ]; then
1620 rm tazlito.conf
1621 else
1622 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1623 'or in the same directory of the file you want to configure.'
1624 cd /etc
1625 fi
1627 empty_config_file
1629 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1631 # ISO name.
1632 echo -n "ISO name : " ; read answer
1633 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1634 # Volume name.
1635 echo -n "Volume name : " ; read answer
1636 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1637 # Packages repository.
1638 echo -n "Packages repository : " ; read answer
1639 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1640 # Distro path.
1641 echo -n "Distro path : " ; read answer
1642 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1643 footer "Config file is ready to use."
1644 echo 'You can now extract an ISO or generate a distro.'
1645 newline
1646 ;;
1649 gen-iso)
1650 # Simply generate a new iso.
1652 check_root
1653 verify_rootcd
1654 gen_livecd_isolinux
1655 distro_stats
1656 ;;
1659 gen-initiso)
1660 # Simply generate a new initramfs with a new iso.
1662 check_root
1663 verify_rootcd
1664 gen_initramfs "$ROOTFS"
1665 gen_livecd_isolinux
1666 distro_stats
1667 ;;
1670 extract-distro)
1671 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1673 check_root
1674 ISO_IMAGE="$2"
1675 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1676 'Example:\n tazlito image.iso /path/target'
1678 # Set the distro path by checking for $3 on cmdline.
1679 TARGET="${3:-$DISTRO}"
1681 # Exit if existing distro is found.
1682 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1683 'Please clean the distro tree or change directory path.'
1685 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
1687 # Start to mount the ISO.
1688 action 'Mounting ISO image...'
1689 mkdir -p "$TMP_DIR"
1690 # Get ISO file size.
1691 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
1692 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
1693 sleep 2
1694 # Prepare target dir, copy the kernel and the rootfs.
1695 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
1696 status
1698 action 'Copying the Linux kernel...'
1699 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
1700 make_bzImage_hardlink "$TARGET/rootcd/boot"
1701 else
1702 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
1703 fi
1704 status
1706 for i in $(ls $TMP_DIR); do
1707 [ "$i" == 'boot' ] && continue
1708 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
1709 done
1711 for loader in isolinux syslinux extlinux grub; do
1712 [ -d "$TMP_DIR/boot/$loader" ] || continue
1713 action 'Copying %s files...' "$loader"
1714 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
1715 status
1716 done
1718 action 'Copying the rootfs...'
1719 cp $TMP_DIR/boot/rootfs.?z "$TARGET/rootcd/boot"
1720 status
1722 # Extract initramfs.
1723 cd "$TARGET/rootfs"
1724 action 'Extracting the rootfs...'
1725 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
1726 # unpack /usr
1727 for i in etc/tazlito/*.extract; do
1728 [ -f "$i" ] && . $i ../rootcd
1729 done
1730 # Umount and remove temp directory and cd to $TARGET to get stats.
1731 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
1732 cd ..
1733 status
1735 newline
1736 separator
1737 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
1738 echo "Distro tree : $(pwd)"
1739 echo "Rootfs size : $(du -sh rootfs)"
1740 echo "Rootcd size : $(du -sh rootcd)"
1741 footer
1742 ;;
1745 list-flavors)
1746 # Show available flavors.
1747 local list='/etc/tazlito/flavors.list'
1748 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
1749 title 'List of flavors'
1750 cat $list
1751 footer
1752 ;;
1755 show-flavor)
1756 # Show flavor description.
1757 set -e
1758 flavor=${2%.flavor}
1759 flv_dir="$(extract_flavor "$flavor")"
1760 desc="$flv_dir/$flavor.desc"
1761 if [ -n "$brief" ]; then
1762 if [ -z "$noheader" ]; then
1763 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
1764 separator
1765 fi
1766 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
1767 "$(field ISO "$desc")" \
1768 "$(field Rootfs "$desc")" \
1769 "$(field Description "$desc")"
1770 else
1771 separator
1772 cat "$desc"
1773 fi
1774 cleanup
1775 ;;
1778 gen-liveflavor)
1779 # Generate a new flavor from the live system.
1780 FLAVOR=${2%.flavor}
1781 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1783 case "$FLAVOR" in
1784 -?|-h*|--help)
1785 cat <<EOT
1786 SliTaz Live Tool - Version: $VERSION
1788 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
1790 $(boldify '<flavor-patch-file> format:')
1791 $(optlist "\
1792 code data
1793 + package to add
1794 - package to remove
1795 ! non-free package to add
1796 ? display message
1797 @ flavor description
1798 ")
1800 $(boldify 'Example:')
1801 $(optlist "\
1802 @ Developer tools for SliTaz maintainers
1803 + slitaz-toolchain
1804 + mercurial
1805 ")
1806 EOT
1807 exit 1
1808 ;;
1809 esac
1810 mv /etc/tazlito/distro-packages.list \
1811 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
1812 rm -f distro-packages.list non-free.list 2>/dev/null
1813 tazpkg recharge
1815 DESC=""
1816 [ -n "$3" ] && \
1817 while read action pkg; do
1818 case "$action" in
1819 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
1820 -) yes | tazpkg remove $pkg ;;
1821 !) echo $pkg >> non-free.list ;;
1822 @) DESC="$pkg" ;;
1823 \?) echo -en "$pkg"; read action ;;
1824 esac
1825 done < $3
1827 yes '' | tazlito gen-distro
1828 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
1829 mv /etc/tazlito/distro-packages.list.$$ \
1830 /etc/tazlito/distro-packages.list 2>/dev/null
1831 ;;
1834 gen-flavor)
1835 # Generate a new flavor from the last ISO image generated
1836 FLAVOR=${2%.flavor}
1837 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1839 title 'Flavor generation'
1840 check_rootfs
1841 FILES="$FLAVOR.pkglist"
1843 action 'Creating file %s...' "$FLAVOR.flavor"
1844 for i in rootcd rootfs; do
1845 if [ -d "$ADDFILES/$i" ] ; then
1846 FILES="$FILES\n$FLAVOR.$i"
1847 (cd "$ADDFILES/$i"; find . | cpio -o -H newc 2>/dev/null | gzip -9) > $FLAVOR.$i
1848 fi
1849 done
1850 status
1852 answer=$(grep -s ^Description $FLAVOR.desc)
1853 answer=${answer#Description : }
1854 if [ -z "$answer" ]; then
1855 echo -n "Description: "
1856 read answer
1857 fi
1859 action 'Compressing flavor %s...' "$FLAVOR"
1860 echo "Flavor : $FLAVOR" > $FLAVOR.desc
1861 echo "Description : $answer" >> $FLAVOR.desc
1862 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
1863 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
1864 for i in $(ls $ROOTFS$INSTALLED); do
1865 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
1866 EXTRAVERSION=""
1867 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
1868 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
1869 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
1870 echo "$i" >> $FLAVOR.nonfree
1871 else
1872 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
1873 fi
1874 done
1875 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
1876 for i in $LOCALSTATE/undigest/*/mirror ; do
1877 [ -s $i ] && cat $i >> $FLAVOR.mirrors
1878 done
1879 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
1880 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
1881 rm $(echo -e $FILES)
1882 status
1884 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
1885 ;;
1888 upgrade-flavor)
1889 # Strip versions from pkglist and update estimated numbers in flavor.desc
1890 flavor="${2%.flavor}"
1891 set -e
1892 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1893 set +e
1895 flv_dir="$(extract_flavor "$flavor")"
1897 strip_versions "$flv_dir/$flavor.pkglist"
1899 action 'Updating %s...' "$flavor.desc"
1901 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
1902 set -- $(module calc_sizes "$flv_dir" "$flavor")
1903 restore_mirrors >/dev/null
1905 sed -i -e '/Image is ready/d' \
1906 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
1907 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
1908 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
1909 -e "s|\(Packages *:\).*$|\1 $4|" \
1910 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
1911 "$flv_dir/$flavor.desc"
1913 pack_flavor "$flv_dir" "$flavor"
1914 status
1915 display_unknown "$flv_dir/err"
1916 display_warn "$flv_dir/warn"
1917 cleanup
1918 ;;
1921 extract-flavor)
1922 # Extract a flavor into $FLAVORS_REPOSITORY
1923 flavor="${2%.flavor}"
1924 set -e
1925 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1926 set +e
1928 action 'Extracting %s...' "$flavor.flavor"
1929 flv_dir="$(extract_flavor "$flavor" full)"
1930 storage="$FLAVORS_REPOSITORY/$flavor"
1932 rm -rf "$storage" 2>/dev/null
1933 mkdir -p "$storage"
1934 cp -a "$flv_dir"/* "$storage"
1935 rm "$storage/description"
1936 status
1938 strip_versions "$storage/packages.list"
1940 cleanup
1941 ;;
1944 pack-flavor)
1945 # Create a flavor from $FLAVORS_REPOSITORY.
1946 flavor=${2%.flavor}
1947 storage="$FLAVORS_REPOSITORY/$flavor"
1949 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
1951 action 'Creating flavor %s...' "$flavor"
1952 tmp_dir="$(mktemp -d)"
1954 while read from to; do
1955 [ -s "$storage/$from" ] || continue
1956 cp -a "$storage/$from" "$tmp_dir/$to"
1957 done <<EOT
1958 mirrors $flavor.mirrors
1959 distro.sh $flavor-distro.sh
1960 receipt $flavor.receipt
1961 non-free.list $flavor.nonfree
1962 EOT
1964 # Build the package list.
1965 # It can include a list from another flavor with the keyword @include
1966 if [ -s "$storage/packages.list" ]; then
1967 include=$(grep '^@include' "$storage/packages.list")
1968 if [ -n "$include" ]; then
1969 include=${include#@include }
1970 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
1971 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
1972 else
1973 echo -e "\nERROR: Can't find include package list from $include\n"
1974 fi
1975 fi
1976 # Generate the final/initial package list
1977 [ -s "$storage/packages.list" ] && \
1978 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
1979 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
1980 fi
1982 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
1983 # Process multi-rootfs flavor
1984 . "$storage/receipt"
1985 set -- $ROOTFS_SELECTION
1986 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
1987 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
1988 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
1990 for i in rootcd rootfs; do
1991 mkdir "$tmp_dir/$i"
1992 # Copy extra files from the first flavor
1993 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
1994 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
1995 # Overload extra files by meta flavor
1996 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
1997 [ -n "$(ls $tmp_dir/$i)" ] &&
1998 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
1999 dogzip "$tmp_dir/$flavor.$i"
2000 rm -rf "$tmp_dir/$i"
2001 done
2002 else
2003 # Process plain flavor
2004 for i in rootcd rootfs; do
2005 [ -d "$storage/$i" ] || continue
2006 (cd "$storage/$i";
2007 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2008 done
2009 fi
2011 unset VERSION MAINTAINER ROOTFS_SELECTION
2012 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2013 ROOTFS_SIZE="$1 (estimated)"
2014 INITRAMFS_SIZE="$2 (estimated)"
2015 ISO_SIZE="$3 (estimated)"
2016 PKGNUM="$4"
2017 . "$storage/receipt"
2019 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2020 Flavor : $FLAVOR
2021 Description : $SHORT_DESC
2022 Version : $VERSION
2023 Maintainer : $MAINTAINER
2024 LiveCD RAM size : $FRUGAL_RAM
2025 Rootfs list : $ROOTFS_SELECTION
2026 Build date : $(date '+%Y%m%d at %T')
2027 Packages : $PKGNUM
2028 Rootfs size : $ROOTFS_SIZE
2029 Initramfs size : $INITRAMFS_SIZE
2030 ISO image size : $ISO_SIZE
2031 ================================================================================
2033 EOT
2035 rm -f $tmp_dir/packages.list
2036 pack_flavor "$tmp_dir" "$flavor"
2037 status
2038 display_unknown "$tmp_dir/err"
2039 display_warn "$flv_dir/warn"
2040 cleanup
2041 ;;
2044 get-flavor)
2045 # Get a flavor's files and prepare for gen-distro.
2046 flavor=${2%.flavor}
2047 title 'Preparing %s distro flavor' "$flavor"
2048 set -e
2049 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2050 set +e
2052 action 'Cleaning %s...' "$DISTRO"
2053 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2054 # Clean old files
2055 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2056 [ -f "$i" ] && rm "$i"
2057 done
2058 mkdir -p "$DISTRO"
2059 status
2061 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2063 action 'Extracting flavor %s...' "$flavor.flavor"
2064 flv_dir="$(extract_flavor "$flavor" info)"
2065 cp -a "$flv_dir"/* .
2066 mv packages.list distro-packages.list
2067 mv -f info /etc/tazlito
2068 status
2070 for i in rootcd rootfs; do
2071 if [ -d "$i" ]; then
2072 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2073 fi
2074 done
2076 rm -f /etc/tazlito/rootfs.list
2077 grep -q '^Rootfs list' description &&
2078 grep '^Rootfs list' description | sed 's/.*: \(.*\)$/\1/' > /etc/tazlito/rootfs.list
2080 action 'Updating %s...' 'tazlito.conf'
2081 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2082 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2083 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2084 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2085 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2086 status
2088 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2089 cleanup
2090 ;;
2093 iso2flavor)
2094 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2095 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2097 FLAVOR=${3%.flavor}
2098 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2099 mount -o loop,ro $2 $TMP_DIR/iso
2100 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2101 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2102 ! -s $TMP_DIR/flavor/*.desc ]; then
2103 _ 'META flavors are not supported.'
2104 umount -d $TMP_DIR/iso
2105 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2106 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2107 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2108 umount -d $TMP_DIR/iso
2109 else
2110 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2111 uncompress $i | \
2112 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2113 done
2114 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2115 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2116 '/etc/slitaz-release' '/boot/rootfs.gz'
2117 umount -d $TMP_DIR/iso
2118 else
2119 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2120 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2121 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2122 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2123 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2124 umount -d $TMP_DIR/iso
2125 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2126 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2127 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2128 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2129 < $TMP_DIR/rootfs$INSTALLED.md5
2130 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2131 if [ -s $TMP_DIR/flavor/*desc ]; then
2132 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2133 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2134 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2135 for i in rootfs rootcd ; do
2136 [ -s $TMP_DIR/flavor/*.list$i ] &&
2137 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2138 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2139 done
2140 else
2141 find_flavor_rootfs $TMP_DIR/rootfs
2142 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2143 for i in rootfs rootcd ; do
2144 [ "$(ls $TMP_DIR/$i)" ] &&
2145 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2146 done
2147 unset VERSION MAINTAINER
2148 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2149 if [ -n "$DESCRIPTION" ]; then
2150 _n 'Flavor version : '; read -t 30 VERSION
2151 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2152 fi
2154 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2155 Flavor : $FLAVOR
2156 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2157 Version : ${VERSION:-1.0}
2158 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2159 LiveCD RAM size : $RAM_SIZE
2160 Build date : $BUILD_DATE
2161 Packages : $PKGCNT
2162 Rootfs size : $ROOTFS_SIZE
2163 Initramfs size : $INITRAMFS_SIZE
2164 ISO image size : $ISO_SIZE
2165 ================================================================================
2167 EOT
2168 longline "Tazlito can't detect each file installed during \
2169 a package post_install. You should extract this flavor (tazlito extract-flavor \
2170 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2171 tree and remove files generated by post_installs.
2172 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2173 repack the flavor (tazlito pack-flavor $FLAVOR)"
2174 fi
2175 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2176 fi
2177 fi
2178 rm -rf $TMP_DIR
2179 ;;
2182 gen-distro)
2183 # Generate a live distro tree with a set of packages.
2185 check_root
2186 start_time=$(date +%s)
2188 # Tazlito options: --iso or --cdrom
2189 CDROM=''
2190 [ -n "$iso" ] && CDROM="-o loop $iso"
2191 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2193 # Check if a package list was specified on cmdline.
2194 if [ -f "$2" ]; then
2195 LIST_NAME="$2"
2196 else
2197 LIST_NAME='distro-packages.list'
2198 fi
2200 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2201 'Please clean the distro tree or change directory path.'
2202 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2203 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2205 # If list not given: build list with all installed packages
2206 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2207 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2208 fi
2210 # Exit if no list name.
2211 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2213 # Start generation.
2214 title 'Tazlito generating a distro'
2216 # Misc checks
2217 mkdir -p "$PACKAGES_REPOSITORY"
2218 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2219 newline
2221 # Mount CD-ROM to be able to repack boot-loader packages
2222 if [ ! -e /boot -a -n "$CDROM" ]; then
2223 mkdir $TMP_MNT
2224 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2225 ln -s "$TMP_MNT/boot" /
2226 if [ ! -d "$ADDFILES/rootcd" ] ; then
2227 mkdir -p "$ADDFILES/rootcd"
2228 for i in $(ls $TMP_MNT); do
2229 [ "$i" == 'boot' ] && continue
2230 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2231 done
2232 fi
2233 else
2234 rmdir "$TMP_MNT"
2235 fi
2236 fi
2238 # Rootfs stuff.
2239 echo 'Preparing the rootfs directory...'
2240 mkdir -p "$ROOTFS"
2241 export root="$ROOTFS"
2242 strip_versions "$LIST_NAME"
2244 if [ "$REPACK" == 'y' ]; then
2245 # Determine full packages list with all dependencies
2246 tmp_dir="$(mktemp -d)"
2247 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2248 touch "$tmp_dir/full.pkglist"
2249 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2251 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2252 while read pkgname pkgver; do
2253 # Is package in full list?
2254 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2255 # Is package already repacked?
2256 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2257 _ 'Repacking %s...' "$pkgname-$pkgver"
2258 tazpkg repack "$pkgname" --quiet
2259 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2260 status
2261 done
2263 rm -r "$tmp_dir"
2264 fi
2266 if [ -f non-free.list ]; then
2267 # FIXME: working in the ROOTFS chroot?
2268 newline
2269 echo 'Preparing non-free packages...'
2270 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2271 for pkg in $(cat 'non-free.list'); do
2272 if [ ! -d "$INSTALLED/$pkg" ]; then
2273 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2274 tazpkg get-install get-$pkg
2275 fi
2276 get-$pkg "$ROOTFS"
2277 fi
2278 tazpkg repack $pkg
2279 pkg=$(ls $pkg*.tazpkg)
2280 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2281 mv $pkg $PACKAGES_REPOSITORY
2282 done
2283 fi
2284 cp $LIST_NAME $DISTRO/distro-packages.list
2285 newline
2287 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2289 cd $DISTRO
2290 cp distro-packages.list $ROOTFS/etc/tazlito
2291 # Copy all files from $ADDFILES/rootfs to the rootfs.
2292 if [ -d "$ADDFILES/rootfs" ] ; then
2293 action 'Copying addfiles content to the rootfs...'
2294 cp -a $ADDFILES/rootfs/* $ROOTFS
2295 status
2296 fi
2298 action 'Root filesystem is generated...'; status
2300 # Root CD part.
2301 action 'Preparing the rootcd directory...'
2302 mkdir -p $ROOTCD
2303 status
2305 # Move the boot dir with the Linux kernel from rootfs.
2306 # The boot dir goes directly on the CD.
2307 if [ -d "$ROOTFS/boot" ] ; then
2308 action 'Moving the boot directory...'
2309 mv $ROOTFS/boot $ROOTCD
2310 cd $ROOTCD/boot
2311 make_bzImage_hardlink
2312 status
2313 fi
2314 cd $DISTRO
2315 # Copy all files from $ADDFILES/rootcd to the rootcd.
2316 if [ -d "$ADDFILES/rootcd" ] ; then
2317 action 'Copying addfiles content to the rootcd...'
2318 cp -a $ADDFILES/rootcd/* $ROOTCD
2319 status
2320 fi
2321 # Execute the distro script used to perform tasks in the rootfs
2322 # before compression. Give rootfs path in arg
2323 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2324 if [ -x "$DISTRO_SCRIPT" ]; then
2325 echo 'Executing distro script...'
2326 sh $DISTRO_SCRIPT $DISTRO
2327 fi
2329 # Execute the custom_rules() found in receipt.
2330 if [ -s "$TOP_DIR/receipt" ]; then
2331 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2332 echo -e "Executing: custom_rules()\n"
2333 . "$TOP_DIR/receipt"
2334 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2335 fi
2336 fi
2338 # Multi-rootfs
2339 if [ -s /etc/tazlito/rootfs.list ]; then
2341 FLAVOR_LIST="$(awk '{
2342 for (i = 2; i <= NF; i+=2)
2343 printf "%s ", i;
2344 }' /etc/tazlito/rootfs.list)"
2346 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2347 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2348 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2350 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2351 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2352 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2353 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2355 n=0
2356 last=$ROOTFS
2357 while read flavor; do
2358 n=$(($n+1))
2359 mkdir ${ROOTFS}0$n
2360 export root="${ROOTFS}0$n"
2361 # initial tazpkg setup in empty rootfs
2362 tazpkg --root=$root >/dev/null 2>&1
2364 newline
2365 boldify "Building $flavor rootfs..."
2367 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2368 cp "$TOP_DIR/$flavor.flavor" .
2370 if [ ! -s "$flavor.flavor" ]; then
2371 # We may have it in $FLAVORS_REPOSITORY
2372 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2373 tazlito pack-flavor $flavor
2374 else
2375 download $flavor.flavor
2376 fi
2377 fi
2379 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2380 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2381 cp $flavor.pkglist $DISTRO/list-packages0$n
2382 status
2384 strip_versions "$DISTRO/list-packages0$n"
2386 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2388 rm -rf ${ROOTFS}0$n/boot
2390 cd $DISTRO
2391 if [ -s $flavor.rootfs ]; then
2392 _n 'Adding %s rootfs extra files...' "$flavor"
2393 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2394 fi
2396 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2397 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2398 status
2400 rm -f $flavor.flavor install-list
2401 mergefs ${ROOTFS}0$n $last
2402 last=${ROOTFS}0$n
2403 done <<EOT
2404 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2405 EOT
2406 #'
2407 i=$(($n+1))
2408 while [ $n -gt 0 ]; do
2409 mv ${ROOTFS}0$n ${ROOTFS}$i
2410 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2411 gen_initramfs ${ROOTFS}$i
2412 n=$(($n-1))
2413 i=$(($i-1))
2414 export LZMA_HISTORY_BITS=26
2415 done
2416 mv $ROOTFS ${ROOTFS}$i
2417 gen_initramfs ${ROOTFS}$i
2418 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2419 else
2420 # Initramfs and ISO image stuff.
2421 gen_initramfs $ROOTFS
2422 fi
2423 gen_livecd_isolinux
2424 distro_stats
2425 cleanup
2426 ;;
2429 clean-distro)
2430 # Remove old distro tree.
2432 check_root
2433 title 'Cleaning: %s' "$DISTRO"
2434 if [ -d "$DISTRO" ] ; then
2435 if [ -d "$ROOTFS" ] ; then
2436 action 'Removing the rootfs...'
2437 rm -f $DISTRO/$INITRAMFS
2438 rm -rf $ROOTFS
2439 status
2440 fi
2441 if [ -d "$ROOTCD" ] ; then
2442 action 'Removing the rootcd...'
2443 rm -rf $ROOTCD
2444 status
2445 fi
2446 action 'Removing eventual ISO image...'
2447 rm -f $DISTRO/$ISO_NAME.iso
2448 rm -f $DISTRO/$ISO_NAME.md5
2449 status
2450 fi
2451 footer
2452 ;;
2455 check-distro)
2456 # Check for a few LiveCD needed files not installed by packages.
2458 # TODO: Remove this function.
2459 # First two files are maintained by tazpkg while it runs on rootfs,
2460 # while last one file should be maintained by tazlito itself.
2461 check_rootfs
2462 title 'Checking distro: %s' "$ROOTFS"
2463 # SliTaz release info.
2464 rel='/etc/slitaz-release'
2465 if [ ! -f "$ROOTFS$rel" ]; then
2466 _ 'Missing release info: %s' "$rel"
2467 else
2468 action 'Release : %s' "$(cat $ROOTFS$rel)"
2469 status
2470 fi
2471 # Tazpkg mirror.
2472 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2473 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2474 todomsg
2475 else
2476 action 'Mirror configuration exists...'
2477 status
2478 fi
2479 # Isolinux msg
2480 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2481 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2482 todomsg
2483 else
2484 action 'Isolinux message seems good...'
2485 status
2486 fi
2487 footer
2488 ;;
2491 writeiso)
2492 # Writefs to ISO image including /home unlike gen-distro we don't use
2493 # packages to generate a rootfs, we build a compressed rootfs with all
2494 # the current filesystem similar to 'tazusb writefs'.
2496 DISTRO='/home/slitaz/distro'
2497 ROOTCD="$DISTRO/rootcd"
2498 COMPRESSION="${2:-none}"
2499 ISO_NAME="${3:-slitaz}"
2500 check_root
2501 # Start info
2502 title 'Write filesystem to ISO'
2503 longline "The command writeiso will write the current filesystem into a \
2504 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2505 newline
2506 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2508 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2509 # Save some space
2510 rm -rf /var/cache/tazpkg/*
2511 rm -f /var/lib/tazpkg/*.bak
2512 rm -rf $DISTRO
2514 # Optionally remove sound card selection and screen resolution.
2515 if [ -z $LaunchedByTazpanel ]; then
2516 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2517 case $anser in
2518 y)
2519 action 'Removing current sound card and screen configurations...'
2520 rm -f /var/lib/sound-card-driver
2521 rm -f /var/lib/alsa/asound.state
2522 rm -f /etc/X11/xorg.conf ;;
2523 *)
2524 action 'Keeping current sound card and screen configurations...' ;;
2525 esac
2526 status
2527 newline
2529 # Optionally remove i18n settings
2530 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2531 case $anser in
2532 y)
2533 action 'Removing current locale/keymap settings...'
2534 newline > /etc/locale.conf
2535 newline > /etc/keymap.conf ;;
2536 *)
2537 action 'Keeping current locale/keymap settings...' ;;
2538 esac
2539 status
2540 fi
2542 # Clean-up files by default
2543 newline > /etc/udev/rules.d/70-persistent-net.rules
2544 newline > /etc/udev/rules.d/70-persistant-cd.rules
2546 # Create list of files including default user files since it is defined in /etc/passwd
2547 # and some new users might have been added.
2548 cd /
2549 echo 'init' > /tmp/list
2550 for dir in bin etc sbin var dev lib root usr home opt; do
2551 [ -d $dir ] && find $dir
2552 done >> /tmp/list
2554 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2555 [ -d $dir ] && echo $dir
2556 done >> /tmp/list
2558 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2560 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2561 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2562 #fi
2563 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2564 touch /var/log/wtmp
2566 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2567 sed -i "/var\/log\/$removelog/d" /tmp/list
2568 done
2570 # Generate initramfs with specified compression and display rootfs
2571 # size in realtime.
2572 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2574 write_initramfs &
2575 sleep 2
2576 cd - > /dev/null
2577 echo -en "\nFilesystem size:"
2578 while [ ! -f /tmp/rootfs ]; do
2579 sleep 1
2580 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2581 done
2582 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2583 echo -e "\n"
2584 rm -f /tmp/rootfs
2586 # Move freshly generated rootfs to the cdrom.
2587 mkdir -p $ROOTCD/boot
2588 mv -f /$INITRAMFS $ROOTCD/boot
2589 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2591 # Now we need the kernel and isolinux files.
2592 copy_from_cd() {
2593 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2594 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2595 unmeta_boot $ROOTCD
2596 umount /media/cdrom
2599 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2600 copy_from_cd;
2601 elif mount | grep /media/cdrom; then
2602 copy_from_cd;
2603 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2604 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2605 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2606 else
2607 touch /tmp/.write-iso-error
2608 longline "When SliTaz is running in RAM the kernel and bootloader \
2609 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
2610 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
2611 echo -en "----\nENTER to continue..."; read i
2612 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2613 copy_from_cd
2614 fi
2616 # Generate the iso image.
2617 touch /tmp/.write-iso
2618 newline
2619 cd $DISTRO
2620 create_iso $ISO_NAME.iso $ROOTCD
2621 action 'Creating the ISO md5sum...'
2622 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2623 status
2625 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2626 rm -f /tmp/.write-iso
2628 if [ -z $LaunchedByTazpanel ]; then
2629 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2630 case $anser in
2631 y)
2632 umount /dev/cdrom 2>/dev/null
2633 eject
2634 echo -n "Please insert a blank CD-ROM and press ENTER..."
2635 read i && sleep 2
2636 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2637 echo -en "----\nENTER to continue..."; read i ;;
2638 *)
2639 exit 0 ;;
2640 esac
2641 fi
2642 ;;
2645 burn-iso)
2646 # Guess CD-ROM device, ask user and burn the ISO.
2648 check_root
2649 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2650 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2651 # We can specify an alternative ISO from the cmdline.
2652 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2653 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2655 title 'Tazlito burn ISO'
2656 echo "CD-ROM device : /dev/$DRIVE_NAME"
2657 echo "Drive speed : $DRIVE_SPEED"
2658 echo "ISO image : $iso"
2659 footer
2661 case $(yesorno 'Burn ISO image?' 'n') in
2662 y)
2663 title 'Starting Wodim to burn the ISO...'
2664 sleep 2
2665 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2666 footer 'ISO image is burned to CD-ROM.'
2667 ;;
2668 *)
2669 die 'Exiting. No ISO burned.'
2670 ;;
2671 esac
2672 ;;
2675 merge)
2676 # Merge multiple rootfs into one iso.
2678 if [ -z "$2" ]; then
2679 cat <<EOT
2680 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2682 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2683 i.e: rootfsN is a subset of rootfsN-1
2684 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2685 The boot loader will select the rootfs according to the RAM size detected.
2687 Example:
2688 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
2690 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
2691 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
2693 EOT
2694 exit 2
2695 fi
2697 shift # skip merge
2698 append="$1 slitaz1"
2699 shift # skip size1
2700 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
2702 ISO=$1.merged
2704 # Extract filesystems
2705 action 'Mounting %s' "$1"
2706 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
2707 status || cleanup_merge
2709 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2710 make_bzImage_hardlink $TMP_DIR/iso/boot
2711 umount -d $TMP_DIR/mnt
2712 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
2713 _ '%s is already a merged iso. Aborting.' "$1"
2714 cleanup_merge
2715 fi
2716 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
2717 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
2718 if [ ! -f /boot/isolinux/ifmem.c32 -a
2719 ! -f /boot/isolinux/c32box.c32 ]; then
2720 cat <<EOT
2721 No file /boot/isolinux/ifmem.c32
2722 Please install syslinux package !
2723 EOT
2724 rm -rf $TMP_DIR
2725 exit 1
2726 fi
2727 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
2728 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
2729 fi
2731 action 'Extracting %s' 'iso/rootfs.gz'
2732 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
2733 [ -d $TMP_DIR/rootfs1/etc ]
2734 status || cleanup_merge
2736 n=1
2737 while [ -n "$2" ]; do
2738 shift # skip rootfs N-1
2739 p=$n
2740 n=$(($n + 1))
2741 append="$append $1 slitaz$n"
2742 shift # skip size N
2743 mkdir -p $TMP_DIR/rootfs$n
2745 action 'Extracting %s' "$1"
2746 extract_rootfs $1 $TMP_DIR/rootfs$n &&
2747 [ -d "$TMP_DIR/rootfs$n/etc" ]
2748 status || cleanup_merge
2750 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
2751 action 'Creating %s' "rootfs$p.gz"
2752 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
2753 status
2754 done
2755 action 'Creating %s' "rootfs$n.gz"
2756 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
2757 status
2758 rm -f $TMP_DIR/iso/boot/rootfs.gz
2759 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
2760 create_iso $ISO $TMP_DIR/iso
2761 rm -rf $TMP_DIR
2762 ;;
2765 repack)
2766 # Repack an iso with maximum lzma compression ratio.
2768 ISO=$2
2769 mkdir -p $TMP_DIR/mnt
2771 # Extract filesystems
2772 action 'Mounting %s' "$ISO"
2773 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
2774 status || cleanup_merge
2776 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2777 umount -d $TMP_DIR/mnt
2779 for i in $TMP_DIR/iso/boot/rootfs* ; do
2780 action 'Repacking %s' "$(basename $i)"
2781 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
2782 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
2783 align_to_32bits $i
2784 status
2785 done
2787 create_iso $ISO $TMP_DIR/iso
2788 rm -rf $TMP_DIR
2789 ;;
2792 build-loram)
2793 # Build a Live CD for low RAM systems.
2795 ISO="$2"
2796 OUTPUT="$3"
2797 [ -z "$3" ] && \
2798 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
2799 mkdir -p "$TMP_DIR/iso"
2800 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
2801 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
2802 if ! check_iso_for_loram ; then
2803 umount -d "$TMP_DIR/iso"
2804 die "$ISO is not a valid SliTaz live CD. Abort."
2805 fi
2806 case "$4" in
2807 cdrom) build_loram_cdrom ;;
2808 http) build_loram_http ;;
2809 *) build_loram_ram ;;
2810 esac
2811 umount $TMP_DIR/iso # no -d: needs /proc
2812 losetup -d $loopdev
2813 rm -rf $TMP_DIR
2814 ;;
2817 emu-iso)
2818 # Emulate an ISO image with Qemu.
2819 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2820 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
2821 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
2822 echo -e "\nStarting Qemu emulator:\n"
2823 echo -e "qemu $QEMU_OPTS $iso\n"
2824 qemu $QEMU_OPTS $iso
2825 ;;
2828 deduplicate)
2829 # Deduplicate files in a tree
2830 shift
2831 deduplicate "$@"
2832 ;;
2835 usage|*)
2836 # Print usage also for all unknown commands.
2837 usage
2838 ;;
2839 esac
2841 exit 0