tazlito view tazlito @ rev 413

tazlito update_bootconfig() fix isolinux.cfg creation
author Aleksej Bobylev <al.bobylev@gmail.com>
date Sun Feb 21 04:51:59 2016 +0200 (2016-02-21)
parents 94c0fa7c65ba
children 4fccc5d405ed
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 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 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)
1553 display_unknown() {
1554 [ -s "$1" ] || return
1555 echo "Unknown packages:" >&2
1556 cat "$1" >&2
1557 rm "$1"
1561 # Display warnings about critical packages absent (informative)
1562 display_warn() {
1563 [ -s "$1" ] || return
1564 echo "Absent critical packages:" >&2
1565 cat "$1" >&2
1566 rm "$1"
1567 echo "Probably ISO image will be unusable."
1573 ####################
1574 # Tazlito commands #
1575 ####################
1577 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1578 case "$0" in
1579 *reduplicate)
1580 find ${@:-.} ! -type d -links +1 \
1581 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1582 exit 0 ;;
1583 *deduplicate)
1584 deduplicate "$@"
1585 exit 0 ;;
1586 esac
1589 case "$COMMAND" in
1590 stats)
1591 # Tazlito general statistics from the config file.
1593 title 'Tazlito statistics'
1594 optlist "\
1595 Config file : $CONFIG_FILE
1596 ISO name : $ISO_NAME.iso
1597 Volume name : $VOLUM_NAME
1598 Prepared : $PREPARED
1599 Packages repository : $PACKAGES_REPOSITORY
1600 Distro directory : $DISTRO
1601 Additional files : $ADDFILES
1602 " | sed '/: $/d'
1603 footer
1604 ;;
1607 list-addfiles)
1608 # Simple list of additional files in the rootfs
1609 newline
1610 if [ -d "$ADDFILES/rootfs" ]; then
1611 cd $ADDFILES
1612 find rootfs -type f
1613 else
1614 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1615 fi
1616 newline
1617 ;;
1620 gen-config)
1621 # Generate a new config file in the current dir or the specified
1622 # directory by $2.
1624 if [ -n "$2" ]; then
1625 mkdir -p "$2" && cd "$2"
1626 fi
1628 newline
1629 action 'Generating empty tazlito.conf...'
1630 empty_config_file
1631 status
1633 separator
1634 if [ -f 'tazlito.conf' ] ; then
1635 _ 'Configuration file is ready to edit.'
1636 _ 'File location: %s' "$(pwd)/tazlito.conf"
1637 newline
1638 fi
1639 ;;
1642 configure)
1643 # Configure a tazlito.conf config file. Start by getting
1644 # a empty config file and sed it.
1646 if [ -f 'tazlito.conf' ]; then
1647 rm tazlito.conf
1648 else
1649 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1650 'or in the same directory of the file you want to configure.'
1651 cd /etc
1652 fi
1654 empty_config_file
1656 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1658 # ISO name.
1659 echo -n "ISO name : " ; read answer
1660 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1661 # Volume name.
1662 echo -n "Volume name : " ; read answer
1663 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1664 # Packages repository.
1665 echo -n "Packages repository : " ; read answer
1666 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1667 # Distro path.
1668 echo -n "Distro path : " ; read answer
1669 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1670 footer "Config file is ready to use."
1671 echo 'You can now extract an ISO or generate a distro.'
1672 newline
1673 ;;
1676 gen-iso)
1677 # Simply generate a new iso.
1679 check_root
1680 verify_rootcd
1681 gen_livecd_isolinux
1682 distro_stats
1683 ;;
1686 gen-initiso)
1687 # Simply generate a new initramfs with a new iso.
1689 check_root
1690 verify_rootcd
1691 gen_initramfs "$ROOTFS"
1692 gen_livecd_isolinux
1693 distro_stats
1694 ;;
1697 extract-distro)
1698 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1700 check_root
1701 ISO_IMAGE="$2"
1702 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1703 'Example:\n tazlito image.iso /path/target'
1705 # Set the distro path by checking for $3 on cmdline.
1706 TARGET="${3:-$DISTRO}"
1708 # Exit if existing distro is found.
1709 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1710 'Please clean the distro tree or change directory path.'
1712 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
1714 # Start to mount the ISO.
1715 action 'Mounting ISO image...'
1716 mkdir -p "$TMP_DIR"
1717 # Get ISO file size.
1718 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
1719 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
1720 sleep 2
1721 # Prepare target dir, copy the kernel and the rootfs.
1722 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
1723 status
1725 action 'Copying the Linux kernel...'
1726 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
1727 make_bzImage_hardlink "$TARGET/rootcd/boot"
1728 else
1729 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
1730 fi
1731 status
1733 for i in $(ls $TMP_DIR); do
1734 [ "$i" == 'boot' ] && continue
1735 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
1736 done
1738 for loader in isolinux syslinux extlinux grub; do
1739 [ -d "$TMP_DIR/boot/$loader" ] || continue
1740 action 'Copying %s files...' "$loader"
1741 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
1742 status
1743 done
1745 action 'Copying the rootfs...'
1746 cp $TMP_DIR/boot/rootfs.?z "$TARGET/rootcd/boot"
1747 status
1749 # Extract initramfs.
1750 cd "$TARGET/rootfs"
1751 action 'Extracting the rootfs...'
1752 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
1753 # unpack /usr
1754 for i in etc/tazlito/*.extract; do
1755 [ -f "$i" ] && . $i ../rootcd
1756 done
1757 # Umount and remove temp directory and cd to $TARGET to get stats.
1758 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
1759 cd ..
1760 status
1762 newline
1763 separator
1764 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
1765 echo "Distro tree : $(pwd)"
1766 echo "Rootfs size : $(du -sh rootfs)"
1767 echo "Rootcd size : $(du -sh rootcd)"
1768 footer
1769 ;;
1772 list-flavors)
1773 # Show available flavors.
1774 local list='/etc/tazlito/flavors.list'
1775 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
1776 title 'List of flavors'
1777 cat $list
1778 footer
1779 ;;
1782 show-flavor)
1783 # Show flavor description.
1784 set -e
1785 flavor=${2%.flavor}
1786 flv_dir="$(extract_flavor "$flavor")"
1787 desc="$flv_dir/$flavor.desc"
1788 if [ -n "$brief" ]; then
1789 if [ -z "$noheader" ]; then
1790 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
1791 separator
1792 fi
1793 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
1794 "$(field ISO "$desc")" \
1795 "$(field Rootfs "$desc")" \
1796 "$(field Description "$desc")"
1797 else
1798 separator
1799 cat "$desc"
1800 fi
1801 cleanup
1802 ;;
1805 gen-liveflavor)
1806 # Generate a new flavor from the live system.
1807 FLAVOR=${2%.flavor}
1808 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1810 case "$FLAVOR" in
1811 -?|-h*|--help)
1812 cat <<EOT
1813 SliTaz Live Tool - Version: $VERSION
1815 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
1817 $(boldify '<flavor-patch-file> format:')
1818 $(optlist "\
1819 code data
1820 + package to add
1821 - package to remove
1822 ! non-free package to add
1823 ? display message
1824 @ flavor description
1825 ")
1827 $(boldify 'Example:')
1828 $(optlist "\
1829 @ Developer tools for SliTaz maintainers
1830 + slitaz-toolchain
1831 + mercurial
1832 ")
1833 EOT
1834 exit 1
1835 ;;
1836 esac
1837 mv /etc/tazlito/distro-packages.list \
1838 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
1839 rm -f distro-packages.list non-free.list 2>/dev/null
1840 tazpkg recharge
1842 DESC=""
1843 [ -n "$3" ] && \
1844 while read action pkg; do
1845 case "$action" in
1846 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
1847 -) yes | tazpkg remove $pkg ;;
1848 !) echo $pkg >> non-free.list ;;
1849 @) DESC="$pkg" ;;
1850 \?) echo -en "$pkg"; read action ;;
1851 esac
1852 done < $3
1854 yes '' | tazlito gen-distro
1855 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
1856 mv /etc/tazlito/distro-packages.list.$$ \
1857 /etc/tazlito/distro-packages.list 2>/dev/null
1858 ;;
1861 gen-flavor)
1862 # Generate a new flavor from the last ISO image generated
1863 FLAVOR=${2%.flavor}
1864 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1866 title 'Flavor generation'
1867 check_rootfs
1868 FILES="$FLAVOR.pkglist"
1870 action 'Creating file %s...' "$FLAVOR.flavor"
1871 for i in rootcd rootfs; do
1872 if [ -d "$ADDFILES/$i" ] ; then
1873 FILES="$FILES\n$FLAVOR.$i"
1874 (cd "$ADDFILES/$i"; find . | cpio -o -H newc 2>/dev/null | gzip -9) > $FLAVOR.$i
1875 fi
1876 done
1877 status
1879 answer=$(grep -s ^Description $FLAVOR.desc)
1880 answer=${answer#Description : }
1881 if [ -z "$answer" ]; then
1882 echo -n "Description: "
1883 read answer
1884 fi
1886 action 'Compressing flavor %s...' "$FLAVOR"
1887 echo "Flavor : $FLAVOR" > $FLAVOR.desc
1888 echo "Description : $answer" >> $FLAVOR.desc
1889 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
1890 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
1891 for i in $(ls $ROOTFS$INSTALLED); do
1892 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
1893 EXTRAVERSION=""
1894 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
1895 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
1896 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
1897 echo "$i" >> $FLAVOR.nonfree
1898 else
1899 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
1900 fi
1901 done
1902 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
1903 for i in $LOCALSTATE/undigest/*/mirror ; do
1904 [ -s $i ] && cat $i >> $FLAVOR.mirrors
1905 done
1906 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
1907 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | gzip -9 > $FLAVOR.flavor
1908 rm $(echo -e $FILES)
1909 status
1911 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
1912 ;;
1915 upgrade-flavor)
1916 # Strip versions from pkglist and update estimated numbers in flavor.desc
1917 flavor="${2%.flavor}"
1918 set -e
1919 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1920 set +e
1922 flv_dir="$(extract_flavor "$flavor")"
1924 strip_versions "$flv_dir/$flavor.pkglist"
1926 action 'Updating %s...' "$flavor.desc"
1928 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
1929 set -- $(calc_sizes "$flv_dir" "$flavor")
1930 restore_mirrors >/dev/null
1932 sed -i -e '/Image is ready/d' \
1933 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
1934 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
1935 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
1936 -e "s|\(Packages *:\).*$|\1 $4|" \
1937 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
1938 "$flv_dir/$flavor.desc"
1940 pack_flavor "$flv_dir" "$flavor"
1941 status
1942 display_unknown "$flv_dir/err"
1943 display_warn "$flv_dir/warn"
1944 cleanup
1945 ;;
1948 extract-flavor)
1949 # Extract a flavor into $FLAVORS_REPOSITORY
1950 flavor="${2%.flavor}"
1951 set -e
1952 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1953 set +e
1955 action 'Extracting %s...' "$flavor.flavor"
1956 flv_dir="$(extract_flavor "$flavor" full)"
1957 storage="$FLAVORS_REPOSITORY/$flavor"
1959 rm -rf "$storage" 2>/dev/null
1960 mkdir -p "$storage"
1961 cp -a "$flv_dir"/* "$storage"
1962 rm "$storage/description"
1963 status
1965 strip_versions "$storage/packages.list"
1967 cleanup
1968 ;;
1971 pack-flavor)
1972 # Create a flavor from $FLAVORS_REPOSITORY.
1973 flavor=${2%.flavor}
1974 storage="$FLAVORS_REPOSITORY/$flavor"
1976 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
1978 action 'Creating flavor %s...' "$flavor"
1979 tmp_dir="$(mktemp -d)"
1981 while read from to; do
1982 [ -s "$storage/$from" ] || continue
1983 cp -a "$storage/$from" "$tmp_dir/$to"
1984 done <<EOT
1985 mirrors $flavor.mirrors
1986 distro.sh $flavor-distro.sh
1987 receipt $flavor.receipt
1988 non-free.list $flavor.nonfree
1989 EOT
1991 # Build the package list.
1992 # It can include a list from another flavor with the keyword @include
1993 if [ -s "$storage/packages.list" ]; then
1994 include=$(grep '^@include' "$storage/packages.list")
1995 if [ -n "$include" ]; then
1996 include=${include#@include }
1997 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
1998 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
1999 else
2000 echo -e "\nERROR: Can't find include package list from $include\n"
2001 fi
2002 fi
2003 # Generate the final/initial package list
2004 [ -s "$storage/packages.list" ] && \
2005 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2006 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2007 fi
2009 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2010 # Process multi-rootfs flavor
2011 . "$storage/receipt"
2012 set -- $ROOTFS_SELECTION
2013 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2014 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2015 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2017 for i in rootcd rootfs; do
2018 mkdir "$tmp_dir/$i"
2019 # Copy extra files from the first flavor
2020 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2021 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2022 # Overload extra files by meta flavor
2023 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2024 [ -n "$(ls $tmp_dir/$i)" ] &&
2025 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2026 gzip -9 > "$tmp_dir/$flavor.$i"
2027 rm -rf "$tmp_dir/$i"
2028 done
2029 else
2030 # Process plain flavor
2031 for i in rootcd rootfs; do
2032 [ -d "$storage/$i" ] || continue
2033 (cd "$storage/$i";
2034 find . | cpio -o -H newc 2>/dev/null) | gzip -9 > "$tmp_dir/$flavor.$i"
2035 done
2036 fi
2038 unset VERSION MAINTAINER ROOTFS_SELECTION
2039 set -- $(calc_sizes "$tmp_dir" "$flavor")
2040 ROOTFS_SIZE="$1 (estimated)"
2041 INITRAMFS_SIZE="$2 (estimated)"
2042 ISO_SIZE="$3 (estimated)"
2043 PKGNUM="$4"
2044 . "$storage/receipt"
2046 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2047 Flavor : $FLAVOR
2048 Description : $SHORT_DESC
2049 Version : $VERSION
2050 Maintainer : $MAINTAINER
2051 LiveCD RAM size : $FRUGAL_RAM
2052 Rootfs list : $ROOTFS_SELECTION
2053 Build date : $(date '+%Y%m%d at %T')
2054 Packages : $PKGNUM
2055 Rootfs size : $ROOTFS_SIZE
2056 Initramfs size : $INITRAMFS_SIZE
2057 ISO image size : $ISO_SIZE
2058 ================================================================================
2060 EOT
2062 rm -f $tmp_dir/packages.list
2063 pack_flavor "$tmp_dir" "$flavor"
2064 status
2065 display_unknown "$tmp_dir/err"
2066 display_warn "$flv_dir/warn"
2067 cleanup
2068 ;;
2071 get-flavor)
2072 # Get a flavor's files and prepare for gen-distro.
2073 flavor=${2%.flavor}
2074 title 'Preparing %s distro flavor' "$flavor"
2075 set -e
2076 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2077 set +e
2079 action 'Cleaning %s...' "$DISTRO"
2080 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2081 # Clean old files
2082 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2083 [ -f "$i" ] && rm "$i"
2084 done
2085 mkdir -p "$DISTRO"
2086 status
2088 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2090 action 'Extracting flavor %s...' "$flavor.flavor"
2091 flv_dir="$(extract_flavor "$flavor" info)"
2092 cp -a "$flv_dir"/* .
2093 mv packages.list distro-packages.list
2094 mv -f info /etc/tazlito
2095 status
2097 for i in rootcd rootfs; do
2098 if [ -d "$i" ]; then
2099 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2100 fi
2101 done
2103 rm -f /etc/tazlito/rootfs.list
2104 grep -q '^Rootfs list' description &&
2105 grep '^Rootfs list' description | sed 's/.*: \(.*\)$/\1/' > /etc/tazlito/rootfs.list
2107 action 'Updating tazlito.conf...'
2108 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2109 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2110 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2111 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2112 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2113 status
2115 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2116 cleanup
2117 ;;
2120 iso2flavor)
2121 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2122 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2124 FLAVOR=${3%.flavor}
2125 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2126 mount -o loop,ro $2 $TMP_DIR/iso
2127 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2128 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2129 ! -s $TMP_DIR/flavor/*.desc ]; then
2130 echo "META flavors are not supported."
2131 umount -d $TMP_DIR/iso
2132 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2133 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2134 echo "No /boot/rootfs.gz in ISO image. Needs a SliTaz ISO."
2135 umount -d $TMP_DIR/iso
2136 else
2137 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*gz); do
2138 ( zcat < $i || unlzma < $i ) | \
2139 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2140 done
2141 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2142 echo "No file /etc/slitaz-release in /boot/rootfs.gz of iso image. Needs a non loram SliTaz iso."
2143 umount -d $TMP_DIR/iso
2144 else
2145 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2146 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2147 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2148 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2149 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2150 umount -d $TMP_DIR/iso
2151 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2152 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2153 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2154 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2155 < $TMP_DIR/rootfs$INSTALLED.md5
2156 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2157 if [ -s $TMP_DIR/flavor/*desc ]; then
2158 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2159 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2160 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2161 for i in rootfs rootcd ; do
2162 [ -s $TMP_DIR/flavor/*.list$i ] &&
2163 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2164 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | gzip -9 > $TMP_DIR/$FLAVOR.$i
2165 done
2166 else
2167 find_flavor_rootfs $TMP_DIR/rootfs
2168 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2169 for i in rootfs rootcd ; do
2170 [ "$(ls $TMP_DIR/$i)" ] &&
2171 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | gzip -9 > "$TMP_DIR/$FLAVOR.$i"
2172 done
2173 unset VERSION MAINTAINER
2174 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2175 if [ -n "$DESCRIPTION" ]; then
2176 echo -en "Flavor version : "; read -t 30 VERSION
2177 echo -en "Flavor maintainer (your email) : "; read -t 30 MAINTAINER
2178 fi
2180 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2181 Flavor : $FLAVOR
2182 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2183 Version : ${VERSION:-1.0}
2184 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2185 LiveCD RAM size : $RAM_SIZE
2186 Build date : $BUILD_DATE
2187 Packages : $PKGCNT
2188 Rootfs size : $ROOTFS_SIZE
2189 Initramfs size : $INITRAMFS_SIZE
2190 ISO image size : $ISO_SIZE
2191 ================================================================================
2193 EOT
2194 longline "Tazlito can't detect each file installed during \
2195 a package post_install. You should extract this flavor (tazlito extract-flavor \
2196 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2197 tree and remove files generated by post_installs.
2198 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2199 repack the flavor (tazlito pack-flavor $FLAVOR)"
2200 fi
2201 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | gzip -9 > $FLAVOR.flavor
2202 fi
2203 fi
2204 rm -rf $TMP_DIR
2205 ;;
2208 gen-distro)
2209 # Generate a live distro tree with a set of packages.
2211 check_root
2212 start_time=$(date +%s)
2214 # Tazlito options: --iso or --cdrom
2215 CDROM=''
2216 [ -n "$iso" ] && CDROM="-o loop $iso"
2217 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2219 # Check if a package list was specified on cmdline.
2220 if [ -f "$2" ]; then
2221 LIST_NAME="$2"
2222 else
2223 LIST_NAME='distro-packages.list'
2224 fi
2226 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2227 'Please clean the distro tree or change directory path.'
2228 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2229 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2231 # If list not given: build list with all installed packages
2232 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2233 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2234 fi
2236 # Exit if no list name.
2237 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2239 # Start generation.
2240 title 'Tazlito generating a distro'
2242 # Misc checks
2243 mkdir -p "$PACKAGES_REPOSITORY"
2244 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2246 # Mount CD-ROM to be able to repack boot-loader packages
2247 if [ ! -e /boot -a -n "$CDROM" ]; then
2248 mkdir $TMP_MNT
2249 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2250 ln -s "$TMP_MNT/boot" /
2251 if [ ! -d "$ADDFILES/rootcd" ] ; then
2252 mkdir -p "$ADDFILES/rootcd"
2253 for i in $(ls $TMP_MNT); do
2254 [ "$i" == 'boot' ] && continue
2255 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2256 done
2257 fi
2258 else
2259 rmdir "$TMP_MNT"
2260 fi
2261 fi
2263 # Rootfs stuff.
2264 echo 'Preparing the rootfs directory...'
2265 mkdir -p "$ROOTFS"
2266 mkdir -p "$TMP_DIR"
2268 strip_versions "$LIST_NAME"
2270 if [ "$REPACK" == 'y' ]; then
2271 # Determine full packages list with all dependencies
2272 tmp_dir="$(mktemp -d)"
2273 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2274 touch "$tmp_dir/full.pkglist"
2275 calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2277 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2278 while read pkgname pkgver; do
2279 # Is package in full list?
2280 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2281 # Is package already repacked?
2282 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2283 _ 'Repacking %s...' "$pkgname-$pkgver"
2284 tazpkg repack "$pkgname" --quiet
2285 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2286 status
2287 done
2289 rm -r "$tmp_dir"
2290 fi
2292 # initial tazpkg setup in empty rootfs
2293 export root="$ROOTFS"
2294 tazpkg >/dev/null 2>&1
2295 # link rootfs packages cache to the regular packages cache
2296 rm -r "$ROOTFS/var/cache/tazpkg"
2297 ln -s /var/cache/tazpkg "$ROOTFS/var/cache/tazpkg"
2299 setup_mirrors mirrors
2301 # Just in case if flavor not contains "tazlito" package
2302 mkdir -p "$ROOTFS/etc/tazlito"
2304 if [ -f non-free.list ]; then
2305 # FIXME: working in the ROOTFS chroot?
2306 newline
2307 echo 'Preparing non-free packages...'
2308 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2309 for pkg in $(cat 'non-free.list'); do
2310 if [ ! -d "$INSTALLED/$pkg" ]; then
2311 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2312 tazpkg get-install get-$pkg
2313 fi
2314 get-$pkg "$ROOTFS"
2315 fi
2316 tazpkg repack $pkg
2317 pkg=$(ls $pkg*.tazpkg)
2318 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2319 mv $pkg $PACKAGES_REPOSITORY
2320 done
2321 fi
2322 cp $LIST_NAME $DISTRO/distro-packages.list
2323 newline
2325 for pkg in $(cat $DISTRO/distro-packages.list); do
2326 action 'Installing package: %s' "$pkg"
2327 yes y | tazpkg -gi $pkg --root=$ROOTFS --quiet >> $log || exit 1
2328 status
2329 done
2330 newline
2332 restore_mirrors
2334 # Un-link packages cache
2335 rm $ROOTFS/var/cache/tazpkg
2336 # Clean /var/lib/tazpkg
2337 rm $ROOTFS/var/lib/tazpkg/ID* \
2338 $ROOTFS/var/lib/tazpkg/descriptions.txt \
2339 $ROOTFS/var/lib/tazpkg/extra.list \
2340 $ROOTFS/var/lib/tazpkg/files* \
2341 $ROOTFS/var/lib/tazpkg/packages* \
2342 $ROOTFS/var/lib/tazpkg/priority \
2343 -rf $ROOTFS/var/lib/tazpkg/undigest \
2344 2>/dev/null
2345 # Back to default mirror
2346 echo "$DEFAULT_MIRROR" > $ROOTFS/var/lib/tazpkg/mirror
2348 cd $DISTRO
2349 cp distro-packages.list $ROOTFS/etc/tazlito
2350 # Copy all files from $ADDFILES/rootfs to the rootfs.
2351 if [ -d "$ADDFILES/rootfs" ] ; then
2352 action 'Copying addfiles content to the rootfs...'
2353 cp -a $ADDFILES/rootfs/* $ROOTFS
2354 status
2355 fi
2357 action 'Root filesystem is generated...'; status
2359 # Root CD part.
2360 action 'Preparing the rootcd directory...'
2361 mkdir -p $ROOTCD
2362 status
2364 # Move the boot dir with the Linux kernel from rootfs.
2365 # The boot dir goes directly on the CD.
2366 if [ -d "$ROOTFS/boot" ] ; then
2367 action 'Moving the boot directory...'
2368 mv $ROOTFS/boot $ROOTCD
2369 cd $ROOTCD/boot
2370 make_bzImage_hardlink
2371 status
2372 fi
2373 cd $DISTRO
2374 # Copy all files from $ADDFILES/rootcd to the rootcd.
2375 if [ -d "$ADDFILES/rootcd" ] ; then
2376 action 'Copying addfiles content to the rootcd...'
2377 cp -a $ADDFILES/rootcd/* $ROOTCD
2378 status
2379 fi
2380 # Execute the distro script used to perform tasks in the rootfs
2381 # before compression. Give rootfs path in arg
2382 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2383 if [ -x "$DISTRO_SCRIPT" ]; then
2384 echo 'Executing distro script...'
2385 sh $DISTRO_SCRIPT $DISTRO
2386 fi
2388 # Execute the custom_rules() found in receipt.
2389 if [ -s "$TOP_DIR/receipt" ]; then
2390 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2391 echo -e "Executing: custom_rules()\n"
2392 . "$TOP_DIR/receipt"
2393 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2394 fi
2395 fi
2397 # Multi-rootfs
2398 if [ -s /etc/tazlito/rootfs.list ]; then
2400 FLAVOR_LIST="$(awk '{
2401 for (i = 2; i <= NF; i+=2)
2402 printf "%s ", i;
2403 }' /etc/tazlito/rootfs.list)"
2405 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2406 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2407 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2409 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2410 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2411 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2412 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2414 n=0
2415 last=$ROOTFS
2416 while read flavor; do
2417 n=$(($n+1))
2418 newline
2419 boldify "Building $flavor rootfs..."
2421 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2422 cp "$TOP_DIR/$flavor.flavor" .
2424 if [ ! -s "$flavor.flavor" ]; then
2425 # We may have it in $FLAVORS_REPOSITORY
2426 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2427 tazlito pack-flavor $flavor
2428 else
2429 download $flavor.flavor
2430 fi
2431 fi
2433 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2434 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2435 sed 's/.*/&.tazpkg/' < $flavor.pkglist > $DISTRO/list-packages0$n
2436 status
2438 strip_versions "$DISTRO/list-packages0$n"
2440 mkdir ${ROOTFS}0$n
2441 # Install packages
2442 cd $PACKAGES_REPOSITORY
2444 # initial tazpkg setup in empty rootfs
2445 export root="${ROOTFS}0$n"
2446 tazpkg >/dev/null 2>&1
2447 # link rootfs packages cache to the regular packages cache
2448 rm -r "${ROOTFS}0$n/var/cache/tazpkg"
2449 ln -s /var/cache/tazpkg "${ROOTFS}0$n/var/cache/tazpkg"
2451 setup_mirrors mirrors
2453 # Just in case if flavor not contains "tazlito" package
2454 mkdir -p "${ROOTFS}0$n/etc/tazlito"
2457 for pkg in $(cat $DISTRO/list-packages0$n); do
2458 action 'Installing package: %s' "$pkg"
2459 yes y | tazpkg -gi $pkg --root=${ROOTFS}0$n --quiet >> $log || exit 1
2460 status
2461 done
2463 restore_mirrors
2465 rm -rf ${ROOTFS}0$n/boot
2467 # Un-link packages cache
2468 rm ${ROOTFS}0$n/var/cache/tazpkg
2470 # Clean /var/lib/tazpkg
2471 rm ${ROOTFS}0$n/var/lib/tazpkg/ID* \
2472 ${ROOTFS}0$n/var/lib/tazpkg/descriptions.txt \
2473 ${ROOTFS}0$n/var/lib/tazpkg/extra.list \
2474 ${ROOTFS}0$n/var/lib/tazpkg/files* \
2475 ${ROOTFS}0$n/var/lib/tazpkg/packages.* \
2476 ${ROOTFS}0$n/var/lib/tazpkg/priority \
2477 -rf ${ROOTFS}0$n/var/lib/tazpkg/undigest \
2478 2>/dev/null
2480 # Back to default mirror
2481 echo "$DEFAULT_MIRROR" > ${ROOTFS}0$n/var/lib/tazpkg/mirror
2484 cd $DISTRO
2485 if [ -s $flavor.rootfs ]; then
2486 echo -n "Adding $flavor rootfs extra files..."
2487 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2488 fi
2490 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2491 mv $DISTRO/list-packages0$n ${ROOTFS}0$n/etc/tazlito/distro-packages.list
2492 status
2494 rm -f $flavor.flavor install-list
2495 mergefs ${ROOTFS}0$n $last
2496 last=${ROOTFS}0$n
2497 done <<EOT
2498 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2499 EOT
2500 #'
2501 i=$(($n+1))
2502 while [ $n -gt 0 ]; do
2503 mv ${ROOTFS}0$n ${ROOTFS}$i
2504 echo "Compressing ${ROOTFS}0$n ($(du -hs ${ROOTFS}$i | awk '{ print $1 }'))..."
2505 gen_initramfs ${ROOTFS}$i
2506 n=$(($n-1))
2507 i=$(($i-1))
2508 done
2509 mv $ROOTFS ${ROOTFS}$i
2510 gen_initramfs ${ROOTFS}$i
2511 update_bootconfig $ROOTCD/boot/isolinux \
2512 "$(cat /etc/tazlito/rootfs.list)"
2513 else
2514 # Initramfs and ISO image stuff.
2515 gen_initramfs $ROOTFS
2516 fi
2517 gen_livecd_isolinux
2518 distro_stats
2519 cleanup
2520 ;;
2523 clean-distro)
2524 # Remove old distro tree.
2526 check_root
2527 title 'Cleaning: %s' "$DISTRO"
2528 if [ -d "$DISTRO" ] ; then
2529 if [ -d "$ROOTFS" ] ; then
2530 action 'Removing the rootfs...'
2531 rm -f $DISTRO/$INITRAMFS
2532 rm -rf $ROOTFS
2533 status
2534 fi
2535 if [ -d "$ROOTCD" ] ; then
2536 action 'Removing the rootcd...'
2537 rm -rf $ROOTCD
2538 status
2539 fi
2540 action 'Removing eventual ISO image...'
2541 rm -f $DISTRO/$ISO_NAME.iso
2542 rm -f $DISTRO/$ISO_NAME.md5
2543 status
2544 fi
2545 footer
2546 ;;
2549 check-distro)
2550 # Check for a few LiveCD needed files not installed by packages.
2552 # TODO: Remove this function.
2553 # First two files are maintained by tazpkg while it runs on rootfs,
2554 # while last one file should be maintained by tazlito itself.
2555 check_rootfs
2556 title 'Checking distro: %s' "$ROOTFS"
2557 # SliTaz release info.
2558 if [ ! -f "$ROOTFS/etc/slitaz-release" ]; then
2559 echo "Missing release info : /etc/slitaz-release"
2560 else
2561 release=$(cat $ROOTFS/etc/slitaz-release)
2562 echo -n "Release : $release"
2563 status
2564 fi
2565 # Tazpkg mirror.
2566 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2567 echo -n "Mirror URL : Missing $LOCALSTATE/mirror"
2568 todomsg
2569 else
2570 action 'Mirror configuration exists...'
2571 status
2572 fi
2573 # Isolinux msg
2574 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2575 echo -n "Isolinux msg : Missing cooking date XXXXXXXX (ex $(date +%Y%m%d))"
2576 todomsg
2577 else
2578 action 'Isolinux message seems good...'
2579 status
2580 fi
2581 footer
2582 ;;
2585 writeiso)
2586 # Writefs to ISO image including /home unlike gen-distro we don't use
2587 # packages to generate a rootfs, we build a compressed rootfs with all
2588 # the current filesystem similar to 'tazusb writefs'.
2590 DISTRO='/home/slitaz/distro'
2591 ROOTCD="$DISTRO/rootcd"
2592 COMPRESSION="${2:-none}"
2593 ISO_NAME="${3:-slitaz}"
2594 check_root
2595 # Start info
2596 title 'Write filesystem to ISO'
2597 longline "The command writeiso will write the current filesystem into a \
2598 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2599 newline
2600 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2602 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2603 # Save some space
2604 rm -rf /var/cache/tazpkg/*
2605 rm -f /var/lib/tazpkg/*.bak
2606 rm -rf $DISTRO
2608 # Optionally remove sound card selection and screen resolution.
2609 if [ -z $LaunchedByTazpanel ]; then
2610 echo "Do you wish to remove the sound card and screen configs ? "
2611 echo -n "Press ENTER to keep or answer (No|yes|exit): "
2612 read anser
2613 case $anser in
2614 e|E|"exit"|Exit)
2615 exit 0 ;;
2616 y|Y|yes|Yes)
2617 echo -n "Removing current sound card and screen configurations..."
2618 rm -f /var/lib/sound-card-driver
2619 rm -f /var/lib/alsa/asound.state
2620 rm -f /etc/X11/xorg.conf ;;
2621 *)
2622 echo -n "Keeping current sound card and screen configurations..." ;;
2623 esac
2624 status
2625 newline
2627 # Optionally remove i18n settings
2628 echo "Do you wish to remove local/keymap settings ? "
2629 echo -n "Press ENTER to keep or answer (No|yes|exit): "
2630 read anser
2631 case $anser in
2632 e|E|"exit"|Exit)
2633 exit 0 ;;
2634 y|Y|yes|Yes)
2635 echo "Removing current locale/keymap settings..."
2636 newline > /etc/locale.conf
2637 newline > /etc/keymap.conf ;;
2638 *)
2639 echo "Keeping current locale/keymap settings..." ;;
2640 esac
2641 status
2642 fi
2644 # Clean-up files by default
2645 newline > /etc/udev/rules.d/70-persistent-net.rules
2646 newline > /etc/udev/rules.d/70-persistant-cd.rules
2648 # Create list of files including default user files since it is defined in /etc/passwd
2649 # and some new users might have been added.
2650 cd /
2651 echo 'init' > /tmp/list
2652 for dir in bin etc sbin var dev lib root usr home opt; do
2653 [ -d $dir ] && find $dir
2654 done >> /tmp/list
2656 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2657 [ -d $dir ] && echo $dir
2658 done >> /tmp/list
2660 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2662 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2663 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2664 #fi
2665 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2666 touch /var/log/wtmp
2668 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2669 sed -i "/var\/log\/$removelog/d" /tmp/list
2670 done
2672 # Generate initramfs with specified compression and display rootfs
2673 # size in realtime.
2674 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2676 write_initramfs &
2677 sleep 2
2678 cd - > /dev/null
2679 echo -en "\nFilesystem size:"
2680 while [ ! -f /tmp/rootfs ]; do
2681 sleep 1
2682 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2683 done
2684 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2685 echo -e "\n"
2686 rm -f /tmp/rootfs
2688 # Move freshly generated rootfs to the cdrom.
2689 mkdir -p $ROOTCD/boot
2690 mv -f /$INITRAMFS $ROOTCD/boot
2691 echo "Located in: $ROOTCD/boot/$INITRAMFS"
2693 # Now we need the kernel and isolinux files.
2694 copy_from_cd() {
2695 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2696 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2697 unmeta_boot $ROOTCD
2698 umount /media/cdrom
2701 bootloader='/var/lib/tazpkg/installed/syslinux/volatile.cpio.gz'
2702 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2703 copy_from_cd;
2704 elif mount | grep /media/cdrom; then
2705 copy_from_cd;
2706 elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2707 cp $bootloader $ROOTCD
2708 cd $ROOTCD
2709 zcat volatile.cpio.gz | cpio -id
2710 rm -f volatile.cpio.gz
2711 [ -f /boot/*slitaz ] && \
2712 cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2713 [ -f /boot/*slitaz64 ] && \
2714 cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2715 else
2716 touch /tmp/.write-iso-error
2717 longline "When SliTaz is running in RAM the kernel and bootloader \
2718 files are kept on the CD-ROM. Please insert a Live CD or loop mount the \
2719 slitaz.iso to /media/cdrom (run # mount -o loop slitaz-rolling.iso /media/cdrom ) \
2720 or # (tazpkg -gi linux --forced) to let Tazlito copy the files."
2721 echo -en "----\nENTER to continue..."; read i
2722 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2723 copy_from_cd
2724 fi
2726 # Generate the iso image.
2727 touch /tmp/.write-iso
2728 newline
2729 cd $DISTRO
2730 echo "Generating ISO image..."
2731 genisoimage -R -o $ISO_NAME.iso -b boot/isolinux/isolinux.bin \
2732 -c boot/isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
2733 -V "SliTaz" -p "$(id -un)" -input-charset utf-8 \
2734 -P "$(hostname)" -boot-info-table $ROOTCD
2735 if [ -x /usr/bin/isohybrid ]; then
2736 action 'Creating hybrid ISO/disk...'
2737 /usr/bin/isohybrid $ISO_NAME.iso -entry 2 2>/dev/null
2738 status
2739 fi
2740 if [ -x /usr/bin/iso2exe ]; then
2741 action 'Creating hybrid ISO/EXE...'
2742 /usr/bin/iso2exe $ISO_NAME.iso 2>/dev/null
2743 status
2744 fi
2745 action 'Creating the ISO md5sum...'
2746 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2747 status
2749 separator
2750 echo "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2751 rm -f /tmp/.write-iso
2752 newline
2753 if [ -z $LaunchedByTazpanel ]; then
2754 echo -n "Exit or burn ISO to CD-ROM (Exit|burn)? "; read anser
2755 case $anser in
2756 burn)
2757 umount /dev/cdrom 2>/dev/null
2758 eject
2759 echo -n "Please insert a blank CD-ROM and press ENTER..."
2760 read i && sleep 2
2761 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2762 echo -en "----\nENTER to continue..."; read i ;;
2763 *)
2764 exit 0 ;;
2765 esac
2766 fi
2767 ;;
2770 burn-iso)
2771 # Guess CD-ROM device, ask user and burn the ISO.
2773 check_root
2774 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2775 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2776 # We can specify an alternative ISO from the cmdline.
2777 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2778 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2780 title 'Tazlito burn ISO'
2781 echo "CD-ROM device : /dev/$DRIVE_NAME"
2782 echo "Drive speed : $DRIVE_SPEED"
2783 echo "ISO image : $iso"
2784 footer
2786 case $(yesorno 'Burn ISO image?' 'n') in
2787 y)
2788 title 'Starting Wodim to burn the ISO...'
2789 sleep 2
2790 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2791 footer 'ISO image is burned to CD-ROM.'
2792 ;;
2793 *)
2794 die 'Exiting. No ISO burned.'
2795 ;;
2796 esac
2797 ;;
2800 merge)
2801 # Merge multiple rootfs into one iso.
2803 if [ -z "$2" ]; then
2804 cat <<EOT
2805 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2807 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2808 i.e: rootfsN is a subset of rootfsN-1
2809 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2810 The boot loader will select the rootfs according to the RAM size detected.
2812 Example:
2813 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
2815 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
2816 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
2818 EOT
2819 exit 2
2820 fi
2822 shift # skip merge
2823 append="$1 slitaz1"
2824 shift # skip size1
2825 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
2827 ISO=$1.merged
2829 # Extract filesystems
2830 action 'Mounting %s' "$1"
2831 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
2832 status || cleanup_merge
2834 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2835 make_bzImage_hardlink $TMP_DIR/iso/boot
2836 umount -d $TMP_DIR/mnt
2837 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
2838 echo "$1 is already a merged iso. Aborting."
2839 cleanup_merge
2840 fi
2841 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
2842 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
2843 if [ ! -f /boot/isolinux/ifmem.c32 -a
2844 ! -f /boot/isolinux/c32box.c32 ]; then
2845 cat <<EOT
2846 No file /boot/isolinux/ifmem.c32
2847 Please install syslinux package !
2848 EOT
2849 rm -rf $TMP_DIR
2850 exit 1
2851 fi
2852 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
2853 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
2854 fi
2856 action 'Extracting iso/rootfs.gz'
2857 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
2858 [ -d $TMP_DIR/rootfs1/etc ]
2859 status || cleanup_merge
2861 n=1
2862 while [ -n "$2" ]; do
2863 shift # skip rootfs N-1
2864 p=$n
2865 n=$(($n + 1))
2866 append="$append $1 slitaz$n"
2867 shift # skip size N
2868 mkdir -p $TMP_DIR/rootfs$n
2870 action 'Extracting %s' "$1"
2871 extract_rootfs $1 $TMP_DIR/rootfs$n &&
2872 [ -d "$TMP_DIR/rootfs$n/etc" ]
2873 status || cleanup_merge
2875 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
2876 action 'Creating rootfs%s.gz' "$p"
2877 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
2878 status
2879 done
2880 action 'Creating rootfs%s.gz' "$n"
2881 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
2882 status
2883 rm -f $TMP_DIR/iso/boot/rootfs.gz
2884 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
2885 create_iso $ISO $TMP_DIR/iso
2886 rm -rf $TMP_DIR
2887 ;;
2890 repack)
2891 # Repack an iso with maximum lzma compression ratio.
2893 ISO=$2
2894 mkdir -p $TMP_DIR/mnt
2896 # Extract filesystems
2897 action 'Mounting %s' "$ISO"
2898 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
2899 status || cleanup_merge
2901 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2902 umount -d $TMP_DIR/mnt
2904 for i in $TMP_DIR/iso/boot/rootfs* ; do
2905 action 'Repacking %s' "$(basename $i)"
2906 (zcat $i 2>/dev/null || unlzma < $i || cat $i) 2>/dev/null > $TMP_DIR/rootfs
2907 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
2908 align_to_32bits $i
2909 status
2910 done
2912 create_iso $ISO $TMP_DIR/iso
2913 rm -rf $TMP_DIR
2914 ;;
2917 build-loram)
2918 # Build a Live CD for low RAM systems.
2920 ISO="$2"
2921 OUTPUT="$3"
2922 [ -z "$3" ] && \
2923 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
2924 mkdir -p "$TMP_DIR/iso"
2925 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
2926 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$ISO$/!d;s/:.*//;q")
2927 if ! check_iso_for_loram ; then
2928 umount -d "$TMP_DIR/iso"
2929 die "$ISO is not a valid SliTaz live CD. Abort."
2930 fi
2931 case "$4" in
2932 cdrom) build_loram_cdrom ;;
2933 http) build_loram_http ;;
2934 *) build_loram_ram ;;
2935 esac
2936 umount $TMP_DIR/iso # no -d: needs /proc
2937 losetup -d $loopdev
2938 rm -rf $TMP_DIR
2939 ;;
2942 emu-iso)
2943 # Emulate an ISO image with Qemu.
2944 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2945 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
2946 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
2947 echo -e "\nStarting Qemu emulator:\n"
2948 echo -e "qemu $QEMU_OPTS $iso\n"
2949 qemu $QEMU_OPTS $iso
2950 ;;
2953 deduplicate)
2954 # Deduplicate files in a tree
2955 shift
2956 deduplicate "$@"
2957 ;;
2960 usage|*)
2961 # Print usage also for all unknown commands.
2962 usage
2963 ;;
2964 esac
2966 exit 0