tazlito view tazlito @ rev 459

tazlito: pass current 'mirror' to rootfs: ISO prepared in cooking environment will be cooking, in next - will be next...
author Aleksej Bobylev <al.bobylev@gmail.com>
date Sat Aug 26 12:05:06 2017 +0300 (2017-08-26)
parents d67c38068716
children 8a23ad1f4426
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 action 'Strip versions from list %s...' "$(basename "$1")"
1480 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1481 [ -f "$in_list" ] || die "List '$in_list' not found."
1483 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1484 awk '
1486 if (FILENAME ~ "packages.info") {
1487 # Collect package names
1488 FS = "\t"; pkg[$1] = 1;
1489 } else {
1490 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1491 while (NF > 1 && ! pkg[$0])
1492 NF --;
1493 printf "%s\n", $0;
1495 }' $(pi_lists) "$in_list" > "$tmp_list"
1497 cat "$tmp_list" > "$in_list"
1498 rm "$tmp_list"
1499 status
1503 # Display list of unknown packages (informative)
1505 display_unknown() {
1506 [ -s "$1" ] || return
1507 echo "Unknown packages:" >&2
1508 cat "$1" >&2
1509 rm "$1"
1513 # Display warnings about critical packages absent (informative)
1515 display_warn() {
1516 [ -s "$1" ] || return
1517 echo "Absent critical packages:" >&2
1518 cat "$1" >&2
1519 rm "$1"
1520 echo "Probably ISO image will be unusable."
1524 # Install packages to rootfs
1526 install_list_to_rootfs() {
1527 local list="$1" rootfs="$2" pkg i ii
1528 local undigest="$rootfs/var/lib/tazpkg/undigest"
1530 # initial tazpkg setup in empty rootfs
1531 tazpkg --root=$rootfs >/dev/null 2>&1
1532 # pass current 'mirror' to the rootfs
1533 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
1534 # link rootfs packages cache to the regular packages cache
1535 rm -r "$rootfs/var/cache/tazpkg"
1536 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1538 setup_mirrors mirrors
1540 # Just in case if flavor not contains "tazlito" package
1541 mkdir -p "$rootfs/etc/tazlito"
1543 newline
1544 for pkg in $(cat $list); do
1545 action 'Installing package: %s' "$pkg"
1546 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1547 status
1548 done
1549 newline
1551 restore_mirrors
1552 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1553 for i in fresh repacked; do
1554 ii="$undigest/$i"
1555 [ -d "$ii" ] && rm -rf "$ii"
1556 ii="$rootfs/var/lib/tazpkg/priority"
1557 if [ -f "$ii" ]; then
1558 sed -i "/$i/d" "$ii"
1559 [ -s "$ii" ] || rm "$ii"
1560 fi
1561 done
1562 [ -d "$undigest" ] && \
1563 for i in $(find "$undigest" -type f); do
1564 # Remove all undigest PKGDB files but 'mirror'
1565 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1566 done
1567 [ -d "$undigest" ] && \
1568 rmdir --ignore-fail-on-non-empty "$undigest"
1570 # Un-link packages cache
1571 rm "$rootfs/var/cache/tazpkg"
1573 # Clean /var/lib/tazpkg
1574 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1580 ####################
1581 # Tazlito commands #
1582 ####################
1584 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1585 case "$0" in
1586 *reduplicate)
1587 find ${@:-.} ! -type d -links +1 \
1588 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1589 exit 0 ;;
1590 *deduplicate)
1591 deduplicate "$@"
1592 exit 0 ;;
1593 esac
1596 case "$COMMAND" in
1597 stats)
1598 # Tazlito general statistics from the config file.
1600 title 'Tazlito statistics'
1601 optlist "\
1602 Config file : $CONFIG_FILE
1603 ISO name : $ISO_NAME.iso
1604 Volume name : $VOLUM_NAME
1605 Prepared : $PREPARED
1606 Packages repository : $PACKAGES_REPOSITORY
1607 Distro directory : $DISTRO
1608 Additional files : $ADDFILES
1609 " | sed '/: $/d'
1610 footer
1611 ;;
1614 list-addfiles)
1615 # Simple list of additional files in the rootfs
1616 newline
1617 if [ -d "$ADDFILES/rootfs" ]; then
1618 cd $ADDFILES
1619 find rootfs -type f
1620 else
1621 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1622 fi
1623 newline
1624 ;;
1627 gen-config)
1628 # Generate a new config file in the current dir or the specified
1629 # directory by $2.
1631 if [ -n "$2" ]; then
1632 mkdir -p "$2" && cd "$2"
1633 fi
1635 newline
1636 action 'Generating empty tazlito.conf...'
1637 empty_config_file
1638 status
1640 separator
1641 if [ -f 'tazlito.conf' ] ; then
1642 _ 'Configuration file is ready to edit.'
1643 _ 'File location: %s' "$(pwd)/tazlito.conf"
1644 newline
1645 fi
1646 ;;
1649 configure)
1650 # Configure a tazlito.conf config file. Start by getting
1651 # a empty config file and sed it.
1653 if [ -f 'tazlito.conf' ]; then
1654 rm tazlito.conf
1655 else
1656 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1657 'or in the same directory of the file you want to configure.'
1658 cd /etc
1659 fi
1661 empty_config_file
1663 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1665 # ISO name.
1666 echo -n "ISO name : " ; read answer
1667 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1668 # Volume name.
1669 echo -n "Volume name : " ; read answer
1670 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1671 # Packages repository.
1672 echo -n "Packages repository : " ; read answer
1673 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1674 # Distro path.
1675 echo -n "Distro path : " ; read answer
1676 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1677 footer "Config file is ready to use."
1678 echo 'You can now extract an ISO or generate a distro.'
1679 newline
1680 ;;
1683 gen-iso)
1684 # Simply generate a new iso.
1686 check_root
1687 verify_rootcd
1688 gen_livecd_isolinux
1689 distro_stats
1690 ;;
1693 gen-initiso)
1694 # Simply generate a new initramfs with a new iso.
1696 check_root
1697 verify_rootcd
1698 gen_initramfs "$ROOTFS"
1699 gen_livecd_isolinux
1700 distro_stats
1701 ;;
1704 extract-distro)
1705 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1707 check_root
1708 ISO_IMAGE="$2"
1709 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1710 'Example:\n tazlito image.iso /path/target'
1712 # Set the distro path by checking for $3 on cmdline.
1713 TARGET="${3:-$DISTRO}"
1715 # Exit if existing distro is found.
1716 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1717 'Please clean the distro tree or change directory path.'
1719 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
1721 # Start to mount the ISO.
1722 action 'Mounting ISO image...'
1723 mkdir -p "$TMP_DIR"
1724 # Get ISO file size.
1725 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
1726 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
1727 sleep 2
1728 # Prepare target dir, copy the kernel and the rootfs.
1729 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
1730 status
1732 action 'Copying the Linux kernel...'
1733 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
1734 make_bzImage_hardlink "$TARGET/rootcd/boot"
1735 else
1736 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
1737 fi
1738 status
1740 for i in $(ls $TMP_DIR); do
1741 [ "$i" == 'boot' ] && continue
1742 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
1743 done
1745 for loader in isolinux syslinux extlinux grub; do
1746 [ -d "$TMP_DIR/boot/$loader" ] || continue
1747 action 'Copying %s files...' "$loader"
1748 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
1749 status
1750 done
1752 action 'Copying the rootfs...'
1753 cp $TMP_DIR/boot/rootfs.?z "$TARGET/rootcd/boot"
1754 status
1756 # Extract initramfs.
1757 cd "$TARGET/rootfs"
1758 action 'Extracting the rootfs...'
1759 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
1760 # unpack /usr
1761 for i in etc/tazlito/*.extract; do
1762 [ -f "$i" ] && . $i ../rootcd
1763 done
1764 # Umount and remove temp directory and cd to $TARGET to get stats.
1765 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
1766 cd ..
1767 status
1769 newline
1770 separator
1771 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
1772 echo "Distro tree : $(pwd)"
1773 echo "Rootfs size : $(du -sh rootfs)"
1774 echo "Rootcd size : $(du -sh rootcd)"
1775 footer
1776 ;;
1779 list-flavors)
1780 # Show available flavors.
1781 list='/etc/tazlito/flavors.list'
1782 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
1783 title 'List of flavors'
1784 cat $list
1785 footer
1786 ;;
1789 show-flavor)
1790 # Show flavor description.
1791 set -e
1792 flavor=${2%.flavor}
1793 flv_dir="$(extract_flavor "$flavor")"
1794 desc="$flv_dir/$flavor.desc"
1795 if [ -n "$brief" ]; then
1796 if [ -z "$noheader" ]; then
1797 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
1798 separator
1799 fi
1800 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
1801 "$(field ISO "$desc")" \
1802 "$(field Rootfs "$desc")" \
1803 "$(field Description "$desc")"
1804 else
1805 separator
1806 cat "$desc"
1807 fi
1808 cleanup
1809 ;;
1812 gen-liveflavor)
1813 # Generate a new flavor from the live system.
1814 FLAVOR=${2%.flavor}
1815 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1817 case "$FLAVOR" in
1818 -?|-h*|--help)
1819 cat <<EOT
1820 SliTaz Live Tool - Version: $VERSION
1822 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
1824 $(boldify '<flavor-patch-file> format:')
1825 $(optlist "\
1826 code data
1827 + package to add
1828 - package to remove
1829 ! non-free package to add
1830 ? display message
1831 @ flavor description
1832 ")
1834 $(boldify 'Example:')
1835 $(optlist "\
1836 @ Developer tools for SliTaz maintainers
1837 + slitaz-toolchain
1838 + mercurial
1839 ")
1840 EOT
1841 exit 1
1842 ;;
1843 esac
1844 mv /etc/tazlito/distro-packages.list \
1845 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
1846 rm -f distro-packages.list non-free.list 2>/dev/null
1847 tazpkg recharge
1849 DESC=""
1850 [ -n "$3" ] && \
1851 while read action pkg; do
1852 case "$action" in
1853 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
1854 -) yes | tazpkg remove $pkg ;;
1855 !) echo $pkg >> non-free.list ;;
1856 @) DESC="$pkg" ;;
1857 \?) echo -en "$pkg"; read action ;;
1858 esac
1859 done < $3
1861 yes '' | tazlito gen-distro
1862 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
1863 mv /etc/tazlito/distro-packages.list.$$ \
1864 /etc/tazlito/distro-packages.list 2>/dev/null
1865 ;;
1868 gen-flavor)
1869 # Generate a new flavor from the last ISO image generated
1870 FLAVOR=${2%.flavor}
1871 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1873 title 'Flavor generation'
1874 check_rootfs
1875 FILES="$FLAVOR.pkglist"
1877 action 'Creating file %s...' "$FLAVOR.flavor"
1878 for i in rootcd rootfs; do
1879 if [ -d "$ADDFILES/$i" ] ; then
1880 FILES="$FILES\n$FLAVOR.$i"
1881 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
1882 fi
1883 done
1884 status
1886 answer=$(grep -s ^Description $FLAVOR.desc)
1887 answer=${answer#Description : }
1888 if [ -z "$answer" ]; then
1889 echo -n "Description: "
1890 read answer
1891 fi
1893 action 'Compressing flavor %s...' "$FLAVOR"
1894 echo "Flavor : $FLAVOR" > $FLAVOR.desc
1895 echo "Description : $answer" >> $FLAVOR.desc
1896 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
1897 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
1898 for i in $(ls $ROOTFS$INSTALLED); do
1899 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
1900 EXTRAVERSION=""
1901 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
1902 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
1903 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
1904 echo "$i" >> $FLAVOR.nonfree
1905 else
1906 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
1907 fi
1908 done
1909 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
1910 for i in $LOCALSTATE/undigest/*/mirror ; do
1911 [ -s $i ] && cat $i >> $FLAVOR.mirrors
1912 done
1913 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
1914 touch -t 197001010100.00 $FLAVOR.*
1915 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
1916 rm $(echo -e $FILES)
1917 status
1919 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
1920 ;;
1923 upgrade-flavor)
1924 # Strip versions from pkglist and update estimated numbers in flavor.desc
1925 flavor="${2%.flavor}"
1926 set -e
1927 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1928 set +e
1930 flv_dir="$(extract_flavor "$flavor")"
1932 strip_versions "$flv_dir/$flavor.pkglist"
1934 action 'Updating %s...' "$flavor.desc"
1936 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
1937 set -- $(module calc_sizes "$flv_dir" "$flavor")
1938 restore_mirrors >/dev/null
1940 sed -i -e '/Image is ready/d' \
1941 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
1942 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
1943 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
1944 -e "s|\(Packages *:\).*$|\1 $4|" \
1945 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
1946 "$flv_dir/$flavor.desc"
1948 pack_flavor "$flv_dir" "$flavor"
1949 status
1950 display_unknown "$flv_dir/err"
1951 display_warn "$flv_dir/warn"
1952 cleanup
1953 ;;
1956 extract-flavor)
1957 # Extract a flavor into $FLAVORS_REPOSITORY
1958 flavor="${2%.flavor}"
1959 set -e
1960 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1961 set +e
1963 action 'Extracting %s...' "$flavor.flavor"
1964 flv_dir="$(extract_flavor "$flavor" full)"
1965 storage="$FLAVORS_REPOSITORY/$flavor"
1967 rm -rf "$storage" 2>/dev/null
1968 mkdir -p "$storage"
1969 cp -a "$flv_dir"/* "$storage"
1970 rm "$storage/description"
1971 status
1973 strip_versions "$storage/packages.list"
1975 cleanup
1976 ;;
1979 pack-flavor)
1980 # Create a flavor from $FLAVORS_REPOSITORY.
1981 flavor=${2%.flavor}
1982 storage="$FLAVORS_REPOSITORY/$flavor"
1984 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
1986 action 'Creating flavor %s...' "$flavor"
1987 tmp_dir="$(mktemp -d)"
1989 while read from to; do
1990 [ -s "$storage/$from" ] || continue
1991 cp -a "$storage/$from" "$tmp_dir/$to"
1992 done <<EOT
1993 mirrors $flavor.mirrors
1994 distro.sh $flavor-distro.sh
1995 receipt $flavor.receipt
1996 non-free.list $flavor.nonfree
1997 EOT
1999 # Build the package list.
2000 # It can include a list from another flavor with the keyword @include
2001 if [ -s "$storage/packages.list" ]; then
2002 include=$(grep '^@include' "$storage/packages.list")
2003 if [ -n "$include" ]; then
2004 include=${include#@include }
2005 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2006 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2007 else
2008 echo -e "\nERROR: Can't find include package list from $include\n"
2009 fi
2010 fi
2011 # Generate the final/initial package list
2012 [ -s "$storage/packages.list" ] && \
2013 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2014 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2015 fi
2017 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2018 # Process multi-rootfs flavor
2019 . "$storage/receipt"
2020 set -- $ROOTFS_SELECTION
2021 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2022 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2023 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2025 for i in rootcd rootfs; do
2026 mkdir "$tmp_dir/$i"
2027 # Copy extra files from the first flavor
2028 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2029 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2030 # Overload extra files by meta flavor
2031 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2032 [ -n "$(ls $tmp_dir/$i)" ] &&
2033 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2034 dogzip "$tmp_dir/$flavor.$i"
2035 rm -rf "$tmp_dir/$i"
2036 done
2037 else
2038 # Process plain flavor
2039 for i in rootcd rootfs; do
2040 [ -d "$storage/$i" ] || continue
2041 (cd "$storage/$i";
2042 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2043 done
2044 fi
2046 unset VERSION MAINTAINER ROOTFS_SELECTION
2047 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2048 ROOTFS_SIZE="$1 (estimated)"
2049 INITRAMFS_SIZE="$2 (estimated)"
2050 ISO_SIZE="$3 (estimated)"
2051 PKGNUM="$4"
2052 . "$storage/receipt"
2054 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2055 Flavor : $FLAVOR
2056 Description : $SHORT_DESC
2057 Version : $VERSION
2058 Maintainer : $MAINTAINER
2059 LiveCD RAM size : $FRUGAL_RAM
2060 Rootfs list : $ROOTFS_SELECTION
2061 Build date : $(date '+%Y%m%d at %T')
2062 Packages : $PKGNUM
2063 Rootfs size : $ROOTFS_SIZE
2064 Initramfs size : $INITRAMFS_SIZE
2065 ISO image size : $ISO_SIZE
2066 ================================================================================
2068 EOT
2070 rm -f $tmp_dir/packages.list
2071 pack_flavor "$tmp_dir" "$flavor"
2072 status
2073 display_unknown "$tmp_dir/err"
2074 display_warn "$flv_dir/warn"
2075 cleanup
2076 ;;
2079 get-flavor)
2080 # Get a flavor's files and prepare for gen-distro.
2081 flavor=${2%.flavor}
2082 title 'Preparing %s distro flavor' "$flavor"
2083 set -e
2084 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2085 set +e
2087 action 'Cleaning %s...' "$DISTRO"
2088 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2089 # Clean old files
2090 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2091 [ -f "$i" ] && rm "$i"
2092 done
2093 mkdir -p "$DISTRO"
2094 status
2096 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2098 action 'Extracting flavor %s...' "$flavor.flavor"
2099 flv_dir="$(extract_flavor "$flavor" info)"
2100 cp -a "$flv_dir"/* .
2101 mv packages.list distro-packages.list
2102 mv -f info /etc/tazlito
2103 status
2105 for i in rootcd rootfs; do
2106 if [ -d "$i" ]; then
2107 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2108 fi
2109 done
2111 rm -f /etc/tazlito/rootfs.list
2112 grep -q '^Rootfs list' description &&
2113 grep '^Rootfs list' description | sed 's/.*: \(.*\)$/\1/' > /etc/tazlito/rootfs.list
2115 action 'Updating %s...' 'tazlito.conf'
2116 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2117 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2118 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2119 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2120 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2121 status
2123 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2124 cleanup
2125 ;;
2128 iso2flavor)
2129 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2130 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2132 FLAVOR=${3%.flavor}
2133 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2134 mount -o loop,ro $2 $TMP_DIR/iso
2135 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2136 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2137 ! -s $TMP_DIR/flavor/*.desc ]; then
2138 _ 'META flavors are not supported.'
2139 umount -d $TMP_DIR/iso
2140 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2141 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2142 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2143 umount -d $TMP_DIR/iso
2144 else
2145 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2146 uncompress $i | \
2147 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2148 done
2149 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2150 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2151 '/etc/slitaz-release' '/boot/rootfs.gz'
2152 umount -d $TMP_DIR/iso
2153 else
2154 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2155 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2156 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2157 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2158 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2159 umount -d $TMP_DIR/iso
2160 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2161 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2162 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2163 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2164 < $TMP_DIR/rootfs$INSTALLED.md5
2165 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2166 if [ -s $TMP_DIR/flavor/*desc ]; then
2167 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2168 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2169 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2170 for i in rootfs rootcd ; do
2171 [ -s $TMP_DIR/flavor/*.list$i ] &&
2172 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2173 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2174 done
2175 else
2176 find_flavor_rootfs $TMP_DIR/rootfs
2177 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2178 for i in rootfs rootcd ; do
2179 [ "$(ls $TMP_DIR/$i)" ] &&
2180 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2181 done
2182 unset VERSION MAINTAINER
2183 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2184 if [ -n "$DESCRIPTION" ]; then
2185 _n 'Flavor version : '; read -t 30 VERSION
2186 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2187 fi
2189 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2190 Flavor : $FLAVOR
2191 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2192 Version : ${VERSION:-1.0}
2193 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2194 LiveCD RAM size : $RAM_SIZE
2195 Build date : $BUILD_DATE
2196 Packages : $PKGCNT
2197 Rootfs size : $ROOTFS_SIZE
2198 Initramfs size : $INITRAMFS_SIZE
2199 ISO image size : $ISO_SIZE
2200 ================================================================================
2202 EOT
2203 longline "Tazlito can't detect each file installed during \
2204 a package post_install. You should extract this flavor (tazlito extract-flavor \
2205 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2206 tree and remove files generated by post_installs.
2207 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2208 repack the flavor (tazlito pack-flavor $FLAVOR)"
2209 fi
2210 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2211 fi
2212 fi
2213 rm -rf $TMP_DIR
2214 ;;
2217 gen-distro)
2218 # Generate a live distro tree with a set of packages.
2220 check_root
2221 start_time=$(date +%s)
2223 # Tazlito options: --iso or --cdrom
2224 CDROM=''
2225 [ -n "$iso" ] && CDROM="-o loop $iso"
2226 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2228 # Check if a package list was specified on cmdline.
2229 if [ -f "$2" ]; then
2230 LIST_NAME="$2"
2231 else
2232 LIST_NAME='distro-packages.list'
2233 fi
2235 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2236 'Please clean the distro tree or change directory path.'
2237 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2238 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2240 # If list not given: build list with all installed packages
2241 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2242 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2243 fi
2245 # Exit if no list name.
2246 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2248 # Start generation.
2249 title 'Tazlito generating a distro'
2251 # Misc checks
2252 mkdir -p "$PACKAGES_REPOSITORY"
2253 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2254 newline
2256 # Mount CD-ROM to be able to repack boot-loader packages
2257 if [ ! -e /boot -a -n "$CDROM" ]; then
2258 mkdir $TMP_MNT
2259 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2260 ln -s "$TMP_MNT/boot" /
2261 if [ ! -d "$ADDFILES/rootcd" ] ; then
2262 mkdir -p "$ADDFILES/rootcd"
2263 for i in $(ls $TMP_MNT); do
2264 [ "$i" == 'boot' ] && continue
2265 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2266 done
2267 fi
2268 else
2269 rmdir "$TMP_MNT"
2270 fi
2271 fi
2273 # Rootfs stuff.
2274 echo 'Preparing the rootfs directory...'
2275 mkdir -p "$ROOTFS"
2276 export root="$ROOTFS"
2277 # pass current 'mirror' to the root
2278 mkdir -p $root/var/lib/tazpkg
2279 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2280 strip_versions "$LIST_NAME"
2282 if [ "$REPACK" == 'y' ]; then
2283 # Determine full packages list with all dependencies
2284 tmp_dir="$(mktemp -d)"
2285 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2286 touch "$tmp_dir/full.pkglist"
2287 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2289 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2290 while read pkgname pkgver; do
2291 # Is package in full list?
2292 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2293 # Is package already repacked?
2294 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2295 _ 'Repacking %s...' "$pkgname-$pkgver"
2296 tazpkg repack "$pkgname" --quiet
2297 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2298 status
2299 done
2301 rm -r "$tmp_dir"
2302 fi
2304 if [ -f non-free.list ]; then
2305 # FIXME: working in the ROOTFS chroot?
2306 newline
2307 echo 'Preparing non-free packages...'
2308 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2309 for pkg in $(cat 'non-free.list'); do
2310 if [ ! -d "$INSTALLED/$pkg" ]; then
2311 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2312 tazpkg get-install get-$pkg
2313 fi
2314 get-$pkg "$ROOTFS"
2315 fi
2316 tazpkg repack $pkg
2317 pkg=$(ls $pkg*.tazpkg)
2318 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2319 mv $pkg $PACKAGES_REPOSITORY
2320 done
2321 fi
2322 cp $LIST_NAME $DISTRO/distro-packages.list
2323 newline
2325 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2327 cd $DISTRO
2328 cp distro-packages.list $ROOTFS/etc/tazlito
2329 # Copy all files from $ADDFILES/rootfs to the rootfs.
2330 if [ -d "$ADDFILES/rootfs" ] ; then
2331 action 'Copying addfiles content to the rootfs...'
2332 cp -a $ADDFILES/rootfs/* $ROOTFS
2333 status
2334 fi
2336 action 'Root filesystem is generated...'; status
2338 # Root CD part.
2339 action 'Preparing the rootcd directory...'
2340 mkdir -p $ROOTCD
2341 status
2343 # Move the boot dir with the Linux kernel from rootfs.
2344 # The boot dir goes directly on the CD.
2345 if [ -d "$ROOTFS/boot" ] ; then
2346 action 'Moving the boot directory...'
2347 mv $ROOTFS/boot $ROOTCD
2348 cd $ROOTCD/boot
2349 make_bzImage_hardlink
2350 status
2351 fi
2352 cd $DISTRO
2353 # Copy all files from $ADDFILES/rootcd to the rootcd.
2354 if [ -d "$ADDFILES/rootcd" ] ; then
2355 action 'Copying addfiles content to the rootcd...'
2356 cp -a $ADDFILES/rootcd/* $ROOTCD
2357 status
2358 fi
2359 # Execute the distro script used to perform tasks in the rootfs
2360 # before compression. Give rootfs path in arg
2361 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2362 if [ -x "$DISTRO_SCRIPT" ]; then
2363 echo 'Executing distro script...'
2364 sh $DISTRO_SCRIPT $DISTRO
2365 fi
2367 # Execute the custom_rules() found in receipt.
2368 if [ -s "$TOP_DIR/receipt" ]; then
2369 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2370 echo -e "Executing: custom_rules()\n"
2371 . "$TOP_DIR/receipt"
2372 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2373 fi
2374 fi
2376 # Multi-rootfs
2377 if [ -s /etc/tazlito/rootfs.list ]; then
2379 FLAVOR_LIST="$(awk '{
2380 for (i = 2; i <= NF; i+=2)
2381 printf "%s ", i;
2382 }' /etc/tazlito/rootfs.list)"
2384 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2385 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2386 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2388 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2389 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2390 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2391 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2393 n=0
2394 last=$ROOTFS
2395 while read flavor; do
2396 n=$(($n+1))
2397 mkdir ${ROOTFS}0$n
2398 export root="${ROOTFS}0$n"
2399 # initial tazpkg setup in empty rootfs
2400 tazpkg --root=$root >/dev/null 2>&1
2402 newline
2403 boldify "Building $flavor rootfs..."
2405 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2406 cp "$TOP_DIR/$flavor.flavor" .
2408 if [ ! -s "$flavor.flavor" ]; then
2409 # We may have it in $FLAVORS_REPOSITORY
2410 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2411 tazlito pack-flavor $flavor
2412 else
2413 download $flavor.flavor
2414 fi
2415 fi
2417 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2418 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2419 cp $flavor.pkglist $DISTRO/list-packages0$n
2420 status
2422 strip_versions "$DISTRO/list-packages0$n"
2424 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2426 rm -rf ${ROOTFS}0$n/boot
2428 cd $DISTRO
2429 if [ -s $flavor.rootfs ]; then
2430 _n 'Adding %s rootfs extra files...' "$flavor"
2431 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2432 fi
2434 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2435 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2436 status
2438 rm -f $flavor.flavor install-list
2439 mergefs ${ROOTFS}0$n $last
2440 last=${ROOTFS}0$n
2441 done <<EOT
2442 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2443 EOT
2444 #'
2445 i=$(($n+1))
2446 while [ $n -gt 0 ]; do
2447 mv ${ROOTFS}0$n ${ROOTFS}$i
2448 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2449 gen_initramfs ${ROOTFS}$i
2450 n=$(($n-1))
2451 i=$(($i-1))
2452 export LZMA_HISTORY_BITS=26
2453 done
2454 mv $ROOTFS ${ROOTFS}$i
2455 gen_initramfs ${ROOTFS}$i
2456 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2457 else
2458 # Initramfs and ISO image stuff.
2459 gen_initramfs $ROOTFS
2460 fi
2461 gen_livecd_isolinux
2462 distro_stats
2463 cleanup
2464 ;;
2467 clean-distro)
2468 # Remove old distro tree.
2470 check_root
2471 title 'Cleaning: %s' "$DISTRO"
2472 if [ -d "$DISTRO" ] ; then
2473 if [ -d "$ROOTFS" ] ; then
2474 action 'Removing the rootfs...'
2475 rm -f $DISTRO/$INITRAMFS
2476 rm -rf $ROOTFS
2477 status
2478 fi
2479 if [ -d "$ROOTCD" ] ; then
2480 action 'Removing the rootcd...'
2481 rm -rf $ROOTCD
2482 status
2483 fi
2484 action 'Removing eventual ISO image...'
2485 rm -f $DISTRO/$ISO_NAME.iso
2486 rm -f $DISTRO/$ISO_NAME.md5
2487 status
2488 fi
2489 footer
2490 ;;
2493 check-distro)
2494 # Check for a few LiveCD needed files not installed by packages.
2496 # TODO: Remove this function.
2497 # First two files are maintained by tazpkg while it runs on rootfs,
2498 # while last one file should be maintained by tazlito itself.
2499 check_rootfs
2500 title 'Checking distro: %s' "$ROOTFS"
2501 # SliTaz release info.
2502 rel='/etc/slitaz-release'
2503 if [ ! -f "$ROOTFS$rel" ]; then
2504 _ 'Missing release info: %s' "$rel"
2505 else
2506 action 'Release : %s' "$(cat $ROOTFS$rel)"
2507 status
2508 fi
2509 # Tazpkg mirror.
2510 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2511 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2512 todomsg
2513 else
2514 action 'Mirror configuration exists...'
2515 status
2516 fi
2517 # Isolinux msg
2518 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2519 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2520 todomsg
2521 else
2522 action 'Isolinux message seems good...'
2523 status
2524 fi
2525 footer
2526 ;;
2529 writeiso)
2530 # Writefs to ISO image including /home unlike gen-distro we don't use
2531 # packages to generate a rootfs, we build a compressed rootfs with all
2532 # the current filesystem similar to 'tazusb writefs'.
2534 DISTRO='/home/slitaz/distro'
2535 ROOTCD="$DISTRO/rootcd"
2536 COMPRESSION="${2:-none}"
2537 ISO_NAME="${3:-slitaz}"
2538 check_root
2539 # Start info
2540 title 'Write filesystem to ISO'
2541 longline "The command writeiso will write the current filesystem into a \
2542 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2543 newline
2544 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2546 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2547 # Save some space
2548 rm -rf /var/cache/tazpkg/*
2549 rm -f /var/lib/tazpkg/*.bak
2550 rm -rf $DISTRO
2552 # Optionally remove sound card selection and screen resolution.
2553 if [ -z $LaunchedByTazpanel ]; then
2554 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2555 case $anser in
2556 y)
2557 action 'Removing current sound card and screen configurations...'
2558 rm -f /var/lib/sound-card-driver
2559 rm -f /var/lib/alsa/asound.state
2560 rm -f /etc/X11/xorg.conf ;;
2561 *)
2562 action 'Keeping current sound card and screen configurations...' ;;
2563 esac
2564 status
2565 newline
2567 # Optionally remove i18n settings
2568 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2569 case $anser in
2570 y)
2571 action 'Removing current locale/keymap settings...'
2572 newline > /etc/locale.conf
2573 newline > /etc/keymap.conf ;;
2574 *)
2575 action 'Keeping current locale/keymap settings...' ;;
2576 esac
2577 status
2578 fi
2580 # Clean-up files by default
2581 newline > /etc/udev/rules.d/70-persistent-net.rules
2582 newline > /etc/udev/rules.d/70-persistant-cd.rules
2584 # Create list of files including default user files since it is defined in /etc/passwd
2585 # and some new users might have been added.
2586 cd /
2587 echo 'init' > /tmp/list
2588 for dir in bin etc sbin var dev lib root usr home opt; do
2589 [ -d $dir ] && find $dir
2590 done >> /tmp/list
2592 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2593 [ -d $dir ] && echo $dir
2594 done >> /tmp/list
2596 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2598 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2599 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2600 #fi
2601 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2602 touch /var/log/wtmp
2604 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2605 sed -i "/var\/log\/$removelog/d" /tmp/list
2606 done
2608 # Generate initramfs with specified compression and display rootfs
2609 # size in realtime.
2610 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2612 write_initramfs &
2613 sleep 2
2614 cd - > /dev/null
2615 echo -en "\nFilesystem size:"
2616 while [ ! -f /tmp/rootfs ]; do
2617 sleep 1
2618 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2619 done
2620 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2621 echo -e "\n"
2622 rm -f /tmp/rootfs
2624 # Move freshly generated rootfs to the cdrom.
2625 mkdir -p $ROOTCD/boot
2626 mv -f /$INITRAMFS $ROOTCD/boot
2627 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2629 # Now we need the kernel and isolinux files.
2630 copy_from_cd() {
2631 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2632 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2633 unmeta_boot $ROOTCD
2634 umount /media/cdrom
2637 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2638 copy_from_cd;
2639 elif mount | grep /media/cdrom; then
2640 copy_from_cd;
2641 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2642 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2643 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2644 else
2645 touch /tmp/.write-iso-error
2646 longline "When SliTaz is running in RAM the kernel and bootloader \
2647 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
2648 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
2649 echo -en "----\nENTER to continue..."; read i
2650 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2651 copy_from_cd
2652 fi
2654 # Generate the iso image.
2655 touch /tmp/.write-iso
2656 newline
2657 cd $DISTRO
2658 create_iso $ISO_NAME.iso $ROOTCD
2659 action 'Creating the ISO md5sum...'
2660 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2661 status
2663 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2664 rm -f /tmp/.write-iso
2666 if [ -z $LaunchedByTazpanel ]; then
2667 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2668 case $anser in
2669 y)
2670 umount /dev/cdrom 2>/dev/null
2671 eject
2672 echo -n "Please insert a blank CD-ROM and press ENTER..."
2673 read i && sleep 2
2674 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2675 echo -en "----\nENTER to continue..."; read i ;;
2676 *)
2677 exit 0 ;;
2678 esac
2679 fi
2680 ;;
2683 burn-iso)
2684 # Guess CD-ROM device, ask user and burn the ISO.
2686 check_root
2687 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2688 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2689 # We can specify an alternative ISO from the cmdline.
2690 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2691 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2693 title 'Tazlito burn ISO'
2694 echo "CD-ROM device : /dev/$DRIVE_NAME"
2695 echo "Drive speed : $DRIVE_SPEED"
2696 echo "ISO image : $iso"
2697 footer
2699 case $(yesorno 'Burn ISO image?' 'n') in
2700 y)
2701 title 'Starting Wodim to burn the ISO...'
2702 sleep 2
2703 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2704 footer 'ISO image is burned to CD-ROM.'
2705 ;;
2706 *)
2707 die 'Exiting. No ISO burned.'
2708 ;;
2709 esac
2710 ;;
2713 merge)
2714 # Merge multiple rootfs into one iso.
2716 if [ -z "$2" ]; then
2717 cat <<EOT
2718 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2720 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2721 i.e: rootfsN is a subset of rootfsN-1
2722 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2723 The boot loader will select the rootfs according to the RAM size detected.
2725 Example:
2726 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
2728 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
2729 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
2731 EOT
2732 exit 2
2733 fi
2735 shift # skip merge
2736 append="$1 slitaz1"
2737 shift # skip size1
2738 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
2740 ISO=$1.merged
2742 # Extract filesystems
2743 action 'Mounting %s' "$1"
2744 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
2745 status || cleanup_merge
2747 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2748 make_bzImage_hardlink $TMP_DIR/iso/boot
2749 umount -d $TMP_DIR/mnt
2750 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
2751 _ '%s is already a merged iso. Aborting.' "$1"
2752 cleanup_merge
2753 fi
2754 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
2755 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
2756 if [ ! -f /boot/isolinux/ifmem.c32 -a
2757 ! -f /boot/isolinux/c32box.c32 ]; then
2758 cat <<EOT
2759 No file /boot/isolinux/ifmem.c32
2760 Please install syslinux package !
2761 EOT
2762 rm -rf $TMP_DIR
2763 exit 1
2764 fi
2765 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
2766 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
2767 fi
2769 action 'Extracting %s' 'iso/rootfs.gz'
2770 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
2771 [ -d $TMP_DIR/rootfs1/etc ]
2772 status || cleanup_merge
2774 n=1
2775 while [ -n "$2" ]; do
2776 shift # skip rootfs N-1
2777 p=$n
2778 n=$(($n + 1))
2779 append="$append $1 slitaz$n"
2780 shift # skip size N
2781 mkdir -p $TMP_DIR/rootfs$n
2783 action 'Extracting %s' "$1"
2784 extract_rootfs $1 $TMP_DIR/rootfs$n &&
2785 [ -d "$TMP_DIR/rootfs$n/etc" ]
2786 status || cleanup_merge
2788 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
2789 action 'Creating %s' "rootfs$p.gz"
2790 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
2791 status
2792 done
2793 action 'Creating %s' "rootfs$n.gz"
2794 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
2795 status
2796 rm -f $TMP_DIR/iso/boot/rootfs.gz
2797 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
2798 create_iso $ISO $TMP_DIR/iso
2799 rm -rf $TMP_DIR
2800 ;;
2803 repack)
2804 # Repack an iso with maximum lzma compression ratio.
2806 ISO=$2
2807 mkdir -p $TMP_DIR/mnt
2809 # Extract filesystems
2810 action 'Mounting %s' "$ISO"
2811 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
2812 status || cleanup_merge
2814 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2815 umount -d $TMP_DIR/mnt
2817 for i in $TMP_DIR/iso/boot/rootfs* ; do
2818 action 'Repacking %s' "$(basename $i)"
2819 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
2820 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
2821 align_to_32bits $i
2822 status
2823 done
2825 create_iso $ISO $TMP_DIR/iso
2826 rm -rf $TMP_DIR
2827 ;;
2830 build-loram)
2831 # Build a Live CD for low RAM systems.
2833 ISO="$2"
2834 OUTPUT="$3"
2835 [ -z "$3" ] && \
2836 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
2837 mkdir -p "$TMP_DIR/iso"
2838 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
2839 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
2840 if ! check_iso_for_loram ; then
2841 umount -d "$TMP_DIR/iso"
2842 die "$ISO is not a valid SliTaz live CD. Abort."
2843 fi
2844 case "$4" in
2845 cdrom) build_loram_cdrom ;;
2846 http) build_loram_http ;;
2847 *) build_loram_ram ;;
2848 esac
2849 umount $TMP_DIR/iso # no -d: needs /proc
2850 losetup -d $loopdev
2851 rm -rf $TMP_DIR
2852 ;;
2855 emu-iso)
2856 # Emulate an ISO image with Qemu.
2857 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2858 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
2859 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
2860 echo -e "\nStarting Qemu emulator:\n"
2861 echo -e "qemu $QEMU_OPTS $iso\n"
2862 qemu $QEMU_OPTS $iso
2863 ;;
2866 deduplicate)
2867 # Deduplicate files in a tree
2868 shift
2869 deduplicate "$@"
2870 ;;
2873 usage|*)
2874 # Print usage also for all unknown commands.
2875 usage
2876 ;;
2877 esac
2879 exit 0