tazlito view tazlito @ rev 431

variable lzma history for russian dolls: 24-26 bits (again)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Fri Sep 09 21:26:49 2016 +0200 (2016-09-09)
parents 000740da7eac
children 045897b5020e
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:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
286 -input-charset utf-8 \
287 -A "tazlito $VERSION/$(genisoimage --version)" \
288 -copyright README -P "www.slitaz.org" -boot-info-table $2
289 if [ -x '/usr/bin/isohybrid' ]; then
290 action 'Creating hybrid ISO...'
291 /usr/bin/isohybrid $1 -entry 2 2>/dev/null
292 status
293 fi
295 if [ -s '/etc/tazlito/info' ]; then
296 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
297 action 'Storing ISO info...'
298 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
299 status
300 fi
301 fi
303 if [ -x '/usr/bin/iso2exe' ]; then
304 echo 'Creating EXE header...'
305 /usr/bin/iso2exe $1 2>/dev/null
306 fi
307 }
310 # Generate a new ISO image using isolinux.
312 gen_livecd_isolinux() {
313 # Some packages may want to alter iso
314 genisohooks iso
315 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
317 # Set date for boot msg.
318 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
319 DATE=$(date +%Y%m%d)
320 action 'Setting build date to: %s...' "$DATE"
321 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
322 status
323 fi
325 cd $DISTRO
326 create_iso $ISO_NAME.iso $ROOTCD
328 action 'Creating the ISO md5sum...'
329 md5sum $ISO_NAME.iso > $ISO_NAME.md5
330 status
332 separator
333 # Some packages may want to alter final iso
334 genisohooks final
335 }
338 lzma_history_bits() {
339 #
340 # This generates an ISO which boots with Qemu but gives
341 # rootfs errors in frugal or liveUSB mode.
342 #
343 # local n
344 # local sz
345 # n=20 # 1Mb
346 # sz=$(du -sk $1 | cut -f1)
347 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
348 # n=$(( $n + 1 ))
349 # sz=$(( $sz / 2 ))
350 # done
351 # echo $n
352 echo ${LZMA_HISTORY_BITS:=24}
353 }
356 lzma_switches() {
357 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
358 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
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 export LZMA_HISTORY_BITS=26
2406 done
2407 mv $ROOTFS ${ROOTFS}$i
2408 gen_initramfs ${ROOTFS}$i
2409 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2410 else
2411 # Initramfs and ISO image stuff.
2412 gen_initramfs $ROOTFS
2413 fi
2414 gen_livecd_isolinux
2415 distro_stats
2416 cleanup
2417 ;;
2420 clean-distro)
2421 # Remove old distro tree.
2423 check_root
2424 title 'Cleaning: %s' "$DISTRO"
2425 if [ -d "$DISTRO" ] ; then
2426 if [ -d "$ROOTFS" ] ; then
2427 action 'Removing the rootfs...'
2428 rm -f $DISTRO/$INITRAMFS
2429 rm -rf $ROOTFS
2430 status
2431 fi
2432 if [ -d "$ROOTCD" ] ; then
2433 action 'Removing the rootcd...'
2434 rm -rf $ROOTCD
2435 status
2436 fi
2437 action 'Removing eventual ISO image...'
2438 rm -f $DISTRO/$ISO_NAME.iso
2439 rm -f $DISTRO/$ISO_NAME.md5
2440 status
2441 fi
2442 footer
2443 ;;
2446 check-distro)
2447 # Check for a few LiveCD needed files not installed by packages.
2449 # TODO: Remove this function.
2450 # First two files are maintained by tazpkg while it runs on rootfs,
2451 # while last one file should be maintained by tazlito itself.
2452 check_rootfs
2453 title 'Checking distro: %s' "$ROOTFS"
2454 # SliTaz release info.
2455 rel='/etc/slitaz-release'
2456 if [ ! -f "$ROOTFS$rel" ]; then
2457 _ 'Missing release info: %s' "$rel"
2458 else
2459 action 'Release : %s' "$(cat $ROOTFS$rel)"
2460 status
2461 fi
2462 # Tazpkg mirror.
2463 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2464 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2465 todomsg
2466 else
2467 action 'Mirror configuration exists...'
2468 status
2469 fi
2470 # Isolinux msg
2471 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2472 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2473 todomsg
2474 else
2475 action 'Isolinux message seems good...'
2476 status
2477 fi
2478 footer
2479 ;;
2482 writeiso)
2483 # Writefs to ISO image including /home unlike gen-distro we don't use
2484 # packages to generate a rootfs, we build a compressed rootfs with all
2485 # the current filesystem similar to 'tazusb writefs'.
2487 DISTRO='/home/slitaz/distro'
2488 ROOTCD="$DISTRO/rootcd"
2489 COMPRESSION="${2:-none}"
2490 ISO_NAME="${3:-slitaz}"
2491 check_root
2492 # Start info
2493 title 'Write filesystem to ISO'
2494 longline "The command writeiso will write the current filesystem into a \
2495 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2496 newline
2497 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2499 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2500 # Save some space
2501 rm -rf /var/cache/tazpkg/*
2502 rm -f /var/lib/tazpkg/*.bak
2503 rm -rf $DISTRO
2505 # Optionally remove sound card selection and screen resolution.
2506 if [ -z $LaunchedByTazpanel ]; then
2507 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2508 case $anser in
2509 y)
2510 action 'Removing current sound card and screen configurations...'
2511 rm -f /var/lib/sound-card-driver
2512 rm -f /var/lib/alsa/asound.state
2513 rm -f /etc/X11/xorg.conf ;;
2514 *)
2515 action 'Keeping current sound card and screen configurations...' ;;
2516 esac
2517 status
2518 newline
2520 # Optionally remove i18n settings
2521 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2522 case $anser in
2523 y)
2524 action 'Removing current locale/keymap settings...'
2525 newline > /etc/locale.conf
2526 newline > /etc/keymap.conf ;;
2527 *)
2528 action 'Keeping current locale/keymap settings...' ;;
2529 esac
2530 status
2531 fi
2533 # Clean-up files by default
2534 newline > /etc/udev/rules.d/70-persistent-net.rules
2535 newline > /etc/udev/rules.d/70-persistant-cd.rules
2537 # Create list of files including default user files since it is defined in /etc/passwd
2538 # and some new users might have been added.
2539 cd /
2540 echo 'init' > /tmp/list
2541 for dir in bin etc sbin var dev lib root usr home opt; do
2542 [ -d $dir ] && find $dir
2543 done >> /tmp/list
2545 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2546 [ -d $dir ] && echo $dir
2547 done >> /tmp/list
2549 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2551 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2552 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2553 #fi
2554 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2555 touch /var/log/wtmp
2557 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2558 sed -i "/var\/log\/$removelog/d" /tmp/list
2559 done
2561 # Generate initramfs with specified compression and display rootfs
2562 # size in realtime.
2563 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2565 write_initramfs &
2566 sleep 2
2567 cd - > /dev/null
2568 echo -en "\nFilesystem size:"
2569 while [ ! -f /tmp/rootfs ]; do
2570 sleep 1
2571 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2572 done
2573 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2574 echo -e "\n"
2575 rm -f /tmp/rootfs
2577 # Move freshly generated rootfs to the cdrom.
2578 mkdir -p $ROOTCD/boot
2579 mv -f /$INITRAMFS $ROOTCD/boot
2580 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2582 # Now we need the kernel and isolinux files.
2583 copy_from_cd() {
2584 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2585 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2586 unmeta_boot $ROOTCD
2587 umount /media/cdrom
2590 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2591 copy_from_cd;
2592 elif mount | grep /media/cdrom; then
2593 copy_from_cd;
2594 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2595 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2596 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2597 else
2598 touch /tmp/.write-iso-error
2599 longline "When SliTaz is running in RAM the kernel and bootloader \
2600 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
2601 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
2602 echo -en "----\nENTER to continue..."; read i
2603 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2604 copy_from_cd
2605 fi
2607 # Generate the iso image.
2608 touch /tmp/.write-iso
2609 newline
2610 cd $DISTRO
2611 create_iso $ISO_NAME.iso $ROOTCD
2612 action 'Creating the ISO md5sum...'
2613 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2614 status
2616 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2617 rm -f /tmp/.write-iso
2619 if [ -z $LaunchedByTazpanel ]; then
2620 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2621 case $anser in
2622 y)
2623 umount /dev/cdrom 2>/dev/null
2624 eject
2625 echo -n "Please insert a blank CD-ROM and press ENTER..."
2626 read i && sleep 2
2627 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2628 echo -en "----\nENTER to continue..."; read i ;;
2629 *)
2630 exit 0 ;;
2631 esac
2632 fi
2633 ;;
2636 burn-iso)
2637 # Guess CD-ROM device, ask user and burn the ISO.
2639 check_root
2640 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2641 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2642 # We can specify an alternative ISO from the cmdline.
2643 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2644 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2646 title 'Tazlito burn ISO'
2647 echo "CD-ROM device : /dev/$DRIVE_NAME"
2648 echo "Drive speed : $DRIVE_SPEED"
2649 echo "ISO image : $iso"
2650 footer
2652 case $(yesorno 'Burn ISO image?' 'n') in
2653 y)
2654 title 'Starting Wodim to burn the ISO...'
2655 sleep 2
2656 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2657 footer 'ISO image is burned to CD-ROM.'
2658 ;;
2659 *)
2660 die 'Exiting. No ISO burned.'
2661 ;;
2662 esac
2663 ;;
2666 merge)
2667 # Merge multiple rootfs into one iso.
2669 if [ -z "$2" ]; then
2670 cat <<EOT
2671 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2673 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2674 i.e: rootfsN is a subset of rootfsN-1
2675 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2676 The boot loader will select the rootfs according to the RAM size detected.
2678 Example:
2679 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
2681 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
2682 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
2684 EOT
2685 exit 2
2686 fi
2688 shift # skip merge
2689 append="$1 slitaz1"
2690 shift # skip size1
2691 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
2693 ISO=$1.merged
2695 # Extract filesystems
2696 action 'Mounting %s' "$1"
2697 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
2698 status || cleanup_merge
2700 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2701 make_bzImage_hardlink $TMP_DIR/iso/boot
2702 umount -d $TMP_DIR/mnt
2703 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
2704 _ '%s is already a merged iso. Aborting.' "$1"
2705 cleanup_merge
2706 fi
2707 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
2708 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
2709 if [ ! -f /boot/isolinux/ifmem.c32 -a
2710 ! -f /boot/isolinux/c32box.c32 ]; then
2711 cat <<EOT
2712 No file /boot/isolinux/ifmem.c32
2713 Please install syslinux package !
2714 EOT
2715 rm -rf $TMP_DIR
2716 exit 1
2717 fi
2718 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
2719 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
2720 fi
2722 action 'Extracting %s' 'iso/rootfs.gz'
2723 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
2724 [ -d $TMP_DIR/rootfs1/etc ]
2725 status || cleanup_merge
2727 n=1
2728 while [ -n "$2" ]; do
2729 shift # skip rootfs N-1
2730 p=$n
2731 n=$(($n + 1))
2732 append="$append $1 slitaz$n"
2733 shift # skip size N
2734 mkdir -p $TMP_DIR/rootfs$n
2736 action 'Extracting %s' "$1"
2737 extract_rootfs $1 $TMP_DIR/rootfs$n &&
2738 [ -d "$TMP_DIR/rootfs$n/etc" ]
2739 status || cleanup_merge
2741 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
2742 action 'Creating %s' "rootfs$p.gz"
2743 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
2744 status
2745 done
2746 action 'Creating %s' "rootfs$n.gz"
2747 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
2748 status
2749 rm -f $TMP_DIR/iso/boot/rootfs.gz
2750 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
2751 create_iso $ISO $TMP_DIR/iso
2752 rm -rf $TMP_DIR
2753 ;;
2756 repack)
2757 # Repack an iso with maximum lzma compression ratio.
2759 ISO=$2
2760 mkdir -p $TMP_DIR/mnt
2762 # Extract filesystems
2763 action 'Mounting %s' "$ISO"
2764 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
2765 status || cleanup_merge
2767 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2768 umount -d $TMP_DIR/mnt
2770 for i in $TMP_DIR/iso/boot/rootfs* ; do
2771 action 'Repacking %s' "$(basename $i)"
2772 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
2773 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
2774 align_to_32bits $i
2775 status
2776 done
2778 create_iso $ISO $TMP_DIR/iso
2779 rm -rf $TMP_DIR
2780 ;;
2783 build-loram)
2784 # Build a Live CD for low RAM systems.
2786 ISO="$2"
2787 OUTPUT="$3"
2788 [ -z "$3" ] && \
2789 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
2790 mkdir -p "$TMP_DIR/iso"
2791 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
2792 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
2793 if ! check_iso_for_loram ; then
2794 umount -d "$TMP_DIR/iso"
2795 die "$ISO is not a valid SliTaz live CD. Abort."
2796 fi
2797 case "$4" in
2798 cdrom) build_loram_cdrom ;;
2799 http) build_loram_http ;;
2800 *) build_loram_ram ;;
2801 esac
2802 umount $TMP_DIR/iso # no -d: needs /proc
2803 losetup -d $loopdev
2804 rm -rf $TMP_DIR
2805 ;;
2808 emu-iso)
2809 # Emulate an ISO image with Qemu.
2810 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2811 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
2812 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
2813 echo -e "\nStarting Qemu emulator:\n"
2814 echo -e "qemu $QEMU_OPTS $iso\n"
2815 qemu $QEMU_OPTS $iso
2816 ;;
2819 deduplicate)
2820 # Deduplicate files in a tree
2821 shift
2822 deduplicate "$@"
2823 ;;
2826 usage|*)
2827 # Print usage also for all unknown commands.
2828 usage
2829 ;;
2830 esac
2832 exit 0