tazlito view tazlito @ rev 457

tazlito buid-loram http: add rolling support
author Pascal Bellard <pascal.bellard@slitaz.org>
date Thu Aug 17 16:11:23 2017 +0200 (2017-08-17)
parents bc72a0c472cc
children d67c38068716
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 touch -t 197001010100.00 "$1.*"
631 # Info to be stored inside ISO
632 [ "$2" == info ] && echo -e $infos | cpio -o -H newc | dogzip info
633 rm $1.list*
635 # Renames
636 while read from to; do
637 [ -f "$from" ] || continue
638 mv "$from" "$to"
639 done <<EOT
640 $1.nonfree non-free.list
641 $1.pkglist packages.list
642 $1-distro.sh distro.sh
643 $1.receipt receipt
644 $1.mirrors mirrors
645 $1.desc description
646 EOT
647 fi
649 echo $dir
650 }
653 # Pack flavor file from temp directory
655 pack_flavor() {
656 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
657 }
660 # Remove duplicate files
662 mergefs() {
663 # Note, many packages have files with spaces in the name
664 IFS=$'\n'
666 local size1=$(du -hs "$1" | awk '{ print $1 }')
667 local size2=$(du -hs "$2" | awk '{ print $1 }')
668 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
670 # merge symlinks files and devices
671 ( cd "$1"; find ) | \
672 while read file; do
673 if [ -L "$1/$file" ]; then
674 [ -L "$2/$file" -a "$(readlink "$1/$file")" == "$(readlink "$2/$file")" ] &&
675 rm -f "$2/$file"
677 elif [ -f "$1/$file" ]; then
678 [ -f "$2/$file" ] && cmp -s "$1/$file" "$2/$file" &&
679 rm -f "$2/$file"
681 [ -f "$2/$file" ] &&
682 [ "$(basename "$file")" == 'volatile.cpio.gz' ] &&
683 [ "$(dirname $(dirname "$file"))" == ".$INSTALLED" ] &&
684 rm -f "$2/$file"
686 elif [ -b "$1/$file" ]; then
687 [ -b "$2/$file" ] &&
688 [ "$(stat -c '%a:%u:%g:%t:%T' "$1/$file")" == \
689 "$(stat -c '%a:%u:%g:%t:%T' "$2/$file")" ] &&
690 rm -f "$2/$file"
692 elif [ -c "$1/$file" ]; then
693 [ -c "$2/$file" ] &&
694 [ "$(stat -c '%a:%u:%g:%t:%T' "$1/$file")" == \
695 "$(stat -c '%a:%u:%g:%t:%T' "$2/$file")" ] &&
696 rm -f "$2/$file"
697 fi
698 done
700 # cleanup directories; TODO: simplify
701 ( cd "$1"; find . -type d ) | sed '1!G;h;$!d' | \
702 while read file; do
703 [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
704 done
706 unset IFS
707 status
708 }
711 cleanup_merge() {
712 rm -rf $TMP_DIR
713 exit 1
714 }
717 # Update isolinux config files for multiple rootfs
719 update_bootconfig() {
720 local files
721 action 'Updating boot config files...'
722 files="$(grep -l 'include common' $1/*.cfg)"
723 for file in $files; do
724 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
725 if (/label/) label=$0;
726 else if (/kernel/) kernel=$0;
727 else if (/append/) {
728 i=index($0,"rootfs.gz");
729 append=substr($0,i+9);
730 }
731 else if (/include/) {
732 for (i = 1; i <= n; i++) {
733 print label i
734 print kernel;
735 initrd="initrd=/boot/rootfs" n ".gz"
736 for (j = n - 1; j >= i; j--) {
737 initrd=initrd ",/boot/rootfs" j ".gz";
738 }
739 printf "\tappend %s%s\n",initrd,append;
740 print "";
741 }
742 print;
743 }
744 else print;
745 }' < $file > $file.$$
746 mv -f $file.$$ $file
747 done
748 sel="$(echo $2 | awk '{
749 for (i=1; i<=NF; i++)
750 if (i % 2 == 0) printf " slitaz%d", i/2
751 else printf " %s", $i
752 }')"
754 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
756 label slitaz
757 kernel /boot/isolinux/ifmem.c32
758 append$sel noram
760 label noram
761 config noram.cfg
763 EOT
765 # Update vesamenu
766 if [ -s "$1/isolinux.cfg" ]; then
767 files="$files $1/isolinux.cfg"
768 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
769 BEGIN {
770 kernel = " COM32 c32box.c32"
771 }
772 {
773 if (/ROWS/) print "MENU ROWS " n+$3;
774 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
775 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
776 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
777 else if (/VSHIFT/) {
778 x = $3-n;
779 if (x < 0) x = 0;
780 print "MENU VSHIFT " x;
781 }
782 else if (/rootfs.gz/) {
783 linux = "";
784 if (/bzImage/) linux = "linux /boot/bzImage ";
785 i = index($0, "rootfs.gz");
786 append = substr($0, i+9);
787 printf "\tkernel /boot/isolinux/ifmem.c32\n";
788 printf "\tappend%s noram\n", sel;
789 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
790 for (i = 1; i <= n; i++) {
791 print "LABEL slitaz" i
792 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
793 printf "%s\n", kernel;
794 initrd = "initrd=/boot/rootfs" n ".gz"
795 for (j = n - 1; j >= i; j--) {
796 initrd = initrd ",/boot/rootfs" j ".gz";
797 }
798 printf "\tappend %s%s%s\n\n", linux, initrd, append;
799 }
800 }
801 else if (/bzImage/) kernel = $0;
802 else print;
803 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
804 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
805 fi
807 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
808 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
809 cat > $1/noram.cfg <<EOT
810 implicit 0
811 prompt 1
812 timeout 80
813 $(grep '^F[0-9]' $1/isolinux.cfg)
815 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
816 say Not enough RAM to boot slitaz. Trying hacker mode...
817 default hacker
818 label hacker
819 KERNEL /boot/bzImage
820 append rw root=/dev/null vga=normal
822 label reboot
823 EOT
825 if [ -s $1/c32box.c32 ]; then
826 cat >> $1/noram.cfg <<EOT
827 COM32 c32box.c32
828 append reboot
830 label poweroff
831 COM32 c32box.c32
832 append poweroff
834 EOT
835 else
836 echo " com32 reboot.c32" >> $1/noram.cfg
837 fi
839 # Restore real label names
840 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
841 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
842 while read pat; do
843 sed -i "s/slitaz$pat/" $files
844 done
845 status
846 }
849 # Uncompress rootfs or module to stdout
851 uncompress() {
852 zcat $1 2> /dev/null || xzcat $1 2> /dev/null || unlzma < $1 || cat $i
853 }
856 # Install a missing package
858 install_package() {
859 if [ -z "$2" ]; then
860 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
861 else
862 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
863 fi
864 case "$answer" in
865 y)
866 # We don't want package on host cache.
867 action 'Getting and installing package: %s' "$1"
868 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
869 status ;;
870 *)
871 return 1 ;;
872 esac
873 }
876 # Check iso for loram transformation
878 check_iso_for_loram() {
879 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
880 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
881 }
884 # Build initial rootfs for loram ISO ram/cdrom/http
886 build_initfs() {
887 urliso="mirror.switch.ch/ftp/mirror/slitaz \
888 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
889 mirror3.slitaz.org mirror.slitaz.org"
890 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
891 [ -z "$version" ] && die "Can't find the kernel version." \
892 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
894 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
895 need_lib=false
896 for i in bin dev run mnt proc tmp sys lib/modules; do
897 mkdir -p $TMP_DIR/initfs/$i
898 done
899 ln -s bin $TMP_DIR/initfs/sbin
900 ln -s . $TMP_DIR/initfs/usr
901 for aufs in aufs overlayfs; do
902 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
903 install_package $aufs $version && break
904 done || return 1
905 [ -s /init ] || install_package slitaz-boot-files
906 cp /init $TMP_DIR/initfs/
907 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
908 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
909 $TMP_DIR/initfs/lib/modules 2>/dev/null
910 cp -a /dev/tty0 /dev/fd0 $TMP_DIR/initfs/dev 2>/dev/null
911 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
912 $TMP_DIR/initfs/lib/modules
913 if [ "$1" == 'cdrom' ]; then
914 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
915 else
916 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
917 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
918 install_package linux-squashfs $version || return 1
919 done
920 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
921 $TMP_DIR/initfs/lib/modules
922 ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
923 cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
924 fi
925 for i in $(ls /dev/[hs]d[a-f]*); do
926 cp -a $i $TMP_DIR/initfs/dev
927 done
928 if [ "$1" == 'http' ]; then
929 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
930 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
931 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
932 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
933 cp -a /dev/fuse $TMP_DIR/initfs/dev
934 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
935 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
936 else
937 need_lib=true
938 fi
939 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
940 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
941 else
942 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
943 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
944 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
945 cp -a /lib/librt* $TMP_DIR/initfs/lib
946 cp -a /lib/libdl* $TMP_DIR/initfs/lib
947 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
948 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
949 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
950 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
951 need_lib=true
952 fi
953 cd $TMP_DIR/fs
954 echo 'Getting slitaz-release & ethernet modules...'
955 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
956 uncompress $i | cpio -idmu etc/slitaz-release lib/modules* >/dev/null
957 done
958 cd - > /dev/null
959 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
960 find $TMP_DIR/fs/lib/modules/*/kernel/drivers/net/ethernet \
961 -type f -name '*.ko*' | while read mod; do
962 f=$TMP_DIR/initfs/lib/modules/$(basename $mod | sed s/..z$//)
963 uncompress $mod > $f
964 grep -q alias=pci: $f || rm -f $f
965 done
966 for i in $TMP_DIR/initfs/lib/modules/*.ko ; do
967 f=$(basename $i)..z
968 grep -q $f:$ $TMP_DIR/fs/lib/modules/*/modules.dep && continue
969 deps="$(grep $f: $TMP_DIR/fs/lib/modules/*/modules.dep | sed 's/.*: //')"
970 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > $TMP_DIR/initfs/lib/modules/$(basename $i .ko).dep
971 for j in $deps; do
972 mod=$(ls $TMP_DIR/fs/lib/modules/*/$j)
973 uncompress $mod > $TMP_DIR/initfs/lib/modules/$(basename $j | sed s/..z$//)
974 done
975 done
976 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"
977 _n 'List of URLs to insert: '
978 read -t 30 urliso2
979 urliso="$urliso2 $urliso"
980 fi
981 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
982 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
983 sed -i 's/LD_T.*ot/newline/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
984 else
985 cp /bin/busybox $TMP_DIR/initfs/bin
986 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
987 cp /sbin/insmod $TMP_DIR/initfs/bin
988 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
989 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
990 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
991 fi
992 need_lib=true
993 fi
994 for i in $($TMP_DIR/initfs/bin/busybox | awk \
995 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
996 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
997 done
998 for i in /dev/console /dev/loop* /dev/null /dev/tty /dev/zero \
999 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1000 cp -a $i $TMP_DIR/initfs/dev
1001 done
1002 $need_lib && for i in /lib/ld-* /lib/lib[cm].so* /lib/lib[cm]-* ; do
1003 cp -a $i $TMP_DIR/initfs/lib
1004 done
1005 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1006 #!/bin/sh
1008 getarg() {
1009 grep -q " \$1=" /proc/cmdline || return 1
1010 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1011 return 0
1014 copy_rootfs() {
1015 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1016 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1017 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1018 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1019 path=/mnt/
1020 return 0
1021 else
1022 rm -f /mnt/rootfs*
1023 return 1
1024 fi
1027 echo "Switching / to tmpfs..."
1028 mount -t proc proc /proc
1029 size="\$(grep rootfssize= < /proc/cmdline | \\
1030 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1031 [ -n "\$size" ] || size="-o size=90%"
1033 mount -t sysfs sysfs /sys
1034 for i in /lib/modules/*.ko ; do
1035 echo -en "Probe \$i \\r"
1036 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1037 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1038 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1039 insmod /lib/modules/\$k.ko 2> /dev/null
1040 done
1041 echo "Loading \$i"
1042 insmod \$i 2> /dev/null
1043 break
1044 done
1045 done
1046 umount /sys
1047 while read var default; do
1048 eval \$var=\$default
1049 getarg \$var \$var
1050 done <<EOT
1051 eth eth0
1052 dns 208.67.222.222,208.67.220.220
1053 netmask 255.255.255.0
1054 gw
1055 ip
1056 EOT
1057 if [ -n "\$ip" ]; then
1058 ifconfig \$eth \$ip netmask \$netmask up
1059 route add default gateway \$gw
1060 for i in \$(echo \$dns | sed 's/,/ /g'); do
1061 echo "nameserver \$i" >> /etc/resolv.conf
1062 done
1063 else
1064 udhcpc -f -q -s /lib/udhcpc -i \$eth
1065 fi
1066 for i in $urliso ; do
1067 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1068 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"
1069 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1070 done
1071 getarg urliso URLISO
1072 DIR=fs
1073 if getarg loram DIR; then
1074 DEVICE=\${DIR%,*}
1075 DIR=/\${DIR#*,}
1076 fi
1077 mount -t tmpfs \$size tmpfs /mnt
1078 path2=/mnt/.httpfs/
1079 path=/mnt/.cdrom/
1080 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1081 while [ ! -d \$path/boot ]; do
1082 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1083 httpfs \$i \$path2 && echo \$i && break
1084 done
1085 mount -o loop,ro -t iso9660 \$path2/*.iso \$path
1086 done
1088 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1089 umount /proc
1090 branch=:/mnt/.cdrom/\$DIR
1091 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1092 branch=
1093 lp=1
1094 insmod /lib/modules/squashfs.ko 2> /dev/null
1095 for i in \${path}boot/rootfs?.* ; do
1096 fs=\${i#*root}
1097 branch=\$branch:/mnt/.\$fs
1098 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1099 losetup -o 124 /dev/loop\$lp \$i
1100 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1101 lp=\$((\$lp+1))
1102 done
1103 else
1104 mkdir -p /mnt/.rw/mnt/.httpfs
1105 fi
1106 while read type opt; do
1107 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1108 done <<EOT
1109 aufs br=/mnt/.rw\$branch
1110 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1111 EOT
1112 rm -rf /lib/modules
1113 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1114 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1115 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1116 EOTEOT
1117 chmod +x $TMP_DIR/initfs/init
1118 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1119 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1120 rm -f $i
1121 dogzip ${i%.gz}
1122 done 2>/dev/null
1123 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1124 lzma e $TMP_DIR/initfs.gz -si
1125 lzma_set_size $TMP_DIR/initfs.gz
1126 rm -rf $TMP_DIR/initfs
1127 align_to_32bits $TMP_DIR/initfs.gz
1128 return 0
1132 # Move each initramfs to squashfs
1134 build_loram_rootfs() {
1135 rootfs_sizes=""
1136 for i in $TMP_DIR/iso/boot/rootfs*; do
1137 mkdir -p $TMP_DIR/fs
1138 cd $TMP_DIR/fs
1139 uncompress $i | cpio -idm
1140 deduplicate
1141 cd - > /dev/null
1142 rootfs=$TMP_DIR/$(basename $i)
1143 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp xz -Xbcj x86
1144 cd $TMP_DIR
1145 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1146 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1147 rm -f $rootfs
1148 mv $rootfs.cpio $rootfs
1149 cd - > /dev/null
1150 rm -rf $TMP_DIR/fs
1151 done
1155 # Move meta boot configuration files to basic configuration files
1156 # because meta loram flavor is useless when rootfs is not loaded in RAM
1158 unmeta_boot() {
1159 local root=${1:-$TMP_DIR/loramiso}
1160 if [ -f $root/boot/isolinux/noram.cfg ]; then
1161 # We keep enough information to do unloram...
1162 [ -s $root/boot/isolinux/common.cfg ] &&
1163 sed -i 's/label slitaz/label orgslitaz/' \
1164 $root/boot/isolinux/common.cfg
1165 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1166 shift
1167 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1168 $root/boot/isolinux/isolinux.cfg
1169 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1170 sed -i "s/label $3\$/label slitaz/;s|=/boot/rootfs\(.*\).gz |=/boot/rootfs.gz |" \
1171 $root/boot/isolinux/*.cfg
1172 fi
1176 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1177 # These squashfs may be loaded in RAM at boot time.
1178 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1179 # Meta flavors are converted to normal flavors.
1181 build_loram_cdrom() {
1182 build_initfs cdrom || return 1
1183 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1184 mkdir $TMP_DIR/loramiso/fs
1185 cd $TMP_DIR/loramiso/fs
1186 for i in $( ls ../boot/root* | sort -r ) ; do
1187 uncompress $i | cpio -idmu
1188 rm -f $i
1189 done
1190 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1191 cd - >/dev/null
1192 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1193 unmeta_boot
1194 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1195 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1196 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1197 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1198 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1199 create_iso $OUTPUT $TMP_DIR/loramiso
1203 # Create http bootstrap to load and remove loram_cdrom
1204 # Meta flavors are converted to normal flavors.
1206 build_loram_http() {
1207 build_initfs http || return 1
1208 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1209 rm -f $TMP_DIR/loramiso/boot/rootfs*
1210 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1211 unmeta_boot
1212 create_iso $OUTPUT $TMP_DIR/loramiso
1216 # Update meta flavor selection sizes.
1217 # Reduce sizes with rootfs gains.
1219 update_metaiso_sizes() {
1220 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1221 do
1222 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1223 local sizes="$rootfs_sizes"
1224 local new
1225 set -- $append
1226 shift
1227 [ "$1" == "ifmem" ] && shift
1228 new=""
1229 while [ -n "$2" ]; do
1230 local s
1231 case "$1" in
1232 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1233 *M) s=$(( ${1%M} * 1024 ));;
1234 *) s=${1%K};;
1235 esac
1236 sizes=${sizes#* }
1237 for i in $sizes ; do
1238 s=$(( $s - $i ))
1239 done
1240 new="$new $s $2"
1241 shift 2
1242 done
1243 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1244 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1245 sed -i 's|\(initrd=\)\(/boot/rootfs.\.gz\)|\1/boot/rootfs.gz,\2|' $cfg
1246 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1247 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1248 done
1252 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1253 # Meta flavor selection sizes are updated.
1255 build_loram_ram() {
1256 build_initfs ram || return 1
1257 build_loram_rootfs
1258 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1259 make_bzImage_hardlink $TMP_DIR/loramiso/boot
1260 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1261 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1262 update_metaiso_sizes
1263 create_iso $OUTPUT $TMP_DIR/loramiso
1267 # Remove files installed by packages
1269 find_flavor_rootfs() {
1270 for i in $1/etc/tazlito/*.extract; do
1271 [ -e $i ] || continue
1272 chroot $1 /bin/sh ${i#$1}
1273 done
1275 # Clean hardlinks and files patched by genisofs in /boot
1276 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1277 rm -f $1/boot/$i*
1278 done
1280 # Clean files generated in post_install
1281 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1282 $1/dev/core $1/dev/fd $1/dev/std*
1284 # Verify md5
1285 cat $1$INSTALLED/*/md5sum | \
1286 while read md5 file; do
1287 [ -e "$1$file" ] || continue
1288 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1289 rm -f "$1$file"
1290 done
1292 # Check configuration files
1293 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1294 [ -e $i ] || continue
1295 mkdir /tmp/volatile$$
1296 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1297 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1298 while read file ; do
1299 [ -e "$1/$file" ] || continue
1300 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1301 done
1302 rm -rf /tmp/volatile$$
1303 done
1305 # Remove other files blindly
1306 for i in $1$INSTALLED/*/files.list; do
1307 for file in $(cat "$i"); do
1308 [ "$1$file" -nt "$i" ] && continue
1309 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1310 [ -d "$1$file" ] || rm -f "$1$file"
1311 done
1312 done
1314 # Remove tazpkg files and tmp files
1315 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1316 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1317 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1318 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1319 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1321 # Cleanup directory tree
1322 cd $1
1323 find * -type d | sort -r | while read dir; do
1324 rmdir "$dir" 2>/dev/null
1325 done
1326 cd - > /dev/null
1330 # Get byte(s) from a binary file
1332 get() {
1333 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null
1337 # Get cpio flavor info from the ISO image
1339 flavordata() {
1340 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1341 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1345 # Restore undigest mirrors
1347 restore_mirrors() {
1348 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1349 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1351 action 'Restoring mirrors...'
1352 if [ -d "$undigest.bak" ]; then
1353 [ -d "$undigest" ] && rm -r "$undigest"
1354 mv "$undigest.bak" "$undigest"
1355 fi
1356 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1357 :; status
1361 # Setup undigest mirrors
1363 setup_mirrors() {
1364 # Setup mirrors in plain system or in chroot (with variable root=)
1365 local mirrorlist="$1" fresh repacked
1366 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1368 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1369 restore_mirrors
1371 _ 'Setting up mirrors for %s...' "$root/"
1372 # Backing up current undigest mirrors and priority
1373 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1374 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1375 rm -rf '/var/www/tazlito/'
1376 mkdir -p '/var/www/tazlito/'
1378 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1379 fresh='/home/slitaz/packages'
1380 if [ -d "$fresh" ]; then
1381 # Setup first undigest mirror
1382 mkdir -p "$undigest/fresh"
1383 echo "$fresh" > "$undigest/fresh/mirror"
1384 echo 'fresh' >> "$priority"
1385 # Rebuild mirror DB if needed
1386 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1387 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1388 tazpkg mkdb "$fresh" --forced --root=''
1389 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1390 fi
1392 # Repacked packages: high priority
1393 repacked="$PACKAGES_REPOSITORY"
1394 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1395 # According to Tazlito setup file (tazlito.conf):
1396 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1397 # or
1398 # WORK_DIR="/home/slitaz"
1399 # and
1400 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1401 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1403 # Setup second undigest mirror
1404 mkdir -p "$undigest/repacked"
1405 echo "$repacked" > "$undigest/repacked/mirror"
1406 echo 'repacked' >> "$priority"
1407 # Rebuild mirror DB if needed
1408 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1409 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1410 tazpkg mkdb "$repacked" --forced --root=''
1411 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1412 fi
1414 # All repositories listed in mirrors list: normal priority
1415 [ -e "$mirrorlist" ] && \
1416 while read mirror; do
1417 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1418 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1419 mkdir -p "$undigest/$mirrorid"
1420 echo "$mirror" > "$undigest/$mirrorid/mirror"
1421 echo "$mirrorid" >> "$priority"
1422 done < "$mirrorlist"
1424 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1426 # Show list of mirrors
1427 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1428 function show(num, name, url) {
1429 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1432 num++;
1433 "cat " db "/undigest/" $0 "/mirror" | getline url;
1434 show(num, $0, url);
1436 END {
1437 num++;
1438 "cat " db "/mirror" | getline url;
1439 show(num, "main", url);
1440 }' "$priority"
1442 tazpkg recharge --quiet >/dev/null
1446 # Get list of 'packages.info' lists using priority
1448 pi_lists() {
1449 local pi
1450 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1451 local priority="$root$LOCALSTATE/priority"
1452 local undigest="$root$LOCALSTATE/undigest"
1455 [ -s "$priority" ] && cat "$priority"
1456 echo 'main'
1457 [ -d "$undigest" ] && ls "$undigest"
1458 } | awk -vun="$undigest/" '
1460 if (arr[$0] != 1) {
1461 arr[$0] = 1;
1462 print un $0 "/packages.info";
1464 }' | sed 's|/undigest/main||' | \
1465 while read pi; do
1466 [ -e "$pi" ] && echo "$pi"
1467 done
1471 # Strip versions from packages list
1473 strip_versions() {
1474 action 'Strip versions from list %s...' "$(basename "$1")"
1475 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1476 [ -f "$in_list" ] || die "List '$in_list' not found."
1478 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1479 awk '
1481 if (FILENAME ~ "packages.info") {
1482 # Collect package names
1483 FS = "\t"; pkg[$1] = 1;
1484 } else {
1485 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1486 while (NF > 1 && ! pkg[$0])
1487 NF --;
1488 printf "%s\n", $0;
1490 }' $(pi_lists) "$in_list" > "$tmp_list"
1492 cat "$tmp_list" > "$in_list"
1493 rm "$tmp_list"
1494 status
1498 # Display list of unknown packages (informative)
1500 display_unknown() {
1501 [ -s "$1" ] || return
1502 echo "Unknown packages:" >&2
1503 cat "$1" >&2
1504 rm "$1"
1508 # Display warnings about critical packages absent (informative)
1510 display_warn() {
1511 [ -s "$1" ] || return
1512 echo "Absent critical packages:" >&2
1513 cat "$1" >&2
1514 rm "$1"
1515 echo "Probably ISO image will be unusable."
1519 # Install packages to rootfs
1521 install_list_to_rootfs() {
1522 local list="$1" rootfs="$2" pkg i ii
1523 local undigest="$rootfs/var/lib/tazpkg/undigest"
1525 # initial tazpkg setup in empty rootfs
1526 tazpkg --root=$rootfs >/dev/null 2>&1
1527 # link rootfs packages cache to the regular packages cache
1528 rm -r "$rootfs/var/cache/tazpkg"
1529 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1531 setup_mirrors mirrors
1533 # Just in case if flavor not contains "tazlito" package
1534 mkdir -p "$rootfs/etc/tazlito"
1536 newline
1537 for pkg in $(cat $list); do
1538 action 'Installing package: %s' "$pkg"
1539 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1540 status
1541 done
1542 newline
1544 restore_mirrors
1545 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1546 for i in fresh repacked; do
1547 ii="$undigest/$i"
1548 [ -d "$ii" ] && rm -rf "$ii"
1549 ii="$rootfs/var/lib/tazpkg/priority"
1550 if [ -f "$ii" ]; then
1551 sed -i "/$i/d" "$ii"
1552 [ -s "$ii" ] || rm "$ii"
1553 fi
1554 done
1555 [ -d "$undigest" ] && \
1556 for i in $(find "$undigest" -type f); do
1557 # Remove all undigest PKGDB files but 'mirror'
1558 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1559 done
1560 [ -d "$undigest" ] && \
1561 rmdir --ignore-fail-on-non-empty "$undigest"
1563 # Un-link packages cache
1564 rm "$rootfs/var/cache/tazpkg"
1566 # Clean /var/lib/tazpkg
1567 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1573 ####################
1574 # Tazlito commands #
1575 ####################
1577 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1578 case "$0" in
1579 *reduplicate)
1580 find ${@:-.} ! -type d -links +1 \
1581 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1582 exit 0 ;;
1583 *deduplicate)
1584 deduplicate "$@"
1585 exit 0 ;;
1586 esac
1589 case "$COMMAND" in
1590 stats)
1591 # Tazlito general statistics from the config file.
1593 title 'Tazlito statistics'
1594 optlist "\
1595 Config file : $CONFIG_FILE
1596 ISO name : $ISO_NAME.iso
1597 Volume name : $VOLUM_NAME
1598 Prepared : $PREPARED
1599 Packages repository : $PACKAGES_REPOSITORY
1600 Distro directory : $DISTRO
1601 Additional files : $ADDFILES
1602 " | sed '/: $/d'
1603 footer
1604 ;;
1607 list-addfiles)
1608 # Simple list of additional files in the rootfs
1609 newline
1610 if [ -d "$ADDFILES/rootfs" ]; then
1611 cd $ADDFILES
1612 find rootfs -type f
1613 else
1614 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1615 fi
1616 newline
1617 ;;
1620 gen-config)
1621 # Generate a new config file in the current dir or the specified
1622 # directory by $2.
1624 if [ -n "$2" ]; then
1625 mkdir -p "$2" && cd "$2"
1626 fi
1628 newline
1629 action 'Generating empty tazlito.conf...'
1630 empty_config_file
1631 status
1633 separator
1634 if [ -f 'tazlito.conf' ] ; then
1635 _ 'Configuration file is ready to edit.'
1636 _ 'File location: %s' "$(pwd)/tazlito.conf"
1637 newline
1638 fi
1639 ;;
1642 configure)
1643 # Configure a tazlito.conf config file. Start by getting
1644 # a empty config file and sed it.
1646 if [ -f 'tazlito.conf' ]; then
1647 rm tazlito.conf
1648 else
1649 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1650 'or in the same directory of the file you want to configure.'
1651 cd /etc
1652 fi
1654 empty_config_file
1656 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1658 # ISO name.
1659 echo -n "ISO name : " ; read answer
1660 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1661 # Volume name.
1662 echo -n "Volume name : " ; read answer
1663 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1664 # Packages repository.
1665 echo -n "Packages repository : " ; read answer
1666 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1667 # Distro path.
1668 echo -n "Distro path : " ; read answer
1669 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1670 footer "Config file is ready to use."
1671 echo 'You can now extract an ISO or generate a distro.'
1672 newline
1673 ;;
1676 gen-iso)
1677 # Simply generate a new iso.
1679 check_root
1680 verify_rootcd
1681 gen_livecd_isolinux
1682 distro_stats
1683 ;;
1686 gen-initiso)
1687 # Simply generate a new initramfs with a new iso.
1689 check_root
1690 verify_rootcd
1691 gen_initramfs "$ROOTFS"
1692 gen_livecd_isolinux
1693 distro_stats
1694 ;;
1697 extract-distro)
1698 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1700 check_root
1701 ISO_IMAGE="$2"
1702 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1703 'Example:\n tazlito image.iso /path/target'
1705 # Set the distro path by checking for $3 on cmdline.
1706 TARGET="${3:-$DISTRO}"
1708 # Exit if existing distro is found.
1709 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1710 'Please clean the distro tree or change directory path.'
1712 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
1714 # Start to mount the ISO.
1715 action 'Mounting ISO image...'
1716 mkdir -p "$TMP_DIR"
1717 # Get ISO file size.
1718 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
1719 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
1720 sleep 2
1721 # Prepare target dir, copy the kernel and the rootfs.
1722 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
1723 status
1725 action 'Copying the Linux kernel...'
1726 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
1727 make_bzImage_hardlink "$TARGET/rootcd/boot"
1728 else
1729 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
1730 fi
1731 status
1733 for i in $(ls $TMP_DIR); do
1734 [ "$i" == 'boot' ] && continue
1735 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
1736 done
1738 for loader in isolinux syslinux extlinux grub; do
1739 [ -d "$TMP_DIR/boot/$loader" ] || continue
1740 action 'Copying %s files...' "$loader"
1741 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
1742 status
1743 done
1745 action 'Copying the rootfs...'
1746 cp $TMP_DIR/boot/rootfs.?z "$TARGET/rootcd/boot"
1747 status
1749 # Extract initramfs.
1750 cd "$TARGET/rootfs"
1751 action 'Extracting the rootfs...'
1752 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
1753 # unpack /usr
1754 for i in etc/tazlito/*.extract; do
1755 [ -f "$i" ] && . $i ../rootcd
1756 done
1757 # Umount and remove temp directory and cd to $TARGET to get stats.
1758 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
1759 cd ..
1760 status
1762 newline
1763 separator
1764 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
1765 echo "Distro tree : $(pwd)"
1766 echo "Rootfs size : $(du -sh rootfs)"
1767 echo "Rootcd size : $(du -sh rootcd)"
1768 footer
1769 ;;
1772 list-flavors)
1773 # Show available flavors.
1774 list='/etc/tazlito/flavors.list'
1775 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
1776 title 'List of flavors'
1777 cat $list
1778 footer
1779 ;;
1782 show-flavor)
1783 # Show flavor description.
1784 set -e
1785 flavor=${2%.flavor}
1786 flv_dir="$(extract_flavor "$flavor")"
1787 desc="$flv_dir/$flavor.desc"
1788 if [ -n "$brief" ]; then
1789 if [ -z "$noheader" ]; then
1790 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
1791 separator
1792 fi
1793 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
1794 "$(field ISO "$desc")" \
1795 "$(field Rootfs "$desc")" \
1796 "$(field Description "$desc")"
1797 else
1798 separator
1799 cat "$desc"
1800 fi
1801 cleanup
1802 ;;
1805 gen-liveflavor)
1806 # Generate a new flavor from the live system.
1807 FLAVOR=${2%.flavor}
1808 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1810 case "$FLAVOR" in
1811 -?|-h*|--help)
1812 cat <<EOT
1813 SliTaz Live Tool - Version: $VERSION
1815 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
1817 $(boldify '<flavor-patch-file> format:')
1818 $(optlist "\
1819 code data
1820 + package to add
1821 - package to remove
1822 ! non-free package to add
1823 ? display message
1824 @ flavor description
1825 ")
1827 $(boldify 'Example:')
1828 $(optlist "\
1829 @ Developer tools for SliTaz maintainers
1830 + slitaz-toolchain
1831 + mercurial
1832 ")
1833 EOT
1834 exit 1
1835 ;;
1836 esac
1837 mv /etc/tazlito/distro-packages.list \
1838 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
1839 rm -f distro-packages.list non-free.list 2>/dev/null
1840 tazpkg recharge
1842 DESC=""
1843 [ -n "$3" ] && \
1844 while read action pkg; do
1845 case "$action" in
1846 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
1847 -) yes | tazpkg remove $pkg ;;
1848 !) echo $pkg >> non-free.list ;;
1849 @) DESC="$pkg" ;;
1850 \?) echo -en "$pkg"; read action ;;
1851 esac
1852 done < $3
1854 yes '' | tazlito gen-distro
1855 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
1856 mv /etc/tazlito/distro-packages.list.$$ \
1857 /etc/tazlito/distro-packages.list 2>/dev/null
1858 ;;
1861 gen-flavor)
1862 # Generate a new flavor from the last ISO image generated
1863 FLAVOR=${2%.flavor}
1864 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1866 title 'Flavor generation'
1867 check_rootfs
1868 FILES="$FLAVOR.pkglist"
1870 action 'Creating file %s...' "$FLAVOR.flavor"
1871 for i in rootcd rootfs; do
1872 if [ -d "$ADDFILES/$i" ] ; then
1873 FILES="$FILES\n$FLAVOR.$i"
1874 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
1875 fi
1876 done
1877 status
1879 answer=$(grep -s ^Description $FLAVOR.desc)
1880 answer=${answer#Description : }
1881 if [ -z "$answer" ]; then
1882 echo -n "Description: "
1883 read answer
1884 fi
1886 action 'Compressing flavor %s...' "$FLAVOR"
1887 echo "Flavor : $FLAVOR" > $FLAVOR.desc
1888 echo "Description : $answer" >> $FLAVOR.desc
1889 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
1890 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
1891 for i in $(ls $ROOTFS$INSTALLED); do
1892 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
1893 EXTRAVERSION=""
1894 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
1895 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
1896 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
1897 echo "$i" >> $FLAVOR.nonfree
1898 else
1899 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
1900 fi
1901 done
1902 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
1903 for i in $LOCALSTATE/undigest/*/mirror ; do
1904 [ -s $i ] && cat $i >> $FLAVOR.mirrors
1905 done
1906 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
1907 touch -t 197001010100.00 $FLAVOR.*
1908 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
1909 rm $(echo -e $FILES)
1910 status
1912 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
1913 ;;
1916 upgrade-flavor)
1917 # Strip versions from pkglist and update estimated numbers in flavor.desc
1918 flavor="${2%.flavor}"
1919 set -e
1920 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1921 set +e
1923 flv_dir="$(extract_flavor "$flavor")"
1925 strip_versions "$flv_dir/$flavor.pkglist"
1927 action 'Updating %s...' "$flavor.desc"
1929 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
1930 set -- $(module calc_sizes "$flv_dir" "$flavor")
1931 restore_mirrors >/dev/null
1933 sed -i -e '/Image is ready/d' \
1934 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
1935 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
1936 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
1937 -e "s|\(Packages *:\).*$|\1 $4|" \
1938 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
1939 "$flv_dir/$flavor.desc"
1941 pack_flavor "$flv_dir" "$flavor"
1942 status
1943 display_unknown "$flv_dir/err"
1944 display_warn "$flv_dir/warn"
1945 cleanup
1946 ;;
1949 extract-flavor)
1950 # Extract a flavor into $FLAVORS_REPOSITORY
1951 flavor="${2%.flavor}"
1952 set -e
1953 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1954 set +e
1956 action 'Extracting %s...' "$flavor.flavor"
1957 flv_dir="$(extract_flavor "$flavor" full)"
1958 storage="$FLAVORS_REPOSITORY/$flavor"
1960 rm -rf "$storage" 2>/dev/null
1961 mkdir -p "$storage"
1962 cp -a "$flv_dir"/* "$storage"
1963 rm "$storage/description"
1964 status
1966 strip_versions "$storage/packages.list"
1968 cleanup
1969 ;;
1972 pack-flavor)
1973 # Create a flavor from $FLAVORS_REPOSITORY.
1974 flavor=${2%.flavor}
1975 storage="$FLAVORS_REPOSITORY/$flavor"
1977 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
1979 action 'Creating flavor %s...' "$flavor"
1980 tmp_dir="$(mktemp -d)"
1982 while read from to; do
1983 [ -s "$storage/$from" ] || continue
1984 cp -a "$storage/$from" "$tmp_dir/$to"
1985 done <<EOT
1986 mirrors $flavor.mirrors
1987 distro.sh $flavor-distro.sh
1988 receipt $flavor.receipt
1989 non-free.list $flavor.nonfree
1990 EOT
1992 # Build the package list.
1993 # It can include a list from another flavor with the keyword @include
1994 if [ -s "$storage/packages.list" ]; then
1995 include=$(grep '^@include' "$storage/packages.list")
1996 if [ -n "$include" ]; then
1997 include=${include#@include }
1998 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
1999 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2000 else
2001 echo -e "\nERROR: Can't find include package list from $include\n"
2002 fi
2003 fi
2004 # Generate the final/initial package list
2005 [ -s "$storage/packages.list" ] && \
2006 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2007 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2008 fi
2010 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2011 # Process multi-rootfs flavor
2012 . "$storage/receipt"
2013 set -- $ROOTFS_SELECTION
2014 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2015 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2016 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2018 for i in rootcd rootfs; do
2019 mkdir "$tmp_dir/$i"
2020 # Copy extra files from the first flavor
2021 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2022 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2023 # Overload extra files by meta flavor
2024 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2025 [ -n "$(ls $tmp_dir/$i)" ] &&
2026 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2027 dogzip "$tmp_dir/$flavor.$i"
2028 rm -rf "$tmp_dir/$i"
2029 done
2030 else
2031 # Process plain flavor
2032 for i in rootcd rootfs; do
2033 [ -d "$storage/$i" ] || continue
2034 (cd "$storage/$i";
2035 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2036 done
2037 fi
2039 unset VERSION MAINTAINER ROOTFS_SELECTION
2040 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2041 ROOTFS_SIZE="$1 (estimated)"
2042 INITRAMFS_SIZE="$2 (estimated)"
2043 ISO_SIZE="$3 (estimated)"
2044 PKGNUM="$4"
2045 . "$storage/receipt"
2047 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2048 Flavor : $FLAVOR
2049 Description : $SHORT_DESC
2050 Version : $VERSION
2051 Maintainer : $MAINTAINER
2052 LiveCD RAM size : $FRUGAL_RAM
2053 Rootfs list : $ROOTFS_SELECTION
2054 Build date : $(date '+%Y%m%d at %T')
2055 Packages : $PKGNUM
2056 Rootfs size : $ROOTFS_SIZE
2057 Initramfs size : $INITRAMFS_SIZE
2058 ISO image size : $ISO_SIZE
2059 ================================================================================
2061 EOT
2063 rm -f $tmp_dir/packages.list
2064 pack_flavor "$tmp_dir" "$flavor"
2065 status
2066 display_unknown "$tmp_dir/err"
2067 display_warn "$flv_dir/warn"
2068 cleanup
2069 ;;
2072 get-flavor)
2073 # Get a flavor's files and prepare for gen-distro.
2074 flavor=${2%.flavor}
2075 title 'Preparing %s distro flavor' "$flavor"
2076 set -e
2077 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2078 set +e
2080 action 'Cleaning %s...' "$DISTRO"
2081 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2082 # Clean old files
2083 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2084 [ -f "$i" ] && rm "$i"
2085 done
2086 mkdir -p "$DISTRO"
2087 status
2089 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2091 action 'Extracting flavor %s...' "$flavor.flavor"
2092 flv_dir="$(extract_flavor "$flavor" info)"
2093 cp -a "$flv_dir"/* .
2094 mv packages.list distro-packages.list
2095 mv -f info /etc/tazlito
2096 status
2098 for i in rootcd rootfs; do
2099 if [ -d "$i" ]; then
2100 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2101 fi
2102 done
2104 rm -f /etc/tazlito/rootfs.list
2105 grep -q '^Rootfs list' description &&
2106 grep '^Rootfs list' description | sed 's/.*: \(.*\)$/\1/' > /etc/tazlito/rootfs.list
2108 action 'Updating %s...' 'tazlito.conf'
2109 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2110 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2111 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2112 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2113 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2114 status
2116 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2117 cleanup
2118 ;;
2121 iso2flavor)
2122 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2123 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2125 FLAVOR=${3%.flavor}
2126 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2127 mount -o loop,ro $2 $TMP_DIR/iso
2128 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2129 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2130 ! -s $TMP_DIR/flavor/*.desc ]; then
2131 _ 'META flavors are not supported.'
2132 umount -d $TMP_DIR/iso
2133 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2134 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2135 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2136 umount -d $TMP_DIR/iso
2137 else
2138 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2139 uncompress $i | \
2140 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2141 done
2142 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2143 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2144 '/etc/slitaz-release' '/boot/rootfs.gz'
2145 umount -d $TMP_DIR/iso
2146 else
2147 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2148 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2149 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2150 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2151 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2152 umount -d $TMP_DIR/iso
2153 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2154 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2155 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2156 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2157 < $TMP_DIR/rootfs$INSTALLED.md5
2158 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2159 if [ -s $TMP_DIR/flavor/*desc ]; then
2160 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2161 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2162 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2163 for i in rootfs rootcd ; do
2164 [ -s $TMP_DIR/flavor/*.list$i ] &&
2165 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2166 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2167 done
2168 else
2169 find_flavor_rootfs $TMP_DIR/rootfs
2170 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2171 for i in rootfs rootcd ; do
2172 [ "$(ls $TMP_DIR/$i)" ] &&
2173 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2174 done
2175 unset VERSION MAINTAINER
2176 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2177 if [ -n "$DESCRIPTION" ]; then
2178 _n 'Flavor version : '; read -t 30 VERSION
2179 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2180 fi
2182 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2183 Flavor : $FLAVOR
2184 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2185 Version : ${VERSION:-1.0}
2186 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2187 LiveCD RAM size : $RAM_SIZE
2188 Build date : $BUILD_DATE
2189 Packages : $PKGCNT
2190 Rootfs size : $ROOTFS_SIZE
2191 Initramfs size : $INITRAMFS_SIZE
2192 ISO image size : $ISO_SIZE
2193 ================================================================================
2195 EOT
2196 longline "Tazlito can't detect each file installed during \
2197 a package post_install. You should extract this flavor (tazlito extract-flavor \
2198 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2199 tree and remove files generated by post_installs.
2200 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2201 repack the flavor (tazlito pack-flavor $FLAVOR)"
2202 fi
2203 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2204 fi
2205 fi
2206 rm -rf $TMP_DIR
2207 ;;
2210 gen-distro)
2211 # Generate a live distro tree with a set of packages.
2213 check_root
2214 start_time=$(date +%s)
2216 # Tazlito options: --iso or --cdrom
2217 CDROM=''
2218 [ -n "$iso" ] && CDROM="-o loop $iso"
2219 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2221 # Check if a package list was specified on cmdline.
2222 if [ -f "$2" ]; then
2223 LIST_NAME="$2"
2224 else
2225 LIST_NAME='distro-packages.list'
2226 fi
2228 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2229 'Please clean the distro tree or change directory path.'
2230 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2231 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2233 # If list not given: build list with all installed packages
2234 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2235 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2236 fi
2238 # Exit if no list name.
2239 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2241 # Start generation.
2242 title 'Tazlito generating a distro'
2244 # Misc checks
2245 mkdir -p "$PACKAGES_REPOSITORY"
2246 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2247 newline
2249 # Mount CD-ROM to be able to repack boot-loader packages
2250 if [ ! -e /boot -a -n "$CDROM" ]; then
2251 mkdir $TMP_MNT
2252 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2253 ln -s "$TMP_MNT/boot" /
2254 if [ ! -d "$ADDFILES/rootcd" ] ; then
2255 mkdir -p "$ADDFILES/rootcd"
2256 for i in $(ls $TMP_MNT); do
2257 [ "$i" == 'boot' ] && continue
2258 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2259 done
2260 fi
2261 else
2262 rmdir "$TMP_MNT"
2263 fi
2264 fi
2266 # Rootfs stuff.
2267 echo 'Preparing the rootfs directory...'
2268 mkdir -p "$ROOTFS"
2269 export root="$ROOTFS"
2270 strip_versions "$LIST_NAME"
2272 if [ "$REPACK" == 'y' ]; then
2273 # Determine full packages list with all dependencies
2274 tmp_dir="$(mktemp -d)"
2275 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2276 touch "$tmp_dir/full.pkglist"
2277 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2279 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2280 while read pkgname pkgver; do
2281 # Is package in full list?
2282 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2283 # Is package already repacked?
2284 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2285 _ 'Repacking %s...' "$pkgname-$pkgver"
2286 tazpkg repack "$pkgname" --quiet
2287 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2288 status
2289 done
2291 rm -r "$tmp_dir"
2292 fi
2294 if [ -f non-free.list ]; then
2295 # FIXME: working in the ROOTFS chroot?
2296 newline
2297 echo 'Preparing non-free packages...'
2298 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2299 for pkg in $(cat 'non-free.list'); do
2300 if [ ! -d "$INSTALLED/$pkg" ]; then
2301 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2302 tazpkg get-install get-$pkg
2303 fi
2304 get-$pkg "$ROOTFS"
2305 fi
2306 tazpkg repack $pkg
2307 pkg=$(ls $pkg*.tazpkg)
2308 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2309 mv $pkg $PACKAGES_REPOSITORY
2310 done
2311 fi
2312 cp $LIST_NAME $DISTRO/distro-packages.list
2313 newline
2315 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2317 cd $DISTRO
2318 cp distro-packages.list $ROOTFS/etc/tazlito
2319 # Copy all files from $ADDFILES/rootfs to the rootfs.
2320 if [ -d "$ADDFILES/rootfs" ] ; then
2321 action 'Copying addfiles content to the rootfs...'
2322 cp -a $ADDFILES/rootfs/* $ROOTFS
2323 status
2324 fi
2326 action 'Root filesystem is generated...'; status
2328 # Root CD part.
2329 action 'Preparing the rootcd directory...'
2330 mkdir -p $ROOTCD
2331 status
2333 # Move the boot dir with the Linux kernel from rootfs.
2334 # The boot dir goes directly on the CD.
2335 if [ -d "$ROOTFS/boot" ] ; then
2336 action 'Moving the boot directory...'
2337 mv $ROOTFS/boot $ROOTCD
2338 cd $ROOTCD/boot
2339 make_bzImage_hardlink
2340 status
2341 fi
2342 cd $DISTRO
2343 # Copy all files from $ADDFILES/rootcd to the rootcd.
2344 if [ -d "$ADDFILES/rootcd" ] ; then
2345 action 'Copying addfiles content to the rootcd...'
2346 cp -a $ADDFILES/rootcd/* $ROOTCD
2347 status
2348 fi
2349 # Execute the distro script used to perform tasks in the rootfs
2350 # before compression. Give rootfs path in arg
2351 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2352 if [ -x "$DISTRO_SCRIPT" ]; then
2353 echo 'Executing distro script...'
2354 sh $DISTRO_SCRIPT $DISTRO
2355 fi
2357 # Execute the custom_rules() found in receipt.
2358 if [ -s "$TOP_DIR/receipt" ]; then
2359 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2360 echo -e "Executing: custom_rules()\n"
2361 . "$TOP_DIR/receipt"
2362 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2363 fi
2364 fi
2366 # Multi-rootfs
2367 if [ -s /etc/tazlito/rootfs.list ]; then
2369 FLAVOR_LIST="$(awk '{
2370 for (i = 2; i <= NF; i+=2)
2371 printf "%s ", i;
2372 }' /etc/tazlito/rootfs.list)"
2374 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2375 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2376 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2378 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2379 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2380 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2381 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2383 n=0
2384 last=$ROOTFS
2385 while read flavor; do
2386 n=$(($n+1))
2387 mkdir ${ROOTFS}0$n
2388 export root="${ROOTFS}0$n"
2389 # initial tazpkg setup in empty rootfs
2390 tazpkg --root=$root >/dev/null 2>&1
2392 newline
2393 boldify "Building $flavor rootfs..."
2395 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2396 cp "$TOP_DIR/$flavor.flavor" .
2398 if [ ! -s "$flavor.flavor" ]; then
2399 # We may have it in $FLAVORS_REPOSITORY
2400 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2401 tazlito pack-flavor $flavor
2402 else
2403 download $flavor.flavor
2404 fi
2405 fi
2407 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2408 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2409 cp $flavor.pkglist $DISTRO/list-packages0$n
2410 status
2412 strip_versions "$DISTRO/list-packages0$n"
2414 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2416 rm -rf ${ROOTFS}0$n/boot
2418 cd $DISTRO
2419 if [ -s $flavor.rootfs ]; then
2420 _n 'Adding %s rootfs extra files...' "$flavor"
2421 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2422 fi
2424 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2425 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2426 status
2428 rm -f $flavor.flavor install-list
2429 mergefs ${ROOTFS}0$n $last
2430 last=${ROOTFS}0$n
2431 done <<EOT
2432 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2433 EOT
2434 #'
2435 i=$(($n+1))
2436 while [ $n -gt 0 ]; do
2437 mv ${ROOTFS}0$n ${ROOTFS}$i
2438 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2439 gen_initramfs ${ROOTFS}$i
2440 n=$(($n-1))
2441 i=$(($i-1))
2442 export LZMA_HISTORY_BITS=26
2443 done
2444 mv $ROOTFS ${ROOTFS}$i
2445 gen_initramfs ${ROOTFS}$i
2446 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2447 else
2448 # Initramfs and ISO image stuff.
2449 gen_initramfs $ROOTFS
2450 fi
2451 gen_livecd_isolinux
2452 distro_stats
2453 cleanup
2454 ;;
2457 clean-distro)
2458 # Remove old distro tree.
2460 check_root
2461 title 'Cleaning: %s' "$DISTRO"
2462 if [ -d "$DISTRO" ] ; then
2463 if [ -d "$ROOTFS" ] ; then
2464 action 'Removing the rootfs...'
2465 rm -f $DISTRO/$INITRAMFS
2466 rm -rf $ROOTFS
2467 status
2468 fi
2469 if [ -d "$ROOTCD" ] ; then
2470 action 'Removing the rootcd...'
2471 rm -rf $ROOTCD
2472 status
2473 fi
2474 action 'Removing eventual ISO image...'
2475 rm -f $DISTRO/$ISO_NAME.iso
2476 rm -f $DISTRO/$ISO_NAME.md5
2477 status
2478 fi
2479 footer
2480 ;;
2483 check-distro)
2484 # Check for a few LiveCD needed files not installed by packages.
2486 # TODO: Remove this function.
2487 # First two files are maintained by tazpkg while it runs on rootfs,
2488 # while last one file should be maintained by tazlito itself.
2489 check_rootfs
2490 title 'Checking distro: %s' "$ROOTFS"
2491 # SliTaz release info.
2492 rel='/etc/slitaz-release'
2493 if [ ! -f "$ROOTFS$rel" ]; then
2494 _ 'Missing release info: %s' "$rel"
2495 else
2496 action 'Release : %s' "$(cat $ROOTFS$rel)"
2497 status
2498 fi
2499 # Tazpkg mirror.
2500 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2501 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2502 todomsg
2503 else
2504 action 'Mirror configuration exists...'
2505 status
2506 fi
2507 # Isolinux msg
2508 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2509 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2510 todomsg
2511 else
2512 action 'Isolinux message seems good...'
2513 status
2514 fi
2515 footer
2516 ;;
2519 writeiso)
2520 # Writefs to ISO image including /home unlike gen-distro we don't use
2521 # packages to generate a rootfs, we build a compressed rootfs with all
2522 # the current filesystem similar to 'tazusb writefs'.
2524 DISTRO='/home/slitaz/distro'
2525 ROOTCD="$DISTRO/rootcd"
2526 COMPRESSION="${2:-none}"
2527 ISO_NAME="${3:-slitaz}"
2528 check_root
2529 # Start info
2530 title 'Write filesystem to ISO'
2531 longline "The command writeiso will write the current filesystem into a \
2532 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2533 newline
2534 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2536 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2537 # Save some space
2538 rm -rf /var/cache/tazpkg/*
2539 rm -f /var/lib/tazpkg/*.bak
2540 rm -rf $DISTRO
2542 # Optionally remove sound card selection and screen resolution.
2543 if [ -z $LaunchedByTazpanel ]; then
2544 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2545 case $anser in
2546 y)
2547 action 'Removing current sound card and screen configurations...'
2548 rm -f /var/lib/sound-card-driver
2549 rm -f /var/lib/alsa/asound.state
2550 rm -f /etc/X11/xorg.conf ;;
2551 *)
2552 action 'Keeping current sound card and screen configurations...' ;;
2553 esac
2554 status
2555 newline
2557 # Optionally remove i18n settings
2558 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2559 case $anser in
2560 y)
2561 action 'Removing current locale/keymap settings...'
2562 newline > /etc/locale.conf
2563 newline > /etc/keymap.conf ;;
2564 *)
2565 action 'Keeping current locale/keymap settings...' ;;
2566 esac
2567 status
2568 fi
2570 # Clean-up files by default
2571 newline > /etc/udev/rules.d/70-persistent-net.rules
2572 newline > /etc/udev/rules.d/70-persistant-cd.rules
2574 # Create list of files including default user files since it is defined in /etc/passwd
2575 # and some new users might have been added.
2576 cd /
2577 echo 'init' > /tmp/list
2578 for dir in bin etc sbin var dev lib root usr home opt; do
2579 [ -d $dir ] && find $dir
2580 done >> /tmp/list
2582 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2583 [ -d $dir ] && echo $dir
2584 done >> /tmp/list
2586 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2588 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2589 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2590 #fi
2591 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2592 touch /var/log/wtmp
2594 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2595 sed -i "/var\/log\/$removelog/d" /tmp/list
2596 done
2598 # Generate initramfs with specified compression and display rootfs
2599 # size in realtime.
2600 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2602 write_initramfs &
2603 sleep 2
2604 cd - > /dev/null
2605 echo -en "\nFilesystem size:"
2606 while [ ! -f /tmp/rootfs ]; do
2607 sleep 1
2608 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2609 done
2610 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2611 echo -e "\n"
2612 rm -f /tmp/rootfs
2614 # Move freshly generated rootfs to the cdrom.
2615 mkdir -p $ROOTCD/boot
2616 mv -f /$INITRAMFS $ROOTCD/boot
2617 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2619 # Now we need the kernel and isolinux files.
2620 copy_from_cd() {
2621 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2622 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2623 unmeta_boot $ROOTCD
2624 umount /media/cdrom
2627 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2628 copy_from_cd;
2629 elif mount | grep /media/cdrom; then
2630 copy_from_cd;
2631 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2632 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2633 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2634 else
2635 touch /tmp/.write-iso-error
2636 longline "When SliTaz is running in RAM the kernel and bootloader \
2637 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
2638 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
2639 echo -en "----\nENTER to continue..."; read i
2640 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2641 copy_from_cd
2642 fi
2644 # Generate the iso image.
2645 touch /tmp/.write-iso
2646 newline
2647 cd $DISTRO
2648 create_iso $ISO_NAME.iso $ROOTCD
2649 action 'Creating the ISO md5sum...'
2650 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2651 status
2653 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2654 rm -f /tmp/.write-iso
2656 if [ -z $LaunchedByTazpanel ]; then
2657 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2658 case $anser in
2659 y)
2660 umount /dev/cdrom 2>/dev/null
2661 eject
2662 echo -n "Please insert a blank CD-ROM and press ENTER..."
2663 read i && sleep 2
2664 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2665 echo -en "----\nENTER to continue..."; read i ;;
2666 *)
2667 exit 0 ;;
2668 esac
2669 fi
2670 ;;
2673 burn-iso)
2674 # Guess CD-ROM device, ask user and burn the ISO.
2676 check_root
2677 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2678 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2679 # We can specify an alternative ISO from the cmdline.
2680 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2681 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2683 title 'Tazlito burn ISO'
2684 echo "CD-ROM device : /dev/$DRIVE_NAME"
2685 echo "Drive speed : $DRIVE_SPEED"
2686 echo "ISO image : $iso"
2687 footer
2689 case $(yesorno 'Burn ISO image?' 'n') in
2690 y)
2691 title 'Starting Wodim to burn the ISO...'
2692 sleep 2
2693 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2694 footer 'ISO image is burned to CD-ROM.'
2695 ;;
2696 *)
2697 die 'Exiting. No ISO burned.'
2698 ;;
2699 esac
2700 ;;
2703 merge)
2704 # Merge multiple rootfs into one iso.
2706 if [ -z "$2" ]; then
2707 cat <<EOT
2708 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2710 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2711 i.e: rootfsN is a subset of rootfsN-1
2712 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2713 The boot loader will select the rootfs according to the RAM size detected.
2715 Example:
2716 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
2718 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
2719 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
2721 EOT
2722 exit 2
2723 fi
2725 shift # skip merge
2726 append="$1 slitaz1"
2727 shift # skip size1
2728 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
2730 ISO=$1.merged
2732 # Extract filesystems
2733 action 'Mounting %s' "$1"
2734 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
2735 status || cleanup_merge
2737 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2738 make_bzImage_hardlink $TMP_DIR/iso/boot
2739 umount -d $TMP_DIR/mnt
2740 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
2741 _ '%s is already a merged iso. Aborting.' "$1"
2742 cleanup_merge
2743 fi
2744 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
2745 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
2746 if [ ! -f /boot/isolinux/ifmem.c32 -a
2747 ! -f /boot/isolinux/c32box.c32 ]; then
2748 cat <<EOT
2749 No file /boot/isolinux/ifmem.c32
2750 Please install syslinux package !
2751 EOT
2752 rm -rf $TMP_DIR
2753 exit 1
2754 fi
2755 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
2756 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
2757 fi
2759 action 'Extracting %s' 'iso/rootfs.gz'
2760 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
2761 [ -d $TMP_DIR/rootfs1/etc ]
2762 status || cleanup_merge
2764 n=1
2765 while [ -n "$2" ]; do
2766 shift # skip rootfs N-1
2767 p=$n
2768 n=$(($n + 1))
2769 append="$append $1 slitaz$n"
2770 shift # skip size N
2771 mkdir -p $TMP_DIR/rootfs$n
2773 action 'Extracting %s' "$1"
2774 extract_rootfs $1 $TMP_DIR/rootfs$n &&
2775 [ -d "$TMP_DIR/rootfs$n/etc" ]
2776 status || cleanup_merge
2778 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
2779 action 'Creating %s' "rootfs$p.gz"
2780 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
2781 status
2782 done
2783 action 'Creating %s' "rootfs$n.gz"
2784 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
2785 status
2786 rm -f $TMP_DIR/iso/boot/rootfs.gz
2787 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
2788 create_iso $ISO $TMP_DIR/iso
2789 rm -rf $TMP_DIR
2790 ;;
2793 repack)
2794 # Repack an iso with maximum lzma compression ratio.
2796 ISO=$2
2797 mkdir -p $TMP_DIR/mnt
2799 # Extract filesystems
2800 action 'Mounting %s' "$ISO"
2801 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
2802 status || cleanup_merge
2804 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2805 umount -d $TMP_DIR/mnt
2807 for i in $TMP_DIR/iso/boot/rootfs* ; do
2808 action 'Repacking %s' "$(basename $i)"
2809 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
2810 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
2811 align_to_32bits $i
2812 status
2813 done
2815 create_iso $ISO $TMP_DIR/iso
2816 rm -rf $TMP_DIR
2817 ;;
2820 build-loram)
2821 # Build a Live CD for low RAM systems.
2823 ISO="$2"
2824 OUTPUT="$3"
2825 [ -z "$3" ] && \
2826 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
2827 mkdir -p "$TMP_DIR/iso"
2828 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
2829 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
2830 if ! check_iso_for_loram ; then
2831 umount -d "$TMP_DIR/iso"
2832 die "$ISO is not a valid SliTaz live CD. Abort."
2833 fi
2834 case "$4" in
2835 cdrom) build_loram_cdrom ;;
2836 http) build_loram_http ;;
2837 *) build_loram_ram ;;
2838 esac
2839 umount $TMP_DIR/iso # no -d: needs /proc
2840 losetup -d $loopdev
2841 rm -rf $TMP_DIR
2842 ;;
2845 emu-iso)
2846 # Emulate an ISO image with Qemu.
2847 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2848 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
2849 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
2850 echo -e "\nStarting Qemu emulator:\n"
2851 echo -e "qemu $QEMU_OPTS $iso\n"
2852 qemu $QEMU_OPTS $iso
2853 ;;
2856 deduplicate)
2857 # Deduplicate files in a tree
2858 shift
2859 deduplicate "$@"
2860 ;;
2863 usage|*)
2864 # Print usage also for all unknown commands.
2865 usage
2866 ;;
2867 esac
2869 exit 0