tazlito view tazlito @ rev 473

typo in build loram
author Pascal Bellard <pascal.bellard@slitaz.org>
date Mon Dec 25 13:03:49 2017 +0100 (2017-12-25)
parents 4bae445cd0bf
children 7a846c7d75cd
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-2017 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 touch boot/isolinux/boot.cat
283 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; > md5sum
284 status
286 cd - >/dev/null
287 title 'Generating ISO image'
289 _ 'Generating %s' "$1"
290 make_bzImage_hardlink $2/boot
291 uefi="$(cd $2 ; ls boot/isolinux/*efi*img 2> /dev/null)"
292 genisoimage -R -o $1 -hide-rr-moved -sort /tmp/cdsort$$ \
293 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
294 -no-emul-boot -boot-load-size 4 -boot-info-table \
295 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
296 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
297 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
298 -A "tazlito $VERSION/$(genisoimage --version)" \
299 -copyright README -P "www.slitaz.org" -no-pad $2
300 rm -f /tmp/cdsort$$
301 dd if=/dev/zero bs=2k count=16 >> $1 2> /dev/null
303 mkdir /tmp/mnt$$
304 mount -o loop,ro $1 /tmp/mnt$$
305 for i in boot/isolinux/isolinux.bin boot/isolinux/boot.cat ; do
306 sed -i "s|.* $i|$( cd /tmp/mnt$$ ; md5sum $i)|" $2/md5sum
307 done
308 dd if=$2/md5sum of=$1 conv=notrunc bs=2k \
309 seek=$(stat -m /tmp/mnt$$/md5sum | sed q) 2> /dev/null
310 umount -d /tmp/mnt$$
311 rmdir /tmp/mnt$$
313 if [ -s '/etc/tazlito/info' ]; then
314 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
315 action 'Storing ISO info...'
316 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
317 status
318 fi
319 fi
321 if [ -x '/usr/bin/isohybrid' ]; then
322 action 'Creating hybrid ISO...'
323 /usr/bin/isohybrid $1 -entry 2 2>/dev/null
324 status
325 fi
327 if [ -x '/usr/bin/iso2exe' ]; then
328 echo 'Creating EXE header...'
329 /usr/bin/iso2exe $1 2>/dev/null
330 fi
331 }
334 # Generate a new ISO image using isolinux.
336 gen_livecd_isolinux() {
337 # Some packages may want to alter iso
338 genisohooks iso
339 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
341 # Set date for boot msg.
342 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
343 DATE=$(date +%Y%m%d)
344 action 'Setting build date to: %s...' "$DATE"
345 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
346 status
347 fi
349 cd $DISTRO
350 create_iso $ISO_NAME.iso $ROOTCD
352 action 'Creating the ISO md5sum...'
353 md5sum $ISO_NAME.iso > $ISO_NAME.md5
354 status
356 separator
357 # Some packages may want to alter final iso
358 genisohooks final
359 }
362 lzma_history_bits() {
363 #
364 # This generates an ISO which boots with Qemu but gives
365 # rootfs errors in frugal or liveUSB mode.
366 #
367 # local n
368 # local sz
369 # n=20 # 1Mb
370 # sz=$(du -sk $1 | cut -f1)
371 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
372 # n=$(( $n + 1 ))
373 # sz=$(( $sz / 2 ))
374 # done
375 # echo $n
376 echo ${LZMA_HISTORY_BITS:-24}
377 }
380 lzma_switches() {
381 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
382 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
383 }
386 lzma_set_size() {
387 # Update size field for lzma'd file packed using -si switch
388 return # Need to fix kernel code?
390 local n i
391 n=$(unlzma < $1 | wc -c)
392 for i in $(seq 1 8); do
393 printf '\\\\x%02X' $(($n & 255))
394 n=$(($n >> 8))
395 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
396 }
399 align_to_32bits() {
400 local size=$(stat -c %s ${1:-/dev/null})
401 [ $((${size:-0} & 3)) -ne 0 ] &&
402 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
403 }
406 dogzip() {
407 gzip -9 > $1
408 [ -x /usr/bin/advdef ] && advdef -qz4 $1
409 }
412 # Pack rootfs
414 pack_rootfs() {
415 ( cd $1; find . -print | cpio -o -H newc ) | \
416 case "$COMPRESSION" in
417 none)
418 _ 'Creating %s without compression...' 'initramfs'
419 cat > $2
420 ;;
421 gzip)
422 _ 'Creating %s with gzip compression...' 'initramfs'
423 dogzip $2
424 ;;
425 *)
426 _ 'Creating %s with lzma compression...' 'initramfs'
427 lzma e -si -so $(lzma_switches $1) > $2
428 lzma_set_size $2
429 ;;
430 esac
431 align_to_32bits $2
432 echo 1 > /tmp/rootfs
433 }
436 # Compression functions for writeiso.
438 write_initramfs() {
439 case "$COMPRESSION" in
440 lzma)
441 _n 'Creating %s with lzma compression...' "$INITRAMFS"
442 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
443 align='y'
444 lzma_set_size "/$INITRAMFS"
445 ;;
446 gzip)
447 _ 'Creating %s with gzip compression...' "$INITRAMFS"
448 cpio -o -H newc | dogzip "/$INITRAMFS"
449 ;;
450 *)
451 # align='y'
452 _ 'Creating %s without compression...' "$INITRAMFS"
453 cpio -o -H newc > "/$INITRAMFS"
454 ;;
455 esac < /tmp/list
456 [ "$align" == 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
457 echo 1 > /tmp/rootfs
458 }
461 # Deduplicate files (MUST be on the same filesystem).
463 deduplicate() {
464 find "${@:-.}" -type f -size +0c -xdev -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
465 (
466 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""
467 while read attr inode link file; do
468 [ -L "$file" ] && continue
469 if [ "$attr" == "$old_attr" -a "$inode" != "$old_inode" ]; then
470 if cmp "$file" "$old_file" >/dev/null 2>&1 ; then
471 rm -f "$file"
472 if ln "$old_file" "$file" 2>/dev/null; then
473 inode="$old_inode"
474 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
475 save="$(($save+(${attr%%-*}+512)/1024))"
476 else
477 cp -a "$old_file" "$file"
478 fi
479 fi
480 fi
481 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
482 done
483 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
484 )
486 find "$@" -type l -xdev -exec stat -c '%s-%u-%g-TARGET- %i %h %n' {} \; | sort | \
487 (
488 old_attr=""; hardlinks=0;
489 while read attr inode link file; do
490 attr="${attr/-TARGET-/-$(readlink $file)}"
491 if [ "$attr" == "$old_attr" ]; then
492 if [ "$inode" != "$old_inode" ]; then
493 rm -f "$file"
494 if ln "$old_file" "$file" 2>/dev/null; then
495 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
496 else
497 cp -a "$old_file" "$file"
498 fi
499 fi
500 else
501 old_file="$file"
502 old_attr="$attr"
503 old_inode="$inode"
504 fi
505 done
506 _ '%s duplicate symlinks.' "$hardlinks"
507 )
508 }
511 # Generate a new initramfs from the root filesystem.
513 gen_initramfs() {
514 # Just in case CTRL+c
515 rm -f $DISTRO/gen
517 # Some packages may want to alter rootfs
518 genisohooks rootfs
519 cd $1
521 # Normalize file time
522 find $1 -newer $1 -exec touch -hr $1 {} \;
524 # Link duplicate files
525 deduplicate
527 # Use lzma if installed. Display rootfs size in realtime.
528 rm -f /tmp/rootfs 2>/dev/null
529 pack_rootfs . $DISTRO/$(basename $1).gz &
530 sleep 2
531 echo -en "\nFilesystem size:"
532 while [ ! -f /tmp/rootfs ]; do
533 sleep 1
534 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
535 done
536 echo -e "\n"
537 rm -f /tmp/rootfs
538 cd $DISTRO
539 mv $(basename $1).gz $ROOTCD/boot
540 }
543 distro_sizes() {
544 if [ -n "$start_time" ]; then
545 time=$(($(date +%s) - $start_time))
546 sec=$time
547 div=$(( ($time + 30) / 60))
548 [ "$div" -ne 0 ] && min="~ ${div}m"
549 _ 'Build time : %ss %s' "$sec" "$min"
550 fi
551 cat <<EOT
552 Build date : $(date +%Y%m%d)
553 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
554 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
555 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
556 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
557 EOT
558 footer "Image is ready: $ISO_NAME.iso"
559 }
562 # Print ISO and rootfs size.
564 distro_stats() {
565 title 'Distro statistics: %s' "$DISTRO"
566 distro_sizes
567 }
570 # Create an empty configuration file.
572 empty_config_file() {
573 cat >> tazlito.conf <<"EOF"
574 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
575 #
577 # Name of the ISO image to generate.
578 ISO_NAME=""
580 # ISO image volume name.
581 VOLUM_NAME="SliTaz"
583 # Name of the preparer.
584 PREPARED="$USER"
586 # Path to the packages repository and the packages.list.
587 PACKAGES_REPOSITORY=""
589 # Path to the distro tree to gen-distro from a list of packages.
590 DISTRO=""
592 # Path to the directory containing additional files
593 # to copy into the rootfs and rootcd of the LiveCD.
594 ADDFILES="$DISTRO/addfiles"
596 # Default answer for binary question (Y or N)
597 DEFAULT_ANSWER="ASK"
599 # Compression utility (lzma, gzip or none)
600 COMPRESSION="lzma"
601 EOF
602 }
605 # Extract rootfs.gz somewhere
607 extract_rootfs() {
608 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
609 # First part (lzcat or zcat) may not fail, but cpio will fail on uncorrect format
610 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
611 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
612 (cd "$2"; cat "$1" | cpio -idm --quiet 2>/dev/null)
613 }
616 # Extract flavor file to temp directory
618 extract_flavor() {
619 # Input: $1 - flavor name to extract;
620 # $2 = absent/empty: just extract 'outer layer'
621 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
622 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
623 # Output: temp dir path where flavor was extracted
624 local f="$1.flavor" from to infos="$1.desc"
625 [ -f "$f" ] || die "File '$f' not found"
626 local dir="$(mktemp -d)"
627 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
629 if [ -n "$2" ]; then
630 cd $dir
632 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
634 for i in rootcd rootfs; do
635 [ -f "$1.$i" ] || continue
636 mkdir "$i"
637 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
638 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
639 rm "$1.$i"
640 done
641 touch -t 197001010100.00 "$1.*"
642 # Info to be stored inside ISO
643 [ "$2" == info ] && echo -e $infos | cpio -o -H newc | dogzip info
644 rm $1.list*
646 # Renames
647 while read from to; do
648 [ -f "$from" ] || continue
649 mv "$from" "$to"
650 done <<EOT
651 $1.nonfree non-free.list
652 $1.pkglist packages.list
653 $1-distro.sh distro.sh
654 $1.receipt receipt
655 $1.mirrors mirrors
656 $1.desc description
657 EOT
658 fi
660 echo $dir
661 }
664 # Pack flavor file from temp directory
666 pack_flavor() {
667 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
668 }
671 # Remove duplicate files
673 files_match() {
674 if [ -d "$1" ]; then
675 return 1
677 elif [ -L "$1" ] && [ -L "$2" ]; then
678 [ "$(readlink "$1")" == "$(readlink "$2")" ] && return 0
680 elif [ -f "$1" ] && [ -f "$2" ]; then
681 cmp -s "$1" "$2" && return 0
683 [ "$(basename "$3")" == 'volatile.cpio.gz' ] &&
684 [ "$(dirname $(dirname "$3"))" == ".$INSTALLED" ] &&
685 return 0
687 elif [ "$(ls -l "$1"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$1")" == \
688 "$(ls -l "$2"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$2")" ]; then
689 return 0
691 fi
692 return 1
693 }
695 remove_with_path() {
696 dir="$(dirname $1)"
697 rm -f "$1"
698 while rmdir "$dir" 2> /dev/null; do
699 dir="$(dirname $dir)"
700 done
701 }
703 mergefs() {
704 # Note, many packages have files with spaces in the name
705 IFS=$'\n'
707 local size1=$(du -hs "$1" | awk '{ print $1 }')
708 local size2=$(du -hs "$2" | awk '{ print $1 }')
709 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
711 # merge symlinks files and devices
712 ( cd "$1"; find ) | \
713 while read file; do
714 files_match "$1/$file" "$2/$file" "$file" &&
715 remove_with_path "$2/$file"
716 done
718 unset IFS
719 status
720 }
723 cleanup_merge() {
724 rm -rf $TMP_DIR
725 exit 1
726 }
729 # Update isolinux config files for multiple rootfs
731 update_bootconfig() {
732 local files
733 action 'Updating boot config files...'
734 files="$(grep -l 'include common' $1/*.cfg)"
735 for file in $files; do
736 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
737 if (/label/) label=$0;
738 else if (/kernel/) kernel=$0;
739 else if (/append/) {
740 i=index($0,"rootfs.gz");
741 append=substr($0,i+9);
742 }
743 else if (/include/) {
744 for (i = 1; i <= n; i++) {
745 print label i
746 print kernel;
747 initrd="initrd=/boot/rootfs" n ".gz"
748 for (j = n - 1; j >= i; j--) {
749 initrd=initrd ",/boot/rootfs" j ".gz";
750 }
751 printf "\tappend %s%s\n",initrd,append;
752 print "";
753 }
754 print;
755 }
756 else print;
757 }' < $file > $file.$$
758 mv -f $file.$$ $file
759 done
760 sel="$(echo $2 | awk '{
761 for (i=1; i<=NF; i++)
762 if (i % 2 == 0) printf " slitaz%d", i/2
763 else printf " %s", $i
764 }')"
766 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
768 label slitaz
769 kernel /boot/isolinux/ifmem.c32
770 append$sel noram
772 label noram
773 config noram.cfg
775 EOT
777 # Update vesamenu
778 if [ -s "$1/isolinux.cfg" ]; then
779 files="$files $1/isolinux.cfg"
780 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
781 BEGIN {
782 kernel = " COM32 c32box.c32"
783 }
784 {
785 if (/ROWS/) print "MENU ROWS " n+$3;
786 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
787 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
788 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
789 else if (/VSHIFT/) {
790 x = $3-n;
791 if (x < 0) x = 0;
792 print "MENU VSHIFT " x;
793 }
794 else if (/rootfs.gz/) {
795 linux = "";
796 if (/bzImage/) linux = "linux /boot/bzImage ";
797 i = index($0, "rootfs.gz");
798 append = substr($0, i+9);
799 printf "\tkernel /boot/isolinux/ifmem.c32\n";
800 printf "\tappend%s noram\n", sel;
801 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
802 for (i = 1; i <= n; i++) {
803 print "LABEL slitaz" i
804 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
805 printf "%s\n", kernel;
806 initrd = "initrd=/boot/rootfs" n ".gz"
807 for (j = n - 1; j >= i; j--) {
808 initrd = initrd ",/boot/rootfs" j ".gz";
809 }
810 printf "\tappend %s%s%s\n\n", linux, initrd, append;
811 }
812 }
813 else if (/bzImage/) kernel = $0;
814 else print;
815 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
816 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
817 fi
819 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
820 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
821 cat > $1/noram.cfg <<EOT
822 implicit 0
823 prompt 1
824 timeout 80
825 $(grep '^F[0-9]' $1/isolinux.cfg)
827 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
828 say Not enough RAM to boot slitaz. Trying hacker mode...
829 default hacker
830 label hacker
831 KERNEL /boot/bzImage
832 append rw root=/dev/null vga=normal
834 label reboot
835 EOT
837 if [ -s $1/c32box.c32 ]; then
838 cat >> $1/noram.cfg <<EOT
839 COM32 c32box.c32
840 append reboot
842 label poweroff
843 COM32 c32box.c32
844 append poweroff
846 EOT
847 else
848 echo " com32 reboot.c32" >> $1/noram.cfg
849 fi
851 # Restore real label names
852 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
853 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
854 while read pat; do
855 sed -i "s/slitaz$pat/" $files
856 done
857 status
858 }
861 # Uncompress rootfs or module to stdout
863 uncompress() {
864 zcat $1 2> /dev/null || xzcat $1 2> /dev/null ||
865 { [ $(od -N 1 -An $1) -eq 135 ] && unlzma < $1; } || cat $1
866 }
869 # Install a missing package
871 install_package() {
872 if [ -z "$2" ]; then
873 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
874 else
875 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
876 fi
877 case "$answer" in
878 y)
879 # We don't want package on host cache.
880 action 'Getting and installing package: %s' "$1"
881 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
882 status ;;
883 *)
884 return 1 ;;
885 esac
886 }
889 # Check iso for loram transformation
891 check_iso_for_loram() {
892 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
893 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
894 }
897 # Build initial rootfs for loram ISO ram/cdrom/http
899 build_initfs() {
900 urliso="mirror.switch.ch/ftp/mirror/slitaz \
901 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
902 mirror3.slitaz.org mirror.slitaz.org"
903 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
904 [ -z "$version" ] && die "Can't find the kernel version." \
905 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
907 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
908 need_lib=false
909 for i in bin dev run mnt proc tmp sys lib/modules; do
910 mkdir -p $TMP_DIR/initfs/$i
911 done
912 ln -s bin $TMP_DIR/initfs/sbin
913 ln -s . $TMP_DIR/initfs/usr
914 for aufs in aufs overlayfs; do
915 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
916 install_package $aufs $version && break
917 done || return 1
918 [ -s /init ] || install_package slitaz-boot-scripts
919 cp /init $TMP_DIR/initfs/
920 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
921 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
922 $TMP_DIR/initfs/lib/modules 2>/dev/null
923 cp -a /dev/tty0 /dev/fd0 $TMP_DIR/initfs/dev 2>/dev/null
924 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
925 $TMP_DIR/initfs/lib/modules
926 if [ "$1" == 'cdrom' ]; then
927 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
928 else
929 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
930 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
931 install_package linux-squashfs $version || return 1
932 done
933 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
934 $TMP_DIR/initfs/lib/modules
935 ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
936 cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
937 fi
938 for i in $(ls /dev/[hs]d[a-f]*); do
939 cp -a $i $TMP_DIR/initfs/dev
940 done
941 if [ "$1" == 'http' ]; then
942 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
943 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
944 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
945 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
946 cp -a /dev/fuse $TMP_DIR/initfs/dev
947 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
948 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
949 else
950 need_lib=true
951 fi
952 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
953 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
954 else
955 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
956 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
957 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
958 cp -a /lib/librt* $TMP_DIR/initfs/lib
959 cp -a /lib/libdl* $TMP_DIR/initfs/lib
960 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
961 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
962 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
963 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
964 need_lib=true
965 fi
966 cd $TMP_DIR/fs
967 echo 'Getting slitaz-release & ethernet modules...'
968 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
969 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
970 [ -s rootfs* ] || continue
971 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
972 rm -f rootfs*
973 done 2>&1 > /dev/null
974 cd - > /dev/null
975 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
976 find $TMP_DIR/fs/lib/modules/*/kernel/drivers/net/ethernet \
977 -type f -name '*.ko*' | while read mod; do
978 f=$TMP_DIR/initfs/lib/modules/$(basename $mod | sed s/..z$//)
979 uncompress $mod > $f
980 grep -q alias=pci: $f || rm -f $f
981 done
982 for i in $TMP_DIR/initfs/lib/modules/*.ko ; do
983 f=$(basename $i)..z
984 grep -q $f:$ $TMP_DIR/fs/lib/modules/*/modules.dep && continue
985 deps="$(grep $f: $TMP_DIR/fs/lib/modules/*/modules.dep | sed 's/.*: //')"
986 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > $TMP_DIR/initfs/lib/modules/$(basename $i .ko).dep
987 for j in $deps; do
988 mod=$(ls $TMP_DIR/fs/lib/modules/*/$j)
989 uncompress $mod > $TMP_DIR/initfs/lib/modules/$(basename $j | sed s/..z$//)
990 done
991 done
992 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"
993 _n 'List of URLs to insert: '
994 read -t 30 urliso2
995 urliso="$urliso2 $urliso"
996 fi
997 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
998 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
999 sed -i 's/LD_T.*ot/newline/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
1000 else
1001 cp /bin/busybox $TMP_DIR/initfs/bin
1002 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
1003 cp /sbin/insmod $TMP_DIR/initfs/bin
1004 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
1005 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
1006 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
1007 fi
1008 need_lib=true
1009 fi
1010 for i in $($TMP_DIR/initfs/bin/busybox | awk \
1011 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
1012 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1013 done
1014 for i in /dev/console /dev/loop* /dev/null /dev/tty /dev/zero \
1015 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1016 cp -a $i $TMP_DIR/initfs/dev
1017 done
1018 $need_lib && for i in /lib/ld-* /lib/lib[cm].so* /lib/lib[cm]-* ; do
1019 cp -a $i $TMP_DIR/initfs/lib
1020 done
1021 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1022 #!/bin/sh
1024 getarg() {
1025 grep -q " \$1=" /proc/cmdline || return 1
1026 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1027 return 0
1030 copy_rootfs() {
1031 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1032 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1033 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1034 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1035 path=/mnt/
1036 return 0
1037 else
1038 rm -f /mnt/rootfs*
1039 return 1
1040 fi
1043 echo "Switching / to tmpfs..."
1044 mount -t proc proc /proc
1045 size="\$(grep rootfssize= < /proc/cmdline | \\
1046 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1047 [ -n "\$size" ] || size="-o size=90%"
1049 mount -t sysfs sysfs /sys
1050 for i in /lib/modules/*.ko ; do
1051 echo -en "Probe \$i \\r"
1052 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1053 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1054 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1055 insmod /lib/modules/\$k.ko 2> /dev/null
1056 done
1057 echo "Loading \$i"
1058 insmod \$i 2> /dev/null
1059 break
1060 done
1061 done
1062 umount /sys
1063 while read var default; do
1064 eval \$var=\$default
1065 getarg \$var \$var
1066 done <<EOT
1067 eth eth0
1068 dns 208.67.222.222,208.67.220.220
1069 netmask 255.255.255.0
1070 gw
1071 ip
1072 EOT
1073 grep -q \$eth /proc/net/dev || sh
1074 if [ -n "\$ip" ]; then
1075 ifconfig \$eth \$ip netmask \$netmask up
1076 route add default gateway \$gw
1077 for i in \$(echo \$dns | sed 's/,/ /g'); do
1078 echo "nameserver \$i" >> /etc/resolv.conf
1079 done
1080 else
1081 udhcpc -f -q -s /lib/udhcpc -i \$eth
1082 fi
1083 for i in $urliso ; do
1084 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1085 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"
1086 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1087 done
1088 getarg urliso URLISO
1089 DIR=fs
1090 if getarg loram DIR; then
1091 DEVICE=\${DIR%,*}
1092 DIR=/\${DIR#*,}
1093 fi
1094 mount -t tmpfs \$size tmpfs /mnt
1095 path2=/mnt/.httpfs/
1096 path=/mnt/.cdrom/
1097 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1098 while [ ! -d \$path/boot ]; do
1099 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1100 httpfs \$i \$path2 && echo \$i && break
1101 done
1102 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1103 done
1105 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1106 umount /proc
1107 branch=:/mnt/.cdrom/\$DIR
1108 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1109 branch=
1110 lp=1
1111 insmod /lib/modules/squashfs.ko 2> /dev/null
1112 for i in \${path}boot/rootfs?.* ; do
1113 fs=\${i#*root}
1114 branch=\$branch:/mnt/.\$fs
1115 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1116 losetup -o 124 /dev/loop\$lp \$i
1117 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1118 lp=\$((\$lp+1))
1119 done
1120 fi
1121 mkdir -p /mnt/.rw/mnt/.httpfs
1122 while read type opt; do
1123 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1124 done <<EOT
1125 aufs br=/mnt/.rw\$branch
1126 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1127 EOT
1128 rm -rf /lib/modules
1129 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1130 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1131 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1132 EOTEOT
1133 chmod +x $TMP_DIR/initfs/init
1134 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1135 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1136 rm -f $i
1137 dogzip ${i%.gz}
1138 done 2>/dev/null
1139 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1140 lzma e $TMP_DIR/initfs.gz -si
1141 lzma_set_size $TMP_DIR/initfs.gz
1142 rm -rf $TMP_DIR/initfs
1143 align_to_32bits $TMP_DIR/initfs.gz
1144 return 0
1148 # Move each initramfs to squashfs
1150 build_loram_rootfs() {
1151 rootfs_sizes=""
1152 for i in $TMP_DIR/iso/boot/rootfs*; do
1153 mkdir -p $TMP_DIR/fs
1154 cd $TMP_DIR/fs
1155 uncompress $i | cpio -idm
1156 deduplicate
1157 cd - > /dev/null
1158 rootfs=$TMP_DIR/$(basename $i)
1159 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp ${1:-xz -Xbcj x86}
1160 cd $TMP_DIR
1161 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1162 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1163 rm -f $rootfs
1164 mv $rootfs.cpio $rootfs
1165 cd - > /dev/null
1166 rm -rf $TMP_DIR/fs
1167 done
1171 # Move meta boot configuration files to basic configuration files
1172 # because meta loram flavor is useless when rootfs is not loaded in RAM
1174 unmeta_boot() {
1175 local root=${1:-$TMP_DIR/loramiso}
1176 if [ -f $root/boot/isolinux/noram.cfg ]; then
1177 # We keep enough information to do unloram...
1178 [ -s $root/boot/isolinux/common.cfg ] &&
1179 sed -i 's/label slitaz/label orgslitaz/' \
1180 $root/boot/isolinux/common.cfg
1181 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1182 shift
1183 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1184 $root/boot/isolinux/isolinux.cfg
1185 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1186 sed -i "s/label $3\$/label slitaz/;s|=\(.*rootfs\)\(.*\)\.gz |=\1.gz |" \
1187 $root/boot/isolinux/*.cfg
1188 fi
1192 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1193 # These squashfs may be loaded in RAM at boot time.
1194 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1195 # Meta flavors are converted to normal flavors.
1197 build_loram_cdrom() {
1198 build_initfs cdrom || return 1
1199 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1200 mkdir $TMP_DIR/loramiso/fs
1201 cd $TMP_DIR/loramiso/fs
1202 for i in $( ls ../boot/root* | sort -r ) ; do
1203 uncompress $i | cpio -idmu
1204 rm -f $i
1205 done
1206 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1207 cd - >/dev/null
1208 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1209 unmeta_boot
1210 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1211 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1212 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1213 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1214 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1215 create_iso $OUTPUT $TMP_DIR/loramiso
1219 # Create http bootstrap to load and remove loram_cdrom
1220 # Meta flavors are converted to normal flavors.
1222 build_loram_http() {
1223 build_initfs http || return 1
1224 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1225 rm -f $TMP_DIR/loramiso/boot/rootfs*
1226 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1227 unmeta_boot
1228 create_iso $OUTPUT $TMP_DIR/loramiso
1232 # Update meta flavor selection sizes.
1233 # Reduce sizes with rootfs gains.
1235 update_metaiso_sizes() {
1236 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1237 do
1238 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1239 local sizes="$rootfs_sizes"
1240 local new
1241 set -- $append
1242 shift
1243 [ "$1" == "ifmem" ] && shift
1244 new=""
1245 while [ -n "$2" ]; do
1246 local s
1247 case "$1" in
1248 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1249 *M) s=$(( ${1%M} * 1024 ));;
1250 *) s=${1%K};;
1251 esac
1252 sizes=${sizes#* }
1253 for i in $sizes ; do
1254 s=$(( $s - $i ))
1255 done
1256 new="$new $s $2"
1257 shift 2
1258 done
1259 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1260 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1261 sed -i 's|\(initrd=\)\([^r]*\)\(rootfs\)|\1\2rootfs.gz,\2\3|' $cfg
1262 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1263 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1264 done
1268 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1269 # Meta flavor selection sizes are updated.
1271 build_loram_ram() {
1272 build_initfs ram || return 1
1273 build_loram_rootfs "$1"
1274 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1275 make_bzImage_hardlink $TMP_DIR/loramiso/boot
1276 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1277 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1278 update_metaiso_sizes
1279 create_iso $OUTPUT $TMP_DIR/loramiso
1283 # Remove files installed by packages
1285 find_flavor_rootfs() {
1286 for i in $1/etc/tazlito/*.extract; do
1287 [ -e $i ] || continue
1288 chroot $1 /bin/sh ${i#$1}
1289 done
1291 # Clean hardlinks and files patched by genisofs in /boot
1292 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1293 rm -f $1/boot/$i*
1294 done
1296 # Clean files generated in post_install
1297 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1298 $1/dev/core $1/dev/fd $1/dev/std*
1300 # Verify md5
1301 cat $1$INSTALLED/*/md5sum | \
1302 while read md5 file; do
1303 [ -e "$1$file" ] || continue
1304 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1305 rm -f "$1$file"
1306 done
1308 # Check configuration files
1309 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1310 [ -e $i ] || continue
1311 mkdir /tmp/volatile$$
1312 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1313 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1314 while read file ; do
1315 [ -e "$1/$file" ] || continue
1316 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1317 done
1318 rm -rf /tmp/volatile$$
1319 done
1321 # Remove other files blindly
1322 for i in $1$INSTALLED/*/files.list; do
1323 for file in $(cat "$i"); do
1324 [ "$1$file" -nt "$i" ] && continue
1325 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1326 [ -d "$1$file" ] || rm -f "$1$file"
1327 done
1328 done
1330 # Remove tazpkg files and tmp files
1331 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1332 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1333 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1334 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1335 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1337 # Cleanup directory tree
1338 cd $1
1339 find * -type d | sort -r | while read dir; do
1340 rmdir "$dir" 2>/dev/null
1341 done
1342 cd - > /dev/null
1346 # Get byte(s) from a binary file
1348 get() {
1349 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null
1353 # Get cpio flavor info from the ISO image
1355 flavordata() {
1356 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1357 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1361 # Restore undigest mirrors
1363 restore_mirrors() {
1364 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1365 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1367 action 'Restoring mirrors...'
1368 if [ -d "$undigest.bak" ]; then
1369 [ -d "$undigest" ] && rm -r "$undigest"
1370 mv "$undigest.bak" "$undigest"
1371 fi
1372 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1373 :; status
1377 # Setup undigest mirrors
1379 setup_mirrors() {
1380 # Setup mirrors in plain system or in chroot (with variable root=)
1381 local mirrorlist="$1" fresh repacked
1382 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1384 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1385 restore_mirrors
1387 _ 'Setting up mirrors for %s...' "$root/"
1388 # Backing up current undigest mirrors and priority
1389 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1390 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1391 rm -rf '/var/www/tazlito/'
1392 mkdir -p '/var/www/tazlito/'
1394 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1395 fresh='/home/slitaz/packages'
1396 if [ -d "$fresh" ]; then
1397 # Setup first undigest mirror
1398 mkdir -p "$undigest/fresh"
1399 echo "$fresh" > "$undigest/fresh/mirror"
1400 echo 'fresh' >> "$priority"
1401 # Rebuild mirror DB if needed
1402 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1403 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1404 tazpkg mkdb "$fresh" --forced --root=''
1405 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1406 fi
1408 # Repacked packages: high priority
1409 repacked="$PACKAGES_REPOSITORY"
1410 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1411 # According to Tazlito setup file (tazlito.conf):
1412 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1413 # or
1414 # WORK_DIR="/home/slitaz"
1415 # and
1416 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1417 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1419 # Setup second undigest mirror
1420 mkdir -p "$undigest/repacked"
1421 echo "$repacked" > "$undigest/repacked/mirror"
1422 echo 'repacked' >> "$priority"
1423 # Rebuild mirror DB if needed
1424 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1425 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1426 tazpkg mkdb "$repacked" --forced --root=''
1427 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1428 fi
1430 # All repositories listed in mirrors list: normal priority
1431 [ -e "$mirrorlist" ] && \
1432 while read mirror; do
1433 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1434 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1435 mkdir -p "$undigest/$mirrorid"
1436 echo "$mirror" > "$undigest/$mirrorid/mirror"
1437 echo "$mirrorid" >> "$priority"
1438 done < "$mirrorlist"
1440 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1442 # Show list of mirrors
1443 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1444 function show(num, name, url) {
1445 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1448 num++;
1449 "cat " db "/undigest/" $0 "/mirror" | getline url;
1450 show(num, $0, url);
1452 END {
1453 num++;
1454 "cat " db "/mirror" | getline url;
1455 show(num, "main", url);
1456 }' "$priority"
1458 tazpkg recharge --quiet >/dev/null
1462 # Get list of 'packages.info' lists using priority
1464 pi_lists() {
1465 local pi
1466 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1467 local priority="$root$LOCALSTATE/priority"
1468 local undigest="$root$LOCALSTATE/undigest"
1471 [ -s "$priority" ] && cat "$priority"
1472 echo 'main'
1473 [ -d "$undigest" ] && ls "$undigest"
1474 } | awk -vun="$undigest/" '
1476 if (arr[$0] != 1) {
1477 arr[$0] = 1;
1478 print un $0 "/packages.info";
1480 }' | sed 's|/undigest/main||' | \
1481 while read pi; do
1482 [ -e "$pi" ] && echo "$pi"
1483 done
1487 # Strip versions from packages list
1489 strip_versions() {
1490 if [ -n "$stripped" ]; then
1491 action 'Consider list %s already stripped' "$(basename "$1")"
1492 status
1493 return 0
1494 fi
1495 action 'Strip versions from list %s...' "$(basename "$1")"
1496 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1497 [ -f "$in_list" ] || die "List '$in_list' not found."
1499 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1500 awk '
1502 if (FILENAME ~ "packages.info") {
1503 # Collect package names
1504 FS = "\t"; pkg[$1] = 1;
1505 } else {
1506 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1507 while (NF > 1 && ! pkg[$0])
1508 NF --;
1509 printf "%s\n", $0;
1511 }' $(pi_lists) "$in_list" > "$tmp_list"
1513 cat "$tmp_list" > "$in_list"
1514 rm "$tmp_list"
1515 status
1519 # Display list of unknown packages (informative)
1521 display_unknown() {
1522 [ -s "$1" ] || return
1523 echo "Unknown packages:" >&2
1524 cat "$1" >&2
1525 rm "$1"
1529 # Display warnings about critical packages absent (informative)
1531 display_warn() {
1532 [ -s "$1" ] || return
1533 echo "Absent critical packages:" >&2
1534 cat "$1" >&2
1535 rm "$1"
1536 echo "Probably ISO image will be unusable."
1540 # Install packages to rootfs
1542 install_list_to_rootfs() {
1543 local list="$1" rootfs="$2" pkg i ii
1544 local undigest="$rootfs/var/lib/tazpkg/undigest"
1546 # initial tazpkg setup in empty rootfs
1547 tazpkg --root=$rootfs >/dev/null 2>&1
1548 # pass current 'mirror' to the rootfs
1549 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
1550 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
1551 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
1552 # link rootfs packages cache to the regular packages cache
1553 rm -r "$rootfs/var/cache/tazpkg"
1554 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1556 setup_mirrors mirrors
1558 # Just in case if flavor not contains "tazlito" package
1559 mkdir -p "$rootfs/etc/tazlito"
1561 newline
1563 # Choose detailed log with --detailed
1564 if [ -n "$detailed" ]; then
1565 while read pkg; do
1566 separator '-'
1567 echo $pkg
1568 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
1569 done < $list
1570 separator '='
1571 else
1572 while read pkg; do
1573 action 'Installing package: %s' "$pkg"
1574 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1575 status
1576 done < $list
1577 fi
1578 newline
1580 restore_mirrors
1581 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1582 for i in fresh repacked; do
1583 ii="$undigest/$i"
1584 [ -d "$ii" ] && rm -rf "$ii"
1585 ii="$rootfs/var/lib/tazpkg/priority"
1586 if [ -f "$ii" ]; then
1587 sed -i "/$i/d" "$ii"
1588 [ -s "$ii" ] || rm "$ii"
1589 fi
1590 done
1591 [ -d "$undigest" ] && \
1592 for i in $(find "$undigest" -type f); do
1593 # Remove all undigest PKGDB files but 'mirror'
1594 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1595 done
1596 [ -d "$undigest" ] && \
1597 rmdir --ignore-fail-on-non-empty "$undigest"
1599 # Un-link packages cache
1600 rm "$rootfs/var/cache/tazpkg"
1602 # Clean /var/lib/tazpkg
1603 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1609 ####################
1610 # Tazlito commands #
1611 ####################
1613 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1614 case "$0" in
1615 *reduplicate)
1616 find ${@:-.} ! -type d -links +1 \
1617 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1618 exit 0 ;;
1619 *deduplicate)
1620 deduplicate "$@"
1621 exit 0 ;;
1622 esac
1625 case "$COMMAND" in
1626 stats)
1627 # Tazlito general statistics from the config file.
1629 title 'Tazlito statistics'
1630 optlist "\
1631 Config file : $CONFIG_FILE
1632 ISO name : $ISO_NAME.iso
1633 Volume name : $VOLUM_NAME
1634 Prepared : $PREPARED
1635 Packages repository : $PACKAGES_REPOSITORY
1636 Distro directory : $DISTRO
1637 Additional files : $ADDFILES
1638 " | sed '/: $/d'
1639 footer
1640 ;;
1643 list-addfiles)
1644 # Simple list of additional files in the rootfs
1645 newline
1646 if [ -d "$ADDFILES/rootfs" ]; then
1647 cd $ADDFILES
1648 find rootfs -type f
1649 else
1650 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1651 fi
1652 newline
1653 ;;
1656 gen-config)
1657 # Generate a new config file in the current dir or the specified
1658 # directory by $2.
1660 if [ -n "$2" ]; then
1661 mkdir -p "$2" && cd "$2"
1662 fi
1664 newline
1665 action 'Generating empty tazlito.conf...'
1666 empty_config_file
1667 status
1669 separator
1670 if [ -f 'tazlito.conf' ] ; then
1671 _ 'Configuration file is ready to edit.'
1672 _ 'File location: %s' "$(pwd)/tazlito.conf"
1673 newline
1674 fi
1675 ;;
1678 configure)
1679 # Configure a tazlito.conf config file. Start by getting
1680 # a empty config file and sed it.
1682 if [ -f 'tazlito.conf' ]; then
1683 rm tazlito.conf
1684 else
1685 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1686 'or in the same directory of the file you want to configure.'
1687 cd /etc
1688 fi
1690 empty_config_file
1692 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1694 # ISO name.
1695 echo -n "ISO name : " ; read answer
1696 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1697 # Volume name.
1698 echo -n "Volume name : " ; read answer
1699 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1700 # Packages repository.
1701 echo -n "Packages repository : " ; read answer
1702 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1703 # Distro path.
1704 echo -n "Distro path : " ; read answer
1705 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1706 footer "Config file is ready to use."
1707 echo 'You can now extract an ISO or generate a distro.'
1708 newline
1709 ;;
1712 gen-iso)
1713 # Simply generate a new iso.
1715 check_root
1716 verify_rootcd
1717 gen_livecd_isolinux
1718 distro_stats
1719 ;;
1722 gen-initiso)
1723 # Simply generate a new initramfs with a new iso.
1725 check_root
1726 verify_rootcd
1727 gen_initramfs "$ROOTFS"
1728 gen_livecd_isolinux
1729 distro_stats
1730 ;;
1733 extract-distro)
1734 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1736 check_root
1737 ISO_IMAGE="$2"
1738 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1739 'Example:\n tazlito image.iso /path/target'
1741 # Set the distro path by checking for $3 on cmdline.
1742 TARGET="${3:-$DISTRO}"
1744 # Exit if existing distro is found.
1745 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1746 'Please clean the distro tree or change directory path.'
1748 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
1750 # Start to mount the ISO.
1751 action 'Mounting ISO image...'
1752 mkdir -p "$TMP_DIR"
1753 # Get ISO file size.
1754 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
1755 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
1756 sleep 2
1757 # Prepare target dir, copy the kernel and the rootfs.
1758 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
1759 status
1761 action 'Copying the Linux kernel...'
1762 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
1763 make_bzImage_hardlink "$TARGET/rootcd/boot"
1764 else
1765 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
1766 fi
1767 status
1769 for i in $(ls $TMP_DIR); do
1770 [ "$i" == 'boot' ] && continue
1771 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
1772 done
1774 for loader in isolinux syslinux extlinux grub; do
1775 [ -d "$TMP_DIR/boot/$loader" ] || continue
1776 action 'Copying %s files...' "$loader"
1777 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
1778 status
1779 done
1781 action 'Copying the rootfs...'
1782 cp $TMP_DIR/boot/rootfs.?z "$TARGET/rootcd/boot"
1783 status
1785 # Extract initramfs.
1786 cd "$TARGET/rootfs"
1787 action 'Extracting the rootfs...'
1788 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
1789 # unpack /usr
1790 for i in etc/tazlito/*.extract; do
1791 [ -f "$i" ] && . $i ../rootcd
1792 done
1793 # Umount and remove temp directory and cd to $TARGET to get stats.
1794 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
1795 cd ..
1796 status
1798 newline
1799 separator
1800 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
1801 echo "Distro tree : $(pwd)"
1802 echo "Rootfs size : $(du -sh rootfs)"
1803 echo "Rootcd size : $(du -sh rootcd)"
1804 footer
1805 ;;
1808 list-flavors)
1809 # Show available flavors.
1810 list='/etc/tazlito/flavors.list'
1811 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
1812 title 'List of flavors'
1813 cat $list
1814 footer
1815 ;;
1818 show-flavor)
1819 # Show flavor description.
1820 set -e
1821 flavor=${2%.flavor}
1822 flv_dir="$(extract_flavor "$flavor")"
1823 desc="$flv_dir/$flavor.desc"
1824 if [ -n "$brief" ]; then
1825 if [ -z "$noheader" ]; then
1826 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
1827 separator
1828 fi
1829 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
1830 "$(field ISO "$desc")" \
1831 "$(field Rootfs "$desc")" \
1832 "$(field Description "$desc")"
1833 else
1834 separator
1835 cat "$desc"
1836 fi
1837 cleanup
1838 ;;
1841 gen-liveflavor)
1842 # Generate a new flavor from the live system.
1843 FLAVOR=${2%.flavor}
1844 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1846 case "$FLAVOR" in
1847 -?|-h*|--help)
1848 cat <<EOT
1849 SliTaz Live Tool - Version: $VERSION
1851 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
1853 $(boldify '<flavor-patch-file> format:')
1854 $(optlist "\
1855 code data
1856 + package to add
1857 - package to remove
1858 ! non-free package to add
1859 ? display message
1860 @ flavor description
1861 ")
1863 $(boldify 'Example:')
1864 $(optlist "\
1865 @ Developer tools for SliTaz maintainers
1866 + slitaz-toolchain
1867 + mercurial
1868 ")
1869 EOT
1870 exit 1
1871 ;;
1872 esac
1873 mv /etc/tazlito/distro-packages.list \
1874 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
1875 rm -f distro-packages.list non-free.list 2>/dev/null
1876 tazpkg recharge
1878 DESC=""
1879 [ -n "$3" ] && \
1880 while read action pkg; do
1881 case "$action" in
1882 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
1883 -) yes | tazpkg remove $pkg ;;
1884 !) echo $pkg >> non-free.list ;;
1885 @) DESC="$pkg" ;;
1886 \?) echo -en "$pkg"; read action ;;
1887 esac
1888 done < $3
1890 yes '' | tazlito gen-distro
1891 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
1892 mv /etc/tazlito/distro-packages.list.$$ \
1893 /etc/tazlito/distro-packages.list 2>/dev/null
1894 ;;
1897 gen-flavor)
1898 # Generate a new flavor from the last ISO image generated
1899 FLAVOR=${2%.flavor}
1900 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
1902 title 'Flavor generation'
1903 check_rootfs
1904 FILES="$FLAVOR.pkglist"
1906 action 'Creating file %s...' "$FLAVOR.flavor"
1907 for i in rootcd rootfs; do
1908 if [ -d "$ADDFILES/$i" ] ; then
1909 FILES="$FILES\n$FLAVOR.$i"
1910 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
1911 fi
1912 done
1913 status
1915 answer=$(grep -s ^Description $FLAVOR.desc)
1916 answer=${answer#Description : }
1917 if [ -z "$answer" ]; then
1918 echo -n "Description: "
1919 read answer
1920 fi
1922 action 'Compressing flavor %s...' "$FLAVOR"
1923 echo "Flavor : $FLAVOR" > $FLAVOR.desc
1924 echo "Description : $answer" >> $FLAVOR.desc
1925 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
1926 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
1927 for i in $(ls $ROOTFS$INSTALLED); do
1928 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
1929 EXTRAVERSION=""
1930 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
1931 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
1932 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
1933 echo "$i" >> $FLAVOR.nonfree
1934 else
1935 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
1936 fi
1937 done
1938 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
1939 for i in $LOCALSTATE/undigest/*/mirror ; do
1940 [ -s $i ] && cat $i >> $FLAVOR.mirrors
1941 done
1942 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
1943 touch -t 197001010100.00 $FLAVOR.*
1944 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
1945 rm $(echo -e $FILES)
1946 status
1948 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
1949 ;;
1952 upgrade-flavor)
1953 # Strip versions from pkglist and update estimated numbers in flavor.desc
1954 flavor="${2%.flavor}"
1955 set -e
1956 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1957 set +e
1959 flv_dir="$(extract_flavor "$flavor")"
1961 strip_versions "$flv_dir/$flavor.pkglist"
1963 action 'Updating %s...' "$flavor.desc"
1965 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
1966 set -- $(module calc_sizes "$flv_dir" "$flavor")
1967 restore_mirrors >/dev/null
1969 sed -i -e '/Image is ready/d' \
1970 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
1971 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
1972 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
1973 -e "s|\(Packages *:\).*$|\1 $4|" \
1974 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
1975 "$flv_dir/$flavor.desc"
1977 pack_flavor "$flv_dir" "$flavor"
1978 status
1979 display_unknown "$flv_dir/err"
1980 display_warn "$flv_dir/warn"
1981 cleanup
1982 ;;
1985 extract-flavor)
1986 # Extract a flavor into $FLAVORS_REPOSITORY
1987 flavor="${2%.flavor}"
1988 set -e
1989 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
1990 set +e
1992 action 'Extracting %s...' "$flavor.flavor"
1993 flv_dir="$(extract_flavor "$flavor" full)"
1994 storage="$FLAVORS_REPOSITORY/$flavor"
1996 rm -rf "$storage" 2>/dev/null
1997 mkdir -p "$storage"
1998 cp -a "$flv_dir"/* "$storage"
1999 rm "$storage/description"
2000 status
2002 strip_versions "$storage/packages.list"
2004 cleanup
2005 ;;
2008 pack-flavor)
2009 # Create a flavor from $FLAVORS_REPOSITORY.
2010 flavor=${2%.flavor}
2011 storage="$FLAVORS_REPOSITORY/$flavor"
2013 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2015 action 'Creating flavor %s...' "$flavor"
2016 tmp_dir="$(mktemp -d)"
2018 while read from to; do
2019 [ -s "$storage/$from" ] || continue
2020 cp -a "$storage/$from" "$tmp_dir/$to"
2021 done <<EOT
2022 mirrors $flavor.mirrors
2023 distro.sh $flavor-distro.sh
2024 receipt $flavor.receipt
2025 non-free.list $flavor.nonfree
2026 EOT
2028 # Build the package list.
2029 # It can include a list from another flavor with the keyword @include
2030 if [ -s "$storage/packages.list" ]; then
2031 include=$(grep '^@include' "$storage/packages.list")
2032 if [ -n "$include" ]; then
2033 include=${include#@include }
2034 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2035 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2036 else
2037 echo -e "\nERROR: Can't find include package list from $include\n"
2038 fi
2039 fi
2040 # Generate the final/initial package list
2041 [ -s "$storage/packages.list" ] && \
2042 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2043 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2044 fi
2046 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2047 # Process multi-rootfs flavor
2048 . "$storage/receipt"
2049 set -- $ROOTFS_SELECTION
2050 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2051 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2052 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2054 for i in rootcd rootfs; do
2055 mkdir "$tmp_dir/$i"
2056 # Copy extra files from the first flavor
2057 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2058 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2059 # Overload extra files by meta flavor
2060 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2061 [ -n "$(ls $tmp_dir/$i)" ] &&
2062 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2063 dogzip "$tmp_dir/$flavor.$i"
2064 rm -rf "$tmp_dir/$i"
2065 done
2066 else
2067 # Process plain flavor
2068 for i in rootcd rootfs; do
2069 [ -d "$storage/$i" ] || continue
2070 (cd "$storage/$i";
2071 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2072 done
2073 fi
2075 unset VERSION MAINTAINER ROOTFS_SELECTION
2076 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2077 ROOTFS_SIZE="$1 (estimated)"
2078 INITRAMFS_SIZE="$2 (estimated)"
2079 ISO_SIZE="$3 (estimated)"
2080 PKGNUM="$4"
2081 . "$storage/receipt"
2083 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2084 Flavor : $FLAVOR
2085 Description : $SHORT_DESC
2086 Version : $VERSION
2087 Maintainer : $MAINTAINER
2088 LiveCD RAM size : $FRUGAL_RAM
2089 Rootfs list : $ROOTFS_SELECTION
2090 Build date : $(date '+%Y%m%d at %T')
2091 Packages : $PKGNUM
2092 Rootfs size : $ROOTFS_SIZE
2093 Initramfs size : $INITRAMFS_SIZE
2094 ISO image size : $ISO_SIZE
2095 ================================================================================
2097 EOT
2099 rm -f $tmp_dir/packages.list
2100 pack_flavor "$tmp_dir" "$flavor"
2101 status
2102 display_unknown "$tmp_dir/err"
2103 display_warn "$flv_dir/warn"
2104 cleanup
2105 ;;
2108 get-flavor)
2109 # Get a flavor's files and prepare for gen-distro.
2110 flavor=${2%.flavor}
2111 title 'Preparing %s distro flavor' "$flavor"
2112 set -e
2113 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2114 set +e
2116 action 'Cleaning %s...' "$DISTRO"
2117 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2118 # Clean old files
2119 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2120 [ -f "$i" ] && rm "$i"
2121 done
2122 mkdir -p "$DISTRO"
2123 status
2125 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2127 action 'Extracting flavor %s...' "$flavor.flavor"
2128 flv_dir="$(extract_flavor "$flavor" info)"
2129 cp -a "$flv_dir"/* .
2130 mv packages.list distro-packages.list
2131 mv -f info /etc/tazlito
2132 status
2134 for i in rootcd rootfs; do
2135 if [ -d "$i" ]; then
2136 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2137 fi
2138 done
2140 sed '/^Rootfs list/!d;s/.*: //' description > /etc/tazlito/rootfs.list
2141 [ -s /etc/tazlito/rootfs.list ] || rm -f /etc/tazlito/rootfs.list
2143 action 'Updating %s...' 'tazlito.conf'
2144 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2145 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2146 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2147 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2148 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2149 status
2151 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2152 cleanup
2153 ;;
2156 iso2flavor)
2157 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2158 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2160 FLAVOR=${3%.flavor}
2161 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2162 mount -o loop,ro $2 $TMP_DIR/iso
2163 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2164 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2165 ! -s $TMP_DIR/flavor/*.desc ]; then
2166 _ 'META flavors are not supported.'
2167 umount -d $TMP_DIR/iso
2168 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2169 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2170 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2171 umount -d $TMP_DIR/iso
2172 else
2173 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2174 uncompress $i | \
2175 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2176 done
2177 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2178 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2179 '/etc/slitaz-release' '/boot/rootfs.gz'
2180 umount -d $TMP_DIR/iso
2181 else
2182 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2183 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2184 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2185 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2186 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2187 umount -d $TMP_DIR/iso
2188 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2189 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2190 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2191 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2192 < $TMP_DIR/rootfs$INSTALLED.md5
2193 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2194 if [ -s $TMP_DIR/flavor/*desc ]; then
2195 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2196 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2197 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2198 for i in rootfs rootcd ; do
2199 [ -s $TMP_DIR/flavor/*.list$i ] &&
2200 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2201 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2202 done
2203 else
2204 find_flavor_rootfs $TMP_DIR/rootfs
2205 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2206 for i in rootfs rootcd ; do
2207 [ "$(ls $TMP_DIR/$i)" ] &&
2208 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2209 done
2210 unset VERSION MAINTAINER
2211 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2212 if [ -n "$DESCRIPTION" ]; then
2213 _n 'Flavor version : '; read -t 30 VERSION
2214 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2215 fi
2217 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2218 Flavor : $FLAVOR
2219 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2220 Version : ${VERSION:-1.0}
2221 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2222 LiveCD RAM size : $RAM_SIZE
2223 Build date : $BUILD_DATE
2224 Packages : $PKGCNT
2225 Rootfs size : $ROOTFS_SIZE
2226 Initramfs size : $INITRAMFS_SIZE
2227 ISO image size : $ISO_SIZE
2228 ================================================================================
2230 EOT
2231 longline "Tazlito can't detect each file installed during \
2232 a package post_install. You should extract this flavor (tazlito extract-flavor \
2233 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2234 tree and remove files generated by post_installs.
2235 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2236 repack the flavor (tazlito pack-flavor $FLAVOR)"
2237 fi
2238 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2239 fi
2240 fi
2241 rm -rf $TMP_DIR
2242 ;;
2245 gen-distro)
2246 # Generate a live distro tree with a set of packages.
2248 check_root
2249 start_time=$(date +%s)
2251 # Tazlito options: --iso or --cdrom
2252 CDROM=''
2253 [ -n "$iso" ] && CDROM="-o loop $iso"
2254 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2256 # Check if a package list was specified on cmdline.
2257 if [ -f "$2" ]; then
2258 LIST_NAME="$2"
2259 else
2260 LIST_NAME='distro-packages.list'
2261 fi
2263 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2264 'Please clean the distro tree or change directory path.'
2265 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2266 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2268 # If list not given: build list with all installed packages
2269 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2270 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2271 fi
2273 # Exit if no list name.
2274 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2276 # Start generation.
2277 title 'Tazlito generating a distro'
2279 # Misc checks
2280 mkdir -p "$PACKAGES_REPOSITORY"
2281 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2282 newline
2284 # Mount CD-ROM to be able to repack boot-loader packages
2285 if [ ! -e /boot -a -n "$CDROM" ]; then
2286 mkdir $TMP_MNT
2287 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2288 ln -s "$TMP_MNT/boot" /
2289 if [ ! -d "$ADDFILES/rootcd" ] ; then
2290 mkdir -p "$ADDFILES/rootcd"
2291 for i in $(ls $TMP_MNT); do
2292 [ "$i" == 'boot' ] && continue
2293 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2294 done
2295 fi
2296 else
2297 rmdir "$TMP_MNT"
2298 fi
2299 fi
2301 # Rootfs stuff.
2302 echo 'Preparing the rootfs directory...'
2303 mkdir -p "$ROOTFS"
2304 export root="$ROOTFS"
2305 # pass current 'mirror' to the root
2306 mkdir -p $root/var/lib/tazpkg $root/etc
2307 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2308 cp -f /etc/slitaz-release $root/etc/slitaz-release
2309 strip_versions "$LIST_NAME"
2311 if [ "$REPACK" == 'y' ]; then
2312 # Determine full packages list with all dependencies
2313 tmp_dir="$(mktemp -d)"
2314 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2315 touch "$tmp_dir/full.pkglist"
2316 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2318 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2319 while read pkgname pkgver; do
2320 # Is package in full list?
2321 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2322 # Is package already repacked?
2323 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2324 _ 'Repacking %s...' "$pkgname-$pkgver"
2325 tazpkg repack "$pkgname" --quiet
2326 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2327 status
2328 done
2330 rm -r "$tmp_dir"
2331 fi
2333 if [ -f non-free.list ]; then
2334 # FIXME: working in the ROOTFS chroot?
2335 newline
2336 echo 'Preparing non-free packages...'
2337 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2338 for pkg in $(cat 'non-free.list'); do
2339 if [ ! -d "$INSTALLED/$pkg" ]; then
2340 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2341 tazpkg get-install get-$pkg
2342 fi
2343 get-$pkg "$ROOTFS"
2344 fi
2345 tazpkg repack $pkg
2346 pkg=$(ls $pkg*.tazpkg)
2347 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2348 mv $pkg $PACKAGES_REPOSITORY
2349 done
2350 fi
2351 cp $LIST_NAME $DISTRO/distro-packages.list
2352 newline
2354 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2356 cd $DISTRO
2357 cp distro-packages.list $ROOTFS/etc/tazlito
2358 # Copy all files from $ADDFILES/rootfs to the rootfs.
2359 if [ -d "$ADDFILES/rootfs" ] ; then
2360 action 'Copying addfiles content to the rootfs...'
2361 cp -a $ADDFILES/rootfs/* $ROOTFS
2362 status
2363 fi
2365 action 'Root filesystem is generated...'; status
2367 # Root CD part.
2368 action 'Preparing the rootcd directory...'
2369 mkdir -p $ROOTCD
2370 status
2372 # Move the boot dir with the Linux kernel from rootfs.
2373 # The boot dir goes directly on the CD.
2374 if [ -d "$ROOTFS/boot" ] ; then
2375 action 'Moving the boot directory...'
2376 mv $ROOTFS/boot $ROOTCD
2377 cd $ROOTCD/boot
2378 rm -rf grub*
2379 make_bzImage_hardlink
2380 status
2381 fi
2382 cd $DISTRO
2383 # Copy all files from $ADDFILES/rootcd to the rootcd.
2384 if [ -d "$ADDFILES/rootcd" ] ; then
2385 action 'Copying addfiles content to the rootcd...'
2386 cp -a $ADDFILES/rootcd/* $ROOTCD
2387 status
2388 fi
2389 # Execute the distro script used to perform tasks in the rootfs
2390 # before compression. Give rootfs path in arg
2391 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2392 if [ -x "$DISTRO_SCRIPT" ]; then
2393 echo 'Executing distro script...'
2394 sh $DISTRO_SCRIPT $DISTRO
2395 fi
2397 # Execute the custom_rules() found in receipt.
2398 if [ -s "$TOP_DIR/receipt" ]; then
2399 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2400 echo -e "Executing: custom_rules()\n"
2401 . "$TOP_DIR/receipt"
2402 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2403 fi
2404 fi
2406 # Multi-rootfs
2407 if [ -s /etc/tazlito/rootfs.list ]; then
2409 FLAVOR_LIST="$(awk '{
2410 for (i = 2; i <= NF; i+=2)
2411 printf "%s ", $i;
2412 }' /etc/tazlito/rootfs.list)"
2414 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2415 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2416 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2418 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2419 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2420 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2421 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2423 n=0
2424 last=$ROOTFS
2425 while read flavor; do
2426 n=$(($n+1))
2427 mkdir ${ROOTFS}0$n
2428 export root="${ROOTFS}0$n"
2429 # initial tazpkg setup in empty rootfs
2430 tazpkg --root=$root >/dev/null 2>&1
2432 newline
2433 boldify "Building $flavor rootfs..."
2435 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2436 cp "$TOP_DIR/$flavor.flavor" .
2438 if [ ! -s "$flavor.flavor" ]; then
2439 # We may have it in $FLAVORS_REPOSITORY
2440 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2441 tazlito pack-flavor $flavor
2442 else
2443 download $flavor.flavor
2444 fi
2445 fi
2447 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2448 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2449 cp $flavor.pkglist $DISTRO/list-packages0$n
2450 status
2452 strip_versions "$DISTRO/list-packages0$n"
2454 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2456 rm -rf ${ROOTFS}0$n/boot
2458 cd $DISTRO
2459 if [ -s $flavor.rootfs ]; then
2460 _n 'Adding %s rootfs extra files...' "$flavor"
2461 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2462 fi
2464 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2465 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2466 status
2468 rm -f $flavor.flavor install-list
2469 mergefs ${ROOTFS}0$n $last
2470 last=${ROOTFS}0$n
2471 done <<EOT
2472 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2473 EOT
2474 #'
2475 i=$(($n+1))
2476 while [ $n -gt 0 ]; do
2477 mv ${ROOTFS}0$n ${ROOTFS}$i
2478 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2479 gen_initramfs ${ROOTFS}$i
2480 n=$(($n-1))
2481 i=$(($i-1))
2482 export LZMA_HISTORY_BITS=26
2483 done
2484 mv $ROOTFS ${ROOTFS}$i
2485 gen_initramfs ${ROOTFS}$i
2486 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2487 else
2488 # Initramfs and ISO image stuff.
2489 gen_initramfs $ROOTFS
2490 fi
2491 gen_livecd_isolinux
2492 distro_stats
2493 cleanup
2494 ;;
2497 clean-distro)
2498 # Remove old distro tree.
2500 check_root
2501 title 'Cleaning: %s' "$DISTRO"
2502 if [ -d "$DISTRO" ] ; then
2503 if [ -d "$ROOTFS" ] ; then
2504 action 'Removing the rootfs...'
2505 rm -f $DISTRO/$INITRAMFS
2506 rm -rf $ROOTFS
2507 status
2508 fi
2509 if [ -d "$ROOTCD" ] ; then
2510 action 'Removing the rootcd...'
2511 rm -rf $ROOTCD
2512 status
2513 fi
2514 action 'Removing eventual ISO image...'
2515 rm -f $DISTRO/$ISO_NAME.iso
2516 rm -f $DISTRO/$ISO_NAME.md5
2517 status
2518 fi
2519 footer
2520 ;;
2523 check-distro)
2524 # Check for a few LiveCD needed files not installed by packages.
2526 # TODO: Remove this function.
2527 # First two files are maintained by tazpkg while it runs on rootfs,
2528 # while last one file should be maintained by tazlito itself.
2529 check_rootfs
2530 title 'Checking distro: %s' "$ROOTFS"
2531 # SliTaz release info.
2532 rel='/etc/slitaz-release'
2533 if [ ! -f "$ROOTFS$rel" ]; then
2534 _ 'Missing release info: %s' "$rel"
2535 else
2536 action 'Release : %s' "$(cat $ROOTFS$rel)"
2537 status
2538 fi
2539 # Tazpkg mirror.
2540 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2541 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2542 todomsg
2543 else
2544 action 'Mirror configuration exists...'
2545 status
2546 fi
2547 # Isolinux msg
2548 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2549 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2550 todomsg
2551 else
2552 action 'Isolinux message seems good...'
2553 status
2554 fi
2555 footer
2556 ;;
2559 writeiso)
2560 # Writefs to ISO image including /home unlike gen-distro we don't use
2561 # packages to generate a rootfs, we build a compressed rootfs with all
2562 # the current filesystem similar to 'tazusb writefs'.
2564 DISTRO='/home/slitaz/distro'
2565 ROOTCD="$DISTRO/rootcd"
2566 COMPRESSION="${2:-none}"
2567 ISO_NAME="${3:-slitaz}"
2568 check_root
2569 # Start info
2570 title 'Write filesystem to ISO'
2571 longline "The command writeiso will write the current filesystem into a \
2572 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2573 newline
2574 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2576 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2577 # Save some space
2578 rm -rf /var/cache/tazpkg/*
2579 rm -f /var/lib/tazpkg/*.bak
2580 rm -rf $DISTRO
2582 # Optionally remove sound card selection and screen resolution.
2583 if [ -z $LaunchedByTazpanel ]; then
2584 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2585 case $anser in
2586 y)
2587 action 'Removing current sound card and screen configurations...'
2588 rm -f /var/lib/sound-card-driver
2589 rm -f /var/lib/alsa/asound.state
2590 rm -f /etc/X11/xorg.conf ;;
2591 *)
2592 action 'Keeping current sound card and screen configurations...' ;;
2593 esac
2594 status
2595 newline
2597 # Optionally remove i18n settings
2598 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2599 case $anser in
2600 y)
2601 action 'Removing current locale/keymap settings...'
2602 newline > /etc/locale.conf
2603 newline > /etc/keymap.conf ;;
2604 *)
2605 action 'Keeping current locale/keymap settings...' ;;
2606 esac
2607 status
2608 fi
2610 # Clean-up files by default
2611 newline > /etc/udev/rules.d/70-persistent-net.rules
2612 newline > /etc/udev/rules.d/70-persistant-cd.rules
2614 # Create list of files including default user files since it is defined in /etc/passwd
2615 # and some new users might have been added.
2616 cd /
2617 echo 'init' > /tmp/list
2618 for dir in bin etc sbin var dev lib root usr home opt; do
2619 [ -d $dir ] && find $dir
2620 done >> /tmp/list
2622 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2623 [ -d $dir ] && echo $dir
2624 done >> /tmp/list
2626 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2628 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2629 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2630 #fi
2631 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2632 touch /var/log/wtmp
2634 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2635 sed -i "/var\/log\/$removelog/d" /tmp/list
2636 done
2638 # Generate initramfs with specified compression and display rootfs
2639 # size in realtime.
2640 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2642 write_initramfs &
2643 sleep 2
2644 cd - > /dev/null
2645 echo -en "\nFilesystem size:"
2646 while [ ! -f /tmp/rootfs ]; do
2647 sleep 1
2648 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2649 done
2650 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2651 echo -e "\n"
2652 rm -f /tmp/rootfs
2654 # Move freshly generated rootfs to the cdrom.
2655 mkdir -p $ROOTCD/boot
2656 mv -f /$INITRAMFS $ROOTCD/boot
2657 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2659 # Now we need the kernel and isolinux files.
2660 copy_from_cd() {
2661 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2662 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2663 unmeta_boot $ROOTCD
2664 umount /media/cdrom
2667 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2668 copy_from_cd;
2669 elif mount | grep /media/cdrom; then
2670 copy_from_cd;
2671 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2672 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2673 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2674 else
2675 touch /tmp/.write-iso-error
2676 longline "When SliTaz is running in RAM the kernel and bootloader \
2677 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
2678 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
2679 echo -en "----\nENTER to continue..."; read i
2680 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2681 copy_from_cd
2682 fi
2684 # Generate the iso image.
2685 touch /tmp/.write-iso
2686 newline
2687 cd $DISTRO
2688 create_iso $ISO_NAME.iso $ROOTCD
2689 action 'Creating the ISO md5sum...'
2690 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2691 status
2693 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2694 rm -f /tmp/.write-iso
2696 if [ -z $LaunchedByTazpanel ]; then
2697 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2698 case $anser in
2699 y)
2700 umount /dev/cdrom 2>/dev/null
2701 eject
2702 echo -n "Please insert a blank CD-ROM and press ENTER..."
2703 read i && sleep 2
2704 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2705 echo -en "----\nENTER to continue..."; read i ;;
2706 *)
2707 exit 0 ;;
2708 esac
2709 fi
2710 ;;
2713 burn-iso)
2714 # Guess CD-ROM device, ask user and burn the ISO.
2716 check_root
2717 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2718 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2719 # We can specify an alternative ISO from the cmdline.
2720 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2721 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2723 title 'Tazlito burn ISO'
2724 echo "CD-ROM device : /dev/$DRIVE_NAME"
2725 echo "Drive speed : $DRIVE_SPEED"
2726 echo "ISO image : $iso"
2727 footer
2729 case $(yesorno 'Burn ISO image?' 'n') in
2730 y)
2731 title 'Starting Wodim to burn the ISO...'
2732 sleep 2
2733 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2734 footer 'ISO image is burned to CD-ROM.'
2735 ;;
2736 *)
2737 die 'Exiting. No ISO burned.'
2738 ;;
2739 esac
2740 ;;
2743 merge)
2744 # Merge multiple rootfs into one iso.
2746 if [ -z "$2" ]; then
2747 cat <<EOT
2748 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2750 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2751 i.e: rootfsN is a subset of rootfsN-1
2752 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2753 The boot loader will select the rootfs according to the RAM size detected.
2755 Example:
2756 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
2758 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
2759 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
2761 EOT
2762 exit 2
2763 fi
2765 shift # skip merge
2766 append="$1 slitaz1"
2767 shift # skip size1
2768 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
2770 ISO=$1.merged
2772 # Extract filesystems
2773 action 'Mounting %s' "$1"
2774 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
2775 status || cleanup_merge
2777 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2778 make_bzImage_hardlink $TMP_DIR/iso/boot
2779 umount -d $TMP_DIR/mnt
2780 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
2781 _ '%s is already a merged iso. Aborting.' "$1"
2782 cleanup_merge
2783 fi
2784 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
2785 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
2786 if [ ! -f /boot/isolinux/ifmem.c32 -a
2787 ! -f /boot/isolinux/c32box.c32 ]; then
2788 cat <<EOT
2789 No file /boot/isolinux/ifmem.c32
2790 Please install syslinux package !
2791 EOT
2792 rm -rf $TMP_DIR
2793 exit 1
2794 fi
2795 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
2796 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
2797 fi
2799 action 'Extracting %s' 'iso/rootfs.gz'
2800 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
2801 [ -d $TMP_DIR/rootfs1/etc ]
2802 status || cleanup_merge
2804 n=1
2805 while [ -n "$2" ]; do
2806 shift # skip rootfs N-1
2807 p=$n
2808 n=$(($n + 1))
2809 append="$append $1 slitaz$n"
2810 shift # skip size N
2811 mkdir -p $TMP_DIR/rootfs$n
2813 action 'Extracting %s' "$1"
2814 extract_rootfs $1 $TMP_DIR/rootfs$n &&
2815 [ -d "$TMP_DIR/rootfs$n/etc" ]
2816 status || cleanup_merge
2818 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
2819 action 'Creating %s' "rootfs$p.gz"
2820 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
2821 status
2822 done
2823 action 'Creating %s' "rootfs$n.gz"
2824 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
2825 status
2826 rm -f $TMP_DIR/iso/boot/rootfs.gz
2827 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
2828 create_iso $ISO $TMP_DIR/iso
2829 rm -rf $TMP_DIR
2830 ;;
2833 repack)
2834 # Repack an iso with maximum lzma compression ratio.
2836 ISO=$2
2837 mkdir -p $TMP_DIR/mnt
2839 # Extract filesystems
2840 action 'Mounting %s' "$ISO"
2841 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
2842 status || cleanup_merge
2844 cp -a $TMP_DIR/mnt $TMP_DIR/iso
2845 umount -d $TMP_DIR/mnt
2847 for i in $TMP_DIR/iso/boot/rootfs* ; do
2848 action 'Repacking %s' "$(basename $i)"
2849 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
2850 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
2851 align_to_32bits $i
2852 status
2853 done
2855 create_iso $ISO $TMP_DIR/iso
2856 rm -rf $TMP_DIR
2857 ;;
2860 build-loram)
2861 # Build a Live CD for low RAM systems.
2863 ISO="$2"
2864 OUTPUT="$3"
2865 [ -z "$3" ] && \
2866 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
2867 mkdir -p "$TMP_DIR/iso"
2868 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
2869 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
2870 if ! check_iso_for_loram ; then
2871 umount -d "$TMP_DIR/iso"
2872 die "$ISO is not a valid SliTaz live CD. Abort."
2873 fi
2874 case "$4" in
2875 cdrom) build_loram_cdrom ;;
2876 http) build_loram_http ;;
2877 *) build_loram_ram "$5" ;;
2878 esac
2879 umount $TMP_DIR/iso # no -d: needs /proc
2880 losetup -d $loopdev
2881 rm -rf $TMP_DIR
2882 ;;
2885 emu-iso)
2886 # Emulate an ISO image with Qemu.
2887 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2888 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
2889 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
2890 echo -e "\nStarting Qemu emulator:\n"
2891 echo -e "qemu $QEMU_OPTS $iso\n"
2892 qemu $QEMU_OPTS $iso
2893 ;;
2896 deduplicate)
2897 # Deduplicate files in a tree
2898 shift
2899 deduplicate "$@"
2900 ;;
2903 usage|*)
2904 # Print usage also for all unknown commands.
2905 usage
2906 ;;
2907 esac
2909 exit 0