tazlito view tazlito @ rev 429

writeiso: fix message
author Xander Ziiryanoff <psychomaniak@xakep.ru>
date Fri Aug 19 17:28:40 2016 +0200 (2016-08-19)
parents da648e687bb6
children 000740da7eac
line source
1 #!/bin/sh
2 # TazLito - SliTaz Live Tool.
3 #
4 # Tazlito is a tool to help generate and configure SliTaz Live CD
5 # ISO images. You can create a custom distro in one command from a list of
6 # packages, extract an existing ISO image to hack it, create a new initramfs
7 # and/or a new ISO. Most commands must be run by root, except the stats
8 # and the configuration file manipulation.
9 #
10 # (C) 2007-2016 SliTaz - GNU General Public License.
11 #
12 # Authors: see the AUTHORS file
13 #
15 VERSION='6.0'
17 . /lib/libtaz.sh
18 # Force to use Busybox cpio and wget
19 alias cpio='busybox cpio'
20 alias wget='busybox wget'
22 # Tazlito configuration variables to be shorter
23 # and to use words rather than numbers.
24 COMMAND="$1"
25 LIST_NAME="$2"
26 TMP_DIR="/tmp/tazlito-$$-$RANDOM"
27 TMP_MNT="/media/tazlito-$$-$RANDOM"
28 TOP_DIR="$(pwd)"
29 INITRAMFS='rootfs.gz'
30 LOCALSTATE='/var/lib/tazpkg'
31 INSTALLED="$LOCALSTATE/installed"
32 CACHE_DIR='/var/cache/tazpkg'
33 MIRROR="$LOCALSTATE/mirror"
34 DEFAULT_MIRROR="http://mirror1.slitaz.org/packages/$(cat /etc/slitaz-release)/"
36 log='/var/log/tazlito.log'
37 if [ $(id -u) -eq 0 ]; then
38 newline > $log
39 fi
42 cleanup() {
43 if [ -d "$TMP_MNT" ]; then
44 umount $TMP_MNT
45 rmdir $TMP_MNT
46 rm -f /boot
47 fi
48 [ -d "$tmp_dir" ] && rm -r "$tmp_dir"
49 [ -d "$flv_dir" ] && rm -r "$flv_dir"
50 }
53 # Report error and finish work
55 die() {
56 emsg "<n>$(longline "$@")<n> " >&2
57 cleanup
58 exit 1
59 }
62 # Run Tazlito module
63 module() {
64 local mod="$1"; shift
65 /usr/libexec/tazlito/$mod $@
66 }
70 # Try to include config file, continue if command is gen-config or exit.
71 # The main config used by default is in /etc/tazlito.
72 # Specific distro config file can be put in a distro tree.
73 for i in /etc/tazlito "$TOP_DIR"; do
74 [ -f "$i/tazlito.conf" ] && CONFIG_FILE="$i/tazlito.conf"
75 done
77 [ -z "$CONFIG_FILE" -a "$COMMAND" != 'gen-config' ] && \
78 die 'Unable to find any configuration file.' \
79 'Please read the docs or run `tazlito gen-config` to get an empty config file.'
81 . $CONFIG_FILE
83 # While Tazpkg is not used the default mirror URL file does not exist
84 # and user can't recharge the list of flavors.
85 [ $(id -u) -eq 0 -a ! -f "$MIRROR" ] && echo "$DEFAULT_MIRROR" > $MIRROR
87 # Set the rootfs and rootcd path with $DISTRO
88 # configuration variable.
89 ROOTFS="$DISTRO/rootfs"
90 ROOTCD="$DISTRO/rootcd"
95 #####################
96 # Tazlito functions #
97 #####################
100 # Print the usage.
102 usage () {
103 [ $(basename $0) == 'tazlito' ] && cat <<EOT
105 SliTaz Live Tool - Version: $(colorize 34 "$VERSION")
107 $(boldify "Usage:") tazlito [command] [list|iso|flavor|compression] [dir|iso]
109 $(boldify "Commands:")
110 EOT
111 optlist "\
112 usage Print this short usage.
113 stats View Tazlito and distro configuration statistics.
114 list-addfiles Simple list of additional files in the rootfs.
115 gen-config Generate a new configuration file for a distro.
116 configure Configure the main config file or a specific tazlito.conf.
117 gen-iso Generate a new ISO from a distro tree.
118 gen-initiso Generate a new initramfs and ISO from the distro tree.
119 list-flavors List all flavors available on the mirror.
120 gen-flavor Generate a new Live CD description.
121 gen-liveflavor Generate a Live CD description from current system.
122 show-flavor Show Live CD description.
123 get-flavor Get a flavor's list of packages (--noup to skip update).
124 upgrade-flavor Update package list to the latest available versions.
125 extract-flavor Extract a *.flavor file into $FLAVORS_REPOSITORY.
126 pack-flavor Pack (and update) a flavor from $FLAVORS_REPOSITORY.
127 iso2flavor Create a flavor file from a SliTaz ISO image.
128 extract-distro Extract an ISO to a directory and rebuild Live CD tree.
129 gen-distro Generate a Live distro and ISO from a list of packages.
130 clean-distro Remove all files generated by gen-distro.
131 check-distro Help to check if distro is ready to release.
132 writeiso Use running system to generate a bootable ISO (with /home).
133 merge Merge multiple rootfs into one ISO.
134 deduplicate Deduplicate files in a tree.
135 repack Recompress rootfs into ISO with maximum ratio.
136 build-loram Generate a Live CD for low-RAM systems.
137 emu-iso Emulate an ISO image with QEMU.
138 burn-iso Burn ISO image to a CD-ROM using Wodim.
139 "
140 }
143 yesorno() {
144 local answer
145 echo -n "$1 (y=yes, n=no) [$2] " >&2
146 case "$DEFAULT_ANSWER" in
147 Y|y) answer="y";;
148 N|n) answer="n";;
149 *)
150 read -t 30 answer
151 [ -z "$answer" ] && answer="$2"
152 [ "$answer" != 'y' -a "$answer" != 'n' ] && answer="$2"
153 ;;
154 esac
155 echo "$answer"
156 }
159 field() {
160 grep "^$1" "$2" | \
161 case "$1" in
162 Desc*) sed 's|^.*: *||';;
163 *) sed 's/.*: \([0-9KMG\.]*\).*/\1/';;
164 esac
165 }
168 todomsg() {
169 echo -e "\\033[70G[ \\033[1;31mTODO\\033[0;39m ]"
170 }
173 # Download a file from this mirror
175 download_from() {
176 local i mirrors="$1"
177 shift
178 for i in $mirrors; do
179 case "$i" in
180 http://*|ftp://*|https://*)
181 wget -c $i$@ && break;;
182 *)
183 cp $i/$1 . && break;;
184 esac
185 done
186 }
189 # Download a file trying all mirrors
191 download() {
192 local i
193 for i in $(cat $MIRROR $LOCALSTATE/undigest/*/mirror 2>/dev/null); do
194 download_from "$i" "$@" && break
195 done
196 }
199 # Execute hooks provided by some packages
201 genisohooks() {
202 local here="$(pwd)"
203 for i in $(ls $ROOTFS/etc/tazlito/*.$1 2>/dev/null); do
204 cd $ROOTFS
205 . $i $ROOTCD
206 done
207 cd "$here"
208 }
211 # Echo the package name if the tazpkg is already installed
213 installed_package_name() {
214 local tazpkg="$1" package VERSION EXTRAVERSION
216 # Try to find package name and version to be able
217 # to repack it from installation
218 # A dash (-) can exist in name *and* in version
219 package=${tazpkg%-*}
220 i=$package
221 while true; do
222 unset VERSION EXTRAVERSION
223 eval $(grep -s ^VERSION= $INSTALLED/$i/receipt)
224 eval $(grep -s ^EXTRAVERSION= $INSTALLED/$i/receipt)
225 if [ "$i-$VERSION$EXTRAVERSION" == "$tazpkg" ]; then
226 echo $i
227 break
228 fi
229 case "$i" in
230 *-*);;
231 *) break;;
232 esac
233 i=${i%-*}
234 done
235 }
238 # Check for the rootfs tree.
240 check_rootfs() {
241 [ -d "$ROOTFS/etc" ] || die 'Unable to find a distro rootfs...'
242 }
245 # Check for the boot dir into the root CD tree.
247 verify_rootcd() {
248 [ -d "$ROOTCD/boot" ] || die 'Unable to find the rootcd boot directory...'
249 }
252 # isolinux.conf doesn't know the kernel version.
253 # We name the kernel image 'bzImage'.
254 # isolinux/syslinux first tries the '64' suffix with a 64bits cpu.
256 make_bzImage_hardlink() {
257 if [ -s ${1:-.}/vmlinuz*slitaz ]; then
258 rm -f ${1:-.}/bzImage 2>/dev/null
259 ln ${1:-.}/vmlinuz*slitaz ${1:-.}/bzImage
260 fi
261 if [ -s ${1:-.}/vmlinuz*slitaz64 ]; then
262 rm -f ${1:-.}/bzImage64 2> /dev/null
263 ln ${1:-.}/vmlinuz*slitaz64 ${1:-.}/bzImage64
264 fi
265 }
268 create_iso() {
269 cd $2
270 deduplicate
272 action 'Computing md5...'
273 find * -type f ! -name md5sum ! -name 'vmlinuz*' -exec md5sum {} \; > md5sum
274 sed -i -e '/ boot\/isolinux\/isolinux.bin$/d' \
275 -e '/ boot\/isolinux\/boot.cat$/d' md5sum
276 status
278 cd - >/dev/null
279 title 'Generating ISO image'
281 _ 'Generating %s' "$1"
282 make_bzImage_hardlink $2/boot
283 genisoimage -R -o $1 -hide-rr-moved -b boot/isolinux/isolinux.bin \
284 -c boot/isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
285 -V "$VOLUM_NAME" -p "$PREPARED" -input-charset utf-8 \
286 -A "tazlito $VERSION/$(genisoimage --version)" \
287 -copyright README -P "www.slitaz.org" -boot-info-table $2
288 if [ -x '/usr/bin/isohybrid' ]; then
289 action 'Creating hybrid ISO...'
290 /usr/bin/isohybrid $1 -entry 2 2>/dev/null
291 status
292 fi
294 if [ -s '/etc/tazlito/info' ]; then
295 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
296 action 'Storing ISO info...'
297 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
298 status
299 fi
300 fi
302 if [ -x '/usr/bin/iso2exe' ]; then
303 echo 'Creating EXE header...'
304 /usr/bin/iso2exe $1 2>/dev/null
305 fi
306 }
309 # Generate a new ISO image using isolinux.
311 gen_livecd_isolinux() {
312 # Some packages may want to alter iso
313 genisohooks iso
314 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
316 # Set date for boot msg.
317 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
318 DATE=$(date +%Y%m%d)
319 action 'Setting build date to: %s...' "$DATE"
320 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
321 status
322 fi
324 cd $DISTRO
325 create_iso $ISO_NAME.iso $ROOTCD
327 action 'Creating the ISO md5sum...'
328 md5sum $ISO_NAME.iso > $ISO_NAME.md5
329 status
331 separator
332 # Some packages may want to alter final iso
333 genisohooks final
334 }
337 lzma_history_bits() {
338 #
339 # This generates an ISO which boots with Qemu but gives
340 # rootfs errors in frugal or liveUSB mode.
341 #
342 # local n
343 # local sz
344 # n=20 # 1Mb
345 # sz=$(du -sk $1 | cut -f1)
346 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
347 # n=$(( $n + 1 ))
348 # sz=$(( $sz / 2 ))
349 # done
350 # echo $n
351 echo 24
352 }
355 lzma_switches() {
356 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
357 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1}"
358 }
361 lzma_set_size() {
362 # Update size field for lzma'd file packed using -si switch
363 return # Need to fix kernel code?
365 local n i
366 n=$(unlzma < $1 | wc -c)
367 for i in $(seq 1 8); do
368 printf '\\\\x%02X' $(($n & 255))
369 n=$(($n >> 8))
370 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
371 }
374 align_to_32bits() {
375 local size=$(stat -c %s ${1:-/dev/null})
376 [ $((${size:-0} & 3)) -ne 0 ] &&
377 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
378 }
381 # Pack rootfs
383 pack_rootfs() {
384 ( cd $1; find . -print | cpio -o -H newc ) | \
385 case "$COMPRESSION" in
386 none)
387 _ 'Creating %s without compression...' 'initramfs'
388 cat > $2
389 ;;
390 gzip)
391 _ 'Creating %s with gzip compression...' 'initramfs'
392 gzip -9 > $2
393 ;;
394 *)
395 _ 'Creating %s with lzma compression...' 'initramfs'
396 lzma e -si -so $(lzma_switches $1) > $2
397 lzma_set_size $2
398 ;;
399 esac
400 align_to_32bits $2
401 echo 1 > /tmp/rootfs
402 }
405 # Compression functions for writeiso.
407 write_initramfs() {
408 case "$COMPRESSION" in
409 lzma)
410 _n 'Creating %s with lzma compression...' "$INITRAMFS"
411 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
412 align='y'
413 lzma_set_size "/$INITRAMFS"
414 ;;
415 gzip)
416 _ 'Creating %s with gzip compression...' "$INITRAMFS"
417 cpio -o -H newc | gzip -9 > "/$INITRAMFS"
418 [ -x /usr/bin/advdef ] && advdef -z4 "/$INITRAMFS"
419 ;;
420 *)
421 # align='y'
422 _ 'Creating %s without compression...' "$INITRAMFS"
423 cpio -o -H newc > "/$INITRAMFS"
424 ;;
425 esac < /tmp/list
426 [ "$align" == 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
427 echo 1 > /tmp/rootfs
428 }
431 # Deduplicate files (MUST be on the same filesystem).
433 deduplicate() {
434 find "${@:-.}" -type f -size +0c -xdev -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
435 (
436 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""
437 while read attr inode link file; do
438 [ -L "$file" ] && continue
439 if [ "$attr" == "$old_attr" -a "$inode" != "$old_inode" ]; then
440 if cmp "$file" "$old_file" >/dev/null 2>&1 ; then
441 rm -f "$file"
442 if ln "$old_file" "$file" 2>/dev/null; then
443 inode="$old_inode"
444 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
445 save="$(($save+(${attr%%-*}+512)/1024))"
446 else
447 cp -a "$old_file" "$file"
448 fi
449 fi
450 fi
451 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
452 done
453 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
454 )
456 find "$@" -type l -xdev -exec stat -c '%s-%u-%g-TARGET- %i %h %n' {} \; | sort | \
457 (
458 old_attr=""; hardlinks=0;
459 while read attr inode link file; do
460 attr="${attr/-TARGET-/-$(readlink $file)}"
461 if [ "$attr" == "$old_attr" ]; then
462 if [ "$inode" != "$old_inode" ]; then
463 rm -f "$file"
464 if ln "$old_file" "$file" 2>/dev/null; then
465 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
466 else
467 cp -a "$old_file" "$file"
468 fi
469 fi
470 else
471 old_file="$file"
472 old_attr="$attr"
473 old_inode="$inode"
474 fi
475 done
476 _ '%s duplicate symlinks.' "$hardlinks"
477 )
478 }
481 # Generate a new initramfs from the root filesystem.
483 gen_initramfs() {
484 # Just in case CTRL+c
485 rm -f $DISTRO/gen
487 # Some packages may want to alter rootfs
488 genisohooks rootfs
489 cd $1
491 # Link duplicate files
492 deduplicate
494 # Use lzma if installed. Display rootfs size in realtime.
495 rm -f /tmp/rootfs 2>/dev/null
496 pack_rootfs . $DISTRO/$(basename $1).gz &
497 sleep 2
498 echo -en "\nFilesystem size:"
499 while [ ! -f /tmp/rootfs ]; do
500 sleep 1
501 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
502 done
503 echo -e "\n"
504 rm -f /tmp/rootfs
505 cd $DISTRO
506 mv $(basename $1).gz $ROOTCD/boot
507 }
510 distro_sizes() {
511 if [ -n "$start_time" ]; then
512 time=$(($(date +%s) - $start_time))
513 sec=$time
514 div=$(( ($time + 30) / 60))
515 [ "$div" -ne 0 ] && min="~ ${div}m"
516 _ 'Build time : %ss %s' "$sec" "$min"
517 fi
518 cat <<EOT
519 Build date : $(date +%Y%m%d)
520 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
521 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
522 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
523 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
524 EOT
525 footer "Image is ready: $ISO_NAME.iso"
526 }
529 # Print ISO and rootfs size.
531 distro_stats() {
532 title 'Distro statistics: %s' "$DISTRO"
533 distro_sizes
534 }
537 # Create an empty configuration file.
539 empty_config_file() {
540 cat >> tazlito.conf <<"EOF"
541 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
542 #
544 # Name of the ISO image to generate.
545 ISO_NAME=""
547 # ISO image volume name.
548 VOLUM_NAME="SliTaz"
550 # Name of the preparer.
551 PREPARED="$USER"
553 # Path to the packages repository and the packages.list.
554 PACKAGES_REPOSITORY=""
556 # Path to the distro tree to gen-distro from a list of packages.
557 DISTRO=""
559 # Path to the directory containing additional files
560 # to copy into the rootfs and rootcd of the LiveCD.
561 ADDFILES="$DISTRO/addfiles"
563 # Default answer for binary question (Y or N)
564 DEFAULT_ANSWER="ASK"
566 # Compression utility (lzma, gzip or none)
567 COMPRESSION="lzma"
568 EOF
569 }
572 # Extract rootfs.gz somewhere
574 extract_rootfs() {
575 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
576 # First part (lzcat or zcat) may not fail, but cpio will fail on uncorrect format
577 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
578 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
579 (cd "$2"; cat "$1" | cpio -idm --quiet 2>/dev/null)
580 }
583 # Extract flavor file to temp directory
585 extract_flavor() {
586 # Input: $1 - flavor name to extract;
587 # $2 = absent/empty: just extract 'outer layer'
588 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
589 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
590 # Output: temp dir path where flavor was extracted
591 local f="$1.flavor" from to infos="$1.desc"
592 [ -f "$f" ] || die "File '$f' not found"
593 local dir="$(mktemp -d)"
594 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
596 if [ -n "$2" ]; then
597 cd $dir
599 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
601 for i in rootcd rootfs; do
602 [ -f "$1.$i" ] || continue
603 mkdir "$i"
604 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
605 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
606 rm "$1.$i"
607 done
608 # Info to be stored inside ISO
609 [ "$2" == info ] && echo -e $infos | cpio -o -H newc | gzip -9 > info
610 rm $1.list*
612 # Renames
613 while read from to; do
614 [ -f "$from" ] || continue
615 mv "$from" "$to"
616 done <<EOT
617 $1.nonfree non-free.list
618 $1.pkglist packages.list
619 $1-distro.sh distro.sh
620 $1.receipt receipt
621 $1.mirrors mirrors
622 $1.desc description
623 EOT
624 fi
626 echo $dir
627 }
630 # Pack flavor file from temp directory
632 pack_flavor() {
633 (cd "$1"; ls | grep -v err | cpio -o -H newc) | gzip -9 > "$2.flavor"
634 }
637 # Remove duplicate files
639 mergefs() {
640 # Note, many packages have files with spaces in the name
641 IFS=$'\n'
643 local size1=$(du -hs "$1" | awk '{ print $1 }')
644 local size2=$(du -hs "$2" | awk '{ print $1 }')
645 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
647 # merge symlinks files and devices
648 ( cd "$1"; find ) | \
649 while read file; do
650 if [ -L "$1/$file" ]; then
651 [ -L "$2/$file" -a "$(readlink "$1/$file")" == "$(readlink "$2/$file")" ] &&
652 rm -f "$2/$file"
654 elif [ -f "$1/$file" ]; then
655 [ -f "$2/$file" ] && cmp -s "$1/$file" "$2/$file" &&
656 rm -f "$2/$file"
658 [ -f "$2/$file" ] &&
659 [ "$(basename "$file")" == 'volatile.cpio.gz' ] &&
660 [ "$(dirname $(dirname "$file"))" == ".$INSTALLED" ] &&
661 rm -f "$2/$file"
663 elif [ -b "$1/$file" ]; then
664 [ -b "$2/$file" ] &&
665 [ "$(stat -c '%a:%u:%g:%t:%T' "$1/$file")" == \
666 "$(stat -c '%a:%u:%g:%t:%T' "$2/$file")" ] &&
667 rm -f "$2/$file"
669 elif [ -c "$1/$file" ]; then
670 [ -c "$2/$file" ] &&
671 [ "$(stat -c '%a:%u:%g:%t:%T' "$1/$file")" == \
672 "$(stat -c '%a:%u:%g:%t:%T' "$2/$file")" ] &&
673 rm -f "$2/$file"
674 fi
675 done
677 # cleanup directories; TODO: simplify
678 ( cd "$1"; find . -type d ) | sed '1!G;h;$!d' | \
679 while read file; do
680 [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
681 done
683 unset IFS
684 status
685 }
688 cleanup_merge() {
689 rm -rf $TMP_DIR
690 exit 1
691 }
694 # Update isolinux config files for multiple rootfs
696 update_bootconfig() {
697 local files
698 action 'Updating boot config files...'
699 files="$(grep -l 'include common' $1/*.cfg)"
700 for file in $files; do
701 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
702 if (/label/) label=$0;
703 else if (/kernel/) kernel=$0;
704 else if (/append/) {
705 i=index($0,"rootfs.gz");
706 append=substr($0,i+9);
707 }
708 else if (/include/) {
709 for (i = 1; i <= n; i++) {
710 print label i
711 print kernel;
712 initrd="initrd=/boot/rootfs" n ".gz"
713 for (j = n - 1; j >= i; j--) {
714 initrd=initrd ",/boot/rootfs" j ".gz";
715 }
716 printf "\tappend %s%s\n",initrd,append;
717 print "";
718 }
719 print;
720 }
721 else print;
722 }' < $file > $file.$$
723 mv -f $file.$$ $file
724 done
725 sel="$(echo $2 | awk '{
726 for (i=1; i<=NF; i++)
727 if (i % 2 == 0) printf " slitaz%d", i/2
728 else printf " %s", $i
729 }')"
731 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
733 label slitaz
734 kernel /boot/isolinux/ifmem.c32
735 append$sel noram
737 label noram
738 config noram.cfg
740 EOT
742 # Update vesamenu
743 if [ -s "$1/isolinux.cfg" ]; then
744 files="$files $1/isolinux.cfg"
745 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
746 BEGIN {
747 kernel = " COM32 c32box.c32"
748 }
749 {
750 if (/ROWS/) print "MENU ROWS " n+$3;
751 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
752 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
753 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
754 else if (/VSHIFT/) {
755 x = $3-n;
756 if (x < 0) x = 0;
757 print "MENU VSHIFT " x;
758 }
759 else if (/rootfs.gz/) {
760 linux = "";
761 if (/bzImage/) linux = "linux /boot/bzImage ";
762 i = index($0, "rootfs.gz");
763 append = substr($0, i+9);
764 printf "\tkernel /boot/isolinux/ifmem.c32\n";
765 printf "\tappend%s noram\n", sel;
766 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
767 for (i = 1; i <= n; i++) {
768 print "LABEL slitaz" i
769 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
770 printf "%s\n", kernel;
771 initrd = "initrd=/boot/rootfs" n ".gz"
772 for (j = n - 1; j >= i; j--) {
773 initrd = initrd ",/boot/rootfs" j ".gz";
774 }
775 printf "\tappend %s%s%s\n\n", linux, initrd, append;
776 }
777 }
778 else if (/bzImage/) kernel = $0;
779 else print;
780 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
781 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
782 fi
784 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
785 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
786 cat > $1/noram.cfg <<EOT
787 implicit 0
788 prompt 1
789 timeout 80
790 $(grep '^F[0-9]' $1/isolinux.cfg)
792 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
793 say Not enough RAM to boot slitaz. Trying hacker mode...
794 default hacker
795 label hacker
796 KERNEL /boot/bzImage
797 append rw root=/dev/null vga=normal
799 label reboot
800 EOT
802 if [ -s $1/c32box.c32 ]; then
803 cat >> $1/noram.cfg <<EOT
804 COM32 c32box.c32
805 append reboot
807 label poweroff
808 COM32 c32box.c32
809 append poweroff
811 EOT
812 else
813 echo " com32 reboot.c32" >> $1/noram.cfg
814 fi
816 # Restore real label names
817 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
818 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
819 while read pat; do
820 sed -i "s/slitaz$pat/" $files
821 done
822 status
823 }
826 # Uncompress rootfs or module to stdout
828 uncompress() {
829 zcat $1 2> /dev/null || xzcat $1 2> /dev/null || unlzma < $1 || cat $i
830 }
833 # Install a missing package
835 install_package() {
836 if [ -z "$2" ]; then
837 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
838 else
839 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
840 fi
841 case "$answer" in
842 y)
843 # We don't want package on host cache.
844 action 'Getting and installing package: %s' "$1"
845 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
846 status ;;
847 *)
848 return 1 ;;
849 esac
850 }
853 # Check iso for loram transformation
855 check_iso_for_loram() {
856 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
857 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
858 }
861 # Build initial rootfs for loram ISO ram/cdrom/http
863 build_initfs() {
864 urliso="mirror.switch.ch/ftp/mirror/slitaz \
865 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
866 mirror3.slitaz.org mirror.slitaz.org"
867 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
868 [ -z "$version" ] && die "Can't find the kernel version." \
869 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
871 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
872 need_lib=false
873 for i in bin dev run mnt proc tmp sys lib/modules; do
874 mkdir -p $TMP_DIR/initfs/$i
875 done
876 ln -s bin $TMP_DIR/initfs/sbin
877 ln -s . $TMP_DIR/initfs/usr
878 for aufs in aufs overlayfs; do
879 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
880 install_package $aufs $version && break
881 done || return 1
882 cp /init $TMP_DIR/initfs/
883 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
884 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
885 $TMP_DIR/initfs/lib/modules 2>/dev/null
886 cp -a /dev/tty0 /dev/fd0 $TMP_DIR/initfs/dev 2>/dev/null
887 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
888 $TMP_DIR/initfs/lib/modules
889 if [ "$1" == 'cdrom' ]; then
890 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
891 else
892 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
893 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
894 install_package linux-squashfs $version || return 1
895 done
896 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
897 $TMP_DIR/initfs/lib/modules
898 ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
899 cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
900 fi
901 for i in $(ls /dev/[hs]d[a-f]*); do
902 cp -a $i $TMP_DIR/initfs/dev
903 done
904 if [ "$1" == 'http' ]; then
905 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
906 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
907 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
908 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
909 cp -a /dev/fuse $TMP_DIR/initfs/dev
910 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
911 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
912 else
913 need_lib=true
914 fi
915 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
916 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
917 else
918 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
919 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
920 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
921 cp -a /lib/librt* $TMP_DIR/initfs/lib
922 cp -a /lib/libdl* $TMP_DIR/initfs/lib
923 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
924 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
925 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
926 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
927 need_lib=true
928 fi
929 cd $TMP_DIR/fs
930 echo 'Getting slitaz-release & ethernet modules...'
931 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
932 uncompress $i | cpio -idmu etc/slitaz-release lib/modules* >/dev/null
933 done
934 cd - > /dev/null
935 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
936 find $TMP_DIR/fs/lib/modules/*/kernel/drivers/net/ethernet \
937 -type f -name '*.ko*' | while read mod; do
938 f=$TMP_DIR/initfs/lib/modules/$(basename $mod | sed s/..z$//)
939 uncompress $mod > $f
940 grep -q alias=pci: $f || rm -f $f
941 done
942 for i in $TMP_DIR/initfs/lib/modules/*.ko ; do
943 f=$(basename $i)..z
944 grep -q $f:$ $TMP_DIR/fs/lib/modules/*/modules.dep && continue
945 deps="$(grep $f: $TMP_DIR/fs/lib/modules/*/modules.dep | sed 's/.*: //')"
946 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > $TMP_DIR/initfs/lib/modules/$(basename $i .ko).dep
947 for j in $deps; do
948 mod=$(ls $TMP_DIR/fs/lib/modules/*/$j)
949 uncompress $mod > $TMP_DIR/initfs/lib/modules/$(basename $j | sed s/..z$//)
950 done
951 done
952 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"
953 _n 'List of URLs to insert: '
954 read -t 30 urliso2
955 urliso="$urliso2 $urliso"
956 fi
957 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
958 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
959 sed -i 's/LD_T.*ot/newline/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
960 else
961 cp /bin/busybox $TMP_DIR/initfs/bin
962 need_lib=true
963 fi
964 for i in $($TMP_DIR/initfs/bin/busybox | awk \
965 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
966 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
967 done
968 for i in /dev/console /dev/loop* /dev/null /dev/tty /dev/zero \
969 /dev/kmem /dev/mem /dev/random /dev/urandom; do
970 cp -a $i $TMP_DIR/initfs/dev
971 done
972 $need_lib && for i in /lib/ld-* /lib/lib[cm].so* /lib/lib[cm]-* ; do
973 cp -a $i $TMP_DIR/initfs/lib
974 done
975 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
976 #!/bin/sh
978 getarg() {
979 grep -q " \$1=" /proc/cmdline || return 1
980 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
981 return 0
982 }
984 copy_rootfs() {
985 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
986 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
987 [ \$(( \$total / \$need )) -gt 1 ] || return 1
988 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
989 path=/mnt/
990 return 0
991 else
992 rm -f /mnt/rootfs*
993 return 1
994 fi
995 }
997 echo "Switching / to tmpfs..."
998 mount -t proc proc /proc
999 size="\$(grep rootfssize= < /proc/cmdline | \\
1000 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1001 [ -n "\$size" ] || size="-o size=90%"
1003 mount -t sysfs sysfs /sys
1004 for i in /lib/modules/*.ko ; do
1005 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1006 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1007 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1008 insmod /lib/modules/\$k.ko 2> /dev/null
1009 done
1010 insmod \$i 2> /dev/null
1011 break
1012 done
1013 done
1014 umount /sys
1015 while read var default; do
1016 eval \$var=\$default
1017 getarg \$var \$var
1018 done <<EOT
1019 eth eth0
1020 dns 208.67.222.222,208.67.220.220
1021 netmask 255.255.255.0
1022 gw
1023 ip
1024 EOT
1025 if [ -n "\$ip" ]; then
1026 ifconfig \$eth \$ip netmask \$netmask up
1027 route add default gateway \$gw
1028 for i in \$(echo \$dns | sed 's/,/ /g'); do
1029 echo "nameserver \$i" >> /etc/resolv.conf
1030 done
1031 else
1032 udhcpc -f -q -s /lib/udhcpc -i \$eth
1033 fi
1034 for i in $urliso ; do
1035 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1036 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"
1037 done
1038 getarg urliso URLISO
1039 DIR=fs
1040 if getarg loram DIR; then
1041 DEVICE=\${DIR%,*}
1042 DIR=/\${DIR#*,}
1043 fi
1044 mount -t tmpfs \$size tmpfs /mnt
1045 path2=/mnt/.httpfs/
1046 path=/mnt/.cdrom/
1047 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1048 while [ ! -d \$path/boot ]; do
1049 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1050 httpfs \$i \$path2 && break
1051 done
1052 mount -o loop,ro -t iso9660 \$path2/*.iso \$path
1053 done
1055 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1056 umount /proc
1057 branch=:/mnt/.cdrom/\$DIR
1058 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1059 branch=
1060 for i in \${path}rootfs* ; do
1061 fs=\${i#*root}
1062 branch=\$branch:/mnt/.\$fs
1063 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1064 insmod /lib/modules/squashfs.ko 2> /dev/null
1065 mount -o loop,ro -t squashfs \${path}root\$fs /mnt/.\$fs
1066 done
1067 else
1068 mkdir -p /mnt/.rw/mnt/.httpfs
1069 fi
1070 while read type opt; do
1071 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1072 done <<EOT
1073 aufs br=/mnt/.rw\$branch
1074 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1075 EOT
1076 rm -rf /lib/modules
1077 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1078 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1079 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1080 EOTEOT
1081 chmod +x $TMP_DIR/initfs/init
1082 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1083 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1084 rm -f $i
1085 gzip -9 ${i%.gz}
1086 done 2>/dev/null
1087 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1088 lzma e $TMP_DIR/initfs.gz -si
1089 lzma_set_size $TMP_DIR/initfs.gz
1090 rm -rf $TMP_DIR/initfs
1091 align_to_32bits $TMP_DIR/initfs.gz
1092 return 0
1096 # Move each initramfs to squashfs
1098 build_loram_rootfs() {
1099 rootfs_sizes=""
1100 for i in $TMP_DIR/iso/boot/rootfs*; do
1101 mkdir -p $TMP_DIR/fs
1102 cd $TMP_DIR/fs
1103 uncompress $i | cpio -idm
1104 cd - > /dev/null
1105 rootfs=$TMP_DIR/$(basename $i)
1106 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp xz -Xbcj x86
1107 cd $TMP_DIR
1108 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1109 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1110 rm -f $rootfs
1111 mv $rootfs.cpio $rootfs
1112 cd - > /dev/null
1113 rm -rf $TMP_DIR/fs
1114 done
1118 # Move meta boot configuration files to basic configuration files
1119 # because meta loram flavor is useless when rootfs is not loaded in RAM
1121 unmeta_boot() {
1122 local root=${1:-$TMP_DIR/loramiso}
1123 if [ -f $root/boot/isolinux/noram.cfg ]; then
1124 # We keep enough information to do unloram...
1125 [ -s $root/boot/isolinux/common.cfg ] &&
1126 sed -i 's/label slitaz/label orgslitaz/' \
1127 $root/boot/isolinux/common.cfg
1128 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1129 shift
1130 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1131 $root/boot/isolinux/isolinux.cfg
1132 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1133 sed -i "s/label $3\$/label slitaz/;s|=/boot/rootfs\(.*\).gz |=/boot/rootfs.gz |" \
1134 $root/boot/isolinux/*.cfg
1135 fi
1139 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1140 # These squashfs may be loaded in RAM at boot time.
1141 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1142 # Meta flavors are converted to normal flavors.
1144 build_loram_cdrom() {
1145 build_initfs cdrom || return 1
1146 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1147 mkdir $TMP_DIR/loramiso/fs
1148 cd $TMP_DIR/loramiso/fs
1149 for i in $( ls ../boot/root* | sort -r ) ; do
1150 uncompress $i | cpio -idmu
1151 rm -f $i
1152 done
1153 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1154 cd - >/dev/null
1155 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1156 unmeta_boot
1157 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1158 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1159 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1160 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1161 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1162 create_iso $OUTPUT $TMP_DIR/loramiso
1166 # Create http bootstrap to load and remove loram_cdrom
1167 # Meta flavors are converted to normal flavors.
1169 build_loram_http() {
1170 build_initfs http || return 1
1171 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1172 rm -f $TMP_DIR/loramiso/boot/rootfs*
1173 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1174 unmeta_boot
1175 create_iso $OUTPUT $TMP_DIR/loramiso
1179 # Update meta flavor selection sizes.
1180 # Reduce sizes with rootfs gains.
1182 update_metaiso_sizes() {
1183 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1184 do
1185 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1186 local sizes="$rootfs_sizes"
1187 local new
1188 set -- $append
1189 shift
1190 [ "$1" == "ifmem" ] && shift
1191 new=""
1192 while [ -n "$2" ]; do
1193 local s
1194 case "$1" in
1195 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1196 *M) s=$(( ${1%M} * 1024 ));;
1197 *) s=${1%K};;
1198 esac
1199 sizes=${sizes#* }
1200 for i in $sizes ; do
1201 s=$(( $s - $i ))
1202 done
1203 new="$new $s $2"
1204 shift 2
1205 done
1206 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1207 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1208 sed -i 's|\(initrd=\)\(/boot/rootfs.\.gz\)|\1/boot/rootfs.gz,\2|' $cfg
1209 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1210 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1211 done
1215 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1216 # Meta flavor selection sizes are updated.
1218 build_loram_ram() {
1219 build_initfs ram || return 1
1220 build_loram_rootfs
1221 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1222 make_bzImage_hardlink $TMP_DIR/loramiso/boot
1223 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1224 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1225 update_metaiso_sizes
1226 create_iso $OUTPUT $TMP_DIR/loramiso
1230 # Remove files installed by packages
1232 find_flavor_rootfs() {
1233 for i in $1/etc/tazlito/*.extract; do
1234 [ -e $i ] || continue
1235 chroot $1 /bin/sh ${i#$1}
1236 done
1238 # Clean hardlinks and files patched by genisofs in /boot
1239 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1240 rm -f $1/boot/$i*
1241 done
1243 # Clean files generated in post_install
1244 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1245 $1/dev/core $1/dev/fd $1/dev/std*
1247 # Verify md5
1248 cat $1$INSTALLED/*/md5sum | \
1249 while read md5 file; do
1250 [ -e "$1$file" ] || continue
1251 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1252 rm -f "$1$file"
1253 done
1255 # Check configuration files
1256 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1257 [ -e $i ] || continue
1258 mkdir /tmp/volatile$$
1259 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1260 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1261 while read file ; do
1262 [ -e "$1/$file" ] || continue
1263 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1264 done
1265 rm -rf /tmp/volatile$$
1266 done
1268 # Remove other files blindly
1269 for i in $1$INSTALLED/*/files.list; do
1270 for file in $(cat "$i"); do
1271 [ "$1$file" -nt "$i" ] && continue
1272 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1273 [ -d "$1$file" ] || rm -f "$1$file"
1274 done
1275 done
1277 # Remove tazpkg files and tmp files
1278 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1279 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1280 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1281 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1282 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1284 # Cleanup directory tree
1285 cd $1
1286 find * -type d | sort -r | while read dir; do
1287 rmdir "$dir" 2>/dev/null
1288 done
1289 cd - > /dev/null
1293 # Get byte(s) from a binary file
1295 get() {
1296 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null
1300 # Get cpio flavor info from the ISO image
1302 flavordata() {
1303 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1304 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1308 # Restore undigest mirrors
1310 restore_mirrors() {
1311 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1312 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1314 action 'Restoring mirrors...'
1315 if [ -d "$undigest.bak" ]; then
1316 [ -d "$undigest" ] && rm -r "$undigest"
1317 mv "$undigest.bak" "$undigest"
1318 fi
1319 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1320 :; status
1324 # Setup undigest mirrors
1326 setup_mirrors() {
1327 # Setup mirrors in plain system or in chroot (with variable root=)
1328 local mirrorlist="$1" fresh repacked
1329 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1331 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1332 restore_mirrors
1334 _ 'Setting up mirrors for %s...' "$root/"
1335 # Backing up current undigest mirrors and priority
1336 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1337 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1338 rm -rf '/var/www/tazlito/'
1339 mkdir -p '/var/www/tazlito/'
1341 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1342 fresh='/home/slitaz/packages'
1343 if [ -d "$fresh" ]; then
1344 # Setup first undigest mirror
1345 mkdir -p "$undigest/fresh"
1346 echo "$fresh" > "$undigest/fresh/mirror"
1347 echo 'fresh' >> "$priority"
1348 # Rebuild mirror DB if needed
1349 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1350 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1351 tazpkg mkdb "$fresh" --forced --root=''
1352 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1353 fi
1355 # Repacked packages: high priority
1356 repacked="$PACKAGES_REPOSITORY"
1357 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1358 # According to Tazlito setup file (tazlito.conf):
1359 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1360 # or
1361 # WORK_DIR="/home/slitaz"
1362 # and
1363 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1364 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1366 # Setup second undigest mirror
1367 mkdir -p "$undigest/repacked"
1368 echo "$repacked" > "$undigest/repacked/mirror"
1369 echo 'repacked' >> "$priority"
1370 # Rebuild mirror DB if needed
1371 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1372 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1373 tazpkg mkdb "$repacked" --forced --root=''
1374 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1375 fi
1377 # All repositories listed in mirrors list: normal priority
1378 [ -e "$mirrorlist" ] && \
1379 while read mirror; do
1380 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1381 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1382 mkdir -p "$undigest/$mirrorid"
1383 echo "$mirror" > "$undigest/$mirrorid/mirror"
1384 echo "$mirrorid" >> "$priority"
1385 done < "$mirrorlist"
1387 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1389 # Show list of mirrors
1390 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1391 function show(num, name, url) {
1392 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1395 num++;
1396 "cat " db "/undigest/" $0 "/mirror" | getline url;
1397 show(num, $0, url);
1399 END {
1400 num++;
1401 "cat " db "/mirror" | getline url;
1402 show(num, "main", url);
1403 }' "$priority"
1405 tazpkg recharge --quiet >/dev/null
1409 # Get list of 'packages.info' lists using priority
1411 pi_lists() {
1412 local pi
1413 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1414 local priority="$root$LOCALSTATE/priority"
1415 local undigest="$root$LOCALSTATE/undigest"
1418 [ -s "$priority" ] && cat "$priority"
1419 echo 'main'
1420 [ -d "$undigest" ] && ls "$undigest"
1421 } | awk -vun="$undigest/" '
1423 if (arr[$0] != 1) {
1424 arr[$0] = 1;
1425 print un $0 "/packages.info";
1427 }' | sed 's|/undigest/main||' | \
1428 while read pi; do
1429 [ -e "$pi" ] && echo "$pi"
1430 done
1434 # Strip versions from packages list
1436 strip_versions() {
1437 action 'Strip versions from list %s...' "$(basename "$1")"
1438 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1439 [ -f "$in_list" ] || die "List '$in_list' not found."
1441 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1442 awk '
1444 if (FILENAME ~ "packages.info") {
1445 # Collect package names
1446 FS = "\t"; pkg[$1] = 1;
1447 } else {
1448 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1449 while (NF > 1 && ! pkg[$0])
1450 NF --;
1451 printf "%s\n", $0;
1453 }' $(pi_lists) "$in_list" > "$tmp_list"
1455 cat "$tmp_list" > "$in_list"
1456 rm "$tmp_list"
1457 status
1461 # Display list of unknown packages (informative)
1463 display_unknown() {
1464 [ -s "$1" ] || return
1465 echo "Unknown packages:" >&2
1466 cat "$1" >&2
1467 rm "$1"
1471 # Display warnings about critical packages absent (informative)
1473 display_warn() {
1474 [ -s "$1" ] || return
1475 echo "Absent critical packages:" >&2
1476 cat "$1" >&2
1477 rm "$1"
1478 echo "Probably ISO image will be unusable."
1482 # Install packages to rootfs
1484 install_list_to_rootfs() {
1485 local list="$1" rootfs="$2" pkg i ii
1486 local undigest="$rootfs/var/lib/tazpkg/undigest"
1488 # initial tazpkg setup in empty rootfs
1489 tazpkg --root=$rootfs >/dev/null 2>&1
1490 # link rootfs packages cache to the regular packages cache
1491 rm -r "$rootfs/var/cache/tazpkg"
1492 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1494 setup_mirrors mirrors
1496 # Just in case if flavor not contains "tazlito" package
1497 mkdir -p "$rootfs/etc/tazlito"
1499 newline
1500 for pkg in $(cat $list); do
1501 action 'Installing package: %s' "$pkg"
1502 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1503 status
1504 done
1505 newline
1507 restore_mirrors
1508 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1509 for i in fresh repacked; do
1510 ii="$undigest/$i"
1511 [ -d "$ii" ] && rm -rf "$ii"
1512 ii="$rootfs/var/lib/tazpkg/priority"
1513 if [ -f "$ii" ]; then
1514 sed -i "/$i/d" "$ii"
1515 [ -s "$ii" ] || rm "$ii"
1516 fi
1517 done
1518 [ -d "$undigest" ] && \
1519 for i in $(find "$undigest" -type f); do
1520 # Remove all undigest PKGDB files but 'mirror'
1521 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1522 done
1523 [ -d "$undigest" ] && \
1524 rmdir --ignore-fail-on-non-empty "$undigest"
1526 # Un-link packages cache
1527 rm "$rootfs/var/cache/tazpkg"
1529 # Clean /var/lib/tazpkg
1530 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1536 ####################
1537 # Tazlito commands #
1538 ####################
1540 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1541 case "$0" in
1542 *reduplicate)
1543 find ${@:-.} ! -type d -links +1 \
1544 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1545 exit 0 ;;
1546 *deduplicate)
1547 deduplicate "$@"
1548 exit 0 ;;
1549 esac
1552 case "$COMMAND" in
1553 stats)
1554 # Tazlito general statistics from the config file.
1556 title 'Tazlito statistics'
1557 optlist "\
1558 Config file : $CONFIG_FILE
1559 ISO name : $ISO_NAME.iso
1560 Volume name : $VOLUM_NAME
1561 Prepared : $PREPARED
1562 Packages repository : $PACKAGES_REPOSITORY
1563 Distro directory : $DISTRO
1564 Additional files : $ADDFILES
1565 " | sed '/: $/d'
1566 footer
1567 ;;
1570 list-addfiles)
1571 # Simple list of additional files in the rootfs
1572 newline
1573 if [ -d "$ADDFILES/rootfs" ]; then
1574 cd $ADDFILES
1575 find rootfs -type f
1576 else
1577 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1578 fi
1579 newline
1580 ;;
1583 gen-config)
1584 # Generate a new config file in the current dir or the specified
1585 # directory by $2.
1587 if [ -n "$2" ]; then
1588 mkdir -p "$2" && cd "$2"
1589 fi
1591 newline
1592 action 'Generating empty tazlito.conf...'
1593 empty_config_file
1594 status
1596 separator
1597 if [ -f 'tazlito.conf' ] ; then
1598 _ 'Configuration file is ready to edit.'
1599 _ 'File location: %s' "$(pwd)/tazlito.conf"
1600 newline
1601 fi
1602 ;;
1605 configure)
1606 # Configure a tazlito.conf config file. Start by getting
1607 # a empty config file and sed it.
1609 if [ -f 'tazlito.conf' ]; then
1610 rm tazlito.conf
1611 else
1612 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1613 'or in the same directory of the file you want to configure.'
1614 cd /etc
1615 fi
1617 empty_config_file
1619 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1621 # ISO name.
1622 echo -n "ISO name : " ; read answer
1623 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1624 # Volume name.
1625 echo -n "Volume name : " ; read answer
1626 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1627 # Packages repository.
1628 echo -n "Packages repository : " ; read answer
1629 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1630 # Distro path.
1631 echo -n "Distro path : " ; read answer
1632 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1633 footer "Config file is ready to use."
1634 echo 'You can now extract an ISO or generate a distro.'
1635 newline
1636 ;;
1639 gen-iso)
1640 # Simply generate a new iso.
1642 check_root
1643 verify_rootcd
1644 gen_livecd_isolinux
1645 distro_stats
1646 ;;
1649 gen-initiso)
1650 # Simply generate a new initramfs with a new iso.
1652 check_root
1653 verify_rootcd
1654 gen_initramfs "$ROOTFS"
1655 gen_livecd_isolinux
1656 distro_stats
1657 ;;
1660 extract-distro)
1661 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1663 check_root
1664 ISO_IMAGE="$2"
1665 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1666 'Example:\n tazlito image.iso /path/target'
1668 # Set the distro path by checking for $3 on cmdline.
1669 TARGET="${3:-$DISTRO}"
1671 # Exit if existing distro is found.
1672 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1673 'Please clean the distro tree or change directory path.'
1675 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
1677 # Start to mount the ISO.
1678 action 'Mounting ISO image...'
1679 mkdir -p "$TMP_DIR"
1680 # Get ISO file size.
1681 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
1682 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
1683 sleep 2
1684 # Prepare target dir, copy the kernel and the rootfs.
1685 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
1686 status
1688 action 'Copying the Linux kernel...'
1689 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
1690 make_bzImage_hardlink "$TARGET/rootcd/boot"
1691 else
1692 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
1693 fi
1694 status
1696 for i in $(ls $TMP_DIR); do
1697 [ "$i" == 'boot' ] && continue
1698 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
1699 done
1701 for loader in isolinux syslinux extlinux grub; do
1702 [ -d "$TMP_DIR/boot/$loader" ] || continue
1703 action 'Copying %s files...' "$loader"
1704 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
1705 status
1706 done
1708 action 'Copying the rootfs...'
1709 cp $TMP_DIR/boot/rootfs.?z "$TARGET/rootcd/boot"
1710 status
1712 # Extract initramfs.
1713 cd "$TARGET/rootfs"
1714 action 'Extracting the rootfs...'
1715 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
1716 # unpack /usr
1717 for i in etc/tazlito/*.extract; do
1718 [ -f "$i" ] && . $i ../rootcd
1719 done
1720 # Umount and remove temp directory and cd to $TARGET to get stats.
1721 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
1722 cd ..
1723 status
1725 newline
1726 separator
1727 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
1728 echo "Distro tree : $(pwd)"
1729 echo "Rootfs size : $(du -sh rootfs)"
1730 echo "Rootcd size : $(du -sh rootcd)"
1731 footer
1732 ;;
1735 list-flavors)
1736 # Show available flavors.
1737 local list='/etc/tazlito/flavors.list'
1738 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
1739 title 'List of flavors'
1740 cat $list
1741 footer
1742 ;;
1745 show-flavor)
1746 # Show flavor description.
1747 set -e
1748 flavor=${2%.flavor}
1749 flv_dir="$(extract_flavor "$flavor")"
1750 desc="$flv_dir/$flavor.desc"
1751 if [ -n "$brief" ]; then
1752 if [ -z "$noheader" ]; then
1753 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
1754 separator
1755 fi
1756 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
1757 "$(field ISO "$desc")" \
1758 "$(field Rootfs "$desc")" \
1759 "$(field Description "$desc")"
1760 else
1761 separator
1762 cat "$desc"
1763 fi
1764 cleanup
1765 ;;
1768 gen-liveflavor)
1769 # Generate a new flavor from the live system.
1770 FLAVOR=${2%.flavor}
1771 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1773 case "$FLAVOR" in
1774 -?|-h*|--help)
1775 cat <<EOT
1776 SliTaz Live Tool - Version: $VERSION
1778 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
1780 $(boldify '<flavor-patch-file> format:')
1781 $(optlist "\
1782 code data
1783 + package to add
1784 - package to remove
1785 ! non-free package to add
1786 ? display message
1787 @ flavor description
1788 ")
1790 $(boldify 'Example:')
1791 $(optlist "\
1792 @ Developer tools for SliTaz maintainers
1793 + slitaz-toolchain
1794 + mercurial
1795 ")
1796 EOT
1797 exit 1
1798 ;;
1799 esac
1800 mv /etc/tazlito/distro-packages.list \
1801 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
1802 rm -f distro-packages.list non-free.list 2>/dev/null
1803 tazpkg recharge
1805 DESC=""
1806 [ -n "$3" ] && \
1807 while read action pkg; do
1808 case "$action" in
1809 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
1810 -) yes | tazpkg remove $pkg ;;
1811 !) echo $pkg >> non-free.list ;;
1812 @) DESC="$pkg" ;;
1813 \?) echo -en "$pkg"; read action ;;
1814 esac
1815 done < $3
1817 yes '' | tazlito gen-distro
1818 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
1819 mv /etc/tazlito/distro-packages.list.$$ \
1820 /etc/tazlito/distro-packages.list 2>/dev/null
1821 ;;
1824 gen-flavor)
1825 # Generate a new flavor from the last ISO image generated
1826 FLAVOR=${2%.flavor}
1827 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1829 title 'Flavor generation'
1830 check_rootfs
1831 FILES="$FLAVOR.pkglist"
1833 action 'Creating file %s...' "$FLAVOR.flavor"
1834 for i in rootcd rootfs; do
1835 if [ -d "$ADDFILES/$i" ] ; then
1836 FILES="$FILES\n$FLAVOR.$i"
1837 (cd "$ADDFILES/$i"; find . | cpio -o -H newc 2>/dev/null | gzip -9) > $FLAVOR.$i
1838 fi
1839 done
1840 status
1842 answer=$(grep -s ^Description $FLAVOR.desc)
1843 answer=${answer#Description : }
1844 if [ -z "$answer" ]; then
1845 echo -n "Description: "
1846 read answer
1847 fi
1849 action 'Compressing flavor %s...' "$FLAVOR"
1850 echo "Flavor : $FLAVOR" > $FLAVOR.desc
1851 echo "Description : $answer" >> $FLAVOR.desc
1852 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
1853 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
1854 for i in $(ls $ROOTFS$INSTALLED); do
1855 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
1856 EXTRAVERSION=""
1857 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
1858 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
1859 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
1860 echo "$i" >> $FLAVOR.nonfree
1861 else
1862 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
1863 fi
1864 done
1865 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
1866 for i in $LOCALSTATE/undigest/*/mirror ; do
1867 [ -s $i ] && cat $i >> $FLAVOR.mirrors
1868 done
1869 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
1870 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | gzip -9 > $FLAVOR.flavor
1871 rm $(echo -e $FILES)
1872 status
1874 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
1875 ;;
1878 upgrade-flavor)
1879 # Strip versions from pkglist and update estimated numbers in flavor.desc
1880 flavor="${2%.flavor}"
1881 set -e
1882 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1883 set +e
1885 flv_dir="$(extract_flavor "$flavor")"
1887 strip_versions "$flv_dir/$flavor.pkglist"
1889 action 'Updating %s...' "$flavor.desc"
1891 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
1892 set -- $(module calc_sizes "$flv_dir" "$flavor")
1893 restore_mirrors >/dev/null
1895 sed -i -e '/Image is ready/d' \
1896 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
1897 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
1898 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
1899 -e "s|\(Packages *:\).*$|\1 $4|" \
1900 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
1901 "$flv_dir/$flavor.desc"
1903 pack_flavor "$flv_dir" "$flavor"
1904 status
1905 display_unknown "$flv_dir/err"
1906 display_warn "$flv_dir/warn"
1907 cleanup
1908 ;;
1911 extract-flavor)
1912 # Extract a flavor into $FLAVORS_REPOSITORY
1913 flavor="${2%.flavor}"
1914 set -e
1915 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1916 set +e
1918 action 'Extracting %s...' "$flavor.flavor"
1919 flv_dir="$(extract_flavor "$flavor" full)"
1920 storage="$FLAVORS_REPOSITORY/$flavor"
1922 rm -rf "$storage" 2>/dev/null
1923 mkdir -p "$storage"
1924 cp -a "$flv_dir"/* "$storage"
1925 rm "$storage/description"
1926 status
1928 strip_versions "$storage/packages.list"
1930 cleanup
1931 ;;
1934 pack-flavor)
1935 # Create a flavor from $FLAVORS_REPOSITORY.
1936 flavor=${2%.flavor}
1937 storage="$FLAVORS_REPOSITORY/$flavor"
1939 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
1941 action 'Creating flavor %s...' "$flavor"
1942 tmp_dir="$(mktemp -d)"
1944 while read from to; do
1945 [ -s "$storage/$from" ] || continue
1946 cp -a "$storage/$from" "$tmp_dir/$to"
1947 done <<EOT
1948 mirrors $flavor.mirrors
1949 distro.sh $flavor-distro.sh
1950 receipt $flavor.receipt
1951 non-free.list $flavor.nonfree
1952 EOT
1954 # Build the package list.
1955 # It can include a list from another flavor with the keyword @include
1956 if [ -s "$storage/packages.list" ]; then
1957 include=$(grep '^@include' "$storage/packages.list")
1958 if [ -n "$include" ]; then
1959 include=${include#@include }
1960 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
1961 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
1962 else
1963 echo -e "\nERROR: Can't find include package list from $include\n"
1964 fi
1965 fi
1966 # Generate the final/initial package list
1967 [ -s "$storage/packages.list" ] && \
1968 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
1969 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
1970 fi
1972 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
1973 # Process multi-rootfs flavor
1974 . "$storage/receipt"
1975 set -- $ROOTFS_SELECTION
1976 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
1977 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
1978 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
1980 for i in rootcd rootfs; do
1981 mkdir "$tmp_dir/$i"
1982 # Copy extra files from the first flavor
1983 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
1984 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
1985 # Overload extra files by meta flavor
1986 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
1987 [ -n "$(ls $tmp_dir/$i)" ] &&
1988 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
1989 gzip -9 > "$tmp_dir/$flavor.$i"
1990 rm -rf "$tmp_dir/$i"
1991 done
1992 else
1993 # Process plain flavor
1994 for i in rootcd rootfs; do
1995 [ -d "$storage/$i" ] || continue
1996 (cd "$storage/$i";
1997 find . | cpio -o -H newc 2>/dev/null) | gzip -9 > "$tmp_dir/$flavor.$i"
1998 done
1999 fi
2001 unset VERSION MAINTAINER ROOTFS_SELECTION
2002 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2003 ROOTFS_SIZE="$1 (estimated)"
2004 INITRAMFS_SIZE="$2 (estimated)"
2005 ISO_SIZE="$3 (estimated)"
2006 PKGNUM="$4"
2007 . "$storage/receipt"
2009 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2010 Flavor : $FLAVOR
2011 Description : $SHORT_DESC
2012 Version : $VERSION
2013 Maintainer : $MAINTAINER
2014 LiveCD RAM size : $FRUGAL_RAM
2015 Rootfs list : $ROOTFS_SELECTION
2016 Build date : $(date '+%Y%m%d at %T')
2017 Packages : $PKGNUM
2018 Rootfs size : $ROOTFS_SIZE
2019 Initramfs size : $INITRAMFS_SIZE
2020 ISO image size : $ISO_SIZE
2021 ================================================================================
2023 EOT
2025 rm -f $tmp_dir/packages.list
2026 pack_flavor "$tmp_dir" "$flavor"
2027 status
2028 display_unknown "$tmp_dir/err"
2029 display_warn "$flv_dir/warn"
2030 cleanup
2031 ;;
2034 get-flavor)
2035 # Get a flavor's files and prepare for gen-distro.
2036 flavor=${2%.flavor}
2037 title 'Preparing %s distro flavor' "$flavor"
2038 set -e
2039 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2040 set +e
2042 action 'Cleaning %s...' "$DISTRO"
2043 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2044 # Clean old files
2045 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2046 [ -f "$i" ] && rm "$i"
2047 done
2048 mkdir -p "$DISTRO"
2049 status
2051 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2053 action 'Extracting flavor %s...' "$flavor.flavor"
2054 flv_dir="$(extract_flavor "$flavor" info)"
2055 cp -a "$flv_dir"/* .
2056 mv packages.list distro-packages.list
2057 mv -f info /etc/tazlito
2058 status
2060 for i in rootcd rootfs; do
2061 if [ -d "$i" ]; then
2062 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2063 fi
2064 done
2066 rm -f /etc/tazlito/rootfs.list
2067 grep -q '^Rootfs list' description &&
2068 grep '^Rootfs list' description | sed 's/.*: \(.*\)$/\1/' > /etc/tazlito/rootfs.list
2070 action 'Updating %s...' 'tazlito.conf'
2071 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2072 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2073 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2074 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2075 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2076 status
2078 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2079 cleanup
2080 ;;
2083 iso2flavor)
2084 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2085 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2087 FLAVOR=${3%.flavor}
2088 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2089 mount -o loop,ro $2 $TMP_DIR/iso
2090 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2091 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2092 ! -s $TMP_DIR/flavor/*.desc ]; then
2093 _ 'META flavors are not supported.'
2094 umount -d $TMP_DIR/iso
2095 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2096 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2097 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2098 umount -d $TMP_DIR/iso
2099 else
2100 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2101 uncompress $i | \
2102 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2103 done
2104 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2105 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2106 '/etc/slitaz-release' '/boot/rootfs.gz'
2107 umount -d $TMP_DIR/iso
2108 else
2109 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2110 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2111 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2112 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2113 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2114 umount -d $TMP_DIR/iso
2115 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2116 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2117 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2118 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2119 < $TMP_DIR/rootfs$INSTALLED.md5
2120 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2121 if [ -s $TMP_DIR/flavor/*desc ]; then
2122 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2123 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2124 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2125 for i in rootfs rootcd ; do
2126 [ -s $TMP_DIR/flavor/*.list$i ] &&
2127 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2128 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | gzip -9 > $TMP_DIR/$FLAVOR.$i
2129 done
2130 else
2131 find_flavor_rootfs $TMP_DIR/rootfs
2132 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2133 for i in rootfs rootcd ; do
2134 [ "$(ls $TMP_DIR/$i)" ] &&
2135 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | gzip -9 > "$TMP_DIR/$FLAVOR.$i"
2136 done
2137 unset VERSION MAINTAINER
2138 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2139 if [ -n "$DESCRIPTION" ]; then
2140 _n 'Flavor version : '; read -t 30 VERSION
2141 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2142 fi
2144 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2145 Flavor : $FLAVOR
2146 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2147 Version : ${VERSION:-1.0}
2148 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2149 LiveCD RAM size : $RAM_SIZE
2150 Build date : $BUILD_DATE
2151 Packages : $PKGCNT
2152 Rootfs size : $ROOTFS_SIZE
2153 Initramfs size : $INITRAMFS_SIZE
2154 ISO image size : $ISO_SIZE
2155 ================================================================================
2157 EOT
2158 longline "Tazlito can't detect each file installed during \
2159 a package post_install. You should extract this flavor (tazlito extract-flavor \
2160 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2161 tree and remove files generated by post_installs.
2162 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2163 repack the flavor (tazlito pack-flavor $FLAVOR)"
2164 fi
2165 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | gzip -9 > $FLAVOR.flavor
2166 fi
2167 fi
2168 rm -rf $TMP_DIR
2169 ;;
2172 gen-distro)
2173 # Generate a live distro tree with a set of packages.
2175 check_root
2176 start_time=$(date +%s)
2178 # Tazlito options: --iso or --cdrom
2179 CDROM=''
2180 [ -n "$iso" ] && CDROM="-o loop $iso"
2181 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2183 # Check if a package list was specified on cmdline.
2184 if [ -f "$2" ]; then
2185 LIST_NAME="$2"
2186 else
2187 LIST_NAME='distro-packages.list'
2188 fi
2190 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2191 'Please clean the distro tree or change directory path.'
2192 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2193 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2195 # If list not given: build list with all installed packages
2196 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2197 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2198 fi
2200 # Exit if no list name.
2201 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2203 # Start generation.
2204 title 'Tazlito generating a distro'
2206 # Misc checks
2207 mkdir -p "$PACKAGES_REPOSITORY"
2208 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2209 newline
2211 # Mount CD-ROM to be able to repack boot-loader packages
2212 if [ ! -e /boot -a -n "$CDROM" ]; then
2213 mkdir $TMP_MNT
2214 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2215 ln -s "$TMP_MNT/boot" /
2216 if [ ! -d "$ADDFILES/rootcd" ] ; then
2217 mkdir -p "$ADDFILES/rootcd"
2218 for i in $(ls $TMP_MNT); do
2219 [ "$i" == 'boot' ] && continue
2220 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2221 done
2222 fi
2223 else
2224 rmdir "$TMP_MNT"
2225 fi
2226 fi
2228 # Rootfs stuff.
2229 echo 'Preparing the rootfs directory...'
2230 mkdir -p "$ROOTFS"
2231 export root="$ROOTFS"
2232 strip_versions "$LIST_NAME"
2234 if [ "$REPACK" == 'y' ]; then
2235 # Determine full packages list with all dependencies
2236 tmp_dir="$(mktemp -d)"
2237 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2238 touch "$tmp_dir/full.pkglist"
2239 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2241 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2242 while read pkgname pkgver; do
2243 # Is package in full list?
2244 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2245 # Is package already repacked?
2246 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2247 _ 'Repacking %s...' "$pkgname-$pkgver"
2248 tazpkg repack "$pkgname" --quiet
2249 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2250 status
2251 done
2253 rm -r "$tmp_dir"
2254 fi
2256 if [ -f non-free.list ]; then
2257 # FIXME: working in the ROOTFS chroot?
2258 newline
2259 echo 'Preparing non-free packages...'
2260 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2261 for pkg in $(cat 'non-free.list'); do
2262 if [ ! -d "$INSTALLED/$pkg" ]; then
2263 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2264 tazpkg get-install get-$pkg
2265 fi
2266 get-$pkg "$ROOTFS"
2267 fi
2268 tazpkg repack $pkg
2269 pkg=$(ls $pkg*.tazpkg)
2270 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2271 mv $pkg $PACKAGES_REPOSITORY
2272 done
2273 fi
2274 cp $LIST_NAME $DISTRO/distro-packages.list
2275 newline
2277 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2279 cd $DISTRO
2280 cp distro-packages.list $ROOTFS/etc/tazlito
2281 # Copy all files from $ADDFILES/rootfs to the rootfs.
2282 if [ -d "$ADDFILES/rootfs" ] ; then
2283 action 'Copying addfiles content to the rootfs...'
2284 cp -a $ADDFILES/rootfs/* $ROOTFS
2285 status
2286 fi
2288 action 'Root filesystem is generated...'; status
2290 # Root CD part.
2291 action 'Preparing the rootcd directory...'
2292 mkdir -p $ROOTCD
2293 status
2295 # Move the boot dir with the Linux kernel from rootfs.
2296 # The boot dir goes directly on the CD.
2297 if [ -d "$ROOTFS/boot" ] ; then
2298 action 'Moving the boot directory...'
2299 mv $ROOTFS/boot $ROOTCD
2300 cd $ROOTCD/boot
2301 make_bzImage_hardlink
2302 status
2303 fi
2304 cd $DISTRO
2305 # Copy all files from $ADDFILES/rootcd to the rootcd.
2306 if [ -d "$ADDFILES/rootcd" ] ; then
2307 action 'Copying addfiles content to the rootcd...'
2308 cp -a $ADDFILES/rootcd/* $ROOTCD
2309 status
2310 fi
2311 # Execute the distro script used to perform tasks in the rootfs
2312 # before compression. Give rootfs path in arg
2313 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2314 if [ -x "$DISTRO_SCRIPT" ]; then
2315 echo 'Executing distro script...'
2316 sh $DISTRO_SCRIPT $DISTRO
2317 fi
2319 # Execute the custom_rules() found in receipt.
2320 if [ -s "$TOP_DIR/receipt" ]; then
2321 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2322 echo -e "Executing: custom_rules()\n"
2323 . "$TOP_DIR/receipt"
2324 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2325 fi
2326 fi
2328 # Multi-rootfs
2329 if [ -s /etc/tazlito/rootfs.list ]; then
2331 FLAVOR_LIST="$(awk '{
2332 for (i = 2; i <= NF; i+=2)
2333 printf "%s ", i;
2334 }' /etc/tazlito/rootfs.list)"
2336 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2337 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2338 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2340 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2341 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2342 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2343 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2345 n=0
2346 last=$ROOTFS
2347 while read flavor; do
2348 n=$(($n+1))
2349 mkdir ${ROOTFS}0$n
2350 export root="${ROOTFS}0$n"
2351 # initial tazpkg setup in empty rootfs
2352 tazpkg --root=$root >/dev/null 2>&1
2354 newline
2355 boldify "Building $flavor rootfs..."
2357 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2358 cp "$TOP_DIR/$flavor.flavor" .
2360 if [ ! -s "$flavor.flavor" ]; then
2361 # We may have it in $FLAVORS_REPOSITORY
2362 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2363 tazlito pack-flavor $flavor
2364 else
2365 download $flavor.flavor
2366 fi
2367 fi
2369 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2370 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2371 cp $flavor.pkglist $DISTRO/list-packages0$n
2372 status
2374 strip_versions "$DISTRO/list-packages0$n"
2376 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2378 rm -rf ${ROOTFS}0$n/boot
2380 cd $DISTRO
2381 if [ -s $flavor.rootfs ]; then
2382 _n 'Adding %s rootfs extra files...' "$flavor"
2383 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2384 fi
2386 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2387 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2388 status
2390 rm -f $flavor.flavor install-list
2391 mergefs ${ROOTFS}0$n $last
2392 last=${ROOTFS}0$n
2393 done <<EOT
2394 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2395 EOT
2396 #'
2397 i=$(($n+1))
2398 while [ $n -gt 0 ]; do
2399 mv ${ROOTFS}0$n ${ROOTFS}$i
2400 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2401 gen_initramfs ${ROOTFS}$i
2402 n=$(($n-1))
2403 i=$(($i-1))
2404 done
2405 mv $ROOTFS ${ROOTFS}$i
2406 gen_initramfs ${ROOTFS}$i
2407 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2408 else
2409 # Initramfs and ISO image stuff.
2410 gen_initramfs $ROOTFS
2411 fi
2412 gen_livecd_isolinux
2413 distro_stats
2414 cleanup
2415 ;;
2418 clean-distro)
2419 # Remove old distro tree.
2421 check_root
2422 title 'Cleaning: %s' "$DISTRO"
2423 if [ -d "$DISTRO" ] ; then
2424 if [ -d "$ROOTFS" ] ; then
2425 action 'Removing the rootfs...'
2426 rm -f $DISTRO/$INITRAMFS
2427 rm -rf $ROOTFS
2428 status
2429 fi
2430 if [ -d "$ROOTCD" ] ; then
2431 action 'Removing the rootcd...'
2432 rm -rf $ROOTCD
2433 status
2434 fi
2435 action 'Removing eventual ISO image...'
2436 rm -f $DISTRO/$ISO_NAME.iso
2437 rm -f $DISTRO/$ISO_NAME.md5
2438 status
2439 fi
2440 footer
2441 ;;
2444 check-distro)
2445 # Check for a few LiveCD needed files not installed by packages.
2447 # TODO: Remove this function.
2448 # First two files are maintained by tazpkg while it runs on rootfs,
2449 # while last one file should be maintained by tazlito itself.
2450 check_rootfs
2451 title 'Checking distro: %s' "$ROOTFS"
2452 # SliTaz release info.
2453 rel='/etc/slitaz-release'
2454 if [ ! -f "$ROOTFS$rel" ]; then
2455 _ 'Missing release info: %s' "$rel"
2456 else
2457 action 'Release : %s' "$(cat $ROOTFS$rel)"
2458 status
2459 fi
2460 # Tazpkg mirror.
2461 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2462 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2463 todomsg
2464 else
2465 action 'Mirror configuration exists...'
2466 status
2467 fi
2468 # Isolinux msg
2469 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2470 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2471 todomsg
2472 else
2473 action 'Isolinux message seems good...'
2474 status
2475 fi
2476 footer
2477 ;;
2480 writeiso)
2481 # Writefs to ISO image including /home unlike gen-distro we don't use
2482 # packages to generate a rootfs, we build a compressed rootfs with all
2483 # the current filesystem similar to 'tazusb writefs'.
2485 DISTRO='/home/slitaz/distro'
2486 ROOTCD="$DISTRO/rootcd"
2487 COMPRESSION="${2:-none}"
2488 ISO_NAME="${3:-slitaz}"
2489 check_root
2490 # Start info
2491 title 'Write filesystem to ISO'
2492 longline "The command writeiso will write the current filesystem into a \
2493 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2494 newline
2495 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2497 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2498 # Save some space
2499 rm -rf /var/cache/tazpkg/*
2500 rm -f /var/lib/tazpkg/*.bak
2501 rm -rf $DISTRO
2503 # Optionally remove sound card selection and screen resolution.
2504 if [ -z $LaunchedByTazpanel ]; then
2505 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2506 case $anser in
2507 y)
2508 action 'Removing current sound card and screen configurations...'
2509 rm -f /var/lib/sound-card-driver
2510 rm -f /var/lib/alsa/asound.state
2511 rm -f /etc/X11/xorg.conf ;;
2512 *)
2513 action 'Keeping current sound card and screen configurations...' ;;
2514 esac
2515 status
2516 newline
2518 # Optionally remove i18n settings
2519 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2520 case $anser in
2521 y)
2522 action 'Removing current locale/keymap settings...'
2523 newline > /etc/locale.conf
2524 newline > /etc/keymap.conf ;;
2525 *)
2526 action 'Keeping current locale/keymap settings...' ;;
2527 esac
2528 status
2529 fi
2531 # Clean-up files by default
2532 newline > /etc/udev/rules.d/70-persistent-net.rules
2533 newline > /etc/udev/rules.d/70-persistant-cd.rules
2535 # Create list of files including default user files since it is defined in /etc/passwd
2536 # and some new users might have been added.
2537 cd /
2538 echo 'init' > /tmp/list
2539 for dir in bin etc sbin var dev lib root usr home opt; do
2540 [ -d $dir ] && find $dir
2541 done >> /tmp/list
2543 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2544 [ -d $dir ] && echo $dir
2545 done >> /tmp/list
2547 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2549 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2550 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2551 #fi
2552 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2553 touch /var/log/wtmp
2555 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2556 sed -i "/var\/log\/$removelog/d" /tmp/list
2557 done
2559 # Generate initramfs with specified compression and display rootfs
2560 # size in realtime.
2561 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2563 write_initramfs &
2564 sleep 2
2565 cd - > /dev/null
2566 echo -en "\nFilesystem size:"
2567 while [ ! -f /tmp/rootfs ]; do
2568 sleep 1
2569 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2570 done
2571 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2572 echo -e "\n"
2573 rm -f /tmp/rootfs
2575 # Move freshly generated rootfs to the cdrom.
2576 mkdir -p $ROOTCD/boot
2577 mv -f /$INITRAMFS $ROOTCD/boot
2578 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2580 # Now we need the kernel and isolinux files.
2581 copy_from_cd() {
2582 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2583 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2584 unmeta_boot $ROOTCD
2585 umount /media/cdrom
2588 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2589 copy_from_cd;
2590 elif mount | grep /media/cdrom; then
2591 copy_from_cd;
2592 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2593 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2594 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2595 else
2596 touch /tmp/.write-iso-error
2597 longline "When SliTaz is running in RAM the kernel and bootloader \
2598 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
2599 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
2600 echo -en "----\nENTER to continue..."; read i
2601 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2602 copy_from_cd
2603 fi
2605 # Generate the iso image.
2606 touch /tmp/.write-iso
2607 newline
2608 cd $DISTRO
2609 _ 'Generating ISO image...'
2610 genisoimage -R -o $ISO_NAME.iso -b boot/isolinux/isolinux.bin \
2611 -c boot/isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
2612 -V "SliTaz" -p "$(id -un)" -input-charset utf-8 -hide-rr-moved \
2613 -A "tazlito $VERSION/$(genisoimage --version)" -P "$(hostname)" \
2614 -boot-info-table $ROOTCD
2615 if [ -x /usr/bin/isohybrid ]; then
2616 action 'Creating hybrid ISO/disk...'
2617 /usr/bin/isohybrid $ISO_NAME.iso -entry 2 2>/dev/null
2618 status
2619 fi
2620 if [ -x /usr/bin/iso2exe ]; then
2621 action 'Creating hybrid ISO/EXE...'
2622 /usr/bin/iso2exe $ISO_NAME.iso 2>/dev/null
2623 status
2624 fi
2625 action 'Creating the ISO md5sum...'
2626 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2627 status
2629 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2630 rm -f /tmp/.write-iso
2632 if [ -z $LaunchedByTazpanel ]; then
2633 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2634 case $anser in
2635 y)
2636 umount /dev/cdrom 2>/dev/null
2637 eject
2638 echo -n "Please insert a blank CD-ROM and press ENTER..."
2639 read i && sleep 2
2640 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2641 echo -en "----\nENTER to continue..."; read i ;;
2642 *)
2643 exit 0 ;;
2644 esac
2645 fi
2646 ;;
2649 burn-iso)
2650 # Guess CD-ROM device, ask user and burn the ISO.
2652 check_root
2653 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2654 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2655 # We can specify an alternative ISO from the cmdline.
2656 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2657 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2659 title 'Tazlito burn ISO'
2660 echo "CD-ROM device : /dev/$DRIVE_NAME"
2661 echo "Drive speed : $DRIVE_SPEED"
2662 echo "ISO image : $iso"
2663 footer
2665 case $(yesorno 'Burn ISO image?' 'n') in
2666 y)
2667 title 'Starting Wodim to burn the ISO...'
2668 sleep 2
2669 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2670 footer 'ISO image is burned to CD-ROM.'
2671 ;;
2672 *)
2673 die 'Exiting. No ISO burned.'
2674 ;;
2675 esac
2676 ;;
2679 merge)
2680 # Merge multiple rootfs into one iso.
2682 if [ -z "$2" ]; then
2683 cat <<EOT
2684 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2686 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2687 i.e: rootfsN is a subset of rootfsN-1
2688 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2689 The boot loader will select the rootfs according to the RAM size detected.
2691 Example:
2692 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
2694 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
2695 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
2697 EOT
2698 exit 2
2699 fi
2701 shift # skip merge
2702 append="$1 slitaz1"
2703 shift # skip size1
2704 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
2706 ISO=$1.merged
2708 # Extract filesystems
2709 action 'Mounting %s' "$1"
2710 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
2711 status || cleanup_merge
2713 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2714 make_bzImage_hardlink $TMP_DIR/iso/boot
2715 umount -d $TMP_DIR/mnt
2716 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
2717 _ '%s is already a merged iso. Aborting.' "$1"
2718 cleanup_merge
2719 fi
2720 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
2721 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
2722 if [ ! -f /boot/isolinux/ifmem.c32 -a
2723 ! -f /boot/isolinux/c32box.c32 ]; then
2724 cat <<EOT
2725 No file /boot/isolinux/ifmem.c32
2726 Please install syslinux package !
2727 EOT
2728 rm -rf $TMP_DIR
2729 exit 1
2730 fi
2731 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
2732 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
2733 fi
2735 action 'Extracting %s' 'iso/rootfs.gz'
2736 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
2737 [ -d $TMP_DIR/rootfs1/etc ]
2738 status || cleanup_merge
2740 n=1
2741 while [ -n "$2" ]; do
2742 shift # skip rootfs N-1
2743 p=$n
2744 n=$(($n + 1))
2745 append="$append $1 slitaz$n"
2746 shift # skip size N
2747 mkdir -p $TMP_DIR/rootfs$n
2749 action 'Extracting %s' "$1"
2750 extract_rootfs $1 $TMP_DIR/rootfs$n &&
2751 [ -d "$TMP_DIR/rootfs$n/etc" ]
2752 status || cleanup_merge
2754 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
2755 action 'Creating %s' "rootfs$p.gz"
2756 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
2757 status
2758 done
2759 action 'Creating %s' "rootfs$n.gz"
2760 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
2761 status
2762 rm -f $TMP_DIR/iso/boot/rootfs.gz
2763 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
2764 create_iso $ISO $TMP_DIR/iso
2765 rm -rf $TMP_DIR
2766 ;;
2769 repack)
2770 # Repack an iso with maximum lzma compression ratio.
2772 ISO=$2
2773 mkdir -p $TMP_DIR/mnt
2775 # Extract filesystems
2776 action 'Mounting %s' "$ISO"
2777 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
2778 status || cleanup_merge
2780 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2781 umount -d $TMP_DIR/mnt
2783 for i in $TMP_DIR/iso/boot/rootfs* ; do
2784 action 'Repacking %s' "$(basename $i)"
2785 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
2786 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
2787 align_to_32bits $i
2788 status
2789 done
2791 create_iso $ISO $TMP_DIR/iso
2792 rm -rf $TMP_DIR
2793 ;;
2796 build-loram)
2797 # Build a Live CD for low RAM systems.
2799 ISO="$2"
2800 OUTPUT="$3"
2801 [ -z "$3" ] && \
2802 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
2803 mkdir -p "$TMP_DIR/iso"
2804 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
2805 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
2806 if ! check_iso_for_loram ; then
2807 umount -d "$TMP_DIR/iso"
2808 die "$ISO is not a valid SliTaz live CD. Abort."
2809 fi
2810 case "$4" in
2811 cdrom) build_loram_cdrom ;;
2812 http) build_loram_http ;;
2813 *) build_loram_ram ;;
2814 esac
2815 umount $TMP_DIR/iso # no -d: needs /proc
2816 losetup -d $loopdev
2817 rm -rf $TMP_DIR
2818 ;;
2821 emu-iso)
2822 # Emulate an ISO image with Qemu.
2823 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2824 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
2825 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
2826 echo -e "\nStarting Qemu emulator:\n"
2827 echo -e "qemu $QEMU_OPTS $iso\n"
2828 qemu $QEMU_OPTS $iso
2829 ;;
2832 deduplicate)
2833 # Deduplicate files in a tree
2834 shift
2835 deduplicate "$@"
2836 ;;
2839 usage|*)
2840 # Print usage also for all unknown commands.
2841 usage
2842 ;;
2843 esac
2845 exit 0