tazlito view tazlito @ rev 452

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