tazlito view tazlito @ rev 414

tazlito: fix setup_mirrors(), add install_list_to_rootfs(). Working in progress, please don't update tazlito receipt.
Bug: for multi-rootfs $DISTRO/rootfs/var/lib/tazpkg not cleaned and spammed with PKGDB files.
author Aleksej Bobylev <al.bobylev@gmail.com>
date Mon Feb 22 11:24:41 2016 +0200 (2016-02-22)
parents bd4b1f42430b
children 6ac6d30d100b
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://mirror.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 }
63 # Try to include config file, continue if command is gen-config or exit.
64 # The main config used by default is in /etc/tazlito.
65 # Specific distro config file can be put in a distro tree.
66 for i in /etc/tazlito "$TOP_DIR"; do
67 [ -f "$i/tazlito.conf" ] && CONFIG_FILE="$i/tazlito.conf"
68 done
70 [ -z "$CONFIG_FILE" -a "$COMMAND" != 'gen-config' ] && \
71 die 'Unable to find any configuration file.' \
72 'Please read the docs or run `tazlito gen-config` to get an empty config file.'
74 . $CONFIG_FILE
76 # While Tazpkg is not used the default mirror URL file does not exist
77 # and user can't recharge the list of flavors.
78 [ $(id -u) -eq 0 -a ! -f "$MIRROR" ] && echo "$DEFAULT_MIRROR" > $MIRROR
80 # Set the rootfs and rootcd path with $DISTRO
81 # configuration variable.
82 ROOTFS="$DISTRO/rootfs"
83 ROOTCD="$DISTRO/rootcd"
88 #####################
89 # Tazlito functions #
90 #####################
93 # Print the usage.
95 usage () {
96 [ $(basename $0) == 'tazlito' ] && cat <<EOT
98 SliTaz Live Tool - Version: $(colorize 34 "$VERSION")
100 $(boldify "Usage:") tazlito [command] [list|iso|flavor|compression] [dir|iso]
102 $(boldify "Commands:")
103 EOT
104 optlist "\
105 usage Print this short usage.
106 stats View Tazlito and distro configuration statistics.
107 list-addfiles Simple list of additional files in the rootfs.
108 gen-config Generate a new configuration file for a distro.
109 configure Configure the main config file or a specific tazlito.conf.
110 gen-iso Generate a new ISO from a distro tree.
111 gen-initiso Generate a new initramfs and ISO from the distro tree.
112 list-flavors List all flavors available on the mirror.
113 gen-flavor Generate a new Live CD description.
114 gen-liveflavor Generate a Live CD description from current system.
115 show-flavor Show Live CD description.
116 get-flavor Get a flavor's list of packages (--noup to skip update).
117 upgrade-flavor Update package list to the latest available versions.
118 extract-flavor Extract a *.flavor file into $FLAVORS_REPOSITORY.
119 pack-flavor Pack (and update) a flavor from $FLAVORS_REPOSITORY.
120 iso2flavor Create a flavor file from a SliTaz ISO image.
121 extract-distro Extract an ISO to a directory and rebuild Live CD tree.
122 gen-distro Generate a Live distro and ISO from a list of packages.
123 clean-distro Remove all files generated by gen-distro.
124 check-distro Help to check if distro is ready to release.
125 writeiso Use running system to generate a bootable ISO (with /home).
126 merge Merge multiple rootfs into one ISO.
127 deduplicate Deduplicate files in a tree.
128 repack Recompress rootfs into ISO with maximum ratio.
129 build-loram Generate a Live CD for low-RAM systems.
130 emu-iso Emulate an ISO image with QEMU.
131 burn-iso Burn ISO image to a CD-ROM using Wodim.
132 "
133 }
136 yesorno() {
137 local answer
138 echo -n "$1 (y=yes, n=no) [$2] " >&2
139 case "$DEFAULT_ANSWER" in
140 Y|y) answer="y";;
141 N|n) answer="n";;
142 *)
143 read -t 30 answer
144 [ -z "$answer" ] && answer="$2"
145 [ "$answer" != 'y' -a "$answer" != 'n' ] && answer="$2"
146 ;;
147 esac
148 echo "$answer"
149 }
152 field() {
153 grep "^$1" "$2" | \
154 case "$1" in
155 Desc*) sed 's|^.*: *||';;
156 *) sed 's/.*: \([0-9KMG\.]*\).*/\1/';;
157 esac
158 }
161 todomsg() {
162 echo -e "\\033[70G[ \\033[1;31mTODO\\033[0;39m ]"
163 }
166 # Download a file from this mirror
168 download_from() {
169 local i mirrors="$1"
170 shift
171 for i in $mirrors; do
172 case "$i" in
173 http://*|ftp://*|https://*)
174 wget -c $i$@ && break;;
175 *)
176 cp $i/$1 . && break;;
177 esac
178 done
179 }
182 # Download a file trying all mirrors
184 download() {
185 local i
186 for i in $(cat $MIRROR $LOCALSTATE/undigest/*/mirror 2>/dev/null); do
187 download_from "$i" "$@" && break
188 done
189 }
192 # Execute hooks provided by some packages
194 genisohooks() {
195 local here="$(pwd)"
196 for i in $(ls $ROOTFS/etc/tazlito/*.$1 2>/dev/null); do
197 cd $ROOTFS
198 . $i $ROOTCD
199 done
200 cd "$here"
201 }
204 # Echo the package name if the tazpkg is already installed
206 installed_package_name() {
207 local tazpkg="$1" package VERSION EXTRAVERSION
209 # Try to find package name and version to be able
210 # to repack it from installation
211 # A dash (-) can exist in name *and* in version
212 package=${tazpkg%-*}
213 i=$package
214 while true; do
215 unset VERSION EXTRAVERSION
216 eval $(grep -s ^VERSION= $INSTALLED/$i/receipt)
217 eval $(grep -s ^EXTRAVERSION= $INSTALLED/$i/receipt)
218 if [ "$i-$VERSION$EXTRAVERSION" == "$tazpkg" ]; then
219 echo $i
220 break
221 fi
222 case "$i" in
223 *-*);;
224 *) break;;
225 esac
226 i=${i%-*}
227 done
228 }
231 # Check for the rootfs tree.
233 check_rootfs() {
234 [ -d "$ROOTFS/etc" ] || die 'Unable to find a distro rootfs...'
235 }
238 # Check for the boot dir into the root CD tree.
240 verify_rootcd() {
241 [ -d "$ROOTCD/boot" ] || die 'Unable to find the rootcd boot directory...'
242 }
245 # isolinux.conf doesn't know the kernel version.
246 # We name the kernel image 'bzImage'.
247 # isolinux/syslinux first tries the '64' suffix with a 64bits cpu.
249 make_bzImage_hardlink() {
250 if [ -s ${1:-.}/vmlinuz*slitaz ]; then
251 rm -f ${1:-.}/bzImage 2>/dev/null
252 ln ${1:-.}/vmlinuz*slitaz ${1:-.}/bzImage
253 fi
254 if [ -s ${1:-.}/vmlinuz*slitaz64 ]; then
255 rm -f ${1:-.}/bzImage64 2> /dev/null
256 ln ${1:-.}/vmlinuz*slitaz64 ${1:-.}/bzImage64
257 fi
258 }
261 create_iso() {
262 cd $2
263 deduplicate
265 action 'Computing md5...'
266 find * -type f ! -name md5sum ! -name 'vmlinuz*' -exec md5sum {} \; > md5sum
267 sed -i -e '/ boot\/isolinux\/isolinux.bin$/d' \
268 -e '/ boot\/isolinux\/boot.cat$/d' md5sum
269 status
271 cd - >/dev/null
272 title 'Generating ISO image'
274 echo "Generating $1"
275 make_bzImage_hardlink $2/boot
276 genisoimage -R -o $1 -b boot/isolinux/isolinux.bin \
277 -c boot/isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
278 -V "$VOLUM_NAME" -p "$PREPARED" -input-charset utf-8 \
279 -copyright README -P "www.slitaz.org" -boot-info-table $2
281 if [ -x '/usr/bin/isohybrid' ]; then
282 action 'Creating hybrid ISO...'
283 /usr/bin/isohybrid $1 -entry 2 2>/dev/null
284 status
285 fi
287 if [ -s '/etc/tazlito/info' ]; then
288 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
289 action 'Storing ISO info...'
290 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
291 status
292 fi
293 fi
295 if [ -x '/usr/bin/iso2exe' ]; then
296 echo 'Creating EXE header...'
297 /usr/bin/iso2exe $1 2>/dev/null
298 fi
299 }
302 # Generate a new ISO image using isolinux.
304 gen_livecd_isolinux() {
305 # Some packages may want to alter iso
306 genisohooks iso
307 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
309 # Set date for boot msg.
310 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
311 DATE=$(date +%Y%m%d)
312 action 'Setting build date to: %s...' "$DATE"
313 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
314 status
315 fi
317 cd $DISTRO
318 create_iso $ISO_NAME.iso $ROOTCD
320 action 'Creating the ISO md5sum...'
321 md5sum $ISO_NAME.iso > $ISO_NAME.md5
322 status
324 separator
325 # Some packages may want to alter final iso
326 genisohooks final
327 }
330 lzma_history_bits() {
331 #
332 # This generates an ISO which boots with Qemu but gives
333 # rootfs errors in frugal or liveUSB mode.
334 #
335 # local n
336 # local sz
337 # n=20 # 1Mb
338 # sz=$(du -sk $1 | cut -f1)
339 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
340 # n=$(( $n + 1 ))
341 # sz=$(( $sz / 2 ))
342 # done
343 # echo $n
344 echo 24
345 }
348 lzma_switches() {
349 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
350 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1}"
351 }
354 lzma_set_size() {
355 # Update size field for lzma'd file packed using -si switch
356 return # Need to fix kernel code?
358 local n i
359 n=$(unlzma < $1 | wc -c)
360 for i in $(seq 1 8); do
361 printf '\\\\x%02X' $(($n & 255))
362 n=$(($n >> 8))
363 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
364 }
367 align_to_32bits() {
368 local size=$(stat -c %s ${1:-/dev/null})
369 [ $((${size:-0} & 3)) -ne 0 ] &&
370 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
371 }
374 # Pack rootfs
376 pack_rootfs() {
377 ( cd $1; find . -print | cpio -o -H newc ) | \
378 case "$COMPRESSION" in
379 none)
380 _ 'Creating %s without compression...' 'initramfs'
381 cat > $2
382 ;;
383 gzip)
384 _ 'Creating %s with gzip compression...' 'initramfs'
385 gzip -9 > $2
386 ;;
387 *)
388 _ 'Creating %s with lzma compression...' 'initramfs'
389 lzma e -si -so $(lzma_switches $1) > $2
390 lzma_set_size $2
391 ;;
392 esac
393 align_to_32bits $2
394 echo 1 > /tmp/rootfs
395 }
398 # Compression functions for writeiso.
400 write_initramfs() {
401 case "$COMPRESSION" in
402 lzma)
403 _n 'Creating %s with lzma compression...' "$INITRAMFS"
404 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
405 align='y'
406 lzma_set_size "/$INITRAMFS"
407 ;;
408 gzip)
409 _ 'Creating %s with gzip compression...' "$INITRAMFS"
410 cpio -o -H newc | gzip -9 > "/$INITRAMFS"
411 [ -x /usr/bin/advdef ] && advdef -z4 "/$INITRAMFS"
412 ;;
413 *)
414 # align='y'
415 _ 'Creating %s without compression...' "$INITRAMFS"
416 cpio -o -H newc > "/$INITRAMFS"
417 ;;
418 esac < /tmp/list
419 [ "$align" == 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
420 echo 1 > /tmp/rootfs
421 }
424 # Deduplicate files (MUST be on the same filesystem).
426 deduplicate() {
427 find "${@:-.}" -type f -size +0c -xdev -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
428 (
429 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""
430 while read attr inode link file; do
431 [ -L "$file" ] && continue
432 if [ "$attr" == "$old_attr" -a "$inode" != "$old_inode" ]; then
433 if cmp "$file" "$old_file" >/dev/null 2>&1 ; then
434 rm -f "$file"
435 if ln "$old_file" "$file" 2>/dev/null; then
436 inode="$old_inode"
437 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
438 save="$(($save+(${attr%%-*}+512)/1024))"
439 else
440 cp -a "$old_file" "$file"
441 fi
442 fi
443 fi
444 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
445 done
446 echo "$save Kbytes saved in $hardlinks duplicate files."
447 )
449 find "$@" -type l -xdev -exec stat -c '%s-%u-%g-TARGET- %i %h %n' {} \; | sort | \
450 (
451 old_attr=""; hardlinks=0;
452 while read attr inode link file; do
453 attr="${attr/-TARGET-/-$(readlink $file)}"
454 if [ "$attr" == "$old_attr" ]; then
455 if [ "$inode" != "$old_inode" ]; then
456 rm -f "$file"
457 if ln "$old_file" "$file" 2>/dev/null; then
458 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
459 else
460 cp -a "$old_file" "$file"
461 fi
462 fi
463 else
464 old_file="$file"
465 old_attr="$attr"
466 old_inode="$inode"
467 fi
468 done
469 echo "$hardlinks duplicate symlinks."
470 )
471 }
474 # Generate a new initramfs from the root filesystem.
476 gen_initramfs() {
477 # Just in case CTRL+c
478 rm -f $DISTRO/gen
480 # Some packages may want to alter rootfs
481 genisohooks rootfs
482 cd $1
484 # Link duplicate files
485 deduplicate
487 # Use lzma if installed. Display rootfs size in realtime.
488 rm -f /tmp/rootfs 2>/dev/null
489 pack_rootfs . $DISTRO/$(basename $1).gz &
490 sleep 2
491 echo -en "\nFilesystem size:"
492 while [ ! -f /tmp/rootfs ]; do
493 sleep 1
494 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
495 done
496 echo -e "\n"
497 rm -f /tmp/rootfs
498 cd $DISTRO
499 mv $(basename $1).gz $ROOTCD/boot
500 }
503 distro_sizes() {
504 if [ -n "$start_time" ]; then
505 time=$(($(date +%s) - $start_time))
506 sec=$time
507 div=$(( ($time + 30) / 60))
508 [ "$div" -ne 0 ] && min="~ ${div}m"
509 echo "Build time : ${sec}s $min"
510 fi
511 cat <<EOT
512 Build date : $(date +%Y%m%d)
513 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
514 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
515 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
516 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
517 EOT
518 footer "Image is ready: $ISO_NAME.iso"
519 }
522 # Print ISO and rootfs size.
524 distro_stats() {
525 title 'Distro statistics: %s' "$DISTRO"
526 distro_sizes
527 }
530 # Create an empty configuration file.
532 empty_config_file() {
533 cat >> tazlito.conf <<"EOF"
534 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
535 #
537 # Name of the ISO image to generate.
538 ISO_NAME=""
540 # ISO image volume name.
541 VOLUM_NAME="SliTaz"
543 # Name of the preparer.
544 PREPARED="$USER"
546 # Path to the packages repository and the packages.list.
547 PACKAGES_REPOSITORY=""
549 # Path to the distro tree to gen-distro from a list of packages.
550 DISTRO=""
552 # Path to the directory containing additional files
553 # to copy into the rootfs and rootcd of the LiveCD.
554 ADDFILES="$DISTRO/addfiles"
556 # Default answer for binary question (Y or N)
557 DEFAULT_ANSWER="ASK"
559 # Compression utility (lzma, gzip or none)
560 COMPRESSION="lzma"
561 EOF
562 }
565 # Extract rootfs.gz somewhere
567 extract_rootfs() {
568 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
569 # First part (lzcat or zcat) may not fail, but cpio will fail on uncorrect format
570 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
571 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
572 (cd "$2"; cat "$1" | cpio -idm --quiet 2>/dev/null)
573 }
576 # Extract flavor file to temp directory
578 extract_flavor() {
579 # Input: $1 - flavor name to extract;
580 # $2 = absent/empty: just extract 'outer layer'
581 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
582 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
583 # Output: temp dir path where flavor was extracted
584 local f="$1.flavor" from to infos="$1.desc"
585 [ -f "$f" ] || die "File '$f' not found"
586 local dir="$(mktemp -d)"
587 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
589 if [ -n "$2" ]; then
590 cd $dir
592 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
594 for i in rootcd rootfs; do
595 [ -f "$1.$i" ] || continue
596 mkdir "$i"
597 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
598 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
599 rm "$1.$i"
600 done
601 # Info to be stored inside ISO
602 [ "$2" == info ] && echo -e $infos | cpio -o -H newc | gzip -9 > info
603 rm $1.list*
605 # Renames
606 while read from to; do
607 [ -f "$from" ] || continue
608 mv "$from" "$to"
609 done <<EOT
610 $1.nonfree non-free.list
611 $1.pkglist packages.list
612 $1-distro.sh distro.sh
613 $1.receipt receipt
614 $1.mirrors mirrors
615 $1.desc description
616 EOT
617 fi
619 echo $dir
620 }
623 # Pack flavor file from temp directory
625 pack_flavor() {
626 (cd "$1"; ls | grep -v err | cpio -o -H newc) | gzip -9 > "$2.flavor"
627 }
630 # Remove duplicate files
632 mergefs() {
633 # Note, many packages have files with spaces in the name
634 IFS=$'\n'
636 local size1=$(du -hs "$1" | awk '{ print $1 }')
637 local size2=$(du -hs "$2" | awk '{ print $1 }')
638 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
640 # merge symlinks files and devices
641 ( cd "$1"; find ) | \
642 while read file; do
643 if [ -L "$1/$file" ]; then
644 [ -L "$2/$file" -a "$(readlink "$1/$file")" == "$(readlink "$2/$file")" ] &&
645 rm -f "$2/$file"
647 elif [ -f "$1/$file" ]; then
648 [ -f "$2/$file" ] && cmp -s "$1/$file" "$2/$file" &&
649 rm -f "$2/$file"
651 [ -f "$2/$file" ] &&
652 [ "$(basename "$file")" == 'volatile.cpio.gz' ] &&
653 [ "$(dirname $(dirname "$file"))" == ".$INSTALLED" ] &&
654 rm -f "$2/$file"
656 elif [ -b "$1/$file" ]; then
657 [ -b "$2/$file" ] &&
658 [ "$(stat -c '%a:%u:%g:%t:%T' "$1/$file")" == \
659 "$(stat -c '%a:%u:%g:%t:%T' "$2/$file")" ] &&
660 rm -f "$2/$file"
662 elif [ -c "$1/$file" ]; then
663 [ -c "$2/$file" ] &&
664 [ "$(stat -c '%a:%u:%g:%t:%T' "$1/$file")" == \
665 "$(stat -c '%a:%u:%g:%t:%T' "$2/$file")" ] &&
666 rm -f "$2/$file"
667 fi
668 done
670 # cleanup directories; TODO: simplify
671 ( cd "$1"; find . -type d ) | sed '1!G;h;$!d' | \
672 while read file; do
673 [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
674 done
676 unset IFS
677 status
678 }
681 cleanup_merge() {
682 rm -rf $TMP_DIR
683 exit 1
684 }
687 # Update isolinux config files for multiple rootfs
689 update_bootconfig() {
690 local files
691 echo -n "Updating boot config files..."
692 files="$(grep -l 'include common' $1/*.cfg)"
693 for file in $files; do
694 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
695 if (/label/) label=$0;
696 else if (/kernel/) kernel=$0;
697 else if (/append/) {
698 i=index($0,"rootfs.gz");
699 append=substr($0,i+9);
700 }
701 else if (/include/) {
702 for (i = 1; i <= n; i++) {
703 print label i
704 print kernel;
705 initrd="initrd=/boot/rootfs" n ".gz"
706 for (j = n - 1; j >= i; j--) {
707 initrd=initrd ",/boot/rootfs" j ".gz";
708 }
709 printf "\tappend %s%s\n",initrd,append;
710 print "";
711 }
712 print;
713 }
714 else print;
715 }' < $file > $file.$$
716 mv -f $file.$$ $file
717 done
718 sel="$(echo $2 | awk '{
719 for (i=1; i<=NF; i++)
720 if (i % 2 == 0) printf " slitaz%d", i/2
721 else printf " %s", $i
722 }')"
724 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
726 label slitaz
727 kernel /boot/isolinux/ifmem.c32
728 append$sel noram
730 label noram
731 config noram.cfg
733 EOT
735 # Update vesamenu
736 if [ -s "$1/isolinux.cfg" ]; then
737 files="$files $1/isolinux.cfg"
738 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
739 BEGIN {
740 kernel = " COM32 c32box.c32"
741 }
742 {
743 if (/ROWS/) print "MENU ROWS " n+$3;
744 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
745 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
746 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
747 else if (/VSHIFT/) {
748 x = $3-n;
749 if (x < 0) x = 0;
750 print "MENU VSHIFT " x;
751 }
752 else if (/rootfs.gz/) {
753 linux = "";
754 if (/bzImage/) linux = "linux /boot/bzImage ";
755 i = index($0, "rootfs.gz");
756 append = substr($0, i+9);
757 printf "\tkernel /boot/isolinux/ifmem.c32\n";
758 printf "\tappend%s noram\n", sel;
759 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
760 for (i = 1; i <= n; i++) {
761 print "LABEL slitaz" i
762 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
763 printf "%s\n", kernel;
764 initrd = "initrd=/boot/rootfs" n ".gz"
765 for (j = n - 1; j >= i; j--) {
766 initrd = initrd ",/boot/rootfs" j ".gz";
767 }
768 printf "\tappend %s%s%s\n\n", linux, initrd, append;
769 }
770 }
771 else if (/bzImage/) kernel = $0;
772 else print;
773 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
774 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
775 fi
777 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
778 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
779 cat > $1/noram.cfg <<EOT
780 implicit 0
781 prompt 1
782 timeout 80
783 $(grep '^F[0-9]' $1/isolinux.cfg)
785 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
786 say Not enough RAM to boot slitaz. Trying hacker mode...
787 default hacker
788 label hacker
789 KERNEL /boot/bzImage
790 append rw root=/dev/null vga=normal
792 label reboot
793 EOT
795 if [ -s $1/c32box.c32 ]; then
796 cat >> $1/noram.cfg <<EOT
797 COM32 c32box.c32
798 append reboot
800 label poweroff
801 COM32 c32box.c32
802 append poweroff
804 EOT
805 else
806 echo " com32 reboot.c32" >> $1/noram.cfg
807 fi
809 # Restore real label names
810 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
811 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
812 while read pat; do
813 sed -i "s/slitaz$pat/" $files
814 done
815 status
816 }
819 # Install a missing package
821 install_package() {
822 if [ -z "$2" ]; then
823 _n 'Install package %s? ' "$1"
824 else
825 _n 'Install package %s for Kernel %s? ' "$1" "$2"
826 fi
827 echo -n '[y = yes] '
828 read answer
829 case "$answer" in
830 y*|Y*|o*|O*)
831 # We don't want package on host cache.
832 action 'Getting and installing package: %s' "$1"
833 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
834 status ;;
835 *)
836 return 1 ;;
837 esac
838 }
841 # Check iso for loram transformation
843 check_iso_for_loram() {
844 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
845 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
846 }
849 # Build initial rootfs for loram ISO ram/cdrom/http
851 build_initfs() {
852 urliso="mirror.slitaz.org mirror.switch.ch/ftp/mirror/slitaz \
853 download.tuxfamily.org/slitaz slitaz.c3sl.ufpr.br"
854 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
855 [ -z "$version" ] && die "Can't find the kernel version." \
856 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
858 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
859 need_lib=false
860 for i in bin dev run mnt proc tmp sys lib/modules; do
861 mkdir -p $TMP_DIR/initfs/$i
862 done
863 ln -s bin $TMP_DIR/initfs/sbin
864 ln -s . $TMP_DIR/initfs/usr
865 for aufs in aufs overlayfs; do
866 [ ! -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] &&
867 install_package $aufs $version && break
868 done || return 1
869 cp /init $TMP_DIR/initfs/
870 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
871 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
872 $TMP_DIR/initfs/lib/modules 2>/dev/null
873 cp -a /dev/tty0 /dev/fd0 $TMP_DIR/initfs/dev 2>/dev/null
874 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
875 $TMP_DIR/initfs/lib/modules
876 if [ "$1" == 'cdrom' ]; then
877 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
878 else
879 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
880 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
881 install_package linux-squashfs $version || return 1
882 done
883 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
884 $TMP_DIR/initfs/lib/modules
885 ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
886 cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
887 fi
888 for i in $(ls /dev/[hs]d[a-f]*); do
889 cp -a $i $TMP_DIR/initfs/dev
890 done
891 if [ "$1" == 'http' ]; then
892 mkdir $TMP_DIR/initfs/etc
893 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
894 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
895 sed -i 's|/sbin/||' $TMP_DIR/initfs/lib/udhcpc
896 cp -a /dev/fuse $TMP_DIR/initfs/dev
897 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
898 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/httpfs
899 else
900 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
901 need_lib=true
902 fi
903 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
904 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
905 else
906 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
907 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
908 cp -a /lib/librt* $TMP_DIR/initfs/lib
909 cp -a /lib/libdl* $TMP_DIR/initfs/lib
910 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
911 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
912 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
913 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
914 need_lib=true
915 fi
916 cd $TMP_DIR/initfs
917 echo 'Getting slitaz-release...'
918 for i in $TMP_DIR/iso/boot/rootfs*.gz; do
919 (zcat $i 2>/dev/null || unlzma < $i) | cpio -idmu etc/slitaz-release >/dev/null
920 done
921 cd - > /dev/null
922 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"
923 echo -n "List of URLs to insert: "
924 read -t 30 urliso2
925 urliso="$urliso2 $urliso"
926 fi
927 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
928 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
929 sed -i 's/LD_T.*ot/newline/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
930 else
931 cp /bin/busybox $TMP_DIR/initfs/bin
932 need_lib=true
933 fi
934 for i in $($TMP_DIR/initfs/bin/busybox | awk \
935 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
936 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
937 done
938 for i in /dev/console /dev/loop* /dev/null /dev/tty /dev/zero \
939 /dev/kmem /dev/mem /dev/random /dev/urandom; do
940 cp -a $i $TMP_DIR/initfs/dev
941 done
942 $need_lib && for i in /lib/ld-* /lib/lib[cm].so* /lib/lib[cm]-* ; do
943 cp -a $i $TMP_DIR/initfs/lib
944 done
945 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
946 #!/bin/sh
948 getarg() {
949 grep -q " \$1=" /proc/cmdline || return 1
950 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
951 return 0
952 }
954 copy_rootfs() {
955 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
956 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
957 [ \$(( \$total / \$need )) -gt 1 ] || return 1
958 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
959 path=/mnt/
960 return 0
961 else
962 rm -f /mnt/rootfs*
963 return 1
964 fi
965 }
967 echo "Switching / to tmpfs..."
968 mount -t proc proc /proc
969 size="\$(grep rootfssize= < /proc/cmdline | \\
970 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
971 [ -n "\$size" ] || size="-o size=90%"
973 while read var default; do
974 eval \$var=\$default
975 getarg \$var \$var
976 done <<EOT
977 eth eth0
978 dns 208.67.222.222,208.67.220.220
979 netmask 255.255.255.0
980 gw
981 ip
982 EOT
983 if [ -n "\$ip" ]; then
984 ifconfig \$eth \$ip netmask \$netmask up
985 route add default gateway \$gw
986 for i in \$(echo \$dns | sed 's/,/ /g'); do
987 echo "nameserver \$i" >> /etc/resolv.conf
988 done
989 else
990 udhcpc -f -q -s /lib/udhcpc -i \$eth
991 fi
992 for i in $urliso ; do
993 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
994 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"
995 done
996 getarg urliso URLISO
997 DIR=fs
998 if getarg loram DIR; then
999 DEVICE=\${DIR%,*}
1000 DIR=/\${DIR#*,}
1001 fi
1002 mount -t tmpfs \$size tmpfs /mnt
1003 path2=/mnt/.httpfs/
1004 path=/mnt/.cdrom/
1005 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1006 while [ ! -d \$path/boot ]; do
1007 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1008 httpfs \$i \$path2 && break
1009 done
1010 mount -o loop,ro -t iso9660 \$path2/*.iso \$path
1011 done
1013 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1014 umount /proc
1015 branch=:/mnt/.cdrom/\$DIR
1016 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1017 branch=
1018 for i in \${path}rootfs* ; do
1019 fs=\${i#*root}
1020 branch=\$branch:/mnt/.\$fs
1021 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1022 insmod /lib/squashfs.ko.gz 2> /dev/null
1023 mount -o loop,ro -t squashfs \${path}root\$fs /mnt/.\$fs
1024 done
1025 else
1026 mkdir -p /mnt/.rw/mnt/.httpfs
1027 fi
1028 while read type opt; do
1029 insmod /lib/\$type.ko.gz && mount -t \$type -o \$opt none /mnt && break
1030 done <<EOT
1031 aufs br=/mnt/.rw\$branch
1032 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1033 EOT
1034 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1035 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1036 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1037 EOTEOT
1038 chmod +x $TMP_DIR/initfs/init
1039 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1040 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1041 rm -f $i
1042 gzip -9 ${i%.gz}
1043 done 2>/dev/null
1044 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1045 lzma e $TMP_DIR/initfs.gz -si
1046 lzma_set_size $TMP_DIR/initfs.gz
1047 rm -rf $TMP_DIR/initfs
1048 align_to_32bits $TMP_DIR/initfs.gz
1049 return 0
1053 # Move each initramfs to squashfs
1055 build_loram_rootfs() {
1056 rootfs_sizes=""
1057 for i in $TMP_DIR/iso/boot/rootfs*.gz; do
1058 mkdir -p $TMP_DIR/fs
1059 cd $TMP_DIR/fs
1060 (zcat $i 2>/dev/null || unlzma < $i) | cpio -idm
1061 cd - > /dev/null
1062 rootfs=$TMP_DIR/$(basename $i)
1063 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp xz -Xbcj x86
1064 cd $TMP_DIR
1065 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1066 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1067 rm -f $rootfs
1068 mv $rootfs.cpio $rootfs
1069 cd - > /dev/null
1070 rm -rf $TMP_DIR/fs
1071 done
1075 # Move meta boot configuration files to basic configuration files
1076 # because meta loram flavor is useless when rootfs is not loaded in RAM
1078 unmeta_boot() {
1079 local root=${1:-$TMP_DIR/loramiso}
1080 if [ -f $root/boot/isolinux/noram.cfg ]; then
1081 # We keep enough information to do unloram...
1082 [ -s $root/boot/isolinux/common.cfg ] &&
1083 sed -i 's/label slitaz/label orgslitaz/' \
1084 $root/boot/isolinux/common.cfg
1085 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1086 shift
1087 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1088 $root/boot/isolinux/isolinux.cfg
1089 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1090 sed -i "s/label $3\$/label slitaz/;s|=/boot/rootfs\(.*\).gz |=/boot/rootfs.gz |" \
1091 $root/boot/isolinux/*.cfg
1092 fi
1096 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1097 # These squashfs may be loaded in RAM at boot time.
1098 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1099 # Meta flavors are converted to normal flavors.
1101 build_loram_cdrom() {
1102 build_initfs cdrom || return 1
1103 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1104 mkdir $TMP_DIR/loramiso/fs
1105 cd $TMP_DIR/loramiso/fs
1106 for i in $( ls ../boot/root* | sort -r ) ; do
1107 (zcat $i 2>/dev/null || unlzma < $i) | cpio -idmu
1108 rm -f $i
1109 done
1110 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1111 cd - >/dev/null
1112 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1113 unmeta_boot
1114 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1115 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1116 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1117 create_iso $OUTPUT $TMP_DIR/loramiso
1121 # Create http bootstrap to load and remove loram_cdrom
1122 # Meta flavors are converted to normal flavors.
1124 build_loram_http() {
1125 build_initfs http || return 1
1126 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1127 rm -f $TMP_DIR/loramiso/boot/rootfs*
1128 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1129 unmeta_boot
1130 create_iso $OUTPUT $TMP_DIR/loramiso
1134 # Update meta flavor selection sizes.
1135 # Reduce sizes with rootfs gains.
1137 update_metaiso_sizes() {
1138 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1139 do
1140 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1141 local sizes="$rootfs_sizes"
1142 local new
1143 set -- $append
1144 shift
1145 [ "$1" == "ifmem" ] && shift
1146 new=""
1147 while [ -n "$2" ]; do
1148 local s
1149 case "$1" in
1150 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1151 *M) s=$(( ${1%M} * 1024 ));;
1152 *) s=${1%K};;
1153 esac
1154 sizes=${sizes#* }
1155 for i in $sizes ; do
1156 s=$(( $s - $i ))
1157 done
1158 new="$new $s $2"
1159 shift 2
1160 done
1161 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1162 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1163 sed -i 's|\(initrd=\)\(/boot/rootfs.\.gz\)|\1/boot/rootfs.gz,\2|' $cfg
1164 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1165 done
1169 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1170 # Meta flavor selection sizes are updated.
1172 build_loram_ram() {
1173 build_initfs ram || return 1
1174 build_loram_rootfs
1175 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1176 make_bzImage_hardlink $TMP_DIR/loramiso/boot
1177 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1178 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1179 update_metaiso_sizes
1180 create_iso $OUTPUT $TMP_DIR/loramiso
1184 # Remove files installed by packages
1186 find_flavor_rootfs() {
1187 for i in $1/etc/tazlito/*.extract; do
1188 [ -e $i ] || continue
1189 chroot $1 /bin/sh ${i#$1}
1190 done
1192 # Clean hardlinks and files patched by genisofs in /boot
1193 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1194 rm -f $1/boot/$i*
1195 done
1197 # Clean files generated in post_install
1198 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1199 $1/dev/core $1/dev/fd $1/dev/std*
1201 # Verify md5
1202 cat $1$INSTALLED/*/md5sum | \
1203 while read md5 file; do
1204 [ -e "$1$file" ] || continue
1205 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1206 rm -f "$1$file"
1207 done
1209 # Check configuration files
1210 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1211 [ -e $i ] || continue
1212 mkdir /tmp/volatile$$
1213 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1214 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1215 while read file ; do
1216 [ -e "$1/$file" ] || continue
1217 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1218 done
1219 rm -rf /tmp/volatile$$
1220 done
1222 # Remove other files blindly
1223 for i in $1$INSTALLED/*/files.list; do
1224 for file in $(cat "$i"); do
1225 [ "$1$file" -nt "$i" ] && continue
1226 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1227 [ -d "$1$file" ] || rm -f "$1$file"
1228 done
1229 done
1231 # Remove tazpkg files and tmp files
1232 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1233 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1234 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1235 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1236 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1238 # Cleanup directory tree
1239 cd $1
1240 find * -type d | sort -r | while read dir; do
1241 rmdir "$dir" 2>/dev/null
1242 done
1243 cd - > /dev/null
1247 # Get byte(s) from a binary file
1249 get() {
1250 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null
1254 # Get cpio flavor info from the ISO image
1256 flavordata() {
1257 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1258 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1262 # Restore undigest mirrors
1264 restore_mirrors() {
1265 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1266 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1268 action 'Restoring mirrors...'
1269 if [ -d "$undigest.bak" ]; then
1270 [ -d "$undigest" ] && rm -r "$undigest"
1271 mv "$undigest.bak" "$undigest"
1272 fi
1273 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1274 :; status
1278 # Setup undigest mirrors
1280 setup_mirrors() {
1281 # Setup mirrors in plain system or in chroot (with variable root=)
1283 # Note, difficulties exists in using local-filesystem-mirrors (when content
1284 # of the 'mirror' file is point to folder somewhere in the FS) inside chroot,
1285 # because mirror should be in the chroot too. We make local mirrors to be
1286 # accessible via http://localhost/... using built-in SliTaz web server.
1287 local mirrorlist="$1" fresh repacked
1288 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1290 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1291 restore_mirrors
1293 _ 'Setting up mirrors for %s...' "$root/"
1294 # Backing up current undigest mirrors and priority
1295 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1296 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1297 rm -rf '/var/www/tazlito/'
1298 mkdir -p '/var/www/tazlito/'
1300 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1301 fresh='/home/slitaz/packages'
1302 if [ -d "$fresh" ]; then
1303 # Make this mirror accessible using http://localhost/tazlito/fresh
1304 ln -s "$fresh" '/var/www/tazlito/fresh'
1305 # Setup first undigest mirror
1306 mkdir -p "$undigest/fresh"
1307 echo "http://localhost/tazlito/fresh/" > "$undigest/fresh/mirror"
1308 echo 'fresh' >> "$priority"
1309 # Rebuild mirror DB if needed
1310 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1311 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1312 tazpkg mkdb "$fresh" --forced --root=''
1313 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1314 fi
1316 # Repacked packages: high priority
1317 repacked="$PACKAGES_REPOSITORY"
1318 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1319 # According to Tazlito setup file (tazlito.conf):
1320 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1321 # or
1322 # WORK_DIR="/home/slitaz"
1323 # and
1324 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1325 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1327 # Make this mirror accessible using http://localhost/tazlito/repacked
1328 ln -s "$repacked" '/var/www/tazlito/repacked'
1329 # Setup second undigest mirror
1330 mkdir -p "$undigest/repacked"
1331 echo "http://localhost/tazlito/repacked/" > "$undigest/repacked/mirror"
1332 echo 'repacked' >> "$priority"
1333 # Rebuild mirror DB if needed
1334 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1335 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1336 tazpkg mkdb "$repacked" --forced --root=''
1337 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1338 fi
1340 # All repositories listed in mirrors list: normal priority
1341 [ -e "$mirrorlist" ] && \
1342 while read mirror; do
1343 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1344 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1345 mkdir -p "$undigest/$mirrorid"
1346 echo "$mirror" > "$undigest/$mirrorid/mirror"
1347 echo "$mirrorid" >> "$priority"
1348 done < "$mirrorlist"
1350 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1352 # Show list of mirrors
1353 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1354 function show(num, name, url, pad, len) {
1355 pad = "................................";
1356 len = (32 - length(name));
1357 printf " %-1.1d. %s%*.*s %-44.44s\n", num, name, len, len, pad, url;
1360 num++;
1361 "cat " db "/undigest/" $0 "/mirror" | getline url;
1362 show(num, $0, url);
1364 END {
1365 num++;
1366 "cat " db "/mirror" | getline url;
1367 show(num, "main", url);
1368 }' "$priority"
1370 tazpkg recharge --quiet
1374 # Get list of 'packages.info' lists using priority
1376 pi_lists() {
1377 local pi
1378 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge >/dev/null 2>&1
1379 local priority="$root$LOCALSTATE/priority"
1380 local undigest="$root$LOCALSTATE/undigest"
1383 [ -s "$priority" ] && cat "$priority"
1384 echo 'main'
1385 [ -d "$undigest" ] && ls "$undigest"
1386 } | awk -vun="$undigest/" '
1388 if (arr[$0] != 1) {
1389 arr[$0] = 1;
1390 print un $0 "/packages.info";
1392 }' | sed 's|/undigest/main||' | \
1393 while read pi; do
1394 [ -e "$pi" ] && echo "$pi"
1395 done
1399 # Strip versions from packages list
1401 strip_versions() {
1402 action 'Strip versions from list %s...' "$(basename "$1")"
1403 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1404 [ -f "$in_list" ] || die "List '$in_list' not found."
1406 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1407 awk '
1409 if (FILENAME ~ "packages.info") {
1410 # Collect package names
1411 FS = "\t"; pkg[$1] = 1;
1412 } else {
1413 FS = "-"; OFS = "-"; $0 = $0; # Fix bug with FS for first record
1414 while (NF > 1 && ! pkg[$0])
1415 NF --;
1416 printf "%s\n", $0;
1418 }' $(pi_lists) "$in_list" > "$tmp_list"
1420 cat "$tmp_list" > "$in_list"
1421 rm "$tmp_list"
1422 status
1426 # Calculate sizes (estimated) and real packages number (including all dependencies)
1427 # using given extracted flavor and current mirrors.
1429 # Input: <unpacked flavor dir> <flavor name> [<output full list file>]
1430 # Output in human readable form:
1431 # <unpacked size> <packed size> <size of ISO> <number of packages>
1432 # File $1/err output: unknown packages
1433 # File $1/warn output: warnings about missing packages
1434 # TODO: use 'equivalent packages' rules
1436 calc_sizes() {
1437 local dir="$1" flavor="$2" outfile="$3"
1438 local rootfs_packed=0 rootfs_unpacked=0 rootcd_unpacked=0
1440 if [ -s "$dir/$flavor.rootfs" ]; then
1441 rootfs_packed="$(wc -c < "$dir/$flavor.rootfs")";
1442 rootfs_unpacked="$(zcat "$dir/$flavor.rootfs" | wc -c)";
1443 fi
1444 if [ -s "$dir/$flavor.rootcd" ]; then
1445 rootcd_unpacked="$(zcat "$dir/$flavor.rootcd" | wc -c)";
1446 fi
1448 awk -F$'\t' \
1449 -vrootfs_p="$rootfs_packed" -vrootfs_u="$rootfs_unpacked" -vrootcd_u="$rootcd_unpacked" \
1450 -voutfile="$outfile" -verrfile="$dir/err" -vwarnfile="$dir/warn" '
1451 BEGIN {
1452 K = 1024; M = K * 1024; G = M * 1024;
1454 function h2b(h) {
1455 # Convert human-readable format to bytes
1456 if (h ~ "K") return h * K;
1457 if (h ~ "M") return h * M;
1458 if (h ~ "G") return h * G;
1459 return h;
1461 function b2h(b, p) {
1462 # Convert bytes to human-readable format
1463 if (b >= G) { b /= G; p = "G"; }
1464 else if (b >= M) { b /= M; p = "M"; }
1465 else { b /= K; p = "K"; }
1466 if (b >= 100) printf "%d%s\n", b, p;
1467 else printf "%.1f%s\n", b, p;
1469 function mark_deps(pkg, localdepend, localdepends) {
1470 # Mark package with its dependencies (to be processed later)
1471 if (sizes[pkg]) {
1472 if (! pkgs[pkg]) {
1473 pkgs[pkg] = sizes[pkg];
1475 if (depends[pkg]) {
1476 split(depends[pkg], localdepends, " ");
1477 # Recursive call
1478 for (localdepend in localdepends)
1479 mark_deps(localdepends[localdepend]);
1482 } else {
1483 printf " %s\n", $1 >> errfile;
1486 function calc(pkg, size_u, size_p) {
1487 # Calculate unpacked and packed sizes of /boot
1488 if (pkgs[pkg]) { boot_u += h2b(size_u); boot_p += h2b(size_p); }
1490 # main loop
1492 if (FILENAME ~ "packages.info") {
1493 # Step #1: fill arrays "sizes" and "depends"
1494 if (! sizes[$1]) {
1495 sizes[$1] = $7;
1496 depends[$1] = $8;
1498 } else {
1499 # Step #2: mark packages and its dependencies
1500 mark_deps($1);
1503 END {
1504 # Calculate sums for all marked packages and its deps
1505 for (pkg in pkgs) {
1506 num_pkgs ++;
1507 split(pkgs[pkg], s, " ");
1508 size_packed += h2b(s[1]);
1509 size_unpacked += h2b(s[2]);
1510 if (outfile) print pkg >> outfile;
1512 # Add files placed in flavor.rootfs
1513 size_packed += rootfs_p;
1514 size_unpacked += rootfs_u;
1516 # Check critical packages: "syslinux" and one of the packages containing "vmlinuz*"
1517 printf "" > warnfile;
1518 if (! pkgs["syslinux"]) printf " * Syslinux\n" >> warnfile;
1519 if (! pkgs["linux"] && ! pkgs["linux-without-modules"] && \
1520 ! pkgs["linux64"] && ! pkgs["linux64-without-modules"] && \
1521 ! pkgs["linux-libre"] && ! pkgs["linux-libre-without-modules"] && \
1522 ! pkgs["linux-uml"]) printf " * Linux kernel\n" >> warnfile;
1524 # Calculate unpacked and packed sizes of /boot
1525 calc("syslinux", "156K", "120K" );
1526 calc("gpxe", "196K", "188K" );
1527 calc("ipxe", "316K", "312K" );
1528 calc("memtest", "52K", "48K" );
1529 calc("memtest-serial", "52K", "48K" );
1530 calc("slitaz-configs-base", "36K", "28K" );
1531 calc("linux", "2.8M", "2.8M" );
1532 calc("linux-without-modules", "12.6M", "12.8M");
1533 calc("linux64", "3.0M", "3.0M" );
1534 calc("linux64-without-modules", "13.2M", "13.4M");
1535 calc("linux-libre", "2.3M", "2.3M" );
1536 calc("linux-libre-without-modules", "6.9M", "6.9M" );
1537 calc("linux-uml", "3.0M", "1.1M" );
1539 # /boot is moved away from rootfs
1540 size_packed -= boot_p;
1541 size_unpacked -= boot_u;
1543 # Add rootcd payload and /boot content sizes
1544 size_iso = size_packed + rootcd_u + boot_u;
1546 printf "%s %s ", b2h(size_unpacked), b2h(size_packed);
1547 printf "%s %d\n", b2h(size_iso), num_pkgs;
1548 }' $(pi_lists) "$dir/$flavor.pkglist"
1552 # Display list of unknown packages (informative)
1554 display_unknown() {
1555 [ -s "$1" ] || return
1556 echo "Unknown packages:" >&2
1557 cat "$1" >&2
1558 rm "$1"
1562 # Display warnings about critical packages absent (informative)
1564 display_warn() {
1565 [ -s "$1" ] || return
1566 echo "Absent critical packages:" >&2
1567 cat "$1" >&2
1568 rm "$1"
1569 echo "Probably ISO image will be unusable."
1573 # Install packages to rootfs
1575 install_list_to_rootfs() {
1576 local list="$1" rootfs="$2" pkg i ii
1578 # initial tazpkg setup in empty rootfs
1579 export root="$rootfs"
1580 tazpkg --root=$rootfs >/dev/null 2>&1
1581 # link rootfs packages cache to the regular packages cache
1582 rm -r "$rootfs/var/cache/tazpkg"
1583 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1585 setup_mirrors mirrors
1587 # Just in case if flavor not contains "tazlito" package
1588 mkdir -p "$rootfs/etc/tazlito"
1590 for pkg in $(cat $list); do
1591 action 'Installing package: %s' "$pkg"
1592 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1593 status
1594 done
1595 newline
1597 restore_mirrors
1598 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1599 for i in fresh repacked; do
1600 ii="$rootfs/var/lib/tazpkg/undigest/$i"
1601 [ -d "$ii" ] && rm -rf "$ii"
1602 ii="$rootfs/var/lib/tazpkg/priority"
1603 if [ -f "$ii" ]; then
1604 sed -i "/$i/d" "$ii"
1605 [ -s "$ii" ] || rm "$ii"
1606 fi
1607 done
1608 [ -d "$rootfs/var/lib/tazpkg/undigest" ] && \
1609 for i in $(find "$rootfs/var/lib/tazpkg/undigest" -type f); do
1610 # Remove all undigest PKGDB files but 'mirror'
1611 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1612 done
1613 [ -d "$rootfs/var/lib/tazpkg/undigest" ] && \
1614 rmdir --ignore-fail-on-non-empty "$rootfs/var/lib/tazpkg/undigest"
1616 # Un-link packages cache
1617 rm "$rootfs/var/cache/tazpkg"
1619 # Clean /var/lib/tazpkg
1620 rm $rootfs/var/lib/tazpkg/ID* \
1621 $rootfs/var/lib/tazpkg/descriptions.txt \
1622 $rootfs/var/lib/tazpkg/extra.list \
1623 $rootfs/var/lib/tazpkg/files* \
1624 $rootfs/var/lib/tazpkg/packages.* \
1625 2>/dev/null
1631 ####################
1632 # Tazlito commands #
1633 ####################
1635 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1636 case "$0" in
1637 *reduplicate)
1638 find ${@:-.} ! -type d -links +1 \
1639 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1640 exit 0 ;;
1641 *deduplicate)
1642 deduplicate "$@"
1643 exit 0 ;;
1644 esac
1647 case "$COMMAND" in
1648 stats)
1649 # Tazlito general statistics from the config file.
1651 title 'Tazlito statistics'
1652 optlist "\
1653 Config file : $CONFIG_FILE
1654 ISO name : $ISO_NAME.iso
1655 Volume name : $VOLUM_NAME
1656 Prepared : $PREPARED
1657 Packages repository : $PACKAGES_REPOSITORY
1658 Distro directory : $DISTRO
1659 Additional files : $ADDFILES
1660 " | sed '/: $/d'
1661 footer
1662 ;;
1665 list-addfiles)
1666 # Simple list of additional files in the rootfs
1667 newline
1668 if [ -d "$ADDFILES/rootfs" ]; then
1669 cd $ADDFILES
1670 find rootfs -type f
1671 else
1672 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1673 fi
1674 newline
1675 ;;
1678 gen-config)
1679 # Generate a new config file in the current dir or the specified
1680 # directory by $2.
1682 if [ -n "$2" ]; then
1683 mkdir -p "$2" && cd "$2"
1684 fi
1686 newline
1687 action 'Generating empty tazlito.conf...'
1688 empty_config_file
1689 status
1691 separator
1692 if [ -f 'tazlito.conf' ] ; then
1693 _ 'Configuration file is ready to edit.'
1694 _ 'File location: %s' "$(pwd)/tazlito.conf"
1695 newline
1696 fi
1697 ;;
1700 configure)
1701 # Configure a tazlito.conf config file. Start by getting
1702 # a empty config file and sed it.
1704 if [ -f 'tazlito.conf' ]; then
1705 rm tazlito.conf
1706 else
1707 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1708 'or in the same directory of the file you want to configure.'
1709 cd /etc
1710 fi
1712 empty_config_file
1714 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1716 # ISO name.
1717 echo -n "ISO name : " ; read answer
1718 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1719 # Volume name.
1720 echo -n "Volume name : " ; read answer
1721 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1722 # Packages repository.
1723 echo -n "Packages repository : " ; read answer
1724 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1725 # Distro path.
1726 echo -n "Distro path : " ; read answer
1727 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1728 footer "Config file is ready to use."
1729 echo 'You can now extract an ISO or generate a distro.'
1730 newline
1731 ;;
1734 gen-iso)
1735 # Simply generate a new iso.
1737 check_root
1738 verify_rootcd
1739 gen_livecd_isolinux
1740 distro_stats
1741 ;;
1744 gen-initiso)
1745 # Simply generate a new initramfs with a new iso.
1747 check_root
1748 verify_rootcd
1749 gen_initramfs "$ROOTFS"
1750 gen_livecd_isolinux
1751 distro_stats
1752 ;;
1755 extract-distro)
1756 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1758 check_root
1759 ISO_IMAGE="$2"
1760 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1761 'Example:\n tazlito image.iso /path/target'
1763 # Set the distro path by checking for $3 on cmdline.
1764 TARGET="${3:-$DISTRO}"
1766 # Exit if existing distro is found.
1767 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1768 'Please clean the distro tree or change directory path.'
1770 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
1772 # Start to mount the ISO.
1773 action 'Mounting ISO image...'
1774 mkdir -p "$TMP_DIR"
1775 # Get ISO file size.
1776 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
1777 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
1778 sleep 2
1779 # Prepare target dir, copy the kernel and the rootfs.
1780 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
1781 status
1783 action 'Copying the Linux kernel...'
1784 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
1785 make_bzImage_hardlink "$TARGET/rootcd/boot"
1786 else
1787 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
1788 fi
1789 status
1791 for i in $(ls $TMP_DIR); do
1792 [ "$i" == 'boot' ] && continue
1793 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
1794 done
1796 for loader in isolinux syslinux extlinux grub; do
1797 [ -d "$TMP_DIR/boot/$loader" ] || continue
1798 action 'Copying %s files...' "$loader"
1799 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
1800 status
1801 done
1803 action 'Copying the rootfs...'
1804 cp $TMP_DIR/boot/rootfs.?z "$TARGET/rootcd/boot"
1805 status
1807 # Extract initramfs.
1808 cd "$TARGET/rootfs"
1809 action 'Extracting the rootfs...'
1810 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
1811 # unpack /usr
1812 for i in etc/tazlito/*.extract; do
1813 [ -f "$i" ] && . $i ../rootcd
1814 done
1815 # Umount and remove temp directory and cd to $TARGET to get stats.
1816 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
1817 cd ..
1818 status
1820 newline
1821 separator
1822 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
1823 echo "Distro tree : $(pwd)"
1824 echo "Rootfs size : $(du -sh rootfs)"
1825 echo "Rootcd size : $(du -sh rootcd)"
1826 footer
1827 ;;
1830 list-flavors)
1831 # Show available flavors.
1832 local list='/etc/tazlito/flavors.list'
1833 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
1834 title 'List of flavors'
1835 cat $list
1836 footer
1837 ;;
1840 show-flavor)
1841 # Show flavor description.
1842 set -e
1843 flavor=${2%.flavor}
1844 flv_dir="$(extract_flavor "$flavor")"
1845 desc="$flv_dir/$flavor.desc"
1846 if [ -n "$brief" ]; then
1847 if [ -z "$noheader" ]; then
1848 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
1849 separator
1850 fi
1851 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
1852 "$(field ISO "$desc")" \
1853 "$(field Rootfs "$desc")" \
1854 "$(field Description "$desc")"
1855 else
1856 separator
1857 cat "$desc"
1858 fi
1859 cleanup
1860 ;;
1863 gen-liveflavor)
1864 # Generate a new flavor from the live system.
1865 FLAVOR=${2%.flavor}
1866 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1868 case "$FLAVOR" in
1869 -?|-h*|--help)
1870 cat <<EOT
1871 SliTaz Live Tool - Version: $VERSION
1873 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
1875 $(boldify '<flavor-patch-file> format:')
1876 $(optlist "\
1877 code data
1878 + package to add
1879 - package to remove
1880 ! non-free package to add
1881 ? display message
1882 @ flavor description
1883 ")
1885 $(boldify 'Example:')
1886 $(optlist "\
1887 @ Developer tools for SliTaz maintainers
1888 + slitaz-toolchain
1889 + mercurial
1890 ")
1891 EOT
1892 exit 1
1893 ;;
1894 esac
1895 mv /etc/tazlito/distro-packages.list \
1896 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
1897 rm -f distro-packages.list non-free.list 2>/dev/null
1898 tazpkg recharge
1900 DESC=""
1901 [ -n "$3" ] && \
1902 while read action pkg; do
1903 case "$action" in
1904 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
1905 -) yes | tazpkg remove $pkg ;;
1906 !) echo $pkg >> non-free.list ;;
1907 @) DESC="$pkg" ;;
1908 \?) echo -en "$pkg"; read action ;;
1909 esac
1910 done < $3
1912 yes '' | tazlito gen-distro
1913 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
1914 mv /etc/tazlito/distro-packages.list.$$ \
1915 /etc/tazlito/distro-packages.list 2>/dev/null
1916 ;;
1919 gen-flavor)
1920 # Generate a new flavor from the last ISO image generated
1921 FLAVOR=${2%.flavor}
1922 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1924 title 'Flavor generation'
1925 check_rootfs
1926 FILES="$FLAVOR.pkglist"
1928 action 'Creating file %s...' "$FLAVOR.flavor"
1929 for i in rootcd rootfs; do
1930 if [ -d "$ADDFILES/$i" ] ; then
1931 FILES="$FILES\n$FLAVOR.$i"
1932 (cd "$ADDFILES/$i"; find . | cpio -o -H newc 2>/dev/null | gzip -9) > $FLAVOR.$i
1933 fi
1934 done
1935 status
1937 answer=$(grep -s ^Description $FLAVOR.desc)
1938 answer=${answer#Description : }
1939 if [ -z "$answer" ]; then
1940 echo -n "Description: "
1941 read answer
1942 fi
1944 action 'Compressing flavor %s...' "$FLAVOR"
1945 echo "Flavor : $FLAVOR" > $FLAVOR.desc
1946 echo "Description : $answer" >> $FLAVOR.desc
1947 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
1948 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
1949 for i in $(ls $ROOTFS$INSTALLED); do
1950 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
1951 EXTRAVERSION=""
1952 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
1953 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
1954 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
1955 echo "$i" >> $FLAVOR.nonfree
1956 else
1957 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
1958 fi
1959 done
1960 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
1961 for i in $LOCALSTATE/undigest/*/mirror ; do
1962 [ -s $i ] && cat $i >> $FLAVOR.mirrors
1963 done
1964 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
1965 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | gzip -9 > $FLAVOR.flavor
1966 rm $(echo -e $FILES)
1967 status
1969 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
1970 ;;
1973 upgrade-flavor)
1974 # Strip versions from pkglist and update estimated numbers in flavor.desc
1975 flavor="${2%.flavor}"
1976 set -e
1977 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1978 set +e
1980 flv_dir="$(extract_flavor "$flavor")"
1982 strip_versions "$flv_dir/$flavor.pkglist"
1984 action 'Updating %s...' "$flavor.desc"
1986 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
1987 set -- $(calc_sizes "$flv_dir" "$flavor")
1988 restore_mirrors >/dev/null
1990 sed -i -e '/Image is ready/d' \
1991 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
1992 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
1993 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
1994 -e "s|\(Packages *:\).*$|\1 $4|" \
1995 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
1996 "$flv_dir/$flavor.desc"
1998 pack_flavor "$flv_dir" "$flavor"
1999 status
2000 display_unknown "$flv_dir/err"
2001 display_warn "$flv_dir/warn"
2002 cleanup
2003 ;;
2006 extract-flavor)
2007 # Extract a flavor into $FLAVORS_REPOSITORY
2008 flavor="${2%.flavor}"
2009 set -e
2010 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2011 set +e
2013 action 'Extracting %s...' "$flavor.flavor"
2014 flv_dir="$(extract_flavor "$flavor" full)"
2015 storage="$FLAVORS_REPOSITORY/$flavor"
2017 rm -rf "$storage" 2>/dev/null
2018 mkdir -p "$storage"
2019 cp -a "$flv_dir"/* "$storage"
2020 rm "$storage/description"
2021 status
2023 strip_versions "$storage/packages.list"
2025 cleanup
2026 ;;
2029 pack-flavor)
2030 # Create a flavor from $FLAVORS_REPOSITORY.
2031 flavor=${2%.flavor}
2032 storage="$FLAVORS_REPOSITORY/$flavor"
2034 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2036 action 'Creating flavor %s...' "$flavor"
2037 tmp_dir="$(mktemp -d)"
2039 while read from to; do
2040 [ -s "$storage/$from" ] || continue
2041 cp -a "$storage/$from" "$tmp_dir/$to"
2042 done <<EOT
2043 mirrors $flavor.mirrors
2044 distro.sh $flavor-distro.sh
2045 receipt $flavor.receipt
2046 non-free.list $flavor.nonfree
2047 EOT
2049 # Build the package list.
2050 # It can include a list from another flavor with the keyword @include
2051 if [ -s "$storage/packages.list" ]; then
2052 include=$(grep '^@include' "$storage/packages.list")
2053 if [ -n "$include" ]; then
2054 include=${include#@include }
2055 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2056 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2057 else
2058 echo -e "\nERROR: Can't find include package list from $include\n"
2059 fi
2060 fi
2061 # Generate the final/initial package list
2062 [ -s "$storage/packages.list" ] && \
2063 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2064 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2065 fi
2067 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2068 # Process multi-rootfs flavor
2069 . "$storage/receipt"
2070 set -- $ROOTFS_SELECTION
2071 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2072 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2073 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2075 for i in rootcd rootfs; do
2076 mkdir "$tmp_dir/$i"
2077 # Copy extra files from the first flavor
2078 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2079 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2080 # Overload extra files by meta flavor
2081 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2082 [ -n "$(ls $tmp_dir/$i)" ] &&
2083 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2084 gzip -9 > "$tmp_dir/$flavor.$i"
2085 rm -rf "$tmp_dir/$i"
2086 done
2087 else
2088 # Process plain flavor
2089 for i in rootcd rootfs; do
2090 [ -d "$storage/$i" ] || continue
2091 (cd "$storage/$i";
2092 find . | cpio -o -H newc 2>/dev/null) | gzip -9 > "$tmp_dir/$flavor.$i"
2093 done
2094 fi
2096 unset VERSION MAINTAINER ROOTFS_SELECTION
2097 set -- $(calc_sizes "$tmp_dir" "$flavor")
2098 ROOTFS_SIZE="$1 (estimated)"
2099 INITRAMFS_SIZE="$2 (estimated)"
2100 ISO_SIZE="$3 (estimated)"
2101 PKGNUM="$4"
2102 . "$storage/receipt"
2104 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2105 Flavor : $FLAVOR
2106 Description : $SHORT_DESC
2107 Version : $VERSION
2108 Maintainer : $MAINTAINER
2109 LiveCD RAM size : $FRUGAL_RAM
2110 Rootfs list : $ROOTFS_SELECTION
2111 Build date : $(date '+%Y%m%d at %T')
2112 Packages : $PKGNUM
2113 Rootfs size : $ROOTFS_SIZE
2114 Initramfs size : $INITRAMFS_SIZE
2115 ISO image size : $ISO_SIZE
2116 ================================================================================
2118 EOT
2120 rm -f $tmp_dir/packages.list
2121 pack_flavor "$tmp_dir" "$flavor"
2122 status
2123 display_unknown "$tmp_dir/err"
2124 display_warn "$flv_dir/warn"
2125 cleanup
2126 ;;
2129 get-flavor)
2130 # Get a flavor's files and prepare for gen-distro.
2131 flavor=${2%.flavor}
2132 title 'Preparing %s distro flavor' "$flavor"
2133 set -e
2134 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2135 set +e
2137 action 'Cleaning %s...' "$DISTRO"
2138 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2139 # Clean old files
2140 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2141 [ -f "$i" ] && rm "$i"
2142 done
2143 mkdir -p "$DISTRO"
2144 status
2146 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2148 action 'Extracting flavor %s...' "$flavor.flavor"
2149 flv_dir="$(extract_flavor "$flavor" info)"
2150 cp -a "$flv_dir"/* .
2151 mv packages.list distro-packages.list
2152 mv -f info /etc/tazlito
2153 status
2155 for i in rootcd rootfs; do
2156 if [ -d "$i" ]; then
2157 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2158 fi
2159 done
2161 rm -f /etc/tazlito/rootfs.list
2162 grep -q '^Rootfs list' description &&
2163 grep '^Rootfs list' description | sed 's/.*: \(.*\)$/\1/' > /etc/tazlito/rootfs.list
2165 action 'Updating tazlito.conf...'
2166 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2167 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2168 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2169 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2170 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2171 status
2173 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2174 cleanup
2175 ;;
2178 iso2flavor)
2179 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2180 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2182 FLAVOR=${3%.flavor}
2183 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2184 mount -o loop,ro $2 $TMP_DIR/iso
2185 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2186 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2187 ! -s $TMP_DIR/flavor/*.desc ]; then
2188 echo "META flavors are not supported."
2189 umount -d $TMP_DIR/iso
2190 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2191 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2192 echo "No /boot/rootfs.gz in ISO image. Needs a SliTaz ISO."
2193 umount -d $TMP_DIR/iso
2194 else
2195 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*gz); do
2196 ( zcat < $i || unlzma < $i ) | \
2197 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2198 done
2199 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2200 echo "No file /etc/slitaz-release in /boot/rootfs.gz of iso image. Needs a non loram SliTaz iso."
2201 umount -d $TMP_DIR/iso
2202 else
2203 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2204 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2205 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2206 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2207 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2208 umount -d $TMP_DIR/iso
2209 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2210 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2211 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2212 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2213 < $TMP_DIR/rootfs$INSTALLED.md5
2214 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2215 if [ -s $TMP_DIR/flavor/*desc ]; then
2216 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2217 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2218 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2219 for i in rootfs rootcd ; do
2220 [ -s $TMP_DIR/flavor/*.list$i ] &&
2221 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2222 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | gzip -9 > $TMP_DIR/$FLAVOR.$i
2223 done
2224 else
2225 find_flavor_rootfs $TMP_DIR/rootfs
2226 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2227 for i in rootfs rootcd ; do
2228 [ "$(ls $TMP_DIR/$i)" ] &&
2229 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | gzip -9 > "$TMP_DIR/$FLAVOR.$i"
2230 done
2231 unset VERSION MAINTAINER
2232 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2233 if [ -n "$DESCRIPTION" ]; then
2234 echo -en "Flavor version : "; read -t 30 VERSION
2235 echo -en "Flavor maintainer (your email) : "; read -t 30 MAINTAINER
2236 fi
2238 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2239 Flavor : $FLAVOR
2240 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2241 Version : ${VERSION:-1.0}
2242 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2243 LiveCD RAM size : $RAM_SIZE
2244 Build date : $BUILD_DATE
2245 Packages : $PKGCNT
2246 Rootfs size : $ROOTFS_SIZE
2247 Initramfs size : $INITRAMFS_SIZE
2248 ISO image size : $ISO_SIZE
2249 ================================================================================
2251 EOT
2252 longline "Tazlito can't detect each file installed during \
2253 a package post_install. You should extract this flavor (tazlito extract-flavor \
2254 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2255 tree and remove files generated by post_installs.
2256 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2257 repack the flavor (tazlito pack-flavor $FLAVOR)"
2258 fi
2259 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | gzip -9 > $FLAVOR.flavor
2260 fi
2261 fi
2262 rm -rf $TMP_DIR
2263 ;;
2266 gen-distro)
2267 # Generate a live distro tree with a set of packages.
2269 check_root
2270 start_time=$(date +%s)
2272 # Tazlito options: --iso or --cdrom
2273 CDROM=''
2274 [ -n "$iso" ] && CDROM="-o loop $iso"
2275 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2277 # Check if a package list was specified on cmdline.
2278 if [ -f "$2" ]; then
2279 LIST_NAME="$2"
2280 else
2281 LIST_NAME='distro-packages.list'
2282 fi
2284 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2285 'Please clean the distro tree or change directory path.'
2286 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2287 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2289 # If list not given: build list with all installed packages
2290 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2291 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2292 fi
2294 # Exit if no list name.
2295 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2297 # Start generation.
2298 title 'Tazlito generating a distro'
2300 # Misc checks
2301 mkdir -p "$PACKAGES_REPOSITORY"
2302 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2304 # Mount CD-ROM to be able to repack boot-loader packages
2305 if [ ! -e /boot -a -n "$CDROM" ]; then
2306 mkdir $TMP_MNT
2307 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2308 ln -s "$TMP_MNT/boot" /
2309 if [ ! -d "$ADDFILES/rootcd" ] ; then
2310 mkdir -p "$ADDFILES/rootcd"
2311 for i in $(ls $TMP_MNT); do
2312 [ "$i" == 'boot' ] && continue
2313 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2314 done
2315 fi
2316 else
2317 rmdir "$TMP_MNT"
2318 fi
2319 fi
2321 # Rootfs stuff.
2322 echo 'Preparing the rootfs directory...'
2323 mkdir -p "$ROOTFS"
2324 mkdir -p "$TMP_DIR"
2326 strip_versions "$LIST_NAME"
2328 if [ "$REPACK" == 'y' ]; then
2329 # Determine full packages list with all dependencies
2330 tmp_dir="$(mktemp -d)"
2331 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2332 touch "$tmp_dir/full.pkglist"
2333 calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2335 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2336 while read pkgname pkgver; do
2337 # Is package in full list?
2338 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2339 # Is package already repacked?
2340 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2341 _ 'Repacking %s...' "$pkgname-$pkgver"
2342 tazpkg repack "$pkgname" --quiet
2343 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2344 status
2345 done
2347 rm -r "$tmp_dir"
2348 fi
2350 if [ -f non-free.list ]; then
2351 # FIXME: working in the ROOTFS chroot?
2352 newline
2353 echo 'Preparing non-free packages...'
2354 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2355 for pkg in $(cat 'non-free.list'); do
2356 if [ ! -d "$INSTALLED/$pkg" ]; then
2357 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2358 tazpkg get-install get-$pkg
2359 fi
2360 get-$pkg "$ROOTFS"
2361 fi
2362 tazpkg repack $pkg
2363 pkg=$(ls $pkg*.tazpkg)
2364 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2365 mv $pkg $PACKAGES_REPOSITORY
2366 done
2367 fi
2368 cp $LIST_NAME $DISTRO/distro-packages.list
2369 newline
2371 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2373 cd $DISTRO
2374 cp distro-packages.list $ROOTFS/etc/tazlito
2375 # Copy all files from $ADDFILES/rootfs to the rootfs.
2376 if [ -d "$ADDFILES/rootfs" ] ; then
2377 action 'Copying addfiles content to the rootfs...'
2378 cp -a $ADDFILES/rootfs/* $ROOTFS
2379 status
2380 fi
2382 action 'Root filesystem is generated...'; status
2384 # Root CD part.
2385 action 'Preparing the rootcd directory...'
2386 mkdir -p $ROOTCD
2387 status
2389 # Move the boot dir with the Linux kernel from rootfs.
2390 # The boot dir goes directly on the CD.
2391 if [ -d "$ROOTFS/boot" ] ; then
2392 action 'Moving the boot directory...'
2393 mv $ROOTFS/boot $ROOTCD
2394 cd $ROOTCD/boot
2395 make_bzImage_hardlink
2396 status
2397 fi
2398 cd $DISTRO
2399 # Copy all files from $ADDFILES/rootcd to the rootcd.
2400 if [ -d "$ADDFILES/rootcd" ] ; then
2401 action 'Copying addfiles content to the rootcd...'
2402 cp -a $ADDFILES/rootcd/* $ROOTCD
2403 status
2404 fi
2405 # Execute the distro script used to perform tasks in the rootfs
2406 # before compression. Give rootfs path in arg
2407 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2408 if [ -x "$DISTRO_SCRIPT" ]; then
2409 echo 'Executing distro script...'
2410 sh $DISTRO_SCRIPT $DISTRO
2411 fi
2413 # Execute the custom_rules() found in receipt.
2414 if [ -s "$TOP_DIR/receipt" ]; then
2415 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2416 echo -e "Executing: custom_rules()\n"
2417 . "$TOP_DIR/receipt"
2418 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2419 fi
2420 fi
2422 # Multi-rootfs
2423 if [ -s /etc/tazlito/rootfs.list ]; then
2425 FLAVOR_LIST="$(awk '{
2426 for (i = 2; i <= NF; i+=2)
2427 printf "%s ", i;
2428 }' /etc/tazlito/rootfs.list)"
2430 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2431 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2432 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2434 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2435 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2436 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2437 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2439 n=0
2440 last=$ROOTFS
2441 while read flavor; do
2442 n=$(($n+1))
2443 newline
2444 boldify "Building $flavor rootfs..."
2446 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2447 cp "$TOP_DIR/$flavor.flavor" .
2449 if [ ! -s "$flavor.flavor" ]; then
2450 # We may have it in $FLAVORS_REPOSITORY
2451 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2452 tazlito pack-flavor $flavor
2453 else
2454 download $flavor.flavor
2455 fi
2456 fi
2458 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2459 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2460 sed 's/.*/&.tazpkg/' < $flavor.pkglist > $DISTRO/list-packages0$n
2461 status
2463 strip_versions "$DISTRO/list-packages0$n"
2465 mkdir ${ROOTFS}0$n
2466 # Install packages
2467 cd $PACKAGES_REPOSITORY
2469 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2471 rm -rf ${ROOTFS}0$n/boot
2473 cd $DISTRO
2474 if [ -s $flavor.rootfs ]; then
2475 echo -n "Adding $flavor rootfs extra files..."
2476 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2477 fi
2479 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2480 mv $DISTRO/list-packages0$n ${ROOTFS}0$n/etc/tazlito/distro-packages.list
2481 status
2483 rm -f $flavor.flavor install-list
2484 mergefs ${ROOTFS}0$n $last
2485 last=${ROOTFS}0$n
2486 done <<EOT
2487 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2488 EOT
2489 #'
2490 i=$(($n+1))
2491 while [ $n -gt 0 ]; do
2492 mv ${ROOTFS}0$n ${ROOTFS}$i
2493 echo "Compressing ${ROOTFS}0$n ($(du -hs ${ROOTFS}$i | awk '{ print $1 }'))..."
2494 gen_initramfs ${ROOTFS}$i
2495 n=$(($n-1))
2496 i=$(($i-1))
2497 done
2498 mv $ROOTFS ${ROOTFS}$i
2499 gen_initramfs ${ROOTFS}$i
2500 update_bootconfig $ROOTCD/boot/isolinux \
2501 "$(cat /etc/tazlito/rootfs.list)"
2502 else
2503 # Initramfs and ISO image stuff.
2504 gen_initramfs $ROOTFS
2505 fi
2506 gen_livecd_isolinux
2507 distro_stats
2508 cleanup
2509 ;;
2512 clean-distro)
2513 # Remove old distro tree.
2515 check_root
2516 title 'Cleaning: %s' "$DISTRO"
2517 if [ -d "$DISTRO" ] ; then
2518 if [ -d "$ROOTFS" ] ; then
2519 action 'Removing the rootfs...'
2520 rm -f $DISTRO/$INITRAMFS
2521 rm -rf $ROOTFS
2522 status
2523 fi
2524 if [ -d "$ROOTCD" ] ; then
2525 action 'Removing the rootcd...'
2526 rm -rf $ROOTCD
2527 status
2528 fi
2529 action 'Removing eventual ISO image...'
2530 rm -f $DISTRO/$ISO_NAME.iso
2531 rm -f $DISTRO/$ISO_NAME.md5
2532 status
2533 fi
2534 footer
2535 ;;
2538 check-distro)
2539 # Check for a few LiveCD needed files not installed by packages.
2541 # TODO: Remove this function.
2542 # First two files are maintained by tazpkg while it runs on rootfs,
2543 # while last one file should be maintained by tazlito itself.
2544 check_rootfs
2545 title 'Checking distro: %s' "$ROOTFS"
2546 # SliTaz release info.
2547 if [ ! -f "$ROOTFS/etc/slitaz-release" ]; then
2548 echo "Missing release info : /etc/slitaz-release"
2549 else
2550 release=$(cat $ROOTFS/etc/slitaz-release)
2551 echo -n "Release : $release"
2552 status
2553 fi
2554 # Tazpkg mirror.
2555 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2556 echo -n "Mirror URL : Missing $LOCALSTATE/mirror"
2557 todomsg
2558 else
2559 action 'Mirror configuration exists...'
2560 status
2561 fi
2562 # Isolinux msg
2563 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2564 echo -n "Isolinux msg : Missing cooking date XXXXXXXX (ex $(date +%Y%m%d))"
2565 todomsg
2566 else
2567 action 'Isolinux message seems good...'
2568 status
2569 fi
2570 footer
2571 ;;
2574 writeiso)
2575 # Writefs to ISO image including /home unlike gen-distro we don't use
2576 # packages to generate a rootfs, we build a compressed rootfs with all
2577 # the current filesystem similar to 'tazusb writefs'.
2579 DISTRO='/home/slitaz/distro'
2580 ROOTCD="$DISTRO/rootcd"
2581 COMPRESSION="${2:-none}"
2582 ISO_NAME="${3:-slitaz}"
2583 check_root
2584 # Start info
2585 title 'Write filesystem to ISO'
2586 longline "The command writeiso will write the current filesystem into a \
2587 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2588 newline
2589 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2591 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2592 # Save some space
2593 rm -rf /var/cache/tazpkg/*
2594 rm -f /var/lib/tazpkg/*.bak
2595 rm -rf $DISTRO
2597 # Optionally remove sound card selection and screen resolution.
2598 if [ -z $LaunchedByTazpanel ]; then
2599 echo "Do you wish to remove the sound card and screen configs ? "
2600 echo -n "Press ENTER to keep or answer (No|yes|exit): "
2601 read anser
2602 case $anser in
2603 e|E|"exit"|Exit)
2604 exit 0 ;;
2605 y|Y|yes|Yes)
2606 echo -n "Removing current sound card and screen configurations..."
2607 rm -f /var/lib/sound-card-driver
2608 rm -f /var/lib/alsa/asound.state
2609 rm -f /etc/X11/xorg.conf ;;
2610 *)
2611 echo -n "Keeping current sound card and screen configurations..." ;;
2612 esac
2613 status
2614 newline
2616 # Optionally remove i18n settings
2617 echo "Do you wish to remove local/keymap settings ? "
2618 echo -n "Press ENTER to keep or answer (No|yes|exit): "
2619 read anser
2620 case $anser in
2621 e|E|"exit"|Exit)
2622 exit 0 ;;
2623 y|Y|yes|Yes)
2624 echo "Removing current locale/keymap settings..."
2625 newline > /etc/locale.conf
2626 newline > /etc/keymap.conf ;;
2627 *)
2628 echo "Keeping current locale/keymap settings..." ;;
2629 esac
2630 status
2631 fi
2633 # Clean-up files by default
2634 newline > /etc/udev/rules.d/70-persistent-net.rules
2635 newline > /etc/udev/rules.d/70-persistant-cd.rules
2637 # Create list of files including default user files since it is defined in /etc/passwd
2638 # and some new users might have been added.
2639 cd /
2640 echo 'init' > /tmp/list
2641 for dir in bin etc sbin var dev lib root usr home opt; do
2642 [ -d $dir ] && find $dir
2643 done >> /tmp/list
2645 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2646 [ -d $dir ] && echo $dir
2647 done >> /tmp/list
2649 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2651 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2652 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2653 #fi
2654 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2655 touch /var/log/wtmp
2657 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2658 sed -i "/var\/log\/$removelog/d" /tmp/list
2659 done
2661 # Generate initramfs with specified compression and display rootfs
2662 # size in realtime.
2663 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2665 write_initramfs &
2666 sleep 2
2667 cd - > /dev/null
2668 echo -en "\nFilesystem size:"
2669 while [ ! -f /tmp/rootfs ]; do
2670 sleep 1
2671 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2672 done
2673 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2674 echo -e "\n"
2675 rm -f /tmp/rootfs
2677 # Move freshly generated rootfs to the cdrom.
2678 mkdir -p $ROOTCD/boot
2679 mv -f /$INITRAMFS $ROOTCD/boot
2680 echo "Located in: $ROOTCD/boot/$INITRAMFS"
2682 # Now we need the kernel and isolinux files.
2683 copy_from_cd() {
2684 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2685 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2686 unmeta_boot $ROOTCD
2687 umount /media/cdrom
2690 bootloader='/var/lib/tazpkg/installed/syslinux/volatile.cpio.gz'
2691 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2692 copy_from_cd;
2693 elif mount | grep /media/cdrom; then
2694 copy_from_cd;
2695 elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2696 cp $bootloader $ROOTCD
2697 cd $ROOTCD
2698 zcat volatile.cpio.gz | cpio -id
2699 rm -f volatile.cpio.gz
2700 [ -f /boot/*slitaz ] && \
2701 cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2702 [ -f /boot/*slitaz64 ] && \
2703 cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2704 else
2705 touch /tmp/.write-iso-error
2706 longline "When SliTaz is running in RAM the kernel and bootloader \
2707 files are kept on the CD-ROM. Please insert a Live CD or loop mount the \
2708 slitaz.iso to /media/cdrom (run # mount -o loop slitaz-rolling.iso /media/cdrom ) \
2709 or # (tazpkg -gi linux --forced) to let Tazlito copy the files."
2710 echo -en "----\nENTER to continue..."; read i
2711 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2712 copy_from_cd
2713 fi
2715 # Generate the iso image.
2716 touch /tmp/.write-iso
2717 newline
2718 cd $DISTRO
2719 echo "Generating ISO image..."
2720 genisoimage -R -o $ISO_NAME.iso -b boot/isolinux/isolinux.bin \
2721 -c boot/isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
2722 -V "SliTaz" -p "$(id -un)" -input-charset utf-8 \
2723 -P "$(hostname)" -boot-info-table $ROOTCD
2724 if [ -x /usr/bin/isohybrid ]; then
2725 action 'Creating hybrid ISO/disk...'
2726 /usr/bin/isohybrid $ISO_NAME.iso -entry 2 2>/dev/null
2727 status
2728 fi
2729 if [ -x /usr/bin/iso2exe ]; then
2730 action 'Creating hybrid ISO/EXE...'
2731 /usr/bin/iso2exe $ISO_NAME.iso 2>/dev/null
2732 status
2733 fi
2734 action 'Creating the ISO md5sum...'
2735 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2736 status
2738 separator
2739 echo "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2740 rm -f /tmp/.write-iso
2741 newline
2742 if [ -z $LaunchedByTazpanel ]; then
2743 echo -n "Exit or burn ISO to CD-ROM (Exit|burn)? "; read anser
2744 case $anser in
2745 burn)
2746 umount /dev/cdrom 2>/dev/null
2747 eject
2748 echo -n "Please insert a blank CD-ROM and press ENTER..."
2749 read i && sleep 2
2750 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2751 echo -en "----\nENTER to continue..."; read i ;;
2752 *)
2753 exit 0 ;;
2754 esac
2755 fi
2756 ;;
2759 burn-iso)
2760 # Guess CD-ROM device, ask user and burn the ISO.
2762 check_root
2763 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2764 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2765 # We can specify an alternative ISO from the cmdline.
2766 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2767 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2769 title 'Tazlito burn ISO'
2770 echo "CD-ROM device : /dev/$DRIVE_NAME"
2771 echo "Drive speed : $DRIVE_SPEED"
2772 echo "ISO image : $iso"
2773 footer
2775 case $(yesorno 'Burn ISO image?' 'n') in
2776 y)
2777 title 'Starting Wodim to burn the ISO...'
2778 sleep 2
2779 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2780 footer 'ISO image is burned to CD-ROM.'
2781 ;;
2782 *)
2783 die 'Exiting. No ISO burned.'
2784 ;;
2785 esac
2786 ;;
2789 merge)
2790 # Merge multiple rootfs into one iso.
2792 if [ -z "$2" ]; then
2793 cat <<EOT
2794 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2796 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2797 i.e: rootfsN is a subset of rootfsN-1
2798 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2799 The boot loader will select the rootfs according to the RAM size detected.
2801 Example:
2802 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
2804 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
2805 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
2807 EOT
2808 exit 2
2809 fi
2811 shift # skip merge
2812 append="$1 slitaz1"
2813 shift # skip size1
2814 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
2816 ISO=$1.merged
2818 # Extract filesystems
2819 action 'Mounting %s' "$1"
2820 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
2821 status || cleanup_merge
2823 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2824 make_bzImage_hardlink $TMP_DIR/iso/boot
2825 umount -d $TMP_DIR/mnt
2826 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
2827 echo "$1 is already a merged iso. Aborting."
2828 cleanup_merge
2829 fi
2830 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
2831 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
2832 if [ ! -f /boot/isolinux/ifmem.c32 -a
2833 ! -f /boot/isolinux/c32box.c32 ]; then
2834 cat <<EOT
2835 No file /boot/isolinux/ifmem.c32
2836 Please install syslinux package !
2837 EOT
2838 rm -rf $TMP_DIR
2839 exit 1
2840 fi
2841 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
2842 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
2843 fi
2845 action 'Extracting iso/rootfs.gz'
2846 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
2847 [ -d $TMP_DIR/rootfs1/etc ]
2848 status || cleanup_merge
2850 n=1
2851 while [ -n "$2" ]; do
2852 shift # skip rootfs N-1
2853 p=$n
2854 n=$(($n + 1))
2855 append="$append $1 slitaz$n"
2856 shift # skip size N
2857 mkdir -p $TMP_DIR/rootfs$n
2859 action 'Extracting %s' "$1"
2860 extract_rootfs $1 $TMP_DIR/rootfs$n &&
2861 [ -d "$TMP_DIR/rootfs$n/etc" ]
2862 status || cleanup_merge
2864 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
2865 action 'Creating rootfs%s.gz' "$p"
2866 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
2867 status
2868 done
2869 action 'Creating rootfs%s.gz' "$n"
2870 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
2871 status
2872 rm -f $TMP_DIR/iso/boot/rootfs.gz
2873 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
2874 create_iso $ISO $TMP_DIR/iso
2875 rm -rf $TMP_DIR
2876 ;;
2879 repack)
2880 # Repack an iso with maximum lzma compression ratio.
2882 ISO=$2
2883 mkdir -p $TMP_DIR/mnt
2885 # Extract filesystems
2886 action 'Mounting %s' "$ISO"
2887 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
2888 status || cleanup_merge
2890 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2891 umount -d $TMP_DIR/mnt
2893 for i in $TMP_DIR/iso/boot/rootfs* ; do
2894 action 'Repacking %s' "$(basename $i)"
2895 (zcat $i 2>/dev/null || unlzma < $i || cat $i) 2>/dev/null > $TMP_DIR/rootfs
2896 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
2897 align_to_32bits $i
2898 status
2899 done
2901 create_iso $ISO $TMP_DIR/iso
2902 rm -rf $TMP_DIR
2903 ;;
2906 build-loram)
2907 # Build a Live CD for low RAM systems.
2909 ISO="$2"
2910 OUTPUT="$3"
2911 [ -z "$3" ] && \
2912 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
2913 mkdir -p "$TMP_DIR/iso"
2914 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
2915 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$ISO$/!d;s/:.*//;q")
2916 if ! check_iso_for_loram ; then
2917 umount -d "$TMP_DIR/iso"
2918 die "$ISO is not a valid SliTaz live CD. Abort."
2919 fi
2920 case "$4" in
2921 cdrom) build_loram_cdrom ;;
2922 http) build_loram_http ;;
2923 *) build_loram_ram ;;
2924 esac
2925 umount $TMP_DIR/iso # no -d: needs /proc
2926 losetup -d $loopdev
2927 rm -rf $TMP_DIR
2928 ;;
2931 emu-iso)
2932 # Emulate an ISO image with Qemu.
2933 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2934 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
2935 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
2936 echo -e "\nStarting Qemu emulator:\n"
2937 echo -e "qemu $QEMU_OPTS $iso\n"
2938 qemu $QEMU_OPTS $iso
2939 ;;
2942 deduplicate)
2943 # Deduplicate files in a tree
2944 shift
2945 deduplicate "$@"
2946 ;;
2949 usage|*)
2950 # Print usage also for all unknown commands.
2951 usage
2952 ;;
2953 esac
2955 exit 0