tazlito view tazlito @ rev 456

tazlito build-loram needs /init
author Pascal Bellard <pascal.bellard@slitaz.org>
date Wed Aug 16 19:14:45 2017 +0200 (2017-08-16)
parents c9ed5c101d4e
children 8ff519d67e94
line source
1 #!/bin/sh
2 # TazLito - SliTaz Live Tool.
3 #
4 # Tazlito is a tool to help generate and configure SliTaz Live CD
5 # ISO images. You can create a custom distro in one command from a list of
6 # packages, extract an existing ISO image to hack it, create a new initramfs
7 # and/or a new ISO. Most commands must be run by root, except the stats
8 # and the configuration file manipulation.
9 #
10 # (C) 2007-2016 SliTaz - GNU General Public License.
11 #
12 # Authors: see the AUTHORS file
13 #
15 VERSION='6.0'
17 . /lib/libtaz.sh
18 # Force to use Busybox cpio and wget
19 alias cpio='busybox cpio'
20 alias wget='busybox wget'
22 # Tazlito configuration variables to be shorter
23 # and to use words rather than numbers.
24 COMMAND="$1"
25 LIST_NAME="$2"
26 TMP_DIR="/tmp/tazlito-$$-$RANDOM"
27 TMP_MNT="/media/tazlito-$$-$RANDOM"
28 TOP_DIR="$(pwd)"
29 INITRAMFS='rootfs.gz'
30 LOCALSTATE='/var/lib/tazpkg'
31 INSTALLED="$LOCALSTATE/installed"
32 CACHE_DIR='/var/cache/tazpkg'
33 MIRROR="$LOCALSTATE/mirror"
34 DEFAULT_MIRROR="http://mirror1.slitaz.org/packages/$(cat /etc/slitaz-release)/"
36 log='/var/log/tazlito.log'
37 if [ $(id -u) -eq 0 ]; then
38 newline > $log
39 fi
42 cleanup() {
43 if [ -d "$TMP_MNT" ]; then
44 umount $TMP_MNT
45 rmdir $TMP_MNT
46 rm -f /boot
47 fi
48 [ -d "$tmp_dir" ] && rm -r "$tmp_dir"
49 [ -d "$flv_dir" ] && rm -r "$flv_dir"
50 }
53 # Report error and finish work
55 die() {
56 emsg "<n>$(longline "$@")<n> " >&2
57 cleanup
58 exit 1
59 }
62 # Run Tazlito module
63 module() {
64 local mod="$1"; shift
65 /usr/libexec/tazlito/$mod $@
66 }
70 # Try to include config file, continue if command is gen-config or exit.
71 # The main config used by default is in /etc/tazlito.
72 # Specific distro config file can be put in a distro tree.
73 for i in /etc/tazlito "$TOP_DIR"; do
74 [ -f "$i/tazlito.conf" ] && CONFIG_FILE="$i/tazlito.conf"
75 done
77 [ -z "$CONFIG_FILE" -a "$COMMAND" != 'gen-config' ] && \
78 die 'Unable to find any configuration file.' \
79 'Please read the docs or run `tazlito gen-config` to get an empty config file.'
81 . $CONFIG_FILE
83 # While Tazpkg is not used the default mirror URL file does not exist
84 # and user can't recharge the list of flavors.
85 [ $(id -u) -eq 0 -a ! -f "$MIRROR" ] && echo "$DEFAULT_MIRROR" > $MIRROR
87 # Set the rootfs and rootcd path with $DISTRO
88 # configuration variable.
89 ROOTFS="$DISTRO/rootfs"
90 ROOTCD="$DISTRO/rootcd"
95 #####################
96 # Tazlito functions #
97 #####################
100 # Print the usage.
102 usage () {
103 [ $(basename $0) == 'tazlito' ] && cat <<EOT
105 SliTaz Live Tool - Version: $(colorize 34 "$VERSION")
107 $(boldify "Usage:") tazlito [command] [list|iso|flavor|compression] [dir|iso]
109 $(boldify "Commands:")
110 EOT
111 optlist "\
112 usage Print this short usage.
113 stats View Tazlito and distro configuration statistics.
114 list-addfiles Simple list of additional files in the rootfs.
115 gen-config Generate a new configuration file for a distro.
116 configure Configure the main config file or a specific tazlito.conf.
117 gen-iso Generate a new ISO from a distro tree.
118 gen-initiso Generate a new initramfs and ISO from the distro tree.
119 list-flavors List all flavors available on the mirror.
120 gen-flavor Generate a new Live CD description.
121 gen-liveflavor Generate a Live CD description from current system.
122 show-flavor Show Live CD description.
123 get-flavor Get a flavor's list of packages (--noup to skip update).
124 upgrade-flavor Update package list to the latest available versions.
125 extract-flavor Extract a *.flavor file into $FLAVORS_REPOSITORY.
126 pack-flavor Pack (and update) a flavor from $FLAVORS_REPOSITORY.
127 iso2flavor Create a flavor file from a SliTaz ISO image.
128 extract-distro Extract an ISO to a directory and rebuild Live CD tree.
129 gen-distro Generate a Live distro and ISO from a list of packages.
130 clean-distro Remove all files generated by gen-distro.
131 check-distro Help to check if distro is ready to release.
132 writeiso Use running system to generate a bootable ISO (with /home).
133 merge Merge multiple rootfs into one ISO.
134 deduplicate Deduplicate files in a tree.
135 repack Recompress rootfs into ISO with maximum ratio.
136 build-loram Generate a Live CD for low-RAM systems.
137 emu-iso Emulate an ISO image with QEMU.
138 burn-iso Burn ISO image to a CD-ROM using Wodim.
139 "
140 }
143 yesorno() {
144 local answer
145 echo -n "$1 (y=yes, n=no) [$2] " >&2
146 case "$DEFAULT_ANSWER" in
147 Y|y) answer="y";;
148 N|n) answer="n";;
149 *)
150 read -t 30 answer
151 [ -z "$answer" ] && answer="$2"
152 [ "$answer" != 'y' -a "$answer" != 'n' ] && answer="$2"
153 ;;
154 esac
155 echo "$answer"
156 }
159 field() {
160 grep "^$1" "$2" | \
161 case "$1" in
162 Desc*) sed 's|^.*: *||';;
163 *) sed 's/.*: \([0-9KMG\.]*\).*/\1/';;
164 esac
165 }
168 todomsg() {
169 echo -e "\\033[70G[ \\033[1;31mTODO\\033[0;39m ]"
170 }
173 # Download a file from this mirror
175 download_from() {
176 local i mirrors="$1"
177 shift
178 for i in $mirrors; do
179 case "$i" in
180 http://*|ftp://*|https://*)
181 wget -c $i$@ && break;;
182 *)
183 cp $i/$1 . && break;;
184 esac
185 done
186 }
189 # Download a file trying all mirrors
191 download() {
192 local i
193 for i in $(cat $MIRROR $LOCALSTATE/undigest/*/mirror 2>/dev/null); do
194 download_from "$i" "$@" && break
195 done
196 }
199 # Execute hooks provided by some packages
201 genisohooks() {
202 local here="$(pwd)"
203 for i in $(ls $ROOTFS/etc/tazlito/*.$1 2>/dev/null); do
204 cd $ROOTFS
205 . $i $ROOTCD
206 done
207 cd "$here"
208 }
211 # Echo the package name if the tazpkg is already installed
213 installed_package_name() {
214 local tazpkg="$1" package VERSION EXTRAVERSION
216 # Try to find package name and version to be able
217 # to repack it from installation
218 # A dash (-) can exist in name *and* in version
219 package=${tazpkg%-*}
220 i=$package
221 while true; do
222 unset VERSION EXTRAVERSION
223 eval $(grep -s ^VERSION= $INSTALLED/$i/receipt)
224 eval $(grep -s ^EXTRAVERSION= $INSTALLED/$i/receipt)
225 if [ "$i-$VERSION$EXTRAVERSION" == "$tazpkg" ]; then
226 echo $i
227 break
228 fi
229 case "$i" in
230 *-*);;
231 *) break;;
232 esac
233 i=${i%-*}
234 done
235 }
238 # Check for the rootfs tree.
240 check_rootfs() {
241 [ -d "$ROOTFS/etc" ] || die 'Unable to find a distro rootfs...'
242 }
245 # Check for the boot dir into the root CD tree.
247 verify_rootcd() {
248 [ -d "$ROOTCD/boot" ] || die 'Unable to find the rootcd boot directory...'
249 }
252 # isolinux.conf doesn't know the kernel version.
253 # We name the kernel image 'bzImage'.
254 # isolinux/syslinux first tries the '64' suffix with a 64bits cpu.
256 make_bzImage_hardlink() {
257 if [ -s ${1:-.}/vmlinuz*slitaz ]; then
258 rm -f ${1:-.}/bzImage 2>/dev/null
259 ln ${1:-.}/vmlinuz*slitaz ${1:-.}/bzImage
260 fi
261 if [ -s ${1:-.}/vmlinuz*slitaz64 ]; then
262 rm -f ${1:-.}/bzImage64 2> /dev/null
263 ln ${1:-.}/vmlinuz*slitaz64 ${1:-.}/bzImage64
264 fi
265 }
268 create_iso() {
269 cd $2
270 deduplicate
272 cat > /tmp/cdsort$$ <<EOT
273 $PWD/boot 100
274 $PWD/boot/bzImage 200
275 $(n=199; ls -r $PWD/boot/rootfs* | while read f; do echo "$f $((n--))"; done)
276 $PWD/boot/isolinux 300
277 $PWD/boot/isolinux/boot.cat 400
278 $PWD/boot/isolinux/isolinux.bin 399
279 EOT
281 action 'Computing md5...'
282 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; > md5sum
283 sed -i -e '/ boot\/isolinux\/isolinux.bin$/d' \
284 -e '/ boot\/isolinux\/boot.cat$/d' md5sum
285 status
287 cd - >/dev/null
288 title 'Generating ISO image'
290 _ 'Generating %s' "$1"
291 make_bzImage_hardlink $2/boot
292 uefi="$(cd $2 ; ls boot/isolinux/*efi*img 2> /dev/null)"
293 genisoimage -R -o $1 -hide-rr-moved -sort /tmp/cdsort$$ \
294 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
295 -no-emul-boot -boot-load-size 4 -boot-info-table \
296 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
297 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
298 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
299 -A "tazlito $VERSION/$(genisoimage --version)" \
300 -copyright README -P "www.slitaz.org" $2
301 rm -f /tmp/cdsort$$
302 if [ -s '/etc/tazlito/info' ]; then
303 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
304 action 'Storing ISO info...'
305 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
306 status
307 fi
308 fi
310 if [ -x '/usr/bin/isohybrid' ]; then
311 action 'Creating hybrid ISO...'
312 /usr/bin/isohybrid $1 -entry 2 2>/dev/null
313 status
314 fi
316 if [ -x '/usr/bin/iso2exe' ]; then
317 echo 'Creating EXE header...'
318 /usr/bin/iso2exe $1 2>/dev/null
319 fi
320 }
323 # Generate a new ISO image using isolinux.
325 gen_livecd_isolinux() {
326 # Some packages may want to alter iso
327 genisohooks iso
328 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
330 # Set date for boot msg.
331 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
332 DATE=$(date +%Y%m%d)
333 action 'Setting build date to: %s...' "$DATE"
334 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
335 status
336 fi
338 cd $DISTRO
339 create_iso $ISO_NAME.iso $ROOTCD
341 action 'Creating the ISO md5sum...'
342 md5sum $ISO_NAME.iso > $ISO_NAME.md5
343 status
345 separator
346 # Some packages may want to alter final iso
347 genisohooks final
348 }
351 lzma_history_bits() {
352 #
353 # This generates an ISO which boots with Qemu but gives
354 # rootfs errors in frugal or liveUSB mode.
355 #
356 # local n
357 # local sz
358 # n=20 # 1Mb
359 # sz=$(du -sk $1 | cut -f1)
360 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
361 # n=$(( $n + 1 ))
362 # sz=$(( $sz / 2 ))
363 # done
364 # echo $n
365 echo ${LZMA_HISTORY_BITS:-24}
366 }
369 lzma_switches() {
370 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
371 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
372 }
375 lzma_set_size() {
376 # Update size field for lzma'd file packed using -si switch
377 return # Need to fix kernel code?
379 local n i
380 n=$(unlzma < $1 | wc -c)
381 for i in $(seq 1 8); do
382 printf '\\\\x%02X' $(($n & 255))
383 n=$(($n >> 8))
384 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
385 }
388 align_to_32bits() {
389 local size=$(stat -c %s ${1:-/dev/null})
390 [ $((${size:-0} & 3)) -ne 0 ] &&
391 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
392 }
395 dogzip() {
396 gzip -9 > $1
397 [ -x /usr/bin/advdef ] && advdef -qz4 $1
398 }
401 # Pack rootfs
403 pack_rootfs() {
404 ( cd $1; find . -print | cpio -o -H newc ) | \
405 case "$COMPRESSION" in
406 none)
407 _ 'Creating %s without compression...' 'initramfs'
408 cat > $2
409 ;;
410 gzip)
411 _ 'Creating %s with gzip compression...' 'initramfs'
412 dogzip $2
413 ;;
414 *)
415 _ 'Creating %s with lzma compression...' 'initramfs'
416 lzma e -si -so $(lzma_switches $1) > $2
417 lzma_set_size $2
418 ;;
419 esac
420 align_to_32bits $2
421 echo 1 > /tmp/rootfs
422 }
425 # Compression functions for writeiso.
427 write_initramfs() {
428 case "$COMPRESSION" in
429 lzma)
430 _n 'Creating %s with lzma compression...' "$INITRAMFS"
431 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
432 align='y'
433 lzma_set_size "/$INITRAMFS"
434 ;;
435 gzip)
436 _ 'Creating %s with gzip compression...' "$INITRAMFS"
437 cpio -o -H newc | dogzip "/$INITRAMFS"
438 ;;
439 *)
440 # align='y'
441 _ 'Creating %s without compression...' "$INITRAMFS"
442 cpio -o -H newc > "/$INITRAMFS"
443 ;;
444 esac < /tmp/list
445 [ "$align" == 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
446 echo 1 > /tmp/rootfs
447 }
450 # Deduplicate files (MUST be on the same filesystem).
452 deduplicate() {
453 find "${@:-.}" -type f -size +0c -xdev -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
454 (
455 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""
456 while read attr inode link file; do
457 [ -L "$file" ] && continue
458 if [ "$attr" == "$old_attr" -a "$inode" != "$old_inode" ]; then
459 if cmp "$file" "$old_file" >/dev/null 2>&1 ; then
460 rm -f "$file"
461 if ln "$old_file" "$file" 2>/dev/null; then
462 inode="$old_inode"
463 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
464 save="$(($save+(${attr%%-*}+512)/1024))"
465 else
466 cp -a "$old_file" "$file"
467 fi
468 fi
469 fi
470 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
471 done
472 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
473 )
475 find "$@" -type l -xdev -exec stat -c '%s-%u-%g-TARGET- %i %h %n' {} \; | sort | \
476 (
477 old_attr=""; hardlinks=0;
478 while read attr inode link file; do
479 attr="${attr/-TARGET-/-$(readlink $file)}"
480 if [ "$attr" == "$old_attr" ]; then
481 if [ "$inode" != "$old_inode" ]; then
482 rm -f "$file"
483 if ln "$old_file" "$file" 2>/dev/null; then
484 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
485 else
486 cp -a "$old_file" "$file"
487 fi
488 fi
489 else
490 old_file="$file"
491 old_attr="$attr"
492 old_inode="$inode"
493 fi
494 done
495 _ '%s duplicate symlinks.' "$hardlinks"
496 )
497 }
500 # Generate a new initramfs from the root filesystem.
502 gen_initramfs() {
503 # Just in case CTRL+c
504 rm -f $DISTRO/gen
506 # Some packages may want to alter rootfs
507 genisohooks rootfs
508 cd $1
510 # Normalize file time
511 find $1 -newer $1 -exec touch -hr $1 {} \;
513 # Link duplicate files
514 deduplicate
516 # Use lzma if installed. Display rootfs size in realtime.
517 rm -f /tmp/rootfs 2>/dev/null
518 pack_rootfs . $DISTRO/$(basename $1).gz &
519 sleep 2
520 echo -en "\nFilesystem size:"
521 while [ ! -f /tmp/rootfs ]; do
522 sleep 1
523 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
524 done
525 echo -e "\n"
526 rm -f /tmp/rootfs
527 cd $DISTRO
528 mv $(basename $1).gz $ROOTCD/boot
529 }
532 distro_sizes() {
533 if [ -n "$start_time" ]; then
534 time=$(($(date +%s) - $start_time))
535 sec=$time
536 div=$(( ($time + 30) / 60))
537 [ "$div" -ne 0 ] && min="~ ${div}m"
538 _ 'Build time : %ss %s' "$sec" "$min"
539 fi
540 cat <<EOT
541 Build date : $(date +%Y%m%d)
542 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
543 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
544 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
545 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
546 EOT
547 footer "Image is ready: $ISO_NAME.iso"
548 }
551 # Print ISO and rootfs size.
553 distro_stats() {
554 title 'Distro statistics: %s' "$DISTRO"
555 distro_sizes
556 }
559 # Create an empty configuration file.
561 empty_config_file() {
562 cat >> tazlito.conf <<"EOF"
563 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
564 #
566 # Name of the ISO image to generate.
567 ISO_NAME=""
569 # ISO image volume name.
570 VOLUM_NAME="SliTaz"
572 # Name of the preparer.
573 PREPARED="$USER"
575 # Path to the packages repository and the packages.list.
576 PACKAGES_REPOSITORY=""
578 # Path to the distro tree to gen-distro from a list of packages.
579 DISTRO=""
581 # Path to the directory containing additional files
582 # to copy into the rootfs and rootcd of the LiveCD.
583 ADDFILES="$DISTRO/addfiles"
585 # Default answer for binary question (Y or N)
586 DEFAULT_ANSWER="ASK"
588 # Compression utility (lzma, gzip or none)
589 COMPRESSION="lzma"
590 EOF
591 }
594 # Extract rootfs.gz somewhere
596 extract_rootfs() {
597 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
598 # First part (lzcat or zcat) may not fail, but cpio will fail on uncorrect format
599 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
600 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
601 (cd "$2"; cat "$1" | cpio -idm --quiet 2>/dev/null)
602 }
605 # Extract flavor file to temp directory
607 extract_flavor() {
608 # Input: $1 - flavor name to extract;
609 # $2 = absent/empty: just extract 'outer layer'
610 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
611 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
612 # Output: temp dir path where flavor was extracted
613 local f="$1.flavor" from to infos="$1.desc"
614 [ -f "$f" ] || die "File '$f' not found"
615 local dir="$(mktemp -d)"
616 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
618 if [ -n "$2" ]; then
619 cd $dir
621 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
623 for i in rootcd rootfs; do
624 [ -f "$1.$i" ] || continue
625 mkdir "$i"
626 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
627 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
628 rm "$1.$i"
629 done
630 touch -t 197001010100.00 "$1.*"
631 # Info to be stored inside ISO
632 [ "$2" == info ] && echo -e $infos | cpio -o -H newc | dogzip info
633 rm $1.list*
635 # Renames
636 while read from to; do
637 [ -f "$from" ] || continue
638 mv "$from" "$to"
639 done <<EOT
640 $1.nonfree non-free.list
641 $1.pkglist packages.list
642 $1-distro.sh distro.sh
643 $1.receipt receipt
644 $1.mirrors mirrors
645 $1.desc description
646 EOT
647 fi
649 echo $dir
650 }
653 # Pack flavor file from temp directory
655 pack_flavor() {
656 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
657 }
660 # Remove duplicate files
662 mergefs() {
663 # Note, many packages have files with spaces in the name
664 IFS=$'\n'
666 local size1=$(du -hs "$1" | awk '{ print $1 }')
667 local size2=$(du -hs "$2" | awk '{ print $1 }')
668 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
670 # merge symlinks files and devices
671 ( cd "$1"; find ) | \
672 while read file; do
673 if [ -L "$1/$file" ]; then
674 [ -L "$2/$file" -a "$(readlink "$1/$file")" == "$(readlink "$2/$file")" ] &&
675 rm -f "$2/$file"
677 elif [ -f "$1/$file" ]; then
678 [ -f "$2/$file" ] && cmp -s "$1/$file" "$2/$file" &&
679 rm -f "$2/$file"
681 [ -f "$2/$file" ] &&
682 [ "$(basename "$file")" == 'volatile.cpio.gz' ] &&
683 [ "$(dirname $(dirname "$file"))" == ".$INSTALLED" ] &&
684 rm -f "$2/$file"
686 elif [ -b "$1/$file" ]; then
687 [ -b "$2/$file" ] &&
688 [ "$(stat -c '%a:%u:%g:%t:%T' "$1/$file")" == \
689 "$(stat -c '%a:%u:%g:%t:%T' "$2/$file")" ] &&
690 rm -f "$2/$file"
692 elif [ -c "$1/$file" ]; then
693 [ -c "$2/$file" ] &&
694 [ "$(stat -c '%a:%u:%g:%t:%T' "$1/$file")" == \
695 "$(stat -c '%a:%u:%g:%t:%T' "$2/$file")" ] &&
696 rm -f "$2/$file"
697 fi
698 done
700 # cleanup directories; TODO: simplify
701 ( cd "$1"; find . -type d ) | sed '1!G;h;$!d' | \
702 while read file; do
703 [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
704 done
706 unset IFS
707 status
708 }
711 cleanup_merge() {
712 rm -rf $TMP_DIR
713 exit 1
714 }
717 # Update isolinux config files for multiple rootfs
719 update_bootconfig() {
720 local files
721 action 'Updating boot config files...'
722 files="$(grep -l 'include common' $1/*.cfg)"
723 for file in $files; do
724 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
725 if (/label/) label=$0;
726 else if (/kernel/) kernel=$0;
727 else if (/append/) {
728 i=index($0,"rootfs.gz");
729 append=substr($0,i+9);
730 }
731 else if (/include/) {
732 for (i = 1; i <= n; i++) {
733 print label i
734 print kernel;
735 initrd="initrd=/boot/rootfs" n ".gz"
736 for (j = n - 1; j >= i; j--) {
737 initrd=initrd ",/boot/rootfs" j ".gz";
738 }
739 printf "\tappend %s%s\n",initrd,append;
740 print "";
741 }
742 print;
743 }
744 else print;
745 }' < $file > $file.$$
746 mv -f $file.$$ $file
747 done
748 sel="$(echo $2 | awk '{
749 for (i=1; i<=NF; i++)
750 if (i % 2 == 0) printf " slitaz%d", i/2
751 else printf " %s", $i
752 }')"
754 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
756 label slitaz
757 kernel /boot/isolinux/ifmem.c32
758 append$sel noram
760 label noram
761 config noram.cfg
763 EOT
765 # Update vesamenu
766 if [ -s "$1/isolinux.cfg" ]; then
767 files="$files $1/isolinux.cfg"
768 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
769 BEGIN {
770 kernel = " COM32 c32box.c32"
771 }
772 {
773 if (/ROWS/) print "MENU ROWS " n+$3;
774 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
775 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
776 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
777 else if (/VSHIFT/) {
778 x = $3-n;
779 if (x < 0) x = 0;
780 print "MENU VSHIFT " x;
781 }
782 else if (/rootfs.gz/) {
783 linux = "";
784 if (/bzImage/) linux = "linux /boot/bzImage ";
785 i = index($0, "rootfs.gz");
786 append = substr($0, i+9);
787 printf "\tkernel /boot/isolinux/ifmem.c32\n";
788 printf "\tappend%s noram\n", sel;
789 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
790 for (i = 1; i <= n; i++) {
791 print "LABEL slitaz" i
792 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
793 printf "%s\n", kernel;
794 initrd = "initrd=/boot/rootfs" n ".gz"
795 for (j = n - 1; j >= i; j--) {
796 initrd = initrd ",/boot/rootfs" j ".gz";
797 }
798 printf "\tappend %s%s%s\n\n", linux, initrd, append;
799 }
800 }
801 else if (/bzImage/) kernel = $0;
802 else print;
803 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
804 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
805 fi
807 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
808 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
809 cat > $1/noram.cfg <<EOT
810 implicit 0
811 prompt 1
812 timeout 80
813 $(grep '^F[0-9]' $1/isolinux.cfg)
815 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
816 say Not enough RAM to boot slitaz. Trying hacker mode...
817 default hacker
818 label hacker
819 KERNEL /boot/bzImage
820 append rw root=/dev/null vga=normal
822 label reboot
823 EOT
825 if [ -s $1/c32box.c32 ]; then
826 cat >> $1/noram.cfg <<EOT
827 COM32 c32box.c32
828 append reboot
830 label poweroff
831 COM32 c32box.c32
832 append poweroff
834 EOT
835 else
836 echo " com32 reboot.c32" >> $1/noram.cfg
837 fi
839 # Restore real label names
840 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
841 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
842 while read pat; do
843 sed -i "s/slitaz$pat/" $files
844 done
845 status
846 }
849 # Uncompress rootfs or module to stdout
851 uncompress() {
852 zcat $1 2> /dev/null || xzcat $1 2> /dev/null || unlzma < $1 || cat $i
853 }
856 # Install a missing package
858 install_package() {
859 if [ -z "$2" ]; then
860 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
861 else
862 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
863 fi
864 case "$answer" in
865 y)
866 # We don't want package on host cache.
867 action 'Getting and installing package: %s' "$1"
868 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
869 status ;;
870 *)
871 return 1 ;;
872 esac
873 }
876 # Check iso for loram transformation
878 check_iso_for_loram() {
879 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
880 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
881 }
884 # Build initial rootfs for loram ISO ram/cdrom/http
886 build_initfs() {
887 urliso="mirror.switch.ch/ftp/mirror/slitaz \
888 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
889 mirror3.slitaz.org mirror.slitaz.org"
890 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
891 [ -z "$version" ] && die "Can't find the kernel version." \
892 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
894 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
895 need_lib=false
896 for i in bin dev run mnt proc tmp sys lib/modules; do
897 mkdir -p $TMP_DIR/initfs/$i
898 done
899 ln -s bin $TMP_DIR/initfs/sbin
900 ln -s . $TMP_DIR/initfs/usr
901 for aufs in aufs overlayfs; do
902 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
903 install_package $aufs $version && break
904 done || return 1
905 [ -s /init ] || install_package slitaz-boot-files
906 cp /init $TMP_DIR/initfs/
907 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
908 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
909 $TMP_DIR/initfs/lib/modules 2>/dev/null
910 cp -a /dev/tty0 /dev/fd0 $TMP_DIR/initfs/dev 2>/dev/null
911 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
912 $TMP_DIR/initfs/lib/modules
913 if [ "$1" == 'cdrom' ]; then
914 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
915 else
916 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
917 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
918 install_package linux-squashfs $version || return 1
919 done
920 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
921 $TMP_DIR/initfs/lib/modules
922 ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
923 cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
924 fi
925 for i in $(ls /dev/[hs]d[a-f]*); do
926 cp -a $i $TMP_DIR/initfs/dev
927 done
928 if [ "$1" == 'http' ]; then
929 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
930 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
931 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
932 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
933 cp -a /dev/fuse $TMP_DIR/initfs/dev
934 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
935 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
936 else
937 need_lib=true
938 fi
939 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
940 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
941 else
942 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
943 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
944 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
945 cp -a /lib/librt* $TMP_DIR/initfs/lib
946 cp -a /lib/libdl* $TMP_DIR/initfs/lib
947 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
948 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
949 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
950 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
951 need_lib=true
952 fi
953 cd $TMP_DIR/fs
954 echo 'Getting slitaz-release & ethernet modules...'
955 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
956 uncompress $i | cpio -idmu etc/slitaz-release lib/modules* >/dev/null
957 done
958 cd - > /dev/null
959 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
960 find $TMP_DIR/fs/lib/modules/*/kernel/drivers/net/ethernet \
961 -type f -name '*.ko*' | while read mod; do
962 f=$TMP_DIR/initfs/lib/modules/$(basename $mod | sed s/..z$//)
963 uncompress $mod > $f
964 grep -q alias=pci: $f || rm -f $f
965 done
966 for i in $TMP_DIR/initfs/lib/modules/*.ko ; do
967 f=$(basename $i)..z
968 grep -q $f:$ $TMP_DIR/fs/lib/modules/*/modules.dep && continue
969 deps="$(grep $f: $TMP_DIR/fs/lib/modules/*/modules.dep | sed 's/.*: //')"
970 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > $TMP_DIR/initfs/lib/modules/$(basename $i .ko).dep
971 for j in $deps; do
972 mod=$(ls $TMP_DIR/fs/lib/modules/*/$j)
973 uncompress $mod > $TMP_DIR/initfs/lib/modules/$(basename $j | sed s/..z$//)
974 done
975 done
976 longline "Default URLs for /iso/$(cat $TMP_DIR/initfs/etc/slitaz-release)/flavors/slitaz-loram-cdrom.iso /iso/$(cat $TMP_DIR/initfs/etc/slitaz-release)/flavors/slitaz-$(cat $TMP_DIR/initfs/etc/slitaz-release)-loram-cdrom.iso: $urliso"
977 _n 'List of URLs to insert: '
978 read -t 30 urliso2
979 urliso="$urliso2 $urliso"
980 fi
981 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
982 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
983 sed -i 's/LD_T.*ot/newline/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
984 else
985 cp /bin/busybox $TMP_DIR/initfs/bin
986 need_lib=true
987 fi
988 for i in $($TMP_DIR/initfs/bin/busybox | awk \
989 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
990 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
991 done
992 for i in /dev/console /dev/loop* /dev/null /dev/tty /dev/zero \
993 /dev/kmem /dev/mem /dev/random /dev/urandom; do
994 cp -a $i $TMP_DIR/initfs/dev
995 done
996 $need_lib && for i in /lib/ld-* /lib/lib[cm].so* /lib/lib[cm]-* ; do
997 cp -a $i $TMP_DIR/initfs/lib
998 done
999 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1000 #!/bin/sh
1002 getarg() {
1003 grep -q " \$1=" /proc/cmdline || return 1
1004 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1005 return 0
1008 copy_rootfs() {
1009 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1010 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1011 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1012 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1013 path=/mnt/
1014 return 0
1015 else
1016 rm -f /mnt/rootfs*
1017 return 1
1018 fi
1021 echo "Switching / to tmpfs..."
1022 mount -t proc proc /proc
1023 size="\$(grep rootfssize= < /proc/cmdline | \\
1024 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1025 [ -n "\$size" ] || size="-o size=90%"
1027 mount -t sysfs sysfs /sys
1028 for i in /lib/modules/*.ko ; do
1029 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1030 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1031 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1032 insmod /lib/modules/\$k.ko 2> /dev/null
1033 done
1034 insmod \$i 2> /dev/null
1035 break
1036 done
1037 done
1038 umount /sys
1039 while read var default; do
1040 eval \$var=\$default
1041 getarg \$var \$var
1042 done <<EOT
1043 eth eth0
1044 dns 208.67.222.222,208.67.220.220
1045 netmask 255.255.255.0
1046 gw
1047 ip
1048 EOT
1049 if [ -n "\$ip" ]; then
1050 ifconfig \$eth \$ip netmask \$netmask up
1051 route add default gateway \$gw
1052 for i in \$(echo \$dns | sed 's/,/ /g'); do
1053 echo "nameserver \$i" >> /etc/resolv.conf
1054 done
1055 else
1056 udhcpc -f -q -s /lib/udhcpc -i \$eth
1057 fi
1058 for i in $urliso ; do
1059 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1060 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"
1061 done
1062 getarg urliso URLISO
1063 DIR=fs
1064 if getarg loram DIR; then
1065 DEVICE=\${DIR%,*}
1066 DIR=/\${DIR#*,}
1067 fi
1068 mount -t tmpfs \$size tmpfs /mnt
1069 path2=/mnt/.httpfs/
1070 path=/mnt/.cdrom/
1071 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1072 while [ ! -d \$path/boot ]; do
1073 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1074 httpfs \$i \$path2 && break
1075 done
1076 mount -o loop,ro -t iso9660 \$path2/*.iso \$path
1077 done
1079 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1080 umount /proc
1081 branch=:/mnt/.cdrom/\$DIR
1082 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1083 branch=
1084 for i in \${path}rootfs* ; do
1085 fs=\${i#*root}
1086 branch=\$branch:/mnt/.\$fs
1087 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1088 insmod /lib/modules/squashfs.ko 2> /dev/null
1089 mount -o loop,ro -t squashfs \${path}root\$fs /mnt/.\$fs
1090 done
1091 else
1092 mkdir -p /mnt/.rw/mnt/.httpfs
1093 fi
1094 while read type opt; do
1095 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1096 done <<EOT
1097 aufs br=/mnt/.rw\$branch
1098 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1099 EOT
1100 rm -rf /lib/modules
1101 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1102 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1103 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1104 EOTEOT
1105 chmod +x $TMP_DIR/initfs/init
1106 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1107 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1108 rm -f $i
1109 dogzip ${i%.gz}
1110 done 2>/dev/null
1111 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1112 lzma e $TMP_DIR/initfs.gz -si
1113 lzma_set_size $TMP_DIR/initfs.gz
1114 rm -rf $TMP_DIR/initfs
1115 align_to_32bits $TMP_DIR/initfs.gz
1116 return 0
1120 # Move each initramfs to squashfs
1122 build_loram_rootfs() {
1123 rootfs_sizes=""
1124 for i in $TMP_DIR/iso/boot/rootfs*; do
1125 mkdir -p $TMP_DIR/fs
1126 cd $TMP_DIR/fs
1127 uncompress $i | cpio -idm
1128 deduplicate
1129 cd - > /dev/null
1130 rootfs=$TMP_DIR/$(basename $i)
1131 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp xz -Xbcj x86
1132 cd $TMP_DIR
1133 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1134 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1135 rm -f $rootfs
1136 mv $rootfs.cpio $rootfs
1137 cd - > /dev/null
1138 rm -rf $TMP_DIR/fs
1139 done
1143 # Move meta boot configuration files to basic configuration files
1144 # because meta loram flavor is useless when rootfs is not loaded in RAM
1146 unmeta_boot() {
1147 local root=${1:-$TMP_DIR/loramiso}
1148 if [ -f $root/boot/isolinux/noram.cfg ]; then
1149 # We keep enough information to do unloram...
1150 [ -s $root/boot/isolinux/common.cfg ] &&
1151 sed -i 's/label slitaz/label orgslitaz/' \
1152 $root/boot/isolinux/common.cfg
1153 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1154 shift
1155 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1156 $root/boot/isolinux/isolinux.cfg
1157 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1158 sed -i "s/label $3\$/label slitaz/;s|=/boot/rootfs\(.*\).gz |=/boot/rootfs.gz |" \
1159 $root/boot/isolinux/*.cfg
1160 fi
1164 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1165 # These squashfs may be loaded in RAM at boot time.
1166 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1167 # Meta flavors are converted to normal flavors.
1169 build_loram_cdrom() {
1170 build_initfs cdrom || return 1
1171 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1172 mkdir $TMP_DIR/loramiso/fs
1173 cd $TMP_DIR/loramiso/fs
1174 for i in $( ls ../boot/root* | sort -r ) ; do
1175 uncompress $i | cpio -idmu
1176 rm -f $i
1177 done
1178 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1179 cd - >/dev/null
1180 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1181 unmeta_boot
1182 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1183 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1184 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1185 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1186 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1187 create_iso $OUTPUT $TMP_DIR/loramiso
1191 # Create http bootstrap to load and remove loram_cdrom
1192 # Meta flavors are converted to normal flavors.
1194 build_loram_http() {
1195 build_initfs http || return 1
1196 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1197 rm -f $TMP_DIR/loramiso/boot/rootfs*
1198 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1199 unmeta_boot
1200 create_iso $OUTPUT $TMP_DIR/loramiso
1204 # Update meta flavor selection sizes.
1205 # Reduce sizes with rootfs gains.
1207 update_metaiso_sizes() {
1208 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1209 do
1210 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1211 local sizes="$rootfs_sizes"
1212 local new
1213 set -- $append
1214 shift
1215 [ "$1" == "ifmem" ] && shift
1216 new=""
1217 while [ -n "$2" ]; do
1218 local s
1219 case "$1" in
1220 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1221 *M) s=$(( ${1%M} * 1024 ));;
1222 *) s=${1%K};;
1223 esac
1224 sizes=${sizes#* }
1225 for i in $sizes ; do
1226 s=$(( $s - $i ))
1227 done
1228 new="$new $s $2"
1229 shift 2
1230 done
1231 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1232 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1233 sed -i 's|\(initrd=\)\(/boot/rootfs.\.gz\)|\1/boot/rootfs.gz,\2|' $cfg
1234 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1235 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1236 done
1240 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1241 # Meta flavor selection sizes are updated.
1243 build_loram_ram() {
1244 build_initfs ram || return 1
1245 build_loram_rootfs
1246 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1247 make_bzImage_hardlink $TMP_DIR/loramiso/boot
1248 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1249 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1250 update_metaiso_sizes
1251 create_iso $OUTPUT $TMP_DIR/loramiso
1255 # Remove files installed by packages
1257 find_flavor_rootfs() {
1258 for i in $1/etc/tazlito/*.extract; do
1259 [ -e $i ] || continue
1260 chroot $1 /bin/sh ${i#$1}
1261 done
1263 # Clean hardlinks and files patched by genisofs in /boot
1264 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1265 rm -f $1/boot/$i*
1266 done
1268 # Clean files generated in post_install
1269 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1270 $1/dev/core $1/dev/fd $1/dev/std*
1272 # Verify md5
1273 cat $1$INSTALLED/*/md5sum | \
1274 while read md5 file; do
1275 [ -e "$1$file" ] || continue
1276 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1277 rm -f "$1$file"
1278 done
1280 # Check configuration files
1281 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1282 [ -e $i ] || continue
1283 mkdir /tmp/volatile$$
1284 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1285 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1286 while read file ; do
1287 [ -e "$1/$file" ] || continue
1288 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1289 done
1290 rm -rf /tmp/volatile$$
1291 done
1293 # Remove other files blindly
1294 for i in $1$INSTALLED/*/files.list; do
1295 for file in $(cat "$i"); do
1296 [ "$1$file" -nt "$i" ] && continue
1297 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1298 [ -d "$1$file" ] || rm -f "$1$file"
1299 done
1300 done
1302 # Remove tazpkg files and tmp files
1303 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1304 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1305 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1306 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1307 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1309 # Cleanup directory tree
1310 cd $1
1311 find * -type d | sort -r | while read dir; do
1312 rmdir "$dir" 2>/dev/null
1313 done
1314 cd - > /dev/null
1318 # Get byte(s) from a binary file
1320 get() {
1321 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null
1325 # Get cpio flavor info from the ISO image
1327 flavordata() {
1328 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1329 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1333 # Restore undigest mirrors
1335 restore_mirrors() {
1336 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1337 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1339 action 'Restoring mirrors...'
1340 if [ -d "$undigest.bak" ]; then
1341 [ -d "$undigest" ] && rm -r "$undigest"
1342 mv "$undigest.bak" "$undigest"
1343 fi
1344 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1345 :; status
1349 # Setup undigest mirrors
1351 setup_mirrors() {
1352 # Setup mirrors in plain system or in chroot (with variable root=)
1353 local mirrorlist="$1" fresh repacked
1354 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1356 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1357 restore_mirrors
1359 _ 'Setting up mirrors for %s...' "$root/"
1360 # Backing up current undigest mirrors and priority
1361 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1362 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1363 rm -rf '/var/www/tazlito/'
1364 mkdir -p '/var/www/tazlito/'
1366 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1367 fresh='/home/slitaz/packages'
1368 if [ -d "$fresh" ]; then
1369 # Setup first undigest mirror
1370 mkdir -p "$undigest/fresh"
1371 echo "$fresh" > "$undigest/fresh/mirror"
1372 echo 'fresh' >> "$priority"
1373 # Rebuild mirror DB if needed
1374 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1375 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1376 tazpkg mkdb "$fresh" --forced --root=''
1377 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1378 fi
1380 # Repacked packages: high priority
1381 repacked="$PACKAGES_REPOSITORY"
1382 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1383 # According to Tazlito setup file (tazlito.conf):
1384 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1385 # or
1386 # WORK_DIR="/home/slitaz"
1387 # and
1388 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1389 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1391 # Setup second undigest mirror
1392 mkdir -p "$undigest/repacked"
1393 echo "$repacked" > "$undigest/repacked/mirror"
1394 echo 'repacked' >> "$priority"
1395 # Rebuild mirror DB if needed
1396 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1397 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1398 tazpkg mkdb "$repacked" --forced --root=''
1399 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1400 fi
1402 # All repositories listed in mirrors list: normal priority
1403 [ -e "$mirrorlist" ] && \
1404 while read mirror; do
1405 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1406 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1407 mkdir -p "$undigest/$mirrorid"
1408 echo "$mirror" > "$undigest/$mirrorid/mirror"
1409 echo "$mirrorid" >> "$priority"
1410 done < "$mirrorlist"
1412 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1414 # Show list of mirrors
1415 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1416 function show(num, name, url) {
1417 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1420 num++;
1421 "cat " db "/undigest/" $0 "/mirror" | getline url;
1422 show(num, $0, url);
1424 END {
1425 num++;
1426 "cat " db "/mirror" | getline url;
1427 show(num, "main", url);
1428 }' "$priority"
1430 tazpkg recharge --quiet >/dev/null
1434 # Get list of 'packages.info' lists using priority
1436 pi_lists() {
1437 local pi
1438 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1439 local priority="$root$LOCALSTATE/priority"
1440 local undigest="$root$LOCALSTATE/undigest"
1443 [ -s "$priority" ] && cat "$priority"
1444 echo 'main'
1445 [ -d "$undigest" ] && ls "$undigest"
1446 } | awk -vun="$undigest/" '
1448 if (arr[$0] != 1) {
1449 arr[$0] = 1;
1450 print un $0 "/packages.info";
1452 }' | sed 's|/undigest/main||' | \
1453 while read pi; do
1454 [ -e "$pi" ] && echo "$pi"
1455 done
1459 # Strip versions from packages list
1461 strip_versions() {
1462 action 'Strip versions from list %s...' "$(basename "$1")"
1463 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1464 [ -f "$in_list" ] || die "List '$in_list' not found."
1466 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1467 awk '
1469 if (FILENAME ~ "packages.info") {
1470 # Collect package names
1471 FS = "\t"; pkg[$1] = 1;
1472 } else {
1473 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1474 while (NF > 1 && ! pkg[$0])
1475 NF --;
1476 printf "%s\n", $0;
1478 }' $(pi_lists) "$in_list" > "$tmp_list"
1480 cat "$tmp_list" > "$in_list"
1481 rm "$tmp_list"
1482 status
1486 # Display list of unknown packages (informative)
1488 display_unknown() {
1489 [ -s "$1" ] || return
1490 echo "Unknown packages:" >&2
1491 cat "$1" >&2
1492 rm "$1"
1496 # Display warnings about critical packages absent (informative)
1498 display_warn() {
1499 [ -s "$1" ] || return
1500 echo "Absent critical packages:" >&2
1501 cat "$1" >&2
1502 rm "$1"
1503 echo "Probably ISO image will be unusable."
1507 # Install packages to rootfs
1509 install_list_to_rootfs() {
1510 local list="$1" rootfs="$2" pkg i ii
1511 local undigest="$rootfs/var/lib/tazpkg/undigest"
1513 # initial tazpkg setup in empty rootfs
1514 tazpkg --root=$rootfs >/dev/null 2>&1
1515 # link rootfs packages cache to the regular packages cache
1516 rm -r "$rootfs/var/cache/tazpkg"
1517 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1519 setup_mirrors mirrors
1521 # Just in case if flavor not contains "tazlito" package
1522 mkdir -p "$rootfs/etc/tazlito"
1524 newline
1525 for pkg in $(cat $list); do
1526 action 'Installing package: %s' "$pkg"
1527 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1528 status
1529 done
1530 newline
1532 restore_mirrors
1533 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1534 for i in fresh repacked; do
1535 ii="$undigest/$i"
1536 [ -d "$ii" ] && rm -rf "$ii"
1537 ii="$rootfs/var/lib/tazpkg/priority"
1538 if [ -f "$ii" ]; then
1539 sed -i "/$i/d" "$ii"
1540 [ -s "$ii" ] || rm "$ii"
1541 fi
1542 done
1543 [ -d "$undigest" ] && \
1544 for i in $(find "$undigest" -type f); do
1545 # Remove all undigest PKGDB files but 'mirror'
1546 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1547 done
1548 [ -d "$undigest" ] && \
1549 rmdir --ignore-fail-on-non-empty "$undigest"
1551 # Un-link packages cache
1552 rm "$rootfs/var/cache/tazpkg"
1554 # Clean /var/lib/tazpkg
1555 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1561 ####################
1562 # Tazlito commands #
1563 ####################
1565 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1566 case "$0" in
1567 *reduplicate)
1568 find ${@:-.} ! -type d -links +1 \
1569 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1570 exit 0 ;;
1571 *deduplicate)
1572 deduplicate "$@"
1573 exit 0 ;;
1574 esac
1577 case "$COMMAND" in
1578 stats)
1579 # Tazlito general statistics from the config file.
1581 title 'Tazlito statistics'
1582 optlist "\
1583 Config file : $CONFIG_FILE
1584 ISO name : $ISO_NAME.iso
1585 Volume name : $VOLUM_NAME
1586 Prepared : $PREPARED
1587 Packages repository : $PACKAGES_REPOSITORY
1588 Distro directory : $DISTRO
1589 Additional files : $ADDFILES
1590 " | sed '/: $/d'
1591 footer
1592 ;;
1595 list-addfiles)
1596 # Simple list of additional files in the rootfs
1597 newline
1598 if [ -d "$ADDFILES/rootfs" ]; then
1599 cd $ADDFILES
1600 find rootfs -type f
1601 else
1602 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1603 fi
1604 newline
1605 ;;
1608 gen-config)
1609 # Generate a new config file in the current dir or the specified
1610 # directory by $2.
1612 if [ -n "$2" ]; then
1613 mkdir -p "$2" && cd "$2"
1614 fi
1616 newline
1617 action 'Generating empty tazlito.conf...'
1618 empty_config_file
1619 status
1621 separator
1622 if [ -f 'tazlito.conf' ] ; then
1623 _ 'Configuration file is ready to edit.'
1624 _ 'File location: %s' "$(pwd)/tazlito.conf"
1625 newline
1626 fi
1627 ;;
1630 configure)
1631 # Configure a tazlito.conf config file. Start by getting
1632 # a empty config file and sed it.
1634 if [ -f 'tazlito.conf' ]; then
1635 rm tazlito.conf
1636 else
1637 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1638 'or in the same directory of the file you want to configure.'
1639 cd /etc
1640 fi
1642 empty_config_file
1644 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1646 # ISO name.
1647 echo -n "ISO name : " ; read answer
1648 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1649 # Volume name.
1650 echo -n "Volume name : " ; read answer
1651 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1652 # Packages repository.
1653 echo -n "Packages repository : " ; read answer
1654 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1655 # Distro path.
1656 echo -n "Distro path : " ; read answer
1657 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1658 footer "Config file is ready to use."
1659 echo 'You can now extract an ISO or generate a distro.'
1660 newline
1661 ;;
1664 gen-iso)
1665 # Simply generate a new iso.
1667 check_root
1668 verify_rootcd
1669 gen_livecd_isolinux
1670 distro_stats
1671 ;;
1674 gen-initiso)
1675 # Simply generate a new initramfs with a new iso.
1677 check_root
1678 verify_rootcd
1679 gen_initramfs "$ROOTFS"
1680 gen_livecd_isolinux
1681 distro_stats
1682 ;;
1685 extract-distro)
1686 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1688 check_root
1689 ISO_IMAGE="$2"
1690 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1691 'Example:\n tazlito image.iso /path/target'
1693 # Set the distro path by checking for $3 on cmdline.
1694 TARGET="${3:-$DISTRO}"
1696 # Exit if existing distro is found.
1697 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1698 'Please clean the distro tree or change directory path.'
1700 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
1702 # Start to mount the ISO.
1703 action 'Mounting ISO image...'
1704 mkdir -p "$TMP_DIR"
1705 # Get ISO file size.
1706 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
1707 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
1708 sleep 2
1709 # Prepare target dir, copy the kernel and the rootfs.
1710 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
1711 status
1713 action 'Copying the Linux kernel...'
1714 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
1715 make_bzImage_hardlink "$TARGET/rootcd/boot"
1716 else
1717 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
1718 fi
1719 status
1721 for i in $(ls $TMP_DIR); do
1722 [ "$i" == 'boot' ] && continue
1723 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
1724 done
1726 for loader in isolinux syslinux extlinux grub; do
1727 [ -d "$TMP_DIR/boot/$loader" ] || continue
1728 action 'Copying %s files...' "$loader"
1729 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
1730 status
1731 done
1733 action 'Copying the rootfs...'
1734 cp $TMP_DIR/boot/rootfs.?z "$TARGET/rootcd/boot"
1735 status
1737 # Extract initramfs.
1738 cd "$TARGET/rootfs"
1739 action 'Extracting the rootfs...'
1740 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
1741 # unpack /usr
1742 for i in etc/tazlito/*.extract; do
1743 [ -f "$i" ] && . $i ../rootcd
1744 done
1745 # Umount and remove temp directory and cd to $TARGET to get stats.
1746 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
1747 cd ..
1748 status
1750 newline
1751 separator
1752 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
1753 echo "Distro tree : $(pwd)"
1754 echo "Rootfs size : $(du -sh rootfs)"
1755 echo "Rootcd size : $(du -sh rootcd)"
1756 footer
1757 ;;
1760 list-flavors)
1761 # Show available flavors.
1762 list='/etc/tazlito/flavors.list'
1763 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
1764 title 'List of flavors'
1765 cat $list
1766 footer
1767 ;;
1770 show-flavor)
1771 # Show flavor description.
1772 set -e
1773 flavor=${2%.flavor}
1774 flv_dir="$(extract_flavor "$flavor")"
1775 desc="$flv_dir/$flavor.desc"
1776 if [ -n "$brief" ]; then
1777 if [ -z "$noheader" ]; then
1778 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
1779 separator
1780 fi
1781 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
1782 "$(field ISO "$desc")" \
1783 "$(field Rootfs "$desc")" \
1784 "$(field Description "$desc")"
1785 else
1786 separator
1787 cat "$desc"
1788 fi
1789 cleanup
1790 ;;
1793 gen-liveflavor)
1794 # Generate a new flavor from the live system.
1795 FLAVOR=${2%.flavor}
1796 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1798 case "$FLAVOR" in
1799 -?|-h*|--help)
1800 cat <<EOT
1801 SliTaz Live Tool - Version: $VERSION
1803 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
1805 $(boldify '<flavor-patch-file> format:')
1806 $(optlist "\
1807 code data
1808 + package to add
1809 - package to remove
1810 ! non-free package to add
1811 ? display message
1812 @ flavor description
1813 ")
1815 $(boldify 'Example:')
1816 $(optlist "\
1817 @ Developer tools for SliTaz maintainers
1818 + slitaz-toolchain
1819 + mercurial
1820 ")
1821 EOT
1822 exit 1
1823 ;;
1824 esac
1825 mv /etc/tazlito/distro-packages.list \
1826 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
1827 rm -f distro-packages.list non-free.list 2>/dev/null
1828 tazpkg recharge
1830 DESC=""
1831 [ -n "$3" ] && \
1832 while read action pkg; do
1833 case "$action" in
1834 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
1835 -) yes | tazpkg remove $pkg ;;
1836 !) echo $pkg >> non-free.list ;;
1837 @) DESC="$pkg" ;;
1838 \?) echo -en "$pkg"; read action ;;
1839 esac
1840 done < $3
1842 yes '' | tazlito gen-distro
1843 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
1844 mv /etc/tazlito/distro-packages.list.$$ \
1845 /etc/tazlito/distro-packages.list 2>/dev/null
1846 ;;
1849 gen-flavor)
1850 # Generate a new flavor from the last ISO image generated
1851 FLAVOR=${2%.flavor}
1852 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1854 title 'Flavor generation'
1855 check_rootfs
1856 FILES="$FLAVOR.pkglist"
1858 action 'Creating file %s...' "$FLAVOR.flavor"
1859 for i in rootcd rootfs; do
1860 if [ -d "$ADDFILES/$i" ] ; then
1861 FILES="$FILES\n$FLAVOR.$i"
1862 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
1863 fi
1864 done
1865 status
1867 answer=$(grep -s ^Description $FLAVOR.desc)
1868 answer=${answer#Description : }
1869 if [ -z "$answer" ]; then
1870 echo -n "Description: "
1871 read answer
1872 fi
1874 action 'Compressing flavor %s...' "$FLAVOR"
1875 echo "Flavor : $FLAVOR" > $FLAVOR.desc
1876 echo "Description : $answer" >> $FLAVOR.desc
1877 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
1878 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
1879 for i in $(ls $ROOTFS$INSTALLED); do
1880 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
1881 EXTRAVERSION=""
1882 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
1883 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
1884 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
1885 echo "$i" >> $FLAVOR.nonfree
1886 else
1887 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
1888 fi
1889 done
1890 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
1891 for i in $LOCALSTATE/undigest/*/mirror ; do
1892 [ -s $i ] && cat $i >> $FLAVOR.mirrors
1893 done
1894 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
1895 touch -t 197001010100.00 $FLAVOR.*
1896 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
1897 rm $(echo -e $FILES)
1898 status
1900 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
1901 ;;
1904 upgrade-flavor)
1905 # Strip versions from pkglist and update estimated numbers in flavor.desc
1906 flavor="${2%.flavor}"
1907 set -e
1908 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1909 set +e
1911 flv_dir="$(extract_flavor "$flavor")"
1913 strip_versions "$flv_dir/$flavor.pkglist"
1915 action 'Updating %s...' "$flavor.desc"
1917 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
1918 set -- $(module calc_sizes "$flv_dir" "$flavor")
1919 restore_mirrors >/dev/null
1921 sed -i -e '/Image is ready/d' \
1922 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
1923 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
1924 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
1925 -e "s|\(Packages *:\).*$|\1 $4|" \
1926 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
1927 "$flv_dir/$flavor.desc"
1929 pack_flavor "$flv_dir" "$flavor"
1930 status
1931 display_unknown "$flv_dir/err"
1932 display_warn "$flv_dir/warn"
1933 cleanup
1934 ;;
1937 extract-flavor)
1938 # Extract a flavor into $FLAVORS_REPOSITORY
1939 flavor="${2%.flavor}"
1940 set -e
1941 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1942 set +e
1944 action 'Extracting %s...' "$flavor.flavor"
1945 flv_dir="$(extract_flavor "$flavor" full)"
1946 storage="$FLAVORS_REPOSITORY/$flavor"
1948 rm -rf "$storage" 2>/dev/null
1949 mkdir -p "$storage"
1950 cp -a "$flv_dir"/* "$storage"
1951 rm "$storage/description"
1952 status
1954 strip_versions "$storage/packages.list"
1956 cleanup
1957 ;;
1960 pack-flavor)
1961 # Create a flavor from $FLAVORS_REPOSITORY.
1962 flavor=${2%.flavor}
1963 storage="$FLAVORS_REPOSITORY/$flavor"
1965 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
1967 action 'Creating flavor %s...' "$flavor"
1968 tmp_dir="$(mktemp -d)"
1970 while read from to; do
1971 [ -s "$storage/$from" ] || continue
1972 cp -a "$storage/$from" "$tmp_dir/$to"
1973 done <<EOT
1974 mirrors $flavor.mirrors
1975 distro.sh $flavor-distro.sh
1976 receipt $flavor.receipt
1977 non-free.list $flavor.nonfree
1978 EOT
1980 # Build the package list.
1981 # It can include a list from another flavor with the keyword @include
1982 if [ -s "$storage/packages.list" ]; then
1983 include=$(grep '^@include' "$storage/packages.list")
1984 if [ -n "$include" ]; then
1985 include=${include#@include }
1986 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
1987 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
1988 else
1989 echo -e "\nERROR: Can't find include package list from $include\n"
1990 fi
1991 fi
1992 # Generate the final/initial package list
1993 [ -s "$storage/packages.list" ] && \
1994 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
1995 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
1996 fi
1998 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
1999 # Process multi-rootfs flavor
2000 . "$storage/receipt"
2001 set -- $ROOTFS_SELECTION
2002 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2003 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2004 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2006 for i in rootcd rootfs; do
2007 mkdir "$tmp_dir/$i"
2008 # Copy extra files from the first flavor
2009 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2010 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2011 # Overload extra files by meta flavor
2012 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2013 [ -n "$(ls $tmp_dir/$i)" ] &&
2014 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2015 dogzip "$tmp_dir/$flavor.$i"
2016 rm -rf "$tmp_dir/$i"
2017 done
2018 else
2019 # Process plain flavor
2020 for i in rootcd rootfs; do
2021 [ -d "$storage/$i" ] || continue
2022 (cd "$storage/$i";
2023 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2024 done
2025 fi
2027 unset VERSION MAINTAINER ROOTFS_SELECTION
2028 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2029 ROOTFS_SIZE="$1 (estimated)"
2030 INITRAMFS_SIZE="$2 (estimated)"
2031 ISO_SIZE="$3 (estimated)"
2032 PKGNUM="$4"
2033 . "$storage/receipt"
2035 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2036 Flavor : $FLAVOR
2037 Description : $SHORT_DESC
2038 Version : $VERSION
2039 Maintainer : $MAINTAINER
2040 LiveCD RAM size : $FRUGAL_RAM
2041 Rootfs list : $ROOTFS_SELECTION
2042 Build date : $(date '+%Y%m%d at %T')
2043 Packages : $PKGNUM
2044 Rootfs size : $ROOTFS_SIZE
2045 Initramfs size : $INITRAMFS_SIZE
2046 ISO image size : $ISO_SIZE
2047 ================================================================================
2049 EOT
2051 rm -f $tmp_dir/packages.list
2052 pack_flavor "$tmp_dir" "$flavor"
2053 status
2054 display_unknown "$tmp_dir/err"
2055 display_warn "$flv_dir/warn"
2056 cleanup
2057 ;;
2060 get-flavor)
2061 # Get a flavor's files and prepare for gen-distro.
2062 flavor=${2%.flavor}
2063 title 'Preparing %s distro flavor' "$flavor"
2064 set -e
2065 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2066 set +e
2068 action 'Cleaning %s...' "$DISTRO"
2069 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2070 # Clean old files
2071 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2072 [ -f "$i" ] && rm "$i"
2073 done
2074 mkdir -p "$DISTRO"
2075 status
2077 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2079 action 'Extracting flavor %s...' "$flavor.flavor"
2080 flv_dir="$(extract_flavor "$flavor" info)"
2081 cp -a "$flv_dir"/* .
2082 mv packages.list distro-packages.list
2083 mv -f info /etc/tazlito
2084 status
2086 for i in rootcd rootfs; do
2087 if [ -d "$i" ]; then
2088 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2089 fi
2090 done
2092 rm -f /etc/tazlito/rootfs.list
2093 grep -q '^Rootfs list' description &&
2094 grep '^Rootfs list' description | sed 's/.*: \(.*\)$/\1/' > /etc/tazlito/rootfs.list
2096 action 'Updating %s...' 'tazlito.conf'
2097 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2098 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2099 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2100 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2101 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2102 status
2104 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2105 cleanup
2106 ;;
2109 iso2flavor)
2110 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2111 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2113 FLAVOR=${3%.flavor}
2114 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2115 mount -o loop,ro $2 $TMP_DIR/iso
2116 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2117 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2118 ! -s $TMP_DIR/flavor/*.desc ]; then
2119 _ 'META flavors are not supported.'
2120 umount -d $TMP_DIR/iso
2121 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2122 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2123 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2124 umount -d $TMP_DIR/iso
2125 else
2126 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2127 uncompress $i | \
2128 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2129 done
2130 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2131 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2132 '/etc/slitaz-release' '/boot/rootfs.gz'
2133 umount -d $TMP_DIR/iso
2134 else
2135 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2136 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2137 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2138 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2139 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2140 umount -d $TMP_DIR/iso
2141 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2142 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2143 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2144 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2145 < $TMP_DIR/rootfs$INSTALLED.md5
2146 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2147 if [ -s $TMP_DIR/flavor/*desc ]; then
2148 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2149 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2150 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2151 for i in rootfs rootcd ; do
2152 [ -s $TMP_DIR/flavor/*.list$i ] &&
2153 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2154 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2155 done
2156 else
2157 find_flavor_rootfs $TMP_DIR/rootfs
2158 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2159 for i in rootfs rootcd ; do
2160 [ "$(ls $TMP_DIR/$i)" ] &&
2161 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2162 done
2163 unset VERSION MAINTAINER
2164 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2165 if [ -n "$DESCRIPTION" ]; then
2166 _n 'Flavor version : '; read -t 30 VERSION
2167 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2168 fi
2170 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2171 Flavor : $FLAVOR
2172 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2173 Version : ${VERSION:-1.0}
2174 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2175 LiveCD RAM size : $RAM_SIZE
2176 Build date : $BUILD_DATE
2177 Packages : $PKGCNT
2178 Rootfs size : $ROOTFS_SIZE
2179 Initramfs size : $INITRAMFS_SIZE
2180 ISO image size : $ISO_SIZE
2181 ================================================================================
2183 EOT
2184 longline "Tazlito can't detect each file installed during \
2185 a package post_install. You should extract this flavor (tazlito extract-flavor \
2186 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2187 tree and remove files generated by post_installs.
2188 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2189 repack the flavor (tazlito pack-flavor $FLAVOR)"
2190 fi
2191 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2192 fi
2193 fi
2194 rm -rf $TMP_DIR
2195 ;;
2198 gen-distro)
2199 # Generate a live distro tree with a set of packages.
2201 check_root
2202 start_time=$(date +%s)
2204 # Tazlito options: --iso or --cdrom
2205 CDROM=''
2206 [ -n "$iso" ] && CDROM="-o loop $iso"
2207 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2209 # Check if a package list was specified on cmdline.
2210 if [ -f "$2" ]; then
2211 LIST_NAME="$2"
2212 else
2213 LIST_NAME='distro-packages.list'
2214 fi
2216 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2217 'Please clean the distro tree or change directory path.'
2218 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2219 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2221 # If list not given: build list with all installed packages
2222 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2223 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2224 fi
2226 # Exit if no list name.
2227 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2229 # Start generation.
2230 title 'Tazlito generating a distro'
2232 # Misc checks
2233 mkdir -p "$PACKAGES_REPOSITORY"
2234 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2235 newline
2237 # Mount CD-ROM to be able to repack boot-loader packages
2238 if [ ! -e /boot -a -n "$CDROM" ]; then
2239 mkdir $TMP_MNT
2240 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2241 ln -s "$TMP_MNT/boot" /
2242 if [ ! -d "$ADDFILES/rootcd" ] ; then
2243 mkdir -p "$ADDFILES/rootcd"
2244 for i in $(ls $TMP_MNT); do
2245 [ "$i" == 'boot' ] && continue
2246 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2247 done
2248 fi
2249 else
2250 rmdir "$TMP_MNT"
2251 fi
2252 fi
2254 # Rootfs stuff.
2255 echo 'Preparing the rootfs directory...'
2256 mkdir -p "$ROOTFS"
2257 export root="$ROOTFS"
2258 strip_versions "$LIST_NAME"
2260 if [ "$REPACK" == 'y' ]; then
2261 # Determine full packages list with all dependencies
2262 tmp_dir="$(mktemp -d)"
2263 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2264 touch "$tmp_dir/full.pkglist"
2265 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2267 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2268 while read pkgname pkgver; do
2269 # Is package in full list?
2270 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2271 # Is package already repacked?
2272 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2273 _ 'Repacking %s...' "$pkgname-$pkgver"
2274 tazpkg repack "$pkgname" --quiet
2275 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2276 status
2277 done
2279 rm -r "$tmp_dir"
2280 fi
2282 if [ -f non-free.list ]; then
2283 # FIXME: working in the ROOTFS chroot?
2284 newline
2285 echo 'Preparing non-free packages...'
2286 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2287 for pkg in $(cat 'non-free.list'); do
2288 if [ ! -d "$INSTALLED/$pkg" ]; then
2289 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2290 tazpkg get-install get-$pkg
2291 fi
2292 get-$pkg "$ROOTFS"
2293 fi
2294 tazpkg repack $pkg
2295 pkg=$(ls $pkg*.tazpkg)
2296 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2297 mv $pkg $PACKAGES_REPOSITORY
2298 done
2299 fi
2300 cp $LIST_NAME $DISTRO/distro-packages.list
2301 newline
2303 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2305 cd $DISTRO
2306 cp distro-packages.list $ROOTFS/etc/tazlito
2307 # Copy all files from $ADDFILES/rootfs to the rootfs.
2308 if [ -d "$ADDFILES/rootfs" ] ; then
2309 action 'Copying addfiles content to the rootfs...'
2310 cp -a $ADDFILES/rootfs/* $ROOTFS
2311 status
2312 fi
2314 action 'Root filesystem is generated...'; status
2316 # Root CD part.
2317 action 'Preparing the rootcd directory...'
2318 mkdir -p $ROOTCD
2319 status
2321 # Move the boot dir with the Linux kernel from rootfs.
2322 # The boot dir goes directly on the CD.
2323 if [ -d "$ROOTFS/boot" ] ; then
2324 action 'Moving the boot directory...'
2325 mv $ROOTFS/boot $ROOTCD
2326 cd $ROOTCD/boot
2327 make_bzImage_hardlink
2328 status
2329 fi
2330 cd $DISTRO
2331 # Copy all files from $ADDFILES/rootcd to the rootcd.
2332 if [ -d "$ADDFILES/rootcd" ] ; then
2333 action 'Copying addfiles content to the rootcd...'
2334 cp -a $ADDFILES/rootcd/* $ROOTCD
2335 status
2336 fi
2337 # Execute the distro script used to perform tasks in the rootfs
2338 # before compression. Give rootfs path in arg
2339 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2340 if [ -x "$DISTRO_SCRIPT" ]; then
2341 echo 'Executing distro script...'
2342 sh $DISTRO_SCRIPT $DISTRO
2343 fi
2345 # Execute the custom_rules() found in receipt.
2346 if [ -s "$TOP_DIR/receipt" ]; then
2347 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2348 echo -e "Executing: custom_rules()\n"
2349 . "$TOP_DIR/receipt"
2350 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2351 fi
2352 fi
2354 # Multi-rootfs
2355 if [ -s /etc/tazlito/rootfs.list ]; then
2357 FLAVOR_LIST="$(awk '{
2358 for (i = 2; i <= NF; i+=2)
2359 printf "%s ", i;
2360 }' /etc/tazlito/rootfs.list)"
2362 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2363 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2364 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2366 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2367 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2368 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2369 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2371 n=0
2372 last=$ROOTFS
2373 while read flavor; do
2374 n=$(($n+1))
2375 mkdir ${ROOTFS}0$n
2376 export root="${ROOTFS}0$n"
2377 # initial tazpkg setup in empty rootfs
2378 tazpkg --root=$root >/dev/null 2>&1
2380 newline
2381 boldify "Building $flavor rootfs..."
2383 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2384 cp "$TOP_DIR/$flavor.flavor" .
2386 if [ ! -s "$flavor.flavor" ]; then
2387 # We may have it in $FLAVORS_REPOSITORY
2388 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2389 tazlito pack-flavor $flavor
2390 else
2391 download $flavor.flavor
2392 fi
2393 fi
2395 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2396 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2397 cp $flavor.pkglist $DISTRO/list-packages0$n
2398 status
2400 strip_versions "$DISTRO/list-packages0$n"
2402 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2404 rm -rf ${ROOTFS}0$n/boot
2406 cd $DISTRO
2407 if [ -s $flavor.rootfs ]; then
2408 _n 'Adding %s rootfs extra files...' "$flavor"
2409 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2410 fi
2412 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2413 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2414 status
2416 rm -f $flavor.flavor install-list
2417 mergefs ${ROOTFS}0$n $last
2418 last=${ROOTFS}0$n
2419 done <<EOT
2420 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2421 EOT
2422 #'
2423 i=$(($n+1))
2424 while [ $n -gt 0 ]; do
2425 mv ${ROOTFS}0$n ${ROOTFS}$i
2426 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2427 gen_initramfs ${ROOTFS}$i
2428 n=$(($n-1))
2429 i=$(($i-1))
2430 export LZMA_HISTORY_BITS=26
2431 done
2432 mv $ROOTFS ${ROOTFS}$i
2433 gen_initramfs ${ROOTFS}$i
2434 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2435 else
2436 # Initramfs and ISO image stuff.
2437 gen_initramfs $ROOTFS
2438 fi
2439 gen_livecd_isolinux
2440 distro_stats
2441 cleanup
2442 ;;
2445 clean-distro)
2446 # Remove old distro tree.
2448 check_root
2449 title 'Cleaning: %s' "$DISTRO"
2450 if [ -d "$DISTRO" ] ; then
2451 if [ -d "$ROOTFS" ] ; then
2452 action 'Removing the rootfs...'
2453 rm -f $DISTRO/$INITRAMFS
2454 rm -rf $ROOTFS
2455 status
2456 fi
2457 if [ -d "$ROOTCD" ] ; then
2458 action 'Removing the rootcd...'
2459 rm -rf $ROOTCD
2460 status
2461 fi
2462 action 'Removing eventual ISO image...'
2463 rm -f $DISTRO/$ISO_NAME.iso
2464 rm -f $DISTRO/$ISO_NAME.md5
2465 status
2466 fi
2467 footer
2468 ;;
2471 check-distro)
2472 # Check for a few LiveCD needed files not installed by packages.
2474 # TODO: Remove this function.
2475 # First two files are maintained by tazpkg while it runs on rootfs,
2476 # while last one file should be maintained by tazlito itself.
2477 check_rootfs
2478 title 'Checking distro: %s' "$ROOTFS"
2479 # SliTaz release info.
2480 rel='/etc/slitaz-release'
2481 if [ ! -f "$ROOTFS$rel" ]; then
2482 _ 'Missing release info: %s' "$rel"
2483 else
2484 action 'Release : %s' "$(cat $ROOTFS$rel)"
2485 status
2486 fi
2487 # Tazpkg mirror.
2488 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2489 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2490 todomsg
2491 else
2492 action 'Mirror configuration exists...'
2493 status
2494 fi
2495 # Isolinux msg
2496 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2497 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2498 todomsg
2499 else
2500 action 'Isolinux message seems good...'
2501 status
2502 fi
2503 footer
2504 ;;
2507 writeiso)
2508 # Writefs to ISO image including /home unlike gen-distro we don't use
2509 # packages to generate a rootfs, we build a compressed rootfs with all
2510 # the current filesystem similar to 'tazusb writefs'.
2512 DISTRO='/home/slitaz/distro'
2513 ROOTCD="$DISTRO/rootcd"
2514 COMPRESSION="${2:-none}"
2515 ISO_NAME="${3:-slitaz}"
2516 check_root
2517 # Start info
2518 title 'Write filesystem to ISO'
2519 longline "The command writeiso will write the current filesystem into a \
2520 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2521 newline
2522 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2524 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2525 # Save some space
2526 rm -rf /var/cache/tazpkg/*
2527 rm -f /var/lib/tazpkg/*.bak
2528 rm -rf $DISTRO
2530 # Optionally remove sound card selection and screen resolution.
2531 if [ -z $LaunchedByTazpanel ]; then
2532 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2533 case $anser in
2534 y)
2535 action 'Removing current sound card and screen configurations...'
2536 rm -f /var/lib/sound-card-driver
2537 rm -f /var/lib/alsa/asound.state
2538 rm -f /etc/X11/xorg.conf ;;
2539 *)
2540 action 'Keeping current sound card and screen configurations...' ;;
2541 esac
2542 status
2543 newline
2545 # Optionally remove i18n settings
2546 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2547 case $anser in
2548 y)
2549 action 'Removing current locale/keymap settings...'
2550 newline > /etc/locale.conf
2551 newline > /etc/keymap.conf ;;
2552 *)
2553 action 'Keeping current locale/keymap settings...' ;;
2554 esac
2555 status
2556 fi
2558 # Clean-up files by default
2559 newline > /etc/udev/rules.d/70-persistent-net.rules
2560 newline > /etc/udev/rules.d/70-persistant-cd.rules
2562 # Create list of files including default user files since it is defined in /etc/passwd
2563 # and some new users might have been added.
2564 cd /
2565 echo 'init' > /tmp/list
2566 for dir in bin etc sbin var dev lib root usr home opt; do
2567 [ -d $dir ] && find $dir
2568 done >> /tmp/list
2570 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2571 [ -d $dir ] && echo $dir
2572 done >> /tmp/list
2574 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2576 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2577 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2578 #fi
2579 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2580 touch /var/log/wtmp
2582 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2583 sed -i "/var\/log\/$removelog/d" /tmp/list
2584 done
2586 # Generate initramfs with specified compression and display rootfs
2587 # size in realtime.
2588 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2590 write_initramfs &
2591 sleep 2
2592 cd - > /dev/null
2593 echo -en "\nFilesystem size:"
2594 while [ ! -f /tmp/rootfs ]; do
2595 sleep 1
2596 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2597 done
2598 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2599 echo -e "\n"
2600 rm -f /tmp/rootfs
2602 # Move freshly generated rootfs to the cdrom.
2603 mkdir -p $ROOTCD/boot
2604 mv -f /$INITRAMFS $ROOTCD/boot
2605 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2607 # Now we need the kernel and isolinux files.
2608 copy_from_cd() {
2609 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2610 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2611 unmeta_boot $ROOTCD
2612 umount /media/cdrom
2615 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2616 copy_from_cd;
2617 elif mount | grep /media/cdrom; then
2618 copy_from_cd;
2619 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2620 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2621 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2622 else
2623 touch /tmp/.write-iso-error
2624 longline "When SliTaz is running in RAM the kernel and bootloader \
2625 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
2626 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
2627 echo -en "----\nENTER to continue..."; read i
2628 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2629 copy_from_cd
2630 fi
2632 # Generate the iso image.
2633 touch /tmp/.write-iso
2634 newline
2635 cd $DISTRO
2636 create_iso $ISO_NAME.iso $ROOTCD
2637 action 'Creating the ISO md5sum...'
2638 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2639 status
2641 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2642 rm -f /tmp/.write-iso
2644 if [ -z $LaunchedByTazpanel ]; then
2645 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2646 case $anser in
2647 y)
2648 umount /dev/cdrom 2>/dev/null
2649 eject
2650 echo -n "Please insert a blank CD-ROM and press ENTER..."
2651 read i && sleep 2
2652 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2653 echo -en "----\nENTER to continue..."; read i ;;
2654 *)
2655 exit 0 ;;
2656 esac
2657 fi
2658 ;;
2661 burn-iso)
2662 # Guess CD-ROM device, ask user and burn the ISO.
2664 check_root
2665 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2666 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2667 # We can specify an alternative ISO from the cmdline.
2668 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2669 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2671 title 'Tazlito burn ISO'
2672 echo "CD-ROM device : /dev/$DRIVE_NAME"
2673 echo "Drive speed : $DRIVE_SPEED"
2674 echo "ISO image : $iso"
2675 footer
2677 case $(yesorno 'Burn ISO image?' 'n') in
2678 y)
2679 title 'Starting Wodim to burn the ISO...'
2680 sleep 2
2681 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2682 footer 'ISO image is burned to CD-ROM.'
2683 ;;
2684 *)
2685 die 'Exiting. No ISO burned.'
2686 ;;
2687 esac
2688 ;;
2691 merge)
2692 # Merge multiple rootfs into one iso.
2694 if [ -z "$2" ]; then
2695 cat <<EOT
2696 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2698 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2699 i.e: rootfsN is a subset of rootfsN-1
2700 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2701 The boot loader will select the rootfs according to the RAM size detected.
2703 Example:
2704 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
2706 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
2707 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
2709 EOT
2710 exit 2
2711 fi
2713 shift # skip merge
2714 append="$1 slitaz1"
2715 shift # skip size1
2716 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
2718 ISO=$1.merged
2720 # Extract filesystems
2721 action 'Mounting %s' "$1"
2722 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
2723 status || cleanup_merge
2725 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2726 make_bzImage_hardlink $TMP_DIR/iso/boot
2727 umount -d $TMP_DIR/mnt
2728 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
2729 _ '%s is already a merged iso. Aborting.' "$1"
2730 cleanup_merge
2731 fi
2732 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
2733 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
2734 if [ ! -f /boot/isolinux/ifmem.c32 -a
2735 ! -f /boot/isolinux/c32box.c32 ]; then
2736 cat <<EOT
2737 No file /boot/isolinux/ifmem.c32
2738 Please install syslinux package !
2739 EOT
2740 rm -rf $TMP_DIR
2741 exit 1
2742 fi
2743 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
2744 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
2745 fi
2747 action 'Extracting %s' 'iso/rootfs.gz'
2748 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
2749 [ -d $TMP_DIR/rootfs1/etc ]
2750 status || cleanup_merge
2752 n=1
2753 while [ -n "$2" ]; do
2754 shift # skip rootfs N-1
2755 p=$n
2756 n=$(($n + 1))
2757 append="$append $1 slitaz$n"
2758 shift # skip size N
2759 mkdir -p $TMP_DIR/rootfs$n
2761 action 'Extracting %s' "$1"
2762 extract_rootfs $1 $TMP_DIR/rootfs$n &&
2763 [ -d "$TMP_DIR/rootfs$n/etc" ]
2764 status || cleanup_merge
2766 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
2767 action 'Creating %s' "rootfs$p.gz"
2768 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
2769 status
2770 done
2771 action 'Creating %s' "rootfs$n.gz"
2772 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
2773 status
2774 rm -f $TMP_DIR/iso/boot/rootfs.gz
2775 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
2776 create_iso $ISO $TMP_DIR/iso
2777 rm -rf $TMP_DIR
2778 ;;
2781 repack)
2782 # Repack an iso with maximum lzma compression ratio.
2784 ISO=$2
2785 mkdir -p $TMP_DIR/mnt
2787 # Extract filesystems
2788 action 'Mounting %s' "$ISO"
2789 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
2790 status || cleanup_merge
2792 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2793 umount -d $TMP_DIR/mnt
2795 for i in $TMP_DIR/iso/boot/rootfs* ; do
2796 action 'Repacking %s' "$(basename $i)"
2797 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
2798 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
2799 align_to_32bits $i
2800 status
2801 done
2803 create_iso $ISO $TMP_DIR/iso
2804 rm -rf $TMP_DIR
2805 ;;
2808 build-loram)
2809 # Build a Live CD for low RAM systems.
2811 ISO="$2"
2812 OUTPUT="$3"
2813 [ -z "$3" ] && \
2814 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
2815 mkdir -p "$TMP_DIR/iso"
2816 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
2817 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
2818 if ! check_iso_for_loram ; then
2819 umount -d "$TMP_DIR/iso"
2820 die "$ISO is not a valid SliTaz live CD. Abort."
2821 fi
2822 case "$4" in
2823 cdrom) build_loram_cdrom ;;
2824 http) build_loram_http ;;
2825 *) build_loram_ram ;;
2826 esac
2827 umount $TMP_DIR/iso # no -d: needs /proc
2828 losetup -d $loopdev
2829 rm -rf $TMP_DIR
2830 ;;
2833 emu-iso)
2834 # Emulate an ISO image with Qemu.
2835 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2836 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
2837 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
2838 echo -e "\nStarting Qemu emulator:\n"
2839 echo -e "qemu $QEMU_OPTS $iso\n"
2840 qemu $QEMU_OPTS $iso
2841 ;;
2844 deduplicate)
2845 # Deduplicate files in a tree
2846 shift
2847 deduplicate "$@"
2848 ;;
2851 usage|*)
2852 # Print usage also for all unknown commands.
2853 usage
2854 ;;
2855 esac
2857 exit 0