tazlito view tazlito @ rev 415

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