tazlito view tazlito @ rev 425

tazlito: extra 'cdrom text' entry in loram boot menu
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Jun 19 14:17:14 2016 +0200 (2016-06-19)
parents bda5499d616a
children 1564b943c310
line source
1 #!/bin/sh
2 # TazLito - SliTaz Live Tool.
3 #
4 # Tazlito is a tool to help generate and configure SliTaz Live CD
5 # ISO images. You can create a custom distro in one command from a list of
6 # packages, extract an existing ISO image to hack it, create a new initramfs
7 # and/or a new ISO. Most commands must be run by root, except the stats
8 # and the configuration file manipulation.
9 #
10 # (C) 2007-2016 SliTaz - GNU General Public License.
11 #
12 # Authors: see the AUTHORS file
13 #
15 VERSION='6.0'
17 . /lib/libtaz.sh
18 # Force to use Busybox cpio and wget
19 alias cpio='busybox cpio'
20 alias wget='busybox wget'
22 # Tazlito configuration variables to be shorter
23 # and to use words rather than numbers.
24 COMMAND="$1"
25 LIST_NAME="$2"
26 TMP_DIR="/tmp/tazlito-$$-$RANDOM"
27 TMP_MNT="/media/tazlito-$$-$RANDOM"
28 TOP_DIR="$(pwd)"
29 INITRAMFS='rootfs.gz'
30 LOCALSTATE='/var/lib/tazpkg'
31 INSTALLED="$LOCALSTATE/installed"
32 CACHE_DIR='/var/cache/tazpkg'
33 MIRROR="$LOCALSTATE/mirror"
34 DEFAULT_MIRROR="http://mirror1.slitaz.org/packages/$(cat /etc/slitaz-release)/"
36 log='/var/log/tazlito.log'
37 if [ $(id -u) -eq 0 ]; then
38 newline > $log
39 fi
42 cleanup() {
43 if [ -d "$TMP_MNT" ]; then
44 umount $TMP_MNT
45 rmdir $TMP_MNT
46 rm -f /boot
47 fi
48 [ -d "$tmp_dir" ] && rm -r "$tmp_dir"
49 [ -d "$flv_dir" ] && rm -r "$flv_dir"
50 }
53 # Report error and finish work
55 die() {
56 emsg "<n>$(longline "$@")<n> " >&2
57 cleanup
58 exit 1
59 }
62 # Run Tazlito module
63 module() {
64 local mod="$1"; shift
65 /usr/libexec/tazlito/$mod $@
66 }
70 # Try to include config file, continue if command is gen-config or exit.
71 # The main config used by default is in /etc/tazlito.
72 # Specific distro config file can be put in a distro tree.
73 for i in /etc/tazlito "$TOP_DIR"; do
74 [ -f "$i/tazlito.conf" ] && CONFIG_FILE="$i/tazlito.conf"
75 done
77 [ -z "$CONFIG_FILE" -a "$COMMAND" != 'gen-config' ] && \
78 die 'Unable to find any configuration file.' \
79 'Please read the docs or run `tazlito gen-config` to get an empty config file.'
81 . $CONFIG_FILE
83 # While Tazpkg is not used the default mirror URL file does not exist
84 # and user can't recharge the list of flavors.
85 [ $(id -u) -eq 0 -a ! -f "$MIRROR" ] && echo "$DEFAULT_MIRROR" > $MIRROR
87 # Set the rootfs and rootcd path with $DISTRO
88 # configuration variable.
89 ROOTFS="$DISTRO/rootfs"
90 ROOTCD="$DISTRO/rootcd"
95 #####################
96 # Tazlito functions #
97 #####################
100 # Print the usage.
102 usage () {
103 [ $(basename $0) == 'tazlito' ] && cat <<EOT
105 SliTaz Live Tool - Version: $(colorize 34 "$VERSION")
107 $(boldify "Usage:") tazlito [command] [list|iso|flavor|compression] [dir|iso]
109 $(boldify "Commands:")
110 EOT
111 optlist "\
112 usage Print this short usage.
113 stats View Tazlito and distro configuration statistics.
114 list-addfiles Simple list of additional files in the rootfs.
115 gen-config Generate a new configuration file for a distro.
116 configure Configure the main config file or a specific tazlito.conf.
117 gen-iso Generate a new ISO from a distro tree.
118 gen-initiso Generate a new initramfs and ISO from the distro tree.
119 list-flavors List all flavors available on the mirror.
120 gen-flavor Generate a new Live CD description.
121 gen-liveflavor Generate a Live CD description from current system.
122 show-flavor Show Live CD description.
123 get-flavor Get a flavor's list of packages (--noup to skip update).
124 upgrade-flavor Update package list to the latest available versions.
125 extract-flavor Extract a *.flavor file into $FLAVORS_REPOSITORY.
126 pack-flavor Pack (and update) a flavor from $FLAVORS_REPOSITORY.
127 iso2flavor Create a flavor file from a SliTaz ISO image.
128 extract-distro Extract an ISO to a directory and rebuild Live CD tree.
129 gen-distro Generate a Live distro and ISO from a list of packages.
130 clean-distro Remove all files generated by gen-distro.
131 check-distro Help to check if distro is ready to release.
132 writeiso Use running system to generate a bootable ISO (with /home).
133 merge Merge multiple rootfs into one ISO.
134 deduplicate Deduplicate files in a tree.
135 repack Recompress rootfs into ISO with maximum ratio.
136 build-loram Generate a Live CD for low-RAM systems.
137 emu-iso Emulate an ISO image with QEMU.
138 burn-iso Burn ISO image to a CD-ROM using Wodim.
139 "
140 }
143 yesorno() {
144 local answer
145 echo -n "$1 (y=yes, n=no) [$2] " >&2
146 case "$DEFAULT_ANSWER" in
147 Y|y) answer="y";;
148 N|n) answer="n";;
149 *)
150 read -t 30 answer
151 [ -z "$answer" ] && answer="$2"
152 [ "$answer" != 'y' -a "$answer" != 'n' ] && answer="$2"
153 ;;
154 esac
155 echo "$answer"
156 }
159 field() {
160 grep "^$1" "$2" | \
161 case "$1" in
162 Desc*) sed 's|^.*: *||';;
163 *) sed 's/.*: \([0-9KMG\.]*\).*/\1/';;
164 esac
165 }
168 todomsg() {
169 echo -e "\\033[70G[ \\033[1;31mTODO\\033[0;39m ]"
170 }
173 # Download a file from this mirror
175 download_from() {
176 local i mirrors="$1"
177 shift
178 for i in $mirrors; do
179 case "$i" in
180 http://*|ftp://*|https://*)
181 wget -c $i$@ && break;;
182 *)
183 cp $i/$1 . && break;;
184 esac
185 done
186 }
189 # Download a file trying all mirrors
191 download() {
192 local i
193 for i in $(cat $MIRROR $LOCALSTATE/undigest/*/mirror 2>/dev/null); do
194 download_from "$i" "$@" && break
195 done
196 }
199 # Execute hooks provided by some packages
201 genisohooks() {
202 local here="$(pwd)"
203 for i in $(ls $ROOTFS/etc/tazlito/*.$1 2>/dev/null); do
204 cd $ROOTFS
205 . $i $ROOTCD
206 done
207 cd "$here"
208 }
211 # Echo the package name if the tazpkg is already installed
213 installed_package_name() {
214 local tazpkg="$1" package VERSION EXTRAVERSION
216 # Try to find package name and version to be able
217 # to repack it from installation
218 # A dash (-) can exist in name *and* in version
219 package=${tazpkg%-*}
220 i=$package
221 while true; do
222 unset VERSION EXTRAVERSION
223 eval $(grep -s ^VERSION= $INSTALLED/$i/receipt)
224 eval $(grep -s ^EXTRAVERSION= $INSTALLED/$i/receipt)
225 if [ "$i-$VERSION$EXTRAVERSION" == "$tazpkg" ]; then
226 echo $i
227 break
228 fi
229 case "$i" in
230 *-*);;
231 *) break;;
232 esac
233 i=${i%-*}
234 done
235 }
238 # Check for the rootfs tree.
240 check_rootfs() {
241 [ -d "$ROOTFS/etc" ] || die 'Unable to find a distro rootfs...'
242 }
245 # Check for the boot dir into the root CD tree.
247 verify_rootcd() {
248 [ -d "$ROOTCD/boot" ] || die 'Unable to find the rootcd boot directory...'
249 }
252 # isolinux.conf doesn't know the kernel version.
253 # We name the kernel image 'bzImage'.
254 # isolinux/syslinux first tries the '64' suffix with a 64bits cpu.
256 make_bzImage_hardlink() {
257 if [ -s ${1:-.}/vmlinuz*slitaz ]; then
258 rm -f ${1:-.}/bzImage 2>/dev/null
259 ln ${1:-.}/vmlinuz*slitaz ${1:-.}/bzImage
260 fi
261 if [ -s ${1:-.}/vmlinuz*slitaz64 ]; then
262 rm -f ${1:-.}/bzImage64 2> /dev/null
263 ln ${1:-.}/vmlinuz*slitaz64 ${1:-.}/bzImage64
264 fi
265 }
268 create_iso() {
269 cd $2
270 deduplicate
272 action 'Computing md5...'
273 find * -type f ! -name md5sum ! -name 'vmlinuz*' -exec md5sum {} \; > md5sum
274 sed -i -e '/ boot\/isolinux\/isolinux.bin$/d' \
275 -e '/ boot\/isolinux\/boot.cat$/d' md5sum
276 status
278 cd - >/dev/null
279 title 'Generating ISO image'
281 _ 'Generating %s' "$1"
282 make_bzImage_hardlink $2/boot
283 genisoimage -R -o $1 -b boot/isolinux/isolinux.bin \
284 -c boot/isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
285 -V "$VOLUM_NAME" -p "$PREPARED" -input-charset utf-8 \
286 -copyright README -P "www.slitaz.org" -boot-info-table $2
288 if [ -x '/usr/bin/isohybrid' ]; then
289 action 'Creating hybrid ISO...'
290 /usr/bin/isohybrid $1 -entry 2 2>/dev/null
291 status
292 fi
294 if [ -s '/etc/tazlito/info' ]; then
295 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
296 action 'Storing ISO info...'
297 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
298 status
299 fi
300 fi
302 if [ -x '/usr/bin/iso2exe' ]; then
303 echo 'Creating EXE header...'
304 /usr/bin/iso2exe $1 2>/dev/null
305 fi
306 }
309 # Generate a new ISO image using isolinux.
311 gen_livecd_isolinux() {
312 # Some packages may want to alter iso
313 genisohooks iso
314 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
316 # Set date for boot msg.
317 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
318 DATE=$(date +%Y%m%d)
319 action 'Setting build date to: %s...' "$DATE"
320 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
321 status
322 fi
324 cd $DISTRO
325 create_iso $ISO_NAME.iso $ROOTCD
327 action 'Creating the ISO md5sum...'
328 md5sum $ISO_NAME.iso > $ISO_NAME.md5
329 status
331 separator
332 # Some packages may want to alter final iso
333 genisohooks final
334 }
337 lzma_history_bits() {
338 #
339 # This generates an ISO which boots with Qemu but gives
340 # rootfs errors in frugal or liveUSB mode.
341 #
342 # local n
343 # local sz
344 # n=20 # 1Mb
345 # sz=$(du -sk $1 | cut -f1)
346 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
347 # n=$(( $n + 1 ))
348 # sz=$(( $sz / 2 ))
349 # done
350 # echo $n
351 echo 24
352 }
355 lzma_switches() {
356 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
357 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1}"
358 }
361 lzma_set_size() {
362 # Update size field for lzma'd file packed using -si switch
363 return # Need to fix kernel code?
365 local n i
366 n=$(unlzma < $1 | wc -c)
367 for i in $(seq 1 8); do
368 printf '\\\\x%02X' $(($n & 255))
369 n=$(($n >> 8))
370 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
371 }
374 align_to_32bits() {
375 local size=$(stat -c %s ${1:-/dev/null})
376 [ $((${size:-0} & 3)) -ne 0 ] &&
377 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
378 }
381 # Pack rootfs
383 pack_rootfs() {
384 ( cd $1; find . -print | cpio -o -H newc ) | \
385 case "$COMPRESSION" in
386 none)
387 _ 'Creating %s without compression...' 'initramfs'
388 cat > $2
389 ;;
390 gzip)
391 _ 'Creating %s with gzip compression...' 'initramfs'
392 gzip -9 > $2
393 ;;
394 *)
395 _ 'Creating %s with lzma compression...' 'initramfs'
396 lzma e -si -so $(lzma_switches $1) > $2
397 lzma_set_size $2
398 ;;
399 esac
400 align_to_32bits $2
401 echo 1 > /tmp/rootfs
402 }
405 # Compression functions for writeiso.
407 write_initramfs() {
408 case "$COMPRESSION" in
409 lzma)
410 _n 'Creating %s with lzma compression...' "$INITRAMFS"
411 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
412 align='y'
413 lzma_set_size "/$INITRAMFS"
414 ;;
415 gzip)
416 _ 'Creating %s with gzip compression...' "$INITRAMFS"
417 cpio -o -H newc | gzip -9 > "/$INITRAMFS"
418 [ -x /usr/bin/advdef ] && advdef -z4 "/$INITRAMFS"
419 ;;
420 *)
421 # align='y'
422 _ 'Creating %s without compression...' "$INITRAMFS"
423 cpio -o -H newc > "/$INITRAMFS"
424 ;;
425 esac < /tmp/list
426 [ "$align" == 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
427 echo 1 > /tmp/rootfs
428 }
431 # Deduplicate files (MUST be on the same filesystem).
433 deduplicate() {
434 find "${@:-.}" -type f -size +0c -xdev -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
435 (
436 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""
437 while read attr inode link file; do
438 [ -L "$file" ] && continue
439 if [ "$attr" == "$old_attr" -a "$inode" != "$old_inode" ]; then
440 if cmp "$file" "$old_file" >/dev/null 2>&1 ; then
441 rm -f "$file"
442 if ln "$old_file" "$file" 2>/dev/null; then
443 inode="$old_inode"
444 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
445 save="$(($save+(${attr%%-*}+512)/1024))"
446 else
447 cp -a "$old_file" "$file"
448 fi
449 fi
450 fi
451 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
452 done
453 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
454 )
456 find "$@" -type l -xdev -exec stat -c '%s-%u-%g-TARGET- %i %h %n' {} \; | sort | \
457 (
458 old_attr=""; hardlinks=0;
459 while read attr inode link file; do
460 attr="${attr/-TARGET-/-$(readlink $file)}"
461 if [ "$attr" == "$old_attr" ]; then
462 if [ "$inode" != "$old_inode" ]; then
463 rm -f "$file"
464 if ln "$old_file" "$file" 2>/dev/null; then
465 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
466 else
467 cp -a "$old_file" "$file"
468 fi
469 fi
470 else
471 old_file="$file"
472 old_attr="$attr"
473 old_inode="$inode"
474 fi
475 done
476 _ '%s duplicate symlinks.' "$hardlinks"
477 )
478 }
481 # Generate a new initramfs from the root filesystem.
483 gen_initramfs() {
484 # Just in case CTRL+c
485 rm -f $DISTRO/gen
487 # Some packages may want to alter rootfs
488 genisohooks rootfs
489 cd $1
491 # Link duplicate files
492 deduplicate
494 # Use lzma if installed. Display rootfs size in realtime.
495 rm -f /tmp/rootfs 2>/dev/null
496 pack_rootfs . $DISTRO/$(basename $1).gz &
497 sleep 2
498 echo -en "\nFilesystem size:"
499 while [ ! -f /tmp/rootfs ]; do
500 sleep 1
501 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
502 done
503 echo -e "\n"
504 rm -f /tmp/rootfs
505 cd $DISTRO
506 mv $(basename $1).gz $ROOTCD/boot
507 }
510 distro_sizes() {
511 if [ -n "$start_time" ]; then
512 time=$(($(date +%s) - $start_time))
513 sec=$time
514 div=$(( ($time + 30) / 60))
515 [ "$div" -ne 0 ] && min="~ ${div}m"
516 _ 'Build time : %ss %s' "$sec" "$min"
517 fi
518 cat <<EOT
519 Build date : $(date +%Y%m%d)
520 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
521 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
522 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
523 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
524 EOT
525 footer "Image is ready: $ISO_NAME.iso"
526 }
529 # Print ISO and rootfs size.
531 distro_stats() {
532 title 'Distro statistics: %s' "$DISTRO"
533 distro_sizes
534 }
537 # Create an empty configuration file.
539 empty_config_file() {
540 cat >> tazlito.conf <<"EOF"
541 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
542 #
544 # Name of the ISO image to generate.
545 ISO_NAME=""
547 # ISO image volume name.
548 VOLUM_NAME="SliTaz"
550 # Name of the preparer.
551 PREPARED="$USER"
553 # Path to the packages repository and the packages.list.
554 PACKAGES_REPOSITORY=""
556 # Path to the distro tree to gen-distro from a list of packages.
557 DISTRO=""
559 # Path to the directory containing additional files
560 # to copy into the rootfs and rootcd of the LiveCD.
561 ADDFILES="$DISTRO/addfiles"
563 # Default answer for binary question (Y or N)
564 DEFAULT_ANSWER="ASK"
566 # Compression utility (lzma, gzip or none)
567 COMPRESSION="lzma"
568 EOF
569 }
572 # Extract rootfs.gz somewhere
574 extract_rootfs() {
575 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
576 # First part (lzcat or zcat) may not fail, but cpio will fail on uncorrect format
577 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
578 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
579 (cd "$2"; cat "$1" | cpio -idm --quiet 2>/dev/null)
580 }
583 # Extract flavor file to temp directory
585 extract_flavor() {
586 # Input: $1 - flavor name to extract;
587 # $2 = absent/empty: just extract 'outer layer'
588 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
589 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
590 # Output: temp dir path where flavor was extracted
591 local f="$1.flavor" from to infos="$1.desc"
592 [ -f "$f" ] || die "File '$f' not found"
593 local dir="$(mktemp -d)"
594 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
596 if [ -n "$2" ]; then
597 cd $dir
599 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
601 for i in rootcd rootfs; do
602 [ -f "$1.$i" ] || continue
603 mkdir "$i"
604 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
605 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
606 rm "$1.$i"
607 done
608 # Info to be stored inside ISO
609 [ "$2" == info ] && echo -e $infos | cpio -o -H newc | gzip -9 > info
610 rm $1.list*
612 # Renames
613 while read from to; do
614 [ -f "$from" ] || continue
615 mv "$from" "$to"
616 done <<EOT
617 $1.nonfree non-free.list
618 $1.pkglist packages.list
619 $1-distro.sh distro.sh
620 $1.receipt receipt
621 $1.mirrors mirrors
622 $1.desc description
623 EOT
624 fi
626 echo $dir
627 }
630 # Pack flavor file from temp directory
632 pack_flavor() {
633 (cd "$1"; ls | grep -v err | cpio -o -H newc) | gzip -9 > "$2.flavor"
634 }
637 # Remove duplicate files
639 mergefs() {
640 # Note, many packages have files with spaces in the name
641 IFS=$'\n'
643 local size1=$(du -hs "$1" | awk '{ print $1 }')
644 local size2=$(du -hs "$2" | awk '{ print $1 }')
645 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
647 # merge symlinks files and devices
648 ( cd "$1"; find ) | \
649 while read file; do
650 if [ -L "$1/$file" ]; then
651 [ -L "$2/$file" -a "$(readlink "$1/$file")" == "$(readlink "$2/$file")" ] &&
652 rm -f "$2/$file"
654 elif [ -f "$1/$file" ]; then
655 [ -f "$2/$file" ] && cmp -s "$1/$file" "$2/$file" &&
656 rm -f "$2/$file"
658 [ -f "$2/$file" ] &&
659 [ "$(basename "$file")" == 'volatile.cpio.gz' ] &&
660 [ "$(dirname $(dirname "$file"))" == ".$INSTALLED" ] &&
661 rm -f "$2/$file"
663 elif [ -b "$1/$file" ]; then
664 [ -b "$2/$file" ] &&
665 [ "$(stat -c '%a:%u:%g:%t:%T' "$1/$file")" == \
666 "$(stat -c '%a:%u:%g:%t:%T' "$2/$file")" ] &&
667 rm -f "$2/$file"
669 elif [ -c "$1/$file" ]; then
670 [ -c "$2/$file" ] &&
671 [ "$(stat -c '%a:%u:%g:%t:%T' "$1/$file")" == \
672 "$(stat -c '%a:%u:%g:%t:%T' "$2/$file")" ] &&
673 rm -f "$2/$file"
674 fi
675 done
677 # cleanup directories; TODO: simplify
678 ( cd "$1"; find . -type d ) | sed '1!G;h;$!d' | \
679 while read file; do
680 [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
681 done
683 unset IFS
684 status
685 }
688 cleanup_merge() {
689 rm -rf $TMP_DIR
690 exit 1
691 }
694 # Update isolinux config files for multiple rootfs
696 update_bootconfig() {
697 local files
698 action 'Updating boot config files...'
699 files="$(grep -l 'include common' $1/*.cfg)"
700 for file in $files; do
701 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
702 if (/label/) label=$0;
703 else if (/kernel/) kernel=$0;
704 else if (/append/) {
705 i=index($0,"rootfs.gz");
706 append=substr($0,i+9);
707 }
708 else if (/include/) {
709 for (i = 1; i <= n; i++) {
710 print label i
711 print kernel;
712 initrd="initrd=/boot/rootfs" n ".gz"
713 for (j = n - 1; j >= i; j--) {
714 initrd=initrd ",/boot/rootfs" j ".gz";
715 }
716 printf "\tappend %s%s\n",initrd,append;
717 print "";
718 }
719 print;
720 }
721 else print;
722 }' < $file > $file.$$
723 mv -f $file.$$ $file
724 done
725 sel="$(echo $2 | awk '{
726 for (i=1; i<=NF; i++)
727 if (i % 2 == 0) printf " slitaz%d", i/2
728 else printf " %s", $i
729 }')"
731 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
733 label slitaz
734 kernel /boot/isolinux/ifmem.c32
735 append$sel noram
737 label noram
738 config noram.cfg
740 EOT
742 # Update vesamenu
743 if [ -s "$1/isolinux.cfg" ]; then
744 files="$files $1/isolinux.cfg"
745 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
746 BEGIN {
747 kernel = " COM32 c32box.c32"
748 }
749 {
750 if (/ROWS/) print "MENU ROWS " n+$3;
751 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
752 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
753 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
754 else if (/VSHIFT/) {
755 x = $3-n;
756 if (x < 0) x = 0;
757 print "MENU VSHIFT " x;
758 }
759 else if (/rootfs.gz/) {
760 linux = "";
761 if (/bzImage/) linux = "linux /boot/bzImage ";
762 i = index($0, "rootfs.gz");
763 append = substr($0, i+9);
764 printf "\tkernel /boot/isolinux/ifmem.c32\n";
765 printf "\tappend%s noram\n", sel;
766 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
767 for (i = 1; i <= n; i++) {
768 print "LABEL slitaz" i
769 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
770 printf "%s\n", kernel;
771 initrd = "initrd=/boot/rootfs" n ".gz"
772 for (j = n - 1; j >= i; j--) {
773 initrd = initrd ",/boot/rootfs" j ".gz";
774 }
775 printf "\tappend %s%s%s\n\n", linux, initrd, append;
776 }
777 }
778 else if (/bzImage/) kernel = $0;
779 else print;
780 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
781 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
782 fi
784 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
785 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
786 cat > $1/noram.cfg <<EOT
787 implicit 0
788 prompt 1
789 timeout 80
790 $(grep '^F[0-9]' $1/isolinux.cfg)
792 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
793 say Not enough RAM to boot slitaz. Trying hacker mode...
794 default hacker
795 label hacker
796 KERNEL /boot/bzImage
797 append rw root=/dev/null vga=normal
799 label reboot
800 EOT
802 if [ -s $1/c32box.c32 ]; then
803 cat >> $1/noram.cfg <<EOT
804 COM32 c32box.c32
805 append reboot
807 label poweroff
808 COM32 c32box.c32
809 append poweroff
811 EOT
812 else
813 echo " com32 reboot.c32" >> $1/noram.cfg
814 fi
816 # Restore real label names
817 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
818 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
819 while read pat; do
820 sed -i "s/slitaz$pat/" $files
821 done
822 status
823 }
826 # Install a missing package
828 install_package() {
829 if [ -z "$2" ]; then
830 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
831 else
832 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
833 fi
834 case "$answer" in
835 y)
836 # We don't want package on host cache.
837 action 'Getting and installing package: %s' "$1"
838 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
839 status ;;
840 *)
841 return 1 ;;
842 esac
843 }
846 # Check iso for loram transformation
848 check_iso_for_loram() {
849 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
850 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
851 }
854 # Build initial rootfs for loram ISO ram/cdrom/http
856 build_initfs() {
857 urliso="mirror.slitaz.org mirror.switch.ch/ftp/mirror/slitaz \
858 download.tuxfamily.org/slitaz slitaz.c3sl.ufpr.br"
859 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
860 [ -z "$version" ] && die "Can't find the kernel version." \
861 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
863 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
864 need_lib=false
865 for i in bin dev run mnt proc tmp sys lib/modules; do
866 mkdir -p $TMP_DIR/initfs/$i
867 done
868 ln -s bin $TMP_DIR/initfs/sbin
869 ln -s . $TMP_DIR/initfs/usr
870 for aufs in aufs overlayfs; do
871 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
872 install_package $aufs $version && break
873 done || return 1
874 cp /init $TMP_DIR/initfs/
875 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
876 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
877 $TMP_DIR/initfs/lib/modules 2>/dev/null
878 cp -a /dev/tty0 /dev/fd0 $TMP_DIR/initfs/dev 2>/dev/null
879 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
880 $TMP_DIR/initfs/lib/modules
881 if [ "$1" == 'cdrom' ]; then
882 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
883 else
884 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
885 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
886 install_package linux-squashfs $version || return 1
887 done
888 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
889 $TMP_DIR/initfs/lib/modules
890 ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
891 cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
892 fi
893 for i in $(ls /dev/[hs]d[a-f]*); do
894 cp -a $i $TMP_DIR/initfs/dev
895 done
896 if [ "$1" == 'http' ]; then
897 mkdir $TMP_DIR/initfs/etc
898 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
899 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
900 sed -i 's|/sbin/||' $TMP_DIR/initfs/lib/udhcpc
901 cp -a /dev/fuse $TMP_DIR/initfs/dev
902 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
903 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/httpfs
904 else
905 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
906 need_lib=true
907 fi
908 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
909 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
910 else
911 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
912 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
913 cp -a /lib/librt* $TMP_DIR/initfs/lib
914 cp -a /lib/libdl* $TMP_DIR/initfs/lib
915 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
916 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
917 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
918 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
919 need_lib=true
920 fi
921 cd $TMP_DIR/initfs
922 echo 'Getting slitaz-release...'
923 for i in $TMP_DIR/iso/boot/rootfs*.gz; do
924 (zcat $i 2>/dev/null || unlzma < $i) | cpio -idmu etc/slitaz-release >/dev/null
925 done
926 cd - > /dev/null
927 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"
928 _n 'List of URLs to insert: '
929 read -t 30 urliso2
930 urliso="$urliso2 $urliso"
931 fi
932 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
933 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
934 sed -i 's/LD_T.*ot/newline/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
935 else
936 cp /bin/busybox $TMP_DIR/initfs/bin
937 need_lib=true
938 fi
939 for i in $($TMP_DIR/initfs/bin/busybox | awk \
940 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
941 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
942 done
943 for i in /dev/console /dev/loop* /dev/null /dev/tty /dev/zero \
944 /dev/kmem /dev/mem /dev/random /dev/urandom; do
945 cp -a $i $TMP_DIR/initfs/dev
946 done
947 $need_lib && for i in /lib/ld-* /lib/lib[cm].so* /lib/lib[cm]-* ; do
948 cp -a $i $TMP_DIR/initfs/lib
949 done
950 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
951 #!/bin/sh
953 getarg() {
954 grep -q " \$1=" /proc/cmdline || return 1
955 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
956 return 0
957 }
959 copy_rootfs() {
960 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
961 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
962 [ \$(( \$total / \$need )) -gt 1 ] || return 1
963 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
964 path=/mnt/
965 return 0
966 else
967 rm -f /mnt/rootfs*
968 return 1
969 fi
970 }
972 echo "Switching / to tmpfs..."
973 mount -t proc proc /proc
974 size="\$(grep rootfssize= < /proc/cmdline | \\
975 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
976 [ -n "\$size" ] || size="-o size=90%"
978 while read var default; do
979 eval \$var=\$default
980 getarg \$var \$var
981 done <<EOT
982 eth eth0
983 dns 208.67.222.222,208.67.220.220
984 netmask 255.255.255.0
985 gw
986 ip
987 EOT
988 if [ -n "\$ip" ]; then
989 ifconfig \$eth \$ip netmask \$netmask up
990 route add default gateway \$gw
991 for i in \$(echo \$dns | sed 's/,/ /g'); do
992 echo "nameserver \$i" >> /etc/resolv.conf
993 done
994 else
995 udhcpc -f -q -s /lib/udhcpc -i \$eth
996 fi
997 for i in $urliso ; do
998 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
999 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"
1000 done
1001 getarg urliso URLISO
1002 DIR=fs
1003 if getarg loram DIR; then
1004 DEVICE=\${DIR%,*}
1005 DIR=/\${DIR#*,}
1006 fi
1007 mount -t tmpfs \$size tmpfs /mnt
1008 path2=/mnt/.httpfs/
1009 path=/mnt/.cdrom/
1010 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1011 while [ ! -d \$path/boot ]; do
1012 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1013 httpfs \$i \$path2 && break
1014 done
1015 mount -o loop,ro -t iso9660 \$path2/*.iso \$path
1016 done
1018 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1019 umount /proc
1020 branch=:/mnt/.cdrom/\$DIR
1021 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1022 branch=
1023 for i in \${path}rootfs* ; do
1024 fs=\${i#*root}
1025 branch=\$branch:/mnt/.\$fs
1026 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1027 insmod /lib/squashfs.ko.gz 2> /dev/null
1028 mount -o loop,ro -t squashfs \${path}root\$fs /mnt/.\$fs
1029 done
1030 else
1031 mkdir -p /mnt/.rw/mnt/.httpfs
1032 fi
1033 while read type opt; do
1034 insmod /lib/\$type.ko.gz && mount -t \$type -o \$opt none /mnt && break
1035 done <<EOT
1036 aufs br=/mnt/.rw\$branch
1037 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1038 EOT
1039 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1040 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1041 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1042 EOTEOT
1043 chmod +x $TMP_DIR/initfs/init
1044 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1045 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1046 rm -f $i
1047 gzip -9 ${i%.gz}
1048 done 2>/dev/null
1049 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1050 lzma e $TMP_DIR/initfs.gz -si
1051 lzma_set_size $TMP_DIR/initfs.gz
1052 rm -rf $TMP_DIR/initfs
1053 align_to_32bits $TMP_DIR/initfs.gz
1054 return 0
1058 # Move each initramfs to squashfs
1060 build_loram_rootfs() {
1061 rootfs_sizes=""
1062 for i in $TMP_DIR/iso/boot/rootfs*.gz; do
1063 mkdir -p $TMP_DIR/fs
1064 cd $TMP_DIR/fs
1065 (zcat $i 2>/dev/null || unlzma < $i) | cpio -idm
1066 cd - > /dev/null
1067 rootfs=$TMP_DIR/$(basename $i)
1068 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp xz -Xbcj x86
1069 cd $TMP_DIR
1070 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1071 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1072 rm -f $rootfs
1073 mv $rootfs.cpio $rootfs
1074 cd - > /dev/null
1075 rm -rf $TMP_DIR/fs
1076 done
1080 # Move meta boot configuration files to basic configuration files
1081 # because meta loram flavor is useless when rootfs is not loaded in RAM
1083 unmeta_boot() {
1084 local root=${1:-$TMP_DIR/loramiso}
1085 if [ -f $root/boot/isolinux/noram.cfg ]; then
1086 # We keep enough information to do unloram...
1087 [ -s $root/boot/isolinux/common.cfg ] &&
1088 sed -i 's/label slitaz/label orgslitaz/' \
1089 $root/boot/isolinux/common.cfg
1090 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1091 shift
1092 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1093 $root/boot/isolinux/isolinux.cfg
1094 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1095 sed -i "s/label $3\$/label slitaz/;s|=/boot/rootfs\(.*\).gz |=/boot/rootfs.gz |" \
1096 $root/boot/isolinux/*.cfg
1097 fi
1101 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1102 # These squashfs may be loaded in RAM at boot time.
1103 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1104 # Meta flavors are converted to normal flavors.
1106 build_loram_cdrom() {
1107 build_initfs cdrom || return 1
1108 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1109 mkdir $TMP_DIR/loramiso/fs
1110 cd $TMP_DIR/loramiso/fs
1111 for i in $( ls ../boot/root* | sort -r ) ; do
1112 (zcat $i 2>/dev/null || unlzma < $i) | cpio -idmu
1113 rm -f $i
1114 done
1115 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1116 cd - >/dev/null
1117 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1118 unmeta_boot
1119 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1120 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1121 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1122 create_iso $OUTPUT $TMP_DIR/loramiso
1126 # Create http bootstrap to load and remove loram_cdrom
1127 # Meta flavors are converted to normal flavors.
1129 build_loram_http() {
1130 build_initfs http || return 1
1131 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1132 rm -f $TMP_DIR/loramiso/boot/rootfs*
1133 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1134 unmeta_boot
1135 create_iso $OUTPUT $TMP_DIR/loramiso
1139 # Update meta flavor selection sizes.
1140 # Reduce sizes with rootfs gains.
1142 update_metaiso_sizes() {
1143 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1144 do
1145 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1146 local sizes="$rootfs_sizes"
1147 local new
1148 set -- $append
1149 shift
1150 [ "$1" == "ifmem" ] && shift
1151 new=""
1152 while [ -n "$2" ]; do
1153 local s
1154 case "$1" in
1155 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1156 *M) s=$(( ${1%M} * 1024 ));;
1157 *) s=${1%K};;
1158 esac
1159 sizes=${sizes#* }
1160 for i in $sizes ; do
1161 s=$(( $s - $i ))
1162 done
1163 new="$new $s $2"
1164 shift 2
1165 done
1166 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1167 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1168 sed -i 's|\(initrd=\)\(/boot/rootfs.\.gz\)|\1/boot/rootfs.gz,\2|' $cfg
1169 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1170 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1171 done
1175 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1176 # Meta flavor selection sizes are updated.
1178 build_loram_ram() {
1179 build_initfs ram || return 1
1180 build_loram_rootfs
1181 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1182 make_bzImage_hardlink $TMP_DIR/loramiso/boot
1183 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1184 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1185 update_metaiso_sizes
1186 create_iso $OUTPUT $TMP_DIR/loramiso
1190 # Remove files installed by packages
1192 find_flavor_rootfs() {
1193 for i in $1/etc/tazlito/*.extract; do
1194 [ -e $i ] || continue
1195 chroot $1 /bin/sh ${i#$1}
1196 done
1198 # Clean hardlinks and files patched by genisofs in /boot
1199 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1200 rm -f $1/boot/$i*
1201 done
1203 # Clean files generated in post_install
1204 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1205 $1/dev/core $1/dev/fd $1/dev/std*
1207 # Verify md5
1208 cat $1$INSTALLED/*/md5sum | \
1209 while read md5 file; do
1210 [ -e "$1$file" ] || continue
1211 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1212 rm -f "$1$file"
1213 done
1215 # Check configuration files
1216 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1217 [ -e $i ] || continue
1218 mkdir /tmp/volatile$$
1219 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1220 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1221 while read file ; do
1222 [ -e "$1/$file" ] || continue
1223 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1224 done
1225 rm -rf /tmp/volatile$$
1226 done
1228 # Remove other files blindly
1229 for i in $1$INSTALLED/*/files.list; do
1230 for file in $(cat "$i"); do
1231 [ "$1$file" -nt "$i" ] && continue
1232 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1233 [ -d "$1$file" ] || rm -f "$1$file"
1234 done
1235 done
1237 # Remove tazpkg files and tmp files
1238 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1239 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1240 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1241 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1242 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1244 # Cleanup directory tree
1245 cd $1
1246 find * -type d | sort -r | while read dir; do
1247 rmdir "$dir" 2>/dev/null
1248 done
1249 cd - > /dev/null
1253 # Get byte(s) from a binary file
1255 get() {
1256 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null
1260 # Get cpio flavor info from the ISO image
1262 flavordata() {
1263 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1264 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1268 # Restore undigest mirrors
1270 restore_mirrors() {
1271 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1272 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1274 action 'Restoring mirrors...'
1275 if [ -d "$undigest.bak" ]; then
1276 [ -d "$undigest" ] && rm -r "$undigest"
1277 mv "$undigest.bak" "$undigest"
1278 fi
1279 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1280 :; status
1284 # Setup undigest mirrors
1286 setup_mirrors() {
1287 # Setup mirrors in plain system or in chroot (with variable root=)
1288 local mirrorlist="$1" fresh repacked
1289 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1291 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1292 restore_mirrors
1294 _ 'Setting up mirrors for %s...' "$root/"
1295 # Backing up current undigest mirrors and priority
1296 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1297 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1298 rm -rf '/var/www/tazlito/'
1299 mkdir -p '/var/www/tazlito/'
1301 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1302 fresh='/home/slitaz/packages'
1303 if [ -d "$fresh" ]; then
1304 # Setup first undigest mirror
1305 mkdir -p "$undigest/fresh"
1306 echo "$fresh" > "$undigest/fresh/mirror"
1307 echo 'fresh' >> "$priority"
1308 # Rebuild mirror DB if needed
1309 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1310 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1311 tazpkg mkdb "$fresh" --forced --root=''
1312 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1313 fi
1315 # Repacked packages: high priority
1316 repacked="$PACKAGES_REPOSITORY"
1317 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1318 # According to Tazlito setup file (tazlito.conf):
1319 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1320 # or
1321 # WORK_DIR="/home/slitaz"
1322 # and
1323 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1324 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1326 # Setup second undigest mirror
1327 mkdir -p "$undigest/repacked"
1328 echo "$repacked" > "$undigest/repacked/mirror"
1329 echo 'repacked' >> "$priority"
1330 # Rebuild mirror DB if needed
1331 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1332 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1333 tazpkg mkdb "$repacked" --forced --root=''
1334 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1335 fi
1337 # All repositories listed in mirrors list: normal priority
1338 [ -e "$mirrorlist" ] && \
1339 while read mirror; do
1340 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1341 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1342 mkdir -p "$undigest/$mirrorid"
1343 echo "$mirror" > "$undigest/$mirrorid/mirror"
1344 echo "$mirrorid" >> "$priority"
1345 done < "$mirrorlist"
1347 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1349 # Show list of mirrors
1350 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1351 function show(num, name, url) {
1352 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1355 num++;
1356 "cat " db "/undigest/" $0 "/mirror" | getline url;
1357 show(num, $0, url);
1359 END {
1360 num++;
1361 "cat " db "/mirror" | getline url;
1362 show(num, "main", url);
1363 }' "$priority"
1365 tazpkg recharge --quiet >/dev/null
1369 # Get list of 'packages.info' lists using priority
1371 pi_lists() {
1372 local pi
1373 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1374 local priority="$root$LOCALSTATE/priority"
1375 local undigest="$root$LOCALSTATE/undigest"
1378 [ -s "$priority" ] && cat "$priority"
1379 echo 'main'
1380 [ -d "$undigest" ] && ls "$undigest"
1381 } | awk -vun="$undigest/" '
1383 if (arr[$0] != 1) {
1384 arr[$0] = 1;
1385 print un $0 "/packages.info";
1387 }' | sed 's|/undigest/main||' | \
1388 while read pi; do
1389 [ -e "$pi" ] && echo "$pi"
1390 done
1394 # Strip versions from packages list
1396 strip_versions() {
1397 action 'Strip versions from list %s...' "$(basename "$1")"
1398 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1399 [ -f "$in_list" ] || die "List '$in_list' not found."
1401 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1402 awk '
1404 if (FILENAME ~ "packages.info") {
1405 # Collect package names
1406 FS = "\t"; pkg[$1] = 1;
1407 } else {
1408 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1409 while (NF > 1 && ! pkg[$0])
1410 NF --;
1411 printf "%s\n", $0;
1413 }' $(pi_lists) "$in_list" > "$tmp_list"
1415 cat "$tmp_list" > "$in_list"
1416 rm "$tmp_list"
1417 status
1421 # Display list of unknown packages (informative)
1423 display_unknown() {
1424 [ -s "$1" ] || return
1425 echo "Unknown packages:" >&2
1426 cat "$1" >&2
1427 rm "$1"
1431 # Display warnings about critical packages absent (informative)
1433 display_warn() {
1434 [ -s "$1" ] || return
1435 echo "Absent critical packages:" >&2
1436 cat "$1" >&2
1437 rm "$1"
1438 echo "Probably ISO image will be unusable."
1442 # Install packages to rootfs
1444 install_list_to_rootfs() {
1445 local list="$1" rootfs="$2" pkg i ii
1446 local undigest="$rootfs/var/lib/tazpkg/undigest"
1448 # initial tazpkg setup in empty rootfs
1449 tazpkg --root=$rootfs >/dev/null 2>&1
1450 # link rootfs packages cache to the regular packages cache
1451 rm -r "$rootfs/var/cache/tazpkg"
1452 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1454 setup_mirrors mirrors
1456 # Just in case if flavor not contains "tazlito" package
1457 mkdir -p "$rootfs/etc/tazlito"
1459 newline
1460 for pkg in $(cat $list); do
1461 action 'Installing package: %s' "$pkg"
1462 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1463 status
1464 done
1465 newline
1467 restore_mirrors
1468 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1469 for i in fresh repacked; do
1470 ii="$undigest/$i"
1471 [ -d "$ii" ] && rm -rf "$ii"
1472 ii="$rootfs/var/lib/tazpkg/priority"
1473 if [ -f "$ii" ]; then
1474 sed -i "/$i/d" "$ii"
1475 [ -s "$ii" ] || rm "$ii"
1476 fi
1477 done
1478 [ -d "$undigest" ] && \
1479 for i in $(find "$undigest" -type f); do
1480 # Remove all undigest PKGDB files but 'mirror'
1481 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1482 done
1483 [ -d "$undigest" ] && \
1484 rmdir --ignore-fail-on-non-empty "$undigest"
1486 # Un-link packages cache
1487 rm "$rootfs/var/cache/tazpkg"
1489 # Clean /var/lib/tazpkg
1490 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1496 ####################
1497 # Tazlito commands #
1498 ####################
1500 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1501 case "$0" in
1502 *reduplicate)
1503 find ${@:-.} ! -type d -links +1 \
1504 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1505 exit 0 ;;
1506 *deduplicate)
1507 deduplicate "$@"
1508 exit 0 ;;
1509 esac
1512 case "$COMMAND" in
1513 stats)
1514 # Tazlito general statistics from the config file.
1516 title 'Tazlito statistics'
1517 optlist "\
1518 Config file : $CONFIG_FILE
1519 ISO name : $ISO_NAME.iso
1520 Volume name : $VOLUM_NAME
1521 Prepared : $PREPARED
1522 Packages repository : $PACKAGES_REPOSITORY
1523 Distro directory : $DISTRO
1524 Additional files : $ADDFILES
1525 " | sed '/: $/d'
1526 footer
1527 ;;
1530 list-addfiles)
1531 # Simple list of additional files in the rootfs
1532 newline
1533 if [ -d "$ADDFILES/rootfs" ]; then
1534 cd $ADDFILES
1535 find rootfs -type f
1536 else
1537 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1538 fi
1539 newline
1540 ;;
1543 gen-config)
1544 # Generate a new config file in the current dir or the specified
1545 # directory by $2.
1547 if [ -n "$2" ]; then
1548 mkdir -p "$2" && cd "$2"
1549 fi
1551 newline
1552 action 'Generating empty tazlito.conf...'
1553 empty_config_file
1554 status
1556 separator
1557 if [ -f 'tazlito.conf' ] ; then
1558 _ 'Configuration file is ready to edit.'
1559 _ 'File location: %s' "$(pwd)/tazlito.conf"
1560 newline
1561 fi
1562 ;;
1565 configure)
1566 # Configure a tazlito.conf config file. Start by getting
1567 # a empty config file and sed it.
1569 if [ -f 'tazlito.conf' ]; then
1570 rm tazlito.conf
1571 else
1572 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1573 'or in the same directory of the file you want to configure.'
1574 cd /etc
1575 fi
1577 empty_config_file
1579 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1581 # ISO name.
1582 echo -n "ISO name : " ; read answer
1583 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1584 # Volume name.
1585 echo -n "Volume name : " ; read answer
1586 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1587 # Packages repository.
1588 echo -n "Packages repository : " ; read answer
1589 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1590 # Distro path.
1591 echo -n "Distro path : " ; read answer
1592 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1593 footer "Config file is ready to use."
1594 echo 'You can now extract an ISO or generate a distro.'
1595 newline
1596 ;;
1599 gen-iso)
1600 # Simply generate a new iso.
1602 check_root
1603 verify_rootcd
1604 gen_livecd_isolinux
1605 distro_stats
1606 ;;
1609 gen-initiso)
1610 # Simply generate a new initramfs with a new iso.
1612 check_root
1613 verify_rootcd
1614 gen_initramfs "$ROOTFS"
1615 gen_livecd_isolinux
1616 distro_stats
1617 ;;
1620 extract-distro)
1621 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1623 check_root
1624 ISO_IMAGE="$2"
1625 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1626 'Example:\n tazlito image.iso /path/target'
1628 # Set the distro path by checking for $3 on cmdline.
1629 TARGET="${3:-$DISTRO}"
1631 # Exit if existing distro is found.
1632 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1633 'Please clean the distro tree or change directory path.'
1635 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
1637 # Start to mount the ISO.
1638 action 'Mounting ISO image...'
1639 mkdir -p "$TMP_DIR"
1640 # Get ISO file size.
1641 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
1642 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
1643 sleep 2
1644 # Prepare target dir, copy the kernel and the rootfs.
1645 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
1646 status
1648 action 'Copying the Linux kernel...'
1649 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
1650 make_bzImage_hardlink "$TARGET/rootcd/boot"
1651 else
1652 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
1653 fi
1654 status
1656 for i in $(ls $TMP_DIR); do
1657 [ "$i" == 'boot' ] && continue
1658 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
1659 done
1661 for loader in isolinux syslinux extlinux grub; do
1662 [ -d "$TMP_DIR/boot/$loader" ] || continue
1663 action 'Copying %s files...' "$loader"
1664 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
1665 status
1666 done
1668 action 'Copying the rootfs...'
1669 cp $TMP_DIR/boot/rootfs.?z "$TARGET/rootcd/boot"
1670 status
1672 # Extract initramfs.
1673 cd "$TARGET/rootfs"
1674 action 'Extracting the rootfs...'
1675 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
1676 # unpack /usr
1677 for i in etc/tazlito/*.extract; do
1678 [ -f "$i" ] && . $i ../rootcd
1679 done
1680 # Umount and remove temp directory and cd to $TARGET to get stats.
1681 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
1682 cd ..
1683 status
1685 newline
1686 separator
1687 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
1688 echo "Distro tree : $(pwd)"
1689 echo "Rootfs size : $(du -sh rootfs)"
1690 echo "Rootcd size : $(du -sh rootcd)"
1691 footer
1692 ;;
1695 list-flavors)
1696 # Show available flavors.
1697 local list='/etc/tazlito/flavors.list'
1698 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
1699 title 'List of flavors'
1700 cat $list
1701 footer
1702 ;;
1705 show-flavor)
1706 # Show flavor description.
1707 set -e
1708 flavor=${2%.flavor}
1709 flv_dir="$(extract_flavor "$flavor")"
1710 desc="$flv_dir/$flavor.desc"
1711 if [ -n "$brief" ]; then
1712 if [ -z "$noheader" ]; then
1713 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
1714 separator
1715 fi
1716 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
1717 "$(field ISO "$desc")" \
1718 "$(field Rootfs "$desc")" \
1719 "$(field Description "$desc")"
1720 else
1721 separator
1722 cat "$desc"
1723 fi
1724 cleanup
1725 ;;
1728 gen-liveflavor)
1729 # Generate a new flavor from the live system.
1730 FLAVOR=${2%.flavor}
1731 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1733 case "$FLAVOR" in
1734 -?|-h*|--help)
1735 cat <<EOT
1736 SliTaz Live Tool - Version: $VERSION
1738 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
1740 $(boldify '<flavor-patch-file> format:')
1741 $(optlist "\
1742 code data
1743 + package to add
1744 - package to remove
1745 ! non-free package to add
1746 ? display message
1747 @ flavor description
1748 ")
1750 $(boldify 'Example:')
1751 $(optlist "\
1752 @ Developer tools for SliTaz maintainers
1753 + slitaz-toolchain
1754 + mercurial
1755 ")
1756 EOT
1757 exit 1
1758 ;;
1759 esac
1760 mv /etc/tazlito/distro-packages.list \
1761 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
1762 rm -f distro-packages.list non-free.list 2>/dev/null
1763 tazpkg recharge
1765 DESC=""
1766 [ -n "$3" ] && \
1767 while read action pkg; do
1768 case "$action" in
1769 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
1770 -) yes | tazpkg remove $pkg ;;
1771 !) echo $pkg >> non-free.list ;;
1772 @) DESC="$pkg" ;;
1773 \?) echo -en "$pkg"; read action ;;
1774 esac
1775 done < $3
1777 yes '' | tazlito gen-distro
1778 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
1779 mv /etc/tazlito/distro-packages.list.$$ \
1780 /etc/tazlito/distro-packages.list 2>/dev/null
1781 ;;
1784 gen-flavor)
1785 # Generate a new flavor from the last ISO image generated
1786 FLAVOR=${2%.flavor}
1787 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1789 title 'Flavor generation'
1790 check_rootfs
1791 FILES="$FLAVOR.pkglist"
1793 action 'Creating file %s...' "$FLAVOR.flavor"
1794 for i in rootcd rootfs; do
1795 if [ -d "$ADDFILES/$i" ] ; then
1796 FILES="$FILES\n$FLAVOR.$i"
1797 (cd "$ADDFILES/$i"; find . | cpio -o -H newc 2>/dev/null | gzip -9) > $FLAVOR.$i
1798 fi
1799 done
1800 status
1802 answer=$(grep -s ^Description $FLAVOR.desc)
1803 answer=${answer#Description : }
1804 if [ -z "$answer" ]; then
1805 echo -n "Description: "
1806 read answer
1807 fi
1809 action 'Compressing flavor %s...' "$FLAVOR"
1810 echo "Flavor : $FLAVOR" > $FLAVOR.desc
1811 echo "Description : $answer" >> $FLAVOR.desc
1812 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
1813 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
1814 for i in $(ls $ROOTFS$INSTALLED); do
1815 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
1816 EXTRAVERSION=""
1817 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
1818 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
1819 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
1820 echo "$i" >> $FLAVOR.nonfree
1821 else
1822 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
1823 fi
1824 done
1825 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
1826 for i in $LOCALSTATE/undigest/*/mirror ; do
1827 [ -s $i ] && cat $i >> $FLAVOR.mirrors
1828 done
1829 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
1830 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | gzip -9 > $FLAVOR.flavor
1831 rm $(echo -e $FILES)
1832 status
1834 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
1835 ;;
1838 upgrade-flavor)
1839 # Strip versions from pkglist and update estimated numbers in flavor.desc
1840 flavor="${2%.flavor}"
1841 set -e
1842 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1843 set +e
1845 flv_dir="$(extract_flavor "$flavor")"
1847 strip_versions "$flv_dir/$flavor.pkglist"
1849 action 'Updating %s...' "$flavor.desc"
1851 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
1852 set -- $(module calc_sizes "$flv_dir" "$flavor")
1853 restore_mirrors >/dev/null
1855 sed -i -e '/Image is ready/d' \
1856 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
1857 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
1858 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
1859 -e "s|\(Packages *:\).*$|\1 $4|" \
1860 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
1861 "$flv_dir/$flavor.desc"
1863 pack_flavor "$flv_dir" "$flavor"
1864 status
1865 display_unknown "$flv_dir/err"
1866 display_warn "$flv_dir/warn"
1867 cleanup
1868 ;;
1871 extract-flavor)
1872 # Extract a flavor into $FLAVORS_REPOSITORY
1873 flavor="${2%.flavor}"
1874 set -e
1875 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1876 set +e
1878 action 'Extracting %s...' "$flavor.flavor"
1879 flv_dir="$(extract_flavor "$flavor" full)"
1880 storage="$FLAVORS_REPOSITORY/$flavor"
1882 rm -rf "$storage" 2>/dev/null
1883 mkdir -p "$storage"
1884 cp -a "$flv_dir"/* "$storage"
1885 rm "$storage/description"
1886 status
1888 strip_versions "$storage/packages.list"
1890 cleanup
1891 ;;
1894 pack-flavor)
1895 # Create a flavor from $FLAVORS_REPOSITORY.
1896 flavor=${2%.flavor}
1897 storage="$FLAVORS_REPOSITORY/$flavor"
1899 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
1901 action 'Creating flavor %s...' "$flavor"
1902 tmp_dir="$(mktemp -d)"
1904 while read from to; do
1905 [ -s "$storage/$from" ] || continue
1906 cp -a "$storage/$from" "$tmp_dir/$to"
1907 done <<EOT
1908 mirrors $flavor.mirrors
1909 distro.sh $flavor-distro.sh
1910 receipt $flavor.receipt
1911 non-free.list $flavor.nonfree
1912 EOT
1914 # Build the package list.
1915 # It can include a list from another flavor with the keyword @include
1916 if [ -s "$storage/packages.list" ]; then
1917 include=$(grep '^@include' "$storage/packages.list")
1918 if [ -n "$include" ]; then
1919 include=${include#@include }
1920 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
1921 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
1922 else
1923 echo -e "\nERROR: Can't find include package list from $include\n"
1924 fi
1925 fi
1926 # Generate the final/initial package list
1927 [ -s "$storage/packages.list" ] && \
1928 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
1929 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
1930 fi
1932 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
1933 # Process multi-rootfs flavor
1934 . "$storage/receipt"
1935 set -- $ROOTFS_SELECTION
1936 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
1937 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
1938 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
1940 for i in rootcd rootfs; do
1941 mkdir "$tmp_dir/$i"
1942 # Copy extra files from the first flavor
1943 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
1944 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
1945 # Overload extra files by meta flavor
1946 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
1947 [ -n "$(ls $tmp_dir/$i)" ] &&
1948 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
1949 gzip -9 > "$tmp_dir/$flavor.$i"
1950 rm -rf "$tmp_dir/$i"
1951 done
1952 else
1953 # Process plain flavor
1954 for i in rootcd rootfs; do
1955 [ -d "$storage/$i" ] || continue
1956 (cd "$storage/$i";
1957 find . | cpio -o -H newc 2>/dev/null) | gzip -9 > "$tmp_dir/$flavor.$i"
1958 done
1959 fi
1961 unset VERSION MAINTAINER ROOTFS_SELECTION
1962 set -- $(module calc_sizes "$tmp_dir" "$flavor")
1963 ROOTFS_SIZE="$1 (estimated)"
1964 INITRAMFS_SIZE="$2 (estimated)"
1965 ISO_SIZE="$3 (estimated)"
1966 PKGNUM="$4"
1967 . "$storage/receipt"
1969 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
1970 Flavor : $FLAVOR
1971 Description : $SHORT_DESC
1972 Version : $VERSION
1973 Maintainer : $MAINTAINER
1974 LiveCD RAM size : $FRUGAL_RAM
1975 Rootfs list : $ROOTFS_SELECTION
1976 Build date : $(date '+%Y%m%d at %T')
1977 Packages : $PKGNUM
1978 Rootfs size : $ROOTFS_SIZE
1979 Initramfs size : $INITRAMFS_SIZE
1980 ISO image size : $ISO_SIZE
1981 ================================================================================
1983 EOT
1985 rm -f $tmp_dir/packages.list
1986 pack_flavor "$tmp_dir" "$flavor"
1987 status
1988 display_unknown "$tmp_dir/err"
1989 display_warn "$flv_dir/warn"
1990 cleanup
1991 ;;
1994 get-flavor)
1995 # Get a flavor's files and prepare for gen-distro.
1996 flavor=${2%.flavor}
1997 title 'Preparing %s distro flavor' "$flavor"
1998 set -e
1999 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2000 set +e
2002 action 'Cleaning %s...' "$DISTRO"
2003 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2004 # Clean old files
2005 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2006 [ -f "$i" ] && rm "$i"
2007 done
2008 mkdir -p "$DISTRO"
2009 status
2011 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2013 action 'Extracting flavor %s...' "$flavor.flavor"
2014 flv_dir="$(extract_flavor "$flavor" info)"
2015 cp -a "$flv_dir"/* .
2016 mv packages.list distro-packages.list
2017 mv -f info /etc/tazlito
2018 status
2020 for i in rootcd rootfs; do
2021 if [ -d "$i" ]; then
2022 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2023 fi
2024 done
2026 rm -f /etc/tazlito/rootfs.list
2027 grep -q '^Rootfs list' description &&
2028 grep '^Rootfs list' description | sed 's/.*: \(.*\)$/\1/' > /etc/tazlito/rootfs.list
2030 action 'Updating %s...' 'tazlito.conf'
2031 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2032 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2033 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2034 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2035 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2036 status
2038 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2039 cleanup
2040 ;;
2043 iso2flavor)
2044 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2045 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2047 FLAVOR=${3%.flavor}
2048 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2049 mount -o loop,ro $2 $TMP_DIR/iso
2050 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2051 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2052 ! -s $TMP_DIR/flavor/*.desc ]; then
2053 _ 'META flavors are not supported.'
2054 umount -d $TMP_DIR/iso
2055 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2056 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2057 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2058 umount -d $TMP_DIR/iso
2059 else
2060 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*gz); do
2061 ( zcat < $i || unlzma < $i ) | \
2062 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2063 done
2064 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2065 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2066 '/etc/slitaz-release' '/boot/rootfs.gz'
2067 umount -d $TMP_DIR/iso
2068 else
2069 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2070 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2071 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2072 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2073 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2074 umount -d $TMP_DIR/iso
2075 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2076 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2077 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2078 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2079 < $TMP_DIR/rootfs$INSTALLED.md5
2080 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2081 if [ -s $TMP_DIR/flavor/*desc ]; then
2082 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2083 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2084 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2085 for i in rootfs rootcd ; do
2086 [ -s $TMP_DIR/flavor/*.list$i ] &&
2087 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2088 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | gzip -9 > $TMP_DIR/$FLAVOR.$i
2089 done
2090 else
2091 find_flavor_rootfs $TMP_DIR/rootfs
2092 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2093 for i in rootfs rootcd ; do
2094 [ "$(ls $TMP_DIR/$i)" ] &&
2095 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | gzip -9 > "$TMP_DIR/$FLAVOR.$i"
2096 done
2097 unset VERSION MAINTAINER
2098 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2099 if [ -n "$DESCRIPTION" ]; then
2100 _n 'Flavor version : '; read -t 30 VERSION
2101 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2102 fi
2104 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2105 Flavor : $FLAVOR
2106 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2107 Version : ${VERSION:-1.0}
2108 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2109 LiveCD RAM size : $RAM_SIZE
2110 Build date : $BUILD_DATE
2111 Packages : $PKGCNT
2112 Rootfs size : $ROOTFS_SIZE
2113 Initramfs size : $INITRAMFS_SIZE
2114 ISO image size : $ISO_SIZE
2115 ================================================================================
2117 EOT
2118 longline "Tazlito can't detect each file installed during \
2119 a package post_install. You should extract this flavor (tazlito extract-flavor \
2120 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2121 tree and remove files generated by post_installs.
2122 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2123 repack the flavor (tazlito pack-flavor $FLAVOR)"
2124 fi
2125 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | gzip -9 > $FLAVOR.flavor
2126 fi
2127 fi
2128 rm -rf $TMP_DIR
2129 ;;
2132 gen-distro)
2133 # Generate a live distro tree with a set of packages.
2135 check_root
2136 start_time=$(date +%s)
2138 # Tazlito options: --iso or --cdrom
2139 CDROM=''
2140 [ -n "$iso" ] && CDROM="-o loop $iso"
2141 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2143 # Check if a package list was specified on cmdline.
2144 if [ -f "$2" ]; then
2145 LIST_NAME="$2"
2146 else
2147 LIST_NAME='distro-packages.list'
2148 fi
2150 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2151 'Please clean the distro tree or change directory path.'
2152 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2153 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2155 # If list not given: build list with all installed packages
2156 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2157 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2158 fi
2160 # Exit if no list name.
2161 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2163 # Start generation.
2164 title 'Tazlito generating a distro'
2166 # Misc checks
2167 mkdir -p "$PACKAGES_REPOSITORY"
2168 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2169 newline
2171 # Mount CD-ROM to be able to repack boot-loader packages
2172 if [ ! -e /boot -a -n "$CDROM" ]; then
2173 mkdir $TMP_MNT
2174 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2175 ln -s "$TMP_MNT/boot" /
2176 if [ ! -d "$ADDFILES/rootcd" ] ; then
2177 mkdir -p "$ADDFILES/rootcd"
2178 for i in $(ls $TMP_MNT); do
2179 [ "$i" == 'boot' ] && continue
2180 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2181 done
2182 fi
2183 else
2184 rmdir "$TMP_MNT"
2185 fi
2186 fi
2188 # Rootfs stuff.
2189 echo 'Preparing the rootfs directory...'
2190 mkdir -p "$ROOTFS"
2191 export root="$ROOTFS"
2192 strip_versions "$LIST_NAME"
2194 if [ "$REPACK" == 'y' ]; then
2195 # Determine full packages list with all dependencies
2196 tmp_dir="$(mktemp -d)"
2197 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2198 touch "$tmp_dir/full.pkglist"
2199 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2201 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2202 while read pkgname pkgver; do
2203 # Is package in full list?
2204 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2205 # Is package already repacked?
2206 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2207 _ 'Repacking %s...' "$pkgname-$pkgver"
2208 tazpkg repack "$pkgname" --quiet
2209 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2210 status
2211 done
2213 rm -r "$tmp_dir"
2214 fi
2216 if [ -f non-free.list ]; then
2217 # FIXME: working in the ROOTFS chroot?
2218 newline
2219 echo 'Preparing non-free packages...'
2220 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2221 for pkg in $(cat 'non-free.list'); do
2222 if [ ! -d "$INSTALLED/$pkg" ]; then
2223 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2224 tazpkg get-install get-$pkg
2225 fi
2226 get-$pkg "$ROOTFS"
2227 fi
2228 tazpkg repack $pkg
2229 pkg=$(ls $pkg*.tazpkg)
2230 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2231 mv $pkg $PACKAGES_REPOSITORY
2232 done
2233 fi
2234 cp $LIST_NAME $DISTRO/distro-packages.list
2235 newline
2237 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2239 cd $DISTRO
2240 cp distro-packages.list $ROOTFS/etc/tazlito
2241 # Copy all files from $ADDFILES/rootfs to the rootfs.
2242 if [ -d "$ADDFILES/rootfs" ] ; then
2243 action 'Copying addfiles content to the rootfs...'
2244 cp -a $ADDFILES/rootfs/* $ROOTFS
2245 status
2246 fi
2248 action 'Root filesystem is generated...'; status
2250 # Root CD part.
2251 action 'Preparing the rootcd directory...'
2252 mkdir -p $ROOTCD
2253 status
2255 # Move the boot dir with the Linux kernel from rootfs.
2256 # The boot dir goes directly on the CD.
2257 if [ -d "$ROOTFS/boot" ] ; then
2258 action 'Moving the boot directory...'
2259 mv $ROOTFS/boot $ROOTCD
2260 cd $ROOTCD/boot
2261 make_bzImage_hardlink
2262 status
2263 fi
2264 cd $DISTRO
2265 # Copy all files from $ADDFILES/rootcd to the rootcd.
2266 if [ -d "$ADDFILES/rootcd" ] ; then
2267 action 'Copying addfiles content to the rootcd...'
2268 cp -a $ADDFILES/rootcd/* $ROOTCD
2269 status
2270 fi
2271 # Execute the distro script used to perform tasks in the rootfs
2272 # before compression. Give rootfs path in arg
2273 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2274 if [ -x "$DISTRO_SCRIPT" ]; then
2275 echo 'Executing distro script...'
2276 sh $DISTRO_SCRIPT $DISTRO
2277 fi
2279 # Execute the custom_rules() found in receipt.
2280 if [ -s "$TOP_DIR/receipt" ]; then
2281 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2282 echo -e "Executing: custom_rules()\n"
2283 . "$TOP_DIR/receipt"
2284 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2285 fi
2286 fi
2288 # Multi-rootfs
2289 if [ -s /etc/tazlito/rootfs.list ]; then
2291 FLAVOR_LIST="$(awk '{
2292 for (i = 2; i <= NF; i+=2)
2293 printf "%s ", i;
2294 }' /etc/tazlito/rootfs.list)"
2296 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2297 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2298 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2300 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2301 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2302 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2303 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2305 n=0
2306 last=$ROOTFS
2307 while read flavor; do
2308 n=$(($n+1))
2309 mkdir ${ROOTFS}0$n
2310 export root="${ROOTFS}0$n"
2311 # initial tazpkg setup in empty rootfs
2312 tazpkg --root=$root >/dev/null 2>&1
2314 newline
2315 boldify "Building $flavor rootfs..."
2317 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2318 cp "$TOP_DIR/$flavor.flavor" .
2320 if [ ! -s "$flavor.flavor" ]; then
2321 # We may have it in $FLAVORS_REPOSITORY
2322 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2323 tazlito pack-flavor $flavor
2324 else
2325 download $flavor.flavor
2326 fi
2327 fi
2329 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2330 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2331 cp $flavor.pkglist $DISTRO/list-packages0$n
2332 status
2334 strip_versions "$DISTRO/list-packages0$n"
2336 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2338 rm -rf ${ROOTFS}0$n/boot
2340 cd $DISTRO
2341 if [ -s $flavor.rootfs ]; then
2342 _n 'Adding %s rootfs extra files...' "$flavor"
2343 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2344 fi
2346 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2347 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2348 status
2350 rm -f $flavor.flavor install-list
2351 mergefs ${ROOTFS}0$n $last
2352 last=${ROOTFS}0$n
2353 done <<EOT
2354 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2355 EOT
2356 #'
2357 i=$(($n+1))
2358 while [ $n -gt 0 ]; do
2359 mv ${ROOTFS}0$n ${ROOTFS}$i
2360 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2361 gen_initramfs ${ROOTFS}$i
2362 n=$(($n-1))
2363 i=$(($i-1))
2364 done
2365 mv $ROOTFS ${ROOTFS}$i
2366 gen_initramfs ${ROOTFS}$i
2367 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2368 else
2369 # Initramfs and ISO image stuff.
2370 gen_initramfs $ROOTFS
2371 fi
2372 gen_livecd_isolinux
2373 distro_stats
2374 cleanup
2375 ;;
2378 clean-distro)
2379 # Remove old distro tree.
2381 check_root
2382 title 'Cleaning: %s' "$DISTRO"
2383 if [ -d "$DISTRO" ] ; then
2384 if [ -d "$ROOTFS" ] ; then
2385 action 'Removing the rootfs...'
2386 rm -f $DISTRO/$INITRAMFS
2387 rm -rf $ROOTFS
2388 status
2389 fi
2390 if [ -d "$ROOTCD" ] ; then
2391 action 'Removing the rootcd...'
2392 rm -rf $ROOTCD
2393 status
2394 fi
2395 action 'Removing eventual ISO image...'
2396 rm -f $DISTRO/$ISO_NAME.iso
2397 rm -f $DISTRO/$ISO_NAME.md5
2398 status
2399 fi
2400 footer
2401 ;;
2404 check-distro)
2405 # Check for a few LiveCD needed files not installed by packages.
2407 # TODO: Remove this function.
2408 # First two files are maintained by tazpkg while it runs on rootfs,
2409 # while last one file should be maintained by tazlito itself.
2410 check_rootfs
2411 title 'Checking distro: %s' "$ROOTFS"
2412 # SliTaz release info.
2413 rel='/etc/slitaz-release'
2414 if [ ! -f "$ROOTFS$rel" ]; then
2415 _ 'Missing release info: %s' "$rel"
2416 else
2417 action 'Release : %s' "$(cat $ROOTFS$rel)"
2418 status
2419 fi
2420 # Tazpkg mirror.
2421 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2422 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2423 todomsg
2424 else
2425 action 'Mirror configuration exists...'
2426 status
2427 fi
2428 # Isolinux msg
2429 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2430 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2431 todomsg
2432 else
2433 action 'Isolinux message seems good...'
2434 status
2435 fi
2436 footer
2437 ;;
2440 writeiso)
2441 # Writefs to ISO image including /home unlike gen-distro we don't use
2442 # packages to generate a rootfs, we build a compressed rootfs with all
2443 # the current filesystem similar to 'tazusb writefs'.
2445 DISTRO='/home/slitaz/distro'
2446 ROOTCD="$DISTRO/rootcd"
2447 COMPRESSION="${2:-none}"
2448 ISO_NAME="${3:-slitaz}"
2449 check_root
2450 # Start info
2451 title 'Write filesystem to ISO'
2452 longline "The command writeiso will write the current filesystem into a \
2453 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2454 newline
2455 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2457 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2458 # Save some space
2459 rm -rf /var/cache/tazpkg/*
2460 rm -f /var/lib/tazpkg/*.bak
2461 rm -rf $DISTRO
2463 # Optionally remove sound card selection and screen resolution.
2464 if [ -z $LaunchedByTazpanel ]; then
2465 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2466 case $anser in
2467 y)
2468 action 'Removing current sound card and screen configurations...'
2469 rm -f /var/lib/sound-card-driver
2470 rm -f /var/lib/alsa/asound.state
2471 rm -f /etc/X11/xorg.conf ;;
2472 *)
2473 action 'Keeping current sound card and screen configurations...' ;;
2474 esac
2475 status
2476 newline
2478 # Optionally remove i18n settings
2479 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2480 case $anser in
2481 y)
2482 action 'Removing current locale/keymap settings...'
2483 newline > /etc/locale.conf
2484 newline > /etc/keymap.conf ;;
2485 *)
2486 action 'Keeping current locale/keymap settings...' ;;
2487 esac
2488 status
2489 fi
2491 # Clean-up files by default
2492 newline > /etc/udev/rules.d/70-persistent-net.rules
2493 newline > /etc/udev/rules.d/70-persistant-cd.rules
2495 # Create list of files including default user files since it is defined in /etc/passwd
2496 # and some new users might have been added.
2497 cd /
2498 echo 'init' > /tmp/list
2499 for dir in bin etc sbin var dev lib root usr home opt; do
2500 [ -d $dir ] && find $dir
2501 done >> /tmp/list
2503 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2504 [ -d $dir ] && echo $dir
2505 done >> /tmp/list
2507 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2509 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2510 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2511 #fi
2512 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2513 touch /var/log/wtmp
2515 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2516 sed -i "/var\/log\/$removelog/d" /tmp/list
2517 done
2519 # Generate initramfs with specified compression and display rootfs
2520 # size in realtime.
2521 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2523 write_initramfs &
2524 sleep 2
2525 cd - > /dev/null
2526 echo -en "\nFilesystem size:"
2527 while [ ! -f /tmp/rootfs ]; do
2528 sleep 1
2529 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2530 done
2531 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2532 echo -e "\n"
2533 rm -f /tmp/rootfs
2535 # Move freshly generated rootfs to the cdrom.
2536 mkdir -p $ROOTCD/boot
2537 mv -f /$INITRAMFS $ROOTCD/boot
2538 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2540 # Now we need the kernel and isolinux files.
2541 copy_from_cd() {
2542 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2543 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2544 unmeta_boot $ROOTCD
2545 umount /media/cdrom
2548 bootloader="$LOCALSTATE/installed/syslinux/volatile.cpio.gz"
2549 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2550 copy_from_cd;
2551 elif mount | grep /media/cdrom; then
2552 copy_from_cd;
2553 elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2554 cp $bootloader $ROOTCD
2555 cd $ROOTCD
2556 zcat volatile.cpio.gz | cpio -id
2557 rm -f volatile.cpio.gz
2558 [ -f /boot/*slitaz ] && \
2559 cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2560 [ -f /boot/*slitaz64 ] && \
2561 cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2562 else
2563 touch /tmp/.write-iso-error
2564 longline "When SliTaz is running in RAM the kernel and bootloader \
2565 files are kept on the CD-ROM. Please insert a Live CD or loop mount the \
2566 slitaz.iso to /media/cdrom (run # mount -o loop slitaz-rolling.iso /media/cdrom ) \
2567 or # (tazpkg -gi linux --forced) to let Tazlito copy the files."
2568 echo -en "----\nENTER to continue..."; read i
2569 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2570 copy_from_cd
2571 fi
2573 # Generate the iso image.
2574 touch /tmp/.write-iso
2575 newline
2576 cd $DISTRO
2577 _ 'Generating ISO image...'
2578 genisoimage -R -o $ISO_NAME.iso -b boot/isolinux/isolinux.bin \
2579 -c boot/isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
2580 -V "SliTaz" -p "$(id -un)" -input-charset utf-8 \
2581 -A "tazlito/genisoimage" -P "$(hostname)" -boot-info-table $ROOTCD
2582 if [ -x /usr/bin/isohybrid ]; then
2583 action 'Creating hybrid ISO/disk...'
2584 /usr/bin/isohybrid $ISO_NAME.iso -entry 2 2>/dev/null
2585 status
2586 fi
2587 if [ -x /usr/bin/iso2exe ]; then
2588 action 'Creating hybrid ISO/EXE...'
2589 /usr/bin/iso2exe $ISO_NAME.iso 2>/dev/null
2590 status
2591 fi
2592 action 'Creating the ISO md5sum...'
2593 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2594 status
2596 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2597 rm -f /tmp/.write-iso
2599 if [ -z $LaunchedByTazpanel ]; then
2600 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2601 case $anser in
2602 y)
2603 umount /dev/cdrom 2>/dev/null
2604 eject
2605 echo -n "Please insert a blank CD-ROM and press ENTER..."
2606 read i && sleep 2
2607 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2608 echo -en "----\nENTER to continue..."; read i ;;
2609 *)
2610 exit 0 ;;
2611 esac
2612 fi
2613 ;;
2616 burn-iso)
2617 # Guess CD-ROM device, ask user and burn the ISO.
2619 check_root
2620 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2621 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2622 # We can specify an alternative ISO from the cmdline.
2623 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2624 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2626 title 'Tazlito burn ISO'
2627 echo "CD-ROM device : /dev/$DRIVE_NAME"
2628 echo "Drive speed : $DRIVE_SPEED"
2629 echo "ISO image : $iso"
2630 footer
2632 case $(yesorno 'Burn ISO image?' 'n') in
2633 y)
2634 title 'Starting Wodim to burn the ISO...'
2635 sleep 2
2636 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2637 footer 'ISO image is burned to CD-ROM.'
2638 ;;
2639 *)
2640 die 'Exiting. No ISO burned.'
2641 ;;
2642 esac
2643 ;;
2646 merge)
2647 # Merge multiple rootfs into one iso.
2649 if [ -z "$2" ]; then
2650 cat <<EOT
2651 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2653 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2654 i.e: rootfsN is a subset of rootfsN-1
2655 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2656 The boot loader will select the rootfs according to the RAM size detected.
2658 Example:
2659 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
2661 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
2662 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
2664 EOT
2665 exit 2
2666 fi
2668 shift # skip merge
2669 append="$1 slitaz1"
2670 shift # skip size1
2671 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
2673 ISO=$1.merged
2675 # Extract filesystems
2676 action 'Mounting %s' "$1"
2677 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
2678 status || cleanup_merge
2680 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2681 make_bzImage_hardlink $TMP_DIR/iso/boot
2682 umount -d $TMP_DIR/mnt
2683 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
2684 _ '%s is already a merged iso. Aborting.' "$1"
2685 cleanup_merge
2686 fi
2687 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
2688 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
2689 if [ ! -f /boot/isolinux/ifmem.c32 -a
2690 ! -f /boot/isolinux/c32box.c32 ]; then
2691 cat <<EOT
2692 No file /boot/isolinux/ifmem.c32
2693 Please install syslinux package !
2694 EOT
2695 rm -rf $TMP_DIR
2696 exit 1
2697 fi
2698 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
2699 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
2700 fi
2702 action 'Extracting %s' 'iso/rootfs.gz'
2703 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
2704 [ -d $TMP_DIR/rootfs1/etc ]
2705 status || cleanup_merge
2707 n=1
2708 while [ -n "$2" ]; do
2709 shift # skip rootfs N-1
2710 p=$n
2711 n=$(($n + 1))
2712 append="$append $1 slitaz$n"
2713 shift # skip size N
2714 mkdir -p $TMP_DIR/rootfs$n
2716 action 'Extracting %s' "$1"
2717 extract_rootfs $1 $TMP_DIR/rootfs$n &&
2718 [ -d "$TMP_DIR/rootfs$n/etc" ]
2719 status || cleanup_merge
2721 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
2722 action 'Creating %s' "rootfs$p.gz"
2723 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
2724 status
2725 done
2726 action 'Creating %s' "rootfs$n.gz"
2727 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
2728 status
2729 rm -f $TMP_DIR/iso/boot/rootfs.gz
2730 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
2731 create_iso $ISO $TMP_DIR/iso
2732 rm -rf $TMP_DIR
2733 ;;
2736 repack)
2737 # Repack an iso with maximum lzma compression ratio.
2739 ISO=$2
2740 mkdir -p $TMP_DIR/mnt
2742 # Extract filesystems
2743 action 'Mounting %s' "$ISO"
2744 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
2745 status || cleanup_merge
2747 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2748 umount -d $TMP_DIR/mnt
2750 for i in $TMP_DIR/iso/boot/rootfs* ; do
2751 action 'Repacking %s' "$(basename $i)"
2752 (zcat $i 2>/dev/null || unlzma < $i || cat $i) 2>/dev/null > $TMP_DIR/rootfs
2753 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
2754 align_to_32bits $i
2755 status
2756 done
2758 create_iso $ISO $TMP_DIR/iso
2759 rm -rf $TMP_DIR
2760 ;;
2763 build-loram)
2764 # Build a Live CD for low RAM systems.
2766 ISO="$2"
2767 OUTPUT="$3"
2768 [ -z "$3" ] && \
2769 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
2770 mkdir -p "$TMP_DIR/iso"
2771 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
2772 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$ISO$/!d;s/:.*//;q")
2773 if ! check_iso_for_loram ; then
2774 umount -d "$TMP_DIR/iso"
2775 die "$ISO is not a valid SliTaz live CD. Abort."
2776 fi
2777 case "$4" in
2778 cdrom) build_loram_cdrom ;;
2779 http) build_loram_http ;;
2780 *) build_loram_ram ;;
2781 esac
2782 umount $TMP_DIR/iso # no -d: needs /proc
2783 losetup -d $loopdev
2784 rm -rf $TMP_DIR
2785 ;;
2788 emu-iso)
2789 # Emulate an ISO image with Qemu.
2790 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2791 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
2792 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
2793 echo -e "\nStarting Qemu emulator:\n"
2794 echo -e "qemu $QEMU_OPTS $iso\n"
2795 qemu $QEMU_OPTS $iso
2796 ;;
2799 deduplicate)
2800 # Deduplicate files in a tree
2801 shift
2802 deduplicate "$@"
2803 ;;
2806 usage|*)
2807 # Print usage also for all unknown commands.
2808 usage
2809 ;;
2810 esac
2812 exit 0