tazlito view tazlito @ rev 460

tazlito: pass /etc/slitaz-release to the rootfs too; add option --stripped to consider packages list already stripped.
author Aleksej Bobylev <al.bobylev@gmail.com>
date Fri Sep 08 14:14:08 2017 +0300 (2017-09-08)
parents c6ab9a100548
children f399e0ab8101
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 else
1109 mkdir -p /mnt/.rw/mnt/.httpfs
1110 fi
1111 while read type opt; do
1112 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1113 done <<EOT
1114 aufs br=/mnt/.rw\$branch
1115 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1116 EOT
1117 rm -rf /lib/modules
1118 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1119 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1120 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1121 EOTEOT
1122 chmod +x $TMP_DIR/initfs/init
1123 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1124 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1125 rm -f $i
1126 dogzip ${i%.gz}
1127 done 2>/dev/null
1128 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1129 lzma e $TMP_DIR/initfs.gz -si
1130 lzma_set_size $TMP_DIR/initfs.gz
1131 rm -rf $TMP_DIR/initfs
1132 align_to_32bits $TMP_DIR/initfs.gz
1133 return 0
1137 # Move each initramfs to squashfs
1139 build_loram_rootfs() {
1140 rootfs_sizes=""
1141 for i in $TMP_DIR/iso/boot/rootfs*; do
1142 mkdir -p $TMP_DIR/fs
1143 cd $TMP_DIR/fs
1144 uncompress $i | cpio -idm
1145 deduplicate
1146 cd - > /dev/null
1147 rootfs=$TMP_DIR/$(basename $i)
1148 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp xz -Xbcj x86
1149 cd $TMP_DIR
1150 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1151 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1152 rm -f $rootfs
1153 mv $rootfs.cpio $rootfs
1154 cd - > /dev/null
1155 rm -rf $TMP_DIR/fs
1156 done
1160 # Move meta boot configuration files to basic configuration files
1161 # because meta loram flavor is useless when rootfs is not loaded in RAM
1163 unmeta_boot() {
1164 local root=${1:-$TMP_DIR/loramiso}
1165 if [ -f $root/boot/isolinux/noram.cfg ]; then
1166 # We keep enough information to do unloram...
1167 [ -s $root/boot/isolinux/common.cfg ] &&
1168 sed -i 's/label slitaz/label orgslitaz/' \
1169 $root/boot/isolinux/common.cfg
1170 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1171 shift
1172 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1173 $root/boot/isolinux/isolinux.cfg
1174 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1175 sed -i "s/label $3\$/label slitaz/;s|=/boot/rootfs\(.*\).gz |=/boot/rootfs.gz |" \
1176 $root/boot/isolinux/*.cfg
1177 fi
1181 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1182 # These squashfs may be loaded in RAM at boot time.
1183 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1184 # Meta flavors are converted to normal flavors.
1186 build_loram_cdrom() {
1187 build_initfs cdrom || return 1
1188 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1189 mkdir $TMP_DIR/loramiso/fs
1190 cd $TMP_DIR/loramiso/fs
1191 for i in $( ls ../boot/root* | sort -r ) ; do
1192 uncompress $i | cpio -idmu
1193 rm -f $i
1194 done
1195 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1196 cd - >/dev/null
1197 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1198 unmeta_boot
1199 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1200 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1201 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1202 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1203 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1204 create_iso $OUTPUT $TMP_DIR/loramiso
1208 # Create http bootstrap to load and remove loram_cdrom
1209 # Meta flavors are converted to normal flavors.
1211 build_loram_http() {
1212 build_initfs http || return 1
1213 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1214 rm -f $TMP_DIR/loramiso/boot/rootfs*
1215 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1216 unmeta_boot
1217 create_iso $OUTPUT $TMP_DIR/loramiso
1221 # Update meta flavor selection sizes.
1222 # Reduce sizes with rootfs gains.
1224 update_metaiso_sizes() {
1225 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1226 do
1227 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1228 local sizes="$rootfs_sizes"
1229 local new
1230 set -- $append
1231 shift
1232 [ "$1" == "ifmem" ] && shift
1233 new=""
1234 while [ -n "$2" ]; do
1235 local s
1236 case "$1" in
1237 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1238 *M) s=$(( ${1%M} * 1024 ));;
1239 *) s=${1%K};;
1240 esac
1241 sizes=${sizes#* }
1242 for i in $sizes ; do
1243 s=$(( $s - $i ))
1244 done
1245 new="$new $s $2"
1246 shift 2
1247 done
1248 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1249 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1250 sed -i 's|\(initrd=\)\(/boot/rootfs.\.gz\)|\1/boot/rootfs.gz,\2|' $cfg
1251 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1252 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1253 done
1257 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1258 # Meta flavor selection sizes are updated.
1260 build_loram_ram() {
1261 build_initfs ram || return 1
1262 build_loram_rootfs
1263 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1264 make_bzImage_hardlink $TMP_DIR/loramiso/boot
1265 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1266 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1267 update_metaiso_sizes
1268 create_iso $OUTPUT $TMP_DIR/loramiso
1272 # Remove files installed by packages
1274 find_flavor_rootfs() {
1275 for i in $1/etc/tazlito/*.extract; do
1276 [ -e $i ] || continue
1277 chroot $1 /bin/sh ${i#$1}
1278 done
1280 # Clean hardlinks and files patched by genisofs in /boot
1281 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1282 rm -f $1/boot/$i*
1283 done
1285 # Clean files generated in post_install
1286 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1287 $1/dev/core $1/dev/fd $1/dev/std*
1289 # Verify md5
1290 cat $1$INSTALLED/*/md5sum | \
1291 while read md5 file; do
1292 [ -e "$1$file" ] || continue
1293 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1294 rm -f "$1$file"
1295 done
1297 # Check configuration files
1298 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1299 [ -e $i ] || continue
1300 mkdir /tmp/volatile$$
1301 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1302 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1303 while read file ; do
1304 [ -e "$1/$file" ] || continue
1305 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1306 done
1307 rm -rf /tmp/volatile$$
1308 done
1310 # Remove other files blindly
1311 for i in $1$INSTALLED/*/files.list; do
1312 for file in $(cat "$i"); do
1313 [ "$1$file" -nt "$i" ] && continue
1314 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1315 [ -d "$1$file" ] || rm -f "$1$file"
1316 done
1317 done
1319 # Remove tazpkg files and tmp files
1320 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1321 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1322 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1323 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1324 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1326 # Cleanup directory tree
1327 cd $1
1328 find * -type d | sort -r | while read dir; do
1329 rmdir "$dir" 2>/dev/null
1330 done
1331 cd - > /dev/null
1335 # Get byte(s) from a binary file
1337 get() {
1338 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null
1342 # Get cpio flavor info from the ISO image
1344 flavordata() {
1345 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1346 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1350 # Restore undigest mirrors
1352 restore_mirrors() {
1353 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1354 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1356 action 'Restoring mirrors...'
1357 if [ -d "$undigest.bak" ]; then
1358 [ -d "$undigest" ] && rm -r "$undigest"
1359 mv "$undigest.bak" "$undigest"
1360 fi
1361 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1362 :; status
1366 # Setup undigest mirrors
1368 setup_mirrors() {
1369 # Setup mirrors in plain system or in chroot (with variable root=)
1370 local mirrorlist="$1" fresh repacked
1371 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1373 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1374 restore_mirrors
1376 _ 'Setting up mirrors for %s...' "$root/"
1377 # Backing up current undigest mirrors and priority
1378 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1379 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1380 rm -rf '/var/www/tazlito/'
1381 mkdir -p '/var/www/tazlito/'
1383 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1384 fresh='/home/slitaz/packages'
1385 if [ -d "$fresh" ]; then
1386 # Setup first undigest mirror
1387 mkdir -p "$undigest/fresh"
1388 echo "$fresh" > "$undigest/fresh/mirror"
1389 echo 'fresh' >> "$priority"
1390 # Rebuild mirror DB if needed
1391 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1392 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1393 tazpkg mkdb "$fresh" --forced --root=''
1394 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1395 fi
1397 # Repacked packages: high priority
1398 repacked="$PACKAGES_REPOSITORY"
1399 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1400 # According to Tazlito setup file (tazlito.conf):
1401 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1402 # or
1403 # WORK_DIR="/home/slitaz"
1404 # and
1405 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1406 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1408 # Setup second undigest mirror
1409 mkdir -p "$undigest/repacked"
1410 echo "$repacked" > "$undigest/repacked/mirror"
1411 echo 'repacked' >> "$priority"
1412 # Rebuild mirror DB if needed
1413 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1414 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1415 tazpkg mkdb "$repacked" --forced --root=''
1416 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1417 fi
1419 # All repositories listed in mirrors list: normal priority
1420 [ -e "$mirrorlist" ] && \
1421 while read mirror; do
1422 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1423 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1424 mkdir -p "$undigest/$mirrorid"
1425 echo "$mirror" > "$undigest/$mirrorid/mirror"
1426 echo "$mirrorid" >> "$priority"
1427 done < "$mirrorlist"
1429 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1431 # Show list of mirrors
1432 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1433 function show(num, name, url) {
1434 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1437 num++;
1438 "cat " db "/undigest/" $0 "/mirror" | getline url;
1439 show(num, $0, url);
1441 END {
1442 num++;
1443 "cat " db "/mirror" | getline url;
1444 show(num, "main", url);
1445 }' "$priority"
1447 tazpkg recharge --quiet >/dev/null
1451 # Get list of 'packages.info' lists using priority
1453 pi_lists() {
1454 local pi
1455 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1456 local priority="$root$LOCALSTATE/priority"
1457 local undigest="$root$LOCALSTATE/undigest"
1460 [ -s "$priority" ] && cat "$priority"
1461 echo 'main'
1462 [ -d "$undigest" ] && ls "$undigest"
1463 } | awk -vun="$undigest/" '
1465 if (arr[$0] != 1) {
1466 arr[$0] = 1;
1467 print un $0 "/packages.info";
1469 }' | sed 's|/undigest/main||' | \
1470 while read pi; do
1471 [ -e "$pi" ] && echo "$pi"
1472 done
1476 # Strip versions from packages list
1478 strip_versions() {
1479 if [ -n "$stripped" ]; then
1480 action 'Consider list %s already stripped' "$(basename "$1")"
1481 status
1482 return 0
1483 fi
1484 action 'Strip versions from list %s...' "$(basename "$1")"
1485 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1486 [ -f "$in_list" ] || die "List '$in_list' not found."
1488 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1489 awk '
1491 if (FILENAME ~ "packages.info") {
1492 # Collect package names
1493 FS = "\t"; pkg[$1] = 1;
1494 } else {
1495 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1496 while (NF > 1 && ! pkg[$0])
1497 NF --;
1498 printf "%s\n", $0;
1500 }' $(pi_lists) "$in_list" > "$tmp_list"
1502 cat "$tmp_list" > "$in_list"
1503 rm "$tmp_list"
1504 status
1508 # Display list of unknown packages (informative)
1510 display_unknown() {
1511 [ -s "$1" ] || return
1512 echo "Unknown packages:" >&2
1513 cat "$1" >&2
1514 rm "$1"
1518 # Display warnings about critical packages absent (informative)
1520 display_warn() {
1521 [ -s "$1" ] || return
1522 echo "Absent critical packages:" >&2
1523 cat "$1" >&2
1524 rm "$1"
1525 echo "Probably ISO image will be unusable."
1529 # Install packages to rootfs
1531 install_list_to_rootfs() {
1532 local list="$1" rootfs="$2" pkg i ii
1533 local undigest="$rootfs/var/lib/tazpkg/undigest"
1535 # initial tazpkg setup in empty rootfs
1536 tazpkg --root=$rootfs >/dev/null 2>&1
1537 # pass current 'mirror' to the rootfs
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
1550 for pkg in $(cat $list); do
1551 action 'Installing package: %s' "$pkg"
1552 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1553 status
1554 done
1555 newline
1557 restore_mirrors
1558 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1559 for i in fresh repacked; do
1560 ii="$undigest/$i"
1561 [ -d "$ii" ] && rm -rf "$ii"
1562 ii="$rootfs/var/lib/tazpkg/priority"
1563 if [ -f "$ii" ]; then
1564 sed -i "/$i/d" "$ii"
1565 [ -s "$ii" ] || rm "$ii"
1566 fi
1567 done
1568 [ -d "$undigest" ] && \
1569 for i in $(find "$undigest" -type f); do
1570 # Remove all undigest PKGDB files but 'mirror'
1571 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1572 done
1573 [ -d "$undigest" ] && \
1574 rmdir --ignore-fail-on-non-empty "$undigest"
1576 # Un-link packages cache
1577 rm "$rootfs/var/cache/tazpkg"
1579 # Clean /var/lib/tazpkg
1580 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1586 ####################
1587 # Tazlito commands #
1588 ####################
1590 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1591 case "$0" in
1592 *reduplicate)
1593 find ${@:-.} ! -type d -links +1 \
1594 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1595 exit 0 ;;
1596 *deduplicate)
1597 deduplicate "$@"
1598 exit 0 ;;
1599 esac
1602 case "$COMMAND" in
1603 stats)
1604 # Tazlito general statistics from the config file.
1606 title 'Tazlito statistics'
1607 optlist "\
1608 Config file : $CONFIG_FILE
1609 ISO name : $ISO_NAME.iso
1610 Volume name : $VOLUM_NAME
1611 Prepared : $PREPARED
1612 Packages repository : $PACKAGES_REPOSITORY
1613 Distro directory : $DISTRO
1614 Additional files : $ADDFILES
1615 " | sed '/: $/d'
1616 footer
1617 ;;
1620 list-addfiles)
1621 # Simple list of additional files in the rootfs
1622 newline
1623 if [ -d "$ADDFILES/rootfs" ]; then
1624 cd $ADDFILES
1625 find rootfs -type f
1626 else
1627 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1628 fi
1629 newline
1630 ;;
1633 gen-config)
1634 # Generate a new config file in the current dir or the specified
1635 # directory by $2.
1637 if [ -n "$2" ]; then
1638 mkdir -p "$2" && cd "$2"
1639 fi
1641 newline
1642 action 'Generating empty tazlito.conf...'
1643 empty_config_file
1644 status
1646 separator
1647 if [ -f 'tazlito.conf' ] ; then
1648 _ 'Configuration file is ready to edit.'
1649 _ 'File location: %s' "$(pwd)/tazlito.conf"
1650 newline
1651 fi
1652 ;;
1655 configure)
1656 # Configure a tazlito.conf config file. Start by getting
1657 # a empty config file and sed it.
1659 if [ -f 'tazlito.conf' ]; then
1660 rm tazlito.conf
1661 else
1662 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1663 'or in the same directory of the file you want to configure.'
1664 cd /etc
1665 fi
1667 empty_config_file
1669 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1671 # ISO name.
1672 echo -n "ISO name : " ; read answer
1673 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1674 # Volume name.
1675 echo -n "Volume name : " ; read answer
1676 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1677 # Packages repository.
1678 echo -n "Packages repository : " ; read answer
1679 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1680 # Distro path.
1681 echo -n "Distro path : " ; read answer
1682 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1683 footer "Config file is ready to use."
1684 echo 'You can now extract an ISO or generate a distro.'
1685 newline
1686 ;;
1689 gen-iso)
1690 # Simply generate a new iso.
1692 check_root
1693 verify_rootcd
1694 gen_livecd_isolinux
1695 distro_stats
1696 ;;
1699 gen-initiso)
1700 # Simply generate a new initramfs with a new iso.
1702 check_root
1703 verify_rootcd
1704 gen_initramfs "$ROOTFS"
1705 gen_livecd_isolinux
1706 distro_stats
1707 ;;
1710 extract-distro)
1711 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1713 check_root
1714 ISO_IMAGE="$2"
1715 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1716 'Example:\n tazlito image.iso /path/target'
1718 # Set the distro path by checking for $3 on cmdline.
1719 TARGET="${3:-$DISTRO}"
1721 # Exit if existing distro is found.
1722 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1723 'Please clean the distro tree or change directory path.'
1725 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
1727 # Start to mount the ISO.
1728 action 'Mounting ISO image...'
1729 mkdir -p "$TMP_DIR"
1730 # Get ISO file size.
1731 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
1732 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
1733 sleep 2
1734 # Prepare target dir, copy the kernel and the rootfs.
1735 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
1736 status
1738 action 'Copying the Linux kernel...'
1739 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
1740 make_bzImage_hardlink "$TARGET/rootcd/boot"
1741 else
1742 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
1743 fi
1744 status
1746 for i in $(ls $TMP_DIR); do
1747 [ "$i" == 'boot' ] && continue
1748 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
1749 done
1751 for loader in isolinux syslinux extlinux grub; do
1752 [ -d "$TMP_DIR/boot/$loader" ] || continue
1753 action 'Copying %s files...' "$loader"
1754 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
1755 status
1756 done
1758 action 'Copying the rootfs...'
1759 cp $TMP_DIR/boot/rootfs.?z "$TARGET/rootcd/boot"
1760 status
1762 # Extract initramfs.
1763 cd "$TARGET/rootfs"
1764 action 'Extracting the rootfs...'
1765 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
1766 # unpack /usr
1767 for i in etc/tazlito/*.extract; do
1768 [ -f "$i" ] && . $i ../rootcd
1769 done
1770 # Umount and remove temp directory and cd to $TARGET to get stats.
1771 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
1772 cd ..
1773 status
1775 newline
1776 separator
1777 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
1778 echo "Distro tree : $(pwd)"
1779 echo "Rootfs size : $(du -sh rootfs)"
1780 echo "Rootcd size : $(du -sh rootcd)"
1781 footer
1782 ;;
1785 list-flavors)
1786 # Show available flavors.
1787 list='/etc/tazlito/flavors.list'
1788 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
1789 title 'List of flavors'
1790 cat $list
1791 footer
1792 ;;
1795 show-flavor)
1796 # Show flavor description.
1797 set -e
1798 flavor=${2%.flavor}
1799 flv_dir="$(extract_flavor "$flavor")"
1800 desc="$flv_dir/$flavor.desc"
1801 if [ -n "$brief" ]; then
1802 if [ -z "$noheader" ]; then
1803 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
1804 separator
1805 fi
1806 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
1807 "$(field ISO "$desc")" \
1808 "$(field Rootfs "$desc")" \
1809 "$(field Description "$desc")"
1810 else
1811 separator
1812 cat "$desc"
1813 fi
1814 cleanup
1815 ;;
1818 gen-liveflavor)
1819 # Generate a new flavor from the live system.
1820 FLAVOR=${2%.flavor}
1821 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1823 case "$FLAVOR" in
1824 -?|-h*|--help)
1825 cat <<EOT
1826 SliTaz Live Tool - Version: $VERSION
1828 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
1830 $(boldify '<flavor-patch-file> format:')
1831 $(optlist "\
1832 code data
1833 + package to add
1834 - package to remove
1835 ! non-free package to add
1836 ? display message
1837 @ flavor description
1838 ")
1840 $(boldify 'Example:')
1841 $(optlist "\
1842 @ Developer tools for SliTaz maintainers
1843 + slitaz-toolchain
1844 + mercurial
1845 ")
1846 EOT
1847 exit 1
1848 ;;
1849 esac
1850 mv /etc/tazlito/distro-packages.list \
1851 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
1852 rm -f distro-packages.list non-free.list 2>/dev/null
1853 tazpkg recharge
1855 DESC=""
1856 [ -n "$3" ] && \
1857 while read action pkg; do
1858 case "$action" in
1859 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
1860 -) yes | tazpkg remove $pkg ;;
1861 !) echo $pkg >> non-free.list ;;
1862 @) DESC="$pkg" ;;
1863 \?) echo -en "$pkg"; read action ;;
1864 esac
1865 done < $3
1867 yes '' | tazlito gen-distro
1868 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
1869 mv /etc/tazlito/distro-packages.list.$$ \
1870 /etc/tazlito/distro-packages.list 2>/dev/null
1871 ;;
1874 gen-flavor)
1875 # Generate a new flavor from the last ISO image generated
1876 FLAVOR=${2%.flavor}
1877 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1879 title 'Flavor generation'
1880 check_rootfs
1881 FILES="$FLAVOR.pkglist"
1883 action 'Creating file %s...' "$FLAVOR.flavor"
1884 for i in rootcd rootfs; do
1885 if [ -d "$ADDFILES/$i" ] ; then
1886 FILES="$FILES\n$FLAVOR.$i"
1887 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
1888 fi
1889 done
1890 status
1892 answer=$(grep -s ^Description $FLAVOR.desc)
1893 answer=${answer#Description : }
1894 if [ -z "$answer" ]; then
1895 echo -n "Description: "
1896 read answer
1897 fi
1899 action 'Compressing flavor %s...' "$FLAVOR"
1900 echo "Flavor : $FLAVOR" > $FLAVOR.desc
1901 echo "Description : $answer" >> $FLAVOR.desc
1902 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
1903 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
1904 for i in $(ls $ROOTFS$INSTALLED); do
1905 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
1906 EXTRAVERSION=""
1907 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
1908 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
1909 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
1910 echo "$i" >> $FLAVOR.nonfree
1911 else
1912 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
1913 fi
1914 done
1915 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
1916 for i in $LOCALSTATE/undigest/*/mirror ; do
1917 [ -s $i ] && cat $i >> $FLAVOR.mirrors
1918 done
1919 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
1920 touch -t 197001010100.00 $FLAVOR.*
1921 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
1922 rm $(echo -e $FILES)
1923 status
1925 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
1926 ;;
1929 upgrade-flavor)
1930 # Strip versions from pkglist and update estimated numbers in flavor.desc
1931 flavor="${2%.flavor}"
1932 set -e
1933 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1934 set +e
1936 flv_dir="$(extract_flavor "$flavor")"
1938 strip_versions "$flv_dir/$flavor.pkglist"
1940 action 'Updating %s...' "$flavor.desc"
1942 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
1943 set -- $(module calc_sizes "$flv_dir" "$flavor")
1944 restore_mirrors >/dev/null
1946 sed -i -e '/Image is ready/d' \
1947 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
1948 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
1949 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
1950 -e "s|\(Packages *:\).*$|\1 $4|" \
1951 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
1952 "$flv_dir/$flavor.desc"
1954 pack_flavor "$flv_dir" "$flavor"
1955 status
1956 display_unknown "$flv_dir/err"
1957 display_warn "$flv_dir/warn"
1958 cleanup
1959 ;;
1962 extract-flavor)
1963 # Extract a flavor into $FLAVORS_REPOSITORY
1964 flavor="${2%.flavor}"
1965 set -e
1966 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1967 set +e
1969 action 'Extracting %s...' "$flavor.flavor"
1970 flv_dir="$(extract_flavor "$flavor" full)"
1971 storage="$FLAVORS_REPOSITORY/$flavor"
1973 rm -rf "$storage" 2>/dev/null
1974 mkdir -p "$storage"
1975 cp -a "$flv_dir"/* "$storage"
1976 rm "$storage/description"
1977 status
1979 strip_versions "$storage/packages.list"
1981 cleanup
1982 ;;
1985 pack-flavor)
1986 # Create a flavor from $FLAVORS_REPOSITORY.
1987 flavor=${2%.flavor}
1988 storage="$FLAVORS_REPOSITORY/$flavor"
1990 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
1992 action 'Creating flavor %s...' "$flavor"
1993 tmp_dir="$(mktemp -d)"
1995 while read from to; do
1996 [ -s "$storage/$from" ] || continue
1997 cp -a "$storage/$from" "$tmp_dir/$to"
1998 done <<EOT
1999 mirrors $flavor.mirrors
2000 distro.sh $flavor-distro.sh
2001 receipt $flavor.receipt
2002 non-free.list $flavor.nonfree
2003 EOT
2005 # Build the package list.
2006 # It can include a list from another flavor with the keyword @include
2007 if [ -s "$storage/packages.list" ]; then
2008 include=$(grep '^@include' "$storage/packages.list")
2009 if [ -n "$include" ]; then
2010 include=${include#@include }
2011 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2012 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2013 else
2014 echo -e "\nERROR: Can't find include package list from $include\n"
2015 fi
2016 fi
2017 # Generate the final/initial package list
2018 [ -s "$storage/packages.list" ] && \
2019 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2020 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2021 fi
2023 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2024 # Process multi-rootfs flavor
2025 . "$storage/receipt"
2026 set -- $ROOTFS_SELECTION
2027 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2028 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2029 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2031 for i in rootcd rootfs; do
2032 mkdir "$tmp_dir/$i"
2033 # Copy extra files from the first flavor
2034 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2035 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2036 # Overload extra files by meta flavor
2037 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2038 [ -n "$(ls $tmp_dir/$i)" ] &&
2039 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2040 dogzip "$tmp_dir/$flavor.$i"
2041 rm -rf "$tmp_dir/$i"
2042 done
2043 else
2044 # Process plain flavor
2045 for i in rootcd rootfs; do
2046 [ -d "$storage/$i" ] || continue
2047 (cd "$storage/$i";
2048 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2049 done
2050 fi
2052 unset VERSION MAINTAINER ROOTFS_SELECTION
2053 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2054 ROOTFS_SIZE="$1 (estimated)"
2055 INITRAMFS_SIZE="$2 (estimated)"
2056 ISO_SIZE="$3 (estimated)"
2057 PKGNUM="$4"
2058 . "$storage/receipt"
2060 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2061 Flavor : $FLAVOR
2062 Description : $SHORT_DESC
2063 Version : $VERSION
2064 Maintainer : $MAINTAINER
2065 LiveCD RAM size : $FRUGAL_RAM
2066 Rootfs list : $ROOTFS_SELECTION
2067 Build date : $(date '+%Y%m%d at %T')
2068 Packages : $PKGNUM
2069 Rootfs size : $ROOTFS_SIZE
2070 Initramfs size : $INITRAMFS_SIZE
2071 ISO image size : $ISO_SIZE
2072 ================================================================================
2074 EOT
2076 rm -f $tmp_dir/packages.list
2077 pack_flavor "$tmp_dir" "$flavor"
2078 status
2079 display_unknown "$tmp_dir/err"
2080 display_warn "$flv_dir/warn"
2081 cleanup
2082 ;;
2085 get-flavor)
2086 # Get a flavor's files and prepare for gen-distro.
2087 flavor=${2%.flavor}
2088 title 'Preparing %s distro flavor' "$flavor"
2089 set -e
2090 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2091 set +e
2093 action 'Cleaning %s...' "$DISTRO"
2094 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2095 # Clean old files
2096 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2097 [ -f "$i" ] && rm "$i"
2098 done
2099 mkdir -p "$DISTRO"
2100 status
2102 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2104 action 'Extracting flavor %s...' "$flavor.flavor"
2105 flv_dir="$(extract_flavor "$flavor" info)"
2106 cp -a "$flv_dir"/* .
2107 mv packages.list distro-packages.list
2108 mv -f info /etc/tazlito
2109 status
2111 for i in rootcd rootfs; do
2112 if [ -d "$i" ]; then
2113 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2114 fi
2115 done
2117 rm -f /etc/tazlito/rootfs.list
2118 grep -q '^Rootfs list' description &&
2119 grep '^Rootfs list' description | sed 's/.*: \(.*\)$/\1/' > /etc/tazlito/rootfs.list
2121 action 'Updating %s...' 'tazlito.conf'
2122 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2123 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2124 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2125 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2126 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2127 status
2129 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2130 cleanup
2131 ;;
2134 iso2flavor)
2135 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2136 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2138 FLAVOR=${3%.flavor}
2139 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2140 mount -o loop,ro $2 $TMP_DIR/iso
2141 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2142 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2143 ! -s $TMP_DIR/flavor/*.desc ]; then
2144 _ 'META flavors are not supported.'
2145 umount -d $TMP_DIR/iso
2146 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2147 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2148 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2149 umount -d $TMP_DIR/iso
2150 else
2151 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2152 uncompress $i | \
2153 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2154 done
2155 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2156 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2157 '/etc/slitaz-release' '/boot/rootfs.gz'
2158 umount -d $TMP_DIR/iso
2159 else
2160 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2161 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2162 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2163 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2164 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2165 umount -d $TMP_DIR/iso
2166 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2167 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2168 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2169 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2170 < $TMP_DIR/rootfs$INSTALLED.md5
2171 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2172 if [ -s $TMP_DIR/flavor/*desc ]; then
2173 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2174 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2175 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2176 for i in rootfs rootcd ; do
2177 [ -s $TMP_DIR/flavor/*.list$i ] &&
2178 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2179 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2180 done
2181 else
2182 find_flavor_rootfs $TMP_DIR/rootfs
2183 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2184 for i in rootfs rootcd ; do
2185 [ "$(ls $TMP_DIR/$i)" ] &&
2186 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2187 done
2188 unset VERSION MAINTAINER
2189 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2190 if [ -n "$DESCRIPTION" ]; then
2191 _n 'Flavor version : '; read -t 30 VERSION
2192 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2193 fi
2195 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2196 Flavor : $FLAVOR
2197 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2198 Version : ${VERSION:-1.0}
2199 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2200 LiveCD RAM size : $RAM_SIZE
2201 Build date : $BUILD_DATE
2202 Packages : $PKGCNT
2203 Rootfs size : $ROOTFS_SIZE
2204 Initramfs size : $INITRAMFS_SIZE
2205 ISO image size : $ISO_SIZE
2206 ================================================================================
2208 EOT
2209 longline "Tazlito can't detect each file installed during \
2210 a package post_install. You should extract this flavor (tazlito extract-flavor \
2211 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2212 tree and remove files generated by post_installs.
2213 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2214 repack the flavor (tazlito pack-flavor $FLAVOR)"
2215 fi
2216 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2217 fi
2218 fi
2219 rm -rf $TMP_DIR
2220 ;;
2223 gen-distro)
2224 # Generate a live distro tree with a set of packages.
2226 check_root
2227 start_time=$(date +%s)
2229 # Tazlito options: --iso or --cdrom
2230 CDROM=''
2231 [ -n "$iso" ] && CDROM="-o loop $iso"
2232 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2234 # Check if a package list was specified on cmdline.
2235 if [ -f "$2" ]; then
2236 LIST_NAME="$2"
2237 else
2238 LIST_NAME='distro-packages.list'
2239 fi
2241 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2242 'Please clean the distro tree or change directory path.'
2243 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2244 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2246 # If list not given: build list with all installed packages
2247 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2248 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2249 fi
2251 # Exit if no list name.
2252 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2254 # Start generation.
2255 title 'Tazlito generating a distro'
2257 # Misc checks
2258 mkdir -p "$PACKAGES_REPOSITORY"
2259 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2260 newline
2262 # Mount CD-ROM to be able to repack boot-loader packages
2263 if [ ! -e /boot -a -n "$CDROM" ]; then
2264 mkdir $TMP_MNT
2265 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2266 ln -s "$TMP_MNT/boot" /
2267 if [ ! -d "$ADDFILES/rootcd" ] ; then
2268 mkdir -p "$ADDFILES/rootcd"
2269 for i in $(ls $TMP_MNT); do
2270 [ "$i" == 'boot' ] && continue
2271 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2272 done
2273 fi
2274 else
2275 rmdir "$TMP_MNT"
2276 fi
2277 fi
2279 # Rootfs stuff.
2280 echo 'Preparing the rootfs directory...'
2281 mkdir -p "$ROOTFS"
2282 export root="$ROOTFS"
2283 # pass current 'mirror' to the root
2284 mkdir -p $root/var/lib/tazpkg
2285 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2286 cp -f /etc/slitaz-release $root/etc/slitaz-release
2287 strip_versions "$LIST_NAME"
2289 if [ "$REPACK" == 'y' ]; then
2290 # Determine full packages list with all dependencies
2291 tmp_dir="$(mktemp -d)"
2292 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2293 touch "$tmp_dir/full.pkglist"
2294 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2296 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2297 while read pkgname pkgver; do
2298 # Is package in full list?
2299 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2300 # Is package already repacked?
2301 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2302 _ 'Repacking %s...' "$pkgname-$pkgver"
2303 tazpkg repack "$pkgname" --quiet
2304 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2305 status
2306 done
2308 rm -r "$tmp_dir"
2309 fi
2311 if [ -f non-free.list ]; then
2312 # FIXME: working in the ROOTFS chroot?
2313 newline
2314 echo 'Preparing non-free packages...'
2315 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2316 for pkg in $(cat 'non-free.list'); do
2317 if [ ! -d "$INSTALLED/$pkg" ]; then
2318 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2319 tazpkg get-install get-$pkg
2320 fi
2321 get-$pkg "$ROOTFS"
2322 fi
2323 tazpkg repack $pkg
2324 pkg=$(ls $pkg*.tazpkg)
2325 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2326 mv $pkg $PACKAGES_REPOSITORY
2327 done
2328 fi
2329 cp $LIST_NAME $DISTRO/distro-packages.list
2330 newline
2332 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2334 cd $DISTRO
2335 cp distro-packages.list $ROOTFS/etc/tazlito
2336 # Copy all files from $ADDFILES/rootfs to the rootfs.
2337 if [ -d "$ADDFILES/rootfs" ] ; then
2338 action 'Copying addfiles content to the rootfs...'
2339 cp -a $ADDFILES/rootfs/* $ROOTFS
2340 status
2341 fi
2343 action 'Root filesystem is generated...'; status
2345 # Root CD part.
2346 action 'Preparing the rootcd directory...'
2347 mkdir -p $ROOTCD
2348 status
2350 # Move the boot dir with the Linux kernel from rootfs.
2351 # The boot dir goes directly on the CD.
2352 if [ -d "$ROOTFS/boot" ] ; then
2353 action 'Moving the boot directory...'
2354 mv $ROOTFS/boot $ROOTCD
2355 cd $ROOTCD/boot
2356 make_bzImage_hardlink
2357 status
2358 fi
2359 cd $DISTRO
2360 # Copy all files from $ADDFILES/rootcd to the rootcd.
2361 if [ -d "$ADDFILES/rootcd" ] ; then
2362 action 'Copying addfiles content to the rootcd...'
2363 cp -a $ADDFILES/rootcd/* $ROOTCD
2364 status
2365 fi
2366 # Execute the distro script used to perform tasks in the rootfs
2367 # before compression. Give rootfs path in arg
2368 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2369 if [ -x "$DISTRO_SCRIPT" ]; then
2370 echo 'Executing distro script...'
2371 sh $DISTRO_SCRIPT $DISTRO
2372 fi
2374 # Execute the custom_rules() found in receipt.
2375 if [ -s "$TOP_DIR/receipt" ]; then
2376 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2377 echo -e "Executing: custom_rules()\n"
2378 . "$TOP_DIR/receipt"
2379 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2380 fi
2381 fi
2383 # Multi-rootfs
2384 if [ -s /etc/tazlito/rootfs.list ]; then
2386 FLAVOR_LIST="$(awk '{
2387 for (i = 2; i <= NF; i+=2)
2388 printf "%s ", i;
2389 }' /etc/tazlito/rootfs.list)"
2391 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2392 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2393 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2395 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2396 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2397 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2398 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2400 n=0
2401 last=$ROOTFS
2402 while read flavor; do
2403 n=$(($n+1))
2404 mkdir ${ROOTFS}0$n
2405 export root="${ROOTFS}0$n"
2406 # initial tazpkg setup in empty rootfs
2407 tazpkg --root=$root >/dev/null 2>&1
2409 newline
2410 boldify "Building $flavor rootfs..."
2412 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2413 cp "$TOP_DIR/$flavor.flavor" .
2415 if [ ! -s "$flavor.flavor" ]; then
2416 # We may have it in $FLAVORS_REPOSITORY
2417 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2418 tazlito pack-flavor $flavor
2419 else
2420 download $flavor.flavor
2421 fi
2422 fi
2424 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2425 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2426 cp $flavor.pkglist $DISTRO/list-packages0$n
2427 status
2429 strip_versions "$DISTRO/list-packages0$n"
2431 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2433 rm -rf ${ROOTFS}0$n/boot
2435 cd $DISTRO
2436 if [ -s $flavor.rootfs ]; then
2437 _n 'Adding %s rootfs extra files...' "$flavor"
2438 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2439 fi
2441 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2442 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2443 status
2445 rm -f $flavor.flavor install-list
2446 mergefs ${ROOTFS}0$n $last
2447 last=${ROOTFS}0$n
2448 done <<EOT
2449 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2450 EOT
2451 #'
2452 i=$(($n+1))
2453 while [ $n -gt 0 ]; do
2454 mv ${ROOTFS}0$n ${ROOTFS}$i
2455 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2456 gen_initramfs ${ROOTFS}$i
2457 n=$(($n-1))
2458 i=$(($i-1))
2459 export LZMA_HISTORY_BITS=26
2460 done
2461 mv $ROOTFS ${ROOTFS}$i
2462 gen_initramfs ${ROOTFS}$i
2463 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2464 else
2465 # Initramfs and ISO image stuff.
2466 gen_initramfs $ROOTFS
2467 fi
2468 gen_livecd_isolinux
2469 distro_stats
2470 cleanup
2471 ;;
2474 clean-distro)
2475 # Remove old distro tree.
2477 check_root
2478 title 'Cleaning: %s' "$DISTRO"
2479 if [ -d "$DISTRO" ] ; then
2480 if [ -d "$ROOTFS" ] ; then
2481 action 'Removing the rootfs...'
2482 rm -f $DISTRO/$INITRAMFS
2483 rm -rf $ROOTFS
2484 status
2485 fi
2486 if [ -d "$ROOTCD" ] ; then
2487 action 'Removing the rootcd...'
2488 rm -rf $ROOTCD
2489 status
2490 fi
2491 action 'Removing eventual ISO image...'
2492 rm -f $DISTRO/$ISO_NAME.iso
2493 rm -f $DISTRO/$ISO_NAME.md5
2494 status
2495 fi
2496 footer
2497 ;;
2500 check-distro)
2501 # Check for a few LiveCD needed files not installed by packages.
2503 # TODO: Remove this function.
2504 # First two files are maintained by tazpkg while it runs on rootfs,
2505 # while last one file should be maintained by tazlito itself.
2506 check_rootfs
2507 title 'Checking distro: %s' "$ROOTFS"
2508 # SliTaz release info.
2509 rel='/etc/slitaz-release'
2510 if [ ! -f "$ROOTFS$rel" ]; then
2511 _ 'Missing release info: %s' "$rel"
2512 else
2513 action 'Release : %s' "$(cat $ROOTFS$rel)"
2514 status
2515 fi
2516 # Tazpkg mirror.
2517 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2518 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2519 todomsg
2520 else
2521 action 'Mirror configuration exists...'
2522 status
2523 fi
2524 # Isolinux msg
2525 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2526 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2527 todomsg
2528 else
2529 action 'Isolinux message seems good...'
2530 status
2531 fi
2532 footer
2533 ;;
2536 writeiso)
2537 # Writefs to ISO image including /home unlike gen-distro we don't use
2538 # packages to generate a rootfs, we build a compressed rootfs with all
2539 # the current filesystem similar to 'tazusb writefs'.
2541 DISTRO='/home/slitaz/distro'
2542 ROOTCD="$DISTRO/rootcd"
2543 COMPRESSION="${2:-none}"
2544 ISO_NAME="${3:-slitaz}"
2545 check_root
2546 # Start info
2547 title 'Write filesystem to ISO'
2548 longline "The command writeiso will write the current filesystem into a \
2549 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2550 newline
2551 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2553 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2554 # Save some space
2555 rm -rf /var/cache/tazpkg/*
2556 rm -f /var/lib/tazpkg/*.bak
2557 rm -rf $DISTRO
2559 # Optionally remove sound card selection and screen resolution.
2560 if [ -z $LaunchedByTazpanel ]; then
2561 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2562 case $anser in
2563 y)
2564 action 'Removing current sound card and screen configurations...'
2565 rm -f /var/lib/sound-card-driver
2566 rm -f /var/lib/alsa/asound.state
2567 rm -f /etc/X11/xorg.conf ;;
2568 *)
2569 action 'Keeping current sound card and screen configurations...' ;;
2570 esac
2571 status
2572 newline
2574 # Optionally remove i18n settings
2575 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2576 case $anser in
2577 y)
2578 action 'Removing current locale/keymap settings...'
2579 newline > /etc/locale.conf
2580 newline > /etc/keymap.conf ;;
2581 *)
2582 action 'Keeping current locale/keymap settings...' ;;
2583 esac
2584 status
2585 fi
2587 # Clean-up files by default
2588 newline > /etc/udev/rules.d/70-persistent-net.rules
2589 newline > /etc/udev/rules.d/70-persistant-cd.rules
2591 # Create list of files including default user files since it is defined in /etc/passwd
2592 # and some new users might have been added.
2593 cd /
2594 echo 'init' > /tmp/list
2595 for dir in bin etc sbin var dev lib root usr home opt; do
2596 [ -d $dir ] && find $dir
2597 done >> /tmp/list
2599 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2600 [ -d $dir ] && echo $dir
2601 done >> /tmp/list
2603 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2605 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2606 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2607 #fi
2608 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2609 touch /var/log/wtmp
2611 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2612 sed -i "/var\/log\/$removelog/d" /tmp/list
2613 done
2615 # Generate initramfs with specified compression and display rootfs
2616 # size in realtime.
2617 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2619 write_initramfs &
2620 sleep 2
2621 cd - > /dev/null
2622 echo -en "\nFilesystem size:"
2623 while [ ! -f /tmp/rootfs ]; do
2624 sleep 1
2625 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2626 done
2627 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2628 echo -e "\n"
2629 rm -f /tmp/rootfs
2631 # Move freshly generated rootfs to the cdrom.
2632 mkdir -p $ROOTCD/boot
2633 mv -f /$INITRAMFS $ROOTCD/boot
2634 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2636 # Now we need the kernel and isolinux files.
2637 copy_from_cd() {
2638 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2639 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2640 unmeta_boot $ROOTCD
2641 umount /media/cdrom
2644 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2645 copy_from_cd;
2646 elif mount | grep /media/cdrom; then
2647 copy_from_cd;
2648 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2649 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2650 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2651 else
2652 touch /tmp/.write-iso-error
2653 longline "When SliTaz is running in RAM the kernel and bootloader \
2654 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
2655 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
2656 echo -en "----\nENTER to continue..."; read i
2657 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2658 copy_from_cd
2659 fi
2661 # Generate the iso image.
2662 touch /tmp/.write-iso
2663 newline
2664 cd $DISTRO
2665 create_iso $ISO_NAME.iso $ROOTCD
2666 action 'Creating the ISO md5sum...'
2667 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2668 status
2670 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2671 rm -f /tmp/.write-iso
2673 if [ -z $LaunchedByTazpanel ]; then
2674 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2675 case $anser in
2676 y)
2677 umount /dev/cdrom 2>/dev/null
2678 eject
2679 echo -n "Please insert a blank CD-ROM and press ENTER..."
2680 read i && sleep 2
2681 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2682 echo -en "----\nENTER to continue..."; read i ;;
2683 *)
2684 exit 0 ;;
2685 esac
2686 fi
2687 ;;
2690 burn-iso)
2691 # Guess CD-ROM device, ask user and burn the ISO.
2693 check_root
2694 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2695 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2696 # We can specify an alternative ISO from the cmdline.
2697 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2698 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2700 title 'Tazlito burn ISO'
2701 echo "CD-ROM device : /dev/$DRIVE_NAME"
2702 echo "Drive speed : $DRIVE_SPEED"
2703 echo "ISO image : $iso"
2704 footer
2706 case $(yesorno 'Burn ISO image?' 'n') in
2707 y)
2708 title 'Starting Wodim to burn the ISO...'
2709 sleep 2
2710 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2711 footer 'ISO image is burned to CD-ROM.'
2712 ;;
2713 *)
2714 die 'Exiting. No ISO burned.'
2715 ;;
2716 esac
2717 ;;
2720 merge)
2721 # Merge multiple rootfs into one iso.
2723 if [ -z "$2" ]; then
2724 cat <<EOT
2725 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2727 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2728 i.e: rootfsN is a subset of rootfsN-1
2729 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2730 The boot loader will select the rootfs according to the RAM size detected.
2732 Example:
2733 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
2735 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
2736 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
2738 EOT
2739 exit 2
2740 fi
2742 shift # skip merge
2743 append="$1 slitaz1"
2744 shift # skip size1
2745 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
2747 ISO=$1.merged
2749 # Extract filesystems
2750 action 'Mounting %s' "$1"
2751 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
2752 status || cleanup_merge
2754 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2755 make_bzImage_hardlink $TMP_DIR/iso/boot
2756 umount -d $TMP_DIR/mnt
2757 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
2758 _ '%s is already a merged iso. Aborting.' "$1"
2759 cleanup_merge
2760 fi
2761 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
2762 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
2763 if [ ! -f /boot/isolinux/ifmem.c32 -a
2764 ! -f /boot/isolinux/c32box.c32 ]; then
2765 cat <<EOT
2766 No file /boot/isolinux/ifmem.c32
2767 Please install syslinux package !
2768 EOT
2769 rm -rf $TMP_DIR
2770 exit 1
2771 fi
2772 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
2773 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
2774 fi
2776 action 'Extracting %s' 'iso/rootfs.gz'
2777 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
2778 [ -d $TMP_DIR/rootfs1/etc ]
2779 status || cleanup_merge
2781 n=1
2782 while [ -n "$2" ]; do
2783 shift # skip rootfs N-1
2784 p=$n
2785 n=$(($n + 1))
2786 append="$append $1 slitaz$n"
2787 shift # skip size N
2788 mkdir -p $TMP_DIR/rootfs$n
2790 action 'Extracting %s' "$1"
2791 extract_rootfs $1 $TMP_DIR/rootfs$n &&
2792 [ -d "$TMP_DIR/rootfs$n/etc" ]
2793 status || cleanup_merge
2795 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
2796 action 'Creating %s' "rootfs$p.gz"
2797 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
2798 status
2799 done
2800 action 'Creating %s' "rootfs$n.gz"
2801 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
2802 status
2803 rm -f $TMP_DIR/iso/boot/rootfs.gz
2804 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
2805 create_iso $ISO $TMP_DIR/iso
2806 rm -rf $TMP_DIR
2807 ;;
2810 repack)
2811 # Repack an iso with maximum lzma compression ratio.
2813 ISO=$2
2814 mkdir -p $TMP_DIR/mnt
2816 # Extract filesystems
2817 action 'Mounting %s' "$ISO"
2818 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
2819 status || cleanup_merge
2821 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2822 umount -d $TMP_DIR/mnt
2824 for i in $TMP_DIR/iso/boot/rootfs* ; do
2825 action 'Repacking %s' "$(basename $i)"
2826 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
2827 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
2828 align_to_32bits $i
2829 status
2830 done
2832 create_iso $ISO $TMP_DIR/iso
2833 rm -rf $TMP_DIR
2834 ;;
2837 build-loram)
2838 # Build a Live CD for low RAM systems.
2840 ISO="$2"
2841 OUTPUT="$3"
2842 [ -z "$3" ] && \
2843 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
2844 mkdir -p "$TMP_DIR/iso"
2845 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
2846 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
2847 if ! check_iso_for_loram ; then
2848 umount -d "$TMP_DIR/iso"
2849 die "$ISO is not a valid SliTaz live CD. Abort."
2850 fi
2851 case "$4" in
2852 cdrom) build_loram_cdrom ;;
2853 http) build_loram_http ;;
2854 *) build_loram_ram ;;
2855 esac
2856 umount $TMP_DIR/iso # no -d: needs /proc
2857 losetup -d $loopdev
2858 rm -rf $TMP_DIR
2859 ;;
2862 emu-iso)
2863 # Emulate an ISO image with Qemu.
2864 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2865 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
2866 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
2867 echo -e "\nStarting Qemu emulator:\n"
2868 echo -e "qemu $QEMU_OPTS $iso\n"
2869 qemu $QEMU_OPTS $iso
2870 ;;
2873 deduplicate)
2874 # Deduplicate files in a tree
2875 shift
2876 deduplicate "$@"
2877 ;;
2880 usage|*)
2881 # Print usage also for all unknown commands.
2882 usage
2883 ;;
2884 esac
2886 exit 0