tazlito view tazlito @ rev 464

tazlito: typo
author Pascal Bellard <pascal.bellard@slitaz.org>
date Fri Sep 29 15:56:39 2017 +0200 (2017-09-29)
parents 179f3271b0d5
children 837fc9aaff10
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 ||
853 { [ $(od -N 1 -An $1) -eq 135 ] && unlzma < $1; } || cat $1
854 }
857 # Install a missing package
859 install_package() {
860 if [ -z "$2" ]; then
861 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
862 else
863 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
864 fi
865 case "$answer" in
866 y)
867 # We don't want package on host cache.
868 action 'Getting and installing package: %s' "$1"
869 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
870 status ;;
871 *)
872 return 1 ;;
873 esac
874 }
877 # Check iso for loram transformation
879 check_iso_for_loram() {
880 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
881 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
882 }
885 # Build initial rootfs for loram ISO ram/cdrom/http
887 build_initfs() {
888 urliso="mirror.switch.ch/ftp/mirror/slitaz \
889 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
890 mirror3.slitaz.org mirror.slitaz.org"
891 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
892 [ -z "$version" ] && die "Can't find the kernel version." \
893 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
895 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
896 need_lib=false
897 for i in bin dev run mnt proc tmp sys lib/modules; do
898 mkdir -p $TMP_DIR/initfs/$i
899 done
900 ln -s bin $TMP_DIR/initfs/sbin
901 ln -s . $TMP_DIR/initfs/usr
902 for aufs in aufs overlayfs; do
903 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
904 install_package $aufs $version && break
905 done || return 1
906 [ -s /init ] || install_package slitaz-boot-files
907 cp /init $TMP_DIR/initfs/
908 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
909 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
910 $TMP_DIR/initfs/lib/modules 2>/dev/null
911 cp -a /dev/tty0 /dev/fd0 $TMP_DIR/initfs/dev 2>/dev/null
912 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
913 $TMP_DIR/initfs/lib/modules
914 if [ "$1" == 'cdrom' ]; then
915 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
916 else
917 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
918 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
919 install_package linux-squashfs $version || return 1
920 done
921 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
922 $TMP_DIR/initfs/lib/modules
923 ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
924 cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
925 fi
926 for i in $(ls /dev/[hs]d[a-f]*); do
927 cp -a $i $TMP_DIR/initfs/dev
928 done
929 if [ "$1" == 'http' ]; then
930 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
931 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
932 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
933 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
934 cp -a /dev/fuse $TMP_DIR/initfs/dev
935 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
936 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
937 else
938 need_lib=true
939 fi
940 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
941 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
942 else
943 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
944 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
945 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
946 cp -a /lib/librt* $TMP_DIR/initfs/lib
947 cp -a /lib/libdl* $TMP_DIR/initfs/lib
948 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
949 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
950 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
951 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
952 need_lib=true
953 fi
954 cd $TMP_DIR/fs
955 echo 'Getting slitaz-release & ethernet modules...'
956 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
957 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
958 [ -s rootfs* ] || continue
959 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
960 rm -f rootfs*
961 done 2>&1 > /dev/null
962 cd - > /dev/null
963 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
964 find $TMP_DIR/fs/lib/modules/*/kernel/drivers/net/ethernet \
965 -type f -name '*.ko*' | while read mod; do
966 f=$TMP_DIR/initfs/lib/modules/$(basename $mod | sed s/..z$//)
967 uncompress $mod > $f
968 grep -q alias=pci: $f || rm -f $f
969 done
970 for i in $TMP_DIR/initfs/lib/modules/*.ko ; do
971 f=$(basename $i)..z
972 grep -q $f:$ $TMP_DIR/fs/lib/modules/*/modules.dep && continue
973 deps="$(grep $f: $TMP_DIR/fs/lib/modules/*/modules.dep | sed 's/.*: //')"
974 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > $TMP_DIR/initfs/lib/modules/$(basename $i .ko).dep
975 for j in $deps; do
976 mod=$(ls $TMP_DIR/fs/lib/modules/*/$j)
977 uncompress $mod > $TMP_DIR/initfs/lib/modules/$(basename $j | sed s/..z$//)
978 done
979 done
980 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"
981 _n 'List of URLs to insert: '
982 read -t 30 urliso2
983 urliso="$urliso2 $urliso"
984 fi
985 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
986 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
987 sed -i 's/LD_T.*ot/newline/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
988 else
989 cp /bin/busybox $TMP_DIR/initfs/bin
990 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
991 cp /sbin/insmod $TMP_DIR/initfs/bin
992 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
993 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
994 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
995 fi
996 need_lib=true
997 fi
998 for i in $($TMP_DIR/initfs/bin/busybox | awk \
999 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
1000 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1001 done
1002 for i in /dev/console /dev/loop* /dev/null /dev/tty /dev/zero \
1003 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1004 cp -a $i $TMP_DIR/initfs/dev
1005 done
1006 $need_lib && for i in /lib/ld-* /lib/lib[cm].so* /lib/lib[cm]-* ; do
1007 cp -a $i $TMP_DIR/initfs/lib
1008 done
1009 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1010 #!/bin/sh
1012 getarg() {
1013 grep -q " \$1=" /proc/cmdline || return 1
1014 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1015 return 0
1018 copy_rootfs() {
1019 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1020 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1021 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1022 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1023 path=/mnt/
1024 return 0
1025 else
1026 rm -f /mnt/rootfs*
1027 return 1
1028 fi
1031 echo "Switching / to tmpfs..."
1032 mount -t proc proc /proc
1033 size="\$(grep rootfssize= < /proc/cmdline | \\
1034 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1035 [ -n "\$size" ] || size="-o size=90%"
1037 mount -t sysfs sysfs /sys
1038 for i in /lib/modules/*.ko ; do
1039 echo -en "Probe \$i \\r"
1040 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1041 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1042 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1043 insmod /lib/modules/\$k.ko 2> /dev/null
1044 done
1045 echo "Loading \$i"
1046 insmod \$i 2> /dev/null
1047 break
1048 done
1049 done
1050 umount /sys
1051 while read var default; do
1052 eval \$var=\$default
1053 getarg \$var \$var
1054 done <<EOT
1055 eth eth0
1056 dns 208.67.222.222,208.67.220.220
1057 netmask 255.255.255.0
1058 gw
1059 ip
1060 EOT
1061 grep -q \$eth /proc/net/dev || sh
1062 if [ -n "\$ip" ]; then
1063 ifconfig \$eth \$ip netmask \$netmask up
1064 route add default gateway \$gw
1065 for i in \$(echo \$dns | sed 's/,/ /g'); do
1066 echo "nameserver \$i" >> /etc/resolv.conf
1067 done
1068 else
1069 udhcpc -f -q -s /lib/udhcpc -i \$eth
1070 fi
1071 for i in $urliso ; do
1072 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1073 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"
1074 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1075 done
1076 getarg urliso URLISO
1077 DIR=fs
1078 if getarg loram DIR; then
1079 DEVICE=\${DIR%,*}
1080 DIR=/\${DIR#*,}
1081 fi
1082 mount -t tmpfs \$size tmpfs /mnt
1083 path2=/mnt/.httpfs/
1084 path=/mnt/.cdrom/
1085 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1086 while [ ! -d \$path/boot ]; do
1087 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1088 httpfs \$i \$path2 && echo \$i && break
1089 done
1090 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1091 done
1093 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1094 umount /proc
1095 branch=:/mnt/.cdrom/\$DIR
1096 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1097 branch=
1098 lp=1
1099 insmod /lib/modules/squashfs.ko 2> /dev/null
1100 for i in \${path}boot/rootfs?.* ; do
1101 fs=\${i#*root}
1102 branch=\$branch:/mnt/.\$fs
1103 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1104 losetup -o 124 /dev/loop\$lp \$i
1105 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1106 lp=\$((\$lp+1))
1107 done
1108 fi
1109 mkdir -p /mnt/.rw/mnt/.httpfs
1110 while read type opt; do
1111 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1112 done <<EOT
1113 aufs br=/mnt/.rw\$branch
1114 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1115 EOT
1116 rm -rf /lib/modules
1117 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1118 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1119 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1120 EOTEOT
1121 chmod +x $TMP_DIR/initfs/init
1122 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1123 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1124 rm -f $i
1125 dogzip ${i%.gz}
1126 done 2>/dev/null
1127 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1128 lzma e $TMP_DIR/initfs.gz -si
1129 lzma_set_size $TMP_DIR/initfs.gz
1130 rm -rf $TMP_DIR/initfs
1131 align_to_32bits $TMP_DIR/initfs.gz
1132 return 0
1136 # Move each initramfs to squashfs
1138 build_loram_rootfs() {
1139 rootfs_sizes=""
1140 for i in $TMP_DIR/iso/boot/rootfs*; do
1141 mkdir -p $TMP_DIR/fs
1142 cd $TMP_DIR/fs
1143 uncompress $i | cpio -idm
1144 deduplicate
1145 cd - > /dev/null
1146 rootfs=$TMP_DIR/$(basename $i)
1147 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp xz -Xbcj x86
1148 cd $TMP_DIR
1149 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1150 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1151 rm -f $rootfs
1152 mv $rootfs.cpio $rootfs
1153 cd - > /dev/null
1154 rm -rf $TMP_DIR/fs
1155 done
1159 # Move meta boot configuration files to basic configuration files
1160 # because meta loram flavor is useless when rootfs is not loaded in RAM
1162 unmeta_boot() {
1163 local root=${1:-$TMP_DIR/loramiso}
1164 if [ -f $root/boot/isolinux/noram.cfg ]; then
1165 # We keep enough information to do unloram...
1166 [ -s $root/boot/isolinux/common.cfg ] &&
1167 sed -i 's/label slitaz/label orgslitaz/' \
1168 $root/boot/isolinux/common.cfg
1169 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1170 shift
1171 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1172 $root/boot/isolinux/isolinux.cfg
1173 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1174 sed -i "s/label $3\$/label slitaz/;s|=\(.*\)/rootfs\(.*\).gz |=\1/rootfs.gz |" \
1175 $root/boot/isolinux/*.cfg
1176 fi
1180 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1181 # These squashfs may be loaded in RAM at boot time.
1182 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1183 # Meta flavors are converted to normal flavors.
1185 build_loram_cdrom() {
1186 build_initfs cdrom || return 1
1187 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1188 mkdir $TMP_DIR/loramiso/fs
1189 cd $TMP_DIR/loramiso/fs
1190 for i in $( ls ../boot/root* | sort -r ) ; do
1191 uncompress $i | cpio -idmu
1192 rm -f $i
1193 done
1194 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1195 cd - >/dev/null
1196 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1197 unmeta_boot
1198 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1199 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1200 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1201 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1202 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1203 create_iso $OUTPUT $TMP_DIR/loramiso
1207 # Create http bootstrap to load and remove loram_cdrom
1208 # Meta flavors are converted to normal flavors.
1210 build_loram_http() {
1211 build_initfs http || return 1
1212 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1213 rm -f $TMP_DIR/loramiso/boot/rootfs*
1214 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1215 unmeta_boot
1216 create_iso $OUTPUT $TMP_DIR/loramiso
1220 # Update meta flavor selection sizes.
1221 # Reduce sizes with rootfs gains.
1223 update_metaiso_sizes() {
1224 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1225 do
1226 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1227 local sizes="$rootfs_sizes"
1228 local new
1229 set -- $append
1230 shift
1231 [ "$1" == "ifmem" ] && shift
1232 new=""
1233 while [ -n "$2" ]; do
1234 local s
1235 case "$1" in
1236 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1237 *M) s=$(( ${1%M} * 1024 ));;
1238 *) s=${1%K};;
1239 esac
1240 sizes=${sizes#* }
1241 for i in $sizes ; do
1242 s=$(( $s - $i ))
1243 done
1244 new="$new $s $2"
1245 shift 2
1246 done
1247 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1248 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1249 sed -i 's|\(initrd=\)\(.[^/]*\)\(/rootfs.\.gz\)|\1\2/rootfs.gz,\3|' $cfg
1250 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1251 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1252 done
1256 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1257 # Meta flavor selection sizes are updated.
1259 build_loram_ram() {
1260 build_initfs ram || return 1
1261 build_loram_rootfs
1262 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1263 make_bzImage_hardlink $TMP_DIR/loramiso/boot
1264 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1265 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1266 update_metaiso_sizes
1267 create_iso $OUTPUT $TMP_DIR/loramiso
1271 # Remove files installed by packages
1273 find_flavor_rootfs() {
1274 for i in $1/etc/tazlito/*.extract; do
1275 [ -e $i ] || continue
1276 chroot $1 /bin/sh ${i#$1}
1277 done
1279 # Clean hardlinks and files patched by genisofs in /boot
1280 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1281 rm -f $1/boot/$i*
1282 done
1284 # Clean files generated in post_install
1285 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1286 $1/dev/core $1/dev/fd $1/dev/std*
1288 # Verify md5
1289 cat $1$INSTALLED/*/md5sum | \
1290 while read md5 file; do
1291 [ -e "$1$file" ] || continue
1292 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1293 rm -f "$1$file"
1294 done
1296 # Check configuration files
1297 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1298 [ -e $i ] || continue
1299 mkdir /tmp/volatile$$
1300 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1301 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1302 while read file ; do
1303 [ -e "$1/$file" ] || continue
1304 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1305 done
1306 rm -rf /tmp/volatile$$
1307 done
1309 # Remove other files blindly
1310 for i in $1$INSTALLED/*/files.list; do
1311 for file in $(cat "$i"); do
1312 [ "$1$file" -nt "$i" ] && continue
1313 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1314 [ -d "$1$file" ] || rm -f "$1$file"
1315 done
1316 done
1318 # Remove tazpkg files and tmp files
1319 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1320 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1321 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1322 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1323 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1325 # Cleanup directory tree
1326 cd $1
1327 find * -type d | sort -r | while read dir; do
1328 rmdir "$dir" 2>/dev/null
1329 done
1330 cd - > /dev/null
1334 # Get byte(s) from a binary file
1336 get() {
1337 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null
1341 # Get cpio flavor info from the ISO image
1343 flavordata() {
1344 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1345 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1349 # Restore undigest mirrors
1351 restore_mirrors() {
1352 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1353 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1355 action 'Restoring mirrors...'
1356 if [ -d "$undigest.bak" ]; then
1357 [ -d "$undigest" ] && rm -r "$undigest"
1358 mv "$undigest.bak" "$undigest"
1359 fi
1360 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1361 :; status
1365 # Setup undigest mirrors
1367 setup_mirrors() {
1368 # Setup mirrors in plain system or in chroot (with variable root=)
1369 local mirrorlist="$1" fresh repacked
1370 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1372 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1373 restore_mirrors
1375 _ 'Setting up mirrors for %s...' "$root/"
1376 # Backing up current undigest mirrors and priority
1377 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1378 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1379 rm -rf '/var/www/tazlito/'
1380 mkdir -p '/var/www/tazlito/'
1382 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1383 fresh='/home/slitaz/packages'
1384 if [ -d "$fresh" ]; then
1385 # Setup first undigest mirror
1386 mkdir -p "$undigest/fresh"
1387 echo "$fresh" > "$undigest/fresh/mirror"
1388 echo 'fresh' >> "$priority"
1389 # Rebuild mirror DB if needed
1390 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1391 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1392 tazpkg mkdb "$fresh" --forced --root=''
1393 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1394 fi
1396 # Repacked packages: high priority
1397 repacked="$PACKAGES_REPOSITORY"
1398 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1399 # According to Tazlito setup file (tazlito.conf):
1400 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1401 # or
1402 # WORK_DIR="/home/slitaz"
1403 # and
1404 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1405 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1407 # Setup second undigest mirror
1408 mkdir -p "$undigest/repacked"
1409 echo "$repacked" > "$undigest/repacked/mirror"
1410 echo 'repacked' >> "$priority"
1411 # Rebuild mirror DB if needed
1412 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1413 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1414 tazpkg mkdb "$repacked" --forced --root=''
1415 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1416 fi
1418 # All repositories listed in mirrors list: normal priority
1419 [ -e "$mirrorlist" ] && \
1420 while read mirror; do
1421 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1422 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1423 mkdir -p "$undigest/$mirrorid"
1424 echo "$mirror" > "$undigest/$mirrorid/mirror"
1425 echo "$mirrorid" >> "$priority"
1426 done < "$mirrorlist"
1428 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1430 # Show list of mirrors
1431 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1432 function show(num, name, url) {
1433 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1436 num++;
1437 "cat " db "/undigest/" $0 "/mirror" | getline url;
1438 show(num, $0, url);
1440 END {
1441 num++;
1442 "cat " db "/mirror" | getline url;
1443 show(num, "main", url);
1444 }' "$priority"
1446 tazpkg recharge --quiet >/dev/null
1450 # Get list of 'packages.info' lists using priority
1452 pi_lists() {
1453 local pi
1454 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1455 local priority="$root$LOCALSTATE/priority"
1456 local undigest="$root$LOCALSTATE/undigest"
1459 [ -s "$priority" ] && cat "$priority"
1460 echo 'main'
1461 [ -d "$undigest" ] && ls "$undigest"
1462 } | awk -vun="$undigest/" '
1464 if (arr[$0] != 1) {
1465 arr[$0] = 1;
1466 print un $0 "/packages.info";
1468 }' | sed 's|/undigest/main||' | \
1469 while read pi; do
1470 [ -e "$pi" ] && echo "$pi"
1471 done
1475 # Strip versions from packages list
1477 strip_versions() {
1478 if [ -n "$stripped" ]; then
1479 action 'Consider list %s already stripped' "$(basename "$1")"
1480 status
1481 return 0
1482 fi
1483 action 'Strip versions from list %s...' "$(basename "$1")"
1484 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1485 [ -f "$in_list" ] || die "List '$in_list' not found."
1487 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1488 awk '
1490 if (FILENAME ~ "packages.info") {
1491 # Collect package names
1492 FS = "\t"; pkg[$1] = 1;
1493 } else {
1494 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1495 while (NF > 1 && ! pkg[$0])
1496 NF --;
1497 printf "%s\n", $0;
1499 }' $(pi_lists) "$in_list" > "$tmp_list"
1501 cat "$tmp_list" > "$in_list"
1502 rm "$tmp_list"
1503 status
1507 # Display list of unknown packages (informative)
1509 display_unknown() {
1510 [ -s "$1" ] || return
1511 echo "Unknown packages:" >&2
1512 cat "$1" >&2
1513 rm "$1"
1517 # Display warnings about critical packages absent (informative)
1519 display_warn() {
1520 [ -s "$1" ] || return
1521 echo "Absent critical packages:" >&2
1522 cat "$1" >&2
1523 rm "$1"
1524 echo "Probably ISO image will be unusable."
1528 # Install packages to rootfs
1530 install_list_to_rootfs() {
1531 local list="$1" rootfs="$2" pkg i ii
1532 local undigest="$rootfs/var/lib/tazpkg/undigest"
1534 # initial tazpkg setup in empty rootfs
1535 tazpkg --root=$rootfs >/dev/null 2>&1
1536 # pass current 'mirror' to the rootfs
1537 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
1538 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
1539 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
1540 # link rootfs packages cache to the regular packages cache
1541 rm -r "$rootfs/var/cache/tazpkg"
1542 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1544 setup_mirrors mirrors
1546 # Just in case if flavor not contains "tazlito" package
1547 mkdir -p "$rootfs/etc/tazlito"
1549 newline
1551 # Choose detailed log with --detailed
1552 if [ -n "$detailed" ]; then
1553 while read pkg; do
1554 separator '-'
1555 echo $pkg
1556 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
1557 done < $list
1558 separator '='
1559 else
1560 while read pkg; do
1561 action 'Installing package: %s' "$pkg"
1562 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1563 status
1564 done < $list
1565 fi
1566 newline
1568 restore_mirrors
1569 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1570 for i in fresh repacked; do
1571 ii="$undigest/$i"
1572 [ -d "$ii" ] && rm -rf "$ii"
1573 ii="$rootfs/var/lib/tazpkg/priority"
1574 if [ -f "$ii" ]; then
1575 sed -i "/$i/d" "$ii"
1576 [ -s "$ii" ] || rm "$ii"
1577 fi
1578 done
1579 [ -d "$undigest" ] && \
1580 for i in $(find "$undigest" -type f); do
1581 # Remove all undigest PKGDB files but 'mirror'
1582 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1583 done
1584 [ -d "$undigest" ] && \
1585 rmdir --ignore-fail-on-non-empty "$undigest"
1587 # Un-link packages cache
1588 rm "$rootfs/var/cache/tazpkg"
1590 # Clean /var/lib/tazpkg
1591 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1597 ####################
1598 # Tazlito commands #
1599 ####################
1601 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1602 case "$0" in
1603 *reduplicate)
1604 find ${@:-.} ! -type d -links +1 \
1605 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1606 exit 0 ;;
1607 *deduplicate)
1608 deduplicate "$@"
1609 exit 0 ;;
1610 esac
1613 case "$COMMAND" in
1614 stats)
1615 # Tazlito general statistics from the config file.
1617 title 'Tazlito statistics'
1618 optlist "\
1619 Config file : $CONFIG_FILE
1620 ISO name : $ISO_NAME.iso
1621 Volume name : $VOLUM_NAME
1622 Prepared : $PREPARED
1623 Packages repository : $PACKAGES_REPOSITORY
1624 Distro directory : $DISTRO
1625 Additional files : $ADDFILES
1626 " | sed '/: $/d'
1627 footer
1628 ;;
1631 list-addfiles)
1632 # Simple list of additional files in the rootfs
1633 newline
1634 if [ -d "$ADDFILES/rootfs" ]; then
1635 cd $ADDFILES
1636 find rootfs -type f
1637 else
1638 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1639 fi
1640 newline
1641 ;;
1644 gen-config)
1645 # Generate a new config file in the current dir or the specified
1646 # directory by $2.
1648 if [ -n "$2" ]; then
1649 mkdir -p "$2" && cd "$2"
1650 fi
1652 newline
1653 action 'Generating empty tazlito.conf...'
1654 empty_config_file
1655 status
1657 separator
1658 if [ -f 'tazlito.conf' ] ; then
1659 _ 'Configuration file is ready to edit.'
1660 _ 'File location: %s' "$(pwd)/tazlito.conf"
1661 newline
1662 fi
1663 ;;
1666 configure)
1667 # Configure a tazlito.conf config file. Start by getting
1668 # a empty config file and sed it.
1670 if [ -f 'tazlito.conf' ]; then
1671 rm tazlito.conf
1672 else
1673 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1674 'or in the same directory of the file you want to configure.'
1675 cd /etc
1676 fi
1678 empty_config_file
1680 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1682 # ISO name.
1683 echo -n "ISO name : " ; read answer
1684 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1685 # Volume name.
1686 echo -n "Volume name : " ; read answer
1687 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1688 # Packages repository.
1689 echo -n "Packages repository : " ; read answer
1690 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1691 # Distro path.
1692 echo -n "Distro path : " ; read answer
1693 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1694 footer "Config file is ready to use."
1695 echo 'You can now extract an ISO or generate a distro.'
1696 newline
1697 ;;
1700 gen-iso)
1701 # Simply generate a new iso.
1703 check_root
1704 verify_rootcd
1705 gen_livecd_isolinux
1706 distro_stats
1707 ;;
1710 gen-initiso)
1711 # Simply generate a new initramfs with a new iso.
1713 check_root
1714 verify_rootcd
1715 gen_initramfs "$ROOTFS"
1716 gen_livecd_isolinux
1717 distro_stats
1718 ;;
1721 extract-distro)
1722 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1724 check_root
1725 ISO_IMAGE="$2"
1726 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1727 'Example:\n tazlito image.iso /path/target'
1729 # Set the distro path by checking for $3 on cmdline.
1730 TARGET="${3:-$DISTRO}"
1732 # Exit if existing distro is found.
1733 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1734 'Please clean the distro tree or change directory path.'
1736 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
1738 # Start to mount the ISO.
1739 action 'Mounting ISO image...'
1740 mkdir -p "$TMP_DIR"
1741 # Get ISO file size.
1742 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
1743 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
1744 sleep 2
1745 # Prepare target dir, copy the kernel and the rootfs.
1746 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
1747 status
1749 action 'Copying the Linux kernel...'
1750 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
1751 make_bzImage_hardlink "$TARGET/rootcd/boot"
1752 else
1753 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
1754 fi
1755 status
1757 for i in $(ls $TMP_DIR); do
1758 [ "$i" == 'boot' ] && continue
1759 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
1760 done
1762 for loader in isolinux syslinux extlinux grub; do
1763 [ -d "$TMP_DIR/boot/$loader" ] || continue
1764 action 'Copying %s files...' "$loader"
1765 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
1766 status
1767 done
1769 action 'Copying the rootfs...'
1770 cp $TMP_DIR/boot/rootfs.?z "$TARGET/rootcd/boot"
1771 status
1773 # Extract initramfs.
1774 cd "$TARGET/rootfs"
1775 action 'Extracting the rootfs...'
1776 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
1777 # unpack /usr
1778 for i in etc/tazlito/*.extract; do
1779 [ -f "$i" ] && . $i ../rootcd
1780 done
1781 # Umount and remove temp directory and cd to $TARGET to get stats.
1782 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
1783 cd ..
1784 status
1786 newline
1787 separator
1788 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
1789 echo "Distro tree : $(pwd)"
1790 echo "Rootfs size : $(du -sh rootfs)"
1791 echo "Rootcd size : $(du -sh rootcd)"
1792 footer
1793 ;;
1796 list-flavors)
1797 # Show available flavors.
1798 list='/etc/tazlito/flavors.list'
1799 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
1800 title 'List of flavors'
1801 cat $list
1802 footer
1803 ;;
1806 show-flavor)
1807 # Show flavor description.
1808 set -e
1809 flavor=${2%.flavor}
1810 flv_dir="$(extract_flavor "$flavor")"
1811 desc="$flv_dir/$flavor.desc"
1812 if [ -n "$brief" ]; then
1813 if [ -z "$noheader" ]; then
1814 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
1815 separator
1816 fi
1817 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
1818 "$(field ISO "$desc")" \
1819 "$(field Rootfs "$desc")" \
1820 "$(field Description "$desc")"
1821 else
1822 separator
1823 cat "$desc"
1824 fi
1825 cleanup
1826 ;;
1829 gen-liveflavor)
1830 # Generate a new flavor from the live system.
1831 FLAVOR=${2%.flavor}
1832 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1834 case "$FLAVOR" in
1835 -?|-h*|--help)
1836 cat <<EOT
1837 SliTaz Live Tool - Version: $VERSION
1839 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
1841 $(boldify '<flavor-patch-file> format:')
1842 $(optlist "\
1843 code data
1844 + package to add
1845 - package to remove
1846 ! non-free package to add
1847 ? display message
1848 @ flavor description
1849 ")
1851 $(boldify 'Example:')
1852 $(optlist "\
1853 @ Developer tools for SliTaz maintainers
1854 + slitaz-toolchain
1855 + mercurial
1856 ")
1857 EOT
1858 exit 1
1859 ;;
1860 esac
1861 mv /etc/tazlito/distro-packages.list \
1862 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
1863 rm -f distro-packages.list non-free.list 2>/dev/null
1864 tazpkg recharge
1866 DESC=""
1867 [ -n "$3" ] && \
1868 while read action pkg; do
1869 case "$action" in
1870 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
1871 -) yes | tazpkg remove $pkg ;;
1872 !) echo $pkg >> non-free.list ;;
1873 @) DESC="$pkg" ;;
1874 \?) echo -en "$pkg"; read action ;;
1875 esac
1876 done < $3
1878 yes '' | tazlito gen-distro
1879 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
1880 mv /etc/tazlito/distro-packages.list.$$ \
1881 /etc/tazlito/distro-packages.list 2>/dev/null
1882 ;;
1885 gen-flavor)
1886 # Generate a new flavor from the last ISO image generated
1887 FLAVOR=${2%.flavor}
1888 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1890 title 'Flavor generation'
1891 check_rootfs
1892 FILES="$FLAVOR.pkglist"
1894 action 'Creating file %s...' "$FLAVOR.flavor"
1895 for i in rootcd rootfs; do
1896 if [ -d "$ADDFILES/$i" ] ; then
1897 FILES="$FILES\n$FLAVOR.$i"
1898 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
1899 fi
1900 done
1901 status
1903 answer=$(grep -s ^Description $FLAVOR.desc)
1904 answer=${answer#Description : }
1905 if [ -z "$answer" ]; then
1906 echo -n "Description: "
1907 read answer
1908 fi
1910 action 'Compressing flavor %s...' "$FLAVOR"
1911 echo "Flavor : $FLAVOR" > $FLAVOR.desc
1912 echo "Description : $answer" >> $FLAVOR.desc
1913 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
1914 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
1915 for i in $(ls $ROOTFS$INSTALLED); do
1916 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
1917 EXTRAVERSION=""
1918 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
1919 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
1920 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
1921 echo "$i" >> $FLAVOR.nonfree
1922 else
1923 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
1924 fi
1925 done
1926 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
1927 for i in $LOCALSTATE/undigest/*/mirror ; do
1928 [ -s $i ] && cat $i >> $FLAVOR.mirrors
1929 done
1930 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
1931 touch -t 197001010100.00 $FLAVOR.*
1932 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
1933 rm $(echo -e $FILES)
1934 status
1936 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
1937 ;;
1940 upgrade-flavor)
1941 # Strip versions from pkglist and update estimated numbers in flavor.desc
1942 flavor="${2%.flavor}"
1943 set -e
1944 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1945 set +e
1947 flv_dir="$(extract_flavor "$flavor")"
1949 strip_versions "$flv_dir/$flavor.pkglist"
1951 action 'Updating %s...' "$flavor.desc"
1953 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
1954 set -- $(module calc_sizes "$flv_dir" "$flavor")
1955 restore_mirrors >/dev/null
1957 sed -i -e '/Image is ready/d' \
1958 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
1959 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
1960 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
1961 -e "s|\(Packages *:\).*$|\1 $4|" \
1962 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
1963 "$flv_dir/$flavor.desc"
1965 pack_flavor "$flv_dir" "$flavor"
1966 status
1967 display_unknown "$flv_dir/err"
1968 display_warn "$flv_dir/warn"
1969 cleanup
1970 ;;
1973 extract-flavor)
1974 # Extract a flavor into $FLAVORS_REPOSITORY
1975 flavor="${2%.flavor}"
1976 set -e
1977 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1978 set +e
1980 action 'Extracting %s...' "$flavor.flavor"
1981 flv_dir="$(extract_flavor "$flavor" full)"
1982 storage="$FLAVORS_REPOSITORY/$flavor"
1984 rm -rf "$storage" 2>/dev/null
1985 mkdir -p "$storage"
1986 cp -a "$flv_dir"/* "$storage"
1987 rm "$storage/description"
1988 status
1990 strip_versions "$storage/packages.list"
1992 cleanup
1993 ;;
1996 pack-flavor)
1997 # Create a flavor from $FLAVORS_REPOSITORY.
1998 flavor=${2%.flavor}
1999 storage="$FLAVORS_REPOSITORY/$flavor"
2001 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2003 action 'Creating flavor %s...' "$flavor"
2004 tmp_dir="$(mktemp -d)"
2006 while read from to; do
2007 [ -s "$storage/$from" ] || continue
2008 cp -a "$storage/$from" "$tmp_dir/$to"
2009 done <<EOT
2010 mirrors $flavor.mirrors
2011 distro.sh $flavor-distro.sh
2012 receipt $flavor.receipt
2013 non-free.list $flavor.nonfree
2014 EOT
2016 # Build the package list.
2017 # It can include a list from another flavor with the keyword @include
2018 if [ -s "$storage/packages.list" ]; then
2019 include=$(grep '^@include' "$storage/packages.list")
2020 if [ -n "$include" ]; then
2021 include=${include#@include }
2022 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2023 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2024 else
2025 echo -e "\nERROR: Can't find include package list from $include\n"
2026 fi
2027 fi
2028 # Generate the final/initial package list
2029 [ -s "$storage/packages.list" ] && \
2030 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2031 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2032 fi
2034 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2035 # Process multi-rootfs flavor
2036 . "$storage/receipt"
2037 set -- $ROOTFS_SELECTION
2038 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2039 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2040 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2042 for i in rootcd rootfs; do
2043 mkdir "$tmp_dir/$i"
2044 # Copy extra files from the first flavor
2045 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2046 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2047 # Overload extra files by meta flavor
2048 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2049 [ -n "$(ls $tmp_dir/$i)" ] &&
2050 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2051 dogzip "$tmp_dir/$flavor.$i"
2052 rm -rf "$tmp_dir/$i"
2053 done
2054 else
2055 # Process plain flavor
2056 for i in rootcd rootfs; do
2057 [ -d "$storage/$i" ] || continue
2058 (cd "$storage/$i";
2059 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2060 done
2061 fi
2063 unset VERSION MAINTAINER ROOTFS_SELECTION
2064 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2065 ROOTFS_SIZE="$1 (estimated)"
2066 INITRAMFS_SIZE="$2 (estimated)"
2067 ISO_SIZE="$3 (estimated)"
2068 PKGNUM="$4"
2069 . "$storage/receipt"
2071 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2072 Flavor : $FLAVOR
2073 Description : $SHORT_DESC
2074 Version : $VERSION
2075 Maintainer : $MAINTAINER
2076 LiveCD RAM size : $FRUGAL_RAM
2077 Rootfs list : $ROOTFS_SELECTION
2078 Build date : $(date '+%Y%m%d at %T')
2079 Packages : $PKGNUM
2080 Rootfs size : $ROOTFS_SIZE
2081 Initramfs size : $INITRAMFS_SIZE
2082 ISO image size : $ISO_SIZE
2083 ================================================================================
2085 EOT
2087 rm -f $tmp_dir/packages.list
2088 pack_flavor "$tmp_dir" "$flavor"
2089 status
2090 display_unknown "$tmp_dir/err"
2091 display_warn "$flv_dir/warn"
2092 cleanup
2093 ;;
2096 get-flavor)
2097 # Get a flavor's files and prepare for gen-distro.
2098 flavor=${2%.flavor}
2099 title 'Preparing %s distro flavor' "$flavor"
2100 set -e
2101 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2102 set +e
2104 action 'Cleaning %s...' "$DISTRO"
2105 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2106 # Clean old files
2107 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2108 [ -f "$i" ] && rm "$i"
2109 done
2110 mkdir -p "$DISTRO"
2111 status
2113 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2115 action 'Extracting flavor %s...' "$flavor.flavor"
2116 flv_dir="$(extract_flavor "$flavor" info)"
2117 cp -a "$flv_dir"/* .
2118 mv packages.list distro-packages.list
2119 mv -f info /etc/tazlito
2120 status
2122 for i in rootcd rootfs; do
2123 if [ -d "$i" ]; then
2124 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2125 fi
2126 done
2128 rm -f /etc/tazlito/rootfs.list
2129 grep -q '^Rootfs list' description &&
2130 grep '^Rootfs list' description | sed 's/.*: \(.*\)$/\1/' > /etc/tazlito/rootfs.list
2132 action 'Updating %s...' 'tazlito.conf'
2133 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2134 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2135 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2136 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2137 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2138 status
2140 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2141 cleanup
2142 ;;
2145 iso2flavor)
2146 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2147 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2149 FLAVOR=${3%.flavor}
2150 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2151 mount -o loop,ro $2 $TMP_DIR/iso
2152 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2153 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2154 ! -s $TMP_DIR/flavor/*.desc ]; then
2155 _ 'META flavors are not supported.'
2156 umount -d $TMP_DIR/iso
2157 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2158 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2159 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2160 umount -d $TMP_DIR/iso
2161 else
2162 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2163 uncompress $i | \
2164 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2165 done
2166 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2167 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2168 '/etc/slitaz-release' '/boot/rootfs.gz'
2169 umount -d $TMP_DIR/iso
2170 else
2171 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2172 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2173 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2174 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2175 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2176 umount -d $TMP_DIR/iso
2177 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2178 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2179 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2180 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2181 < $TMP_DIR/rootfs$INSTALLED.md5
2182 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2183 if [ -s $TMP_DIR/flavor/*desc ]; then
2184 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2185 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2186 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2187 for i in rootfs rootcd ; do
2188 [ -s $TMP_DIR/flavor/*.list$i ] &&
2189 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2190 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2191 done
2192 else
2193 find_flavor_rootfs $TMP_DIR/rootfs
2194 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2195 for i in rootfs rootcd ; do
2196 [ "$(ls $TMP_DIR/$i)" ] &&
2197 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2198 done
2199 unset VERSION MAINTAINER
2200 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2201 if [ -n "$DESCRIPTION" ]; then
2202 _n 'Flavor version : '; read -t 30 VERSION
2203 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2204 fi
2206 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2207 Flavor : $FLAVOR
2208 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2209 Version : ${VERSION:-1.0}
2210 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2211 LiveCD RAM size : $RAM_SIZE
2212 Build date : $BUILD_DATE
2213 Packages : $PKGCNT
2214 Rootfs size : $ROOTFS_SIZE
2215 Initramfs size : $INITRAMFS_SIZE
2216 ISO image size : $ISO_SIZE
2217 ================================================================================
2219 EOT
2220 longline "Tazlito can't detect each file installed during \
2221 a package post_install. You should extract this flavor (tazlito extract-flavor \
2222 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2223 tree and remove files generated by post_installs.
2224 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2225 repack the flavor (tazlito pack-flavor $FLAVOR)"
2226 fi
2227 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2228 fi
2229 fi
2230 rm -rf $TMP_DIR
2231 ;;
2234 gen-distro)
2235 # Generate a live distro tree with a set of packages.
2237 check_root
2238 start_time=$(date +%s)
2240 # Tazlito options: --iso or --cdrom
2241 CDROM=''
2242 [ -n "$iso" ] && CDROM="-o loop $iso"
2243 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2245 # Check if a package list was specified on cmdline.
2246 if [ -f "$2" ]; then
2247 LIST_NAME="$2"
2248 else
2249 LIST_NAME='distro-packages.list'
2250 fi
2252 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2253 'Please clean the distro tree or change directory path.'
2254 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2255 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2257 # If list not given: build list with all installed packages
2258 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2259 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2260 fi
2262 # Exit if no list name.
2263 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2265 # Start generation.
2266 title 'Tazlito generating a distro'
2268 # Misc checks
2269 mkdir -p "$PACKAGES_REPOSITORY"
2270 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2271 newline
2273 # Mount CD-ROM to be able to repack boot-loader packages
2274 if [ ! -e /boot -a -n "$CDROM" ]; then
2275 mkdir $TMP_MNT
2276 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2277 ln -s "$TMP_MNT/boot" /
2278 if [ ! -d "$ADDFILES/rootcd" ] ; then
2279 mkdir -p "$ADDFILES/rootcd"
2280 for i in $(ls $TMP_MNT); do
2281 [ "$i" == 'boot' ] && continue
2282 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2283 done
2284 fi
2285 else
2286 rmdir "$TMP_MNT"
2287 fi
2288 fi
2290 # Rootfs stuff.
2291 echo 'Preparing the rootfs directory...'
2292 mkdir -p "$ROOTFS"
2293 export root="$ROOTFS"
2294 # pass current 'mirror' to the root
2295 mkdir -p $root/var/lib/tazpkg $root/etc
2296 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2297 cp -f /etc/slitaz-release $root/etc/slitaz-release
2298 strip_versions "$LIST_NAME"
2300 if [ "$REPACK" == 'y' ]; then
2301 # Determine full packages list with all dependencies
2302 tmp_dir="$(mktemp -d)"
2303 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2304 touch "$tmp_dir/full.pkglist"
2305 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2307 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2308 while read pkgname pkgver; do
2309 # Is package in full list?
2310 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2311 # Is package already repacked?
2312 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2313 _ 'Repacking %s...' "$pkgname-$pkgver"
2314 tazpkg repack "$pkgname" --quiet
2315 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2316 status
2317 done
2319 rm -r "$tmp_dir"
2320 fi
2322 if [ -f non-free.list ]; then
2323 # FIXME: working in the ROOTFS chroot?
2324 newline
2325 echo 'Preparing non-free packages...'
2326 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2327 for pkg in $(cat 'non-free.list'); do
2328 if [ ! -d "$INSTALLED/$pkg" ]; then
2329 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2330 tazpkg get-install get-$pkg
2331 fi
2332 get-$pkg "$ROOTFS"
2333 fi
2334 tazpkg repack $pkg
2335 pkg=$(ls $pkg*.tazpkg)
2336 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2337 mv $pkg $PACKAGES_REPOSITORY
2338 done
2339 fi
2340 cp $LIST_NAME $DISTRO/distro-packages.list
2341 newline
2343 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2345 cd $DISTRO
2346 cp distro-packages.list $ROOTFS/etc/tazlito
2347 # Copy all files from $ADDFILES/rootfs to the rootfs.
2348 if [ -d "$ADDFILES/rootfs" ] ; then
2349 action 'Copying addfiles content to the rootfs...'
2350 cp -a $ADDFILES/rootfs/* $ROOTFS
2351 status
2352 fi
2354 action 'Root filesystem is generated...'; status
2356 # Root CD part.
2357 action 'Preparing the rootcd directory...'
2358 mkdir -p $ROOTCD
2359 status
2361 # Move the boot dir with the Linux kernel from rootfs.
2362 # The boot dir goes directly on the CD.
2363 if [ -d "$ROOTFS/boot" ] ; then
2364 action 'Moving the boot directory...'
2365 mv $ROOTFS/boot $ROOTCD
2366 cd $ROOTCD/boot
2367 rm -rf grub*
2368 make_bzImage_hardlink
2369 status
2370 fi
2371 cd $DISTRO
2372 # Copy all files from $ADDFILES/rootcd to the rootcd.
2373 if [ -d "$ADDFILES/rootcd" ] ; then
2374 action 'Copying addfiles content to the rootcd...'
2375 cp -a $ADDFILES/rootcd/* $ROOTCD
2376 status
2377 fi
2378 # Execute the distro script used to perform tasks in the rootfs
2379 # before compression. Give rootfs path in arg
2380 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2381 if [ -x "$DISTRO_SCRIPT" ]; then
2382 echo 'Executing distro script...'
2383 sh $DISTRO_SCRIPT $DISTRO
2384 fi
2386 # Execute the custom_rules() found in receipt.
2387 if [ -s "$TOP_DIR/receipt" ]; then
2388 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2389 echo -e "Executing: custom_rules()\n"
2390 . "$TOP_DIR/receipt"
2391 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2392 fi
2393 fi
2395 # Multi-rootfs
2396 if [ -s /etc/tazlito/rootfs.list ]; then
2398 FLAVOR_LIST="$(awk '{
2399 for (i = 2; i <= NF; i+=2)
2400 printf "%s ", $i;
2401 }' /etc/tazlito/rootfs.list)"
2403 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2404 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2405 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2407 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2408 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2409 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2410 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2412 n=0
2413 last=$ROOTFS
2414 while read flavor; do
2415 n=$(($n+1))
2416 mkdir ${ROOTFS}0$n
2417 export root="${ROOTFS}0$n"
2418 # initial tazpkg setup in empty rootfs
2419 tazpkg --root=$root >/dev/null 2>&1
2421 newline
2422 boldify "Building $flavor rootfs..."
2424 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2425 cp "$TOP_DIR/$flavor.flavor" .
2427 if [ ! -s "$flavor.flavor" ]; then
2428 # We may have it in $FLAVORS_REPOSITORY
2429 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2430 tazlito pack-flavor $flavor
2431 else
2432 download $flavor.flavor
2433 fi
2434 fi
2436 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2437 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2438 cp $flavor.pkglist $DISTRO/list-packages0$n
2439 status
2441 strip_versions "$DISTRO/list-packages0$n"
2443 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2445 rm -rf ${ROOTFS}0$n/boot
2447 cd $DISTRO
2448 if [ -s $flavor.rootfs ]; then
2449 _n 'Adding %s rootfs extra files...' "$flavor"
2450 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2451 fi
2453 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2454 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2455 status
2457 rm -f $flavor.flavor install-list
2458 mergefs ${ROOTFS}0$n $last
2459 last=${ROOTFS}0$n
2460 done <<EOT
2461 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2462 EOT
2463 #'
2464 i=$(($n+1))
2465 while [ $n -gt 0 ]; do
2466 mv ${ROOTFS}0$n ${ROOTFS}$i
2467 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2468 gen_initramfs ${ROOTFS}$i
2469 n=$(($n-1))
2470 i=$(($i-1))
2471 export LZMA_HISTORY_BITS=26
2472 done
2473 mv $ROOTFS ${ROOTFS}$i
2474 gen_initramfs ${ROOTFS}$i
2475 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2476 else
2477 # Initramfs and ISO image stuff.
2478 gen_initramfs $ROOTFS
2479 fi
2480 gen_livecd_isolinux
2481 distro_stats
2482 cleanup
2483 ;;
2486 clean-distro)
2487 # Remove old distro tree.
2489 check_root
2490 title 'Cleaning: %s' "$DISTRO"
2491 if [ -d "$DISTRO" ] ; then
2492 if [ -d "$ROOTFS" ] ; then
2493 action 'Removing the rootfs...'
2494 rm -f $DISTRO/$INITRAMFS
2495 rm -rf $ROOTFS
2496 status
2497 fi
2498 if [ -d "$ROOTCD" ] ; then
2499 action 'Removing the rootcd...'
2500 rm -rf $ROOTCD
2501 status
2502 fi
2503 action 'Removing eventual ISO image...'
2504 rm -f $DISTRO/$ISO_NAME.iso
2505 rm -f $DISTRO/$ISO_NAME.md5
2506 status
2507 fi
2508 footer
2509 ;;
2512 check-distro)
2513 # Check for a few LiveCD needed files not installed by packages.
2515 # TODO: Remove this function.
2516 # First two files are maintained by tazpkg while it runs on rootfs,
2517 # while last one file should be maintained by tazlito itself.
2518 check_rootfs
2519 title 'Checking distro: %s' "$ROOTFS"
2520 # SliTaz release info.
2521 rel='/etc/slitaz-release'
2522 if [ ! -f "$ROOTFS$rel" ]; then
2523 _ 'Missing release info: %s' "$rel"
2524 else
2525 action 'Release : %s' "$(cat $ROOTFS$rel)"
2526 status
2527 fi
2528 # Tazpkg mirror.
2529 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2530 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2531 todomsg
2532 else
2533 action 'Mirror configuration exists...'
2534 status
2535 fi
2536 # Isolinux msg
2537 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2538 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2539 todomsg
2540 else
2541 action 'Isolinux message seems good...'
2542 status
2543 fi
2544 footer
2545 ;;
2548 writeiso)
2549 # Writefs to ISO image including /home unlike gen-distro we don't use
2550 # packages to generate a rootfs, we build a compressed rootfs with all
2551 # the current filesystem similar to 'tazusb writefs'.
2553 DISTRO='/home/slitaz/distro'
2554 ROOTCD="$DISTRO/rootcd"
2555 COMPRESSION="${2:-none}"
2556 ISO_NAME="${3:-slitaz}"
2557 check_root
2558 # Start info
2559 title 'Write filesystem to ISO'
2560 longline "The command writeiso will write the current filesystem into a \
2561 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2562 newline
2563 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2565 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2566 # Save some space
2567 rm -rf /var/cache/tazpkg/*
2568 rm -f /var/lib/tazpkg/*.bak
2569 rm -rf $DISTRO
2571 # Optionally remove sound card selection and screen resolution.
2572 if [ -z $LaunchedByTazpanel ]; then
2573 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2574 case $anser in
2575 y)
2576 action 'Removing current sound card and screen configurations...'
2577 rm -f /var/lib/sound-card-driver
2578 rm -f /var/lib/alsa/asound.state
2579 rm -f /etc/X11/xorg.conf ;;
2580 *)
2581 action 'Keeping current sound card and screen configurations...' ;;
2582 esac
2583 status
2584 newline
2586 # Optionally remove i18n settings
2587 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2588 case $anser in
2589 y)
2590 action 'Removing current locale/keymap settings...'
2591 newline > /etc/locale.conf
2592 newline > /etc/keymap.conf ;;
2593 *)
2594 action 'Keeping current locale/keymap settings...' ;;
2595 esac
2596 status
2597 fi
2599 # Clean-up files by default
2600 newline > /etc/udev/rules.d/70-persistent-net.rules
2601 newline > /etc/udev/rules.d/70-persistant-cd.rules
2603 # Create list of files including default user files since it is defined in /etc/passwd
2604 # and some new users might have been added.
2605 cd /
2606 echo 'init' > /tmp/list
2607 for dir in bin etc sbin var dev lib root usr home opt; do
2608 [ -d $dir ] && find $dir
2609 done >> /tmp/list
2611 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2612 [ -d $dir ] && echo $dir
2613 done >> /tmp/list
2615 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2617 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2618 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2619 #fi
2620 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2621 touch /var/log/wtmp
2623 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2624 sed -i "/var\/log\/$removelog/d" /tmp/list
2625 done
2627 # Generate initramfs with specified compression and display rootfs
2628 # size in realtime.
2629 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2631 write_initramfs &
2632 sleep 2
2633 cd - > /dev/null
2634 echo -en "\nFilesystem size:"
2635 while [ ! -f /tmp/rootfs ]; do
2636 sleep 1
2637 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2638 done
2639 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2640 echo -e "\n"
2641 rm -f /tmp/rootfs
2643 # Move freshly generated rootfs to the cdrom.
2644 mkdir -p $ROOTCD/boot
2645 mv -f /$INITRAMFS $ROOTCD/boot
2646 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2648 # Now we need the kernel and isolinux files.
2649 copy_from_cd() {
2650 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2651 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2652 unmeta_boot $ROOTCD
2653 umount /media/cdrom
2656 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2657 copy_from_cd;
2658 elif mount | grep /media/cdrom; then
2659 copy_from_cd;
2660 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2661 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2662 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2663 else
2664 touch /tmp/.write-iso-error
2665 longline "When SliTaz is running in RAM the kernel and bootloader \
2666 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
2667 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
2668 echo -en "----\nENTER to continue..."; read i
2669 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2670 copy_from_cd
2671 fi
2673 # Generate the iso image.
2674 touch /tmp/.write-iso
2675 newline
2676 cd $DISTRO
2677 create_iso $ISO_NAME.iso $ROOTCD
2678 action 'Creating the ISO md5sum...'
2679 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2680 status
2682 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2683 rm -f /tmp/.write-iso
2685 if [ -z $LaunchedByTazpanel ]; then
2686 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2687 case $anser in
2688 y)
2689 umount /dev/cdrom 2>/dev/null
2690 eject
2691 echo -n "Please insert a blank CD-ROM and press ENTER..."
2692 read i && sleep 2
2693 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2694 echo -en "----\nENTER to continue..."; read i ;;
2695 *)
2696 exit 0 ;;
2697 esac
2698 fi
2699 ;;
2702 burn-iso)
2703 # Guess CD-ROM device, ask user and burn the ISO.
2705 check_root
2706 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2707 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2708 # We can specify an alternative ISO from the cmdline.
2709 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2710 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2712 title 'Tazlito burn ISO'
2713 echo "CD-ROM device : /dev/$DRIVE_NAME"
2714 echo "Drive speed : $DRIVE_SPEED"
2715 echo "ISO image : $iso"
2716 footer
2718 case $(yesorno 'Burn ISO image?' 'n') in
2719 y)
2720 title 'Starting Wodim to burn the ISO...'
2721 sleep 2
2722 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2723 footer 'ISO image is burned to CD-ROM.'
2724 ;;
2725 *)
2726 die 'Exiting. No ISO burned.'
2727 ;;
2728 esac
2729 ;;
2732 merge)
2733 # Merge multiple rootfs into one iso.
2735 if [ -z "$2" ]; then
2736 cat <<EOT
2737 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2739 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2740 i.e: rootfsN is a subset of rootfsN-1
2741 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2742 The boot loader will select the rootfs according to the RAM size detected.
2744 Example:
2745 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
2747 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
2748 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
2750 EOT
2751 exit 2
2752 fi
2754 shift # skip merge
2755 append="$1 slitaz1"
2756 shift # skip size1
2757 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
2759 ISO=$1.merged
2761 # Extract filesystems
2762 action 'Mounting %s' "$1"
2763 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
2764 status || cleanup_merge
2766 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2767 make_bzImage_hardlink $TMP_DIR/iso/boot
2768 umount -d $TMP_DIR/mnt
2769 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
2770 _ '%s is already a merged iso. Aborting.' "$1"
2771 cleanup_merge
2772 fi
2773 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
2774 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
2775 if [ ! -f /boot/isolinux/ifmem.c32 -a
2776 ! -f /boot/isolinux/c32box.c32 ]; then
2777 cat <<EOT
2778 No file /boot/isolinux/ifmem.c32
2779 Please install syslinux package !
2780 EOT
2781 rm -rf $TMP_DIR
2782 exit 1
2783 fi
2784 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
2785 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
2786 fi
2788 action 'Extracting %s' 'iso/rootfs.gz'
2789 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
2790 [ -d $TMP_DIR/rootfs1/etc ]
2791 status || cleanup_merge
2793 n=1
2794 while [ -n "$2" ]; do
2795 shift # skip rootfs N-1
2796 p=$n
2797 n=$(($n + 1))
2798 append="$append $1 slitaz$n"
2799 shift # skip size N
2800 mkdir -p $TMP_DIR/rootfs$n
2802 action 'Extracting %s' "$1"
2803 extract_rootfs $1 $TMP_DIR/rootfs$n &&
2804 [ -d "$TMP_DIR/rootfs$n/etc" ]
2805 status || cleanup_merge
2807 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
2808 action 'Creating %s' "rootfs$p.gz"
2809 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
2810 status
2811 done
2812 action 'Creating %s' "rootfs$n.gz"
2813 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
2814 status
2815 rm -f $TMP_DIR/iso/boot/rootfs.gz
2816 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
2817 create_iso $ISO $TMP_DIR/iso
2818 rm -rf $TMP_DIR
2819 ;;
2822 repack)
2823 # Repack an iso with maximum lzma compression ratio.
2825 ISO=$2
2826 mkdir -p $TMP_DIR/mnt
2828 # Extract filesystems
2829 action 'Mounting %s' "$ISO"
2830 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
2831 status || cleanup_merge
2833 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2834 umount -d $TMP_DIR/mnt
2836 for i in $TMP_DIR/iso/boot/rootfs* ; do
2837 action 'Repacking %s' "$(basename $i)"
2838 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
2839 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
2840 align_to_32bits $i
2841 status
2842 done
2844 create_iso $ISO $TMP_DIR/iso
2845 rm -rf $TMP_DIR
2846 ;;
2849 build-loram)
2850 # Build a Live CD for low RAM systems.
2852 ISO="$2"
2853 OUTPUT="$3"
2854 [ -z "$3" ] && \
2855 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
2856 mkdir -p "$TMP_DIR/iso"
2857 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
2858 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
2859 if ! check_iso_for_loram ; then
2860 umount -d "$TMP_DIR/iso"
2861 die "$ISO is not a valid SliTaz live CD. Abort."
2862 fi
2863 case "$4" in
2864 cdrom) build_loram_cdrom ;;
2865 http) build_loram_http ;;
2866 *) build_loram_ram ;;
2867 esac
2868 umount $TMP_DIR/iso # no -d: needs /proc
2869 losetup -d $loopdev
2870 rm -rf $TMP_DIR
2871 ;;
2874 emu-iso)
2875 # Emulate an ISO image with Qemu.
2876 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2877 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
2878 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
2879 echo -e "\nStarting Qemu emulator:\n"
2880 echo -e "qemu $QEMU_OPTS $iso\n"
2881 qemu $QEMU_OPTS $iso
2882 ;;
2885 deduplicate)
2886 # Deduplicate files in a tree
2887 shift
2888 deduplicate "$@"
2889 ;;
2892 usage|*)
2893 # Print usage also for all unknown commands.
2894 usage
2895 ;;
2896 esac
2898 exit 0