tazlito view tazlito @ rev 417

tazlito: fix old busybox awk function: "%*x formats are not supported" (supported in current busybox 1.23.2); small fixes
author Aleksej Bobylev <al.bobylev@gmail.com>
date Mon Mar 14 00:56:29 2016 +0200 (2016-03-14)
parents 22eaf700fab5
children 0d0f417f54c7
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 }
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 ] &&
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 done
1174 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1175 # Meta flavor selection sizes are updated.
1177 build_loram_ram() {
1178 build_initfs ram || return 1
1179 build_loram_rootfs
1180 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1181 make_bzImage_hardlink $TMP_DIR/loramiso/boot
1182 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1183 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1184 update_metaiso_sizes
1185 create_iso $OUTPUT $TMP_DIR/loramiso
1189 # Remove files installed by packages
1191 find_flavor_rootfs() {
1192 for i in $1/etc/tazlito/*.extract; do
1193 [ -e $i ] || continue
1194 chroot $1 /bin/sh ${i#$1}
1195 done
1197 # Clean hardlinks and files patched by genisofs in /boot
1198 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1199 rm -f $1/boot/$i*
1200 done
1202 # Clean files generated in post_install
1203 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1204 $1/dev/core $1/dev/fd $1/dev/std*
1206 # Verify md5
1207 cat $1$INSTALLED/*/md5sum | \
1208 while read md5 file; do
1209 [ -e "$1$file" ] || continue
1210 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1211 rm -f "$1$file"
1212 done
1214 # Check configuration files
1215 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1216 [ -e $i ] || continue
1217 mkdir /tmp/volatile$$
1218 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1219 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1220 while read file ; do
1221 [ -e "$1/$file" ] || continue
1222 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1223 done
1224 rm -rf /tmp/volatile$$
1225 done
1227 # Remove other files blindly
1228 for i in $1$INSTALLED/*/files.list; do
1229 for file in $(cat "$i"); do
1230 [ "$1$file" -nt "$i" ] && continue
1231 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1232 [ -d "$1$file" ] || rm -f "$1$file"
1233 done
1234 done
1236 # Remove tazpkg files and tmp files
1237 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1238 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1239 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1240 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1241 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1243 # Cleanup directory tree
1244 cd $1
1245 find * -type d | sort -r | while read dir; do
1246 rmdir "$dir" 2>/dev/null
1247 done
1248 cd - > /dev/null
1252 # Get byte(s) from a binary file
1254 get() {
1255 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null
1259 # Get cpio flavor info from the ISO image
1261 flavordata() {
1262 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1263 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1267 # Restore undigest mirrors
1269 restore_mirrors() {
1270 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1271 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1273 action 'Restoring mirrors...'
1274 if [ -d "$undigest.bak" ]; then
1275 [ -d "$undigest" ] && rm -r "$undigest"
1276 mv "$undigest.bak" "$undigest"
1277 fi
1278 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1279 :; status
1283 # Setup undigest mirrors
1285 setup_mirrors() {
1286 # Setup mirrors in plain system or in chroot (with variable root=)
1288 # Note, difficulties exists in using local-filesystem-mirrors (when content
1289 # of the 'mirror' file is point to folder somewhere in the FS) inside chroot,
1290 # because mirror should be in the chroot too. We make local mirrors to be
1291 # accessible via http://localhost/... using built-in SliTaz web server.
1292 local mirrorlist="$1" fresh repacked
1293 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1295 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1296 restore_mirrors
1298 _ 'Setting up mirrors for %s...' "$root/"
1299 # Backing up current undigest mirrors and priority
1300 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1301 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1302 rm -rf '/var/www/tazlito/'
1303 mkdir -p '/var/www/tazlito/'
1305 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1306 fresh='/home/slitaz/packages'
1307 if [ -d "$fresh" ]; then
1308 # Make this mirror accessible using http://localhost/tazlito/fresh
1309 ln -s "$fresh" '/var/www/tazlito/fresh'
1310 # Setup first undigest mirror
1311 mkdir -p "$undigest/fresh"
1312 echo 'http://localhost/tazlito/fresh/' > "$undigest/fresh/mirror"
1313 echo 'fresh' >> "$priority"
1314 # Rebuild mirror DB if needed
1315 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1316 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1317 tazpkg mkdb "$fresh" --forced --root=''
1318 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1319 fi
1321 # Repacked packages: high priority
1322 repacked="$PACKAGES_REPOSITORY"
1323 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1324 # According to Tazlito setup file (tazlito.conf):
1325 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1326 # or
1327 # WORK_DIR="/home/slitaz"
1328 # and
1329 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1330 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1332 # Make this mirror accessible using http://localhost/tazlito/repacked
1333 ln -s "$repacked" '/var/www/tazlito/repacked'
1334 # Setup second undigest mirror
1335 mkdir -p "$undigest/repacked"
1336 echo 'http://localhost/tazlito/repacked/' > "$undigest/repacked/mirror"
1337 echo 'repacked' >> "$priority"
1338 # Rebuild mirror DB if needed
1339 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1340 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1341 tazpkg mkdb "$repacked" --forced --root=''
1342 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1343 fi
1345 # All repositories listed in mirrors list: normal priority
1346 [ -e "$mirrorlist" ] && \
1347 while read mirror; do
1348 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1349 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1350 mkdir -p "$undigest/$mirrorid"
1351 echo "$mirror" > "$undigest/$mirrorid/mirror"
1352 echo "$mirrorid" >> "$priority"
1353 done < "$mirrorlist"
1355 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1357 # Show list of mirrors
1358 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1359 function show(num, name, url, pad) {
1360 pad = substr("................................", 1, 32 - length(name));
1361 printf " %-1.1d. %s%s %-44.44s\n", num, name, pad, url;
1364 num++;
1365 "cat " db "/undigest/" $0 "/mirror" | getline url;
1366 show(num, $0, url);
1368 END {
1369 num++;
1370 "cat " db "/mirror" | getline url;
1371 show(num, "main", url);
1372 }' "$priority"
1374 tazpkg recharge --quiet >/dev/null
1378 # Get list of 'packages.info' lists using priority
1380 pi_lists() {
1381 local pi
1382 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1383 local priority="$root$LOCALSTATE/priority"
1384 local undigest="$root$LOCALSTATE/undigest"
1387 [ -s "$priority" ] && cat "$priority"
1388 echo 'main'
1389 [ -d "$undigest" ] && ls "$undigest"
1390 } | awk -vun="$undigest/" '
1392 if (arr[$0] != 1) {
1393 arr[$0] = 1;
1394 print un $0 "/packages.info";
1396 }' | sed 's|/undigest/main||' | \
1397 while read pi; do
1398 [ -e "$pi" ] && echo "$pi"
1399 done
1403 # Strip versions from packages list
1405 strip_versions() {
1406 action 'Strip versions from list %s...' "$(basename "$1")"
1407 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1408 [ -f "$in_list" ] || die "List '$in_list' not found."
1410 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1411 awk '
1413 if (FILENAME ~ "packages.info") {
1414 # Collect package names
1415 FS = "\t"; pkg[$1] = 1;
1416 } else {
1417 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1418 while (NF > 1 && ! pkg[$0])
1419 NF --;
1420 printf "%s\n", $0;
1422 }' $(pi_lists) "$in_list" > "$tmp_list"
1424 cat "$tmp_list" > "$in_list"
1425 rm "$tmp_list"
1426 status
1430 # Display list of unknown packages (informative)
1432 display_unknown() {
1433 [ -s "$1" ] || return
1434 echo "Unknown packages:" >&2
1435 cat "$1" >&2
1436 rm "$1"
1440 # Display warnings about critical packages absent (informative)
1442 display_warn() {
1443 [ -s "$1" ] || return
1444 echo "Absent critical packages:" >&2
1445 cat "$1" >&2
1446 rm "$1"
1447 echo "Probably ISO image will be unusable."
1451 # Install packages to rootfs
1453 install_list_to_rootfs() {
1454 local list="$1" rootfs="$2" pkg i ii
1455 local undigest="$rootfs/var/lib/tazpkg/undigest"
1457 # initial tazpkg setup in empty rootfs
1458 tazpkg --root=$rootfs >/dev/null 2>&1
1459 # link rootfs packages cache to the regular packages cache
1460 rm -r "$rootfs/var/cache/tazpkg"
1461 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1463 setup_mirrors mirrors
1465 # Just in case if flavor not contains "tazlito" package
1466 mkdir -p "$rootfs/etc/tazlito"
1468 newline
1469 for pkg in $(cat $list); do
1470 action 'Installing package: %s' "$pkg"
1471 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1472 status
1473 done
1474 newline
1476 restore_mirrors
1477 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1478 for i in fresh repacked; do
1479 ii="$undigest/$i"
1480 [ -d "$ii" ] && rm -rf "$ii"
1481 ii="$rootfs/var/lib/tazpkg/priority"
1482 if [ -f "$ii" ]; then
1483 sed -i "/$i/d" "$ii"
1484 [ -s "$ii" ] || rm "$ii"
1485 fi
1486 done
1487 [ -d "$undigest" ] && \
1488 for i in $(find "$undigest" -type f); do
1489 # Remove all undigest PKGDB files but 'mirror'
1490 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1491 done
1492 [ -d "$undigest" ] && \
1493 rmdir --ignore-fail-on-non-empty "$undigest"
1495 # Un-link packages cache
1496 rm "$rootfs/var/cache/tazpkg"
1498 # Clean /var/lib/tazpkg
1499 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1505 ####################
1506 # Tazlito commands #
1507 ####################
1509 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1510 case "$0" in
1511 *reduplicate)
1512 find ${@:-.} ! -type d -links +1 \
1513 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1514 exit 0 ;;
1515 *deduplicate)
1516 deduplicate "$@"
1517 exit 0 ;;
1518 esac
1521 case "$COMMAND" in
1522 stats)
1523 # Tazlito general statistics from the config file.
1525 title 'Tazlito statistics'
1526 optlist "\
1527 Config file : $CONFIG_FILE
1528 ISO name : $ISO_NAME.iso
1529 Volume name : $VOLUM_NAME
1530 Prepared : $PREPARED
1531 Packages repository : $PACKAGES_REPOSITORY
1532 Distro directory : $DISTRO
1533 Additional files : $ADDFILES
1534 " | sed '/: $/d'
1535 footer
1536 ;;
1539 list-addfiles)
1540 # Simple list of additional files in the rootfs
1541 newline
1542 if [ -d "$ADDFILES/rootfs" ]; then
1543 cd $ADDFILES
1544 find rootfs -type f
1545 else
1546 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1547 fi
1548 newline
1549 ;;
1552 gen-config)
1553 # Generate a new config file in the current dir or the specified
1554 # directory by $2.
1556 if [ -n "$2" ]; then
1557 mkdir -p "$2" && cd "$2"
1558 fi
1560 newline
1561 action 'Generating empty tazlito.conf...'
1562 empty_config_file
1563 status
1565 separator
1566 if [ -f 'tazlito.conf' ] ; then
1567 _ 'Configuration file is ready to edit.'
1568 _ 'File location: %s' "$(pwd)/tazlito.conf"
1569 newline
1570 fi
1571 ;;
1574 configure)
1575 # Configure a tazlito.conf config file. Start by getting
1576 # a empty config file and sed it.
1578 if [ -f 'tazlito.conf' ]; then
1579 rm tazlito.conf
1580 else
1581 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1582 'or in the same directory of the file you want to configure.'
1583 cd /etc
1584 fi
1586 empty_config_file
1588 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1590 # ISO name.
1591 echo -n "ISO name : " ; read answer
1592 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1593 # Volume name.
1594 echo -n "Volume name : " ; read answer
1595 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1596 # Packages repository.
1597 echo -n "Packages repository : " ; read answer
1598 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1599 # Distro path.
1600 echo -n "Distro path : " ; read answer
1601 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1602 footer "Config file is ready to use."
1603 echo 'You can now extract an ISO or generate a distro.'
1604 newline
1605 ;;
1608 gen-iso)
1609 # Simply generate a new iso.
1611 check_root
1612 verify_rootcd
1613 gen_livecd_isolinux
1614 distro_stats
1615 ;;
1618 gen-initiso)
1619 # Simply generate a new initramfs with a new iso.
1621 check_root
1622 verify_rootcd
1623 gen_initramfs "$ROOTFS"
1624 gen_livecd_isolinux
1625 distro_stats
1626 ;;
1629 extract-distro)
1630 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1632 check_root
1633 ISO_IMAGE="$2"
1634 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1635 'Example:\n tazlito image.iso /path/target'
1637 # Set the distro path by checking for $3 on cmdline.
1638 TARGET="${3:-$DISTRO}"
1640 # Exit if existing distro is found.
1641 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1642 'Please clean the distro tree or change directory path.'
1644 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
1646 # Start to mount the ISO.
1647 action 'Mounting ISO image...'
1648 mkdir -p "$TMP_DIR"
1649 # Get ISO file size.
1650 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
1651 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
1652 sleep 2
1653 # Prepare target dir, copy the kernel and the rootfs.
1654 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
1655 status
1657 action 'Copying the Linux kernel...'
1658 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
1659 make_bzImage_hardlink "$TARGET/rootcd/boot"
1660 else
1661 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
1662 fi
1663 status
1665 for i in $(ls $TMP_DIR); do
1666 [ "$i" == 'boot' ] && continue
1667 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
1668 done
1670 for loader in isolinux syslinux extlinux grub; do
1671 [ -d "$TMP_DIR/boot/$loader" ] || continue
1672 action 'Copying %s files...' "$loader"
1673 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
1674 status
1675 done
1677 action 'Copying the rootfs...'
1678 cp $TMP_DIR/boot/rootfs.?z "$TARGET/rootcd/boot"
1679 status
1681 # Extract initramfs.
1682 cd "$TARGET/rootfs"
1683 action 'Extracting the rootfs...'
1684 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
1685 # unpack /usr
1686 for i in etc/tazlito/*.extract; do
1687 [ -f "$i" ] && . $i ../rootcd
1688 done
1689 # Umount and remove temp directory and cd to $TARGET to get stats.
1690 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
1691 cd ..
1692 status
1694 newline
1695 separator
1696 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
1697 echo "Distro tree : $(pwd)"
1698 echo "Rootfs size : $(du -sh rootfs)"
1699 echo "Rootcd size : $(du -sh rootcd)"
1700 footer
1701 ;;
1704 list-flavors)
1705 # Show available flavors.
1706 local list='/etc/tazlito/flavors.list'
1707 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
1708 title 'List of flavors'
1709 cat $list
1710 footer
1711 ;;
1714 show-flavor)
1715 # Show flavor description.
1716 set -e
1717 flavor=${2%.flavor}
1718 flv_dir="$(extract_flavor "$flavor")"
1719 desc="$flv_dir/$flavor.desc"
1720 if [ -n "$brief" ]; then
1721 if [ -z "$noheader" ]; then
1722 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
1723 separator
1724 fi
1725 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
1726 "$(field ISO "$desc")" \
1727 "$(field Rootfs "$desc")" \
1728 "$(field Description "$desc")"
1729 else
1730 separator
1731 cat "$desc"
1732 fi
1733 cleanup
1734 ;;
1737 gen-liveflavor)
1738 # Generate a new flavor from the live system.
1739 FLAVOR=${2%.flavor}
1740 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1742 case "$FLAVOR" in
1743 -?|-h*|--help)
1744 cat <<EOT
1745 SliTaz Live Tool - Version: $VERSION
1747 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
1749 $(boldify '<flavor-patch-file> format:')
1750 $(optlist "\
1751 code data
1752 + package to add
1753 - package to remove
1754 ! non-free package to add
1755 ? display message
1756 @ flavor description
1757 ")
1759 $(boldify 'Example:')
1760 $(optlist "\
1761 @ Developer tools for SliTaz maintainers
1762 + slitaz-toolchain
1763 + mercurial
1764 ")
1765 EOT
1766 exit 1
1767 ;;
1768 esac
1769 mv /etc/tazlito/distro-packages.list \
1770 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
1771 rm -f distro-packages.list non-free.list 2>/dev/null
1772 tazpkg recharge
1774 DESC=""
1775 [ -n "$3" ] && \
1776 while read action pkg; do
1777 case "$action" in
1778 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
1779 -) yes | tazpkg remove $pkg ;;
1780 !) echo $pkg >> non-free.list ;;
1781 @) DESC="$pkg" ;;
1782 \?) echo -en "$pkg"; read action ;;
1783 esac
1784 done < $3
1786 yes '' | tazlito gen-distro
1787 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
1788 mv /etc/tazlito/distro-packages.list.$$ \
1789 /etc/tazlito/distro-packages.list 2>/dev/null
1790 ;;
1793 gen-flavor)
1794 # Generate a new flavor from the last ISO image generated
1795 FLAVOR=${2%.flavor}
1796 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1798 title 'Flavor generation'
1799 check_rootfs
1800 FILES="$FLAVOR.pkglist"
1802 action 'Creating file %s...' "$FLAVOR.flavor"
1803 for i in rootcd rootfs; do
1804 if [ -d "$ADDFILES/$i" ] ; then
1805 FILES="$FILES\n$FLAVOR.$i"
1806 (cd "$ADDFILES/$i"; find . | cpio -o -H newc 2>/dev/null | gzip -9) > $FLAVOR.$i
1807 fi
1808 done
1809 status
1811 answer=$(grep -s ^Description $FLAVOR.desc)
1812 answer=${answer#Description : }
1813 if [ -z "$answer" ]; then
1814 echo -n "Description: "
1815 read answer
1816 fi
1818 action 'Compressing flavor %s...' "$FLAVOR"
1819 echo "Flavor : $FLAVOR" > $FLAVOR.desc
1820 echo "Description : $answer" >> $FLAVOR.desc
1821 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
1822 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
1823 for i in $(ls $ROOTFS$INSTALLED); do
1824 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
1825 EXTRAVERSION=""
1826 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
1827 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
1828 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
1829 echo "$i" >> $FLAVOR.nonfree
1830 else
1831 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
1832 fi
1833 done
1834 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
1835 for i in $LOCALSTATE/undigest/*/mirror ; do
1836 [ -s $i ] && cat $i >> $FLAVOR.mirrors
1837 done
1838 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
1839 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | gzip -9 > $FLAVOR.flavor
1840 rm $(echo -e $FILES)
1841 status
1843 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
1844 ;;
1847 upgrade-flavor)
1848 # Strip versions from pkglist and update estimated numbers in flavor.desc
1849 flavor="${2%.flavor}"
1850 set -e
1851 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1852 set +e
1854 flv_dir="$(extract_flavor "$flavor")"
1856 strip_versions "$flv_dir/$flavor.pkglist"
1858 action 'Updating %s...' "$flavor.desc"
1860 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
1861 set -- $(module calc_sizes "$flv_dir" "$flavor")
1862 restore_mirrors >/dev/null
1864 sed -i -e '/Image is ready/d' \
1865 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
1866 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
1867 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
1868 -e "s|\(Packages *:\).*$|\1 $4|" \
1869 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
1870 "$flv_dir/$flavor.desc"
1872 pack_flavor "$flv_dir" "$flavor"
1873 status
1874 display_unknown "$flv_dir/err"
1875 display_warn "$flv_dir/warn"
1876 cleanup
1877 ;;
1880 extract-flavor)
1881 # Extract a flavor into $FLAVORS_REPOSITORY
1882 flavor="${2%.flavor}"
1883 set -e
1884 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1885 set +e
1887 action 'Extracting %s...' "$flavor.flavor"
1888 flv_dir="$(extract_flavor "$flavor" full)"
1889 storage="$FLAVORS_REPOSITORY/$flavor"
1891 rm -rf "$storage" 2>/dev/null
1892 mkdir -p "$storage"
1893 cp -a "$flv_dir"/* "$storage"
1894 rm "$storage/description"
1895 status
1897 strip_versions "$storage/packages.list"
1899 cleanup
1900 ;;
1903 pack-flavor)
1904 # Create a flavor from $FLAVORS_REPOSITORY.
1905 flavor=${2%.flavor}
1906 storage="$FLAVORS_REPOSITORY/$flavor"
1908 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
1910 action 'Creating flavor %s...' "$flavor"
1911 tmp_dir="$(mktemp -d)"
1913 while read from to; do
1914 [ -s "$storage/$from" ] || continue
1915 cp -a "$storage/$from" "$tmp_dir/$to"
1916 done <<EOT
1917 mirrors $flavor.mirrors
1918 distro.sh $flavor-distro.sh
1919 receipt $flavor.receipt
1920 non-free.list $flavor.nonfree
1921 EOT
1923 # Build the package list.
1924 # It can include a list from another flavor with the keyword @include
1925 if [ -s "$storage/packages.list" ]; then
1926 include=$(grep '^@include' "$storage/packages.list")
1927 if [ -n "$include" ]; then
1928 include=${include#@include }
1929 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
1930 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
1931 else
1932 echo -e "\nERROR: Can't find include package list from $include\n"
1933 fi
1934 fi
1935 # Generate the final/initial package list
1936 [ -s "$storage/packages.list" ] && \
1937 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
1938 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
1939 fi
1941 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
1942 # Process multi-rootfs flavor
1943 . "$storage/receipt"
1944 set -- $ROOTFS_SELECTION
1945 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
1946 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
1947 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
1949 for i in rootcd rootfs; do
1950 mkdir "$tmp_dir/$i"
1951 # Copy extra files from the first flavor
1952 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
1953 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
1954 # Overload extra files by meta flavor
1955 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
1956 [ -n "$(ls $tmp_dir/$i)" ] &&
1957 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
1958 gzip -9 > "$tmp_dir/$flavor.$i"
1959 rm -rf "$tmp_dir/$i"
1960 done
1961 else
1962 # Process plain flavor
1963 for i in rootcd rootfs; do
1964 [ -d "$storage/$i" ] || continue
1965 (cd "$storage/$i";
1966 find . | cpio -o -H newc 2>/dev/null) | gzip -9 > "$tmp_dir/$flavor.$i"
1967 done
1968 fi
1970 unset VERSION MAINTAINER ROOTFS_SELECTION
1971 set -- $(module calc_sizes "$tmp_dir" "$flavor")
1972 ROOTFS_SIZE="$1 (estimated)"
1973 INITRAMFS_SIZE="$2 (estimated)"
1974 ISO_SIZE="$3 (estimated)"
1975 PKGNUM="$4"
1976 . "$storage/receipt"
1978 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
1979 Flavor : $FLAVOR
1980 Description : $SHORT_DESC
1981 Version : $VERSION
1982 Maintainer : $MAINTAINER
1983 LiveCD RAM size : $FRUGAL_RAM
1984 Rootfs list : $ROOTFS_SELECTION
1985 Build date : $(date '+%Y%m%d at %T')
1986 Packages : $PKGNUM
1987 Rootfs size : $ROOTFS_SIZE
1988 Initramfs size : $INITRAMFS_SIZE
1989 ISO image size : $ISO_SIZE
1990 ================================================================================
1992 EOT
1994 rm -f $tmp_dir/packages.list
1995 pack_flavor "$tmp_dir" "$flavor"
1996 status
1997 display_unknown "$tmp_dir/err"
1998 display_warn "$flv_dir/warn"
1999 cleanup
2000 ;;
2003 get-flavor)
2004 # Get a flavor's files and prepare for gen-distro.
2005 flavor=${2%.flavor}
2006 title 'Preparing %s distro flavor' "$flavor"
2007 set -e
2008 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2009 set +e
2011 action 'Cleaning %s...' "$DISTRO"
2012 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2013 # Clean old files
2014 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2015 [ -f "$i" ] && rm "$i"
2016 done
2017 mkdir -p "$DISTRO"
2018 status
2020 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2022 action 'Extracting flavor %s...' "$flavor.flavor"
2023 flv_dir="$(extract_flavor "$flavor" info)"
2024 cp -a "$flv_dir"/* .
2025 mv packages.list distro-packages.list
2026 mv -f info /etc/tazlito
2027 status
2029 for i in rootcd rootfs; do
2030 if [ -d "$i" ]; then
2031 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2032 fi
2033 done
2035 rm -f /etc/tazlito/rootfs.list
2036 grep -q '^Rootfs list' description &&
2037 grep '^Rootfs list' description | sed 's/.*: \(.*\)$/\1/' > /etc/tazlito/rootfs.list
2039 action 'Updating %s...' 'tazlito.conf'
2040 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2041 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2042 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2043 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2044 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2045 status
2047 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2048 cleanup
2049 ;;
2052 iso2flavor)
2053 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2054 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2056 FLAVOR=${3%.flavor}
2057 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2058 mount -o loop,ro $2 $TMP_DIR/iso
2059 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2060 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2061 ! -s $TMP_DIR/flavor/*.desc ]; then
2062 _ 'META flavors are not supported.'
2063 umount -d $TMP_DIR/iso
2064 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2065 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2066 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2067 umount -d $TMP_DIR/iso
2068 else
2069 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*gz); do
2070 ( zcat < $i || unlzma < $i ) | \
2071 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2072 done
2073 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2074 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2075 '/etc/slitaz-release' '/boot/rootfs.gz'
2076 umount -d $TMP_DIR/iso
2077 else
2078 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2079 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2080 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2081 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2082 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2083 umount -d $TMP_DIR/iso
2084 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2085 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2086 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2087 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2088 < $TMP_DIR/rootfs$INSTALLED.md5
2089 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2090 if [ -s $TMP_DIR/flavor/*desc ]; then
2091 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2092 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2093 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2094 for i in rootfs rootcd ; do
2095 [ -s $TMP_DIR/flavor/*.list$i ] &&
2096 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2097 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | gzip -9 > $TMP_DIR/$FLAVOR.$i
2098 done
2099 else
2100 find_flavor_rootfs $TMP_DIR/rootfs
2101 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2102 for i in rootfs rootcd ; do
2103 [ "$(ls $TMP_DIR/$i)" ] &&
2104 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | gzip -9 > "$TMP_DIR/$FLAVOR.$i"
2105 done
2106 unset VERSION MAINTAINER
2107 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2108 if [ -n "$DESCRIPTION" ]; then
2109 _n 'Flavor version : '; read -t 30 VERSION
2110 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2111 fi
2113 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2114 Flavor : $FLAVOR
2115 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2116 Version : ${VERSION:-1.0}
2117 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2118 LiveCD RAM size : $RAM_SIZE
2119 Build date : $BUILD_DATE
2120 Packages : $PKGCNT
2121 Rootfs size : $ROOTFS_SIZE
2122 Initramfs size : $INITRAMFS_SIZE
2123 ISO image size : $ISO_SIZE
2124 ================================================================================
2126 EOT
2127 longline "Tazlito can't detect each file installed during \
2128 a package post_install. You should extract this flavor (tazlito extract-flavor \
2129 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2130 tree and remove files generated by post_installs.
2131 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2132 repack the flavor (tazlito pack-flavor $FLAVOR)"
2133 fi
2134 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | gzip -9 > $FLAVOR.flavor
2135 fi
2136 fi
2137 rm -rf $TMP_DIR
2138 ;;
2141 gen-distro)
2142 # Generate a live distro tree with a set of packages.
2144 check_root
2145 start_time=$(date +%s)
2147 # Tazlito options: --iso or --cdrom
2148 CDROM=''
2149 [ -n "$iso" ] && CDROM="-o loop $iso"
2150 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2152 # Check if a package list was specified on cmdline.
2153 if [ -f "$2" ]; then
2154 LIST_NAME="$2"
2155 else
2156 LIST_NAME='distro-packages.list'
2157 fi
2159 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2160 'Please clean the distro tree or change directory path.'
2161 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2162 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2164 # If list not given: build list with all installed packages
2165 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2166 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2167 fi
2169 # Exit if no list name.
2170 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2172 # Start generation.
2173 title 'Tazlito generating a distro'
2175 # Misc checks
2176 mkdir -p "$PACKAGES_REPOSITORY"
2177 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2178 newline
2180 # Mount CD-ROM to be able to repack boot-loader packages
2181 if [ ! -e /boot -a -n "$CDROM" ]; then
2182 mkdir $TMP_MNT
2183 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2184 ln -s "$TMP_MNT/boot" /
2185 if [ ! -d "$ADDFILES/rootcd" ] ; then
2186 mkdir -p "$ADDFILES/rootcd"
2187 for i in $(ls $TMP_MNT); do
2188 [ "$i" == 'boot' ] && continue
2189 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2190 done
2191 fi
2192 else
2193 rmdir "$TMP_MNT"
2194 fi
2195 fi
2197 # Rootfs stuff.
2198 echo 'Preparing the rootfs directory...'
2199 mkdir -p "$ROOTFS"
2200 export root="$ROOTFS"
2201 strip_versions "$LIST_NAME"
2203 if [ "$REPACK" == 'y' ]; then
2204 # Determine full packages list with all dependencies
2205 tmp_dir="$(mktemp -d)"
2206 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2207 touch "$tmp_dir/full.pkglist"
2208 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2210 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2211 while read pkgname pkgver; do
2212 # Is package in full list?
2213 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2214 # Is package already repacked?
2215 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2216 _ 'Repacking %s...' "$pkgname-$pkgver"
2217 tazpkg repack "$pkgname" --quiet
2218 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2219 status
2220 done
2222 rm -r "$tmp_dir"
2223 fi
2225 if [ -f non-free.list ]; then
2226 # FIXME: working in the ROOTFS chroot?
2227 newline
2228 echo 'Preparing non-free packages...'
2229 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2230 for pkg in $(cat 'non-free.list'); do
2231 if [ ! -d "$INSTALLED/$pkg" ]; then
2232 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2233 tazpkg get-install get-$pkg
2234 fi
2235 get-$pkg "$ROOTFS"
2236 fi
2237 tazpkg repack $pkg
2238 pkg=$(ls $pkg*.tazpkg)
2239 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2240 mv $pkg $PACKAGES_REPOSITORY
2241 done
2242 fi
2243 cp $LIST_NAME $DISTRO/distro-packages.list
2244 newline
2246 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2248 cd $DISTRO
2249 cp distro-packages.list $ROOTFS/etc/tazlito
2250 # Copy all files from $ADDFILES/rootfs to the rootfs.
2251 if [ -d "$ADDFILES/rootfs" ] ; then
2252 action 'Copying addfiles content to the rootfs...'
2253 cp -a $ADDFILES/rootfs/* $ROOTFS
2254 status
2255 fi
2257 action 'Root filesystem is generated...'; status
2259 # Root CD part.
2260 action 'Preparing the rootcd directory...'
2261 mkdir -p $ROOTCD
2262 status
2264 # Move the boot dir with the Linux kernel from rootfs.
2265 # The boot dir goes directly on the CD.
2266 if [ -d "$ROOTFS/boot" ] ; then
2267 action 'Moving the boot directory...'
2268 mv $ROOTFS/boot $ROOTCD
2269 cd $ROOTCD/boot
2270 make_bzImage_hardlink
2271 status
2272 fi
2273 cd $DISTRO
2274 # Copy all files from $ADDFILES/rootcd to the rootcd.
2275 if [ -d "$ADDFILES/rootcd" ] ; then
2276 action 'Copying addfiles content to the rootcd...'
2277 cp -a $ADDFILES/rootcd/* $ROOTCD
2278 status
2279 fi
2280 # Execute the distro script used to perform tasks in the rootfs
2281 # before compression. Give rootfs path in arg
2282 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2283 if [ -x "$DISTRO_SCRIPT" ]; then
2284 echo 'Executing distro script...'
2285 sh $DISTRO_SCRIPT $DISTRO
2286 fi
2288 # Execute the custom_rules() found in receipt.
2289 if [ -s "$TOP_DIR/receipt" ]; then
2290 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2291 echo -e "Executing: custom_rules()\n"
2292 . "$TOP_DIR/receipt"
2293 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2294 fi
2295 fi
2297 # Multi-rootfs
2298 if [ -s /etc/tazlito/rootfs.list ]; then
2300 FLAVOR_LIST="$(awk '{
2301 for (i = 2; i <= NF; i+=2)
2302 printf "%s ", i;
2303 }' /etc/tazlito/rootfs.list)"
2305 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2306 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2307 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2309 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2310 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2311 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2312 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2314 n=0
2315 last=$ROOTFS
2316 while read flavor; do
2317 n=$(($n+1))
2318 newline
2319 boldify "Building $flavor rootfs..."
2321 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2322 cp "$TOP_DIR/$flavor.flavor" .
2324 if [ ! -s "$flavor.flavor" ]; then
2325 # We may have it in $FLAVORS_REPOSITORY
2326 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2327 tazlito pack-flavor $flavor
2328 else
2329 download $flavor.flavor
2330 fi
2331 fi
2333 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2334 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2335 sed 's/.*/&.tazpkg/' < $flavor.pkglist > $DISTRO/list-packages0$n
2336 status
2338 mkdir ${ROOTFS}0$n
2339 export root="${ROOTFS}0$n"
2340 strip_versions "$DISTRO/list-packages0$n"
2342 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2344 rm -rf ${ROOTFS}0$n/boot
2346 cd $DISTRO
2347 if [ -s $flavor.rootfs ]; then
2348 _n 'Adding %s rootfs extra files...' "$flavor"
2349 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2350 fi
2352 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2353 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2354 status
2356 rm -f $flavor.flavor install-list
2357 mergefs ${ROOTFS}0$n $last
2358 last=${ROOTFS}0$n
2359 done <<EOT
2360 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2361 EOT
2362 #'
2363 i=$(($n+1))
2364 while [ $n -gt 0 ]; do
2365 mv ${ROOTFS}0$n ${ROOTFS}$i
2366 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2367 gen_initramfs ${ROOTFS}$i
2368 n=$(($n-1))
2369 i=$(($i-1))
2370 done
2371 mv $ROOTFS ${ROOTFS}$i
2372 gen_initramfs ${ROOTFS}$i
2373 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2374 else
2375 # Initramfs and ISO image stuff.
2376 gen_initramfs $ROOTFS
2377 fi
2378 gen_livecd_isolinux
2379 distro_stats
2380 cleanup
2381 ;;
2384 clean-distro)
2385 # Remove old distro tree.
2387 check_root
2388 title 'Cleaning: %s' "$DISTRO"
2389 if [ -d "$DISTRO" ] ; then
2390 if [ -d "$ROOTFS" ] ; then
2391 action 'Removing the rootfs...'
2392 rm -f $DISTRO/$INITRAMFS
2393 rm -rf $ROOTFS
2394 status
2395 fi
2396 if [ -d "$ROOTCD" ] ; then
2397 action 'Removing the rootcd...'
2398 rm -rf $ROOTCD
2399 status
2400 fi
2401 action 'Removing eventual ISO image...'
2402 rm -f $DISTRO/$ISO_NAME.iso
2403 rm -f $DISTRO/$ISO_NAME.md5
2404 status
2405 fi
2406 footer
2407 ;;
2410 check-distro)
2411 # Check for a few LiveCD needed files not installed by packages.
2413 # TODO: Remove this function.
2414 # First two files are maintained by tazpkg while it runs on rootfs,
2415 # while last one file should be maintained by tazlito itself.
2416 check_rootfs
2417 title 'Checking distro: %s' "$ROOTFS"
2418 # SliTaz release info.
2419 rel='/etc/slitaz-release'
2420 if [ ! -f "$ROOTFS$rel" ]; then
2421 _ 'Missing release info: %s' "$rel"
2422 else
2423 action 'Release : %s' "$(cat $ROOTFS$rel)"
2424 status
2425 fi
2426 # Tazpkg mirror.
2427 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2428 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2429 todomsg
2430 else
2431 action 'Mirror configuration exists...'
2432 status
2433 fi
2434 # Isolinux msg
2435 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2436 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2437 todomsg
2438 else
2439 action 'Isolinux message seems good...'
2440 status
2441 fi
2442 footer
2443 ;;
2446 writeiso)
2447 # Writefs to ISO image including /home unlike gen-distro we don't use
2448 # packages to generate a rootfs, we build a compressed rootfs with all
2449 # the current filesystem similar to 'tazusb writefs'.
2451 DISTRO='/home/slitaz/distro'
2452 ROOTCD="$DISTRO/rootcd"
2453 COMPRESSION="${2:-none}"
2454 ISO_NAME="${3:-slitaz}"
2455 check_root
2456 # Start info
2457 title 'Write filesystem to ISO'
2458 longline "The command writeiso will write the current filesystem into a \
2459 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2460 newline
2461 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2463 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2464 # Save some space
2465 rm -rf /var/cache/tazpkg/*
2466 rm -f /var/lib/tazpkg/*.bak
2467 rm -rf $DISTRO
2469 # Optionally remove sound card selection and screen resolution.
2470 if [ -z $LaunchedByTazpanel ]; then
2471 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2472 case $anser in
2473 y)
2474 action 'Removing current sound card and screen configurations...'
2475 rm -f /var/lib/sound-card-driver
2476 rm -f /var/lib/alsa/asound.state
2477 rm -f /etc/X11/xorg.conf ;;
2478 *)
2479 action 'Keeping current sound card and screen configurations...' ;;
2480 esac
2481 status
2482 newline
2484 # Optionally remove i18n settings
2485 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2486 case $anser in
2487 y)
2488 action 'Removing current locale/keymap settings...'
2489 newline > /etc/locale.conf
2490 newline > /etc/keymap.conf ;;
2491 *)
2492 action 'Keeping current locale/keymap settings...' ;;
2493 esac
2494 status
2495 fi
2497 # Clean-up files by default
2498 newline > /etc/udev/rules.d/70-persistent-net.rules
2499 newline > /etc/udev/rules.d/70-persistant-cd.rules
2501 # Create list of files including default user files since it is defined in /etc/passwd
2502 # and some new users might have been added.
2503 cd /
2504 echo 'init' > /tmp/list
2505 for dir in bin etc sbin var dev lib root usr home opt; do
2506 [ -d $dir ] && find $dir
2507 done >> /tmp/list
2509 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2510 [ -d $dir ] && echo $dir
2511 done >> /tmp/list
2513 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2515 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2516 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2517 #fi
2518 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2519 touch /var/log/wtmp
2521 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2522 sed -i "/var\/log\/$removelog/d" /tmp/list
2523 done
2525 # Generate initramfs with specified compression and display rootfs
2526 # size in realtime.
2527 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2529 write_initramfs &
2530 sleep 2
2531 cd - > /dev/null
2532 echo -en "\nFilesystem size:"
2533 while [ ! -f /tmp/rootfs ]; do
2534 sleep 1
2535 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2536 done
2537 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2538 echo -e "\n"
2539 rm -f /tmp/rootfs
2541 # Move freshly generated rootfs to the cdrom.
2542 mkdir -p $ROOTCD/boot
2543 mv -f /$INITRAMFS $ROOTCD/boot
2544 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2546 # Now we need the kernel and isolinux files.
2547 copy_from_cd() {
2548 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2549 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2550 unmeta_boot $ROOTCD
2551 umount /media/cdrom
2554 bootloader="$LOCALSTATE/installed/syslinux/volatile.cpio.gz"
2555 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2556 copy_from_cd;
2557 elif mount | grep /media/cdrom; then
2558 copy_from_cd;
2559 elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2560 cp $bootloader $ROOTCD
2561 cd $ROOTCD
2562 zcat volatile.cpio.gz | cpio -id
2563 rm -f volatile.cpio.gz
2564 [ -f /boot/*slitaz ] && \
2565 cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2566 [ -f /boot/*slitaz64 ] && \
2567 cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2568 else
2569 touch /tmp/.write-iso-error
2570 longline "When SliTaz is running in RAM the kernel and bootloader \
2571 files are kept on the CD-ROM. Please insert a Live CD or loop mount the \
2572 slitaz.iso to /media/cdrom (run # mount -o loop slitaz-rolling.iso /media/cdrom ) \
2573 or # (tazpkg -gi linux --forced) to let Tazlito copy the files."
2574 echo -en "----\nENTER to continue..."; read i
2575 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2576 copy_from_cd
2577 fi
2579 # Generate the iso image.
2580 touch /tmp/.write-iso
2581 newline
2582 cd $DISTRO
2583 _ 'Generating ISO image...'
2584 genisoimage -R -o $ISO_NAME.iso -b boot/isolinux/isolinux.bin \
2585 -c boot/isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
2586 -V "SliTaz" -p "$(id -un)" -input-charset utf-8 \
2587 -P "$(hostname)" -boot-info-table $ROOTCD
2588 if [ -x /usr/bin/isohybrid ]; then
2589 action 'Creating hybrid ISO/disk...'
2590 /usr/bin/isohybrid $ISO_NAME.iso -entry 2 2>/dev/null
2591 status
2592 fi
2593 if [ -x /usr/bin/iso2exe ]; then
2594 action 'Creating hybrid ISO/EXE...'
2595 /usr/bin/iso2exe $ISO_NAME.iso 2>/dev/null
2596 status
2597 fi
2598 action 'Creating the ISO md5sum...'
2599 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2600 status
2602 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2603 rm -f /tmp/.write-iso
2605 if [ -z $LaunchedByTazpanel ]; then
2606 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2607 case $anser in
2608 y)
2609 umount /dev/cdrom 2>/dev/null
2610 eject
2611 echo -n "Please insert a blank CD-ROM and press ENTER..."
2612 read i && sleep 2
2613 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2614 echo -en "----\nENTER to continue..."; read i ;;
2615 *)
2616 exit 0 ;;
2617 esac
2618 fi
2619 ;;
2622 burn-iso)
2623 # Guess CD-ROM device, ask user and burn the ISO.
2625 check_root
2626 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2627 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2628 # We can specify an alternative ISO from the cmdline.
2629 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2630 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2632 title 'Tazlito burn ISO'
2633 echo "CD-ROM device : /dev/$DRIVE_NAME"
2634 echo "Drive speed : $DRIVE_SPEED"
2635 echo "ISO image : $iso"
2636 footer
2638 case $(yesorno 'Burn ISO image?' 'n') in
2639 y)
2640 title 'Starting Wodim to burn the ISO...'
2641 sleep 2
2642 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2643 footer 'ISO image is burned to CD-ROM.'
2644 ;;
2645 *)
2646 die 'Exiting. No ISO burned.'
2647 ;;
2648 esac
2649 ;;
2652 merge)
2653 # Merge multiple rootfs into one iso.
2655 if [ -z "$2" ]; then
2656 cat <<EOT
2657 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2659 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2660 i.e: rootfsN is a subset of rootfsN-1
2661 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2662 The boot loader will select the rootfs according to the RAM size detected.
2664 Example:
2665 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
2667 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
2668 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
2670 EOT
2671 exit 2
2672 fi
2674 shift # skip merge
2675 append="$1 slitaz1"
2676 shift # skip size1
2677 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
2679 ISO=$1.merged
2681 # Extract filesystems
2682 action 'Mounting %s' "$1"
2683 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
2684 status || cleanup_merge
2686 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2687 make_bzImage_hardlink $TMP_DIR/iso/boot
2688 umount -d $TMP_DIR/mnt
2689 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
2690 _ '%s is already a merged iso. Aborting.' "$1"
2691 cleanup_merge
2692 fi
2693 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
2694 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
2695 if [ ! -f /boot/isolinux/ifmem.c32 -a
2696 ! -f /boot/isolinux/c32box.c32 ]; then
2697 cat <<EOT
2698 No file /boot/isolinux/ifmem.c32
2699 Please install syslinux package !
2700 EOT
2701 rm -rf $TMP_DIR
2702 exit 1
2703 fi
2704 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
2705 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
2706 fi
2708 action 'Extracting %s' 'iso/rootfs.gz'
2709 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
2710 [ -d $TMP_DIR/rootfs1/etc ]
2711 status || cleanup_merge
2713 n=1
2714 while [ -n "$2" ]; do
2715 shift # skip rootfs N-1
2716 p=$n
2717 n=$(($n + 1))
2718 append="$append $1 slitaz$n"
2719 shift # skip size N
2720 mkdir -p $TMP_DIR/rootfs$n
2722 action 'Extracting %s' "$1"
2723 extract_rootfs $1 $TMP_DIR/rootfs$n &&
2724 [ -d "$TMP_DIR/rootfs$n/etc" ]
2725 status || cleanup_merge
2727 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
2728 action 'Creating %s' "rootfs$p.gz"
2729 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
2730 status
2731 done
2732 action 'Creating %s' "rootfs$n.gz"
2733 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
2734 status
2735 rm -f $TMP_DIR/iso/boot/rootfs.gz
2736 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
2737 create_iso $ISO $TMP_DIR/iso
2738 rm -rf $TMP_DIR
2739 ;;
2742 repack)
2743 # Repack an iso with maximum lzma compression ratio.
2745 ISO=$2
2746 mkdir -p $TMP_DIR/mnt
2748 # Extract filesystems
2749 action 'Mounting %s' "$ISO"
2750 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
2751 status || cleanup_merge
2753 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2754 umount -d $TMP_DIR/mnt
2756 for i in $TMP_DIR/iso/boot/rootfs* ; do
2757 action 'Repacking %s' "$(basename $i)"
2758 (zcat $i 2>/dev/null || unlzma < $i || cat $i) 2>/dev/null > $TMP_DIR/rootfs
2759 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
2760 align_to_32bits $i
2761 status
2762 done
2764 create_iso $ISO $TMP_DIR/iso
2765 rm -rf $TMP_DIR
2766 ;;
2769 build-loram)
2770 # Build a Live CD for low RAM systems.
2772 ISO="$2"
2773 OUTPUT="$3"
2774 [ -z "$3" ] && \
2775 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
2776 mkdir -p "$TMP_DIR/iso"
2777 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
2778 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$ISO$/!d;s/:.*//;q")
2779 if ! check_iso_for_loram ; then
2780 umount -d "$TMP_DIR/iso"
2781 die "$ISO is not a valid SliTaz live CD. Abort."
2782 fi
2783 case "$4" in
2784 cdrom) build_loram_cdrom ;;
2785 http) build_loram_http ;;
2786 *) build_loram_ram ;;
2787 esac
2788 umount $TMP_DIR/iso # no -d: needs /proc
2789 losetup -d $loopdev
2790 rm -rf $TMP_DIR
2791 ;;
2794 emu-iso)
2795 # Emulate an ISO image with Qemu.
2796 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2797 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
2798 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
2799 echo -e "\nStarting Qemu emulator:\n"
2800 echo -e "qemu $QEMU_OPTS $iso\n"
2801 qemu $QEMU_OPTS $iso
2802 ;;
2805 deduplicate)
2806 # Deduplicate files in a tree
2807 shift
2808 deduplicate "$@"
2809 ;;
2812 usage|*)
2813 # Print usage also for all unknown commands.
2814 usage
2815 ;;
2816 esac
2818 exit 0