tazlito view tazlito @ rev 432

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