tazlito view tazlito @ rev 101

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