tazlito view tazlito @ rev 418

tazlito: setup_mirrors(): fix creating mirrors in the case of using in chroot
author Aleksej Bobylev <al.bobylev@gmail.com>
date Mon Mar 14 14:13:11 2016 +0200 (2016-03-14)
parents 9d0d7bf20e90
children b6fd50633850
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 ] &&
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=)
1287 local mirrorlist="$1" fresh repacked
1288 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1290 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1291 restore_mirrors
1293 _ 'Setting up mirrors for %s...' "$root/"
1294 # Backing up current undigest mirrors and priority
1295 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1296 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1297 rm -rf '/var/www/tazlito/'
1298 mkdir -p '/var/www/tazlito/'
1300 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1301 fresh='/home/slitaz/packages'
1302 if [ -d "$fresh" ]; then
1303 # Setup first undigest mirror
1304 mkdir -p "$undigest/fresh"
1305 echo "$fresh" > "$undigest/fresh/mirror"
1306 echo 'fresh' >> "$priority"
1307 # Rebuild mirror DB if needed
1308 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1309 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1310 tazpkg mkdb "$fresh" --forced --root=''
1311 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1312 fi
1314 # Repacked packages: high priority
1315 repacked="$PACKAGES_REPOSITORY"
1316 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1317 # According to Tazlito setup file (tazlito.conf):
1318 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1319 # or
1320 # WORK_DIR="/home/slitaz"
1321 # and
1322 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1323 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1325 # Setup second undigest mirror
1326 mkdir -p "$undigest/repacked"
1327 echo "$repacked" > "$undigest/repacked/mirror"
1328 echo 'repacked' >> "$priority"
1329 # Rebuild mirror DB if needed
1330 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1331 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1332 tazpkg mkdb "$repacked" --forced --root=''
1333 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1334 fi
1336 # All repositories listed in mirrors list: normal priority
1337 [ -e "$mirrorlist" ] && \
1338 while read mirror; do
1339 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1340 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1341 mkdir -p "$undigest/$mirrorid"
1342 echo "$mirror" > "$undigest/$mirrorid/mirror"
1343 echo "$mirrorid" >> "$priority"
1344 done < "$mirrorlist"
1346 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1348 # Show list of mirrors
1349 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1350 function show(num, name, url) {
1351 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1354 num++;
1355 "cat " db "/undigest/" $0 "/mirror" | getline url;
1356 show(num, $0, url);
1358 END {
1359 num++;
1360 "cat " db "/mirror" | getline url;
1361 show(num, "main", url);
1362 }' "$priority"
1364 tazpkg recharge --quiet >/dev/null
1368 # Get list of 'packages.info' lists using priority
1370 pi_lists() {
1371 local pi
1372 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1373 local priority="$root$LOCALSTATE/priority"
1374 local undigest="$root$LOCALSTATE/undigest"
1377 [ -s "$priority" ] && cat "$priority"
1378 echo 'main'
1379 [ -d "$undigest" ] && ls "$undigest"
1380 } | awk -vun="$undigest/" '
1382 if (arr[$0] != 1) {
1383 arr[$0] = 1;
1384 print un $0 "/packages.info";
1386 }' | sed 's|/undigest/main||' | \
1387 while read pi; do
1388 [ -e "$pi" ] && echo "$pi"
1389 done
1393 # Strip versions from packages list
1395 strip_versions() {
1396 action 'Strip versions from list %s...' "$(basename "$1")"
1397 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1398 [ -f "$in_list" ] || die "List '$in_list' not found."
1400 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1401 awk '
1403 if (FILENAME ~ "packages.info") {
1404 # Collect package names
1405 FS = "\t"; pkg[$1] = 1;
1406 } else {
1407 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1408 while (NF > 1 && ! pkg[$0])
1409 NF --;
1410 printf "%s\n", $0;
1412 }' $(pi_lists) "$in_list" > "$tmp_list"
1414 cat "$tmp_list" > "$in_list"
1415 rm "$tmp_list"
1416 status
1420 # Display list of unknown packages (informative)
1422 display_unknown() {
1423 [ -s "$1" ] || return
1424 echo "Unknown packages:" >&2
1425 cat "$1" >&2
1426 rm "$1"
1430 # Display warnings about critical packages absent (informative)
1432 display_warn() {
1433 [ -s "$1" ] || return
1434 echo "Absent critical packages:" >&2
1435 cat "$1" >&2
1436 rm "$1"
1437 echo "Probably ISO image will be unusable."
1441 # Install packages to rootfs
1443 install_list_to_rootfs() {
1444 local list="$1" rootfs="$2" pkg i ii
1445 local undigest="$rootfs/var/lib/tazpkg/undigest"
1447 # initial tazpkg setup in empty rootfs
1448 tazpkg --root=$rootfs >/dev/null 2>&1
1449 # link rootfs packages cache to the regular packages cache
1450 rm -r "$rootfs/var/cache/tazpkg"
1451 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1453 setup_mirrors mirrors
1455 # Just in case if flavor not contains "tazlito" package
1456 mkdir -p "$rootfs/etc/tazlito"
1458 newline
1459 for pkg in $(cat $list); do
1460 action 'Installing package: %s' "$pkg"
1461 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1462 status
1463 done
1464 newline
1466 restore_mirrors
1467 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1468 for i in fresh repacked; do
1469 ii="$undigest/$i"
1470 [ -d "$ii" ] && rm -rf "$ii"
1471 ii="$rootfs/var/lib/tazpkg/priority"
1472 if [ -f "$ii" ]; then
1473 sed -i "/$i/d" "$ii"
1474 [ -s "$ii" ] || rm "$ii"
1475 fi
1476 done
1477 [ -d "$undigest" ] && \
1478 for i in $(find "$undigest" -type f); do
1479 # Remove all undigest PKGDB files but 'mirror'
1480 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1481 done
1482 [ -d "$undigest" ] && \
1483 rmdir --ignore-fail-on-non-empty "$undigest"
1485 # Un-link packages cache
1486 rm "$rootfs/var/cache/tazpkg"
1488 # Clean /var/lib/tazpkg
1489 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1495 ####################
1496 # Tazlito commands #
1497 ####################
1499 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1500 case "$0" in
1501 *reduplicate)
1502 find ${@:-.} ! -type d -links +1 \
1503 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1504 exit 0 ;;
1505 *deduplicate)
1506 deduplicate "$@"
1507 exit 0 ;;
1508 esac
1511 case "$COMMAND" in
1512 stats)
1513 # Tazlito general statistics from the config file.
1515 title 'Tazlito statistics'
1516 optlist "\
1517 Config file : $CONFIG_FILE
1518 ISO name : $ISO_NAME.iso
1519 Volume name : $VOLUM_NAME
1520 Prepared : $PREPARED
1521 Packages repository : $PACKAGES_REPOSITORY
1522 Distro directory : $DISTRO
1523 Additional files : $ADDFILES
1524 " | sed '/: $/d'
1525 footer
1526 ;;
1529 list-addfiles)
1530 # Simple list of additional files in the rootfs
1531 newline
1532 if [ -d "$ADDFILES/rootfs" ]; then
1533 cd $ADDFILES
1534 find rootfs -type f
1535 else
1536 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1537 fi
1538 newline
1539 ;;
1542 gen-config)
1543 # Generate a new config file in the current dir or the specified
1544 # directory by $2.
1546 if [ -n "$2" ]; then
1547 mkdir -p "$2" && cd "$2"
1548 fi
1550 newline
1551 action 'Generating empty tazlito.conf...'
1552 empty_config_file
1553 status
1555 separator
1556 if [ -f 'tazlito.conf' ] ; then
1557 _ 'Configuration file is ready to edit.'
1558 _ 'File location: %s' "$(pwd)/tazlito.conf"
1559 newline
1560 fi
1561 ;;
1564 configure)
1565 # Configure a tazlito.conf config file. Start by getting
1566 # a empty config file and sed it.
1568 if [ -f 'tazlito.conf' ]; then
1569 rm tazlito.conf
1570 else
1571 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1572 'or in the same directory of the file you want to configure.'
1573 cd /etc
1574 fi
1576 empty_config_file
1578 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1580 # ISO name.
1581 echo -n "ISO name : " ; read answer
1582 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1583 # Volume name.
1584 echo -n "Volume name : " ; read answer
1585 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1586 # Packages repository.
1587 echo -n "Packages repository : " ; read answer
1588 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1589 # Distro path.
1590 echo -n "Distro path : " ; read answer
1591 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1592 footer "Config file is ready to use."
1593 echo 'You can now extract an ISO or generate a distro.'
1594 newline
1595 ;;
1598 gen-iso)
1599 # Simply generate a new iso.
1601 check_root
1602 verify_rootcd
1603 gen_livecd_isolinux
1604 distro_stats
1605 ;;
1608 gen-initiso)
1609 # Simply generate a new initramfs with a new iso.
1611 check_root
1612 verify_rootcd
1613 gen_initramfs "$ROOTFS"
1614 gen_livecd_isolinux
1615 distro_stats
1616 ;;
1619 extract-distro)
1620 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1622 check_root
1623 ISO_IMAGE="$2"
1624 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1625 'Example:\n tazlito image.iso /path/target'
1627 # Set the distro path by checking for $3 on cmdline.
1628 TARGET="${3:-$DISTRO}"
1630 # Exit if existing distro is found.
1631 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1632 'Please clean the distro tree or change directory path.'
1634 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
1636 # Start to mount the ISO.
1637 action 'Mounting ISO image...'
1638 mkdir -p "$TMP_DIR"
1639 # Get ISO file size.
1640 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
1641 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
1642 sleep 2
1643 # Prepare target dir, copy the kernel and the rootfs.
1644 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
1645 status
1647 action 'Copying the Linux kernel...'
1648 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
1649 make_bzImage_hardlink "$TARGET/rootcd/boot"
1650 else
1651 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
1652 fi
1653 status
1655 for i in $(ls $TMP_DIR); do
1656 [ "$i" == 'boot' ] && continue
1657 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
1658 done
1660 for loader in isolinux syslinux extlinux grub; do
1661 [ -d "$TMP_DIR/boot/$loader" ] || continue
1662 action 'Copying %s files...' "$loader"
1663 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
1664 status
1665 done
1667 action 'Copying the rootfs...'
1668 cp $TMP_DIR/boot/rootfs.?z "$TARGET/rootcd/boot"
1669 status
1671 # Extract initramfs.
1672 cd "$TARGET/rootfs"
1673 action 'Extracting the rootfs...'
1674 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
1675 # unpack /usr
1676 for i in etc/tazlito/*.extract; do
1677 [ -f "$i" ] && . $i ../rootcd
1678 done
1679 # Umount and remove temp directory and cd to $TARGET to get stats.
1680 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
1681 cd ..
1682 status
1684 newline
1685 separator
1686 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
1687 echo "Distro tree : $(pwd)"
1688 echo "Rootfs size : $(du -sh rootfs)"
1689 echo "Rootcd size : $(du -sh rootcd)"
1690 footer
1691 ;;
1694 list-flavors)
1695 # Show available flavors.
1696 local list='/etc/tazlito/flavors.list'
1697 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
1698 title 'List of flavors'
1699 cat $list
1700 footer
1701 ;;
1704 show-flavor)
1705 # Show flavor description.
1706 set -e
1707 flavor=${2%.flavor}
1708 flv_dir="$(extract_flavor "$flavor")"
1709 desc="$flv_dir/$flavor.desc"
1710 if [ -n "$brief" ]; then
1711 if [ -z "$noheader" ]; then
1712 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
1713 separator
1714 fi
1715 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
1716 "$(field ISO "$desc")" \
1717 "$(field Rootfs "$desc")" \
1718 "$(field Description "$desc")"
1719 else
1720 separator
1721 cat "$desc"
1722 fi
1723 cleanup
1724 ;;
1727 gen-liveflavor)
1728 # Generate a new flavor from the live system.
1729 FLAVOR=${2%.flavor}
1730 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1732 case "$FLAVOR" in
1733 -?|-h*|--help)
1734 cat <<EOT
1735 SliTaz Live Tool - Version: $VERSION
1737 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
1739 $(boldify '<flavor-patch-file> format:')
1740 $(optlist "\
1741 code data
1742 + package to add
1743 - package to remove
1744 ! non-free package to add
1745 ? display message
1746 @ flavor description
1747 ")
1749 $(boldify 'Example:')
1750 $(optlist "\
1751 @ Developer tools for SliTaz maintainers
1752 + slitaz-toolchain
1753 + mercurial
1754 ")
1755 EOT
1756 exit 1
1757 ;;
1758 esac
1759 mv /etc/tazlito/distro-packages.list \
1760 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
1761 rm -f distro-packages.list non-free.list 2>/dev/null
1762 tazpkg recharge
1764 DESC=""
1765 [ -n "$3" ] && \
1766 while read action pkg; do
1767 case "$action" in
1768 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
1769 -) yes | tazpkg remove $pkg ;;
1770 !) echo $pkg >> non-free.list ;;
1771 @) DESC="$pkg" ;;
1772 \?) echo -en "$pkg"; read action ;;
1773 esac
1774 done < $3
1776 yes '' | tazlito gen-distro
1777 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
1778 mv /etc/tazlito/distro-packages.list.$$ \
1779 /etc/tazlito/distro-packages.list 2>/dev/null
1780 ;;
1783 gen-flavor)
1784 # Generate a new flavor from the last ISO image generated
1785 FLAVOR=${2%.flavor}
1786 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1788 title 'Flavor generation'
1789 check_rootfs
1790 FILES="$FLAVOR.pkglist"
1792 action 'Creating file %s...' "$FLAVOR.flavor"
1793 for i in rootcd rootfs; do
1794 if [ -d "$ADDFILES/$i" ] ; then
1795 FILES="$FILES\n$FLAVOR.$i"
1796 (cd "$ADDFILES/$i"; find . | cpio -o -H newc 2>/dev/null | gzip -9) > $FLAVOR.$i
1797 fi
1798 done
1799 status
1801 answer=$(grep -s ^Description $FLAVOR.desc)
1802 answer=${answer#Description : }
1803 if [ -z "$answer" ]; then
1804 echo -n "Description: "
1805 read answer
1806 fi
1808 action 'Compressing flavor %s...' "$FLAVOR"
1809 echo "Flavor : $FLAVOR" > $FLAVOR.desc
1810 echo "Description : $answer" >> $FLAVOR.desc
1811 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
1812 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
1813 for i in $(ls $ROOTFS$INSTALLED); do
1814 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
1815 EXTRAVERSION=""
1816 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
1817 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
1818 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
1819 echo "$i" >> $FLAVOR.nonfree
1820 else
1821 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
1822 fi
1823 done
1824 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
1825 for i in $LOCALSTATE/undigest/*/mirror ; do
1826 [ -s $i ] && cat $i >> $FLAVOR.mirrors
1827 done
1828 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
1829 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | gzip -9 > $FLAVOR.flavor
1830 rm $(echo -e $FILES)
1831 status
1833 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
1834 ;;
1837 upgrade-flavor)
1838 # Strip versions from pkglist and update estimated numbers in flavor.desc
1839 flavor="${2%.flavor}"
1840 set -e
1841 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1842 set +e
1844 flv_dir="$(extract_flavor "$flavor")"
1846 strip_versions "$flv_dir/$flavor.pkglist"
1848 action 'Updating %s...' "$flavor.desc"
1850 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
1851 set -- $(module calc_sizes "$flv_dir" "$flavor")
1852 restore_mirrors >/dev/null
1854 sed -i -e '/Image is ready/d' \
1855 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
1856 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
1857 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
1858 -e "s|\(Packages *:\).*$|\1 $4|" \
1859 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
1860 "$flv_dir/$flavor.desc"
1862 pack_flavor "$flv_dir" "$flavor"
1863 status
1864 display_unknown "$flv_dir/err"
1865 display_warn "$flv_dir/warn"
1866 cleanup
1867 ;;
1870 extract-flavor)
1871 # Extract a flavor into $FLAVORS_REPOSITORY
1872 flavor="${2%.flavor}"
1873 set -e
1874 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1875 set +e
1877 action 'Extracting %s...' "$flavor.flavor"
1878 flv_dir="$(extract_flavor "$flavor" full)"
1879 storage="$FLAVORS_REPOSITORY/$flavor"
1881 rm -rf "$storage" 2>/dev/null
1882 mkdir -p "$storage"
1883 cp -a "$flv_dir"/* "$storage"
1884 rm "$storage/description"
1885 status
1887 strip_versions "$storage/packages.list"
1889 cleanup
1890 ;;
1893 pack-flavor)
1894 # Create a flavor from $FLAVORS_REPOSITORY.
1895 flavor=${2%.flavor}
1896 storage="$FLAVORS_REPOSITORY/$flavor"
1898 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
1900 action 'Creating flavor %s...' "$flavor"
1901 tmp_dir="$(mktemp -d)"
1903 while read from to; do
1904 [ -s "$storage/$from" ] || continue
1905 cp -a "$storage/$from" "$tmp_dir/$to"
1906 done <<EOT
1907 mirrors $flavor.mirrors
1908 distro.sh $flavor-distro.sh
1909 receipt $flavor.receipt
1910 non-free.list $flavor.nonfree
1911 EOT
1913 # Build the package list.
1914 # It can include a list from another flavor with the keyword @include
1915 if [ -s "$storage/packages.list" ]; then
1916 include=$(grep '^@include' "$storage/packages.list")
1917 if [ -n "$include" ]; then
1918 include=${include#@include }
1919 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
1920 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
1921 else
1922 echo -e "\nERROR: Can't find include package list from $include\n"
1923 fi
1924 fi
1925 # Generate the final/initial package list
1926 [ -s "$storage/packages.list" ] && \
1927 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
1928 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
1929 fi
1931 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
1932 # Process multi-rootfs flavor
1933 . "$storage/receipt"
1934 set -- $ROOTFS_SELECTION
1935 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
1936 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
1937 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
1939 for i in rootcd rootfs; do
1940 mkdir "$tmp_dir/$i"
1941 # Copy extra files from the first flavor
1942 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
1943 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
1944 # Overload extra files by meta flavor
1945 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
1946 [ -n "$(ls $tmp_dir/$i)" ] &&
1947 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
1948 gzip -9 > "$tmp_dir/$flavor.$i"
1949 rm -rf "$tmp_dir/$i"
1950 done
1951 else
1952 # Process plain flavor
1953 for i in rootcd rootfs; do
1954 [ -d "$storage/$i" ] || continue
1955 (cd "$storage/$i";
1956 find . | cpio -o -H newc 2>/dev/null) | gzip -9 > "$tmp_dir/$flavor.$i"
1957 done
1958 fi
1960 unset VERSION MAINTAINER ROOTFS_SELECTION
1961 set -- $(module calc_sizes "$tmp_dir" "$flavor")
1962 ROOTFS_SIZE="$1 (estimated)"
1963 INITRAMFS_SIZE="$2 (estimated)"
1964 ISO_SIZE="$3 (estimated)"
1965 PKGNUM="$4"
1966 . "$storage/receipt"
1968 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
1969 Flavor : $FLAVOR
1970 Description : $SHORT_DESC
1971 Version : $VERSION
1972 Maintainer : $MAINTAINER
1973 LiveCD RAM size : $FRUGAL_RAM
1974 Rootfs list : $ROOTFS_SELECTION
1975 Build date : $(date '+%Y%m%d at %T')
1976 Packages : $PKGNUM
1977 Rootfs size : $ROOTFS_SIZE
1978 Initramfs size : $INITRAMFS_SIZE
1979 ISO image size : $ISO_SIZE
1980 ================================================================================
1982 EOT
1984 rm -f $tmp_dir/packages.list
1985 pack_flavor "$tmp_dir" "$flavor"
1986 status
1987 display_unknown "$tmp_dir/err"
1988 display_warn "$flv_dir/warn"
1989 cleanup
1990 ;;
1993 get-flavor)
1994 # Get a flavor's files and prepare for gen-distro.
1995 flavor=${2%.flavor}
1996 title 'Preparing %s distro flavor' "$flavor"
1997 set -e
1998 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1999 set +e
2001 action 'Cleaning %s...' "$DISTRO"
2002 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2003 # Clean old files
2004 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2005 [ -f "$i" ] && rm "$i"
2006 done
2007 mkdir -p "$DISTRO"
2008 status
2010 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2012 action 'Extracting flavor %s...' "$flavor.flavor"
2013 flv_dir="$(extract_flavor "$flavor" info)"
2014 cp -a "$flv_dir"/* .
2015 mv packages.list distro-packages.list
2016 mv -f info /etc/tazlito
2017 status
2019 for i in rootcd rootfs; do
2020 if [ -d "$i" ]; then
2021 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2022 fi
2023 done
2025 rm -f /etc/tazlito/rootfs.list
2026 grep -q '^Rootfs list' description &&
2027 grep '^Rootfs list' description | sed 's/.*: \(.*\)$/\1/' > /etc/tazlito/rootfs.list
2029 action 'Updating %s...' 'tazlito.conf'
2030 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2031 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2032 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2033 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2034 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2035 status
2037 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2038 cleanup
2039 ;;
2042 iso2flavor)
2043 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2044 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2046 FLAVOR=${3%.flavor}
2047 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2048 mount -o loop,ro $2 $TMP_DIR/iso
2049 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2050 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2051 ! -s $TMP_DIR/flavor/*.desc ]; then
2052 _ 'META flavors are not supported.'
2053 umount -d $TMP_DIR/iso
2054 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2055 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2056 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2057 umount -d $TMP_DIR/iso
2058 else
2059 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*gz); do
2060 ( zcat < $i || unlzma < $i ) | \
2061 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2062 done
2063 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2064 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2065 '/etc/slitaz-release' '/boot/rootfs.gz'
2066 umount -d $TMP_DIR/iso
2067 else
2068 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2069 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2070 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2071 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2072 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2073 umount -d $TMP_DIR/iso
2074 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2075 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2076 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2077 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2078 < $TMP_DIR/rootfs$INSTALLED.md5
2079 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2080 if [ -s $TMP_DIR/flavor/*desc ]; then
2081 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2082 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2083 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2084 for i in rootfs rootcd ; do
2085 [ -s $TMP_DIR/flavor/*.list$i ] &&
2086 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2087 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | gzip -9 > $TMP_DIR/$FLAVOR.$i
2088 done
2089 else
2090 find_flavor_rootfs $TMP_DIR/rootfs
2091 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2092 for i in rootfs rootcd ; do
2093 [ "$(ls $TMP_DIR/$i)" ] &&
2094 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | gzip -9 > "$TMP_DIR/$FLAVOR.$i"
2095 done
2096 unset VERSION MAINTAINER
2097 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2098 if [ -n "$DESCRIPTION" ]; then
2099 _n 'Flavor version : '; read -t 30 VERSION
2100 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2101 fi
2103 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2104 Flavor : $FLAVOR
2105 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2106 Version : ${VERSION:-1.0}
2107 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2108 LiveCD RAM size : $RAM_SIZE
2109 Build date : $BUILD_DATE
2110 Packages : $PKGCNT
2111 Rootfs size : $ROOTFS_SIZE
2112 Initramfs size : $INITRAMFS_SIZE
2113 ISO image size : $ISO_SIZE
2114 ================================================================================
2116 EOT
2117 longline "Tazlito can't detect each file installed during \
2118 a package post_install. You should extract this flavor (tazlito extract-flavor \
2119 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2120 tree and remove files generated by post_installs.
2121 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2122 repack the flavor (tazlito pack-flavor $FLAVOR)"
2123 fi
2124 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | gzip -9 > $FLAVOR.flavor
2125 fi
2126 fi
2127 rm -rf $TMP_DIR
2128 ;;
2131 gen-distro)
2132 # Generate a live distro tree with a set of packages.
2134 check_root
2135 start_time=$(date +%s)
2137 # Tazlito options: --iso or --cdrom
2138 CDROM=''
2139 [ -n "$iso" ] && CDROM="-o loop $iso"
2140 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2142 # Check if a package list was specified on cmdline.
2143 if [ -f "$2" ]; then
2144 LIST_NAME="$2"
2145 else
2146 LIST_NAME='distro-packages.list'
2147 fi
2149 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2150 'Please clean the distro tree or change directory path.'
2151 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2152 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2154 # If list not given: build list with all installed packages
2155 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2156 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2157 fi
2159 # Exit if no list name.
2160 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2162 # Start generation.
2163 title 'Tazlito generating a distro'
2165 # Misc checks
2166 mkdir -p "$PACKAGES_REPOSITORY"
2167 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2168 newline
2170 # Mount CD-ROM to be able to repack boot-loader packages
2171 if [ ! -e /boot -a -n "$CDROM" ]; then
2172 mkdir $TMP_MNT
2173 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2174 ln -s "$TMP_MNT/boot" /
2175 if [ ! -d "$ADDFILES/rootcd" ] ; then
2176 mkdir -p "$ADDFILES/rootcd"
2177 for i in $(ls $TMP_MNT); do
2178 [ "$i" == 'boot' ] && continue
2179 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2180 done
2181 fi
2182 else
2183 rmdir "$TMP_MNT"
2184 fi
2185 fi
2187 # Rootfs stuff.
2188 echo 'Preparing the rootfs directory...'
2189 mkdir -p "$ROOTFS"
2190 export root="$ROOTFS"
2191 strip_versions "$LIST_NAME"
2193 if [ "$REPACK" == 'y' ]; then
2194 # Determine full packages list with all dependencies
2195 tmp_dir="$(mktemp -d)"
2196 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2197 touch "$tmp_dir/full.pkglist"
2198 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2200 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2201 while read pkgname pkgver; do
2202 # Is package in full list?
2203 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2204 # Is package already repacked?
2205 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2206 _ 'Repacking %s...' "$pkgname-$pkgver"
2207 tazpkg repack "$pkgname" --quiet
2208 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2209 status
2210 done
2212 rm -r "$tmp_dir"
2213 fi
2215 if [ -f non-free.list ]; then
2216 # FIXME: working in the ROOTFS chroot?
2217 newline
2218 echo 'Preparing non-free packages...'
2219 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2220 for pkg in $(cat 'non-free.list'); do
2221 if [ ! -d "$INSTALLED/$pkg" ]; then
2222 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2223 tazpkg get-install get-$pkg
2224 fi
2225 get-$pkg "$ROOTFS"
2226 fi
2227 tazpkg repack $pkg
2228 pkg=$(ls $pkg*.tazpkg)
2229 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2230 mv $pkg $PACKAGES_REPOSITORY
2231 done
2232 fi
2233 cp $LIST_NAME $DISTRO/distro-packages.list
2234 newline
2236 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2238 cd $DISTRO
2239 cp distro-packages.list $ROOTFS/etc/tazlito
2240 # Copy all files from $ADDFILES/rootfs to the rootfs.
2241 if [ -d "$ADDFILES/rootfs" ] ; then
2242 action 'Copying addfiles content to the rootfs...'
2243 cp -a $ADDFILES/rootfs/* $ROOTFS
2244 status
2245 fi
2247 action 'Root filesystem is generated...'; status
2249 # Root CD part.
2250 action 'Preparing the rootcd directory...'
2251 mkdir -p $ROOTCD
2252 status
2254 # Move the boot dir with the Linux kernel from rootfs.
2255 # The boot dir goes directly on the CD.
2256 if [ -d "$ROOTFS/boot" ] ; then
2257 action 'Moving the boot directory...'
2258 mv $ROOTFS/boot $ROOTCD
2259 cd $ROOTCD/boot
2260 make_bzImage_hardlink
2261 status
2262 fi
2263 cd $DISTRO
2264 # Copy all files from $ADDFILES/rootcd to the rootcd.
2265 if [ -d "$ADDFILES/rootcd" ] ; then
2266 action 'Copying addfiles content to the rootcd...'
2267 cp -a $ADDFILES/rootcd/* $ROOTCD
2268 status
2269 fi
2270 # Execute the distro script used to perform tasks in the rootfs
2271 # before compression. Give rootfs path in arg
2272 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2273 if [ -x "$DISTRO_SCRIPT" ]; then
2274 echo 'Executing distro script...'
2275 sh $DISTRO_SCRIPT $DISTRO
2276 fi
2278 # Execute the custom_rules() found in receipt.
2279 if [ -s "$TOP_DIR/receipt" ]; then
2280 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2281 echo -e "Executing: custom_rules()\n"
2282 . "$TOP_DIR/receipt"
2283 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2284 fi
2285 fi
2287 # Multi-rootfs
2288 if [ -s /etc/tazlito/rootfs.list ]; then
2290 FLAVOR_LIST="$(awk '{
2291 for (i = 2; i <= NF; i+=2)
2292 printf "%s ", i;
2293 }' /etc/tazlito/rootfs.list)"
2295 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2296 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2297 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2299 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2300 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2301 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2302 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2304 n=0
2305 last=$ROOTFS
2306 while read flavor; do
2307 n=$(($n+1))
2308 newline
2309 boldify "Building $flavor rootfs..."
2311 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2312 cp "$TOP_DIR/$flavor.flavor" .
2314 if [ ! -s "$flavor.flavor" ]; then
2315 # We may have it in $FLAVORS_REPOSITORY
2316 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2317 tazlito pack-flavor $flavor
2318 else
2319 download $flavor.flavor
2320 fi
2321 fi
2323 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2324 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2325 sed 's/.*/&.tazpkg/' < $flavor.pkglist > $DISTRO/list-packages0$n
2326 status
2328 mkdir ${ROOTFS}0$n
2329 export root="${ROOTFS}0$n"
2330 strip_versions "$DISTRO/list-packages0$n"
2332 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2334 rm -rf ${ROOTFS}0$n/boot
2336 cd $DISTRO
2337 if [ -s $flavor.rootfs ]; then
2338 _n 'Adding %s rootfs extra files...' "$flavor"
2339 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2340 fi
2342 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2343 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2344 status
2346 rm -f $flavor.flavor install-list
2347 mergefs ${ROOTFS}0$n $last
2348 last=${ROOTFS}0$n
2349 done <<EOT
2350 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2351 EOT
2352 #'
2353 i=$(($n+1))
2354 while [ $n -gt 0 ]; do
2355 mv ${ROOTFS}0$n ${ROOTFS}$i
2356 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2357 gen_initramfs ${ROOTFS}$i
2358 n=$(($n-1))
2359 i=$(($i-1))
2360 done
2361 mv $ROOTFS ${ROOTFS}$i
2362 gen_initramfs ${ROOTFS}$i
2363 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2364 else
2365 # Initramfs and ISO image stuff.
2366 gen_initramfs $ROOTFS
2367 fi
2368 gen_livecd_isolinux
2369 distro_stats
2370 cleanup
2371 ;;
2374 clean-distro)
2375 # Remove old distro tree.
2377 check_root
2378 title 'Cleaning: %s' "$DISTRO"
2379 if [ -d "$DISTRO" ] ; then
2380 if [ -d "$ROOTFS" ] ; then
2381 action 'Removing the rootfs...'
2382 rm -f $DISTRO/$INITRAMFS
2383 rm -rf $ROOTFS
2384 status
2385 fi
2386 if [ -d "$ROOTCD" ] ; then
2387 action 'Removing the rootcd...'
2388 rm -rf $ROOTCD
2389 status
2390 fi
2391 action 'Removing eventual ISO image...'
2392 rm -f $DISTRO/$ISO_NAME.iso
2393 rm -f $DISTRO/$ISO_NAME.md5
2394 status
2395 fi
2396 footer
2397 ;;
2400 check-distro)
2401 # Check for a few LiveCD needed files not installed by packages.
2403 # TODO: Remove this function.
2404 # First two files are maintained by tazpkg while it runs on rootfs,
2405 # while last one file should be maintained by tazlito itself.
2406 check_rootfs
2407 title 'Checking distro: %s' "$ROOTFS"
2408 # SliTaz release info.
2409 rel='/etc/slitaz-release'
2410 if [ ! -f "$ROOTFS$rel" ]; then
2411 _ 'Missing release info: %s' "$rel"
2412 else
2413 action 'Release : %s' "$(cat $ROOTFS$rel)"
2414 status
2415 fi
2416 # Tazpkg mirror.
2417 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2418 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2419 todomsg
2420 else
2421 action 'Mirror configuration exists...'
2422 status
2423 fi
2424 # Isolinux msg
2425 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2426 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2427 todomsg
2428 else
2429 action 'Isolinux message seems good...'
2430 status
2431 fi
2432 footer
2433 ;;
2436 writeiso)
2437 # Writefs to ISO image including /home unlike gen-distro we don't use
2438 # packages to generate a rootfs, we build a compressed rootfs with all
2439 # the current filesystem similar to 'tazusb writefs'.
2441 DISTRO='/home/slitaz/distro'
2442 ROOTCD="$DISTRO/rootcd"
2443 COMPRESSION="${2:-none}"
2444 ISO_NAME="${3:-slitaz}"
2445 check_root
2446 # Start info
2447 title 'Write filesystem to ISO'
2448 longline "The command writeiso will write the current filesystem into a \
2449 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2450 newline
2451 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2453 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2454 # Save some space
2455 rm -rf /var/cache/tazpkg/*
2456 rm -f /var/lib/tazpkg/*.bak
2457 rm -rf $DISTRO
2459 # Optionally remove sound card selection and screen resolution.
2460 if [ -z $LaunchedByTazpanel ]; then
2461 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2462 case $anser in
2463 y)
2464 action 'Removing current sound card and screen configurations...'
2465 rm -f /var/lib/sound-card-driver
2466 rm -f /var/lib/alsa/asound.state
2467 rm -f /etc/X11/xorg.conf ;;
2468 *)
2469 action 'Keeping current sound card and screen configurations...' ;;
2470 esac
2471 status
2472 newline
2474 # Optionally remove i18n settings
2475 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2476 case $anser in
2477 y)
2478 action 'Removing current locale/keymap settings...'
2479 newline > /etc/locale.conf
2480 newline > /etc/keymap.conf ;;
2481 *)
2482 action 'Keeping current locale/keymap settings...' ;;
2483 esac
2484 status
2485 fi
2487 # Clean-up files by default
2488 newline > /etc/udev/rules.d/70-persistent-net.rules
2489 newline > /etc/udev/rules.d/70-persistant-cd.rules
2491 # Create list of files including default user files since it is defined in /etc/passwd
2492 # and some new users might have been added.
2493 cd /
2494 echo 'init' > /tmp/list
2495 for dir in bin etc sbin var dev lib root usr home opt; do
2496 [ -d $dir ] && find $dir
2497 done >> /tmp/list
2499 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2500 [ -d $dir ] && echo $dir
2501 done >> /tmp/list
2503 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2505 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2506 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2507 #fi
2508 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2509 touch /var/log/wtmp
2511 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2512 sed -i "/var\/log\/$removelog/d" /tmp/list
2513 done
2515 # Generate initramfs with specified compression and display rootfs
2516 # size in realtime.
2517 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2519 write_initramfs &
2520 sleep 2
2521 cd - > /dev/null
2522 echo -en "\nFilesystem size:"
2523 while [ ! -f /tmp/rootfs ]; do
2524 sleep 1
2525 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2526 done
2527 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2528 echo -e "\n"
2529 rm -f /tmp/rootfs
2531 # Move freshly generated rootfs to the cdrom.
2532 mkdir -p $ROOTCD/boot
2533 mv -f /$INITRAMFS $ROOTCD/boot
2534 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2536 # Now we need the kernel and isolinux files.
2537 copy_from_cd() {
2538 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2539 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2540 unmeta_boot $ROOTCD
2541 umount /media/cdrom
2544 bootloader="$LOCALSTATE/installed/syslinux/volatile.cpio.gz"
2545 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2546 copy_from_cd;
2547 elif mount | grep /media/cdrom; then
2548 copy_from_cd;
2549 elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2550 cp $bootloader $ROOTCD
2551 cd $ROOTCD
2552 zcat volatile.cpio.gz | cpio -id
2553 rm -f volatile.cpio.gz
2554 [ -f /boot/*slitaz ] && \
2555 cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2556 [ -f /boot/*slitaz64 ] && \
2557 cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2558 else
2559 touch /tmp/.write-iso-error
2560 longline "When SliTaz is running in RAM the kernel and bootloader \
2561 files are kept on the CD-ROM. Please insert a Live CD or loop mount the \
2562 slitaz.iso to /media/cdrom (run # mount -o loop slitaz-rolling.iso /media/cdrom ) \
2563 or # (tazpkg -gi linux --forced) to let Tazlito copy the files."
2564 echo -en "----\nENTER to continue..."; read i
2565 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2566 copy_from_cd
2567 fi
2569 # Generate the iso image.
2570 touch /tmp/.write-iso
2571 newline
2572 cd $DISTRO
2573 _ 'Generating ISO image...'
2574 genisoimage -R -o $ISO_NAME.iso -b boot/isolinux/isolinux.bin \
2575 -c boot/isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
2576 -V "SliTaz" -p "$(id -un)" -input-charset utf-8 \
2577 -P "$(hostname)" -boot-info-table $ROOTCD
2578 if [ -x /usr/bin/isohybrid ]; then
2579 action 'Creating hybrid ISO/disk...'
2580 /usr/bin/isohybrid $ISO_NAME.iso -entry 2 2>/dev/null
2581 status
2582 fi
2583 if [ -x /usr/bin/iso2exe ]; then
2584 action 'Creating hybrid ISO/EXE...'
2585 /usr/bin/iso2exe $ISO_NAME.iso 2>/dev/null
2586 status
2587 fi
2588 action 'Creating the ISO md5sum...'
2589 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2590 status
2592 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2593 rm -f /tmp/.write-iso
2595 if [ -z $LaunchedByTazpanel ]; then
2596 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2597 case $anser in
2598 y)
2599 umount /dev/cdrom 2>/dev/null
2600 eject
2601 echo -n "Please insert a blank CD-ROM and press ENTER..."
2602 read i && sleep 2
2603 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2604 echo -en "----\nENTER to continue..."; read i ;;
2605 *)
2606 exit 0 ;;
2607 esac
2608 fi
2609 ;;
2612 burn-iso)
2613 # Guess CD-ROM device, ask user and burn the ISO.
2615 check_root
2616 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2617 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2618 # We can specify an alternative ISO from the cmdline.
2619 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2620 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2622 title 'Tazlito burn ISO'
2623 echo "CD-ROM device : /dev/$DRIVE_NAME"
2624 echo "Drive speed : $DRIVE_SPEED"
2625 echo "ISO image : $iso"
2626 footer
2628 case $(yesorno 'Burn ISO image?' 'n') in
2629 y)
2630 title 'Starting Wodim to burn the ISO...'
2631 sleep 2
2632 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2633 footer 'ISO image is burned to CD-ROM.'
2634 ;;
2635 *)
2636 die 'Exiting. No ISO burned.'
2637 ;;
2638 esac
2639 ;;
2642 merge)
2643 # Merge multiple rootfs into one iso.
2645 if [ -z "$2" ]; then
2646 cat <<EOT
2647 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2649 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2650 i.e: rootfsN is a subset of rootfsN-1
2651 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2652 The boot loader will select the rootfs according to the RAM size detected.
2654 Example:
2655 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
2657 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
2658 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
2660 EOT
2661 exit 2
2662 fi
2664 shift # skip merge
2665 append="$1 slitaz1"
2666 shift # skip size1
2667 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
2669 ISO=$1.merged
2671 # Extract filesystems
2672 action 'Mounting %s' "$1"
2673 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
2674 status || cleanup_merge
2676 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2677 make_bzImage_hardlink $TMP_DIR/iso/boot
2678 umount -d $TMP_DIR/mnt
2679 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
2680 _ '%s is already a merged iso. Aborting.' "$1"
2681 cleanup_merge
2682 fi
2683 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
2684 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
2685 if [ ! -f /boot/isolinux/ifmem.c32 -a
2686 ! -f /boot/isolinux/c32box.c32 ]; then
2687 cat <<EOT
2688 No file /boot/isolinux/ifmem.c32
2689 Please install syslinux package !
2690 EOT
2691 rm -rf $TMP_DIR
2692 exit 1
2693 fi
2694 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
2695 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
2696 fi
2698 action 'Extracting %s' 'iso/rootfs.gz'
2699 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
2700 [ -d $TMP_DIR/rootfs1/etc ]
2701 status || cleanup_merge
2703 n=1
2704 while [ -n "$2" ]; do
2705 shift # skip rootfs N-1
2706 p=$n
2707 n=$(($n + 1))
2708 append="$append $1 slitaz$n"
2709 shift # skip size N
2710 mkdir -p $TMP_DIR/rootfs$n
2712 action 'Extracting %s' "$1"
2713 extract_rootfs $1 $TMP_DIR/rootfs$n &&
2714 [ -d "$TMP_DIR/rootfs$n/etc" ]
2715 status || cleanup_merge
2717 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
2718 action 'Creating %s' "rootfs$p.gz"
2719 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
2720 status
2721 done
2722 action 'Creating %s' "rootfs$n.gz"
2723 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
2724 status
2725 rm -f $TMP_DIR/iso/boot/rootfs.gz
2726 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
2727 create_iso $ISO $TMP_DIR/iso
2728 rm -rf $TMP_DIR
2729 ;;
2732 repack)
2733 # Repack an iso with maximum lzma compression ratio.
2735 ISO=$2
2736 mkdir -p $TMP_DIR/mnt
2738 # Extract filesystems
2739 action 'Mounting %s' "$ISO"
2740 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
2741 status || cleanup_merge
2743 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2744 umount -d $TMP_DIR/mnt
2746 for i in $TMP_DIR/iso/boot/rootfs* ; do
2747 action 'Repacking %s' "$(basename $i)"
2748 (zcat $i 2>/dev/null || unlzma < $i || cat $i) 2>/dev/null > $TMP_DIR/rootfs
2749 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
2750 align_to_32bits $i
2751 status
2752 done
2754 create_iso $ISO $TMP_DIR/iso
2755 rm -rf $TMP_DIR
2756 ;;
2759 build-loram)
2760 # Build a Live CD for low RAM systems.
2762 ISO="$2"
2763 OUTPUT="$3"
2764 [ -z "$3" ] && \
2765 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
2766 mkdir -p "$TMP_DIR/iso"
2767 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
2768 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$ISO$/!d;s/:.*//;q")
2769 if ! check_iso_for_loram ; then
2770 umount -d "$TMP_DIR/iso"
2771 die "$ISO is not a valid SliTaz live CD. Abort."
2772 fi
2773 case "$4" in
2774 cdrom) build_loram_cdrom ;;
2775 http) build_loram_http ;;
2776 *) build_loram_ram ;;
2777 esac
2778 umount $TMP_DIR/iso # no -d: needs /proc
2779 losetup -d $loopdev
2780 rm -rf $TMP_DIR
2781 ;;
2784 emu-iso)
2785 # Emulate an ISO image with Qemu.
2786 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2787 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
2788 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
2789 echo -e "\nStarting Qemu emulator:\n"
2790 echo -e "qemu $QEMU_OPTS $iso\n"
2791 qemu $QEMU_OPTS $iso
2792 ;;
2795 deduplicate)
2796 # Deduplicate files in a tree
2797 shift
2798 deduplicate "$@"
2799 ;;
2802 usage|*)
2803 # Print usage also for all unknown commands.
2804 usage
2805 ;;
2806 esac
2808 exit 0