tazlito view tazlito @ rev 436

uefi support aventually... (again)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Fri Sep 30 15:43:05 2016 +0200 (2016-09-30)
parents c53dcc8b4370
children 338b35b61749
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 uefi="$(cd $2 ; ls boot/isolinux/*efi*img 2> /dev/null)"
284 genisoimage -R -o $1 -hide-rr-moved \
285 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
286 -no-emul-boot -boot-load-size 4 -boot-info-table \
287 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
288 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
289 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
290 -A "tazlito $VERSION/$(genisoimage --version)" \
291 -copyright README -P "www.slitaz.org" $2
292 if [ -s '/etc/tazlito/info' ]; then
293 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
294 action 'Storing ISO info...'
295 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
296 status
297 fi
298 fi
300 if [ -x '/usr/bin/isohybrid' ]; then
301 action 'Creating hybrid ISO...'
302 /usr/bin/isohybrid $1 -entry 2 2>/dev/null
303 status
304 fi
306 if [ -x '/usr/bin/iso2exe' ]; then
307 echo 'Creating EXE header...'
308 /usr/bin/iso2exe $1 2>/dev/null
309 fi
310 }
313 # Generate a new ISO image using isolinux.
315 gen_livecd_isolinux() {
316 # Some packages may want to alter iso
317 genisohooks iso
318 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
320 # Set date for boot msg.
321 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
322 DATE=$(date +%Y%m%d)
323 action 'Setting build date to: %s...' "$DATE"
324 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
325 status
326 fi
328 cd $DISTRO
329 create_iso $ISO_NAME.iso $ROOTCD
331 action 'Creating the ISO md5sum...'
332 md5sum $ISO_NAME.iso > $ISO_NAME.md5
333 status
335 separator
336 # Some packages may want to alter final iso
337 genisohooks final
338 }
341 lzma_history_bits() {
342 #
343 # This generates an ISO which boots with Qemu but gives
344 # rootfs errors in frugal or liveUSB mode.
345 #
346 # local n
347 # local sz
348 # n=20 # 1Mb
349 # sz=$(du -sk $1 | cut -f1)
350 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
351 # n=$(( $n + 1 ))
352 # sz=$(( $sz / 2 ))
353 # done
354 # echo $n
355 echo ${LZMA_HISTORY_BITS:-24}
356 }
359 lzma_switches() {
360 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
361 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
362 }
365 lzma_set_size() {
366 # Update size field for lzma'd file packed using -si switch
367 return # Need to fix kernel code?
369 local n i
370 n=$(unlzma < $1 | wc -c)
371 for i in $(seq 1 8); do
372 printf '\\\\x%02X' $(($n & 255))
373 n=$(($n >> 8))
374 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
375 }
378 align_to_32bits() {
379 local size=$(stat -c %s ${1:-/dev/null})
380 [ $((${size:-0} & 3)) -ne 0 ] &&
381 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
382 }
385 # Pack rootfs
387 pack_rootfs() {
388 ( cd $1; find . -print | cpio -o -H newc ) | \
389 case "$COMPRESSION" in
390 none)
391 _ 'Creating %s without compression...' 'initramfs'
392 cat > $2
393 ;;
394 gzip)
395 _ 'Creating %s with gzip compression...' 'initramfs'
396 gzip -9 > $2
397 ;;
398 *)
399 _ 'Creating %s with lzma compression...' 'initramfs'
400 lzma e -si -so $(lzma_switches $1) > $2
401 lzma_set_size $2
402 ;;
403 esac
404 align_to_32bits $2
405 echo 1 > /tmp/rootfs
406 }
409 # Compression functions for writeiso.
411 write_initramfs() {
412 case "$COMPRESSION" in
413 lzma)
414 _n 'Creating %s with lzma compression...' "$INITRAMFS"
415 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
416 align='y'
417 lzma_set_size "/$INITRAMFS"
418 ;;
419 gzip)
420 _ 'Creating %s with gzip compression...' "$INITRAMFS"
421 cpio -o -H newc | gzip -9 > "/$INITRAMFS"
422 [ -x /usr/bin/advdef ] && advdef -z4 "/$INITRAMFS"
423 ;;
424 *)
425 # align='y'
426 _ 'Creating %s without compression...' "$INITRAMFS"
427 cpio -o -H newc > "/$INITRAMFS"
428 ;;
429 esac < /tmp/list
430 [ "$align" == 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
431 echo 1 > /tmp/rootfs
432 }
435 # Deduplicate files (MUST be on the same filesystem).
437 deduplicate() {
438 find "${@:-.}" -type f -size +0c -xdev -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
439 (
440 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""
441 while read attr inode link file; do
442 [ -L "$file" ] && continue
443 if [ "$attr" == "$old_attr" -a "$inode" != "$old_inode" ]; then
444 if cmp "$file" "$old_file" >/dev/null 2>&1 ; then
445 rm -f "$file"
446 if ln "$old_file" "$file" 2>/dev/null; then
447 inode="$old_inode"
448 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
449 save="$(($save+(${attr%%-*}+512)/1024))"
450 else
451 cp -a "$old_file" "$file"
452 fi
453 fi
454 fi
455 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
456 done
457 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
458 )
460 find "$@" -type l -xdev -exec stat -c '%s-%u-%g-TARGET- %i %h %n' {} \; | sort | \
461 (
462 old_attr=""; hardlinks=0;
463 while read attr inode link file; do
464 attr="${attr/-TARGET-/-$(readlink $file)}"
465 if [ "$attr" == "$old_attr" ]; then
466 if [ "$inode" != "$old_inode" ]; then
467 rm -f "$file"
468 if ln "$old_file" "$file" 2>/dev/null; then
469 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
470 else
471 cp -a "$old_file" "$file"
472 fi
473 fi
474 else
475 old_file="$file"
476 old_attr="$attr"
477 old_inode="$inode"
478 fi
479 done
480 _ '%s duplicate symlinks.' "$hardlinks"
481 )
482 }
485 # Generate a new initramfs from the root filesystem.
487 gen_initramfs() {
488 # Just in case CTRL+c
489 rm -f $DISTRO/gen
491 # Some packages may want to alter rootfs
492 genisohooks rootfs
493 cd $1
495 # Link duplicate files
496 deduplicate
498 # Use lzma if installed. Display rootfs size in realtime.
499 rm -f /tmp/rootfs 2>/dev/null
500 pack_rootfs . $DISTRO/$(basename $1).gz &
501 sleep 2
502 echo -en "\nFilesystem size:"
503 while [ ! -f /tmp/rootfs ]; do
504 sleep 1
505 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
506 done
507 echo -e "\n"
508 rm -f /tmp/rootfs
509 cd $DISTRO
510 mv $(basename $1).gz $ROOTCD/boot
511 }
514 distro_sizes() {
515 if [ -n "$start_time" ]; then
516 time=$(($(date +%s) - $start_time))
517 sec=$time
518 div=$(( ($time + 30) / 60))
519 [ "$div" -ne 0 ] && min="~ ${div}m"
520 _ 'Build time : %ss %s' "$sec" "$min"
521 fi
522 cat <<EOT
523 Build date : $(date +%Y%m%d)
524 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
525 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
526 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
527 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
528 EOT
529 footer "Image is ready: $ISO_NAME.iso"
530 }
533 # Print ISO and rootfs size.
535 distro_stats() {
536 title 'Distro statistics: %s' "$DISTRO"
537 distro_sizes
538 }
541 # Create an empty configuration file.
543 empty_config_file() {
544 cat >> tazlito.conf <<"EOF"
545 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
546 #
548 # Name of the ISO image to generate.
549 ISO_NAME=""
551 # ISO image volume name.
552 VOLUM_NAME="SliTaz"
554 # Name of the preparer.
555 PREPARED="$USER"
557 # Path to the packages repository and the packages.list.
558 PACKAGES_REPOSITORY=""
560 # Path to the distro tree to gen-distro from a list of packages.
561 DISTRO=""
563 # Path to the directory containing additional files
564 # to copy into the rootfs and rootcd of the LiveCD.
565 ADDFILES="$DISTRO/addfiles"
567 # Default answer for binary question (Y or N)
568 DEFAULT_ANSWER="ASK"
570 # Compression utility (lzma, gzip or none)
571 COMPRESSION="lzma"
572 EOF
573 }
576 # Extract rootfs.gz somewhere
578 extract_rootfs() {
579 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
580 # First part (lzcat or zcat) may not fail, but cpio will fail on uncorrect format
581 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
582 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
583 (cd "$2"; cat "$1" | cpio -idm --quiet 2>/dev/null)
584 }
587 # Extract flavor file to temp directory
589 extract_flavor() {
590 # Input: $1 - flavor name to extract;
591 # $2 = absent/empty: just extract 'outer layer'
592 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
593 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
594 # Output: temp dir path where flavor was extracted
595 local f="$1.flavor" from to infos="$1.desc"
596 [ -f "$f" ] || die "File '$f' not found"
597 local dir="$(mktemp -d)"
598 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
600 if [ -n "$2" ]; then
601 cd $dir
603 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
605 for i in rootcd rootfs; do
606 [ -f "$1.$i" ] || continue
607 mkdir "$i"
608 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
609 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
610 rm "$1.$i"
611 done
612 # Info to be stored inside ISO
613 [ "$2" == info ] && echo -e $infos | cpio -o -H newc | gzip -9 > info
614 rm $1.list*
616 # Renames
617 while read from to; do
618 [ -f "$from" ] || continue
619 mv "$from" "$to"
620 done <<EOT
621 $1.nonfree non-free.list
622 $1.pkglist packages.list
623 $1-distro.sh distro.sh
624 $1.receipt receipt
625 $1.mirrors mirrors
626 $1.desc description
627 EOT
628 fi
630 echo $dir
631 }
634 # Pack flavor file from temp directory
636 pack_flavor() {
637 (cd "$1"; ls | grep -v err | cpio -o -H newc) | gzip -9 > "$2.flavor"
638 }
641 # Remove duplicate files
643 mergefs() {
644 # Note, many packages have files with spaces in the name
645 IFS=$'\n'
647 local size1=$(du -hs "$1" | awk '{ print $1 }')
648 local size2=$(du -hs "$2" | awk '{ print $1 }')
649 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
651 # merge symlinks files and devices
652 ( cd "$1"; find ) | \
653 while read file; do
654 if [ -L "$1/$file" ]; then
655 [ -L "$2/$file" -a "$(readlink "$1/$file")" == "$(readlink "$2/$file")" ] &&
656 rm -f "$2/$file"
658 elif [ -f "$1/$file" ]; then
659 [ -f "$2/$file" ] && cmp -s "$1/$file" "$2/$file" &&
660 rm -f "$2/$file"
662 [ -f "$2/$file" ] &&
663 [ "$(basename "$file")" == 'volatile.cpio.gz' ] &&
664 [ "$(dirname $(dirname "$file"))" == ".$INSTALLED" ] &&
665 rm -f "$2/$file"
667 elif [ -b "$1/$file" ]; then
668 [ -b "$2/$file" ] &&
669 [ "$(stat -c '%a:%u:%g:%t:%T' "$1/$file")" == \
670 "$(stat -c '%a:%u:%g:%t:%T' "$2/$file")" ] &&
671 rm -f "$2/$file"
673 elif [ -c "$1/$file" ]; then
674 [ -c "$2/$file" ] &&
675 [ "$(stat -c '%a:%u:%g:%t:%T' "$1/$file")" == \
676 "$(stat -c '%a:%u:%g:%t:%T' "$2/$file")" ] &&
677 rm -f "$2/$file"
678 fi
679 done
681 # cleanup directories; TODO: simplify
682 ( cd "$1"; find . -type d ) | sed '1!G;h;$!d' | \
683 while read file; do
684 [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
685 done
687 unset IFS
688 status
689 }
692 cleanup_merge() {
693 rm -rf $TMP_DIR
694 exit 1
695 }
698 # Update isolinux config files for multiple rootfs
700 update_bootconfig() {
701 local files
702 action 'Updating boot config files...'
703 files="$(grep -l 'include common' $1/*.cfg)"
704 for file in $files; do
705 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
706 if (/label/) label=$0;
707 else if (/kernel/) kernel=$0;
708 else if (/append/) {
709 i=index($0,"rootfs.gz");
710 append=substr($0,i+9);
711 }
712 else if (/include/) {
713 for (i = 1; i <= n; i++) {
714 print label i
715 print kernel;
716 initrd="initrd=/boot/rootfs" n ".gz"
717 for (j = n - 1; j >= i; j--) {
718 initrd=initrd ",/boot/rootfs" j ".gz";
719 }
720 printf "\tappend %s%s\n",initrd,append;
721 print "";
722 }
723 print;
724 }
725 else print;
726 }' < $file > $file.$$
727 mv -f $file.$$ $file
728 done
729 sel="$(echo $2 | awk '{
730 for (i=1; i<=NF; i++)
731 if (i % 2 == 0) printf " slitaz%d", i/2
732 else printf " %s", $i
733 }')"
735 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
737 label slitaz
738 kernel /boot/isolinux/ifmem.c32
739 append$sel noram
741 label noram
742 config noram.cfg
744 EOT
746 # Update vesamenu
747 if [ -s "$1/isolinux.cfg" ]; then
748 files="$files $1/isolinux.cfg"
749 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
750 BEGIN {
751 kernel = " COM32 c32box.c32"
752 }
753 {
754 if (/ROWS/) print "MENU ROWS " n+$3;
755 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
756 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
757 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
758 else if (/VSHIFT/) {
759 x = $3-n;
760 if (x < 0) x = 0;
761 print "MENU VSHIFT " x;
762 }
763 else if (/rootfs.gz/) {
764 linux = "";
765 if (/bzImage/) linux = "linux /boot/bzImage ";
766 i = index($0, "rootfs.gz");
767 append = substr($0, i+9);
768 printf "\tkernel /boot/isolinux/ifmem.c32\n";
769 printf "\tappend%s noram\n", sel;
770 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
771 for (i = 1; i <= n; i++) {
772 print "LABEL slitaz" i
773 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
774 printf "%s\n", kernel;
775 initrd = "initrd=/boot/rootfs" n ".gz"
776 for (j = n - 1; j >= i; j--) {
777 initrd = initrd ",/boot/rootfs" j ".gz";
778 }
779 printf "\tappend %s%s%s\n\n", linux, initrd, append;
780 }
781 }
782 else if (/bzImage/) kernel = $0;
783 else print;
784 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
785 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
786 fi
788 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
789 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
790 cat > $1/noram.cfg <<EOT
791 implicit 0
792 prompt 1
793 timeout 80
794 $(grep '^F[0-9]' $1/isolinux.cfg)
796 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
797 say Not enough RAM to boot slitaz. Trying hacker mode...
798 default hacker
799 label hacker
800 KERNEL /boot/bzImage
801 append rw root=/dev/null vga=normal
803 label reboot
804 EOT
806 if [ -s $1/c32box.c32 ]; then
807 cat >> $1/noram.cfg <<EOT
808 COM32 c32box.c32
809 append reboot
811 label poweroff
812 COM32 c32box.c32
813 append poweroff
815 EOT
816 else
817 echo " com32 reboot.c32" >> $1/noram.cfg
818 fi
820 # Restore real label names
821 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
822 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
823 while read pat; do
824 sed -i "s/slitaz$pat/" $files
825 done
826 status
827 }
830 # Uncompress rootfs or module to stdout
832 uncompress() {
833 zcat $1 2> /dev/null || xzcat $1 2> /dev/null || unlzma < $1 || cat $i
834 }
837 # Install a missing package
839 install_package() {
840 if [ -z "$2" ]; then
841 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
842 else
843 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
844 fi
845 case "$answer" in
846 y)
847 # We don't want package on host cache.
848 action 'Getting and installing package: %s' "$1"
849 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
850 status ;;
851 *)
852 return 1 ;;
853 esac
854 }
857 # Check iso for loram transformation
859 check_iso_for_loram() {
860 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
861 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
862 }
865 # Build initial rootfs for loram ISO ram/cdrom/http
867 build_initfs() {
868 urliso="mirror.switch.ch/ftp/mirror/slitaz \
869 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
870 mirror3.slitaz.org mirror.slitaz.org"
871 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
872 [ -z "$version" ] && die "Can't find the kernel version." \
873 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
875 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
876 need_lib=false
877 for i in bin dev run mnt proc tmp sys lib/modules; do
878 mkdir -p $TMP_DIR/initfs/$i
879 done
880 ln -s bin $TMP_DIR/initfs/sbin
881 ln -s . $TMP_DIR/initfs/usr
882 for aufs in aufs overlayfs; do
883 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
884 install_package $aufs $version && break
885 done || return 1
886 cp /init $TMP_DIR/initfs/
887 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
888 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
889 $TMP_DIR/initfs/lib/modules 2>/dev/null
890 cp -a /dev/tty0 /dev/fd0 $TMP_DIR/initfs/dev 2>/dev/null
891 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
892 $TMP_DIR/initfs/lib/modules
893 if [ "$1" == 'cdrom' ]; then
894 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
895 else
896 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
897 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
898 install_package linux-squashfs $version || return 1
899 done
900 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
901 $TMP_DIR/initfs/lib/modules
902 ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
903 cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
904 fi
905 for i in $(ls /dev/[hs]d[a-f]*); do
906 cp -a $i $TMP_DIR/initfs/dev
907 done
908 if [ "$1" == 'http' ]; then
909 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
910 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
911 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
912 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
913 cp -a /dev/fuse $TMP_DIR/initfs/dev
914 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
915 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
916 else
917 need_lib=true
918 fi
919 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
920 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
921 else
922 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
923 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
924 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
925 cp -a /lib/librt* $TMP_DIR/initfs/lib
926 cp -a /lib/libdl* $TMP_DIR/initfs/lib
927 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
928 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
929 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
930 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
931 need_lib=true
932 fi
933 cd $TMP_DIR/fs
934 echo 'Getting slitaz-release & ethernet modules...'
935 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
936 uncompress $i | cpio -idmu etc/slitaz-release lib/modules* >/dev/null
937 done
938 cd - > /dev/null
939 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
940 find $TMP_DIR/fs/lib/modules/*/kernel/drivers/net/ethernet \
941 -type f -name '*.ko*' | while read mod; do
942 f=$TMP_DIR/initfs/lib/modules/$(basename $mod | sed s/..z$//)
943 uncompress $mod > $f
944 grep -q alias=pci: $f || rm -f $f
945 done
946 for i in $TMP_DIR/initfs/lib/modules/*.ko ; do
947 f=$(basename $i)..z
948 grep -q $f:$ $TMP_DIR/fs/lib/modules/*/modules.dep && continue
949 deps="$(grep $f: $TMP_DIR/fs/lib/modules/*/modules.dep | sed 's/.*: //')"
950 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > $TMP_DIR/initfs/lib/modules/$(basename $i .ko).dep
951 for j in $deps; do
952 mod=$(ls $TMP_DIR/fs/lib/modules/*/$j)
953 uncompress $mod > $TMP_DIR/initfs/lib/modules/$(basename $j | sed s/..z$//)
954 done
955 done
956 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"
957 _n 'List of URLs to insert: '
958 read -t 30 urliso2
959 urliso="$urliso2 $urliso"
960 fi
961 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
962 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
963 sed -i 's/LD_T.*ot/newline/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
964 else
965 cp /bin/busybox $TMP_DIR/initfs/bin
966 need_lib=true
967 fi
968 for i in $($TMP_DIR/initfs/bin/busybox | awk \
969 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
970 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
971 done
972 for i in /dev/console /dev/loop* /dev/null /dev/tty /dev/zero \
973 /dev/kmem /dev/mem /dev/random /dev/urandom; do
974 cp -a $i $TMP_DIR/initfs/dev
975 done
976 $need_lib && for i in /lib/ld-* /lib/lib[cm].so* /lib/lib[cm]-* ; do
977 cp -a $i $TMP_DIR/initfs/lib
978 done
979 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
980 #!/bin/sh
982 getarg() {
983 grep -q " \$1=" /proc/cmdline || return 1
984 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
985 return 0
986 }
988 copy_rootfs() {
989 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
990 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
991 [ \$(( \$total / \$need )) -gt 1 ] || return 1
992 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
993 path=/mnt/
994 return 0
995 else
996 rm -f /mnt/rootfs*
997 return 1
998 fi
999 }
1001 echo "Switching / to tmpfs..."
1002 mount -t proc proc /proc
1003 size="\$(grep rootfssize= < /proc/cmdline | \\
1004 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1005 [ -n "\$size" ] || size="-o size=90%"
1007 mount -t sysfs sysfs /sys
1008 for i in /lib/modules/*.ko ; do
1009 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1010 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1011 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1012 insmod /lib/modules/\$k.ko 2> /dev/null
1013 done
1014 insmod \$i 2> /dev/null
1015 break
1016 done
1017 done
1018 umount /sys
1019 while read var default; do
1020 eval \$var=\$default
1021 getarg \$var \$var
1022 done <<EOT
1023 eth eth0
1024 dns 208.67.222.222,208.67.220.220
1025 netmask 255.255.255.0
1026 gw
1027 ip
1028 EOT
1029 if [ -n "\$ip" ]; then
1030 ifconfig \$eth \$ip netmask \$netmask up
1031 route add default gateway \$gw
1032 for i in \$(echo \$dns | sed 's/,/ /g'); do
1033 echo "nameserver \$i" >> /etc/resolv.conf
1034 done
1035 else
1036 udhcpc -f -q -s /lib/udhcpc -i \$eth
1037 fi
1038 for i in $urliso ; do
1039 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1040 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"
1041 done
1042 getarg urliso URLISO
1043 DIR=fs
1044 if getarg loram DIR; then
1045 DEVICE=\${DIR%,*}
1046 DIR=/\${DIR#*,}
1047 fi
1048 mount -t tmpfs \$size tmpfs /mnt
1049 path2=/mnt/.httpfs/
1050 path=/mnt/.cdrom/
1051 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1052 while [ ! -d \$path/boot ]; do
1053 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1054 httpfs \$i \$path2 && break
1055 done
1056 mount -o loop,ro -t iso9660 \$path2/*.iso \$path
1057 done
1059 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1060 umount /proc
1061 branch=:/mnt/.cdrom/\$DIR
1062 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1063 branch=
1064 for i in \${path}rootfs* ; do
1065 fs=\${i#*root}
1066 branch=\$branch:/mnt/.\$fs
1067 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1068 insmod /lib/modules/squashfs.ko 2> /dev/null
1069 mount -o loop,ro -t squashfs \${path}root\$fs /mnt/.\$fs
1070 done
1071 else
1072 mkdir -p /mnt/.rw/mnt/.httpfs
1073 fi
1074 while read type opt; do
1075 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1076 done <<EOT
1077 aufs br=/mnt/.rw\$branch
1078 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1079 EOT
1080 rm -rf /lib/modules
1081 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1082 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1083 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1084 EOTEOT
1085 chmod +x $TMP_DIR/initfs/init
1086 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1087 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1088 rm -f $i
1089 gzip -9 ${i%.gz}
1090 done 2>/dev/null
1091 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1092 lzma e $TMP_DIR/initfs.gz -si
1093 lzma_set_size $TMP_DIR/initfs.gz
1094 rm -rf $TMP_DIR/initfs
1095 align_to_32bits $TMP_DIR/initfs.gz
1096 return 0
1100 # Move each initramfs to squashfs
1102 build_loram_rootfs() {
1103 rootfs_sizes=""
1104 for i in $TMP_DIR/iso/boot/rootfs*; do
1105 mkdir -p $TMP_DIR/fs
1106 cd $TMP_DIR/fs
1107 uncompress $i | cpio -idm
1108 deduplicate
1109 cd - > /dev/null
1110 rootfs=$TMP_DIR/$(basename $i)
1111 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp xz -Xbcj x86
1112 cd $TMP_DIR
1113 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1114 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1115 rm -f $rootfs
1116 mv $rootfs.cpio $rootfs
1117 cd - > /dev/null
1118 rm -rf $TMP_DIR/fs
1119 done
1123 # Move meta boot configuration files to basic configuration files
1124 # because meta loram flavor is useless when rootfs is not loaded in RAM
1126 unmeta_boot() {
1127 local root=${1:-$TMP_DIR/loramiso}
1128 if [ -f $root/boot/isolinux/noram.cfg ]; then
1129 # We keep enough information to do unloram...
1130 [ -s $root/boot/isolinux/common.cfg ] &&
1131 sed -i 's/label slitaz/label orgslitaz/' \
1132 $root/boot/isolinux/common.cfg
1133 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1134 shift
1135 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1136 $root/boot/isolinux/isolinux.cfg
1137 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1138 sed -i "s/label $3\$/label slitaz/;s|=/boot/rootfs\(.*\).gz |=/boot/rootfs.gz |" \
1139 $root/boot/isolinux/*.cfg
1140 fi
1144 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1145 # These squashfs may be loaded in RAM at boot time.
1146 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1147 # Meta flavors are converted to normal flavors.
1149 build_loram_cdrom() {
1150 build_initfs cdrom || return 1
1151 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1152 mkdir $TMP_DIR/loramiso/fs
1153 cd $TMP_DIR/loramiso/fs
1154 for i in $( ls ../boot/root* | sort -r ) ; do
1155 uncompress $i | cpio -idmu
1156 rm -f $i
1157 done
1158 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1159 cd - >/dev/null
1160 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1161 unmeta_boot
1162 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1163 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1164 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1165 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1166 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1167 create_iso $OUTPUT $TMP_DIR/loramiso
1171 # Create http bootstrap to load and remove loram_cdrom
1172 # Meta flavors are converted to normal flavors.
1174 build_loram_http() {
1175 build_initfs http || return 1
1176 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1177 rm -f $TMP_DIR/loramiso/boot/rootfs*
1178 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1179 unmeta_boot
1180 create_iso $OUTPUT $TMP_DIR/loramiso
1184 # Update meta flavor selection sizes.
1185 # Reduce sizes with rootfs gains.
1187 update_metaiso_sizes() {
1188 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1189 do
1190 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1191 local sizes="$rootfs_sizes"
1192 local new
1193 set -- $append
1194 shift
1195 [ "$1" == "ifmem" ] && shift
1196 new=""
1197 while [ -n "$2" ]; do
1198 local s
1199 case "$1" in
1200 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1201 *M) s=$(( ${1%M} * 1024 ));;
1202 *) s=${1%K};;
1203 esac
1204 sizes=${sizes#* }
1205 for i in $sizes ; do
1206 s=$(( $s - $i ))
1207 done
1208 new="$new $s $2"
1209 shift 2
1210 done
1211 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1212 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1213 sed -i 's|\(initrd=\)\(/boot/rootfs.\.gz\)|\1/boot/rootfs.gz,\2|' $cfg
1214 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1215 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1216 done
1220 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1221 # Meta flavor selection sizes are updated.
1223 build_loram_ram() {
1224 build_initfs ram || return 1
1225 build_loram_rootfs
1226 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1227 make_bzImage_hardlink $TMP_DIR/loramiso/boot
1228 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1229 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1230 update_metaiso_sizes
1231 create_iso $OUTPUT $TMP_DIR/loramiso
1235 # Remove files installed by packages
1237 find_flavor_rootfs() {
1238 for i in $1/etc/tazlito/*.extract; do
1239 [ -e $i ] || continue
1240 chroot $1 /bin/sh ${i#$1}
1241 done
1243 # Clean hardlinks and files patched by genisofs in /boot
1244 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1245 rm -f $1/boot/$i*
1246 done
1248 # Clean files generated in post_install
1249 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1250 $1/dev/core $1/dev/fd $1/dev/std*
1252 # Verify md5
1253 cat $1$INSTALLED/*/md5sum | \
1254 while read md5 file; do
1255 [ -e "$1$file" ] || continue
1256 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1257 rm -f "$1$file"
1258 done
1260 # Check configuration files
1261 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1262 [ -e $i ] || continue
1263 mkdir /tmp/volatile$$
1264 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1265 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1266 while read file ; do
1267 [ -e "$1/$file" ] || continue
1268 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1269 done
1270 rm -rf /tmp/volatile$$
1271 done
1273 # Remove other files blindly
1274 for i in $1$INSTALLED/*/files.list; do
1275 for file in $(cat "$i"); do
1276 [ "$1$file" -nt "$i" ] && continue
1277 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1278 [ -d "$1$file" ] || rm -f "$1$file"
1279 done
1280 done
1282 # Remove tazpkg files and tmp files
1283 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1284 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1285 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1286 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1287 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1289 # Cleanup directory tree
1290 cd $1
1291 find * -type d | sort -r | while read dir; do
1292 rmdir "$dir" 2>/dev/null
1293 done
1294 cd - > /dev/null
1298 # Get byte(s) from a binary file
1300 get() {
1301 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null
1305 # Get cpio flavor info from the ISO image
1307 flavordata() {
1308 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1309 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1313 # Restore undigest mirrors
1315 restore_mirrors() {
1316 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1317 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1319 action 'Restoring mirrors...'
1320 if [ -d "$undigest.bak" ]; then
1321 [ -d "$undigest" ] && rm -r "$undigest"
1322 mv "$undigest.bak" "$undigest"
1323 fi
1324 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1325 :; status
1329 # Setup undigest mirrors
1331 setup_mirrors() {
1332 # Setup mirrors in plain system or in chroot (with variable root=)
1333 local mirrorlist="$1" fresh repacked
1334 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1336 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1337 restore_mirrors
1339 _ 'Setting up mirrors for %s...' "$root/"
1340 # Backing up current undigest mirrors and priority
1341 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1342 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1343 rm -rf '/var/www/tazlito/'
1344 mkdir -p '/var/www/tazlito/'
1346 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1347 fresh='/home/slitaz/packages'
1348 if [ -d "$fresh" ]; then
1349 # Setup first undigest mirror
1350 mkdir -p "$undigest/fresh"
1351 echo "$fresh" > "$undigest/fresh/mirror"
1352 echo 'fresh' >> "$priority"
1353 # Rebuild mirror DB if needed
1354 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1355 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1356 tazpkg mkdb "$fresh" --forced --root=''
1357 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1358 fi
1360 # Repacked packages: high priority
1361 repacked="$PACKAGES_REPOSITORY"
1362 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1363 # According to Tazlito setup file (tazlito.conf):
1364 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1365 # or
1366 # WORK_DIR="/home/slitaz"
1367 # and
1368 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1369 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1371 # Setup second undigest mirror
1372 mkdir -p "$undigest/repacked"
1373 echo "$repacked" > "$undigest/repacked/mirror"
1374 echo 'repacked' >> "$priority"
1375 # Rebuild mirror DB if needed
1376 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1377 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1378 tazpkg mkdb "$repacked" --forced --root=''
1379 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1380 fi
1382 # All repositories listed in mirrors list: normal priority
1383 [ -e "$mirrorlist" ] && \
1384 while read mirror; do
1385 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1386 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1387 mkdir -p "$undigest/$mirrorid"
1388 echo "$mirror" > "$undigest/$mirrorid/mirror"
1389 echo "$mirrorid" >> "$priority"
1390 done < "$mirrorlist"
1392 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1394 # Show list of mirrors
1395 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1396 function show(num, name, url) {
1397 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1400 num++;
1401 "cat " db "/undigest/" $0 "/mirror" | getline url;
1402 show(num, $0, url);
1404 END {
1405 num++;
1406 "cat " db "/mirror" | getline url;
1407 show(num, "main", url);
1408 }' "$priority"
1410 tazpkg recharge --quiet >/dev/null
1414 # Get list of 'packages.info' lists using priority
1416 pi_lists() {
1417 local pi
1418 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1419 local priority="$root$LOCALSTATE/priority"
1420 local undigest="$root$LOCALSTATE/undigest"
1423 [ -s "$priority" ] && cat "$priority"
1424 echo 'main'
1425 [ -d "$undigest" ] && ls "$undigest"
1426 } | awk -vun="$undigest/" '
1428 if (arr[$0] != 1) {
1429 arr[$0] = 1;
1430 print un $0 "/packages.info";
1432 }' | sed 's|/undigest/main||' | \
1433 while read pi; do
1434 [ -e "$pi" ] && echo "$pi"
1435 done
1439 # Strip versions from packages list
1441 strip_versions() {
1442 action 'Strip versions from list %s...' "$(basename "$1")"
1443 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1444 [ -f "$in_list" ] || die "List '$in_list' not found."
1446 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1447 awk '
1449 if (FILENAME ~ "packages.info") {
1450 # Collect package names
1451 FS = "\t"; pkg[$1] = 1;
1452 } else {
1453 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1454 while (NF > 1 && ! pkg[$0])
1455 NF --;
1456 printf "%s\n", $0;
1458 }' $(pi_lists) "$in_list" > "$tmp_list"
1460 cat "$tmp_list" > "$in_list"
1461 rm "$tmp_list"
1462 status
1466 # Display list of unknown packages (informative)
1468 display_unknown() {
1469 [ -s "$1" ] || return
1470 echo "Unknown packages:" >&2
1471 cat "$1" >&2
1472 rm "$1"
1476 # Display warnings about critical packages absent (informative)
1478 display_warn() {
1479 [ -s "$1" ] || return
1480 echo "Absent critical packages:" >&2
1481 cat "$1" >&2
1482 rm "$1"
1483 echo "Probably ISO image will be unusable."
1487 # Install packages to rootfs
1489 install_list_to_rootfs() {
1490 local list="$1" rootfs="$2" pkg i ii
1491 local undigest="$rootfs/var/lib/tazpkg/undigest"
1493 # initial tazpkg setup in empty rootfs
1494 tazpkg --root=$rootfs >/dev/null 2>&1
1495 # link rootfs packages cache to the regular packages cache
1496 rm -r "$rootfs/var/cache/tazpkg"
1497 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1499 setup_mirrors mirrors
1501 # Just in case if flavor not contains "tazlito" package
1502 mkdir -p "$rootfs/etc/tazlito"
1504 newline
1505 for pkg in $(cat $list); do
1506 action 'Installing package: %s' "$pkg"
1507 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1508 status
1509 done
1510 newline
1512 restore_mirrors
1513 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1514 for i in fresh repacked; do
1515 ii="$undigest/$i"
1516 [ -d "$ii" ] && rm -rf "$ii"
1517 ii="$rootfs/var/lib/tazpkg/priority"
1518 if [ -f "$ii" ]; then
1519 sed -i "/$i/d" "$ii"
1520 [ -s "$ii" ] || rm "$ii"
1521 fi
1522 done
1523 [ -d "$undigest" ] && \
1524 for i in $(find "$undigest" -type f); do
1525 # Remove all undigest PKGDB files but 'mirror'
1526 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1527 done
1528 [ -d "$undigest" ] && \
1529 rmdir --ignore-fail-on-non-empty "$undigest"
1531 # Un-link packages cache
1532 rm "$rootfs/var/cache/tazpkg"
1534 # Clean /var/lib/tazpkg
1535 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1541 ####################
1542 # Tazlito commands #
1543 ####################
1545 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1546 case "$0" in
1547 *reduplicate)
1548 find ${@:-.} ! -type d -links +1 \
1549 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1550 exit 0 ;;
1551 *deduplicate)
1552 deduplicate "$@"
1553 exit 0 ;;
1554 esac
1557 case "$COMMAND" in
1558 stats)
1559 # Tazlito general statistics from the config file.
1561 title 'Tazlito statistics'
1562 optlist "\
1563 Config file : $CONFIG_FILE
1564 ISO name : $ISO_NAME.iso
1565 Volume name : $VOLUM_NAME
1566 Prepared : $PREPARED
1567 Packages repository : $PACKAGES_REPOSITORY
1568 Distro directory : $DISTRO
1569 Additional files : $ADDFILES
1570 " | sed '/: $/d'
1571 footer
1572 ;;
1575 list-addfiles)
1576 # Simple list of additional files in the rootfs
1577 newline
1578 if [ -d "$ADDFILES/rootfs" ]; then
1579 cd $ADDFILES
1580 find rootfs -type f
1581 else
1582 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1583 fi
1584 newline
1585 ;;
1588 gen-config)
1589 # Generate a new config file in the current dir or the specified
1590 # directory by $2.
1592 if [ -n "$2" ]; then
1593 mkdir -p "$2" && cd "$2"
1594 fi
1596 newline
1597 action 'Generating empty tazlito.conf...'
1598 empty_config_file
1599 status
1601 separator
1602 if [ -f 'tazlito.conf' ] ; then
1603 _ 'Configuration file is ready to edit.'
1604 _ 'File location: %s' "$(pwd)/tazlito.conf"
1605 newline
1606 fi
1607 ;;
1610 configure)
1611 # Configure a tazlito.conf config file. Start by getting
1612 # a empty config file and sed it.
1614 if [ -f 'tazlito.conf' ]; then
1615 rm tazlito.conf
1616 else
1617 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1618 'or in the same directory of the file you want to configure.'
1619 cd /etc
1620 fi
1622 empty_config_file
1624 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1626 # ISO name.
1627 echo -n "ISO name : " ; read answer
1628 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1629 # Volume name.
1630 echo -n "Volume name : " ; read answer
1631 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1632 # Packages repository.
1633 echo -n "Packages repository : " ; read answer
1634 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1635 # Distro path.
1636 echo -n "Distro path : " ; read answer
1637 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1638 footer "Config file is ready to use."
1639 echo 'You can now extract an ISO or generate a distro.'
1640 newline
1641 ;;
1644 gen-iso)
1645 # Simply generate a new iso.
1647 check_root
1648 verify_rootcd
1649 gen_livecd_isolinux
1650 distro_stats
1651 ;;
1654 gen-initiso)
1655 # Simply generate a new initramfs with a new iso.
1657 check_root
1658 verify_rootcd
1659 gen_initramfs "$ROOTFS"
1660 gen_livecd_isolinux
1661 distro_stats
1662 ;;
1665 extract-distro)
1666 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1668 check_root
1669 ISO_IMAGE="$2"
1670 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1671 'Example:\n tazlito image.iso /path/target'
1673 # Set the distro path by checking for $3 on cmdline.
1674 TARGET="${3:-$DISTRO}"
1676 # Exit if existing distro is found.
1677 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1678 'Please clean the distro tree or change directory path.'
1680 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
1682 # Start to mount the ISO.
1683 action 'Mounting ISO image...'
1684 mkdir -p "$TMP_DIR"
1685 # Get ISO file size.
1686 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
1687 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
1688 sleep 2
1689 # Prepare target dir, copy the kernel and the rootfs.
1690 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
1691 status
1693 action 'Copying the Linux kernel...'
1694 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
1695 make_bzImage_hardlink "$TARGET/rootcd/boot"
1696 else
1697 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
1698 fi
1699 status
1701 for i in $(ls $TMP_DIR); do
1702 [ "$i" == 'boot' ] && continue
1703 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
1704 done
1706 for loader in isolinux syslinux extlinux grub; do
1707 [ -d "$TMP_DIR/boot/$loader" ] || continue
1708 action 'Copying %s files...' "$loader"
1709 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
1710 status
1711 done
1713 action 'Copying the rootfs...'
1714 cp $TMP_DIR/boot/rootfs.?z "$TARGET/rootcd/boot"
1715 status
1717 # Extract initramfs.
1718 cd "$TARGET/rootfs"
1719 action 'Extracting the rootfs...'
1720 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
1721 # unpack /usr
1722 for i in etc/tazlito/*.extract; do
1723 [ -f "$i" ] && . $i ../rootcd
1724 done
1725 # Umount and remove temp directory and cd to $TARGET to get stats.
1726 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
1727 cd ..
1728 status
1730 newline
1731 separator
1732 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
1733 echo "Distro tree : $(pwd)"
1734 echo "Rootfs size : $(du -sh rootfs)"
1735 echo "Rootcd size : $(du -sh rootcd)"
1736 footer
1737 ;;
1740 list-flavors)
1741 # Show available flavors.
1742 local list='/etc/tazlito/flavors.list'
1743 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
1744 title 'List of flavors'
1745 cat $list
1746 footer
1747 ;;
1750 show-flavor)
1751 # Show flavor description.
1752 set -e
1753 flavor=${2%.flavor}
1754 flv_dir="$(extract_flavor "$flavor")"
1755 desc="$flv_dir/$flavor.desc"
1756 if [ -n "$brief" ]; then
1757 if [ -z "$noheader" ]; then
1758 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
1759 separator
1760 fi
1761 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
1762 "$(field ISO "$desc")" \
1763 "$(field Rootfs "$desc")" \
1764 "$(field Description "$desc")"
1765 else
1766 separator
1767 cat "$desc"
1768 fi
1769 cleanup
1770 ;;
1773 gen-liveflavor)
1774 # Generate a new flavor from the live system.
1775 FLAVOR=${2%.flavor}
1776 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1778 case "$FLAVOR" in
1779 -?|-h*|--help)
1780 cat <<EOT
1781 SliTaz Live Tool - Version: $VERSION
1783 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
1785 $(boldify '<flavor-patch-file> format:')
1786 $(optlist "\
1787 code data
1788 + package to add
1789 - package to remove
1790 ! non-free package to add
1791 ? display message
1792 @ flavor description
1793 ")
1795 $(boldify 'Example:')
1796 $(optlist "\
1797 @ Developer tools for SliTaz maintainers
1798 + slitaz-toolchain
1799 + mercurial
1800 ")
1801 EOT
1802 exit 1
1803 ;;
1804 esac
1805 mv /etc/tazlito/distro-packages.list \
1806 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
1807 rm -f distro-packages.list non-free.list 2>/dev/null
1808 tazpkg recharge
1810 DESC=""
1811 [ -n "$3" ] && \
1812 while read action pkg; do
1813 case "$action" in
1814 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
1815 -) yes | tazpkg remove $pkg ;;
1816 !) echo $pkg >> non-free.list ;;
1817 @) DESC="$pkg" ;;
1818 \?) echo -en "$pkg"; read action ;;
1819 esac
1820 done < $3
1822 yes '' | tazlito gen-distro
1823 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
1824 mv /etc/tazlito/distro-packages.list.$$ \
1825 /etc/tazlito/distro-packages.list 2>/dev/null
1826 ;;
1829 gen-flavor)
1830 # Generate a new flavor from the last ISO image generated
1831 FLAVOR=${2%.flavor}
1832 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1834 title 'Flavor generation'
1835 check_rootfs
1836 FILES="$FLAVOR.pkglist"
1838 action 'Creating file %s...' "$FLAVOR.flavor"
1839 for i in rootcd rootfs; do
1840 if [ -d "$ADDFILES/$i" ] ; then
1841 FILES="$FILES\n$FLAVOR.$i"
1842 (cd "$ADDFILES/$i"; find . | cpio -o -H newc 2>/dev/null | gzip -9) > $FLAVOR.$i
1843 fi
1844 done
1845 status
1847 answer=$(grep -s ^Description $FLAVOR.desc)
1848 answer=${answer#Description : }
1849 if [ -z "$answer" ]; then
1850 echo -n "Description: "
1851 read answer
1852 fi
1854 action 'Compressing flavor %s...' "$FLAVOR"
1855 echo "Flavor : $FLAVOR" > $FLAVOR.desc
1856 echo "Description : $answer" >> $FLAVOR.desc
1857 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
1858 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
1859 for i in $(ls $ROOTFS$INSTALLED); do
1860 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
1861 EXTRAVERSION=""
1862 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
1863 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
1864 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
1865 echo "$i" >> $FLAVOR.nonfree
1866 else
1867 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
1868 fi
1869 done
1870 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
1871 for i in $LOCALSTATE/undigest/*/mirror ; do
1872 [ -s $i ] && cat $i >> $FLAVOR.mirrors
1873 done
1874 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
1875 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | gzip -9 > $FLAVOR.flavor
1876 rm $(echo -e $FILES)
1877 status
1879 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
1880 ;;
1883 upgrade-flavor)
1884 # Strip versions from pkglist and update estimated numbers in flavor.desc
1885 flavor="${2%.flavor}"
1886 set -e
1887 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1888 set +e
1890 flv_dir="$(extract_flavor "$flavor")"
1892 strip_versions "$flv_dir/$flavor.pkglist"
1894 action 'Updating %s...' "$flavor.desc"
1896 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
1897 set -- $(module calc_sizes "$flv_dir" "$flavor")
1898 restore_mirrors >/dev/null
1900 sed -i -e '/Image is ready/d' \
1901 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
1902 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
1903 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
1904 -e "s|\(Packages *:\).*$|\1 $4|" \
1905 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
1906 "$flv_dir/$flavor.desc"
1908 pack_flavor "$flv_dir" "$flavor"
1909 status
1910 display_unknown "$flv_dir/err"
1911 display_warn "$flv_dir/warn"
1912 cleanup
1913 ;;
1916 extract-flavor)
1917 # Extract a flavor into $FLAVORS_REPOSITORY
1918 flavor="${2%.flavor}"
1919 set -e
1920 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1921 set +e
1923 action 'Extracting %s...' "$flavor.flavor"
1924 flv_dir="$(extract_flavor "$flavor" full)"
1925 storage="$FLAVORS_REPOSITORY/$flavor"
1927 rm -rf "$storage" 2>/dev/null
1928 mkdir -p "$storage"
1929 cp -a "$flv_dir"/* "$storage"
1930 rm "$storage/description"
1931 status
1933 strip_versions "$storage/packages.list"
1935 cleanup
1936 ;;
1939 pack-flavor)
1940 # Create a flavor from $FLAVORS_REPOSITORY.
1941 flavor=${2%.flavor}
1942 storage="$FLAVORS_REPOSITORY/$flavor"
1944 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
1946 action 'Creating flavor %s...' "$flavor"
1947 tmp_dir="$(mktemp -d)"
1949 while read from to; do
1950 [ -s "$storage/$from" ] || continue
1951 cp -a "$storage/$from" "$tmp_dir/$to"
1952 done <<EOT
1953 mirrors $flavor.mirrors
1954 distro.sh $flavor-distro.sh
1955 receipt $flavor.receipt
1956 non-free.list $flavor.nonfree
1957 EOT
1959 # Build the package list.
1960 # It can include a list from another flavor with the keyword @include
1961 if [ -s "$storage/packages.list" ]; then
1962 include=$(grep '^@include' "$storage/packages.list")
1963 if [ -n "$include" ]; then
1964 include=${include#@include }
1965 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
1966 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
1967 else
1968 echo -e "\nERROR: Can't find include package list from $include\n"
1969 fi
1970 fi
1971 # Generate the final/initial package list
1972 [ -s "$storage/packages.list" ] && \
1973 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
1974 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
1975 fi
1977 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
1978 # Process multi-rootfs flavor
1979 . "$storage/receipt"
1980 set -- $ROOTFS_SELECTION
1981 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
1982 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
1983 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
1985 for i in rootcd rootfs; do
1986 mkdir "$tmp_dir/$i"
1987 # Copy extra files from the first flavor
1988 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
1989 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
1990 # Overload extra files by meta flavor
1991 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
1992 [ -n "$(ls $tmp_dir/$i)" ] &&
1993 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
1994 gzip -9 > "$tmp_dir/$flavor.$i"
1995 rm -rf "$tmp_dir/$i"
1996 done
1997 else
1998 # Process plain flavor
1999 for i in rootcd rootfs; do
2000 [ -d "$storage/$i" ] || continue
2001 (cd "$storage/$i";
2002 find . | cpio -o -H newc 2>/dev/null) | gzip -9 > "$tmp_dir/$flavor.$i"
2003 done
2004 fi
2006 unset VERSION MAINTAINER ROOTFS_SELECTION
2007 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2008 ROOTFS_SIZE="$1 (estimated)"
2009 INITRAMFS_SIZE="$2 (estimated)"
2010 ISO_SIZE="$3 (estimated)"
2011 PKGNUM="$4"
2012 . "$storage/receipt"
2014 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2015 Flavor : $FLAVOR
2016 Description : $SHORT_DESC
2017 Version : $VERSION
2018 Maintainer : $MAINTAINER
2019 LiveCD RAM size : $FRUGAL_RAM
2020 Rootfs list : $ROOTFS_SELECTION
2021 Build date : $(date '+%Y%m%d at %T')
2022 Packages : $PKGNUM
2023 Rootfs size : $ROOTFS_SIZE
2024 Initramfs size : $INITRAMFS_SIZE
2025 ISO image size : $ISO_SIZE
2026 ================================================================================
2028 EOT
2030 rm -f $tmp_dir/packages.list
2031 pack_flavor "$tmp_dir" "$flavor"
2032 status
2033 display_unknown "$tmp_dir/err"
2034 display_warn "$flv_dir/warn"
2035 cleanup
2036 ;;
2039 get-flavor)
2040 # Get a flavor's files and prepare for gen-distro.
2041 flavor=${2%.flavor}
2042 title 'Preparing %s distro flavor' "$flavor"
2043 set -e
2044 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2045 set +e
2047 action 'Cleaning %s...' "$DISTRO"
2048 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2049 # Clean old files
2050 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2051 [ -f "$i" ] && rm "$i"
2052 done
2053 mkdir -p "$DISTRO"
2054 status
2056 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2058 action 'Extracting flavor %s...' "$flavor.flavor"
2059 flv_dir="$(extract_flavor "$flavor" info)"
2060 cp -a "$flv_dir"/* .
2061 mv packages.list distro-packages.list
2062 mv -f info /etc/tazlito
2063 status
2065 for i in rootcd rootfs; do
2066 if [ -d "$i" ]; then
2067 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2068 fi
2069 done
2071 rm -f /etc/tazlito/rootfs.list
2072 grep -q '^Rootfs list' description &&
2073 grep '^Rootfs list' description | sed 's/.*: \(.*\)$/\1/' > /etc/tazlito/rootfs.list
2075 action 'Updating %s...' 'tazlito.conf'
2076 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2077 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2078 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2079 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2080 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2081 status
2083 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2084 cleanup
2085 ;;
2088 iso2flavor)
2089 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2090 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2092 FLAVOR=${3%.flavor}
2093 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2094 mount -o loop,ro $2 $TMP_DIR/iso
2095 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2096 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2097 ! -s $TMP_DIR/flavor/*.desc ]; then
2098 _ 'META flavors are not supported.'
2099 umount -d $TMP_DIR/iso
2100 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2101 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2102 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2103 umount -d $TMP_DIR/iso
2104 else
2105 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2106 uncompress $i | \
2107 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2108 done
2109 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2110 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2111 '/etc/slitaz-release' '/boot/rootfs.gz'
2112 umount -d $TMP_DIR/iso
2113 else
2114 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2115 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2116 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2117 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2118 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2119 umount -d $TMP_DIR/iso
2120 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2121 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2122 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2123 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2124 < $TMP_DIR/rootfs$INSTALLED.md5
2125 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2126 if [ -s $TMP_DIR/flavor/*desc ]; then
2127 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2128 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2129 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2130 for i in rootfs rootcd ; do
2131 [ -s $TMP_DIR/flavor/*.list$i ] &&
2132 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2133 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | gzip -9 > $TMP_DIR/$FLAVOR.$i
2134 done
2135 else
2136 find_flavor_rootfs $TMP_DIR/rootfs
2137 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2138 for i in rootfs rootcd ; do
2139 [ "$(ls $TMP_DIR/$i)" ] &&
2140 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | gzip -9 > "$TMP_DIR/$FLAVOR.$i"
2141 done
2142 unset VERSION MAINTAINER
2143 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2144 if [ -n "$DESCRIPTION" ]; then
2145 _n 'Flavor version : '; read -t 30 VERSION
2146 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2147 fi
2149 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2150 Flavor : $FLAVOR
2151 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2152 Version : ${VERSION:-1.0}
2153 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2154 LiveCD RAM size : $RAM_SIZE
2155 Build date : $BUILD_DATE
2156 Packages : $PKGCNT
2157 Rootfs size : $ROOTFS_SIZE
2158 Initramfs size : $INITRAMFS_SIZE
2159 ISO image size : $ISO_SIZE
2160 ================================================================================
2162 EOT
2163 longline "Tazlito can't detect each file installed during \
2164 a package post_install. You should extract this flavor (tazlito extract-flavor \
2165 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2166 tree and remove files generated by post_installs.
2167 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2168 repack the flavor (tazlito pack-flavor $FLAVOR)"
2169 fi
2170 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | gzip -9 > $FLAVOR.flavor
2171 fi
2172 fi
2173 rm -rf $TMP_DIR
2174 ;;
2177 gen-distro)
2178 # Generate a live distro tree with a set of packages.
2180 check_root
2181 start_time=$(date +%s)
2183 # Tazlito options: --iso or --cdrom
2184 CDROM=''
2185 [ -n "$iso" ] && CDROM="-o loop $iso"
2186 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2188 # Check if a package list was specified on cmdline.
2189 if [ -f "$2" ]; then
2190 LIST_NAME="$2"
2191 else
2192 LIST_NAME='distro-packages.list'
2193 fi
2195 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2196 'Please clean the distro tree or change directory path.'
2197 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2198 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2200 # If list not given: build list with all installed packages
2201 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2202 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2203 fi
2205 # Exit if no list name.
2206 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2208 # Start generation.
2209 title 'Tazlito generating a distro'
2211 # Misc checks
2212 mkdir -p "$PACKAGES_REPOSITORY"
2213 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2214 newline
2216 # Mount CD-ROM to be able to repack boot-loader packages
2217 if [ ! -e /boot -a -n "$CDROM" ]; then
2218 mkdir $TMP_MNT
2219 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2220 ln -s "$TMP_MNT/boot" /
2221 if [ ! -d "$ADDFILES/rootcd" ] ; then
2222 mkdir -p "$ADDFILES/rootcd"
2223 for i in $(ls $TMP_MNT); do
2224 [ "$i" == 'boot' ] && continue
2225 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2226 done
2227 fi
2228 else
2229 rmdir "$TMP_MNT"
2230 fi
2231 fi
2233 # Rootfs stuff.
2234 echo 'Preparing the rootfs directory...'
2235 mkdir -p "$ROOTFS"
2236 export root="$ROOTFS"
2237 strip_versions "$LIST_NAME"
2239 if [ "$REPACK" == 'y' ]; then
2240 # Determine full packages list with all dependencies
2241 tmp_dir="$(mktemp -d)"
2242 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2243 touch "$tmp_dir/full.pkglist"
2244 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2246 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2247 while read pkgname pkgver; do
2248 # Is package in full list?
2249 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2250 # Is package already repacked?
2251 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2252 _ 'Repacking %s...' "$pkgname-$pkgver"
2253 tazpkg repack "$pkgname" --quiet
2254 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2255 status
2256 done
2258 rm -r "$tmp_dir"
2259 fi
2261 if [ -f non-free.list ]; then
2262 # FIXME: working in the ROOTFS chroot?
2263 newline
2264 echo 'Preparing non-free packages...'
2265 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2266 for pkg in $(cat 'non-free.list'); do
2267 if [ ! -d "$INSTALLED/$pkg" ]; then
2268 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2269 tazpkg get-install get-$pkg
2270 fi
2271 get-$pkg "$ROOTFS"
2272 fi
2273 tazpkg repack $pkg
2274 pkg=$(ls $pkg*.tazpkg)
2275 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2276 mv $pkg $PACKAGES_REPOSITORY
2277 done
2278 fi
2279 cp $LIST_NAME $DISTRO/distro-packages.list
2280 newline
2282 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2284 cd $DISTRO
2285 cp distro-packages.list $ROOTFS/etc/tazlito
2286 # Copy all files from $ADDFILES/rootfs to the rootfs.
2287 if [ -d "$ADDFILES/rootfs" ] ; then
2288 action 'Copying addfiles content to the rootfs...'
2289 cp -a $ADDFILES/rootfs/* $ROOTFS
2290 status
2291 fi
2293 action 'Root filesystem is generated...'; status
2295 # Root CD part.
2296 action 'Preparing the rootcd directory...'
2297 mkdir -p $ROOTCD
2298 status
2300 # Move the boot dir with the Linux kernel from rootfs.
2301 # The boot dir goes directly on the CD.
2302 if [ -d "$ROOTFS/boot" ] ; then
2303 action 'Moving the boot directory...'
2304 mv $ROOTFS/boot $ROOTCD
2305 cd $ROOTCD/boot
2306 make_bzImage_hardlink
2307 status
2308 fi
2309 cd $DISTRO
2310 # Copy all files from $ADDFILES/rootcd to the rootcd.
2311 if [ -d "$ADDFILES/rootcd" ] ; then
2312 action 'Copying addfiles content to the rootcd...'
2313 cp -a $ADDFILES/rootcd/* $ROOTCD
2314 status
2315 fi
2316 # Execute the distro script used to perform tasks in the rootfs
2317 # before compression. Give rootfs path in arg
2318 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2319 if [ -x "$DISTRO_SCRIPT" ]; then
2320 echo 'Executing distro script...'
2321 sh $DISTRO_SCRIPT $DISTRO
2322 fi
2324 # Execute the custom_rules() found in receipt.
2325 if [ -s "$TOP_DIR/receipt" ]; then
2326 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2327 echo -e "Executing: custom_rules()\n"
2328 . "$TOP_DIR/receipt"
2329 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2330 fi
2331 fi
2333 # Multi-rootfs
2334 if [ -s /etc/tazlito/rootfs.list ]; then
2336 FLAVOR_LIST="$(awk '{
2337 for (i = 2; i <= NF; i+=2)
2338 printf "%s ", i;
2339 }' /etc/tazlito/rootfs.list)"
2341 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2342 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2343 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2345 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2346 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2347 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2348 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2350 n=0
2351 last=$ROOTFS
2352 while read flavor; do
2353 n=$(($n+1))
2354 mkdir ${ROOTFS}0$n
2355 export root="${ROOTFS}0$n"
2356 # initial tazpkg setup in empty rootfs
2357 tazpkg --root=$root >/dev/null 2>&1
2359 newline
2360 boldify "Building $flavor rootfs..."
2362 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2363 cp "$TOP_DIR/$flavor.flavor" .
2365 if [ ! -s "$flavor.flavor" ]; then
2366 # We may have it in $FLAVORS_REPOSITORY
2367 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2368 tazlito pack-flavor $flavor
2369 else
2370 download $flavor.flavor
2371 fi
2372 fi
2374 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2375 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2376 cp $flavor.pkglist $DISTRO/list-packages0$n
2377 status
2379 strip_versions "$DISTRO/list-packages0$n"
2381 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2383 rm -rf ${ROOTFS}0$n/boot
2385 cd $DISTRO
2386 if [ -s $flavor.rootfs ]; then
2387 _n 'Adding %s rootfs extra files...' "$flavor"
2388 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2389 fi
2391 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2392 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2393 status
2395 rm -f $flavor.flavor install-list
2396 mergefs ${ROOTFS}0$n $last
2397 last=${ROOTFS}0$n
2398 done <<EOT
2399 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2400 EOT
2401 #'
2402 i=$(($n+1))
2403 while [ $n -gt 0 ]; do
2404 mv ${ROOTFS}0$n ${ROOTFS}$i
2405 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2406 gen_initramfs ${ROOTFS}$i
2407 n=$(($n-1))
2408 i=$(($i-1))
2409 export LZMA_HISTORY_BITS=26
2410 done
2411 mv $ROOTFS ${ROOTFS}$i
2412 gen_initramfs ${ROOTFS}$i
2413 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2414 else
2415 # Initramfs and ISO image stuff.
2416 gen_initramfs $ROOTFS
2417 fi
2418 gen_livecd_isolinux
2419 distro_stats
2420 cleanup
2421 ;;
2424 clean-distro)
2425 # Remove old distro tree.
2427 check_root
2428 title 'Cleaning: %s' "$DISTRO"
2429 if [ -d "$DISTRO" ] ; then
2430 if [ -d "$ROOTFS" ] ; then
2431 action 'Removing the rootfs...'
2432 rm -f $DISTRO/$INITRAMFS
2433 rm -rf $ROOTFS
2434 status
2435 fi
2436 if [ -d "$ROOTCD" ] ; then
2437 action 'Removing the rootcd...'
2438 rm -rf $ROOTCD
2439 status
2440 fi
2441 action 'Removing eventual ISO image...'
2442 rm -f $DISTRO/$ISO_NAME.iso
2443 rm -f $DISTRO/$ISO_NAME.md5
2444 status
2445 fi
2446 footer
2447 ;;
2450 check-distro)
2451 # Check for a few LiveCD needed files not installed by packages.
2453 # TODO: Remove this function.
2454 # First two files are maintained by tazpkg while it runs on rootfs,
2455 # while last one file should be maintained by tazlito itself.
2456 check_rootfs
2457 title 'Checking distro: %s' "$ROOTFS"
2458 # SliTaz release info.
2459 rel='/etc/slitaz-release'
2460 if [ ! -f "$ROOTFS$rel" ]; then
2461 _ 'Missing release info: %s' "$rel"
2462 else
2463 action 'Release : %s' "$(cat $ROOTFS$rel)"
2464 status
2465 fi
2466 # Tazpkg mirror.
2467 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2468 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2469 todomsg
2470 else
2471 action 'Mirror configuration exists...'
2472 status
2473 fi
2474 # Isolinux msg
2475 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2476 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2477 todomsg
2478 else
2479 action 'Isolinux message seems good...'
2480 status
2481 fi
2482 footer
2483 ;;
2486 writeiso)
2487 # Writefs to ISO image including /home unlike gen-distro we don't use
2488 # packages to generate a rootfs, we build a compressed rootfs with all
2489 # the current filesystem similar to 'tazusb writefs'.
2491 DISTRO='/home/slitaz/distro'
2492 ROOTCD="$DISTRO/rootcd"
2493 COMPRESSION="${2:-none}"
2494 ISO_NAME="${3:-slitaz}"
2495 check_root
2496 # Start info
2497 title 'Write filesystem to ISO'
2498 longline "The command writeiso will write the current filesystem into a \
2499 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2500 newline
2501 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2503 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2504 # Save some space
2505 rm -rf /var/cache/tazpkg/*
2506 rm -f /var/lib/tazpkg/*.bak
2507 rm -rf $DISTRO
2509 # Optionally remove sound card selection and screen resolution.
2510 if [ -z $LaunchedByTazpanel ]; then
2511 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2512 case $anser in
2513 y)
2514 action 'Removing current sound card and screen configurations...'
2515 rm -f /var/lib/sound-card-driver
2516 rm -f /var/lib/alsa/asound.state
2517 rm -f /etc/X11/xorg.conf ;;
2518 *)
2519 action 'Keeping current sound card and screen configurations...' ;;
2520 esac
2521 status
2522 newline
2524 # Optionally remove i18n settings
2525 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2526 case $anser in
2527 y)
2528 action 'Removing current locale/keymap settings...'
2529 newline > /etc/locale.conf
2530 newline > /etc/keymap.conf ;;
2531 *)
2532 action 'Keeping current locale/keymap settings...' ;;
2533 esac
2534 status
2535 fi
2537 # Clean-up files by default
2538 newline > /etc/udev/rules.d/70-persistent-net.rules
2539 newline > /etc/udev/rules.d/70-persistant-cd.rules
2541 # Create list of files including default user files since it is defined in /etc/passwd
2542 # and some new users might have been added.
2543 cd /
2544 echo 'init' > /tmp/list
2545 for dir in bin etc sbin var dev lib root usr home opt; do
2546 [ -d $dir ] && find $dir
2547 done >> /tmp/list
2549 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2550 [ -d $dir ] && echo $dir
2551 done >> /tmp/list
2553 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2555 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2556 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2557 #fi
2558 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2559 touch /var/log/wtmp
2561 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2562 sed -i "/var\/log\/$removelog/d" /tmp/list
2563 done
2565 # Generate initramfs with specified compression and display rootfs
2566 # size in realtime.
2567 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2569 write_initramfs &
2570 sleep 2
2571 cd - > /dev/null
2572 echo -en "\nFilesystem size:"
2573 while [ ! -f /tmp/rootfs ]; do
2574 sleep 1
2575 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2576 done
2577 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2578 echo -e "\n"
2579 rm -f /tmp/rootfs
2581 # Move freshly generated rootfs to the cdrom.
2582 mkdir -p $ROOTCD/boot
2583 mv -f /$INITRAMFS $ROOTCD/boot
2584 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2586 # Now we need the kernel and isolinux files.
2587 copy_from_cd() {
2588 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2589 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2590 unmeta_boot $ROOTCD
2591 umount /media/cdrom
2594 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2595 copy_from_cd;
2596 elif mount | grep /media/cdrom; then
2597 copy_from_cd;
2598 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2599 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2600 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2601 else
2602 touch /tmp/.write-iso-error
2603 longline "When SliTaz is running in RAM the kernel and bootloader \
2604 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
2605 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
2606 echo -en "----\nENTER to continue..."; read i
2607 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2608 copy_from_cd
2609 fi
2611 # Generate the iso image.
2612 touch /tmp/.write-iso
2613 newline
2614 cd $DISTRO
2615 create_iso $ISO_NAME.iso $ROOTCD
2616 action 'Creating the ISO md5sum...'
2617 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2618 status
2620 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2621 rm -f /tmp/.write-iso
2623 if [ -z $LaunchedByTazpanel ]; then
2624 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2625 case $anser in
2626 y)
2627 umount /dev/cdrom 2>/dev/null
2628 eject
2629 echo -n "Please insert a blank CD-ROM and press ENTER..."
2630 read i && sleep 2
2631 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2632 echo -en "----\nENTER to continue..."; read i ;;
2633 *)
2634 exit 0 ;;
2635 esac
2636 fi
2637 ;;
2640 burn-iso)
2641 # Guess CD-ROM device, ask user and burn the ISO.
2643 check_root
2644 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2645 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2646 # We can specify an alternative ISO from the cmdline.
2647 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2648 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2650 title 'Tazlito burn ISO'
2651 echo "CD-ROM device : /dev/$DRIVE_NAME"
2652 echo "Drive speed : $DRIVE_SPEED"
2653 echo "ISO image : $iso"
2654 footer
2656 case $(yesorno 'Burn ISO image?' 'n') in
2657 y)
2658 title 'Starting Wodim to burn the ISO...'
2659 sleep 2
2660 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2661 footer 'ISO image is burned to CD-ROM.'
2662 ;;
2663 *)
2664 die 'Exiting. No ISO burned.'
2665 ;;
2666 esac
2667 ;;
2670 merge)
2671 # Merge multiple rootfs into one iso.
2673 if [ -z "$2" ]; then
2674 cat <<EOT
2675 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2677 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2678 i.e: rootfsN is a subset of rootfsN-1
2679 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2680 The boot loader will select the rootfs according to the RAM size detected.
2682 Example:
2683 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
2685 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
2686 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
2688 EOT
2689 exit 2
2690 fi
2692 shift # skip merge
2693 append="$1 slitaz1"
2694 shift # skip size1
2695 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
2697 ISO=$1.merged
2699 # Extract filesystems
2700 action 'Mounting %s' "$1"
2701 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
2702 status || cleanup_merge
2704 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2705 make_bzImage_hardlink $TMP_DIR/iso/boot
2706 umount -d $TMP_DIR/mnt
2707 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
2708 _ '%s is already a merged iso. Aborting.' "$1"
2709 cleanup_merge
2710 fi
2711 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
2712 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
2713 if [ ! -f /boot/isolinux/ifmem.c32 -a
2714 ! -f /boot/isolinux/c32box.c32 ]; then
2715 cat <<EOT
2716 No file /boot/isolinux/ifmem.c32
2717 Please install syslinux package !
2718 EOT
2719 rm -rf $TMP_DIR
2720 exit 1
2721 fi
2722 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
2723 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
2724 fi
2726 action 'Extracting %s' 'iso/rootfs.gz'
2727 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
2728 [ -d $TMP_DIR/rootfs1/etc ]
2729 status || cleanup_merge
2731 n=1
2732 while [ -n "$2" ]; do
2733 shift # skip rootfs N-1
2734 p=$n
2735 n=$(($n + 1))
2736 append="$append $1 slitaz$n"
2737 shift # skip size N
2738 mkdir -p $TMP_DIR/rootfs$n
2740 action 'Extracting %s' "$1"
2741 extract_rootfs $1 $TMP_DIR/rootfs$n &&
2742 [ -d "$TMP_DIR/rootfs$n/etc" ]
2743 status || cleanup_merge
2745 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
2746 action 'Creating %s' "rootfs$p.gz"
2747 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
2748 status
2749 done
2750 action 'Creating %s' "rootfs$n.gz"
2751 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
2752 status
2753 rm -f $TMP_DIR/iso/boot/rootfs.gz
2754 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
2755 create_iso $ISO $TMP_DIR/iso
2756 rm -rf $TMP_DIR
2757 ;;
2760 repack)
2761 # Repack an iso with maximum lzma compression ratio.
2763 ISO=$2
2764 mkdir -p $TMP_DIR/mnt
2766 # Extract filesystems
2767 action 'Mounting %s' "$ISO"
2768 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
2769 status || cleanup_merge
2771 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2772 umount -d $TMP_DIR/mnt
2774 for i in $TMP_DIR/iso/boot/rootfs* ; do
2775 action 'Repacking %s' "$(basename $i)"
2776 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
2777 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
2778 align_to_32bits $i
2779 status
2780 done
2782 create_iso $ISO $TMP_DIR/iso
2783 rm -rf $TMP_DIR
2784 ;;
2787 build-loram)
2788 # Build a Live CD for low RAM systems.
2790 ISO="$2"
2791 OUTPUT="$3"
2792 [ -z "$3" ] && \
2793 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
2794 mkdir -p "$TMP_DIR/iso"
2795 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
2796 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
2797 if ! check_iso_for_loram ; then
2798 umount -d "$TMP_DIR/iso"
2799 die "$ISO is not a valid SliTaz live CD. Abort."
2800 fi
2801 case "$4" in
2802 cdrom) build_loram_cdrom ;;
2803 http) build_loram_http ;;
2804 *) build_loram_ram ;;
2805 esac
2806 umount $TMP_DIR/iso # no -d: needs /proc
2807 losetup -d $loopdev
2808 rm -rf $TMP_DIR
2809 ;;
2812 emu-iso)
2813 # Emulate an ISO image with Qemu.
2814 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2815 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
2816 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
2817 echo -e "\nStarting Qemu emulator:\n"
2818 echo -e "qemu $QEMU_OPTS $iso\n"
2819 qemu $QEMU_OPTS $iso
2820 ;;
2823 deduplicate)
2824 # Deduplicate files in a tree
2825 shift
2826 deduplicate "$@"
2827 ;;
2830 usage|*)
2831 # Print usage also for all unknown commands.
2832 usage
2833 ;;
2834 esac
2836 exit 0