tazlito view tazlito @ rev 430

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