tazlito view tazlito @ rev 103

tazlito: better lzma default compression ratio
author Pascal Bellard <pascal.bellard@slitaz.org>
date Mon Aug 17 10:42:38 2009 +0200 (2009-08-17)
parents 329dcaa0bd9b
children 78b1b9a2e4fe
line source
1 #!/bin/sh
2 # TazLito - SliTaz Live Tool.
3 #
4 # Tazlito is a tool to help generate and configure SliTaz LiveCD
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-2009 SliTaz - GNU General Public License.
11 #
12 # Authors : Christophe Lincoln <pankso@slitaz.org>
13 # Pascal Bellard <pascal.bellard@slitaz.org>
14 #
15 VERSION=2.0
17 # Tazlito configuration variables to be shorter
18 # and to use words rather than numbers.
19 COMMAND=$1
20 LIST_NAME=$2
21 TMP_DIR=/tmp/tazlito-$$-$RANDOM
22 TMP_MNT=/media/tazlito-$$-$RANDOM
23 TOP_DIR=`pwd`
24 INITRAMFS=rootfs.gz
25 LOCALSTATE=/var/lib/tazpkg
26 INSTALLED=$LOCALSTATE/installed
27 CACHE_DIR=/var/cache/tazpkg
28 MIRROR=$LOCALSTATE/mirror
29 DEFAULT_MIRROR="http://mirror.slitaz.org/packages/`cat /etc/slitaz-release`/"
31 # Try to include config file, continue if command is gen-config or exit.
32 # The main config used by default is in /etc/tazlito.
33 if [ -f "/etc/tazlito/tazlito.conf" ] ; then
34 CONFIG_FILE="/etc/tazlito/tazlito.conf"
35 fi
36 # Specific distro config file can be put in a distro tree.
37 if [ -f "$TOP_DIR/tazlito.conf" ] ; then
38 CONFIG_FILE="$TOP_DIR/tazlito.conf"
39 fi
40 if [ ! "$CONFIG_FILE" = "" ] ; then
41 . $CONFIG_FILE
42 else
43 if [ "$COMMAND" = "gen-config" ] ; then
44 continue
45 else
46 echo "Unable to find any configuration file. Please read the doc"
47 echo "or run '`basename $0` gen-config' to get an empty config file."
48 exit 0
49 fi
50 fi
52 # While Tazpkg is not used the default mirror url file does not exist
53 # and user can't recharge the list of flavors.
54 if test $(id -u) = 0 ; then
55 if [ ! -f "$MIRROR" ]; then
56 echo "$DEFAULT_MIRROR" > $MIRROR
57 fi
58 fi
60 # Set the rootfs and rootcd path with $DISTRO
61 # configuration variable.
62 ROOTFS=$DISTRO/rootfs
63 ROOTCD=$DISTRO/rootcd
65 #####################
66 # Tazlito functions #
67 #####################
69 # Print the usage.
70 usage ()
71 {
72 echo -e "\nSliTaz Live Tool - Version: $VERSION\n
73 \033[1mUsage: \033[0m `basename $0` [command] [list|iso|flavor] [dir]
74 \033[1mCommands: \033[0m\n
75 usage Print this short usage.
76 stats View Tazlito and distro configuration statistics.
77 gen-config Generate a new configuration file for a distro.
78 configure Configure the main config file or a specific tazlito.conf.
79 gen-iso Generate a new ISO from a distro tree.
80 gen-initiso Generate a new initramfs and ISO from the distro tree.
81 list-flavors List all available package lists on the mirror.
82 gen-flavor Generate a new live-CD description.
83 gen-liveflavor Generate a live-CD description from current system.
84 show-flavor Show live-CD description.
85 get-flavor Get a flavor's list of packages.
86 check-list Check a distro-packages.list for updates.
87 extract-distro Extract an ISO to a directory and rebuild LiveCD tree.
88 gen-distro Generate a Live distro and ISO from a list of packages.
89 clean-distro Remove all files generated by gen-distro.
90 check-distro Help to check if distro is ready to release.
91 merge Merge multiple rootfs into one iso.
92 repack Recompress rootfs in iso with maximum ration.
93 burn-iso Burn ISO image to a cdrom using Wodim.\n"
94 }
96 # Status function.
97 status()
98 {
99 local CHECK=$?
100 echo -en "\\033[70G[ "
101 if [ $CHECK = 0 ]; then
102 echo -en "\\033[1;33mOK"
103 else
104 echo -en "\\033[1;31mFailed"
105 fi
106 echo -e "\\033[0;39m ]"
107 return $CHECK
108 }
110 yesorno()
111 {
112 echo -n "$1"
113 case "$DEFAULT_ANSWER" in
114 Y|y) answer="y";;
115 N|n) answer="n";;
116 *) read answer;;
117 esac
118 }
120 field()
121 {
122 grep "^$1" "$2" | sed 's/.*: \([0-9KMG\.]*\).*/\1/'
123 }
125 todomsg()
126 {
127 echo -e "\\033[70G[ \\033[1;31mTODO\\033[0;39m ]"
128 }
130 # Download a file from this mirror
131 download_from()
132 {
133 local i
134 local mirrors
135 mirrors="$1"
136 shift
137 for i in $mirrors; do
138 case "$i" in
139 http://*|ftp://*) wget -c $i$@ && break;;
140 *) cp $i/$1 . && break;;
141 esac
142 done
143 }
145 # Download a file trying all mirrors
146 download()
147 {
148 local i
149 for i in $(cat $MIRROR $LOCALSTATE/undigest/*/mirror 2> /dev/null); do
150 download_from "$i" "$@" && break
151 done
152 }
154 # Execute hooks provided by some packages
155 genisohooks()
156 {
157 local here=`pwd`
158 cd $ROOTFS
159 for i in $(ls etc/tazlito/*.$1 2> /dev/null); do
160 . $i $ROOTCD
161 done
162 cd $here
163 }
165 cleanup()
166 {
167 if [ -d $TMP_MNT ]; then
168 umount $TMP_MNT
169 rmdir $TMP_MNT
170 rm -f /boot
171 fi
172 }
174 # Echo the package name if the tazpkg is already installed
175 installed_package_name()
176 {
177 local tazpkg
178 local package
179 local VERSION
180 local EXTRAVERSION
181 tazpkg=$1
182 # Try to find package name and version to be able
183 # to repack it from installation
184 # A dash (-) can exist in name *and* in version
185 package=${tazpkg%-*}
186 i=$package
187 while true; do
188 VERSION=""
189 eval $(grep -s ^VERSION= $INSTALLED/$i/receipt)
190 EXTRAVERSION=""
191 eval $(grep -s ^EXTRAVERSION= $INSTALLED/$i/receipt)
192 if [ "$i-$VERSION$EXTRAVERSION" = "$tazpkg" ]; then
193 echo $i
194 break
195 fi
196 case "$i" in
197 *-*);;
198 *) break;;
199 esac
200 i=${i%-*}
201 done
202 }
204 # Check if user is root.
205 check_root()
206 {
207 if test $(id -u) != 0 ; then
208 echo -e "\nYou must be root to run `basename $0` with this option."
209 echo -e "Please type 'su' and root password to become super-user.\n"
210 exit 0
211 fi
212 }
214 # Check for the rootfs tree.
215 check_rootfs()
216 {
217 if [ ! -d "$ROOTFS/etc" ] ; then
218 echo -e "\nUnable to find a distro rootfs...\n"
219 exit 0
220 fi
221 }
223 # Check for the boot dir into the root CD tree.
224 verify_rootcd()
225 {
226 if [ ! -d "$ROOTCD/boot" ] ; then
227 echo -e "\nUnable to find the rootcd boot directory...\n"
228 exit 0
229 fi
230 }
232 create_iso()
233 {
234 genisoimage -R -o $1 -b boot/isolinux/isolinux.bin \
235 -c boot/isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
236 -V "$VOLUM_NAME" -p "$PREPARED" -input-charset iso8859-1 \
237 -boot-info-table $2
238 if [ -x /usr/bin/isohybrid ]; then
239 echo -n "Create hybrid ISO..."
240 /usr/bin/isohybrid $1 2> /dev/null
241 status
242 fi
243 }
245 # Generate a new ISO image using isolinux.
246 gen_livecd_isolinux()
247 {
248 # Some packages may want to alter iso
249 genisohooks iso
250 if [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ]; then
251 echo -e "\nUnable to find isolinux binary.\n"
252 cleanup
253 exit 0
254 fi
255 # Set date for boot msg.
256 if grep -q 'XXXXXXXX' $ROOTCD/boot/isolinux/isolinux.msg; then
257 DATE=`date +%Y%m%d`
258 echo -n "Setting build date to: $DATE..."
259 sed -i s/'XXXXXXXX'/"$DATE"/ $ROOTCD/boot/isolinux/isolinux.msg
260 status
261 fi
262 cd $ROOTCD
263 echo -n "Computing md5..."
264 find * -type f ! -name md5sum -exec md5sum {} \; > md5sum
265 status
266 cd $DISTRO
267 echo ""
268 echo -e "\033[1mGenerating ISO image\033[0m"
269 echo "================================================================================"
270 create_iso $ISO_NAME.iso $ROOTCD
271 echo -n "Creating the ISO md5sum..."
272 md5sum $ISO_NAME.iso > $ISO_NAME.md5
273 status
274 echo "================================================================================"
275 # Some packages may want to alter final iso
276 genisohooks final
277 }
279 lzma_history_bits()
280 {
281 local n
282 local sz
283 n=20 # 1Mb
284 sz=$(du -sk $1 | cut -f1)
285 while [ $sz -gt 1024 -a $n -lt 28 ]; do
286 n=$(( $n + 1 ))
287 sz=$(( $sz / 2 ))
288 done
289 echo $n
290 }
292 # Pack rootfs
293 pack_rootfs()
294 {
295 ( cd $1 ; find . -print | cpio -o -H newc ) | \
296 if [ "$COMPRESSION" = "none" ]; then
297 echo -n "Generating uncompressed initramfs... "
298 cat > $2
299 elif [ -x /usr/bin/lzma -a "$COMPRESSION" != "gzip" ]; then
300 echo -n "Generating lzma'ed initramfs... "
301 lzma e -si -so -d$(lzma_history_bits $1) > $2
302 else
303 echo -n "Generating gziped initramfs... "
304 gzip -9 > $2
305 fi
306 }
308 # Generate a new initramfs from the root filesystem.
309 gen_initramfs()
310 {
311 # Just in case CTRL+c
312 rm -f $DISTRO/gen
313 # Some packages may want to alter rootfs
314 genisohooks rootfs
315 cd $ROOTFS
316 echo ""
318 # Link duplicate files
319 find . -type f -size +0c -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | \
320 sort | ( save=0; old_attr=""; old_inode=""; old_link=""; old_file=""
321 while read attr inode link file; do
322 if [ "$attr" = "$old_attr" -a "$inode" != "$old_inode" ]; then
323 if cmp "$file" "$old_file" >/dev/null; then
324 rm -f "$file"
325 ln "$old_file" "$file"
326 inode="$old_inode"
327 [ "$link" = "1" ] && save="$(expr $save + ${attr%%-*})"
328 fi
329 fi
330 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
331 done
332 echo "$save bytes saved in duplicate files."
333 )
335 # Use lzma if installed
336 pack_rootfs . $DISTRO/$INITRAMFS
337 cd $DISTRO
338 mv $INITRAMFS $ROOTCD/boot
339 }
341 distro_sizes()
342 {
343 echo "Build date : `date +%Y%m%d\ \at\ \%H:%M:%S`"
344 echo "Packages : `ls -1 $ROOTFS$INSTALLED | wc -l`"
345 echo "Rootfs size : `du -sh $ROOTFS | awk '{ print $1 }'`"
346 echo "Initramfs size : `du -sh $ROOTCD/boot/$INITRAMFS | awk '{ print $1 }'`"
347 echo "ISO image size : `du -sh $ISO_NAME.iso | awk '{ print $1 }'`"
348 echo "================================================================================"
349 echo "Image is ready: $ISO_NAME.iso"
350 echo ""
351 }
353 # Print ISO and rootfs size.
354 distro_stats()
355 {
356 echo ""
357 echo -e "\033[1mDistro statistics\033[0m ($DISTRO)"
358 echo "================================================================================"
359 distro_sizes
360 }
362 # Create an empty configuration file.
363 empty_config_file()
364 {
365 cat >> tazlito.conf << "EOF"
366 # tazlito.conf: Tazlito (SliTaz Live Tool)
367 # configuration file.
368 #
370 # Name of the ISO image to generate.
371 ISO_NAME=""
373 # ISO image volume name.
374 VOLUM_NAME="SliTaz"
376 # Name of the preparer.
377 PREPARED="$USER"
379 # Path to the packages repository and the packages.list.
380 PACKAGES_REPOSITORY=""
382 # Path to the distro tree to gen-distro from a
383 # list of packages.
384 DISTRO=""
386 # Path to the directory containing additional files
387 # to copy into the rootfs and rootcd of the LiveCD.
388 ADDFILES="$DISTRO/addfiles"
390 # Default answer for binary question (Y or N)
391 DEFAULT_ANSWER="ASK"
393 # Compression utility (lzma, gzip or none)
394 COMPRESSION="lzma"
395 EOF
396 }
398 # extract rootfs.gz somewhere
399 extract_rootfs()
400 {
401 (zcat $1 || unlzma -c $1 || cat $1) 2>/dev/null | \
402 (cd $2; cpio -idm > /dev/null)
403 }
405 # Remove duplicate files
406 mergefs()
407 {
408 # merge symlinks files and devices
409 ( cd $1; find ) | while read file; do
410 if [ -L $1/$file ]; then
411 [ -L $2/$file ] &&
412 [ "$(readlink $1/$file)" == "$(readlink $2/$file)" ] &&
413 rm -f $2/$file
414 elif [ -f $1/$file ]; then
415 [ -f $2/$file ] &&
416 cmp $1/$file $2/$file > /dev/null 2>&1 && rm -f $2/$file
417 [ -f $2/$file ] &&
418 [ "$(basename $file)" == "volatile.cpio.gz" ] &&
419 [ "$(dirname $(dirname $file))" == \
420 "./var/lib/tazpkg/installed" ] && rm -f $2/$file
421 elif [ -b $1/$file ]; then
422 [ -b $2/$file ] && rm -f $2/$file
423 elif [ -c $1/$file ]; then
424 [ -c $2/$file ] && rm -f $2/$file
425 fi
426 done
428 # cleanup directories
429 ( cd $1; find ) | while read file; do
430 if [ -d $1/$file ]; then
431 [ -d $2/$file ] && rmdir $2/$file 2> /dev/null
432 fi
433 done
434 true
435 }
437 cleanup_merge()
438 {
439 rm -rf $TMP_DIR
440 exit 1
441 }
443 ####################
444 # Tazlito commands #
445 ####################
447 case "$COMMAND" in
448 stats)
449 # Tazlito general statistics from the config file.
450 #
451 echo ""
452 echo -e "\033[1mTazlito statistics\033[0m
453 ===============================================================================
454 Config file : $CONFIG_FILE
455 ISO name : $ISO_NAME.iso
456 Volume name : $VOLUM_NAME
457 Prepared : $PREPARED
458 Packages repository : $PACKAGES_REPOSITORY
459 Distro directory : $DISTRO"
460 if [ ! "$ADDFILES" = "" ] ; then
461 echo -e "Additional files : $ADDFILES"
462 fi
463 echo "================================================================================"
464 echo ""
465 ;;
466 gen-config)
467 # Generate a new config file in the current dir or the specified
468 # directory by $2.
469 #
470 if [ -n "$2" ] ; then
471 mkdir -p $2 && cd $2
472 fi
473 echo -n "Generating empty tazlito.conf..."
474 empty_config_file
475 status
476 echo ""
477 if [ -f "tazlito.conf" ] ; then
478 echo "Configuration file is ready to edit."
479 echo "File location : `pwd`/tazlito.conf"
480 echo ""
481 fi
482 ;;
483 configure)
484 # Configure a tazlito.conf config file. Start by getting
485 # a empty config file and sed it.
486 #
487 if [ -f "tazlito.conf" ] ; then
488 rm tazlito.conf
489 else
490 if test $(id -u) = 0 ; then
491 cd /etc
492 else
493 echo "You must be root to configure the main config file or in"
494 echo "the same directory of the file you want to configure."
495 exit 0
496 fi
497 fi
498 empty_config_file
499 echo""
500 echo -e "\033[1mConfiguring :\033[0m `pwd`/tazlito.conf"
501 echo "================================================================================"
502 # ISO name.
503 echo -n "ISO name : " ; read answer
504 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
505 # Volume name.
506 echo -n "Volume name : " ; read answer
507 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
508 # Packages repository.
509 echo -n "Packages repository : " ; read answer
510 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
511 # Distro path.
512 echo -n "Distro path : " ; read answer
513 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
514 echo "================================================================================"
515 echo "Config file is ready to use."
516 echo "You can now extract an ISO or generate a distro."
517 echo ""
518 ;;
519 gen-iso)
520 # Simply generate a new iso.
521 #
522 check_root
523 verify_rootcd
524 gen_livecd_isolinux
525 distro_stats
526 ;;
527 gen-initiso)
528 # Simply generate a new initramfs with a new iso.
529 #
530 check_root
531 verify_rootcd
532 gen_initramfs
533 gen_livecd_isolinux
534 distro_stats
535 ;;
536 extract-distro)
537 # Extract an ISO image to a directory and rebuild the LiveCD tree.
538 #
539 check_root
540 ISO_IMAGE=$2
541 if [ -z "$ISO_IMAGE" ] ; then
542 echo -e "\nPlease specify the path to the ISO image."
543 echo -e "Example : `basename $0` image.iso /path/target\n"
544 exit 0
545 fi
546 # Set the distro path by checking for $3 on cmdline.
547 if [ -n "$3" ] ; then
548 TARGET=$3
549 else
550 TARGET=$DISTRO
551 fi
552 # Exit if existing distro is found.
553 if [ -d "$TARGET/rootfs" ] ; then
554 echo -e "\nA rootfs exists in : $TARGET"
555 echo -e "Please clean the distro tree or change directory path.\n"
556 exit 0
557 fi
558 echo ""
559 echo -e "\033[1mTazlito extracting :\033[0m `basename $ISO_IMAGE`"
560 echo "================================================================================"
561 # Start to mount the ISO.
562 echo ""
563 echo "Mounting ISO image..."
564 mkdir -p $TMP_DIR
565 # Get ISO file size.
566 isosize=`du -sh $ISO_IMAGE | cut -f1`
567 mount -o loop $ISO_IMAGE $TMP_DIR
568 sleep 2
569 # Prepare target dir, copy the kernel and the rootfs.
570 mkdir -p $TARGET/rootfs
571 mkdir -p $TARGET/rootcd/boot
572 echo -n "Copying the Linux kernel..."
573 if cp $TMP_DIR/boot/vmlinuz* $TARGET/rootcd/boot 2> /dev/null; then
574 ln $TARGET/rootcd/boot/vmlinuz* $TARGET/rootcd/boot/bzImage
575 else
576 cp $TMP_DIR/boot/bzImage $TARGET/rootcd/boot
577 fi
578 status
579 echo -n "Copying isolinux files..."
580 cp -a $TMP_DIR/boot/isolinux $TARGET/rootcd/boot
581 for i in $(ls $TMP_DIR); do
582 [ "$i" = "boot" ] && continue
583 cp -a $TMP_DIR/$i $TARGET/rootcd
584 done
585 status
586 if [ -d $TMP_DIR/boot/syslinux ]; then
587 echo -n "Copying syslinux files..."
588 cp -a $TMP_DIR/boot/syslinux $TARGET/rootcd/boot
589 status
590 fi
591 if [ -d $TMP_DIR/boot/extlinux ]; then
592 echo -n "Copying extlinux files..."
593 cp -a $TMP_DIR/boot/extlinux $TARGET/rootcd/boot
594 status
595 fi
596 if [ -d $TMP_DIR/boot/grub ]; then
597 echo -n "Copying GRUB files..."
598 cp -a $TMP_DIR/boot/grub $TARGET/rootcd/boot
599 status
600 fi
602 echo -n "Copying the rootfs..."
603 cp $TMP_DIR/boot/rootfs.?z $TARGET/rootcd/boot
604 status
605 # Extract initramfs.
606 cd $TARGET/rootfs
607 echo -n "Extracting the rootfs... "
608 extract_rootfs ../rootcd/boot/rootfs.gz $TARGET/rootfs
609 # unpack /usr
610 for i in etc/tazlito/*.extract; do
611 [ -f "$i" ] && . $i ../rootcd
612 done
613 # Umount and remove temp directory and cd to $TARGET to get stats.
614 umount $TMP_DIR && rm -rf $TMP_DIR
615 cd ..
616 echo ""
617 echo "================================================================================"
618 echo "Extracted : `basename $ISO_IMAGE` ($isosize)"
619 echo "Distro tree : `pwd`"
620 echo "Rootfs size : `du -sh rootfs`"
621 echo "Rootcd size : `du -sh rootcd`"
622 echo "================================================================================"
623 echo ""
624 ;;
625 list-flavors)
626 # Show available flavors.
627 if [ ! -s /etc/tazlito/flavors.list -o "$2" == "--recharge" ]; then
628 download flavors.list -O - > /etc/tazlito/flavors.list
629 fi
630 echo ""
631 echo -e "\033[1mList of flavors\033[0m"
632 echo "================================================================================"
633 cat /etc/tazlito/flavors.list
634 echo ""
635 ;;
636 show-flavor)
637 # Show flavor description.
638 FLAVOR=$2
639 if [ ! -f "$FLAVOR.flavor" ]; then
640 echo "File $FLAVOR.flavor not found."
641 exit 1
642 fi
643 mkdir $TMP_DIR
644 zcat $FLAVOR.flavor | ( cd $TMP_DIR; cpio -i 2> /dev/null )
645 if [ "$3" = "--brief" ]; then
646 if [ "$4" != "--noheader" ]; then
647 echo "Name Sizes Description"
648 echo "================================================================================"
649 fi
650 printf "%-15.15s %5.5s/%5.5s %-51s\n" "$FLAVOR" \
651 "$(field ISO $TMP_DIR/$FLAVOR.desc)" \
652 "$(field Rootfs $TMP_DIR/$FLAVOR.desc)" \
653 "$(grep ^Description $TMP_DIR/$FLAVOR.desc | cut -d: -f2)"
654 else
655 echo "================================================================================"
656 cat $TMP_DIR/$FLAVOR.desc
657 fi
658 rm -Rf $TMP_DIR
659 ;;
660 gen-liveflavor)
661 # Generate a new flavor form the live system.
662 FLAVOR=$2
663 DESC=""
664 case "$FLAVOR" in
665 '') echo -n "Flavor name : "
666 read FLAVOR
667 [ -z "$FLAVOR" ] && exit 1;;
668 -?|-h*|--help) echo -e "
670 SliTaz Live Tool - Version: $VERSION
671 \033[1mUsage: \033[0m `basename $0` gen-liveflavor flavor-name [flavor-patch-file]
672 \033[1mflavor-patch-file format: \033[0m
673 code data
674 + package to add
675 - package to remove
676 ! non-free package to add
677 ? display message
678 @ flavor description
680 \033[1mExample: \033[0m
681 @ Developer tools for slitaz maintainers
682 + slitaz-toolchain
683 + mercurial
684 "
685 exit 1;;
686 esac
687 mv /etc/tazlito/distro-packages.list \
688 /etc/tazlito/distro-packages.list.$$ 2> /dev/null
689 rm -f distro-packages.list non-free.list 2> /dev/null
690 tazpkg recharge
691 [ -n "$3" ] && while read action pkg; do
692 case "$action" in
693 +) yes | tazpkg get-install $pkg;;
694 -) yes | tazpkg remove $pkg;;
695 !) echo $pkg >> non-free.list;;
696 @) DESC="$pkg";;
697 \?) echo -en "$pkg"; read action;;
698 esac
699 done < $3
700 yes '' | tazlito gen-distro
701 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
702 mv /etc/tazlito/distro-packages.list.$$ \
703 /etc/tazlito/distro-packages.list 2> /dev/null
704 ;;
705 gen-flavor)
706 # Generate a new flavor from the last iso image generated.
707 FLAVOR=$2
708 echo ""
709 echo -e "\033[1mFlavor generation\033[0m"
710 echo "================================================================================"
711 if [ -z "$FLAVOR" ]; then
712 echo -n "Flavor name : "
713 read FLAVOR
714 [ -z "$FLAVOR" ] && exit 1
715 fi
716 check_rootfs
717 FILES="$FLAVOR.pkglist"
718 echo -n "Creating file $FLAVOR.flavor..."
719 for i in rootcd rootfs; do
720 if [ -d "$ADDFILES/$i" ] ; then
721 FILES="$FILES\n$FLAVOR.$i"
722 ( cd "$ADDFILES/$i"; find . | \
723 cpio -o -H newc 2> /dev/null | gzip -9 ) > $FLAVOR.$i
724 fi
725 done
726 status
727 answer=`grep -s ^Description $FLAVOR.desc`
728 answer=${answer#Description : }
729 if [ -z "$answer" ]; then
730 echo -n "Description : "
731 read answer
732 fi
733 echo -n "Compressing flavor $FLAVOR..."
734 echo "Flavor : $FLAVOR" > $FLAVOR.desc
735 echo "Description : $answer" >> $FLAVOR.desc
736 ( cd $DISTRO; distro_sizes) >> $FLAVOR.desc
737 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2> /dev/null
738 for i in $(ls $ROOTFS$INSTALLED); do
739 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
740 EXTRAVERSION=""
741 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
742 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
743 if [ "$CATEGORY" = "non-free" -a "${i%%-*}" != "get" ]
744 then
745 echo "$i" >> $FLAVOR.nonfree
746 else
747 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
748 fi
749 done
750 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
751 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | \
752 gzip -9 > $FLAVOR.flavor
753 rm `echo -e $FILES`
754 status
755 echo "================================================================================"
756 echo "Flavor size : `du -sh $FLAVOR.flavor`"
757 echo ""
758 ;;
759 get-flavor)
760 # Get a flavor's files and prepare for gen-distro.
761 FLAVOR=$2
762 if [ -f $FLAVOR.flavor ] || download $FLAVOR.flavor; then
763 echo -n "Cleaning $DISTRO..."
764 rm -R $DISTRO 2> /dev/null
765 mkdir -p $DISTRO
766 status
767 mkdir $TMP_DIR
768 zcat $FLAVOR.flavor | ( cd $TMP_DIR; cpio -i 2>/dev/null )
769 echo -n "Create distro-packages.list..."
770 mv $TMP_DIR/$FLAVOR.nonfree non-free.list 2> /dev/null
771 mv $TMP_DIR/$FLAVOR.pkglist distro-packages.list
772 status
773 for i in rootcd rootfs; do
774 if [ -f $TMP_DIR/$FLAVOR.$i ]; then
775 mkdir -p "$ADDFILES/$i"
776 zcat $TMP_DIR/$FLAVOR.$i | \
777 ( cd "$ADDFILES/$i"; cpio -id 2> /dev/null)
778 fi
779 done
780 echo -n "Update tazlito.conf..."
781 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
782 cat tazlito.conf | grep -v "^#VOLUM_NAME" | \
783 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $FLAVOR\"\\n#VOLUM_NA/" \
784 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
785 status
786 rm -Rf $TMP_DIR
787 fi
788 ;;
789 check-list)
790 # Use current packages list in $PWD by default.
791 DISTRO_PKGS_LIST=distro-packages.list
792 [ -d "$2" ] && DISTRO_PKGS_LIST=$2/distro-packages.list
793 [ -f "$2" ] && DISTRO_PKGS_LIST=$2
794 [ ! -f $DISTRO_PKGS_LIST ] && echo "No packages list found." && exit 0
795 echo ""
796 echo -e "\033[1mLiveCD packages list check\033[0m"
797 echo "================================================================================"
798 for pkg in `cat $DISTRO_PKGS_LIST`
799 do
800 if ! grep -q "$pkg" /var/lib/tazpkg/packages.list; then
801 echo "Update: $pkg"
802 up=$(($up + 1))
803 fi
804 done
805 [ -z $up ] && echo -e "List is up-to-date\n" && exit 0
806 echo "================================================================================"
807 echo -e "Updates: $up\n" ;;
808 gen-distro)
809 # Generate a live distro tree with a set of packages.
810 #
811 check_root
813 # Check if a package list was specified on cmdline.
814 LIST_NAME="distro-packages.list"
815 CDROM=""
816 while [ -n "$2" ]; do
817 case "$2" in
818 --iso=*)
819 CDROM="-o loop ${2#--iso=}"
820 ;;
821 --cdrom)
822 CDROM="/dev/cdrom"
823 ;;
824 --force)
825 DELETE_ROOTFS="true"
826 ;;
827 *) if [ ! -f "$2" ] ; then
828 echo -e "\nUnable to find the specified packages list."
829 echo -e "List name : $2\n"
830 exit 1
831 fi
832 LIST_NAME=$2
833 ;;
834 esac
835 shift
836 done
838 if [ -d $ROOTFS ] ; then
839 # Delete $ROOTFS if --force is set on command line
840 if [ ! -z $DELETE_ROOTFS ]; then
841 rm -rf $ROOTFS
842 unset $DELETE_ROOTFS
843 else
844 echo -e "\nA rootfs exists in : $DISTRO"
845 echo -e "Please clean the distro tree or change directory path.\n"
846 exit 0
847 fi
848 fi
849 if [ ! -f "$LIST_NAME" -a -d $INSTALLED ] ; then
850 # Build list with installed packages
851 for i in $(ls $INSTALLED); do
852 eval $(grep ^VERSION= $INSTALLED/$i/receipt)
853 EXTRAVERSION=""
854 eval $(grep ^EXTRAVERSION= $INSTALLED/$i/receipt)
855 echo "$i-$VERSION$EXTRAVERSION" >> $LIST_NAME
856 done
857 fi
858 # Exit if no list name.
859 if [ ! -f "$LIST_NAME" ]; then
860 echo -e "\nNo packages list found or specified. Please read the docs.\n"
861 exit 0
862 fi
863 # Start generation.
864 echo ""
865 echo -e "\033[1mTazlito generating a distro\033[0m"
866 echo "================================================================================"
867 # Misc checks
868 [ -n "$PACKAGES_REPOSITORY" ] || PACKAGES_REPOSITORY="."
869 [ -d $PACKAGES_REPOSITORY ] || mkdir -p $PACKAGES_REPOSITORY
870 # Get the list of packages using cat for a file list.
871 LIST=`cat $LIST_NAME`
872 # Verify if all packages in list are present in $PACKAGES_REPOSITORY.
873 REPACK=""
874 DOWNLOAD=""
875 for pkg in $LIST
876 do
877 [ "$pkg" = "" ] && continue
878 pkg=${pkg%.tazpkg}
879 [ -f $PACKAGES_REPOSITORY/$pkg.tazpkg ] && continue
880 PACKAGE=$(installed_package_name $pkg)
881 [ -n "$PACKAGE" -a "$REPACK" = "y" ] && continue
882 [ -z "$PACKAGE" -a -n "$DOWNLOAD" ] && continue
883 echo -e "\nUnable to find $pkg in the repository."
884 echo -e "Path : $PACKAGES_REPOSITORY\n"
885 if [ -n "$PACKAGE" -a -z "$REPACK" ]; then
886 yesorno "Repack packages from rootfs (y/N) ? "
887 REPACK="$answer"
888 [ "$answer" = "y" ] || REPACK="n"
889 [ "$DOWNLOAD" = "y" ] && break
890 fi
891 if [ -f $MIRROR -a -z "$DOWNLOAD" ]; then
892 yesorno "Download packages from mirror (Y/n) ? "
893 DOWNLOAD="$answer"
894 if [ "$answer" = "n" ]; then
895 [ -z "$PACKAGE" ] && exit 1
896 else
897 DOWNLOAD="y"
898 [ -n "$REPACK" ] && break
899 fi
900 fi
901 [ "$REPACK" = "n" -a "$DOWNLOAD" = "n" ] && exit 1
902 done
904 # Mount cdrom to be able to repack boot-loader packages
905 if [ ! -e /boot -a -n "$CDROM" ]; then
906 mkdir $TMP_MNT
907 if mount -r $CDROM $TMP_MNT 2> /dev/null; then
908 ln -s $TMP_MNT/boot /
909 if [ ! -d "$ADDFILES/rootcd" ] ; then
910 mkdir -p $ADDFILES/rootcd
911 for i in $(ls $TMP_MNT); do
912 [ "$i" = "boot" ] && continue
913 cp -a $TMP_MNT/$i $ADDFILES/rootcd
914 done
915 fi
916 else
917 rmdir $TMP_MNT
918 fi
919 fi
921 # Root fs stuff.
922 echo "Preparing the rootfs directory..."
923 mkdir -p $ROOTFS
924 sleep 2
925 for pkg in $LIST
926 do
927 [ "$pkg" = "" ] && continue
928 # First copy and extract the package in tmp dir.
929 pkg=${pkg%.tazpkg}
930 PACKAGE=$(installed_package_name $pkg)
931 mkdir -p $TMP_DIR
932 if [ ! -f $PACKAGES_REPOSITORY/$pkg.tazpkg ]; then
933 # Look for package in cache
934 if [ -f $CACHE_DIR/$pkg.tazpkg ]; then
935 ln -s $CACHE_DIR/$pkg.tazpkg $PACKAGES_REPOSITORY
936 # Look for package in running distribution
937 elif [ -n "$PACKAGE" -a "$REPACK" = "y" ]; then
938 tazpkg repack $PACKAGE && \
939 mv $pkg.tazpkg $PACKAGES_REPOSITORY
940 fi
941 fi
942 if [ ! -f $PACKAGES_REPOSITORY/$pkg.tazpkg ]; then
943 # Get package from mirror
944 [ "$DOWNLOAD" = "y" ] && \
945 download $pkg.tazpkg && \
946 mv $pkg.tazpkg $PACKAGES_REPOSITORY
947 fi
948 if [ ! -f $PACKAGES_REPOSITORY/$pkg.tazpkg ]; then
949 echo "Missing package $pkg."
950 cleanup
951 exit 1
952 fi
953 done
954 if [ -f non-free.list ]; then
955 echo "Preparing non-free packages..."
956 cp non-free.list $ROOTFS/etc/tazlito/non-free.list
957 for pkg in $(cat non-free.list); do
958 if [ ! -d $INSTALLED/$pkg ]; then
959 if [ ! -d $INSTALLED/get-$pkg ]; then
960 tazpkg get-install get-$pkg
961 fi
962 get-$pkg
963 fi
964 tazpkg repack $pkg
965 pkg=$(ls $pkg*.tazpkg)
966 grep -q "^$pkg$" $LIST_NAME || \
967 echo $pkg >>$LIST_NAME
968 mv $pkg $PACKAGES_REPOSITORY
969 done
970 fi
971 echo ""
972 cp $LIST_NAME $DISTRO/distro-packages.list
973 sed 's/\(.*\)/\1.tazpkg/' < $DISTRO/distro-packages.list > $DISTRO/list-packages
974 cd $PACKAGES_REPOSITORY
975 yes y | tazpkg install-list \
976 $DISTRO/list-packages --root=$ROOTFS
977 cd $DISTRO
978 cp distro-packages.list $ROOTFS/etc/tazlito
979 # Copy all files from $ADDFILES/rootfs to the rootfs.
980 if [ -d "$ADDFILES/rootfs" ] ; then
981 echo -n "Copying addfiles content to the rootfs... "
982 cp -a $ADDFILES/rootfs/* $ROOTFS
983 status
984 fi
985 echo "Root file system is generated..."
986 # Root CD part.
987 echo -n "Preparing the rootcd directory..."
988 mkdir -p $ROOTCD
989 status
990 # Move the boot dir with the Linux kernel from rootfs.
991 # The boot dir goes directly on the CD.
992 if [ -d "$ROOTFS/boot" ] ; then
993 echo -n "Moving the boot directory..."
994 mv $ROOTFS/boot $ROOTCD
995 cd $ROOTCD/boot
996 ln vmlinuz-* bzImage
997 status
998 fi
999 cd $DISTRO
1000 # Copy all files from $ADDFILES/rootcd to the rootcd.
1001 if [ -d "$ADDFILES/rootcd" ] ; then
1002 echo -n "Copying addfiles content to the rootcd... "
1003 cp -a $ADDFILES/rootcd/* $ROOTCD
1004 status
1005 fi
1006 # Execute the distro script (used to perform tasks in the rootfs
1007 # before compression. Give rootfs path in arg
1008 [ -z $DISTRO_SCRIPT ] && DISTRO_SCRIPT=$TOP_DIR/distro.sh
1009 if [ -x $DISTRO_SCRIPT ]; then
1010 echo "Executing distro script..."
1011 sh $DISTRO_SCRIPT $DISTRO
1012 fi
1013 # Initramfs and ISO image stuff.
1014 gen_initramfs
1015 gen_livecd_isolinux
1016 distro_stats
1017 cleanup
1018 ;;
1019 clean-distro)
1020 # Remove old distro tree.
1022 check_root
1023 echo ""
1024 echo -e "\033[1mCleaning :\033[0m $DISTRO"
1025 echo "================================================================================"
1026 if [ -d "$DISTRO" ] ; then
1027 if [ -d "$ROOTFS" ] ; then
1028 echo -n "Removing the rootfs..."
1029 rm -f $DISTRO/$INITRAMFS
1030 rm -rf $ROOTFS
1031 status
1032 fi
1033 if [ -d "$ROOTCD" ] ; then
1034 echo -n "Removing the rootcd..."
1035 rm -rf $ROOTCD
1036 status
1037 fi
1038 echo -n "Removing eventual ISO image..."
1039 rm -f $DISTRO/$ISO_NAME.iso
1040 rm -f $DISTRO/$ISO_NAME.md5
1041 status
1042 fi
1043 echo "================================================================================"
1044 echo ""
1045 ;;
1046 check-distro)
1047 # Check for a few LiveCD needed files not installed by packages.
1049 check_rootfs
1050 echo ""
1051 echo -e "\033[1mChecking distro :\033[0m $ROOTFS"
1052 echo "================================================================================"
1053 # SliTaz release info.
1054 if [ ! -f "$ROOTFS/etc/slitaz-release" ]; then
1055 echo "Missing release info : /etc/slitaz-release"
1056 else
1057 release=`cat $ROOTFS/etc/slitaz-release`
1058 echo -n "Release : $release"
1059 status
1060 fi
1061 # Tazpkg mirror.
1062 if [ ! -f "$ROOTFS/var/lib/tazpkg/mirror" ]; then
1063 echo -n "Mirror URL : Missing /var/lib/tazpkg/mirror"
1064 todomsg
1065 else
1066 echo -n "Mirror configuration exist..."
1067 status
1068 fi
1069 # Isolinux msg
1070 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.msg; then
1071 echo -n "Isolinux msg : Missing cooking date XXXXXXXX (ex `date +%Y%m%d`)"
1072 todomsg
1073 else
1074 echo -n "Isolinux message seems good..."
1075 status
1076 fi
1077 echo "================================================================================"
1078 echo ""
1079 ;;
1080 burn-iso)
1081 # Guess cdrom device, ask user and burn the ISO.
1083 check_root
1084 DRIVE_NAME=`cat /proc/sys/dev/cdrom/info | grep "drive name" | cut -f 3`
1085 DRIVE_SPEED=`cat /proc/sys/dev/cdrom/info | grep "drive speed" | cut -f 3`
1086 # We can specify an alternative ISO from the cmdline.
1087 if [ -n "$2" ] ; then
1088 iso=$2
1089 else
1090 iso=$DISTRO/$ISO_NAME.iso
1091 fi
1092 if [ ! -f "$iso" ]; then
1093 echo -e "\nUnable to find ISO : $iso\n"
1094 exit 0
1095 fi
1096 echo ""
1097 echo -e "\033[1mTazlito burn ISO\033[0m "
1098 echo "================================================================================"
1099 echo "Cdrom device : /dev/$DRIVE_NAME"
1100 echo "Drive speed : $DRIVE_SPEED"
1101 echo "ISO image : $iso"
1102 echo "================================================================================"
1103 echo ""
1104 yesorno "Burn ISO image (y/N) ? "
1105 if [ "$answer" == "y" ]; then
1106 echo ""
1107 echo "Starting Wodim to burn the iso..." && sleep 2
1108 echo "================================================================================"
1109 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
1110 echo "================================================================================"
1111 echo "ISO image is burned to cdrom."
1112 else
1113 echo -e "\nExiting. No ISO burned."
1114 fi
1115 echo ""
1116 ;;
1117 merge)
1118 # Merge multiple rootfs into one iso.
1120 if [ -z "$2" ]; then
1121 cat << EOT
1122 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
1124 Merge multiple rootfs into one iso. Rootfs are like russian doll
1125 i.e: rootfsN is a subset of rootfsN-1
1126 rootfs1 is found in iso, sizeN is the RAM size need to launch rootfsN.
1127 The boot loader will select the rootfs according to the RAM size detected.
1129 Example:
1130 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
1132 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
1133 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
1134 EOT
1135 exit 2
1136 fi
1138 shift # skip merge
1139 append="append $(( (${1%M} - 3) * 1024 )) slitaz1"
1140 shift # skip size1
1141 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
1143 ISO=$1.merged
1144 # Extract filesystems
1145 echo -n "Mount $1"
1146 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
1147 status || cleanup_merge
1148 cp -a $TMP_DIR/mnt $TMP_DIR/iso
1149 rm -f $TMP_DIR/iso/boot/bzImage
1150 ln $TMP_DIR/iso/boot/vmlinuz* $TMP_DIR/iso/boot/bzImage
1151 umount -d $TMP_DIR/mnt
1152 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
1153 echo "$1 is already a merged iso. Abort."
1154 cleanup_merge
1155 fi
1156 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 ]; then
1157 if [ ! -f /boot/isolinux/ifmem.c32 ]; then
1158 cat <<EOT
1159 No file /boot/isolinux/ifmem.c32
1160 Please install syslinux package !
1161 EOT
1162 rm -rf $TMP_DIR
1163 exit 1
1164 fi
1165 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
1166 fi
1168 echo -n "Extract iso/rootfs.gz"
1169 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
1170 [ -d $TMP_DIR/rootfs1/etc ]
1171 status || cleanup_merge
1172 n=1
1173 while [ -n "$2" ]; do
1174 shift # skip rootfs N-1
1175 p=$n
1176 n=$(($n + 1))
1177 append="$append $(( (${1%M} - 3) * 1024 )) slitaz$n"
1178 shift # skip size N
1179 mkdir -p $TMP_DIR/rootfs$n
1180 echo -n "Extract $1"
1181 extract_rootfs $1 $TMP_DIR/rootfs$n &&
1182 [ -d $TMP_DIR/rootfs$n/etc ]
1183 status || cleanup_merge
1184 echo -n "Merge rootfs$n into rootfs$p"
1185 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
1186 status
1187 echo "Create rootfs$p.gz"
1188 pack_rootfs $TMP_DIR/rootfs$p $TMP_DIR/iso/boot/rootfs$p.gz
1189 status
1190 done
1191 echo "Create rootfs$n.gz"
1192 pack_rootfs $TMP_DIR/rootfs$n $TMP_DIR/iso/boot/rootfs$n.gz
1193 status
1194 rm -f $TMP_DIR/iso/boot/rootfs.gz
1196 echo -n "Update boot files"
1197 grep -l 'include common' $TMP_DIR/iso/boot/isolinux/*.cfg | \
1198 while read file ; do
1199 awk -v n=$n '{
1200 if (/label/) label=$0;
1201 else if (/kernel/) kernel=$0;
1202 else if (/append/) {
1203 i=index($0,"rootfs.gz");
1204 append=substr($0,i+9);
1206 else if (/include/) {
1207 for (i = 1; i <= n; i++) {
1208 print label i
1209 print kernel;
1210 initrd="initrd=/boot/rootfs" n ".gz"
1211 for (j = n - 1; j >= i; j--) {
1212 initrd=initrd ",/boot/rootfs" j ".gz";
1214 printf "\tappend %s%s\n",initrd,append;
1215 print "";
1217 print;
1219 else print;
1220 }' < $file > $file.$$
1221 mv -f $file.$$ $file
1222 done
1223 cat >> $TMP_DIR/iso/boot/isolinux/common.cfg <<EOT
1224 label slitaz
1225 kernel /boot/isolinux/ifmem.c32
1226 $append noram
1228 label noram
1229 config noram.cfg
1231 EOT
1232 cat >> $TMP_DIR/iso/boot/isolinux/noram.cfg <<EOT
1233 display isolinux.msg
1234 say Not enough RAM to boot slitaz.
1235 default reboot
1236 label reboot
1237 com32 reboot.c32
1239 implicit 0
1240 prompt 1
1241 timeout 80
1242 F1 help.txt
1243 F2 options.txt
1244 F3 isolinux.msg
1245 F4 display.txt
1246 F5 enhelp.txt
1247 F6 enopts.txt
1248 EOT
1249 status
1250 echo "Generate $ISO"
1251 create_iso $ISO $TMP_DIR/iso
1252 rm -rf $TMP_DIR
1253 ;;
1255 repack)
1256 # Repack an iso with maximum lzma compression ratio.
1259 ISO=$2
1261 mkdir -p $TMP_DIR/mnt
1262 # Extract filesystems
1263 echo -n "Mount $ISO"
1264 mount -o loop,ro $ISO $TMP_DIR/mnt 2> /dev/null
1265 status || cleanup_merge
1266 cp -a $TMP_DIR/mnt $TMP_DIR/iso
1267 umount -d $TMP_DIR/mnt
1269 for i in $TMP_DIR/iso/boot/rootfs* ; do
1270 echo -n "Repack $(basename $i)"
1271 (zcat $i || unlzma -c $i || cat $i) \
1272 2>/dev/null > $TMP_DIR/rootfs
1273 lzma e $TMP_DIR/rootfs $i \
1274 -d$(lzma_history_bits $TMP_DIR/rootfs)
1275 status
1276 done
1278 echo "Generate $ISO"
1279 create_iso $ISO $TMP_DIR/iso
1280 rm -rf $TMP_DIR
1281 ;;
1283 usage|*)
1284 # Clear and print usage also for all unknown commands.
1286 clear
1287 usage
1288 ;;
1290 esac
1292 exit 0