tazlito view tazlito @ rev 424

tazlito: set application_id
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sat May 21 17:45:33 2016 +0200 (2016-05-21)
parents b6fd50633850
children 64aae5899df1
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 mkdir ${ROOTFS}0$n
2309 export root="${ROOTFS}0$n"
2310 # initial tazpkg setup in empty rootfs
2311 tazpkg --root=$root >/dev/null 2>&1
2313 newline
2314 boldify "Building $flavor rootfs..."
2316 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2317 cp "$TOP_DIR/$flavor.flavor" .
2319 if [ ! -s "$flavor.flavor" ]; then
2320 # We may have it in $FLAVORS_REPOSITORY
2321 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2322 tazlito pack-flavor $flavor
2323 else
2324 download $flavor.flavor
2325 fi
2326 fi
2328 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2329 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2330 cp $flavor.pkglist $DISTRO/list-packages0$n
2331 status
2333 strip_versions "$DISTRO/list-packages0$n"
2335 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2337 rm -rf ${ROOTFS}0$n/boot
2339 cd $DISTRO
2340 if [ -s $flavor.rootfs ]; then
2341 _n 'Adding %s rootfs extra files...' "$flavor"
2342 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2343 fi
2345 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2346 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2347 status
2349 rm -f $flavor.flavor install-list
2350 mergefs ${ROOTFS}0$n $last
2351 last=${ROOTFS}0$n
2352 done <<EOT
2353 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2354 EOT
2355 #'
2356 i=$(($n+1))
2357 while [ $n -gt 0 ]; do
2358 mv ${ROOTFS}0$n ${ROOTFS}$i
2359 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2360 gen_initramfs ${ROOTFS}$i
2361 n=$(($n-1))
2362 i=$(($i-1))
2363 done
2364 mv $ROOTFS ${ROOTFS}$i
2365 gen_initramfs ${ROOTFS}$i
2366 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2367 else
2368 # Initramfs and ISO image stuff.
2369 gen_initramfs $ROOTFS
2370 fi
2371 gen_livecd_isolinux
2372 distro_stats
2373 cleanup
2374 ;;
2377 clean-distro)
2378 # Remove old distro tree.
2380 check_root
2381 title 'Cleaning: %s' "$DISTRO"
2382 if [ -d "$DISTRO" ] ; then
2383 if [ -d "$ROOTFS" ] ; then
2384 action 'Removing the rootfs...'
2385 rm -f $DISTRO/$INITRAMFS
2386 rm -rf $ROOTFS
2387 status
2388 fi
2389 if [ -d "$ROOTCD" ] ; then
2390 action 'Removing the rootcd...'
2391 rm -rf $ROOTCD
2392 status
2393 fi
2394 action 'Removing eventual ISO image...'
2395 rm -f $DISTRO/$ISO_NAME.iso
2396 rm -f $DISTRO/$ISO_NAME.md5
2397 status
2398 fi
2399 footer
2400 ;;
2403 check-distro)
2404 # Check for a few LiveCD needed files not installed by packages.
2406 # TODO: Remove this function.
2407 # First two files are maintained by tazpkg while it runs on rootfs,
2408 # while last one file should be maintained by tazlito itself.
2409 check_rootfs
2410 title 'Checking distro: %s' "$ROOTFS"
2411 # SliTaz release info.
2412 rel='/etc/slitaz-release'
2413 if [ ! -f "$ROOTFS$rel" ]; then
2414 _ 'Missing release info: %s' "$rel"
2415 else
2416 action 'Release : %s' "$(cat $ROOTFS$rel)"
2417 status
2418 fi
2419 # Tazpkg mirror.
2420 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2421 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2422 todomsg
2423 else
2424 action 'Mirror configuration exists...'
2425 status
2426 fi
2427 # Isolinux msg
2428 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2429 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2430 todomsg
2431 else
2432 action 'Isolinux message seems good...'
2433 status
2434 fi
2435 footer
2436 ;;
2439 writeiso)
2440 # Writefs to ISO image including /home unlike gen-distro we don't use
2441 # packages to generate a rootfs, we build a compressed rootfs with all
2442 # the current filesystem similar to 'tazusb writefs'.
2444 DISTRO='/home/slitaz/distro'
2445 ROOTCD="$DISTRO/rootcd"
2446 COMPRESSION="${2:-none}"
2447 ISO_NAME="${3:-slitaz}"
2448 check_root
2449 # Start info
2450 title 'Write filesystem to ISO'
2451 longline "The command writeiso will write the current filesystem into a \
2452 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2453 newline
2454 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2456 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2457 # Save some space
2458 rm -rf /var/cache/tazpkg/*
2459 rm -f /var/lib/tazpkg/*.bak
2460 rm -rf $DISTRO
2462 # Optionally remove sound card selection and screen resolution.
2463 if [ -z $LaunchedByTazpanel ]; then
2464 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2465 case $anser in
2466 y)
2467 action 'Removing current sound card and screen configurations...'
2468 rm -f /var/lib/sound-card-driver
2469 rm -f /var/lib/alsa/asound.state
2470 rm -f /etc/X11/xorg.conf ;;
2471 *)
2472 action 'Keeping current sound card and screen configurations...' ;;
2473 esac
2474 status
2475 newline
2477 # Optionally remove i18n settings
2478 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2479 case $anser in
2480 y)
2481 action 'Removing current locale/keymap settings...'
2482 newline > /etc/locale.conf
2483 newline > /etc/keymap.conf ;;
2484 *)
2485 action 'Keeping current locale/keymap settings...' ;;
2486 esac
2487 status
2488 fi
2490 # Clean-up files by default
2491 newline > /etc/udev/rules.d/70-persistent-net.rules
2492 newline > /etc/udev/rules.d/70-persistant-cd.rules
2494 # Create list of files including default user files since it is defined in /etc/passwd
2495 # and some new users might have been added.
2496 cd /
2497 echo 'init' > /tmp/list
2498 for dir in bin etc sbin var dev lib root usr home opt; do
2499 [ -d $dir ] && find $dir
2500 done >> /tmp/list
2502 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2503 [ -d $dir ] && echo $dir
2504 done >> /tmp/list
2506 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2508 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2509 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2510 #fi
2511 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2512 touch /var/log/wtmp
2514 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2515 sed -i "/var\/log\/$removelog/d" /tmp/list
2516 done
2518 # Generate initramfs with specified compression and display rootfs
2519 # size in realtime.
2520 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2522 write_initramfs &
2523 sleep 2
2524 cd - > /dev/null
2525 echo -en "\nFilesystem size:"
2526 while [ ! -f /tmp/rootfs ]; do
2527 sleep 1
2528 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2529 done
2530 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2531 echo -e "\n"
2532 rm -f /tmp/rootfs
2534 # Move freshly generated rootfs to the cdrom.
2535 mkdir -p $ROOTCD/boot
2536 mv -f /$INITRAMFS $ROOTCD/boot
2537 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2539 # Now we need the kernel and isolinux files.
2540 copy_from_cd() {
2541 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2542 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2543 unmeta_boot $ROOTCD
2544 umount /media/cdrom
2547 bootloader="$LOCALSTATE/installed/syslinux/volatile.cpio.gz"
2548 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2549 copy_from_cd;
2550 elif mount | grep /media/cdrom; then
2551 copy_from_cd;
2552 elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2553 cp $bootloader $ROOTCD
2554 cd $ROOTCD
2555 zcat volatile.cpio.gz | cpio -id
2556 rm -f volatile.cpio.gz
2557 [ -f /boot/*slitaz ] && \
2558 cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2559 [ -f /boot/*slitaz64 ] && \
2560 cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2561 else
2562 touch /tmp/.write-iso-error
2563 longline "When SliTaz is running in RAM the kernel and bootloader \
2564 files are kept on the CD-ROM. Please insert a Live CD or loop mount the \
2565 slitaz.iso to /media/cdrom (run # mount -o loop slitaz-rolling.iso /media/cdrom ) \
2566 or # (tazpkg -gi linux --forced) to let Tazlito copy the files."
2567 echo -en "----\nENTER to continue..."; read i
2568 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2569 copy_from_cd
2570 fi
2572 # Generate the iso image.
2573 touch /tmp/.write-iso
2574 newline
2575 cd $DISTRO
2576 _ 'Generating ISO image...'
2577 genisoimage -R -o $ISO_NAME.iso -b boot/isolinux/isolinux.bin \
2578 -c boot/isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
2579 -V "SliTaz" -p "$(id -un)" -input-charset utf-8 \
2580 -A "tazlito/genisoimage" -P "$(hostname)" -boot-info-table $ROOTCD
2581 if [ -x /usr/bin/isohybrid ]; then
2582 action 'Creating hybrid ISO/disk...'
2583 /usr/bin/isohybrid $ISO_NAME.iso -entry 2 2>/dev/null
2584 status
2585 fi
2586 if [ -x /usr/bin/iso2exe ]; then
2587 action 'Creating hybrid ISO/EXE...'
2588 /usr/bin/iso2exe $ISO_NAME.iso 2>/dev/null
2589 status
2590 fi
2591 action 'Creating the ISO md5sum...'
2592 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2593 status
2595 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2596 rm -f /tmp/.write-iso
2598 if [ -z $LaunchedByTazpanel ]; then
2599 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2600 case $anser in
2601 y)
2602 umount /dev/cdrom 2>/dev/null
2603 eject
2604 echo -n "Please insert a blank CD-ROM and press ENTER..."
2605 read i && sleep 2
2606 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2607 echo -en "----\nENTER to continue..."; read i ;;
2608 *)
2609 exit 0 ;;
2610 esac
2611 fi
2612 ;;
2615 burn-iso)
2616 # Guess CD-ROM device, ask user and burn the ISO.
2618 check_root
2619 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2620 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2621 # We can specify an alternative ISO from the cmdline.
2622 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2623 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2625 title 'Tazlito burn ISO'
2626 echo "CD-ROM device : /dev/$DRIVE_NAME"
2627 echo "Drive speed : $DRIVE_SPEED"
2628 echo "ISO image : $iso"
2629 footer
2631 case $(yesorno 'Burn ISO image?' 'n') in
2632 y)
2633 title 'Starting Wodim to burn the ISO...'
2634 sleep 2
2635 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2636 footer 'ISO image is burned to CD-ROM.'
2637 ;;
2638 *)
2639 die 'Exiting. No ISO burned.'
2640 ;;
2641 esac
2642 ;;
2645 merge)
2646 # Merge multiple rootfs into one iso.
2648 if [ -z "$2" ]; then
2649 cat <<EOT
2650 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2652 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2653 i.e: rootfsN is a subset of rootfsN-1
2654 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2655 The boot loader will select the rootfs according to the RAM size detected.
2657 Example:
2658 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
2660 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
2661 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
2663 EOT
2664 exit 2
2665 fi
2667 shift # skip merge
2668 append="$1 slitaz1"
2669 shift # skip size1
2670 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
2672 ISO=$1.merged
2674 # Extract filesystems
2675 action 'Mounting %s' "$1"
2676 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
2677 status || cleanup_merge
2679 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2680 make_bzImage_hardlink $TMP_DIR/iso/boot
2681 umount -d $TMP_DIR/mnt
2682 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
2683 _ '%s is already a merged iso. Aborting.' "$1"
2684 cleanup_merge
2685 fi
2686 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
2687 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
2688 if [ ! -f /boot/isolinux/ifmem.c32 -a
2689 ! -f /boot/isolinux/c32box.c32 ]; then
2690 cat <<EOT
2691 No file /boot/isolinux/ifmem.c32
2692 Please install syslinux package !
2693 EOT
2694 rm -rf $TMP_DIR
2695 exit 1
2696 fi
2697 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
2698 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
2699 fi
2701 action 'Extracting %s' 'iso/rootfs.gz'
2702 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
2703 [ -d $TMP_DIR/rootfs1/etc ]
2704 status || cleanup_merge
2706 n=1
2707 while [ -n "$2" ]; do
2708 shift # skip rootfs N-1
2709 p=$n
2710 n=$(($n + 1))
2711 append="$append $1 slitaz$n"
2712 shift # skip size N
2713 mkdir -p $TMP_DIR/rootfs$n
2715 action 'Extracting %s' "$1"
2716 extract_rootfs $1 $TMP_DIR/rootfs$n &&
2717 [ -d "$TMP_DIR/rootfs$n/etc" ]
2718 status || cleanup_merge
2720 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
2721 action 'Creating %s' "rootfs$p.gz"
2722 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
2723 status
2724 done
2725 action 'Creating %s' "rootfs$n.gz"
2726 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
2727 status
2728 rm -f $TMP_DIR/iso/boot/rootfs.gz
2729 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
2730 create_iso $ISO $TMP_DIR/iso
2731 rm -rf $TMP_DIR
2732 ;;
2735 repack)
2736 # Repack an iso with maximum lzma compression ratio.
2738 ISO=$2
2739 mkdir -p $TMP_DIR/mnt
2741 # Extract filesystems
2742 action 'Mounting %s' "$ISO"
2743 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
2744 status || cleanup_merge
2746 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2747 umount -d $TMP_DIR/mnt
2749 for i in $TMP_DIR/iso/boot/rootfs* ; do
2750 action 'Repacking %s' "$(basename $i)"
2751 (zcat $i 2>/dev/null || unlzma < $i || cat $i) 2>/dev/null > $TMP_DIR/rootfs
2752 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
2753 align_to_32bits $i
2754 status
2755 done
2757 create_iso $ISO $TMP_DIR/iso
2758 rm -rf $TMP_DIR
2759 ;;
2762 build-loram)
2763 # Build a Live CD for low RAM systems.
2765 ISO="$2"
2766 OUTPUT="$3"
2767 [ -z "$3" ] && \
2768 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
2769 mkdir -p "$TMP_DIR/iso"
2770 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
2771 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$ISO$/!d;s/:.*//;q")
2772 if ! check_iso_for_loram ; then
2773 umount -d "$TMP_DIR/iso"
2774 die "$ISO is not a valid SliTaz live CD. Abort."
2775 fi
2776 case "$4" in
2777 cdrom) build_loram_cdrom ;;
2778 http) build_loram_http ;;
2779 *) build_loram_ram ;;
2780 esac
2781 umount $TMP_DIR/iso # no -d: needs /proc
2782 losetup -d $loopdev
2783 rm -rf $TMP_DIR
2784 ;;
2787 emu-iso)
2788 # Emulate an ISO image with Qemu.
2789 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2790 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
2791 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
2792 echo -e "\nStarting Qemu emulator:\n"
2793 echo -e "qemu $QEMU_OPTS $iso\n"
2794 qemu $QEMU_OPTS $iso
2795 ;;
2798 deduplicate)
2799 # Deduplicate files in a tree
2800 shift
2801 deduplicate "$@"
2802 ;;
2805 usage|*)
2806 # Print usage also for all unknown commands.
2807 usage
2808 ;;
2809 esac
2811 exit 0